Skip to main content

HirBuilder

Struct HirBuilder 

Source
pub struct HirBuilder<'a> {
    pub fbt_depth: u32,
    /* private fields */
}

Fields§

§fbt_depth: u32

Traversal context: counts the number of fbt tag parents of the current babel node.

Implementations§

Source§

impl<'a> HirBuilder<'a>

Source

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 AST
  • function_scope: the ScopeId of the function being compiled
  • bindings: optional pre-existing bindings (e.g., from a parent function)
  • context: optional pre-existing captured context map
  • entry_block_kind: the kind of the entry block (defaults to Block)
Source

pub fn environment(&self) -> &Environment

Access the environment.

Source

pub fn environment_mut(&mut self) -> &mut Environment

Access the environment mutably.

Source

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.

Source

pub fn scope_info(&self) -> &ScopeInfo

Access the scope info.

Source

pub fn get_identifier_loc(&self, node_id: u32) -> Option<SourceLocation>

Look up the source location of an identifier by its node_id.

Source

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.

Source

pub fn function_scope(&self) -> ScopeId

Access the function scope (the scope of the function being compiled).

Source

pub fn component_scope(&self) -> ScopeId

Access the component scope.

Source

pub fn context(&self) -> &IndexMap<BindingId, Option<SourceLocation>>

Access the context map.

Source

pub fn context_identifiers(&self) -> &HashSet<BindingId>

Access the pre-computed context identifiers set.

Source

pub fn add_context_identifier(&mut self, binding_id: BindingId)

Add a binding to the context identifiers set (used by hoisting).

Source

pub fn claim_synthetic_scope(&mut self, scope_id: ScopeId)

Source

pub fn is_synthetic_scope_claimed(&self, scope_id: ScopeId) -> bool

Source

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.

Source

pub fn identifier_locs(&self) -> &'a IdentifierLocIndex

Access the identifier location index. Returns the ’a reference to avoid conflicts with mutable borrows on self.

Source

pub fn bindings(&self) -> &IndexMap<BindingId, IdentifierId>

Access the bindings map.

Source

pub fn used_names(&self) -> &IndexMap<String, BindingId>

Access the used names map.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

pub fn complete(&mut self, block: WipBlock, terminal: Terminal)

Save a previously reserved block as completed with the given terminal.

Source

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.

Source

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>.

Source

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.

Source

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>.

Source

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.

Source

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.

Source

pub fn resolve_throw_handler(&self) -> Option<BlockId>

Return the top of the exception handler stack, or None.

Source

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.

Source

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.

Source

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.

Source

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).

Source

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.

Source

pub fn make_temporary(&mut self, loc: Option<SourceLocation>) -> IdentifierId

Create a temporary identifier with a fresh id, returning its IdentifierId.

Source

pub fn set_identifier_loc( &mut self, id: IdentifierId, loc: Option<SourceLocation>, )

Set the source location for an identifier.

Source

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).

Source

pub fn record_diagnostic(&mut self, diagnostic: CompilerDiagnostic)

Record a diagnostic on the environment.

Source

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).

Source

pub fn current_block_kind(&self) -> BlockKind

Return the kind of the current block.

Source

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:

  1. Reverse-postorder sort + unreachable block removal
  2. Check for unreachable blocks containing FunctionExpression instructions
  3. Remove unreachable for-loop updates
  4. Remove dead do-while statements
  5. Remove unnecessary try-catch
  6. Number all instructions and terminals
  7. Mark predecessor blocks
Source

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’.

Source

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.

Source

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).

Source

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)
Source

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.

Source

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.

Source

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.

Auto Trait Implementations§

§

impl<'a> !UnwindSafe for HirBuilder<'a>

§

impl<'a> Freeze for HirBuilder<'a>

§

impl<'a> RefUnwindSafe for HirBuilder<'a>

§

impl<'a> Send for HirBuilder<'a>

§

impl<'a> Sync for HirBuilder<'a>

§

impl<'a> Unpin for HirBuilder<'a>

§

impl<'a> UnsafeUnpin for HirBuilder<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.