pub struct HirBuilder<'a> {
pub fbt_depth: u32,
/* private fields */
}Fields§
§fbt_depth: u32Traversal context: counts the number of fbt tag parents
of the current babel node.
Implementations§
Source§impl<'a> HirBuilder<'a>
impl<'a> HirBuilder<'a>
Sourcepub fn new(
env: &'a mut Environment,
scope_info: &'a ScopeInfo,
function_scope: ScopeId,
component_scope: ScopeId,
context_identifiers: HashSet<BindingId>,
bindings: Option<IndexMap<BindingId, IdentifierId>>,
context: Option<IndexMap<BindingId, Option<SourceLocation>>>,
entry_block_kind: Option<BlockKind>,
used_names: Option<IndexMap<String, BindingId>>,
identifier_locs: &'a IdentifierLocIndex,
) -> Self
pub fn new( env: &'a mut Environment, scope_info: &'a ScopeInfo, function_scope: ScopeId, component_scope: ScopeId, context_identifiers: HashSet<BindingId>, bindings: Option<IndexMap<BindingId, IdentifierId>>, context: Option<IndexMap<BindingId, Option<SourceLocation>>>, entry_block_kind: Option<BlockKind>, used_names: Option<IndexMap<String, BindingId>>, identifier_locs: &'a IdentifierLocIndex, ) -> Self
Create a new HirBuilder.
env: the shared environment (counters, arenas, error accumulator)scope_info: the scope information from the ASTfunction_scope: the ScopeId of the function being compiledbindings: optional pre-existing bindings (e.g., from a parent function)context: optional pre-existing captured context mapentry_block_kind: the kind of the entry block (defaults toBlock)
Sourcepub fn environment(&self) -> &Environment
pub fn environment(&self) -> &Environment
Access the environment.
Sourcepub fn environment_mut(&mut self) -> &mut Environment
pub fn environment_mut(&mut self) -> &mut Environment
Access the environment mutably.
Sourcepub fn make_type(&mut self) -> Type
pub fn make_type(&mut self) -> Type
Create a new unique TypeVar type, allocated from the environment’s type arena so that TypeIds are consistent with identifier type slots.
Sourcepub fn scope_info(&self) -> &ScopeInfo
pub fn scope_info(&self) -> &ScopeInfo
Access the scope info.
Sourcepub fn get_identifier_loc(&self, node_id: u32) -> Option<SourceLocation>
pub fn get_identifier_loc(&self, node_id: u32) -> Option<SourceLocation>
Look up the source location of an identifier by its node_id.
Sourcepub fn is_jsx_identifier_at_pos(&self, offset: u32) -> bool
pub fn is_jsx_identifier_at_pos(&self, offset: u32) -> bool
Check whether a reference at the given byte offset corresponds to a
JSXIdentifier. Scans the node_id-keyed index for an entry whose stored
start matches the offset.
Sourcepub fn function_scope(&self) -> ScopeId
pub fn function_scope(&self) -> ScopeId
Access the function scope (the scope of the function being compiled).
Sourcepub fn component_scope(&self) -> ScopeId
pub fn component_scope(&self) -> ScopeId
Access the component scope.
Sourcepub fn context_identifiers(&self) -> &HashSet<BindingId>
pub fn context_identifiers(&self) -> &HashSet<BindingId>
Access the pre-computed context identifiers set.
Sourcepub fn add_context_identifier(&mut self, binding_id: BindingId)
pub fn add_context_identifier(&mut self, binding_id: BindingId)
Add a binding to the context identifiers set (used by hoisting).
pub fn claim_synthetic_scope(&mut self, scope_id: ScopeId)
pub fn is_synthetic_scope_claimed(&self, scope_id: ScopeId) -> bool
Sourcepub fn scope_info_and_env_mut(&mut self) -> (&ScopeInfo, &mut Environment)
pub fn scope_info_and_env_mut(&mut self) -> (&ScopeInfo, &mut Environment)
Access scope_info and environment mutably at the same time. This is safe because they are disjoint fields, but Rust’s borrow checker can’t prove this through method calls alone.
Sourcepub fn identifier_locs(&self) -> &'a IdentifierLocIndex
pub fn identifier_locs(&self) -> &'a IdentifierLocIndex
Access the identifier location index. Returns the ’a reference to avoid conflicts with mutable borrows on self.
Sourcepub fn bindings(&self) -> &IndexMap<BindingId, IdentifierId>
pub fn bindings(&self) -> &IndexMap<BindingId, IdentifierId>
Access the bindings map.
Sourcepub fn used_names(&self) -> &IndexMap<String, BindingId>
pub fn used_names(&self) -> &IndexMap<String, BindingId>
Access the used names map.
Sourcepub fn merge_used_names(
&mut self,
child_used_names: IndexMap<String, BindingId>,
)
pub fn merge_used_names( &mut self, child_used_names: IndexMap<String, BindingId>, )
Merge used names from a child builder back into this builder. This ensures name deduplication works across function scopes.
Sourcepub fn merge_bindings(
&mut self,
child_bindings: IndexMap<BindingId, IdentifierId>,
)
pub fn merge_bindings( &mut self, child_bindings: IndexMap<BindingId, IdentifierId>, )
Merge bindings (binding_id -> IdentifierId) from a child builder back into this builder. This matches TS behavior where parent and child share the same #bindings map by reference, so bindings resolved by the child are automatically visible to the parent.
Sourcepub fn push(&mut self, instruction: Instruction)
pub fn push(&mut self, instruction: Instruction)
Push an instruction onto the current block.
Adds the instruction to the flat instruction table and records its InstructionId in the current block’s instruction list.
If an exception handler is active, also emits a MaybeThrow terminal after the instruction to model potential control flow to the handler, then continues in a new block.
Sourcepub fn terminate(
&mut self,
terminal: Terminal,
next_block_kind: Option<BlockKind>,
) -> BlockId
pub fn terminate( &mut self, terminal: Terminal, next_block_kind: Option<BlockKind>, ) -> BlockId
Terminate the current block with the given terminal and start a new block.
If next_block_kind is Some, a new current block is created with that kind.
Returns the BlockId of the completed block.
Sourcepub fn terminate_with_continuation(
&mut self,
terminal: Terminal,
continuation: WipBlock,
)
pub fn terminate_with_continuation( &mut self, terminal: Terminal, continuation: WipBlock, )
Terminate the current block with the given terminal, and set a previously reserved block as the new current block.
Sourcepub fn reserve(&mut self, kind: BlockKind) -> WipBlock
pub fn reserve(&mut self, kind: BlockKind) -> WipBlock
Reserve a new block so it can be referenced before construction.
Use terminate_with_continuation() to make it current, or complete() to
save it directly.
Sourcepub fn complete(&mut self, block: WipBlock, terminal: Terminal)
pub fn complete(&mut self, block: WipBlock, terminal: Terminal)
Save a previously reserved block as completed with the given terminal.
Sourcepub fn enter_reserved(
&mut self,
wip: WipBlock,
f: impl FnOnce(&mut Self) -> Terminal,
)
pub fn enter_reserved( &mut self, wip: WipBlock, f: impl FnOnce(&mut Self) -> Terminal, )
Sets the given wip block as current, executes the closure to populate it and obtain its terminal, then completes the block and restores the previous current block.
Sourcepub fn try_enter_reserved(
&mut self,
wip: WipBlock,
f: impl FnOnce(&mut Self) -> Result<Terminal, CompilerDiagnostic>,
) -> Result<(), CompilerDiagnostic>
pub fn try_enter_reserved( &mut self, wip: WipBlock, f: impl FnOnce(&mut Self) -> Result<Terminal, CompilerDiagnostic>, ) -> Result<(), CompilerDiagnostic>
Like enter_reserved, but the closure returns a Result<Terminal, CompilerDiagnostic>.
Sourcepub fn enter(
&mut self,
kind: BlockKind,
f: impl FnOnce(&mut Self, BlockId) -> Terminal,
) -> BlockId
pub fn enter( &mut self, kind: BlockKind, f: impl FnOnce(&mut Self, BlockId) -> Terminal, ) -> BlockId
Create a new block, set it as current, run the closure to populate it and obtain its terminal, complete the block, and restore the previous current block. Returns the new block’s BlockId.
Sourcepub fn try_enter(
&mut self,
kind: BlockKind,
f: impl FnOnce(&mut Self, BlockId) -> Result<Terminal, CompilerDiagnostic>,
) -> Result<BlockId, CompilerDiagnostic>
pub fn try_enter( &mut self, kind: BlockKind, f: impl FnOnce(&mut Self, BlockId) -> Result<Terminal, CompilerDiagnostic>, ) -> Result<BlockId, CompilerDiagnostic>
Like enter, but the closure returns a Result<Terminal, CompilerDiagnostic>.
Sourcepub fn enter_try_catch(&mut self, handler: BlockId, f: impl FnOnce(&mut Self))
pub fn enter_try_catch(&mut self, handler: BlockId, f: impl FnOnce(&mut Self))
Push an exception handler, run the closure, then pop the handler.
Sourcepub fn try_enter_try_catch(
&mut self,
handler: BlockId,
f: impl FnOnce(&mut Self) -> Result<(), CompilerDiagnostic>,
) -> Result<(), CompilerDiagnostic>
pub fn try_enter_try_catch( &mut self, handler: BlockId, f: impl FnOnce(&mut Self) -> Result<(), CompilerDiagnostic>, ) -> Result<(), CompilerDiagnostic>
Like enter_try_catch, but the closure returns a Result.
Sourcepub fn resolve_throw_handler(&self) -> Option<BlockId>
pub fn resolve_throw_handler(&self) -> Option<BlockId>
Return the top of the exception handler stack, or None.
Sourcepub fn loop_scope<T>(
&mut self,
label: Option<String>,
continue_block: BlockId,
break_block: BlockId,
f: impl FnOnce(&mut Self) -> Result<T, CompilerDiagnostic>,
) -> Result<T, CompilerDiagnostic>
pub fn loop_scope<T>( &mut self, label: Option<String>, continue_block: BlockId, break_block: BlockId, f: impl FnOnce(&mut Self) -> Result<T, CompilerDiagnostic>, ) -> Result<T, CompilerDiagnostic>
Push a Loop scope, run the closure, pop and verify.
Sourcepub fn label_scope<T>(
&mut self,
label: String,
break_block: BlockId,
f: impl FnOnce(&mut Self) -> Result<T, CompilerDiagnostic>,
) -> Result<T, CompilerDiagnostic>
pub fn label_scope<T>( &mut self, label: String, break_block: BlockId, f: impl FnOnce(&mut Self) -> Result<T, CompilerDiagnostic>, ) -> Result<T, CompilerDiagnostic>
Push a Label scope, run the closure, pop and verify.
Sourcepub fn switch_scope<T>(
&mut self,
label: Option<String>,
break_block: BlockId,
f: impl FnOnce(&mut Self) -> Result<T, CompilerDiagnostic>,
) -> Result<T, CompilerDiagnostic>
pub fn switch_scope<T>( &mut self, label: Option<String>, break_block: BlockId, f: impl FnOnce(&mut Self) -> Result<T, CompilerDiagnostic>, ) -> Result<T, CompilerDiagnostic>
Push a Switch scope, run the closure, pop and verify.
Sourcepub fn lookup_break(
&self,
label: Option<&str>,
) -> Result<BlockId, CompilerDiagnostic>
pub fn lookup_break( &self, label: Option<&str>, ) -> Result<BlockId, CompilerDiagnostic>
Look up the break target for the given label (or the innermost loop/switch if label is None).
Sourcepub fn lookup_continue(
&self,
label: Option<&str>,
) -> Result<BlockId, CompilerDiagnostic>
pub fn lookup_continue( &self, label: Option<&str>, ) -> Result<BlockId, CompilerDiagnostic>
Look up the continue target for the given label (or the innermost loop if label is None). Only loops support continue.
Sourcepub fn make_temporary(&mut self, loc: Option<SourceLocation>) -> IdentifierId
pub fn make_temporary(&mut self, loc: Option<SourceLocation>) -> IdentifierId
Create a temporary identifier with a fresh id, returning its IdentifierId.
Sourcepub fn set_identifier_loc(
&mut self,
id: IdentifierId,
loc: Option<SourceLocation>,
)
pub fn set_identifier_loc( &mut self, id: IdentifierId, loc: Option<SourceLocation>, )
Set the source location for an identifier.
Sourcepub fn record_error(
&mut self,
error: CompilerErrorDetail,
) -> Result<(), CompilerError>
pub fn record_error( &mut self, error: CompilerErrorDetail, ) -> Result<(), CompilerError>
Record an error on the environment.
Returns Err for Invariant errors (matching TS throw behavior).
Sourcepub fn record_diagnostic(&mut self, diagnostic: CompilerDiagnostic)
pub fn record_diagnostic(&mut self, diagnostic: CompilerDiagnostic)
Record a diagnostic on the environment.
Sourcepub fn has_local_binding(&self, name: &str) -> bool
pub fn has_local_binding(&self, name: &str) -> bool
Check if a name has a local binding (non-module-level). This is used for checking if fbt/fbs JSX tags are local bindings (which is not supported).
Sourcepub fn current_block_kind(&self) -> BlockKind
pub fn current_block_kind(&self) -> BlockKind
Return the kind of the current block.
Sourcepub fn build(
self,
) -> Result<(HIR, Vec<Instruction>, IndexMap<String, BindingId>, IndexMap<BindingId, IdentifierId>), CompilerError>
pub fn build( self, ) -> Result<(HIR, Vec<Instruction>, IndexMap<String, BindingId>, IndexMap<BindingId, IdentifierId>), CompilerError>
Construct the final HIR and instruction table from the completed blocks.
Performs these post-build passes:
- Reverse-postorder sort + unreachable block removal
- Check for unreachable blocks containing FunctionExpression instructions
- Remove unreachable for-loop updates
- Remove dead do-while statements
- Remove unnecessary try-catch
- Number all instructions and terminals
- Mark predecessor blocks
Sourcepub fn resolve_binding(
&mut self,
name: &str,
binding_id: BindingId,
) -> Result<IdentifierId, CompilerError>
pub fn resolve_binding( &mut self, name: &str, binding_id: BindingId, ) -> Result<IdentifierId, CompilerError>
Map a BindingId to an HIR IdentifierId.
On first encounter, creates a new Identifier with the given name and a fresh id.
On subsequent encounters, returns the cached IdentifierId.
Handles name collisions by appending _0, _1, etc.
Records errors for variables named ‘fbt’ or ‘this’.
Sourcepub fn resolve_binding_with_loc(
&mut self,
name: &str,
binding_id: BindingId,
loc: Option<SourceLocation>,
) -> Result<IdentifierId, CompilerError>
pub fn resolve_binding_with_loc( &mut self, name: &str, binding_id: BindingId, loc: Option<SourceLocation>, ) -> Result<IdentifierId, CompilerError>
Map a BindingId to an HIR IdentifierId, with an optional source location.
Sourcepub fn set_identifier_declaration_loc(
&mut self,
id: IdentifierId,
loc: &Option<SourceLocation>,
)
pub fn set_identifier_declaration_loc( &mut self, id: IdentifierId, loc: &Option<SourceLocation>, )
Set the loc on an identifier to the declaration-site loc. This overrides any previously-set loc (which may have come from a reference site).
Sourcepub fn resolve_identifier(
&mut self,
name: &str,
_start_offset: u32,
loc: Option<SourceLocation>,
node_id: Option<u32>,
) -> Result<VariableBinding, CompilerError>
pub fn resolve_identifier( &mut self, name: &str, _start_offset: u32, loc: Option<SourceLocation>, node_id: Option<u32>, ) -> Result<VariableBinding, CompilerError>
Resolve an identifier reference to a VariableBinding.
Uses ScopeInfo to determine whether the reference is:
- Global (no binding found)
- ImportDefault, ImportSpecifier, ImportNamespace (program-scope import binding)
- ModuleLocal (program-scope non-import binding)
- Identifier (local binding, resolved via resolve_binding)
Sourcepub fn is_context_identifier(
&self,
_name: &str,
_start_offset: u32,
node_id: Option<u32>,
) -> bool
pub fn is_context_identifier( &self, _name: &str, _start_offset: u32, node_id: Option<u32>, ) -> bool
Check if an identifier reference resolves to a context identifier.
A context identifier is a variable declared in an ancestor scope of the current function’s scope, but NOT in the program scope itself and NOT in the function’s own scope. These are “captured” variables from an enclosing function.
Sourcepub fn is_context_binding(&self, binding_id: BindingId) -> bool
pub fn is_context_binding(&self, binding_id: BindingId) -> bool
Like is_context_identifier, for callers that already resolved a
BindingId instead of going through a reference node.
Sourcepub fn get_function_declaration_binding(
&self,
function_scope: ScopeId,
name: &str,
) -> Option<BindingId>
pub fn get_function_declaration_binding( &self, function_scope: ScopeId, name: &str, ) -> Option<BindingId>
Resolve the binding for a function declaration’s id the way TS does:
Babel’s path.scope.getBinding(name) starts at the function’s OWN
scope, so a body-level local (or parameter) that shadows the function’s
name resolves to that inner binding rather than to the function’s
hoisted binding in the parent scope.
Babel’s scope.rename re-keys a scope’s bindings when the TS builder
renames a shadowed binding (e.g. init -> init_0), so a binding only
matches if its current name — the resolved HIR identifier name once
resolved — still equals name. A binding renamed to name overwrites
the original key in Babel and takes precedence over an unresolved
binding with that original name.
Returns None when the walk resolves outside the compiled function (degraded scope info); callers should fall back to node-based resolution in that case.