SPPCompiler.SemanticAnalysis.AstUtils.AstMemoryUtils module

class SPPCompiler.SemanticAnalysis.AstUtils.AstMemoryUtils.LightweightMemoryInfo(*, ast_initialization, ast_moved, ast_partial_moves, ast_pins, initialization_counter)

Bases: object

ast_initialization: Optional[Ast]
ast_moved: Optional[Ast]
ast_partial_moves: list[Ast]
ast_pins: list[Ast]
initialization_counter: int
class SPPCompiler.SemanticAnalysis.AstUtils.AstMemoryUtils.MemoryInfo(*, ast_initialization=None, ast_initialization_old=None, ast_moved=None, ast_borrowed=None, ast_partial_moves=<factory>, ast_pins=<factory>, ast_comptime_const=None, initialization_counter=0, is_borrow_mut=False, is_borrow_ref=False, is_inconsistently_initialized=None, is_inconsistently_moved=None, is_inconsistently_partially_moved=None, is_inconsistently_pinned=None, borrow_refers_to=<factory>)

Bases: object

The MemoryInfo class is used to store information about the memory state of a symbol. It is used to identify potential memory conflicts in S++ code, and generates errors when memory conflicts are detected. There are a number of ASTs stored within these class instances, both for checks and reporting errors.

The “ast_initialization” is only None when the “ast_moved” is not None, and vice versa. This is because a symbol can not be both existing and not existing simultaneously. If there are partial moves, then the “ast_initialization” is still not None, and the “ast_moved” will be None.

Attributes:

ast_initialization: The AST where the memory is initialized (variable, parameter, etc). ast_initialization_old: Tracks most recent initialization despite moves (for errors). ast_moved: The AST where the memory is consumed (function argument, binary expression, etc). ast_borrowed: The AST where the memory is marked as borrowed (from parameter convention). ast_partial_moves: A list of partial moves (attributes). ast_pins: A list of pinned attributes (or the entire object).

is_borrow_ref: If the memory is borrowed as an immutable reference. is_borrow_mut: If the memory is borrowed as a mutable reference. ast_comptime_const: If the memory is a compile-time constant (global constant or generic constant). is_inconsistently_initialized: If the memory is inconsistently initialized from branches => (branch, is_initialized). is_inconsistently_moved: If the memory is inconsistently moved from branches => (branch, is_moved). is_inconsistently_partially_moved: If the memory is inconsistently partially moved from branches => (branch, is_partially_moved). is_inconsistently_pinned: If the memory is inconsistently pinned from branches => (branch, is_pinned).

ast_initialization: Optional[Asts.Ast]
ast_initialization_old: Optional[Asts.Ast]
ast_moved: Optional[Asts.Ast]
ast_borrowed: Optional[Asts.Ast]
ast_partial_moves: list[Asts.Ast]
ast_pins: list[Asts.Ast]
ast_comptime_const: Optional[Asts.Ast]
initialization_counter: int
is_borrow_mut: bool
is_borrow_ref: bool
is_inconsistently_initialized: Tuple[Tuple[Asts.CaseExpressionBranchAst, bool], Tuple[Asts.CaseExpressionBranchAst, bool]]
is_inconsistently_moved: Tuple[Tuple[Asts.CaseExpressionBranchAst, bool], Tuple[Asts.CaseExpressionBranchAst, bool]]
is_inconsistently_partially_moved: Tuple[Tuple[Asts.CaseExpressionBranchAst, bool], Tuple[Asts.CaseExpressionBranchAst, bool]]
is_inconsistently_pinned: Tuple[Tuple[Asts.CaseExpressionBranchAst, bool], Tuple[Asts.CaseExpressionBranchAst, bool]]
borrow_refers_to: list[Tuple[Optional[Asts.Ast], Asts.FunctionCallArgumentAst, bool, Scope]]
moved_by(ast)
Return type:

None

initialized_by(ast)
Return type:

None

remove_partial_move(ast)
Return type:

None

snapshot()
Return type:

LightweightMemoryInfo

class SPPCompiler.SemanticAnalysis.AstUtils.AstMemoryUtils.AstMemoryUtils

Bases: object

The AstMemoryUtils class contains static methods for memory-related checks and analysis. The key function is to enforce memory integrity. There are also some convenience functions for checking if memory regions overlap by symbol.

static overlaps(ast_1, ast_2)
Return type:

bool

static right_overlaps(ast_1, ast_2)
Return type:

bool

static enforce_memory_integrity(value_ast, move_ast, sm, check_move=True, check_partial_move=True, check_move_from_borrowed_ctx=True, check_pins=True, check_pins_linked=True, mark_moves=True, **kwargs)

Runs a number of checks to ensure the memory integrity of an AST is maintained. This function is responsible for all memory safety enforcement operations, except for the law of exclusivity, which is maintained by the FunctionCallArgumentGroupAst checker, as this maintains that status of mut/ref borrows.

The consistency checks are only performed if a value is actually used after the branching; if a value isn’t used, then it can be inconsistent across branches, as the symbol will never be analysed in this method.

Note that “ast_comptime_const” is never checked, because the “pins” handle this. This is because comptime const variables are auto-pinned. They can be copied if they superimpose Copy.

Parameters:
  • value_ast – The AST being analysed for memory integrity.

  • move_ast – The AST that is performing the move operation (“=” for example).

  • sm – The scope manager that is managing the current scope.

  • check_move – If a full move is being checked for validity.

  • check_partial_move – If a partial move is being checked for validity.

  • check_move_from_borrowed_ctx – If moving an attribute out of a borrowed context is being checked.

  • check_pins – If moving pinned objects is being checked.

  • check_pins_linked – If moving objects linked to pins is being checked.

  • mark_moves – Whether to update the memory information in the symbol table.

Raises: