diff --git a/src/ast/parser.rs b/src/ast/parser.rs index 2f759a6..cbae469 100644 --- a/src/ast/parser.rs +++ b/src/ast/parser.rs @@ -779,7 +779,7 @@ fn unescape_string(s: &str) -> String { } } Some(c) => result.push_str(&format!("\\{c}")), // 未知转义字符,保留原始形式 - None => result.push('\\'), // 单独的反斜杠,保留原始形式 + None => result.push('\\'), // 单独的反斜杠,保留原始形式 } } else { result.push(c); diff --git a/src/bytecode.rs b/src/bytecode.rs index 9dde5b9..ab772a7 100644 --- a/src/bytecode.rs +++ b/src/bytecode.rs @@ -26,7 +26,6 @@ impl Module { } } - #[derive(Debug, Clone)] pub struct Bytecode { pub opcode: Opcode, diff --git a/src/compiler/codegen/codegen.rs b/src/compiler/codegen/codegen.rs index 6926a5e..d2da222 100644 --- a/src/compiler/codegen/codegen.rs +++ b/src/compiler/codegen/codegen.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; -use log::debug; +use log::{debug, trace}; use petgraph::visit::DfsPostOrder; use crate::{ @@ -17,6 +17,7 @@ pub struct Codegen { reg_alloc: RegAlloc, codes: Vec, block_map: HashMap, + inst_index: usize, } impl Codegen { @@ -25,10 +26,11 @@ impl Codegen { reg_alloc: RegAlloc::new(registers), codes: Vec::new(), block_map: HashMap::new(), + inst_index: 0, } } - pub fn generate_code(&mut self, cfg: ControlFlowGraph, is_func: bool) -> &[Bytecode] { + pub fn generate_code(&mut self, cfg: ControlFlowGraph) -> &[Bytecode] { let mut cfg = cfg; Self::resort_blocks(&mut cfg); @@ -46,22 +48,8 @@ impl Codegen { self.reg_alloc.arrange(&cfg); - let mut index = 0; - let mut patchs: Vec = Vec::new(); - if is_func { - self.codes.push(Bytecode::single( - Opcode::PushC, - Operand::new_register(Register::RBP), - )); - self.codes.push(Bytecode::double( - Opcode::MovC, - Operand::new_register(Register::RBP), - Operand::new_register(Register::RSP), - )); - } - // alloc stack frame, need rewrite with actual stack size // rsp = rsp + stack_size let pos = self.codes.len(); @@ -82,20 +70,22 @@ impl Codegen { for inst in &block.instructions { // preload - for action in self.reg_alloc.pre_allocate(index) { - match action { - Action::Restore { stack, register } => { - self.codes.push(Bytecode::double( - Opcode::Mov, - register.into(), - Operand::Stack(stack as isize), - )); - } - _ => unreachable!(), - } - } - - debug!("inst: {inst:?}"); + // if !inst.is_call() { + // for action in self.reg_alloc.pre_allocate(index) { + // match action { + // Action::UnSpill { stack, register } => { + // self.codes.push(Bytecode::double( + // Opcode::Mov, + // register.into(), + // Operand::Stack(stack as isize), + // )); + // } + // _ => unreachable!(), + // } + // } + // } + + debug!("inst[{}]: {inst:?}", self.inst_index); debug!("register: {}", self.reg_alloc.reg_set); match inst.clone() { @@ -298,20 +288,6 @@ impl Codegen { )); } - if is_func { - // restore prev stack frame - // mov rbp to rsp - // pop rbp - self.codes.push(Bytecode::double( - Opcode::MovC, - Operand::new_register(Register::RSP), - Operand::new_register(Register::RBP), - )); - - self.codes - .push(Bytecode::single(Opcode::PopC, Register::RBP.into())); - } - self.codes.push(Bytecode::empty(Opcode::Ret)); } Instruction::Br { dst } => { @@ -364,21 +340,38 @@ impl Codegen { } } - // spill - for action in self.reg_alloc.post_allocate(index) { - match action { - Action::Spill { stack, register } => { + let (defined, used) = inst.defined_and_used_vars(); + for var in defined { + if matches!(var, Value::Variable(_)) { + if let Some(Action::Spill { stack, register }) = + self.reg_alloc.release(var, self.inst_index) + { + trace!("spilling({var}) {register} -> [rbp+{stack}]"); + self.codes.push(Bytecode::double( + Opcode::Mov, + Operand::Stack(stack as isize), + register.into(), + )); + } + } + } + + for var in used { + if matches!(var, Value::Variable(_)) { + if let Some(Action::Spill { stack, register }) = + self.reg_alloc.release(var, self.inst_index) + { + trace!("spilling({var}) {register} -> [rbp+{stack}]"); self.codes.push(Bytecode::double( Opcode::Mov, Operand::Stack(stack as isize), register.into(), )); } - _ => unreachable!(), } } - index += 1; + self.inst_index += 1; } } @@ -400,16 +393,32 @@ impl Codegen { } // 2. push arguments - for arg in args.iter().rev() { - let arg = self.gen_operand(*arg); - - self.codes.push(Bytecode::single(Opcode::Push, arg)); - } + self.store_args(args, self.inst_index); // 3. call function + self.codes.push(Bytecode::single( + Opcode::PushC, + Operand::new_register(Register::RBP), + )); + self.codes.push(Bytecode::double( + Opcode::MovC, + Operand::new_register(Register::RBP), + Operand::new_register(Register::RSP), + )); + + // call self.codes .push(Bytecode::single(Opcode::Call, func.to_operand())); + self.codes.push(Bytecode::double( + Opcode::MovC, + Operand::new_register(Register::RSP), + Operand::new_register(Register::RBP), + )); + + self.codes + .push(Bytecode::single(Opcode::PopC, Register::RBP.into())); + // 4. pop arguments self.codes.push(Bytecode::triple( Opcode::SubC, @@ -433,6 +442,8 @@ impl Codegen { } fn gen_call_ex(&mut self, func: Value, args: &[Value], result: Value) { + let callable = self.gen_operand(func); + // 1. backup registers let in_use_registers = self.reg_alloc.in_use_registers(); for reg in in_use_registers.iter().copied() { @@ -440,17 +451,31 @@ impl Codegen { } // 2. push arguments - for arg in args.iter().rev() { - let arg = self.gen_operand(*arg); - - self.codes.push(Bytecode::single(Opcode::Push, arg)); - } + self.store_args(args, self.inst_index); // 3. call function + self.codes.push(Bytecode::single( + Opcode::PushC, + Operand::new_register(Register::RBP), + )); + self.codes.push(Bytecode::double( + Opcode::MovC, + Operand::new_register(Register::RBP), + Operand::new_register(Register::RSP), + )); - let callable = self.gen_operand(func); + // call_ex self.codes.push(Bytecode::single(Opcode::CallEx, callable)); + self.codes.push(Bytecode::double( + Opcode::MovC, + Operand::new_register(Register::RSP), + Operand::new_register(Register::RBP), + )); + + self.codes + .push(Bytecode::single(Opcode::PopC, Register::RBP.into())); + // 4. pop arguments self.codes.push(Bytecode::triple( Opcode::SubC, @@ -473,13 +498,12 @@ impl Codegen { } fn gen_call_native(&mut self, func: Value, args: &[Value], result: Value) { + let callable = self.gen_operand(func); + // 1. push arguments - for arg in args.iter().rev() { - let arg = self.gen_operand(*arg); - self.codes.push(Bytecode::single(Opcode::Push, arg)); - } + self.store_args(args, self.inst_index); - // 2. new stack frame + // 3. call function self.codes.push(Bytecode::single( Opcode::PushC, Operand::new_register(Register::RBP), @@ -490,20 +514,22 @@ impl Codegen { Operand::new_register(Register::RSP), )); - // 3. call function - let callable = self.gen_operand(func); + // call_native self.codes.push(Bytecode::double( Opcode::CallNative, callable, Operand::new_immd(args.len() as isize), )); - // 4. restore stack frame - self.codes.push(Bytecode::single( - Opcode::PopC, + self.codes.push(Bytecode::double( + Opcode::MovC, + Operand::new_register(Register::RSP), Operand::new_register(Register::RBP), )); + self.codes + .push(Bytecode::single(Opcode::PopC, Register::RBP.into())); + // 4. pop arguments self.codes.push(Bytecode::triple( Opcode::SubC, @@ -522,13 +548,12 @@ impl Codegen { } fn gen_prop_call(&mut self, object: Value, property: Value, args: &[Value], result: Value) { + let callable = self.gen_operand(object); + // 1. push arguments - for arg in args.iter().rev() { - let arg = self.gen_operand(*arg); - self.codes.push(Bytecode::single(Opcode::Push, arg)); - } + self.store_args(args, self.inst_index); - // 2. new stack frame + // 3. call function self.codes.push(Bytecode::single( Opcode::PushC, Operand::new_register(Register::RBP), @@ -539,9 +564,8 @@ impl Codegen { Operand::new_register(Register::RSP), )); - // 3. call function - let callable = self.gen_operand(object); let prop = self.gen_operand(property); + // prop_call self.codes.push(Bytecode::triple( Opcode::PropCall, callable, @@ -549,12 +573,15 @@ impl Codegen { Operand::new_immd(args.len() as isize), )); - // 4. restore stack frame - self.codes.push(Bytecode::single( - Opcode::PopC, + self.codes.push(Bytecode::double( + Opcode::MovC, + Operand::new_register(Register::RSP), Operand::new_register(Register::RBP), )); + self.codes + .push(Bytecode::single(Opcode::PopC, Register::RBP.into())); + // 4. pop arguments self.codes.push(Bytecode::triple( Opcode::SubC, @@ -572,6 +599,26 @@ impl Codegen { )); } + fn store_args(&mut self, args: &[Value], index: usize) { + for arg in args.iter().rev() { + let op = self.gen_operand(*arg); + self.codes.push(Bytecode::single(Opcode::Push, op)); + if let Some(action) = self.reg_alloc.release(*arg, index) { + match action { + Action::Spill { stack, register } => { + trace!("spilling({arg}) {register} -> [rbp+{stack}]"); + self.codes.push(Bytecode::double( + Opcode::Mov, + Operand::Stack(stack as isize), + register.into(), + )); + } + _ => unreachable!("action must be spill"), + } + } + } + } + fn gen_operand(&mut self, value: Value) -> Operand { match value { Value::Primitive(v) => Operand::new_primitive(v), @@ -579,7 +626,17 @@ impl Codegen { Value::Function(id) => Operand::new_symbol(id.as_usize() as u32), Value::Block(id) => Operand::new_immd(id.as_usize() as isize), Value::Variable(_) => { - let register = self.reg_alloc.alloc(value); + let (register, unspill) = self.reg_alloc.alloc(value, self.inst_index); + + if let Some(Action::Restore { stack, register }) = unspill { + trace!("unspilling({value}) [rbp+{stack}] -> {register}"); + self.codes.push(Bytecode::double( + Opcode::Mov, + register.into(), + Operand::Stack(stack as isize), + )); + } + Operand::new_register(register) } } @@ -684,7 +741,7 @@ mod tests { let mut codegen = Codegen::new(&Register::small_general()); - let bytecodes = codegen.generate_code(cfg, false); + let bytecodes = codegen.generate_code(cfg); for bytecode in bytecodes { println!("{bytecode};"); @@ -727,7 +784,7 @@ mod tests { let mut codegen = Codegen::new(&Register::small_general()); - let bytecodes = codegen.generate_code(cfg, false); + let bytecodes = codegen.generate_code(cfg); for bytecode in bytecodes { println!("{bytecode};"); @@ -828,7 +885,7 @@ mod tests { }); let mut codegen = Codegen::new(&Register::small_general()); - let bytecodes = codegen.generate_code(cfg, false); + let bytecodes = codegen.generate_code(cfg); for bytecode in bytecodes { println!("{bytecode};"); diff --git a/src/compiler/codegen/regalloc.rs b/src/compiler/codegen/regalloc.rs index 09bdc30..439655c 100644 --- a/src/compiler/codegen/regalloc.rs +++ b/src/compiler/codegen/regalloc.rs @@ -376,57 +376,58 @@ impl RegAlloc { self.liveness.stack_size() } - pub fn pre_allocate(&mut self, index: usize) -> Vec { - let mut actions = Vec::new(); + pub fn alloc(&mut self, value: Value, index: usize) -> (Register, Option) { + trace!("allocating {}", value); - let need_preload = self - .liveness - .intervals - .values() - .filter(|interval| interval.ranges.iter().any(|range| range.start == index)); + let interval = self.liveness.intervals.get(&value).unwrap(); - for interval in need_preload { - trace!("preloading {}", interval.var); - match interval.reg { + match self.reg_set.find(value) { + Some(register) => (register, None), + None => match interval.reg { Some(register) => { - self.reg_set.use_register(register, interval.var, true); + self.reg_set.use_register(register, value, true); + (register, None) } None => { - let register = self.reg_set.must_alloc(interval.var); - let stack = interval.stack.unwrap(); + let reg = self.reg_set.must_alloc(value); + + if interval + .ranges + .iter() + .any(|range| range.start == index && interval.start != index) + { + let spill = Action::Restore { + stack: interval.stack.unwrap(), + register: reg, + }; + + return (reg, Some(spill)); + } - actions.push(Action::Restore { stack, register }); + (reg, None) } - } + }, } - - actions } - pub fn post_allocate(&mut self, index: usize) -> Vec { - let need_spill = self.liveness.intervals.values().filter(|interval| { - interval.reg.is_none() && interval.ranges.iter().any(|range| range.end == index) - }); - - let mut actions = Vec::new(); + pub fn release(&mut self, value: Value, index: usize) -> Option { + trace!("releasing {}", value); - for interval in need_spill { - trace!("spilling {}", interval.var); - - let register = self.reg_set.must_release(interval.var); - let stack = interval.stack.unwrap(); - - actions.push(Action::Spill { stack, register }); + if !matches!(value, Value::Variable(_)) { + return None; } - actions - } + let interval = self.liveness.intervals.get(&value).unwrap(); + if interval.ranges.iter().any(|range| range.end == index) { + if let Some(stack) = interval.stack { + if let Some(register) = self.reg_set.release(value) { + let spill = Action::Spill { register, stack }; + return Some(spill); + } + } + } - pub fn alloc(&mut self, value: Value) -> Register { - // 由于所有的变量都在预处理时加载到寄存器,所以,可以直接拿到 - self.reg_set - .find(value) - .unwrap_or_else(|| panic!("Can't find register for value({value})")) + None } pub fn arrange(&mut self, cfg: &ControlFlowGraph) { @@ -464,10 +465,6 @@ impl RegAlloc { } } - for (i, group) in groups.iter().enumerate() { - trace!("Group[{i}]: {group:?}"); - } - // 2. 分配寄存器 // 2.1 如果组数量不多于可用寄存器数量,则直接分配 if groups.len() <= registers.len() { @@ -482,27 +479,33 @@ impl RegAlloc { // 2.2 保留3个临时寄存器,其他的进行优先级分配 let (_temp_regs, fixed_regs) = registers.split_at(3); - // 计算每个组的优先级(基于区间长度) - let mut groups_with_priority: Vec<(usize, Vec)> = - groups.into_iter().enumerate().collect(); + // 排序 + groups.sort_by(|a, b| { + // let a_len: usize = a.iter().map(|interval| interval.end - interval.start).sum(); + // let b_len: usize = b.iter().map(|interval| interval.end - interval.start).sum(); + // b_len.cmp(&a_len) - // 按优先级排序(区间长度降序) - groups_with_priority.sort_by(|(_, a), (_, b)| { - let a_len: usize = a.iter().map(|interval| interval.end - interval.start).sum(); - let b_len: usize = b.iter().map(|interval| interval.end - interval.start).sum(); + let a_len: usize = a.iter().map(|interval| interval.ranges.len()).sum(); + let b_len: usize = b.iter().map(|interval| interval.ranges.len()).sum(); b_len.cmp(&a_len) }); + for (i, group) in groups.iter().enumerate() { + trace!("Group[{i}]: {group:?}"); + // let vars = group.iter().map(|interval| interval.var).collect::>(); + // trace!("Group[{i}]: {vars:?}"); + } + // 2.2.1 分配固定寄存器 - let (fixed_group, temp_group) = groups_with_priority.split_at(fixed_regs.len()); - for ((_, group), reg) in fixed_group.iter().zip(fixed_regs) { + let (fixed_group, temp_group) = groups.split_at(fixed_regs.len()); + for (group, reg) in fixed_group.iter().zip(fixed_regs) { for interval in group { self.liveness.set_register(interval.var, *reg); } } // 2.2.2 分配临时寄存器,只分配栈上空间,不分配寄存器 - for (i, (_, group)) in temp_group.iter().enumerate() { + for (i, group) in temp_group.iter().enumerate() { for interval in group { self.liveness.set_stack(interval.var, i); } @@ -545,14 +548,18 @@ impl RegisterSet { reg.register } - fn must_release(&mut self, value: Value) -> Register { - let reg = self + fn release(&mut self, value: Value) -> Option { + match self .registers .iter_mut() .find(|reg| reg.variable == Some(value)) - .unwrap(); - reg.variable = None; - reg.register + { + Some(reg) => { + reg.variable = None; + Some(reg.register) + } + None => None, + } } fn use_register(&mut self, register: Register, variable: Value, is_fixed: bool) { diff --git a/src/compiler/compiler.rs b/src/compiler/compiler.rs index 99a28db..73fcbdb 100644 --- a/src/compiler/compiler.rs +++ b/src/compiler/compiler.rs @@ -34,9 +34,15 @@ pub enum CompileError { span: Span, }, Unreachable, - BreakOutsideLoop {span: Span}, - ContinueOutsideLoop {span: Span}, - ReturnOutsideFunction {span: Span}, + BreakOutsideLoop { + span: Span, + }, + ContinueOutsideLoop { + span: Span, + }, + ReturnOutsideFunction { + span: Span, + }, } impl From for CompileError { @@ -76,8 +82,12 @@ impl std::fmt::Display for CompileError { } CompileError::Unreachable => write!(f, "Unreachable"), CompileError::BreakOutsideLoop { span } => write!(f, "Break outside loop at {span:?}"), - CompileError::ContinueOutsideLoop { span } => write!(f, "Continue outside loop at {span:?}"), - CompileError::ReturnOutsideFunction { span } => write!(f, "Return outside function at {span:?}"), + CompileError::ContinueOutsideLoop { span } => { + write!(f, "Continue outside loop at {span:?}") + } + CompileError::ReturnOutsideFunction { span } => { + write!(f, "Return outside function at {span:?}") + } } } } @@ -105,7 +115,7 @@ impl Compiler { let unit = lowering(ast, env)?; let mut codegen = Codegen::new(&Register::general()); - let insts = codegen.generate_code(unit.control_flow_graph, false); + let insts = codegen.generate_code(unit.control_flow_graph); let mut instructions = insts.to_vec(); @@ -114,7 +124,7 @@ impl Compiler { let mut offset = instructions.len(); for func in unit.functions { let mut codegen = Codegen::new(&Register::general()); - let insts = codegen.generate_code(func.control_flow_graph, true); + let insts = codegen.generate_code(func.control_flow_graph); symtab.insert(func.id, offset); offset += insts.len(); instructions.extend(insts.to_vec()); @@ -137,6 +147,11 @@ mod test { #[test] fn test_compile_if_else() { + let _ = env_logger::builder() + .filter_level(log::LevelFilter::Trace) + .is_test(true) + .try_init(); + let input = r#" fn add(a, b) { let c = 1; diff --git a/src/ir/instruction.rs b/src/ir/instruction.rs index 793d238..5d26462 100644 --- a/src/ir/instruction.rs +++ b/src/ir/instruction.rs @@ -293,6 +293,16 @@ impl Instruction { ) } + pub fn is_call(&self) -> bool { + matches!( + self, + Instruction::Call { .. } + | Instruction::CallEx { .. } + | Instruction::CallNative { .. } + | Instruction::PropertyCall { .. } + ) + } + pub fn defined_and_used_vars(&self) -> (Vec, Vec) { match self { Instruction::LoadArg { dst, .. } => (vec![*dst], vec![]), @@ -412,9 +422,9 @@ impl std::fmt::Display for Instruction { args, result: dst, } => { - write!(f, "{dst} = call {func}")?; + write!(f, "{dst} = call {func} ")?; for arg in args { - write!(f, " ,{arg}")?; + write!(f, ", {arg}")?; } Ok(()) } @@ -425,7 +435,7 @@ impl std::fmt::Display for Instruction { } => { write!(f, "{dst} = call_ex {callable}")?; for arg in args { - write!(f, " ,{arg}")?; + write!(f, ", {arg}")?; } Ok(()) } @@ -436,7 +446,7 @@ impl std::fmt::Display for Instruction { } => { write!(f, "{dst} = call_native {func}")?; for arg in args { - write!(f, " ,{arg}")?; + write!(f, ", {arg}")?; } Ok(()) } diff --git a/src/lib.rs b/src/lib.rs index 70d9932..8df6954 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,6 +8,6 @@ mod runtime; pub use error::Error; pub use interpreter::Interpreter; -pub use runtime::{Environment, NativeFunction, Null, Object, RuntimeError, ValueRef, Value}; #[cfg(feature = "async")] pub use runtime::Promise; +pub use runtime::{Environment, NativeFunction, Null, Object, RuntimeError, Value, ValueRef}; diff --git a/src/runtime.rs b/src/runtime.rs index 58ae9ba..bdd5ca8 100644 --- a/src/runtime.rs +++ b/src/runtime.rs @@ -9,12 +9,11 @@ mod vm; use crate::bytecode::{Operand, Register}; pub use environment::Environment; +#[cfg(feature = "async")] +pub use object::Promise; pub use object::{Callable, Enumerator, NativeFunction, Null, Object, Range}; pub use value::{Value, ValueRef}; pub use vm::VM; -#[cfg(feature = "async")] -pub use object::Promise; - pub(crate) use object::{Immd, UserFunction}; @@ -123,10 +122,7 @@ impl std::fmt::Display for RuntimeError { write!(f, "Invalid `{kind}` operation: {message}") } RuntimeError::InvalidType { expected, got } => { - write!( - f, - "Invalid type: expected type `{expected}`, got `{got}`" - ) + write!(f, "Invalid type: expected type `{expected}`, got `{got}`") } RuntimeError::InvalidArgumentCount { expected, got } => { write!( @@ -148,10 +144,7 @@ impl std::fmt::Display for RuntimeError { write!(f, "Symbol `{name}` not found") } RuntimeError::IndexOutOfBounds { index, length } => { - write!( - f, - "Index out of bounds: index `{index}`, length `{length}`" - ) + write!(f, "Index out of bounds: index `{index}`, length `{length}`") } RuntimeError::KeyNotFound { key } => { write!(f, "Key `{key}` not found") diff --git a/src/runtime/object/array.rs b/src/runtime/object/array.rs index 7c42f0f..31d713e 100644 --- a/src/runtime/object/array.rs +++ b/src/runtime/object/array.rs @@ -1,4 +1,3 @@ - use crate::{Object, RuntimeError, Value, ValueRef}; use super::Range; diff --git a/src/runtime/object/function.rs b/src/runtime/object/function.rs index 7ec641d..fcd831d 100644 --- a/src/runtime/object/function.rs +++ b/src/runtime/object/function.rs @@ -1,6 +1,6 @@ use std::{fmt, marker::PhantomData}; -use crate::{bytecode::FunctionId, Object, RuntimeError, Value, ValueRef}; +use crate::{Object, RuntimeError, Value, ValueRef, bytecode::FunctionId}; #[derive(Debug, Clone, Copy)] pub struct UserFunction(FunctionId); @@ -106,7 +106,6 @@ pub trait FromValue: Sized { fn from_value(value: &ValueRef) -> Result; } - impl FromValue for T where T: Object + Clone, diff --git a/src/runtime/object/integer.rs b/src/runtime/object/integer.rs index b2fc8fa..89eb0f3 100644 --- a/src/runtime/object/integer.rs +++ b/src/runtime/object/integer.rs @@ -1,4 +1,3 @@ - use crate::{Object, RuntimeError, Value}; macro_rules! impl_object_for_integer { diff --git a/src/runtime/object/promise.rs b/src/runtime/object/promise.rs index e1a59ad..362cdfd 100644 --- a/src/runtime/object/promise.rs +++ b/src/runtime/object/promise.rs @@ -2,7 +2,6 @@ use std::{fmt, pin::Pin}; use futures::FutureExt; - use crate::{Object, Value}; /// Promise diff --git a/src/runtime/object/tuple.rs b/src/runtime/object/tuple.rs index c0aee3f..e33d0f9 100644 --- a/src/runtime/object/tuple.rs +++ b/src/runtime/object/tuple.rs @@ -44,7 +44,6 @@ impl Object for (ValueRef, ValueRef) { } } - // impl Object for (ValueRef, ValueRef) { // fn debug(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { // write!(f, "({:?}, {:?})", self.0, self.1) diff --git a/src/runtime/value.rs b/src/runtime/value.rs index 542d6db..d3a8f05 100644 --- a/src/runtime/value.rs +++ b/src/runtime/value.rs @@ -35,9 +35,6 @@ impl Value { } } - - - #[derive(Debug, Clone)] pub struct ValueRef(Rc>); diff --git a/src/runtime/vm.rs b/src/runtime/vm.rs index 22c693e..7e72a2d 100644 --- a/src/runtime/vm.rs +++ b/src/runtime/vm.rs @@ -142,7 +142,11 @@ impl VM { Ok(self.data_stack[index as usize].clone()) } - pub fn set_value_to_stack(&mut self, offset: isize, value: ValueRef) -> Result<(), RuntimeError> { + pub fn set_value_to_stack( + &mut self, + offset: isize, + value: ValueRef, + ) -> Result<(), RuntimeError> { let index = self.rbp as isize + offset; if index < 0 || index as usize >= STACK_MAX { return Err(RuntimeError::StackOverflow); @@ -164,4 +168,4 @@ impl fmt::Display for VM { write!(f, "Registers: {:?}", &self.registers[0..20])?; Ok(()) } -} \ No newline at end of file +} diff --git a/tests/eval.rs b/tests/eval.rs index 1978a8a..c1b58f9 100644 --- a/tests/eval.rs +++ b/tests/eval.rs @@ -95,7 +95,7 @@ fn test_eval_control_flow() { #[test] fn test_eval_array() { - // init(); + init_logger(); let mut env = Environment::new(); @@ -217,7 +217,6 @@ fn test_eval_for() { println!("ret: {retval:?}"); assert!(retval.is_ok()); - } #[test] diff --git a/tests/interpreter.rs b/tests/interpreter.rs index 7a04f6d..31801fd 100644 --- a/tests/interpreter.rs +++ b/tests/interpreter.rs @@ -376,7 +376,10 @@ fn test_eval_recursive_depth_exceeded() { "#; let result = Interpreter::eval_script(script, env); - assert!(matches!(result.err().unwrap(), evalit::Error::Runtime(RuntimeError::StackOverflow))); + assert!(matches!( + result.err().unwrap(), + evalit::Error::Runtime(RuntimeError::StackOverflow) + )); } #[test]