diff --git a/crates/oxide_emit/src/prepass.rs b/crates/oxide_emit/src/prepass.rs deleted file mode 100644 index b6b80f92..00000000 --- a/crates/oxide_emit/src/prepass.rs +++ /dev/null @@ -1,945 +0,0 @@ -//! emit 前置 pass:builtin 引用预扫描 + 声明预登记。 -//! -//! 在生成临时寄存器前遍历 AST,把内置全局标识符预先登记到固定寄存器槽 -//! (builtin_reg_map),避免与临时寄存器池冲突;同时预声明函数/var 声明, -//! 支持提升语义。 - -use std::collections::HashSet; - -use crate::{CompileCtx, Emitter}; -use oxide_parser::{ - BindingPattern, Declaration, ExportDefaultDeclarationKind, Expression, Statement, VariableDeclarationKind, -}; - -/// 脚本顶层 lexical 声明(let/const/class)禁止使用的受限全局名:3 名静态集。 -/// 受限判定走规范自有属性臂:全局对象上 {configurable:false} 自有属性名(声明 -/// 实例化无法建立遮蔽绑定)——现行规范下恰为三常量;eval 与各 builtin 属性皆 -/// 可配置(合法遮蔽),不在此列。名基静态集(编译期不可查运行时描述符)。与 -/// BUILTIN_GLOBALS 语义不同(后者是 put 写拦截/双写名单),不互相派生,交叠 -/// 名由漂移守卫单测断言恒同步。 -pub(crate) const RESTRICTED_GLOBAL_LEXICAL_NAMES: &[&str] = &["undefined", "NaN", "Infinity"]; - -/// 脚本顶层 lexical 声明撞受限全局名 → SyntaxError(声明实例化期拒绝,整程序 -/// 编译失败)。错误消息与既有重复声明错同形;非顶层或名不在受限集 → Ok。 -fn check_restricted_global_lexical(name: &str, global_lexical: bool) -> Result<(), String> { - if global_lexical && RESTRICTED_GLOBAL_LEXICAL_NAMES.contains(&name) { - return Err(format!("Identifier '{name}' has already been declared")); - } - Ok(()) -} - -impl Emitter { - /// 在临时寄存器池之前分配 builtin 槽位。 - pub(crate) fn pre_register_builtin_references(&self, stmts: &[Statement], ctx: &mut CompileCtx) { - for stmt in stmts { - self.pre_scan_builtin_stmt(stmt, ctx); - } - } - - fn pre_scan_builtin_stmt(&self, stmt: &Statement, ctx: &mut CompileCtx) { - match stmt { - Statement::ExpressionStatement(es) => self.pre_scan_builtin_expr(&es.expression, ctx), - Statement::VariableDeclaration(vd) => { - for d in &vd.declarations { - self.pre_scan_builtin_pattern(&d.id, ctx); - if let Some(init) = &d.init { - self.pre_scan_builtin_expr(init, ctx); - } - } - } - Statement::ReturnStatement(rs) => { - if let Some(a) = &rs.argument { - self.pre_scan_builtin_expr(a, ctx); - } - } - Statement::IfStatement(is) => { - self.pre_scan_builtin_expr(&is.test, ctx); - self.pre_scan_builtin_stmt(&is.consequent, ctx); - if let Some(alt) = &is.alternate { - self.pre_scan_builtin_stmt(alt, ctx); - } - } - Statement::WhileStatement(wh) => { - self.pre_scan_builtin_expr(&wh.test, ctx); - self.pre_scan_builtin_stmt(&wh.body, ctx); - } - Statement::DoWhileStatement(dw) => { - self.pre_scan_builtin_stmt(&dw.body, ctx); - self.pre_scan_builtin_expr(&dw.test, ctx); - } - Statement::ForStatement(fs) => { - if let Some(init) = &fs.init { - if let Some(e) = init.as_expression() { - self.pre_scan_builtin_expr(e, ctx); - } else if let oxide_parser::ForStatementInit::VariableDeclaration(decl) = init { - for d in &decl.declarations { - self.pre_scan_builtin_pattern(&d.id, ctx); - if let Some(init_expr) = &d.init { - self.pre_scan_builtin_expr(init_expr, ctx); - } - } - } - } - if let Some(t) = &fs.test { - self.pre_scan_builtin_expr(t, ctx); - } - if let Some(u) = &fs.update { - self.pre_scan_builtin_expr(u, ctx); - } - self.pre_scan_builtin_stmt(&fs.body, ctx); - } - Statement::ForInStatement(fi) => { - if let oxide_parser::ForStatementLeft::VariableDeclaration(vd) = &fi.left { - for d in &vd.declarations { - self.pre_scan_builtin_pattern(&d.id, ctx); - } - } - self.pre_scan_builtin_expr(&fi.right, ctx); - self.pre_scan_builtin_stmt(&fi.body, ctx); - } - Statement::ForOfStatement(fo) => { - if let oxide_parser::ForStatementLeft::VariableDeclaration(vd) = &fo.left { - for d in &vd.declarations { - self.pre_scan_builtin_pattern(&d.id, ctx); - } - } - self.pre_scan_builtin_expr(&fo.right, ctx); - self.pre_scan_builtin_stmt(&fo.body, ctx); - } - Statement::SwitchStatement(sw) => { - self.pre_scan_builtin_expr(&sw.discriminant, ctx); - for case in &sw.cases { - if let Some(test) = &case.test { - self.pre_scan_builtin_expr(test, ctx); - } - for s in &case.consequent { - self.pre_scan_builtin_stmt(s, ctx); - } - } - } - Statement::ThrowStatement(ts) => { - self.pre_scan_builtin_expr(&ts.argument, ctx); - } - Statement::TryStatement(ts) => { - for s in &ts.block.body { - self.pre_scan_builtin_stmt(s, ctx); - } - if let Some(handler) = &ts.handler { - if let Some(param) = &handler.param { - self.pre_scan_builtin_pattern(¶m.pattern, ctx); - } - for s in &handler.body.body { - self.pre_scan_builtin_stmt(s, ctx); - } - } - if let Some(finalizer) = &ts.finalizer { - for s in &finalizer.body { - self.pre_scan_builtin_stmt(s, ctx); - } - } - } - Statement::BlockStatement(bs) => { - for s in &bs.body { - self.pre_scan_builtin_stmt(s, ctx); - } - } - Statement::LabeledStatement(ls) => self.pre_scan_builtin_stmt(&ls.body, ctx), - Statement::WithStatement(ws) => { - self.pre_scan_builtin_expr(&ws.object, ctx); - self.pre_scan_builtin_stmt(&ws.body, ctx); - } - Statement::ClassDeclaration(cd) => { - if let Some(super_class) = &cd.super_class { - self.pre_scan_builtin_expr(super_class, ctx); - } - } - Statement::ExportNamedDeclaration(exp) => { - if let Some(Declaration::VariableDeclaration(vd)) = &exp.declaration { - for d in &vd.declarations { - self.pre_scan_builtin_pattern(&d.id, ctx); - if let Some(init) = &d.init { - self.pre_scan_builtin_expr(init, ctx); - } - } - } - } - Statement::ExportDefaultDeclaration(exp) => { - if let Some(e) = exp.declaration.as_expression() { - self.pre_scan_builtin_expr(e, ctx); - } - } - Statement::FunctionDeclaration(_) | Statement::BreakStatement(_) | Statement::ContinueStatement(_) => {} - _ => {} - } - } - - fn pre_scan_builtin_expr(&self, expr: &Expression, ctx: &mut CompileCtx) { - match expr { - Expression::Identifier(ident) => { - if CompileCtx::is_known_builtin(ident.name.as_str()) { - let _ = ctx.lookup_or_builtin(ident.name.as_str()); - } - } - Expression::BinaryExpression(bin) => { - self.pre_scan_builtin_expr(&bin.left, ctx); - self.pre_scan_builtin_expr(&bin.right, ctx); - } - Expression::UnaryExpression(un) => { - self.pre_scan_builtin_expr(&un.argument, ctx); - } - Expression::CallExpression(call) => { - self.pre_scan_builtin_expr(&call.callee, ctx); - for arg in &call.arguments { - self.pre_scan_builtin_arg(arg, ctx); - } - } - Expression::NewExpression(ne) => { - self.pre_scan_builtin_expr(&ne.callee, ctx); - for arg in &ne.arguments { - self.pre_scan_builtin_arg(arg, ctx); - } - } - Expression::LogicalExpression(log) => { - self.pre_scan_builtin_expr(&log.left, ctx); - self.pre_scan_builtin_expr(&log.right, ctx); - } - Expression::ConditionalExpression(cond) => { - self.pre_scan_builtin_expr(&cond.test, ctx); - self.pre_scan_builtin_expr(&cond.consequent, ctx); - self.pre_scan_builtin_expr(&cond.alternate, ctx); - } - Expression::PrivateInExpression(pin) => { - self.pre_scan_builtin_expr(&pin.right, ctx); - } - Expression::SequenceExpression(seq) => { - for e in &seq.expressions { - self.pre_scan_builtin_expr(e, ctx); - } - } - Expression::AssignmentExpression(assign) => { - if let Some(target) = assign.left.as_simple_assignment_target() { - self.pre_scan_builtin_target(target, ctx); - } - self.pre_scan_builtin_expr(&assign.right, ctx); - } - Expression::UpdateExpression(update) => { - self.pre_scan_builtin_target(&update.argument, ctx); - } - Expression::TemplateLiteral(tl) => { - for e in &tl.expressions { - self.pre_scan_builtin_expr(e, ctx); - } - } - Expression::TaggedTemplateExpression(tt) => { - self.pre_scan_builtin_expr(&tt.tag, ctx); - for e in &tt.quasi.expressions { - self.pre_scan_builtin_expr(e, ctx); - } - } - Expression::ObjectExpression(obj) => { - for prop in &obj.properties { - match prop { - oxide_parser::ObjectPropertyKind::ObjectProperty(p) => { - if p.computed { - self.pre_scan_builtin_expr(p.key.to_expression(), ctx); - } - self.pre_scan_builtin_expr(&p.value, ctx); - } - oxide_parser::ObjectPropertyKind::SpreadProperty(spread) => { - self.pre_scan_builtin_expr(&spread.argument, ctx); - } - } - } - } - Expression::ArrayExpression(arr) => { - for e in &arr.elements { - if let Some(e) = e.as_expression() { - self.pre_scan_builtin_expr(e, ctx); - } - } - } - Expression::PrivateFieldExpression(member) => { - self.pre_scan_builtin_expr(&member.object, ctx); - } - Expression::StaticMemberExpression(member) => { - self.pre_scan_builtin_expr(&member.object, ctx); - } - Expression::ComputedMemberExpression(member) => { - self.pre_scan_builtin_expr(&member.object, ctx); - self.pre_scan_builtin_expr(&member.expression, ctx); - } - Expression::ChainExpression(chain) => { - self.pre_scan_builtin_chain(&chain.expression, ctx); - } - Expression::ParenthesizedExpression(p) => self.pre_scan_builtin_expr(&p.expression, ctx), - Expression::YieldExpression(ye) => { - if let Some(a) = &ye.argument { - self.pre_scan_builtin_expr(a, ctx); - } - } - Expression::AwaitExpression(ae) => self.pre_scan_builtin_expr(&ae.argument, ctx), - Expression::ArrowFunctionExpression(_) - | Expression::FunctionExpression(_) - | Expression::ClassExpression(_) => {} - _ => {} - } - } - - fn pre_scan_builtin_target(&self, target: &oxide_parser::SimpleAssignmentTarget, ctx: &mut CompileCtx) { - match target { - oxide_parser::SimpleAssignmentTarget::AssignmentTargetIdentifier(id) => { - // 标识符目标与表达式位置标识符引用同口径预登记:目标为某内置名的 - // 唯一出现处(无读侧引用)时缺预登记会解析成隐式全局新槽,旧值读 - // 与短路判定拿到未预载值。 - if CompileCtx::is_known_builtin(id.name.as_str()) { - let _ = ctx.lookup_or_builtin(id.name.as_str()); - } - } - oxide_parser::SimpleAssignmentTarget::StaticMemberExpression(member) => { - self.pre_scan_builtin_expr(&member.object, ctx); - } - oxide_parser::SimpleAssignmentTarget::ComputedMemberExpression(member) => { - self.pre_scan_builtin_expr(&member.object, ctx); - self.pre_scan_builtin_expr(&member.expression, ctx); - } - oxide_parser::SimpleAssignmentTarget::PrivateFieldExpression(member) => { - self.pre_scan_builtin_expr(&member.object, ctx); - } - _ => {} - } - } - - fn pre_scan_builtin_chain(&self, element: &oxide_parser::ChainElement, ctx: &mut CompileCtx) { - match element { - oxide_parser::ChainElement::StaticMemberExpression(member) => { - self.pre_scan_builtin_expr(&member.object, ctx); - } - oxide_parser::ChainElement::ComputedMemberExpression(member) => { - self.pre_scan_builtin_expr(&member.object, ctx); - self.pre_scan_builtin_expr(&member.expression, ctx); - } - oxide_parser::ChainElement::PrivateFieldExpression(member) => { - self.pre_scan_builtin_expr(&member.object, ctx); - } - oxide_parser::ChainElement::CallExpression(call) => { - self.pre_scan_builtin_expr(&call.callee, ctx); - for arg in &call.arguments { - self.pre_scan_builtin_arg(arg, ctx); - } - } - _ => {} - } - } - - /// 遍历调用实参:spread 内部表达式也纳入 builtin 预扫描。 - fn pre_scan_builtin_arg(&self, arg: &oxide_parser::Argument, ctx: &mut CompileCtx) { - if let Some(e) = arg.as_expression() { - self.pre_scan_builtin_expr(e, ctx); - } else if let oxide_parser::Argument::SpreadElement(sp) = arg { - self.pre_scan_builtin_expr(&sp.argument, ctx); - } - } - - /// 遍历绑定 pattern 的计算键表达式(`{[k]: a}` 的键)里的 builtin 引用: - /// 模式键是运行时求值表达式,键内 builtin 标识符须预先登记固定槽位 - /// (与对象字面量计算键预扫描同口径)。 - fn pre_scan_builtin_pattern(&self, pattern: &BindingPattern, ctx: &mut CompileCtx) { - match pattern { - BindingPattern::BindingIdentifier(_) => {} - BindingPattern::ArrayPattern(ap) => { - for e in ap.elements.iter().flatten() { - self.pre_scan_builtin_pattern(e, ctx); - } - if let Some(rest) = &ap.rest { - self.pre_scan_builtin_pattern(&rest.argument, ctx); - } - } - BindingPattern::ObjectPattern(op) => { - for prop in &op.properties { - if prop.computed { - self.pre_scan_builtin_expr(prop.key.to_expression(), ctx); - } - self.pre_scan_builtin_pattern(&prop.value, ctx); - } - if let Some(rest) = &op.rest { - self.pre_scan_builtin_pattern(&rest.argument, ctx); - } - } - BindingPattern::AssignmentPattern(ap) => { - self.pre_scan_builtin_pattern(&ap.left, ctx); - } - } - } - - pub(crate) fn predeclare_function_declarations(&self, statements: &[Statement], ctx: &mut CompileCtx) { - for statement in statements { - let function = match statement { - Statement::FunctionDeclaration(f) => f, - Statement::ExportNamedDeclaration(exp) => match &exp.declaration { - Some(Declaration::FunctionDeclaration(f)) => f, - _ => continue, - }, - // export default function foo(){}:foo 绑定由 lexical predeclare 以 - // Const 预声明(emit 侧 emit_bind_target(Const) 消费预登记槽)。 - _ => continue, - }; - let Some(identifier) = &function.id else { - continue; - }; - let reg = ctx.alloc_reg(); - let _ = ctx.declare_initialized(identifier.name.as_str(), reg, VariableDeclarationKind::Var, false); - } - } - - /// 预声明单个 `var` 名:仅顶层(全局作用域)的 builtin 名落 builtin 镜像槽 - /// (run 起点预载全局属性值),使 GDI 序言与声明点同步都用入口原值而非 - /// fresh undefined 槽,现存值(NaN 等)不被抹;函数体内 builtin 名仍是局部 - /// var 遮蔽(fresh 槽,不命中只读内置拦截);其余名 fresh var 槽。 - pub(crate) fn predeclare_var_name(&self, name: &str, ctx: &mut CompileCtx) { - if ctx.is_global_scope && CompileCtx::is_known_builtin(name) { - let _ = ctx.lookup_or_builtin(name); - } else { - let reg = ctx.alloc_reg(); - let _ = ctx.declare_initialized(name, reg, VariableDeclarationKind::Var, false); - } - } - - /// 预声明语句列表中的全部 `var` 绑定,使先发的提升函数声明能解析它们。 - /// 顶层 `var` 名在编译闭包捕获它的函数体时必须可见。 - pub(crate) fn predeclare_var_declarations(&self, statements: &[Statement], ctx: &mut CompileCtx) { - for statement in statements { - match statement { - Statement::VariableDeclaration(decl) => { - if !matches!(decl.kind, VariableDeclarationKind::Var) { - continue; - } - for d in &decl.declarations { - if let oxide_parser::BindingPattern::BindingIdentifier(bi) = &d.id { - self.predeclare_var_name(bi.name.as_str(), ctx); - } - } - } - Statement::BlockStatement(bs) => self.predeclare_var_declarations(&bs.body, ctx), - Statement::IfStatement(is) => { - self.predeclare_var_declarations(std::slice::from_ref(&is.consequent), ctx); - if let Some(alt) = &is.alternate { - self.predeclare_var_declarations(std::slice::from_ref(alt), ctx); - } - } - Statement::WhileStatement(wh) => { - self.predeclare_var_declarations(std::slice::from_ref(&wh.body), ctx); - } - Statement::DoWhileStatement(dw) => { - self.predeclare_var_declarations(std::slice::from_ref(&dw.body), ctx); - } - Statement::ForStatement(fs) => { - if let Some(oxide_parser::ForStatementInit::VariableDeclaration(decl)) = &fs.init { - if matches!(decl.kind, VariableDeclarationKind::Var) { - for d in &decl.declarations { - if let oxide_parser::BindingPattern::BindingIdentifier(bi) = &d.id { - self.predeclare_var_name(bi.name.as_str(), ctx); - } - } - } - } - self.predeclare_var_declarations(std::slice::from_ref(&fs.body), ctx); - } - Statement::ForInStatement(fi) => { - // var 头名提升到函数/全局作用域(与 For 臂同规则),先于提升 - // 函数声明发射预声明,使函数体按既有 var 绑定解析头名; - // let/const 头是迭代级绑定,不入提升面。 - if let oxide_parser::ForStatementLeft::VariableDeclaration(decl) = &fi.left { - if matches!(decl.kind, VariableDeclarationKind::Var) { - for d in &decl.declarations { - if let oxide_parser::BindingPattern::BindingIdentifier(bi) = &d.id { - self.predeclare_var_name(bi.name.as_str(), ctx); - } - } - } - } - self.predeclare_var_declarations(std::slice::from_ref(&fi.body), ctx); - } - Statement::ForOfStatement(fo) => { - if let oxide_parser::ForStatementLeft::VariableDeclaration(decl) = &fo.left { - if matches!(decl.kind, VariableDeclarationKind::Var) { - for d in &decl.declarations { - if let oxide_parser::BindingPattern::BindingIdentifier(bi) = &d.id { - self.predeclare_var_name(bi.name.as_str(), ctx); - } - } - } - } - self.predeclare_var_declarations(std::slice::from_ref(&fo.body), ctx); - } - Statement::SwitchStatement(sw) => { - for case in &sw.cases { - self.predeclare_var_declarations(&case.consequent, ctx); - } - } - Statement::TryStatement(ts) => { - self.predeclare_var_declarations(&ts.block.body, ctx); - if let Some(handler) = &ts.handler { - self.predeclare_var_declarations(&handler.body.body, ctx); - } - if let Some(finalizer) = &ts.finalizer { - self.predeclare_var_declarations(&finalizer.body, ctx); - } - } - Statement::LabeledStatement(ls) => { - self.predeclare_var_declarations(std::slice::from_ref(&ls.body), ctx); - } - Statement::WithStatement(ws) => { - self.predeclare_var_declarations(std::slice::from_ref(&ws.body), ctx); - } - Statement::ExportNamedDeclaration(exp) => { - if let Some(Declaration::VariableDeclaration(decl)) = &exp.declaration { - if !matches!(decl.kind, VariableDeclarationKind::Var) { - continue; - } - for d in &decl.declarations { - if let oxide_parser::BindingPattern::BindingIdentifier(bi) = &d.id { - self.predeclare_var_name(bi.name.as_str(), ctx); - } - } - } - } - _ => {} - } - } - } - - /// 预声明当前块直接子树中的函数声明(ES2015 块级绑定,kind=Let 落当前块), - /// 使块内声明点之前的引用在编译期可见。递归进入嵌套块时压/弹作用域, - /// 与 emit 阶段嵌套块 push_scope 的时机对齐。 - /// - /// # 边界与前提 - /// - 只处理块内函数声明;switch 不推 scope(其 case 内函数声明随 switch - /// 作用域修复一并处理);export 声明不可能出现在块内。 - /// - 与 lexical 预声明的顺序:本函数在前,`{ let g; function g(){} }` 时 - /// lexical 的 `declare_predeclared` 命中已存在的函数绑定自然报重复声明错, - /// 避免函数预声明被 lexical 占位静默覆盖而破坏 let 的 TDZ。 - /// - var 与函数同名(`{ var g; function g(){} }`):var 落函数作用域、 - /// 函数落当前块,不同 scope 互不冲突。 - pub(crate) fn predeclare_block_function_declarations(&self, statements: &[Statement], ctx: &mut CompileCtx) { - for statement in statements { - match statement { - Statement::FunctionDeclaration(f) => { - let Some(identifier) = &f.id else { - continue; - }; - let reg = ctx.alloc_reg(); - let _ = ctx.declare_initialized(identifier.name.as_str(), reg, VariableDeclarationKind::Let, false); - } - Statement::BlockStatement(bs) => { - ctx.push_scope(); - self.predeclare_block_function_declarations(&bs.body, ctx); - ctx.pop_scope(); - } - Statement::IfStatement(is) => { - self.predeclare_block_function_declarations(std::slice::from_ref(&is.consequent), ctx); - if let Some(alt) = &is.alternate { - self.predeclare_block_function_declarations(std::slice::from_ref(alt), ctx); - } - } - Statement::WhileStatement(wh) => { - self.predeclare_block_function_declarations(std::slice::from_ref(&wh.body), ctx); - } - Statement::DoWhileStatement(dw) => { - self.predeclare_block_function_declarations(std::slice::from_ref(&dw.body), ctx); - } - Statement::ForStatement(fs) => { - // 循环推独立作用域(头声明所在),函数声明落该作用域与 emit 对齐。 - ctx.push_scope(); - self.predeclare_block_function_declarations(std::slice::from_ref(&fs.body), ctx); - ctx.pop_scope(); - } - Statement::ForInStatement(fi) => { - ctx.push_scope(); - self.predeclare_block_function_declarations(std::slice::from_ref(&fi.body), ctx); - ctx.pop_scope(); - } - Statement::ForOfStatement(fo) => { - ctx.push_scope(); - self.predeclare_block_function_declarations(std::slice::from_ref(&fo.body), ctx); - ctx.pop_scope(); - } - Statement::TryStatement(ts) => { - ctx.push_scope(); - self.predeclare_block_function_declarations(&ts.block.body, ctx); - ctx.pop_scope(); - if let Some(handler) = &ts.handler { - ctx.push_scope(); - self.predeclare_block_function_declarations(&handler.body.body, ctx); - ctx.pop_scope(); - } - if let Some(finalizer) = &ts.finalizer { - ctx.push_scope(); - self.predeclare_block_function_declarations(&finalizer.body, ctx); - ctx.pop_scope(); - } - } - Statement::LabeledStatement(ls) => { - self.predeclare_block_function_declarations(std::slice::from_ref(&ls.body), ctx); - } - Statement::WithStatement(ws) => { - self.predeclare_block_function_declarations(std::slice::from_ref(&ws.body), ctx); - } - _ => {} - } - } - } - - /// 预声明当前作用域直接子语句中的 `let`/`const`/`class` 绑定(未初始化, - /// 建立 TDZ 占位)。使声明点之前的读取在编译期可分辨为 TDZ 而非隐式全局, - /// 声明点复用预登记槽位。 - /// - /// # 边界与前提 - /// - 只扫描直接子语句 + 递归 switch case(switch 不推 scope,case 内 lexical - /// 声明属于外层作用域);不递归块/if/for/while body(嵌套块自预声明; - /// 单语句 body 不接受 lexical 声明——lexical 属 Declaration、非 Statement - /// 子产生式,parser 按语法错误直接拒绝,这些形状不会进入 emit)。 - /// - 跳过 for 头声明(循环作用域由 for 分支内联 declare)。 - /// - `global_lexical` 为 true 时(仅脚本顶层调用点传 `!is_eval_script`): - /// lexical 声明撞受限全局名报 SyntaxError(脚本声明实例化对全局对象受限 - /// 自有属性名做检查,eval 代码声明实例化无此检查);函数体/块/try/模块 - /// 调用点传 false,lexical 声明是局部绑定不查。 - pub(crate) fn predeclare_lexical_declarations( - &self, statements: &[Statement], ctx: &mut CompileCtx, global_lexical: bool, - ) -> Result<(), String> { - for statement in statements { - match statement { - Statement::VariableDeclaration(decl) => { - if matches!(decl.kind, VariableDeclarationKind::Var) { - continue; - } - let is_const = matches!(decl.kind, VariableDeclarationKind::Const); - for d in &decl.declarations { - self.predeclare_lexical_pattern(&d.id, is_const, ctx, global_lexical)?; - } - } - Statement::ClassDeclaration(cd) => { - if let Some(id) = &cd.id { - check_restricted_global_lexical(id.name.as_str(), global_lexical)?; - let reg = ctx.alloc_reg(); - let _ = ctx.declare_predeclared(id.name.as_str(), reg, VariableDeclarationKind::Const, true); - } - } - Statement::SwitchStatement(sw) => { - for case in &sw.cases { - for s in &case.consequent { - self.predeclare_lexical_stmt(s, ctx, global_lexical)?; - } - } - } - Statement::ExportNamedDeclaration(exp) => { - if let Some(decl) = &exp.declaration { - match decl { - Declaration::VariableDeclaration(vd) => { - if matches!(vd.kind, VariableDeclarationKind::Var) { - continue; - } - let is_const = matches!(vd.kind, VariableDeclarationKind::Const); - for d in &vd.declarations { - self.predeclare_lexical_pattern(&d.id, is_const, ctx, global_lexical)?; - } - } - Declaration::ClassDeclaration(cd) => { - if let Some(id) = &cd.id { - check_restricted_global_lexical(id.name.as_str(), global_lexical)?; - let reg = ctx.alloc_reg(); - let _ = ctx.declare_predeclared( - id.name.as_str(), - reg, - VariableDeclarationKind::Const, - true, - ); - } - } - _ => {} - } - } - } - Statement::ExportDefaultDeclaration(exp) => match &exp.declaration { - ExportDefaultDeclarationKind::ClassDeclaration(cd) => { - if let Some(id) = &cd.id { - check_restricted_global_lexical(id.name.as_str(), global_lexical)?; - let reg = ctx.alloc_reg(); - let _ = - ctx.declare_predeclared(id.name.as_str(), reg, VariableDeclarationKind::Const, true); - } - } - ExportDefaultDeclarationKind::FunctionDeclaration(fd) => { - if let Some(id) = &fd.id { - let reg = ctx.alloc_reg(); - let _ = - ctx.declare_predeclared(id.name.as_str(), reg, VariableDeclarationKind::Const, true); - } - } - _ => {} - }, - _ => {} - } - } - Ok(()) - } - - /// 预声明单个语句中的 lexical 声明(供 switch case 递归;`let`/`const`/`class` 分支)。 - fn predeclare_lexical_stmt( - &self, stmt: &Statement, ctx: &mut CompileCtx, global_lexical: bool, - ) -> Result<(), String> { - match stmt { - Statement::VariableDeclaration(decl) => { - if matches!(decl.kind, VariableDeclarationKind::Var) { - return Ok(()); - } - let is_const = matches!(decl.kind, VariableDeclarationKind::Const); - for d in &decl.declarations { - self.predeclare_lexical_pattern(&d.id, is_const, ctx, global_lexical)?; - } - } - Statement::ClassDeclaration(cd) => { - if let Some(id) = &cd.id { - check_restricted_global_lexical(id.name.as_str(), global_lexical)?; - let reg = ctx.alloc_reg(); - let _ = ctx.declare_predeclared(id.name.as_str(), reg, VariableDeclarationKind::Const, true); - } - } - _ => {} - } - Ok(()) - } - - /// 递归预声明绑定 pattern 内的全部标识符(含数组/对象/默认值解构)。 - fn predeclare_lexical_pattern( - &self, pattern: &BindingPattern, is_const: bool, ctx: &mut CompileCtx, global_lexical: bool, - ) -> Result<(), String> { - match pattern { - BindingPattern::BindingIdentifier(bi) => { - check_restricted_global_lexical(bi.name.as_str(), global_lexical)?; - let reg = ctx.alloc_reg(); - let _ = ctx.declare_predeclared( - bi.name.as_str(), - reg, - if is_const { - VariableDeclarationKind::Const - } else { - VariableDeclarationKind::Let - }, - is_const, - ); - } - BindingPattern::ArrayPattern(ap) => { - for e in ap.elements.iter().flatten() { - self.predeclare_lexical_pattern(e, is_const, ctx, global_lexical)?; - } - if let Some(rest) = &ap.rest { - self.predeclare_lexical_pattern(&rest.argument, is_const, ctx, global_lexical)?; - } - } - BindingPattern::ObjectPattern(op) => { - for prop in &op.properties { - self.predeclare_lexical_pattern(&prop.value, is_const, ctx, global_lexical)?; - } - if let Some(rest) = &op.rest { - self.predeclare_lexical_pattern(&rest.argument, is_const, ctx, global_lexical)?; - } - } - BindingPattern::AssignmentPattern(ap) => { - self.predeclare_lexical_pattern(&ap.left, is_const, ctx, global_lexical)?; - } - } - Ok(()) - } -} - -impl Emitter { - /// 递归收集语句树内块级函数声明名(源序去重),供 web-compat 外层 var 绑定 - /// 实例化。 - /// - /// # 边界与前提 - /// - 调用点直接子级(函数体/程序顶层直接子句)是提升 var 声明,非块级 - /// 函数,不收集;进入嵌套语句(块/if/循环/switch case/try 各区)后的 - /// 函数声明才是块级。 - /// - 不递归进嵌套函数体:那是独立编译单元,其内部块函数名由该单元自身收集。 - /// - switch 不推作用域(case 内函数声明随外层块),收集须进入 case 才能到达 - /// case 内的 for/块等块级形。 - pub(crate) fn collect_block_function_names(&self, statements: &[Statement]) -> Vec { - let mut names = Vec::new(); - self.collect_block_function_names_into(statements, &mut names, false); - names - } - - fn collect_block_function_names_into(&self, statements: &[Statement], names: &mut Vec, block_level: bool) { - for statement in statements { - match statement { - Statement::FunctionDeclaration(f) => { - if block_level { - if let Some(id) = &f.id { - let name = id.name.to_string(); - if !names.contains(&name) { - names.push(name); - } - } - } - } - Statement::BlockStatement(bs) => self.collect_block_function_names_into(&bs.body, names, true), - Statement::IfStatement(is) => { - self.collect_block_function_names_into(std::slice::from_ref(&is.consequent), names, true); - if let Some(alt) = &is.alternate { - self.collect_block_function_names_into(std::slice::from_ref(alt), names, true); - } - } - Statement::WhileStatement(wh) => { - self.collect_block_function_names_into(std::slice::from_ref(&wh.body), names, true) - } - Statement::DoWhileStatement(dw) => { - self.collect_block_function_names_into(std::slice::from_ref(&dw.body), names, true) - } - Statement::ForStatement(fs) => { - self.collect_block_function_names_into(std::slice::from_ref(&fs.body), names, true) - } - Statement::ForInStatement(fi) => { - self.collect_block_function_names_into(std::slice::from_ref(&fi.body), names, true) - } - Statement::ForOfStatement(fo) => { - self.collect_block_function_names_into(std::slice::from_ref(&fo.body), names, true) - } - Statement::SwitchStatement(sw) => { - for case in &sw.cases { - self.collect_block_function_names_into(&case.consequent, names, true); - } - } - Statement::TryStatement(ts) => { - self.collect_block_function_names_into(&ts.block.body, names, true); - if let Some(handler) = &ts.handler { - self.collect_block_function_names_into(&handler.body.body, names, true); - } - if let Some(finalizer) = &ts.finalizer { - self.collect_block_function_names_into(&finalizer.body, names, true); - } - } - Statement::LabeledStatement(ls) => { - self.collect_block_function_names_into(std::slice::from_ref(&ls.body), names, true) - } - Statement::WithStatement(ws) => { - self.collect_block_function_names_into(std::slice::from_ref(&ws.body), names, true) - } - _ => {} - } - } - } - - /// 收集语句树内的词法声明名(let/const/class 含解构叶、for 头词法名、catch - /// 参数):块级函数名与树内任意词法声明同名时退化为纯块作用域(无外层 - /// 绑定、无求值写回)。 - /// - /// # 边界与前提 - /// - 不递归进嵌套函数体/class 元素体:独立编译单元,其词法名不撞本单元的 - /// 块函数名。 - /// - var 声明是 var 绑定,不撞词法环境,不入集。 - fn collect_lexical_name_suppressions(&self, statements: &[Statement], names: &mut HashSet) { - for statement in statements { - match statement { - Statement::VariableDeclaration(vd) => { - if !matches!(vd.kind, VariableDeclarationKind::Var) { - for d in &vd.declarations { - self.collect_binding_pattern_names(&d.id, names); - } - } - } - Statement::ClassDeclaration(cd) => { - if let Some(id) = &cd.id { - names.insert(id.name.to_string()); - } - } - Statement::ForStatement(fs) => { - if let Some(oxide_parser::ForStatementInit::VariableDeclaration(decl)) = &fs.init { - if !matches!(decl.kind, VariableDeclarationKind::Var) { - for d in &decl.declarations { - self.collect_binding_pattern_names(&d.id, names); - } - } - } - self.collect_lexical_name_suppressions(std::slice::from_ref(&fs.body), names); - } - Statement::ForInStatement(fi) => { - if let oxide_parser::ForStatementLeft::VariableDeclaration(decl) = &fi.left { - if !matches!(decl.kind, VariableDeclarationKind::Var) { - for d in &decl.declarations { - self.collect_binding_pattern_names(&d.id, names); - } - } - } - self.collect_lexical_name_suppressions(std::slice::from_ref(&fi.body), names); - } - Statement::ForOfStatement(fo) => { - if let oxide_parser::ForStatementLeft::VariableDeclaration(decl) = &fo.left { - if !matches!(decl.kind, VariableDeclarationKind::Var) { - for d in &decl.declarations { - self.collect_binding_pattern_names(&d.id, names); - } - } - } - self.collect_lexical_name_suppressions(std::slice::from_ref(&fo.body), names); - } - Statement::TryStatement(ts) => { - // catch 参数是 handler 环境的词法绑定。 - if let Some(handler) = &ts.handler { - if let Some(param) = &handler.param { - self.collect_binding_pattern_names(¶m.pattern, names); - } - self.collect_lexical_name_suppressions(&handler.body.body, names); - } - self.collect_lexical_name_suppressions(&ts.block.body, names); - if let Some(finalizer) = &ts.finalizer { - self.collect_lexical_name_suppressions(&finalizer.body, names); - } - } - Statement::BlockStatement(bs) => self.collect_lexical_name_suppressions(&bs.body, names), - Statement::IfStatement(is) => { - self.collect_lexical_name_suppressions(std::slice::from_ref(&is.consequent), names); - if let Some(alt) = &is.alternate { - self.collect_lexical_name_suppressions(std::slice::from_ref(alt), names); - } - } - Statement::WhileStatement(wh) => { - self.collect_lexical_name_suppressions(std::slice::from_ref(&wh.body), names) - } - Statement::DoWhileStatement(dw) => { - self.collect_lexical_name_suppressions(std::slice::from_ref(&dw.body), names) - } - Statement::SwitchStatement(sw) => { - for case in &sw.cases { - self.collect_lexical_name_suppressions(&case.consequent, names); - } - } - Statement::LabeledStatement(ls) => { - self.collect_lexical_name_suppressions(std::slice::from_ref(&ls.body), names) - } - Statement::WithStatement(ws) => { - self.collect_lexical_name_suppressions(std::slice::from_ref(&ws.body), names) - } - Statement::ExportNamedDeclaration(exp) => { - if let Some(Declaration::VariableDeclaration(vd)) = &exp.declaration { - if !matches!(vd.kind, VariableDeclarationKind::Var) { - for d in &vd.declarations { - self.collect_binding_pattern_names(&d.id, names); - } - } - } - } - _ => {} - } - } - } - - /// 块级函数名 web-compat 外层绑定抑制集:形参名(含解构叶/rest)∪ 语句树内 - /// 词法声明名。命中抑制的名字不建外层 var 绑定、不求值写回。 - pub(crate) fn collect_block_fn_suppressed_names( - &self, statements: &[Statement], param_names: &HashSet, - ) -> HashSet { - let mut names = param_names.clone(); - self.collect_lexical_name_suppressions(statements, &mut names); - names - } -} diff --git a/crates/oxide_emit/src/prepass/block_fn.rs b/crates/oxide_emit/src/prepass/block_fn.rs new file mode 100644 index 00000000..e52e93ec --- /dev/null +++ b/crates/oxide_emit/src/prepass/block_fn.rs @@ -0,0 +1,200 @@ +//! emit 前置 pass,块级函数名收集:web-compat 外层 var 绑定实例化支撑—— +//! 语句树内块级函数声明名源序去重收集、词法声明名抑制集(块函数名与词法名 +//! 同名时退化为纯块作用域)、形参名 ∪ 词法名抑制集构建。 + +use std::collections::HashSet; + +use crate::Emitter; +use oxide_parser::{Declaration, Statement, VariableDeclarationKind}; + +impl Emitter { + /// 递归收集语句树内块级函数声明名(源序去重),供 web-compat 外层 var 绑定 + /// 实例化。 + /// + /// # 边界与前提 + /// - 调用点直接子级(函数体/程序顶层直接子句)是提升 var 声明,非块级 + /// 函数,不收集;进入嵌套语句(块/if/循环/switch case/try 各区)后的 + /// 函数声明才是块级。 + /// - 不递归进嵌套函数体:那是独立编译单元,其内部块函数名由该单元自身收集。 + /// - switch 不推作用域(case 内函数声明随外层块),收集须进入 case 才能到达 + /// case 内的 for/块等块级形。 + pub(crate) fn collect_block_function_names(&self, statements: &[Statement]) -> Vec { + let mut names = Vec::new(); + self.collect_block_function_names_into(statements, &mut names, false); + names + } + + fn collect_block_function_names_into(&self, statements: &[Statement], names: &mut Vec, block_level: bool) { + for statement in statements { + match statement { + Statement::FunctionDeclaration(f) => { + if block_level { + if let Some(id) = &f.id { + let name = id.name.to_string(); + if !names.contains(&name) { + names.push(name); + } + } + } + } + Statement::BlockStatement(bs) => self.collect_block_function_names_into(&bs.body, names, true), + Statement::IfStatement(is) => { + self.collect_block_function_names_into(std::slice::from_ref(&is.consequent), names, true); + if let Some(alt) = &is.alternate { + self.collect_block_function_names_into(std::slice::from_ref(alt), names, true); + } + } + Statement::WhileStatement(wh) => { + self.collect_block_function_names_into(std::slice::from_ref(&wh.body), names, true) + } + Statement::DoWhileStatement(dw) => { + self.collect_block_function_names_into(std::slice::from_ref(&dw.body), names, true) + } + Statement::ForStatement(fs) => { + self.collect_block_function_names_into(std::slice::from_ref(&fs.body), names, true) + } + Statement::ForInStatement(fi) => { + self.collect_block_function_names_into(std::slice::from_ref(&fi.body), names, true) + } + Statement::ForOfStatement(fo) => { + self.collect_block_function_names_into(std::slice::from_ref(&fo.body), names, true) + } + Statement::SwitchStatement(sw) => { + for case in &sw.cases { + self.collect_block_function_names_into(&case.consequent, names, true); + } + } + Statement::TryStatement(ts) => { + self.collect_block_function_names_into(&ts.block.body, names, true); + if let Some(handler) = &ts.handler { + self.collect_block_function_names_into(&handler.body.body, names, true); + } + if let Some(finalizer) = &ts.finalizer { + self.collect_block_function_names_into(&finalizer.body, names, true); + } + } + Statement::LabeledStatement(ls) => { + self.collect_block_function_names_into(std::slice::from_ref(&ls.body), names, true) + } + Statement::WithStatement(ws) => { + self.collect_block_function_names_into(std::slice::from_ref(&ws.body), names, true) + } + _ => {} + } + } + } + + /// 收集语句树内的词法声明名(let/const/class 含解构叶、for 头词法名、catch + /// 参数):块级函数名与树内任意词法声明同名时退化为纯块作用域(无外层 + /// 绑定、无求值写回)。 + /// + /// # 边界与前提 + /// - 不递归进嵌套函数体/class 元素体:独立编译单元,其词法名不撞本单元的 + /// 块函数名。 + /// - var 声明是 var 绑定,不撞词法环境,不入集。 + fn collect_lexical_name_suppressions(&self, statements: &[Statement], names: &mut HashSet) { + for statement in statements { + match statement { + Statement::VariableDeclaration(vd) => { + if !matches!(vd.kind, VariableDeclarationKind::Var) { + for d in &vd.declarations { + self.collect_binding_pattern_names(&d.id, names); + } + } + } + Statement::ClassDeclaration(cd) => { + if let Some(id) = &cd.id { + names.insert(id.name.to_string()); + } + } + Statement::ForStatement(fs) => { + if let Some(oxide_parser::ForStatementInit::VariableDeclaration(decl)) = &fs.init { + if !matches!(decl.kind, VariableDeclarationKind::Var) { + for d in &decl.declarations { + self.collect_binding_pattern_names(&d.id, names); + } + } + } + self.collect_lexical_name_suppressions(std::slice::from_ref(&fs.body), names); + } + Statement::ForInStatement(fi) => { + if let oxide_parser::ForStatementLeft::VariableDeclaration(decl) = &fi.left { + if !matches!(decl.kind, VariableDeclarationKind::Var) { + for d in &decl.declarations { + self.collect_binding_pattern_names(&d.id, names); + } + } + } + self.collect_lexical_name_suppressions(std::slice::from_ref(&fi.body), names); + } + Statement::ForOfStatement(fo) => { + if let oxide_parser::ForStatementLeft::VariableDeclaration(decl) = &fo.left { + if !matches!(decl.kind, VariableDeclarationKind::Var) { + for d in &decl.declarations { + self.collect_binding_pattern_names(&d.id, names); + } + } + } + self.collect_lexical_name_suppressions(std::slice::from_ref(&fo.body), names); + } + Statement::TryStatement(ts) => { + // catch 参数是 handler 环境的词法绑定。 + if let Some(handler) = &ts.handler { + if let Some(param) = &handler.param { + self.collect_binding_pattern_names(¶m.pattern, names); + } + self.collect_lexical_name_suppressions(&handler.body.body, names); + } + self.collect_lexical_name_suppressions(&ts.block.body, names); + if let Some(finalizer) = &ts.finalizer { + self.collect_lexical_name_suppressions(&finalizer.body, names); + } + } + Statement::BlockStatement(bs) => self.collect_lexical_name_suppressions(&bs.body, names), + Statement::IfStatement(is) => { + self.collect_lexical_name_suppressions(std::slice::from_ref(&is.consequent), names); + if let Some(alt) = &is.alternate { + self.collect_lexical_name_suppressions(std::slice::from_ref(alt), names); + } + } + Statement::WhileStatement(wh) => { + self.collect_lexical_name_suppressions(std::slice::from_ref(&wh.body), names) + } + Statement::DoWhileStatement(dw) => { + self.collect_lexical_name_suppressions(std::slice::from_ref(&dw.body), names) + } + Statement::SwitchStatement(sw) => { + for case in &sw.cases { + self.collect_lexical_name_suppressions(&case.consequent, names); + } + } + Statement::LabeledStatement(ls) => { + self.collect_lexical_name_suppressions(std::slice::from_ref(&ls.body), names) + } + Statement::WithStatement(ws) => { + self.collect_lexical_name_suppressions(std::slice::from_ref(&ws.body), names) + } + Statement::ExportNamedDeclaration(exp) => { + if let Some(Declaration::VariableDeclaration(vd)) = &exp.declaration { + if !matches!(vd.kind, VariableDeclarationKind::Var) { + for d in &vd.declarations { + self.collect_binding_pattern_names(&d.id, names); + } + } + } + } + _ => {} + } + } + } + + /// 块级函数名 web-compat 外层绑定抑制集:形参名(含解构叶/rest)∪ 语句树内 + /// 词法声明名。命中抑制的名字不建外层 var 绑定、不求值写回。 + pub(crate) fn collect_block_fn_suppressed_names( + &self, statements: &[Statement], param_names: &HashSet, + ) -> HashSet { + let mut names = param_names.clone(); + self.collect_lexical_name_suppressions(statements, &mut names); + names + } +} diff --git a/crates/oxide_emit/src/prepass/builtin_scan.rs b/crates/oxide_emit/src/prepass/builtin_scan.rs new file mode 100644 index 00000000..b66c81cd --- /dev/null +++ b/crates/oxide_emit/src/prepass/builtin_scan.rs @@ -0,0 +1,350 @@ +//! emit 前置 pass,builtin 引用预扫描:临时寄存器池分配前遍历 AST,把内置 +//! 全局标识符出现处(语句/表达式/赋值目标/链式成员/实参/绑定 pattern 计算 +//! 键)预先登记到固定寄存器槽(builtin_reg_map),避免与临时寄存器池冲突。 + +use crate::{CompileCtx, Emitter}; +use oxide_parser::{BindingPattern, Declaration, Expression, Statement}; + +impl Emitter { + /// 在临时寄存器池之前分配 builtin 槽位。 + pub(crate) fn pre_register_builtin_references(&self, stmts: &[Statement], ctx: &mut CompileCtx) { + for stmt in stmts { + self.pre_scan_builtin_stmt(stmt, ctx); + } + } + + fn pre_scan_builtin_stmt(&self, stmt: &Statement, ctx: &mut CompileCtx) { + match stmt { + Statement::ExpressionStatement(es) => self.pre_scan_builtin_expr(&es.expression, ctx), + Statement::VariableDeclaration(vd) => { + for d in &vd.declarations { + self.pre_scan_builtin_pattern(&d.id, ctx); + if let Some(init) = &d.init { + self.pre_scan_builtin_expr(init, ctx); + } + } + } + Statement::ReturnStatement(rs) => { + if let Some(a) = &rs.argument { + self.pre_scan_builtin_expr(a, ctx); + } + } + Statement::IfStatement(is) => { + self.pre_scan_builtin_expr(&is.test, ctx); + self.pre_scan_builtin_stmt(&is.consequent, ctx); + if let Some(alt) = &is.alternate { + self.pre_scan_builtin_stmt(alt, ctx); + } + } + Statement::WhileStatement(wh) => { + self.pre_scan_builtin_expr(&wh.test, ctx); + self.pre_scan_builtin_stmt(&wh.body, ctx); + } + Statement::DoWhileStatement(dw) => { + self.pre_scan_builtin_stmt(&dw.body, ctx); + self.pre_scan_builtin_expr(&dw.test, ctx); + } + Statement::ForStatement(fs) => { + if let Some(init) = &fs.init { + if let Some(e) = init.as_expression() { + self.pre_scan_builtin_expr(e, ctx); + } else if let oxide_parser::ForStatementInit::VariableDeclaration(decl) = init { + for d in &decl.declarations { + self.pre_scan_builtin_pattern(&d.id, ctx); + if let Some(init_expr) = &d.init { + self.pre_scan_builtin_expr(init_expr, ctx); + } + } + } + } + if let Some(t) = &fs.test { + self.pre_scan_builtin_expr(t, ctx); + } + if let Some(u) = &fs.update { + self.pre_scan_builtin_expr(u, ctx); + } + self.pre_scan_builtin_stmt(&fs.body, ctx); + } + Statement::ForInStatement(fi) => { + if let oxide_parser::ForStatementLeft::VariableDeclaration(vd) = &fi.left { + for d in &vd.declarations { + self.pre_scan_builtin_pattern(&d.id, ctx); + } + } + self.pre_scan_builtin_expr(&fi.right, ctx); + self.pre_scan_builtin_stmt(&fi.body, ctx); + } + Statement::ForOfStatement(fo) => { + if let oxide_parser::ForStatementLeft::VariableDeclaration(vd) = &fo.left { + for d in &vd.declarations { + self.pre_scan_builtin_pattern(&d.id, ctx); + } + } + self.pre_scan_builtin_expr(&fo.right, ctx); + self.pre_scan_builtin_stmt(&fo.body, ctx); + } + Statement::SwitchStatement(sw) => { + self.pre_scan_builtin_expr(&sw.discriminant, ctx); + for case in &sw.cases { + if let Some(test) = &case.test { + self.pre_scan_builtin_expr(test, ctx); + } + for s in &case.consequent { + self.pre_scan_builtin_stmt(s, ctx); + } + } + } + Statement::ThrowStatement(ts) => { + self.pre_scan_builtin_expr(&ts.argument, ctx); + } + Statement::TryStatement(ts) => { + for s in &ts.block.body { + self.pre_scan_builtin_stmt(s, ctx); + } + if let Some(handler) = &ts.handler { + if let Some(param) = &handler.param { + self.pre_scan_builtin_pattern(¶m.pattern, ctx); + } + for s in &handler.body.body { + self.pre_scan_builtin_stmt(s, ctx); + } + } + if let Some(finalizer) = &ts.finalizer { + for s in &finalizer.body { + self.pre_scan_builtin_stmt(s, ctx); + } + } + } + Statement::BlockStatement(bs) => { + for s in &bs.body { + self.pre_scan_builtin_stmt(s, ctx); + } + } + Statement::LabeledStatement(ls) => self.pre_scan_builtin_stmt(&ls.body, ctx), + Statement::WithStatement(ws) => { + self.pre_scan_builtin_expr(&ws.object, ctx); + self.pre_scan_builtin_stmt(&ws.body, ctx); + } + Statement::ClassDeclaration(cd) => { + if let Some(super_class) = &cd.super_class { + self.pre_scan_builtin_expr(super_class, ctx); + } + } + Statement::ExportNamedDeclaration(exp) => { + if let Some(Declaration::VariableDeclaration(vd)) = &exp.declaration { + for d in &vd.declarations { + self.pre_scan_builtin_pattern(&d.id, ctx); + if let Some(init) = &d.init { + self.pre_scan_builtin_expr(init, ctx); + } + } + } + } + Statement::ExportDefaultDeclaration(exp) => { + if let Some(e) = exp.declaration.as_expression() { + self.pre_scan_builtin_expr(e, ctx); + } + } + Statement::FunctionDeclaration(_) | Statement::BreakStatement(_) | Statement::ContinueStatement(_) => {} + _ => {} + } + } + + fn pre_scan_builtin_expr(&self, expr: &Expression, ctx: &mut CompileCtx) { + match expr { + Expression::Identifier(ident) => { + if CompileCtx::is_known_builtin(ident.name.as_str()) { + let _ = ctx.lookup_or_builtin(ident.name.as_str()); + } + } + Expression::BinaryExpression(bin) => { + self.pre_scan_builtin_expr(&bin.left, ctx); + self.pre_scan_builtin_expr(&bin.right, ctx); + } + Expression::UnaryExpression(un) => { + self.pre_scan_builtin_expr(&un.argument, ctx); + } + Expression::CallExpression(call) => { + self.pre_scan_builtin_expr(&call.callee, ctx); + for arg in &call.arguments { + self.pre_scan_builtin_arg(arg, ctx); + } + } + Expression::NewExpression(ne) => { + self.pre_scan_builtin_expr(&ne.callee, ctx); + for arg in &ne.arguments { + self.pre_scan_builtin_arg(arg, ctx); + } + } + Expression::LogicalExpression(log) => { + self.pre_scan_builtin_expr(&log.left, ctx); + self.pre_scan_builtin_expr(&log.right, ctx); + } + Expression::ConditionalExpression(cond) => { + self.pre_scan_builtin_expr(&cond.test, ctx); + self.pre_scan_builtin_expr(&cond.consequent, ctx); + self.pre_scan_builtin_expr(&cond.alternate, ctx); + } + Expression::PrivateInExpression(pin) => { + self.pre_scan_builtin_expr(&pin.right, ctx); + } + Expression::SequenceExpression(seq) => { + for e in &seq.expressions { + self.pre_scan_builtin_expr(e, ctx); + } + } + Expression::AssignmentExpression(assign) => { + if let Some(target) = assign.left.as_simple_assignment_target() { + self.pre_scan_builtin_target(target, ctx); + } + self.pre_scan_builtin_expr(&assign.right, ctx); + } + Expression::UpdateExpression(update) => { + self.pre_scan_builtin_target(&update.argument, ctx); + } + Expression::TemplateLiteral(tl) => { + for e in &tl.expressions { + self.pre_scan_builtin_expr(e, ctx); + } + } + Expression::TaggedTemplateExpression(tt) => { + self.pre_scan_builtin_expr(&tt.tag, ctx); + for e in &tt.quasi.expressions { + self.pre_scan_builtin_expr(e, ctx); + } + } + Expression::ObjectExpression(obj) => { + for prop in &obj.properties { + match prop { + oxide_parser::ObjectPropertyKind::ObjectProperty(p) => { + if p.computed { + self.pre_scan_builtin_expr(p.key.to_expression(), ctx); + } + self.pre_scan_builtin_expr(&p.value, ctx); + } + oxide_parser::ObjectPropertyKind::SpreadProperty(spread) => { + self.pre_scan_builtin_expr(&spread.argument, ctx); + } + } + } + } + Expression::ArrayExpression(arr) => { + for e in &arr.elements { + if let Some(e) = e.as_expression() { + self.pre_scan_builtin_expr(e, ctx); + } + } + } + Expression::PrivateFieldExpression(member) => { + self.pre_scan_builtin_expr(&member.object, ctx); + } + Expression::StaticMemberExpression(member) => { + self.pre_scan_builtin_expr(&member.object, ctx); + } + Expression::ComputedMemberExpression(member) => { + self.pre_scan_builtin_expr(&member.object, ctx); + self.pre_scan_builtin_expr(&member.expression, ctx); + } + Expression::ChainExpression(chain) => { + self.pre_scan_builtin_chain(&chain.expression, ctx); + } + Expression::ParenthesizedExpression(p) => self.pre_scan_builtin_expr(&p.expression, ctx), + Expression::YieldExpression(ye) => { + if let Some(a) = &ye.argument { + self.pre_scan_builtin_expr(a, ctx); + } + } + Expression::AwaitExpression(ae) => self.pre_scan_builtin_expr(&ae.argument, ctx), + Expression::ArrowFunctionExpression(_) + | Expression::FunctionExpression(_) + | Expression::ClassExpression(_) => {} + _ => {} + } + } + + fn pre_scan_builtin_target(&self, target: &oxide_parser::SimpleAssignmentTarget, ctx: &mut CompileCtx) { + match target { + oxide_parser::SimpleAssignmentTarget::AssignmentTargetIdentifier(id) => { + // 标识符目标与表达式位置标识符引用同口径预登记:目标为某内置名的 + // 唯一出现处(无读侧引用)时缺预登记会解析成隐式全局新槽,旧值读 + // 与短路判定拿到未预载值。 + if CompileCtx::is_known_builtin(id.name.as_str()) { + let _ = ctx.lookup_or_builtin(id.name.as_str()); + } + } + oxide_parser::SimpleAssignmentTarget::StaticMemberExpression(member) => { + self.pre_scan_builtin_expr(&member.object, ctx); + } + oxide_parser::SimpleAssignmentTarget::ComputedMemberExpression(member) => { + self.pre_scan_builtin_expr(&member.object, ctx); + self.pre_scan_builtin_expr(&member.expression, ctx); + } + oxide_parser::SimpleAssignmentTarget::PrivateFieldExpression(member) => { + self.pre_scan_builtin_expr(&member.object, ctx); + } + _ => {} + } + } + + fn pre_scan_builtin_chain(&self, element: &oxide_parser::ChainElement, ctx: &mut CompileCtx) { + match element { + oxide_parser::ChainElement::StaticMemberExpression(member) => { + self.pre_scan_builtin_expr(&member.object, ctx); + } + oxide_parser::ChainElement::ComputedMemberExpression(member) => { + self.pre_scan_builtin_expr(&member.object, ctx); + self.pre_scan_builtin_expr(&member.expression, ctx); + } + oxide_parser::ChainElement::PrivateFieldExpression(member) => { + self.pre_scan_builtin_expr(&member.object, ctx); + } + oxide_parser::ChainElement::CallExpression(call) => { + self.pre_scan_builtin_expr(&call.callee, ctx); + for arg in &call.arguments { + self.pre_scan_builtin_arg(arg, ctx); + } + } + _ => {} + } + } + + /// 遍历调用实参:spread 内部表达式也纳入 builtin 预扫描。 + fn pre_scan_builtin_arg(&self, arg: &oxide_parser::Argument, ctx: &mut CompileCtx) { + if let Some(e) = arg.as_expression() { + self.pre_scan_builtin_expr(e, ctx); + } else if let oxide_parser::Argument::SpreadElement(sp) = arg { + self.pre_scan_builtin_expr(&sp.argument, ctx); + } + } + + /// 遍历绑定 pattern 的计算键表达式(`{[k]: a}` 的键)里的 builtin 引用: + /// 模式键是运行时求值表达式,键内 builtin 标识符须预先登记固定槽位 + /// (与对象字面量计算键预扫描同口径)。 + fn pre_scan_builtin_pattern(&self, pattern: &BindingPattern, ctx: &mut CompileCtx) { + match pattern { + BindingPattern::BindingIdentifier(_) => {} + BindingPattern::ArrayPattern(ap) => { + for e in ap.elements.iter().flatten() { + self.pre_scan_builtin_pattern(e, ctx); + } + if let Some(rest) = &ap.rest { + self.pre_scan_builtin_pattern(&rest.argument, ctx); + } + } + BindingPattern::ObjectPattern(op) => { + for prop in &op.properties { + if prop.computed { + self.pre_scan_builtin_expr(prop.key.to_expression(), ctx); + } + self.pre_scan_builtin_pattern(&prop.value, ctx); + } + if let Some(rest) = &op.rest { + self.pre_scan_builtin_pattern(&rest.argument, ctx); + } + } + BindingPattern::AssignmentPattern(ap) => { + self.pre_scan_builtin_pattern(&ap.left, ctx); + } + } + } +} diff --git a/crates/oxide_emit/src/prepass/declare.rs b/crates/oxide_emit/src/prepass/declare.rs new file mode 100644 index 00000000..66698341 --- /dev/null +++ b/crates/oxide_emit/src/prepass/declare.rs @@ -0,0 +1,389 @@ +//! emit 前置 pass,声明预登记:函数/var 声明提升预声明、块级函数声明按 ES2015 +//! 块绑定预声明、let/const/class 建 TDZ 占位;顶层 lexical 声明撞受限全局名 +//! 在声明实例化期拒绝(global_lexical 门控,门控源居 emit_program 调用点)。 + +use super::check_restricted_global_lexical; +use crate::{CompileCtx, Emitter}; +use oxide_parser::{BindingPattern, Declaration, ExportDefaultDeclarationKind, Statement, VariableDeclarationKind}; + +impl Emitter { + pub(crate) fn predeclare_function_declarations(&self, statements: &[Statement], ctx: &mut CompileCtx) { + for statement in statements { + let function = match statement { + Statement::FunctionDeclaration(f) => f, + Statement::ExportNamedDeclaration(exp) => match &exp.declaration { + Some(Declaration::FunctionDeclaration(f)) => f, + _ => continue, + }, + // export default function foo(){}:foo 绑定由 lexical predeclare 以 + // Const 预声明(emit 侧 emit_bind_target(Const) 消费预登记槽)。 + _ => continue, + }; + let Some(identifier) = &function.id else { + continue; + }; + let reg = ctx.alloc_reg(); + let _ = ctx.declare_initialized(identifier.name.as_str(), reg, VariableDeclarationKind::Var, false); + } + } + + /// 预声明单个 `var` 名:仅顶层(全局作用域)的 builtin 名落 builtin 镜像槽 + /// (run 起点预载全局属性值),使 GDI 序言与声明点同步都用入口原值而非 + /// fresh undefined 槽,现存值(NaN 等)不被抹;函数体内 builtin 名仍是局部 + /// var 遮蔽(fresh 槽,不命中只读内置拦截);其余名 fresh var 槽。 + pub(crate) fn predeclare_var_name(&self, name: &str, ctx: &mut CompileCtx) { + if ctx.is_global_scope && CompileCtx::is_known_builtin(name) { + let _ = ctx.lookup_or_builtin(name); + } else { + let reg = ctx.alloc_reg(); + let _ = ctx.declare_initialized(name, reg, VariableDeclarationKind::Var, false); + } + } + + /// 预声明语句列表中的全部 `var` 绑定,使先发的提升函数声明能解析它们。 + /// 顶层 `var` 名在编译闭包捕获它的函数体时必须可见。 + pub(crate) fn predeclare_var_declarations(&self, statements: &[Statement], ctx: &mut CompileCtx) { + for statement in statements { + match statement { + Statement::VariableDeclaration(decl) => { + if !matches!(decl.kind, VariableDeclarationKind::Var) { + continue; + } + for d in &decl.declarations { + if let oxide_parser::BindingPattern::BindingIdentifier(bi) = &d.id { + self.predeclare_var_name(bi.name.as_str(), ctx); + } + } + } + Statement::BlockStatement(bs) => self.predeclare_var_declarations(&bs.body, ctx), + Statement::IfStatement(is) => { + self.predeclare_var_declarations(std::slice::from_ref(&is.consequent), ctx); + if let Some(alt) = &is.alternate { + self.predeclare_var_declarations(std::slice::from_ref(alt), ctx); + } + } + Statement::WhileStatement(wh) => { + self.predeclare_var_declarations(std::slice::from_ref(&wh.body), ctx); + } + Statement::DoWhileStatement(dw) => { + self.predeclare_var_declarations(std::slice::from_ref(&dw.body), ctx); + } + Statement::ForStatement(fs) => { + if let Some(oxide_parser::ForStatementInit::VariableDeclaration(decl)) = &fs.init { + if matches!(decl.kind, VariableDeclarationKind::Var) { + for d in &decl.declarations { + if let oxide_parser::BindingPattern::BindingIdentifier(bi) = &d.id { + self.predeclare_var_name(bi.name.as_str(), ctx); + } + } + } + } + self.predeclare_var_declarations(std::slice::from_ref(&fs.body), ctx); + } + Statement::ForInStatement(fi) => { + // var 头名提升到函数/全局作用域(与 For 臂同规则),先于提升 + // 函数声明发射预声明,使函数体按既有 var 绑定解析头名; + // let/const 头是迭代级绑定,不入提升面。 + if let oxide_parser::ForStatementLeft::VariableDeclaration(decl) = &fi.left { + if matches!(decl.kind, VariableDeclarationKind::Var) { + for d in &decl.declarations { + if let oxide_parser::BindingPattern::BindingIdentifier(bi) = &d.id { + self.predeclare_var_name(bi.name.as_str(), ctx); + } + } + } + } + self.predeclare_var_declarations(std::slice::from_ref(&fi.body), ctx); + } + Statement::ForOfStatement(fo) => { + if let oxide_parser::ForStatementLeft::VariableDeclaration(decl) = &fo.left { + if matches!(decl.kind, VariableDeclarationKind::Var) { + for d in &decl.declarations { + if let oxide_parser::BindingPattern::BindingIdentifier(bi) = &d.id { + self.predeclare_var_name(bi.name.as_str(), ctx); + } + } + } + } + self.predeclare_var_declarations(std::slice::from_ref(&fo.body), ctx); + } + Statement::SwitchStatement(sw) => { + for case in &sw.cases { + self.predeclare_var_declarations(&case.consequent, ctx); + } + } + Statement::TryStatement(ts) => { + self.predeclare_var_declarations(&ts.block.body, ctx); + if let Some(handler) = &ts.handler { + self.predeclare_var_declarations(&handler.body.body, ctx); + } + if let Some(finalizer) = &ts.finalizer { + self.predeclare_var_declarations(&finalizer.body, ctx); + } + } + Statement::LabeledStatement(ls) => { + self.predeclare_var_declarations(std::slice::from_ref(&ls.body), ctx); + } + Statement::WithStatement(ws) => { + self.predeclare_var_declarations(std::slice::from_ref(&ws.body), ctx); + } + Statement::ExportNamedDeclaration(exp) => { + if let Some(Declaration::VariableDeclaration(decl)) = &exp.declaration { + if !matches!(decl.kind, VariableDeclarationKind::Var) { + continue; + } + for d in &decl.declarations { + if let oxide_parser::BindingPattern::BindingIdentifier(bi) = &d.id { + self.predeclare_var_name(bi.name.as_str(), ctx); + } + } + } + } + _ => {} + } + } + } + + /// 预声明当前块直接子树中的函数声明(ES2015 块级绑定,kind=Let 落当前块), + /// 使块内声明点之前的引用在编译期可见。递归进入嵌套块时压/弹作用域, + /// 与 emit 阶段嵌套块 push_scope 的时机对齐。 + /// + /// # 边界与前提 + /// - 只处理块内函数声明;switch 不推 scope(其 case 内函数声明随 switch + /// 作用域修复一并处理);export 声明不可能出现在块内。 + /// - 与 lexical 预声明的顺序:本函数在前,`{ let g; function g(){} }` 时 + /// lexical 的 `declare_predeclared` 命中已存在的函数绑定自然报重复声明错, + /// 避免函数预声明被 lexical 占位静默覆盖而破坏 let 的 TDZ。 + /// - var 与函数同名(`{ var g; function g(){} }`):var 落函数作用域、 + /// 函数落当前块,不同 scope 互不冲突。 + pub(crate) fn predeclare_block_function_declarations(&self, statements: &[Statement], ctx: &mut CompileCtx) { + for statement in statements { + match statement { + Statement::FunctionDeclaration(f) => { + let Some(identifier) = &f.id else { + continue; + }; + let reg = ctx.alloc_reg(); + let _ = ctx.declare_initialized(identifier.name.as_str(), reg, VariableDeclarationKind::Let, false); + } + Statement::BlockStatement(bs) => { + ctx.push_scope(); + self.predeclare_block_function_declarations(&bs.body, ctx); + ctx.pop_scope(); + } + Statement::IfStatement(is) => { + self.predeclare_block_function_declarations(std::slice::from_ref(&is.consequent), ctx); + if let Some(alt) = &is.alternate { + self.predeclare_block_function_declarations(std::slice::from_ref(alt), ctx); + } + } + Statement::WhileStatement(wh) => { + self.predeclare_block_function_declarations(std::slice::from_ref(&wh.body), ctx); + } + Statement::DoWhileStatement(dw) => { + self.predeclare_block_function_declarations(std::slice::from_ref(&dw.body), ctx); + } + Statement::ForStatement(fs) => { + // 循环推独立作用域(头声明所在),函数声明落该作用域与 emit 对齐。 + ctx.push_scope(); + self.predeclare_block_function_declarations(std::slice::from_ref(&fs.body), ctx); + ctx.pop_scope(); + } + Statement::ForInStatement(fi) => { + ctx.push_scope(); + self.predeclare_block_function_declarations(std::slice::from_ref(&fi.body), ctx); + ctx.pop_scope(); + } + Statement::ForOfStatement(fo) => { + ctx.push_scope(); + self.predeclare_block_function_declarations(std::slice::from_ref(&fo.body), ctx); + ctx.pop_scope(); + } + Statement::TryStatement(ts) => { + ctx.push_scope(); + self.predeclare_block_function_declarations(&ts.block.body, ctx); + ctx.pop_scope(); + if let Some(handler) = &ts.handler { + ctx.push_scope(); + self.predeclare_block_function_declarations(&handler.body.body, ctx); + ctx.pop_scope(); + } + if let Some(finalizer) = &ts.finalizer { + ctx.push_scope(); + self.predeclare_block_function_declarations(&finalizer.body, ctx); + ctx.pop_scope(); + } + } + Statement::LabeledStatement(ls) => { + self.predeclare_block_function_declarations(std::slice::from_ref(&ls.body), ctx); + } + Statement::WithStatement(ws) => { + self.predeclare_block_function_declarations(std::slice::from_ref(&ws.body), ctx); + } + _ => {} + } + } + } + + /// 预声明当前作用域直接子语句中的 `let`/`const`/`class` 绑定(未初始化, + /// 建立 TDZ 占位)。使声明点之前的读取在编译期可分辨为 TDZ 而非隐式全局, + /// 声明点复用预登记槽位。 + /// + /// # 边界与前提 + /// - 只扫描直接子语句 + 递归 switch case(switch 不推 scope,case 内 lexical + /// 声明属于外层作用域);不递归块/if/for/while body(嵌套块自预声明; + /// 单语句 body 不接受 lexical 声明——lexical 属 Declaration、非 Statement + /// 子产生式,parser 按语法错误直接拒绝,这些形状不会进入 emit)。 + /// - 跳过 for 头声明(循环作用域由 for 分支内联 declare)。 + /// - `global_lexical` 为 true 时(仅脚本顶层调用点传 `!is_eval_script`): + /// lexical 声明撞受限全局名报 SyntaxError(脚本声明实例化对全局对象受限 + /// 自有属性名做检查,eval 代码声明实例化无此检查);函数体/块/try/模块 + /// 调用点传 false,lexical 声明是局部绑定不查。 + pub(crate) fn predeclare_lexical_declarations( + &self, statements: &[Statement], ctx: &mut CompileCtx, global_lexical: bool, + ) -> Result<(), String> { + for statement in statements { + match statement { + Statement::VariableDeclaration(decl) => { + if matches!(decl.kind, VariableDeclarationKind::Var) { + continue; + } + let is_const = matches!(decl.kind, VariableDeclarationKind::Const); + for d in &decl.declarations { + self.predeclare_lexical_pattern(&d.id, is_const, ctx, global_lexical)?; + } + } + Statement::ClassDeclaration(cd) => { + if let Some(id) = &cd.id { + check_restricted_global_lexical(id.name.as_str(), global_lexical)?; + let reg = ctx.alloc_reg(); + let _ = ctx.declare_predeclared(id.name.as_str(), reg, VariableDeclarationKind::Const, true); + } + } + Statement::SwitchStatement(sw) => { + for case in &sw.cases { + for s in &case.consequent { + self.predeclare_lexical_stmt(s, ctx, global_lexical)?; + } + } + } + Statement::ExportNamedDeclaration(exp) => { + if let Some(decl) = &exp.declaration { + match decl { + Declaration::VariableDeclaration(vd) => { + if matches!(vd.kind, VariableDeclarationKind::Var) { + continue; + } + let is_const = matches!(vd.kind, VariableDeclarationKind::Const); + for d in &vd.declarations { + self.predeclare_lexical_pattern(&d.id, is_const, ctx, global_lexical)?; + } + } + Declaration::ClassDeclaration(cd) => { + if let Some(id) = &cd.id { + check_restricted_global_lexical(id.name.as_str(), global_lexical)?; + let reg = ctx.alloc_reg(); + let _ = ctx.declare_predeclared( + id.name.as_str(), + reg, + VariableDeclarationKind::Const, + true, + ); + } + } + _ => {} + } + } + } + Statement::ExportDefaultDeclaration(exp) => match &exp.declaration { + ExportDefaultDeclarationKind::ClassDeclaration(cd) => { + if let Some(id) = &cd.id { + check_restricted_global_lexical(id.name.as_str(), global_lexical)?; + let reg = ctx.alloc_reg(); + let _ = + ctx.declare_predeclared(id.name.as_str(), reg, VariableDeclarationKind::Const, true); + } + } + ExportDefaultDeclarationKind::FunctionDeclaration(fd) => { + if let Some(id) = &fd.id { + let reg = ctx.alloc_reg(); + let _ = + ctx.declare_predeclared(id.name.as_str(), reg, VariableDeclarationKind::Const, true); + } + } + _ => {} + }, + _ => {} + } + } + Ok(()) + } + + /// 预声明单个语句中的 lexical 声明(供 switch case 递归;`let`/`const`/`class` 分支)。 + fn predeclare_lexical_stmt( + &self, stmt: &Statement, ctx: &mut CompileCtx, global_lexical: bool, + ) -> Result<(), String> { + match stmt { + Statement::VariableDeclaration(decl) => { + if matches!(decl.kind, VariableDeclarationKind::Var) { + return Ok(()); + } + let is_const = matches!(decl.kind, VariableDeclarationKind::Const); + for d in &decl.declarations { + self.predeclare_lexical_pattern(&d.id, is_const, ctx, global_lexical)?; + } + } + Statement::ClassDeclaration(cd) => { + if let Some(id) = &cd.id { + check_restricted_global_lexical(id.name.as_str(), global_lexical)?; + let reg = ctx.alloc_reg(); + let _ = ctx.declare_predeclared(id.name.as_str(), reg, VariableDeclarationKind::Const, true); + } + } + _ => {} + } + Ok(()) + } + + /// 递归预声明绑定 pattern 内的全部标识符(含数组/对象/默认值解构)。 + fn predeclare_lexical_pattern( + &self, pattern: &BindingPattern, is_const: bool, ctx: &mut CompileCtx, global_lexical: bool, + ) -> Result<(), String> { + match pattern { + BindingPattern::BindingIdentifier(bi) => { + check_restricted_global_lexical(bi.name.as_str(), global_lexical)?; + let reg = ctx.alloc_reg(); + let _ = ctx.declare_predeclared( + bi.name.as_str(), + reg, + if is_const { + VariableDeclarationKind::Const + } else { + VariableDeclarationKind::Let + }, + is_const, + ); + } + BindingPattern::ArrayPattern(ap) => { + for e in ap.elements.iter().flatten() { + self.predeclare_lexical_pattern(e, is_const, ctx, global_lexical)?; + } + if let Some(rest) = &ap.rest { + self.predeclare_lexical_pattern(&rest.argument, is_const, ctx, global_lexical)?; + } + } + BindingPattern::ObjectPattern(op) => { + for prop in &op.properties { + self.predeclare_lexical_pattern(&prop.value, is_const, ctx, global_lexical)?; + } + if let Some(rest) = &op.rest { + self.predeclare_lexical_pattern(&rest.argument, is_const, ctx, global_lexical)?; + } + } + BindingPattern::AssignmentPattern(ap) => { + self.predeclare_lexical_pattern(&ap.left, is_const, ctx, global_lexical)?; + } + } + Ok(()) + } +} diff --git a/crates/oxide_emit/src/prepass/mod.rs b/crates/oxide_emit/src/prepass/mod.rs new file mode 100644 index 00000000..1d4e0559 --- /dev/null +++ b/crates/oxide_emit/src/prepass/mod.rs @@ -0,0 +1,26 @@ +//! emit 前置 pass:builtin 引用预扫描 + 声明预登记。 +//! +//! 在生成临时寄存器前遍历 AST,把内置全局标识符预先登记到固定寄存器槽 +//! (builtin_reg_map),避免与临时寄存器池冲突;同时预声明函数/var 声明, +//! 支持提升语义。 + +mod block_fn; +mod builtin_scan; +mod declare; + +/// 脚本顶层 lexical 声明(let/const/class)禁止使用的受限全局名:3 名静态集。 +/// 受限判定走规范自有属性臂:全局对象上 {configurable:false} 自有属性名(声明 +/// 实例化无法建立遮蔽绑定)——现行规范下恰为三常量;eval 与各 builtin 属性皆 +/// 可配置(合法遮蔽),不在此列。名基静态集(编译期不可查运行时描述符)。与 +/// BUILTIN_GLOBALS 语义不同(后者是 put 写拦截/双写名单),不互相派生,交叠 +/// 名由漂移守卫单测断言恒同步。 +pub(crate) const RESTRICTED_GLOBAL_LEXICAL_NAMES: &[&str] = &["undefined", "NaN", "Infinity"]; + +/// 脚本顶层 lexical 声明撞受限全局名 → SyntaxError(声明实例化期拒绝,整程序 +/// 编译失败)。错误消息与既有重复声明错同形;非顶层或名不在受限集 → Ok。 +fn check_restricted_global_lexical(name: &str, global_lexical: bool) -> Result<(), String> { + if global_lexical && RESTRICTED_GLOBAL_LEXICAL_NAMES.contains(&name) { + return Err(format!("Identifier '{name}' has already been declared")); + } + Ok(()) +}