Files
regorus/src/compiler/destructuring_planner/context.rs
Anand Krishnamoorthi 1e4ff952e6 feat!: Introduce structured destructuring plans for bindings (#485)
- add a dedicated `compiler/destructuring_planner` feature that precomputes binding plans for assignments, parameters, and `some in` expressions
- enrich `ScopeContext` with same-scope tracking, local scheduling hints, and module globals so the planner enforces := shadowing rules without blocking parent scopes
- wire the planner through compiler, hoist, interpreter, and engine paths while updating binding plan variants and adding query traversal helpers for dependency analysis
- document the new planner architecture and ship interpreter regressions that exercise nested destructuring, shadowing, and error reporting

Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
2025-10-21 15:57:49 -05:00

57 lines
1.9 KiB
Rust

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
//! Context traits shared across planner submodules.
use alloc::collections::BTreeSet;
use alloc::string::String;
/// Scoping mode for variable binding decisions.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ScopingMode {
/// Respect existing bindings from parent scopes (normal scoping).
RespectParent,
/// Allow shadowing of parent scope bindings (local scoping).
AllowShadowing,
}
/// Trait for determining variable binding status within a scope context.
pub trait VariableBindingContext {
/// Check if a variable is unbound in this context.
///
/// # Arguments
/// * `var_name` - The name of the variable to check
/// * `scoping` - Whether to respect parent scopes or allow shadowing
fn is_var_unbound(&self, var_name: &str, scoping: ScopingMode) -> bool;
/// Determine whether the current scope already bound this variable.
///
/// This is used to detect same-scope rebinding conflicts when the planner
/// encounters `:=` assignments, while still allowing shadowing in nested scopes.
fn has_same_scope_binding(&self, var_name: &str) -> bool;
}
/// Context overlay that tracks newly bound variables on top of an existing context.
pub(crate) struct OverlayBindingContext<'a, T: VariableBindingContext> {
pub(crate) base: &'a T,
pub(crate) newly_bound: &'a BTreeSet<String>,
}
impl<'a, T: VariableBindingContext> VariableBindingContext for OverlayBindingContext<'a, T> {
fn is_var_unbound(&self, var_name: &str, scoping: ScopingMode) -> bool {
if self.newly_bound.contains(var_name) {
return false;
}
self.base.is_var_unbound(var_name, scoping)
}
fn has_same_scope_binding(&self, var_name: &str) -> bool {
if self.newly_bound.contains(var_name) {
return true;
}
self.base.has_same_scope_binding(var_name)
}
}