refactor: VM-only architecture — remove tree-walking interpreter
Eliminate dual-engine architecture (Interpreter + Vm) in favor of a single bytecode VM executor. - Extract shared types (Value, FunctionProto, Closure, UpvalueObj, Runtime trait, NativeFn) into new module - Consolidate builtin registration in — single used by VM, eliminates 40-line duplicate - Delete tree-walker: exec.rs, eval.rs, interpreter.rs, env.rs, module.rs - Change Value::Function(Rc<Function>) → Value::Function(Rc<Closure>) eliminating the closures HashMap pointer-key hack - Fix VM semantic gaps found during migration: * Structural equality for Object/Array in is_equal * CompoundAssignGlobal opcode (global compound assigns were broken) * 9 string methods added to VM get_property * ForInInit error on non-iterable values - Switch run_file/run_repl to VM; remove --vm CLI flag - Move 327 tests from interpreter/ to vm/ — all pass Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,133 +1,3 @@
|
||||
pub mod builtins;
|
||||
pub mod env;
|
||||
pub mod eval;
|
||||
pub mod exec;
|
||||
pub mod interpreter;
|
||||
pub mod module;
|
||||
|
||||
pub use env::Env;
|
||||
pub use interpreter::Interpreter;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
use std::cell::RefCell;
|
||||
use std::fmt;
|
||||
|
||||
/// Trait abstracting runtime services that native functions may need.
|
||||
/// Both the tree-walking `Interpreter` and the bytecode `Vm` implement this.
|
||||
pub trait Runtime {
|
||||
/// Load and execute a module, returning its exports object.
|
||||
/// Implementations differ: tree-walker interprets directly,
|
||||
/// VM compiles to bytecode then executes.
|
||||
fn require(&mut self, path: &str) -> Result<Value, crate::error::RuntimeError>;
|
||||
}
|
||||
|
||||
pub type NativeFn = Rc<dyn Fn(&mut dyn Runtime, Vec<Value>) -> Result<Value, crate::error::RuntimeError>>;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum Value {
|
||||
Number(f64),
|
||||
String(String),
|
||||
Bool(bool),
|
||||
Nil,
|
||||
Object(Rc<RefCell<HashMap<String, Value>>>),
|
||||
Array(Rc<RefCell<Vec<Value>>>),
|
||||
Function(Rc<Function>),
|
||||
NativeFunction(NativeFn),
|
||||
}
|
||||
|
||||
pub enum Signal {
|
||||
None, // 正常执行
|
||||
Return(Value), // return 语句携带的返回值
|
||||
Break, // break 信号
|
||||
Continue, // continue 信号
|
||||
}
|
||||
|
||||
impl Value {
|
||||
pub fn get(&self, key: &str) -> Option<Value> {
|
||||
match self {
|
||||
Value::Object(obj) => obj.borrow().get(key).cloned(),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set(&self, key: &str, val: Value) -> Result<(), crate::error::RuntimeError> {
|
||||
match self {
|
||||
Value::Object(obj) => {
|
||||
obj.borrow_mut().insert(key.to_string(), val);
|
||||
Ok(())
|
||||
},
|
||||
_ => Err(crate::error::RuntimeError::RuntimeError {
|
||||
message: "Only objects have properties".to_string(),
|
||||
token: None,
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for Value {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
match self {
|
||||
Value::Number(n) => write!(f, "Number({:?})", n),
|
||||
Value::String(s) => write!(f, "String({:?})", s),
|
||||
Value::Bool(b) => write!(f, "Bool({:?})", b),
|
||||
Value::Nil => write!(f, "Nil"),
|
||||
Value::Object(_) => write!(f, "Object(...)"),
|
||||
Value::Array(_) => write!(f, "Array(...)"),
|
||||
Value::Function(_) => write!(f, "Function(...)"),
|
||||
Value::NativeFunction(_) => write!(f, "NativeFunction(...)"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Value {
|
||||
/// 容器内值的格式化:字符串加引号以区分类型,其余类型用 Display
|
||||
fn fmt_element(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
Value::String(s) => write!(f, "\"{}\"", s),
|
||||
other => write!(f, "{}", other),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Value {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
Value::Number(n) => write!(f, "{}", n),
|
||||
Value::String(s) => write!(f, "{}", s),
|
||||
Value::Bool(b) => write!(f, "{}", b),
|
||||
Value::Nil => write!(f, "nil"),
|
||||
Value::Object(obj) => {
|
||||
let obj = obj.borrow();
|
||||
write!(f, "{{ ")?;
|
||||
for (key, value) in obj.iter() {
|
||||
write!(f, "{}: ", key)?;
|
||||
value.fmt_element(f)?;
|
||||
write!(f, ", ")?;
|
||||
}
|
||||
write!(f, "}}")
|
||||
},
|
||||
Value::Array(arr) => {
|
||||
let arr = arr.borrow();
|
||||
write!(f, "[")?;
|
||||
for (i, val) in arr.iter().enumerate() {
|
||||
if i > 0 {
|
||||
write!(f, ", ")?;
|
||||
}
|
||||
val.fmt_element(f)?;
|
||||
}
|
||||
write!(f, "]")
|
||||
},
|
||||
Value::Function(_) => write!(f, "<function>"),
|
||||
Value::NativeFunction(_) => write!(f, "<native function>"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Function {
|
||||
pub params: Vec<String>,
|
||||
pub body: Vec<crate::ast::Stmt>,
|
||||
pub env: Rc<RefCell<Env>>, // 闭包捕获环境
|
||||
pub name: Option<String>,
|
||||
}
|
||||
// Re-export shared types from runtime (backward compatibility)
|
||||
pub use crate::runtime::{Value, NativeFn, Runtime};
|
||||
pub use crate::runtime::builtins;
|
||||
|
||||
Reference in New Issue
Block a user