Skip to content

Lowering behaviour, shared helpers, and Builder-built Rust - #21

Merged
dannote merged 4 commits into
ownership-passfrom
lowering-helpers
Oct 26, 2026
Merged

dannote merged 4 commits into
ownership-passfrom
lowering-helpers

Conversation

@dannote

@dannote dannote commented Oct 26, 2026

Copy link
Copy Markdown
Collaborator

Follow-up to #20, stacked on ownership-pass.

  • RustQ.Meta.Lower.Stdlib.Lowering behaviour. Each Elixir module's lowering (Lower.Kernel, Enum, List, Map, MapSet, String, Tuple, Range) declares lower/2 and synth/2 as callbacks. use imports the helpers they share: lowered/2,3, type_of/2, closure/3,4, operand/2, capture/2, in_use?/2, nonnegative_count/2 and the rest. These call Lower and Typing directly; before, the lowering context was a struct of eleven closures.
  • Dispatch by name. Stdlib sends a call to the module named after its Elixir module, but only when that Elixir module belongs to Elixir and the lowering implements the behaviour, so a user alias such as Collection is never looked up. This replaces 18 dispatch clauses. Each answer is cached in :persistent_term, because an uncached lookup costs about 20 µs. Kernel's ../in hand off to Range inside Lower.Kernel.
  • RustQ.Rust.AST.Builder throughout lowering. Struct literals and five copies of a method-call constructor are now A.method, A.path, A.ref, A.block_expr, A.closure and the other Builder constructors, so chains read as pipes. Builder.expr/1 accepts every node in the AST registry instead of a hand-kept list.

Lowered output is unchanged: Figler's 1.7 MB generated.rs is byte-identical before and after. mix ci passes with 885 tests.

Lowering wrote Rust nodes as struct literals and kept five copies of a
method-call constructor. It now builds them with the Builder the Rustler
code generation already uses, and Builder.expr/1 accepts every node in
the AST registry instead of a hand-kept list.
Each Elixir module's lowering implements RustQ.Meta.Lower.Stdlib.Lowering.
Using it imports the helpers they share (lowered/2, type_of/2, closure/3,
in_use?/2, and the rest), which call Lower and Typing directly instead
of through a context of closures. Stdlib dispatches a call to the module
named after its Elixir module when that module implements the behaviour,
in place of a clause per module for lowering and another for typing.
Path calls, unary and binary operations, closures, tuples, Some/Ok/Err,
matches, assignments, and named types now use Builder constructors too.
@dannote
dannote merged commit 9fd46d9 into ownership-pass Oct 26, 2026
@dannote dannote mentioned this pull request Oct 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant