l0_backend_lowering::Lowering class

Defined in module l0_backend_lowering (l0_backend_lowering.py).

Mutually recursive expression, statement, control-flow, and scheduled cleanup lowering.

Public static attributes

static OwnershipConversion convert
static ValueLifetime lifetime
static BackendState state

Protected functions

auto _emit_cleanup_for_return(self, str|None returned_var = None) -> None
Emit cleanup logic for a return statement.
auto _emit_cleanup_for_loop_exit(self, *bool is_break) -> None
Emit cleanup for break/continue.
auto _emit_with_cleanup_from_scope(self, ScopeContext scope, str module_name) -> None
Emit with-statement cleanup for a scope.
auto _emit_block_sequence(self, Block block, str module_name) -> None
Emit statements in a block.
auto _emit_stmt(self, Stmt stmt, str module_name) -> None
Emit a single statement.
auto _emit_block(self, Block stmt, str module_name) -> Any
Emit a block statement with its own scope.
auto _emit_return(self, ReturnStmt stmt, Callable[[], None]|None before_cleanup = None) -> Any
Emit a return statement with cleanup.
auto _register_inline_with_cleanup(self, ScopeContext scope, WithItem item) -> None
Register one inline with-item cleanup in LIFO order.
auto _emit_inline_with_header_item(self, WithItem item, str module_name, ScopeContext scope) -> None
Emit one inline with header item and register its cleanup at the committed point.
auto _emit_condition_branch(self, Expr expr, str true_label, str false_label) -> None
Emit control flow for one condition expression with short-circuit semantics.
auto _emit_condition_expr(self, Expr expr) -> str
Emit a top-level condition expression for direct statement headers.
auto _emit_condition_value(self, Expr expr) -> str
Evaluate a statement condition into a stable boolean temporary.
auto _emit_while(self, WhileStmt stmt, str module_name) -> Any
Emit a while loop.
auto _emit_for(self, ForStmt stmt, str module_name) -> Any
Emit a for loop.
auto _emit_if_else(self, IfStmt stmt, str module_name) -> Any
Emit an if-else statement.
auto _gen_if_else_branch(self, Stmt stmt, str module_name) -> bool
Emit a branch of an if/else.
auto _emit_reassignment(self, AssignStmt stmt) -> None
Emit an assignment statement.
auto _emit_lvalue_with_caching(self, Expr target) -> str
Emit an lvalue expression, caching sub-expressions with side effects.
auto _emit_let(self, LetStmt stmt, str module_name) -> Any
Emit a local 'let' declaration.
auto _emit_with_cleanup_header_let_predecl(self, LetStmt stmt, str module_name) -> Type|None
Predeclare a nullable with-header let for cleanup-block form.
auto _emit_with_cleanup_header_let_assign(self, LetStmt stmt, Type var_ty) -> None
Emit initializer assignment for a predeclared cleanup-block let.
auto _emit_match(self, MatchStmt stmt, str module_name) -> None
Emit a match statement as a switch on the tag field.
auto _emit_case(self, CaseStmt stmt, str module_name) -> None
Emit a case statement as a scalar switch or string if/else chain.
auto _emit_case_literal(self, Expr expr) -> str
Emit a constant literal for a case statement.
auto _emit_pattern_bindings(self, VariantPattern pattern, EnumType enum_type, ScopeContext arm_scope) -> None
Emit pattern variable bindings and add them to arm scope.
auto _emit_with(self, WithStmt stmt, str module_name) -> None
Emit a with statement.
auto _try_emit_intrinsic(self, CallExpr expr) -> str|None
Expand compiler intrinsics inline.
auto _emit_ord_intrinsic(self, CallExpr expr) -> str
Emit ord(enum_value) intrinsic.
auto _try_emit_constructor(self, CallExpr expr) -> str|None
Check if expr is a constructor call and emit appropriate initialization.
auto _emit_struct_constructor(self, CallExpr expr, StructType struct_type) -> str
Emit struct constructor as C designated initializer.
auto _emit_variant_constructor(self, CallExpr expr, EnumType enum_type) -> str
Emit enum variant constructor as C tagged union initializer.
auto _emit_new_expr(self, NewExpr expr) -> str
Emit a heap allocation new expression.
auto _emit_expr_with_expected_type(self, Expr e, Type expected) -> str
Emit expression with implicit type conversion to expected type.
auto _emit_owned_expr_with_expected_type(self, Expr e, Type expected) -> str
Emit expression for contexts that create a new owner.
auto _emit_expr(self, Expr expr, *bool is_statement = False) -> str
Emit an expression and return the C code.
auto _emit_binary_op(self, Expr expr_node, str expr_op, Expr expr_left, Expr expr_right, *bool for_condition = False) -> str
Emit code for a binary operation.

Function documentation

None l0_backend_lowering::Lowering::_emit_cleanup_for_return(self, str|None returned_var = None) protected

Emit cleanup logic for a return statement.

Parameters
returned_var Mangled name of variable being returned (to skip cleanup).

Walks up scope chain, executes any with-statement cleanup data, then cleans ALL owned variables (except return value). The with-cleanup runs first because user cleanup code may reference variables whose owned resources (e.g. string refcounts) are released by the automatic owned-var cleanup.

None l0_backend_lowering::Lowering::_emit_cleanup_for_loop_exit(self, *bool is_break) protected

Emit cleanup for break/continue.

Parameters
is_break True if cleaning for 'break', False for 'continue'.
Exceptions
InternalCompilerError If called outside of a loop.

Walks from current scope up to and including the innermost loop cleanup target, executing any with-statement cleanup data along the way. The with-cleanup runs before owned-var cleanup (see _emit_cleanup_for_return for rationale).

None l0_backend_lowering::Lowering::_emit_with_cleanup_from_scope(self, ScopeContext scope, str module_name) protected

Emit with-statement cleanup for a scope.

Parameters
scope The scope containing cleanup logic.
module_name Name of current module.

None l0_backend_lowering::Lowering::_emit_block_sequence(self, Block block, str module_name) protected

Emit statements in a block.

Parameters
block The Block AST node.
module_name Name of current module.

None l0_backend_lowering::Lowering::_emit_stmt(self, Stmt stmt, str module_name) protected

Emit a single statement.

Parameters
stmt The Stmt AST node.
module_name Name of current module.
Exceptions
InternalCompilerError If statement type is unsupported.

Any l0_backend_lowering::Lowering::_emit_block(self, Block stmt, str module_name) protected

Emit a block statement with its own scope.

Parameters
stmt The Block AST node.
module_name Name of current module.

Any l0_backend_lowering::Lowering::_emit_return(self, ReturnStmt stmt, Callable[[], None]|None before_cleanup = None) protected

Emit a return statement with cleanup.

Parameters
stmt The ReturnStmt AST node.
before_cleanup Optional hook to run after the return value is evaluated and before scope cleanup is emitted.

None l0_backend_lowering::Lowering::_emit_condition_branch(self, Expr expr, str true_label, str false_label) protected

Emit control flow for one condition expression with short-circuit semantics.

Parameters
expr Condition expression to lower.
true_label Jump target when the condition is true.
false_label Jump target when the condition is false.

This path is used only for statement conditions so ARC temps emitted by expression lowering stay inside the correct structural block instead of being hoisted into an enclosing "if (...)" or "while (...)" header.

str l0_backend_lowering::Lowering::_emit_condition_value(self, Expr expr) protected

Evaluate a statement condition into a stable boolean temporary.

Parameters
expr Condition expression to lower.
Returns Name of the generated boolean temp.

The returned temp is safe to reference from an if/while header because any ARC temps created while evaluating the condition are scoped to the emitted condition block and cleaned before control continues.

Any l0_backend_lowering::Lowering::_emit_while(self, WhileStmt stmt, str module_name) protected

Emit a while loop.

Parameters
stmt The WhileStmt AST node.
module_name Name of current module.

Any l0_backend_lowering::Lowering::_emit_for(self, ForStmt stmt, str module_name) protected

Emit a for loop.

Parameters
stmt The ForStmt AST node.
module_name Name of current module.

Any l0_backend_lowering::Lowering::_emit_if_else(self, IfStmt stmt, str module_name) protected

Emit an if-else statement.

Parameters
stmt The IfStmt AST node.
module_name Name of current module.

bool l0_backend_lowering::Lowering::_gen_if_else_branch(self, Stmt stmt, str module_name) protected

Emit a branch of an if/else.

Parameters
stmt The statement in the branch.
module_name Name of current module.
Returns True if branch is unreachable at end.

None l0_backend_lowering::Lowering::_emit_reassignment(self, AssignStmt stmt) protected

Emit an assignment statement.

Parameters
stmt The AssignStmt AST node.
Exceptions
InternalCompilerError If types are missing or emission fails.

str l0_backend_lowering::Lowering::_emit_lvalue_with_caching(self, Expr target) protected

Emit an lvalue expression, caching sub-expressions with side effects.

Parameters
target The lvalue expression.
Returns A C lvalue expression string.
Exceptions
InternalCompilerError If types are missing for complex lvalues.

For targets like *(func_call()), the pointer expression func_call() must be evaluated exactly once, not multiple times during release/assign/retain.

Any l0_backend_lowering::Lowering::_emit_let(self, LetStmt stmt, str module_name) protected

Emit a local 'let' declaration.

Parameters
stmt The LetStmt AST node.
module_name Name of current module.
Exceptions
InternalCompilerError If type cannot be inferred.

Type|None l0_backend_lowering::Lowering::_emit_with_cleanup_header_let_predecl(self, LetStmt stmt, str module_name) protected

Predeclare a nullable with-header let for cleanup-block form.

Parameters
stmt The LetStmt AST node.
module_name Name of current module.
Returns The Type if it was a nullable let, otherwise None.

Nullable lets are predeclared as null so cleanup code can reference them on header ? failure paths.

Non-nullable lets use the normal declaration+initializer path and return None here.

None l0_backend_lowering::Lowering::_emit_with_cleanup_header_let_assign(self, LetStmt stmt, Type var_ty) protected

Emit initializer assignment for a predeclared cleanup-block let.

Parameters
stmt The LetStmt AST node.
var_ty The resolved type of the let.

None l0_backend_lowering::Lowering::_emit_match(self, MatchStmt stmt, str module_name) protected

Emit a match statement as a switch on the tag field.

Parameters
stmt The MatchStmt AST node.
module_name Name of current module.
Exceptions
InternalCompilerError If types or patterns are unsupported.

None l0_backend_lowering::Lowering::_emit_case(self, CaseStmt stmt, str module_name) protected

Emit a case statement as a scalar switch or string if/else chain.

Parameters
stmt The CaseStmt AST node.
module_name Name of current module.
Exceptions
InternalCompilerError If types or literals are unsupported.

str l0_backend_lowering::Lowering::_emit_case_literal(self, Expr expr) protected

Emit a constant literal for a case statement.

Parameters
expr The literal expression.
Returns A C constant string.
Exceptions
InternalCompilerError If literal type is unsupported.

None l0_backend_lowering::Lowering::_emit_pattern_bindings(self, VariantPattern pattern, EnumType enum_type, ScopeContext arm_scope) protected

Emit pattern variable bindings and add them to arm scope.

Parameters
pattern The variant pattern.
enum_type The enum type.
arm_scope The scope for the match arm.
Exceptions
InternalCompilerError If variant decl is missing.

None l0_backend_lowering::Lowering::_emit_with(self, WithStmt stmt, str module_name) protected

Emit a with statement.

Parameters
stmt The WithStmt AST node.
module_name Name of current module.

Inline => form (LIFO cleanup): Emit init statements, then body, then cleanup statements in reverse order.

Cleanup block form: Emit init statements, then body, then cleanup block statements.

Cleanup is emitted at block end and before every early exit (return, break, continue). The scope stores cleanup data so _emit_cleanup_for_return and _emit_cleanup_for_loop_exit can emit it before leaving.

The body and cleanup block are each emitted as real nested C blocks so that any declarations inside them do not collide with the header scope (e.g., legal L0 shadowing like "let x" in both the header and body).

str|None l0_backend_lowering::Lowering::_try_emit_intrinsic(self, CallExpr expr) protected

Expand compiler intrinsics inline.

Parameters
expr The call expression to check.
Returns C code string if it is an intrinsic, otherwise None.

str l0_backend_lowering::Lowering::_emit_ord_intrinsic(self, CallExpr expr) protected

Emit ord(enum_value) intrinsic.

Parameters
expr The ord call expression.
Returns A C expression string for the ordinal value.
Exceptions
InternalCompilerError If argument count is incorrect.

Returns 0-based ordinal of enum variant.

str|None l0_backend_lowering::Lowering::_try_emit_constructor(self, CallExpr expr) protected

Check if expr is a constructor call and emit appropriate initialization.

Parameters
expr The call expression to check.
Returns C code string if this is a constructor, otherwise None.

Struct: Point(1, 2) -> { .x = 1, .y = 2 } Enum: Int(42) -> { .tag = Expr_Int, .data = { .Int = { .value = 42 } } }

str l0_backend_lowering::Lowering::_emit_struct_constructor(self, CallExpr expr, StructType struct_type) protected

Emit struct constructor as C designated initializer.

Parameters
expr The constructor call expression.
struct_type The struct type.
Returns A C struct initializer expression string.
Exceptions
InternalCompilerError If struct info is missing or argument count mismatches.

Point(1, 2) -> (struct l0_modulename_Point){ .x = 1, .y = 2 }

str l0_backend_lowering::Lowering::_emit_variant_constructor(self, CallExpr expr, EnumType enum_type) protected

Emit enum variant constructor as C tagged union initializer.

Parameters
expr The variant call expression.
enum_type The enum type.
Returns A C variant initializer expression string.
Exceptions
InternalCompilerError If variant info or declaration is missing.

Example: Int(42) -> (struct l0_modulename_Int){ .tag = l0_modulename_Int_Int, .data.Int.value = 42 }

str l0_backend_lowering::Lowering::_emit_new_expr(self, NewExpr expr) protected

Emit a heap allocation new expression.

Parameters
expr The NewExpr AST node.
Returns A C expression string for the newly allocated pointer.
Exceptions
InternalCompilerError If type or symbol resolution fails, or if args mismatch.

str l0_backend_lowering::Lowering::_emit_expr_with_expected_type(self, Expr e, Type expected) protected

Emit expression with implicit type conversion to expected type.

Parameters
e The expression to emit.
expected The expected type.
Returns A C expression string.
Exceptions
InternalCompilerError If null literal is assigned to invalid type.

str l0_backend_lowering::Lowering::_emit_owned_expr_with_expected_type(self, Expr e, Type expected) protected

Emit expression for contexts that create a new owner.

Parameters
e The expression to emit.
expected The expected type.
Returns A C expression string.

This applies retain-on-copy when a place expression is copied into an owned destination, while delegating regular type conversion to _emit_expr_with_expected_type.

str l0_backend_lowering::Lowering::_emit_expr(self, Expr expr, *bool is_statement = False) protected

Emit an expression and return the C code.

Parameters
expr The expression to emit.
is_statement True if the expression is used as a statement.
Returns A C expression string, or empty string if used as a statement and no-op.
Exceptions
InternalCompilerError If expression type is unsupported or resolution fails.

str l0_backend_lowering::Lowering::_emit_binary_op(self, Expr expr_node, str expr_op, Expr expr_left, Expr expr_right, *bool for_condition = False) protected

Emit code for a binary operation.

Parameters
expr_node The BinaryOp AST node.
expr_op The operator string.
expr_left The left operand.
expr_right The right operand.
for_condition Whether to preserve condition-context code generation.
Returns C code string for the operation.
Exceptions
InternalCompilerError If types are missing, mismatch, or operation is unsupported.