feat: 新增 for-var 语法支持并修复变量声明语句计数问题
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
use oxide_parser::{Expression, Statement};
|
use oxide_parser::{Expression, ForStatementInit, Statement};
|
||||||
|
|
||||||
use crate::compiler::{is_side_effect_free, CompileCtx, Compiler, Label};
|
use crate::compiler::{is_side_effect_free, CompileCtx, Compiler, Label};
|
||||||
|
|
||||||
@@ -13,8 +13,10 @@ impl Compiler {
|
|||||||
ctx.alloc_reg();
|
ctx.alloc_reg();
|
||||||
if let Some(init) = &d.init {
|
if let Some(init) = &d.init {
|
||||||
self.count_expression(init, ctx);
|
self.count_expression(init, ctx);
|
||||||
|
ctx.projected_pc += 1; // STORE_VAR
|
||||||
|
} else {
|
||||||
|
ctx.projected_pc += 2; // LOAD_CONST(undefined) + STORE_VAR
|
||||||
}
|
}
|
||||||
ctx.projected_pc += 1; // STORE_VAR
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Statement::ReturnStatement(ret) => {
|
Statement::ReturnStatement(ret) => {
|
||||||
@@ -64,6 +66,16 @@ impl Compiler {
|
|||||||
if let Some(init) = &fr.init {
|
if let Some(init) = &fr.init {
|
||||||
if let Some(expr) = init.as_expression() {
|
if let Some(expr) = init.as_expression() {
|
||||||
self.count_expression(expr, ctx);
|
self.count_expression(expr, ctx);
|
||||||
|
} else if let ForStatementInit::VariableDeclaration(decl) = init {
|
||||||
|
for d in &decl.declarations {
|
||||||
|
ctx.alloc_reg();
|
||||||
|
if let Some(init_expr) = &d.init {
|
||||||
|
self.count_expression(init_expr, ctx);
|
||||||
|
ctx.projected_pc += 1; // STORE_VAR
|
||||||
|
} else {
|
||||||
|
ctx.projected_pc += 2; // LOAD_CONST(undefined) + STORE_VAR
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ctx.label_map.insert(start_label, ctx.projected_pc);
|
ctx.label_map.insert(start_label, ctx.projected_pc);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use crate::compiler::Label;
|
use crate::compiler::Label;
|
||||||
use crate::opcode::{self, OpCode};
|
use crate::opcode::{self, OpCode};
|
||||||
use oxide_parser::{AssignmentOperator, Expression, Statement, UnaryOperator};
|
use oxide_parser::{AssignmentOperator, Expression, ForStatementInit, Statement, UnaryOperator};
|
||||||
|
|
||||||
use crate::compiler::{is_int_literal, is_side_effect_free, BinaryOperator, CompileCtx, Compiler};
|
use crate::compiler::{is_int_literal, is_side_effect_free, BinaryOperator, CompileCtx, Compiler};
|
||||||
use crate::module::Constant;
|
use crate::module::Constant;
|
||||||
@@ -150,10 +150,22 @@ impl Compiler {
|
|||||||
if let Some(init) = &fr.init {
|
if let Some(init) = &fr.init {
|
||||||
if let Some(expr) = init.as_expression() {
|
if let Some(expr) = init.as_expression() {
|
||||||
self.emit_expression(expr, ctx)?;
|
self.emit_expression(expr, ctx)?;
|
||||||
} else if init.is_var_declaration() {
|
} else if let ForStatementInit::VariableDeclaration(decl) = init {
|
||||||
return Err(
|
for d in &decl.declarations {
|
||||||
"for-loop `let` init not yet supported; use expression init".into()
|
let name = match &d.id {
|
||||||
);
|
oxide_parser::BindingPattern::BindingIdentifier(bi) => {
|
||||||
|
bi.name.as_str()
|
||||||
|
}
|
||||||
|
_ => return Err("destructuring not supported".into()),
|
||||||
|
};
|
||||||
|
let var_reg = ctx.alloc_reg();
|
||||||
|
ctx.declare(name, var_reg)?;
|
||||||
|
if let Some(init_expr) = &d.init {
|
||||||
|
let val_reg = self.emit_expression(init_expr, ctx)?;
|
||||||
|
ctx.emit(opcode::encode(OpCode::STORE_VAR, var_reg, val_reg, 0));
|
||||||
|
ctx.init_var(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use oxide_parser::{Expression, Statement};
|
use oxide_parser::{Expression, ForStatementInit, Statement};
|
||||||
|
|
||||||
pub fn structural_hash(program: &oxide_parser::Program) -> u64 {
|
pub fn structural_hash(program: &oxide_parser::Program) -> u64 {
|
||||||
use std::hash::Hasher;
|
use std::hash::Hasher;
|
||||||
@@ -53,8 +53,13 @@ fn hash_statement(stmt: &Statement, h: &mut rustc_hash::FxHasher) {
|
|||||||
if let Some(init) = &fr.init {
|
if let Some(init) = &fr.init {
|
||||||
if let Some(expr) = init.as_expression() {
|
if let Some(expr) = init.as_expression() {
|
||||||
hash_expression(expr, h);
|
hash_expression(expr, h);
|
||||||
} else if init.is_var_declaration() {
|
} else if let ForStatementInit::VariableDeclaration(decl) = init {
|
||||||
0u8.hash(h);
|
(decl.declarations.len() as u32).hash(h);
|
||||||
|
for d in &decl.declarations {
|
||||||
|
if let Some(init_expr) = &d.init {
|
||||||
|
hash_expression(init_expr, h);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(test) = &fr.test {
|
if let Some(test) = &fr.test {
|
||||||
|
|||||||
Reference in New Issue
Block a user