Class: ASTTransform::ThunkLowering
- Inherits:
-
Object
- Object
- ASTTransform::ThunkLowering
- Includes:
- TransformationHelper
- Defined in:
- lib/ast_transform/thunk_lowering.rb
Overview
Lowers Thunk nodes into plain Ruby ahead of emission. Each unique thunk (grouped by id identity) becomes a hidden proc; each occurrence becomes the proc's call:
thunk placed at the execution point
=> x = x; __ast_thunk_<n>__ = proc { body } (at the body's source lines)
...
__ast_thunk_<n>__.call (at the occurrence)
Placement is inferred, not authored: the proc's text is inserted into the statement sequence enclosing the occurrence, positioned among its siblings by the body's first source line — the lines the author removed the statements from. A loc-less body has no textual home and packs immediately before its call. Placements never escape a scope boundary (def/class/module bodies absorb their own), because the hidden lvar must share the call's method activation; they DO escape block literals, which close over the defining scope.
The closure is a non-lambda proc on purpose: return inside a proc returns from the method where the proc was
defined, and placement and execution always share one method activation, so a thunked return keeps its original
meaning. Jump keywords whose owner lies outside the body keep Ruby's native behavior (break/retry fail loudly,
next/redo silently alter flow) — what a transform chooses to thunk is the transform author's call.
The x = x pre-declarations cover every local the body assigns at method scope. A local first assigned inside a
block literal is block-local, so without a textual method-scope assignment before the proc, thunked assignments
would be invisible to the statements that read them after the execution point. Self-assignment registers the name
(nil until the thunk runs — exactly what an unexecuted assignment yields) without clobbering an already-assigned
value.
Stateless: the thunks encountered during one lowering are tracked in a Registry created at lower entry, so an
instance is a reusable collaborator.
Defined Under Namespace
Classes: Placement, PlacementError
Constant Summary collapse
- SEQUENCE_TYPES =
[:begin, :kwbegin].freeze
- SCOPE_BODY_INDEXES =
Scope-opening containers: the hidden lvar cannot be referenced across these boundaries, so placements arising inside must land inside.
{ def: 2, defs: 3, class: 2, module: 1, sclass: 1 }.freeze
Instance Method Summary collapse
-
#lower(node) ⇒ Parser::AST::Node
Tree with thunks lowered to plain Ruby.
Methods included from TransformationHelper
Instance Method Details
#lower(node) ⇒ Parser::AST::Node
Returns tree with thunks lowered to plain Ruby.
93 94 95 |
# File 'lib/ast_transform/thunk_lowering.rb', line 93 def lower(node) lower_body(node, Registry.new) end |