feat: 字节码VM基础设施 — 编译器、VM执行循环、Runtime trait
Phase 1-3: 基础VM架构 - 新增 Runtime trait: 抽象树遍历解释器和VM的共同接口 - NativeFn 改为接受 &mut dyn Runtime - 重构所有内置函数使用新签名 - vm/opcode.rs: 33个字节码指令 + 编码/解码辅助函数 - vm/compiler.rs: AST→字节码编译器,支持变量解析、跳转回填、作用域 - vm/vm.rs: 栈式VM执行循环,支持全局变量、原生函数调用 - lib.rs: 新增 run_file_vm() + --vm CLI标志 - 修复: 跳转偏移计算、对象字面量编译 工作特性: 算术、变量、while/for循环、条件、数组、对象、字符串 待完成: 用户定义函数调用、闭包/upvalue捕获、完整require支持 Release模式: 1M算术循环 VM 0.44s vs 树遍历 0.89s (2.0x加速)
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
//! 标准库:core(len, typeof, push, pop)
|
||||
|
||||
use crate::error::RuntimeError;
|
||||
use crate::interpreter::{Interpreter, Value};
|
||||
use crate::interpreter::{Runtime, Value};
|
||||
|
||||
pub fn len(_interp: &mut Interpreter, args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||
pub fn len(_runtime: &mut dyn Runtime, args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||
if args.is_empty() {
|
||||
return Err(RuntimeError::RuntimeError {
|
||||
message: "len() expects 1 argument".into(),
|
||||
@@ -21,7 +21,7 @@ pub fn len(_interp: &mut Interpreter, args: Vec<Value>) -> Result<Value, Runtime
|
||||
}
|
||||
}
|
||||
|
||||
pub fn typeof_fn(_interp: &mut Interpreter, args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||
pub fn typeof_fn(_interp: &mut dyn Runtime, args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||
if args.is_empty() {
|
||||
return Err(RuntimeError::RuntimeError {
|
||||
message: "typeof() expects 1 argument".into(),
|
||||
@@ -41,7 +41,7 @@ pub fn typeof_fn(_interp: &mut Interpreter, args: Vec<Value>) -> Result<Value, R
|
||||
Ok(Value::String(s.into()))
|
||||
}
|
||||
|
||||
pub fn push(_interp: &mut Interpreter, args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||
pub fn push(_interp: &mut dyn Runtime, args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||
if args.len() < 2 {
|
||||
return Err(RuntimeError::RuntimeError {
|
||||
message: "push() expects 2 arguments (array, value)".into(),
|
||||
@@ -61,7 +61,7 @@ pub fn push(_interp: &mut Interpreter, args: Vec<Value>) -> Result<Value, Runtim
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pop(_interp: &mut Interpreter, args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||
pub fn pop(_interp: &mut dyn Runtime, args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||
if args.is_empty() {
|
||||
return Err(RuntimeError::RuntimeError {
|
||||
message: "pop() expects 1 argument (array)".into(),
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
//! 标准库:io(print, input)
|
||||
|
||||
use crate::error::RuntimeError;
|
||||
use crate::interpreter::{Interpreter, Value};
|
||||
use crate::interpreter::{Runtime, Value};
|
||||
|
||||
pub fn print(_interp: &mut Interpreter, args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||
pub fn print(_interp: &mut dyn Runtime, args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||
for arg in args.iter() {
|
||||
print!("{}", arg);
|
||||
}
|
||||
@@ -11,7 +11,7 @@ pub fn print(_interp: &mut Interpreter, args: Vec<Value>) -> Result<Value, Runti
|
||||
Ok(Value::Nil)
|
||||
}
|
||||
|
||||
pub fn input(_interp: &mut Interpreter, args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||
pub fn input(_interp: &mut dyn Runtime, args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||
if let Some(prompt) = args.get(0) {
|
||||
print!("{}", prompt);
|
||||
std::io::Write::flush(&mut std::io::stdout()).unwrap();
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
//! 内置函数模块:按功能分组注册,便于扩展和维护。
|
||||
|
||||
mod core;
|
||||
mod io;
|
||||
mod os;
|
||||
pub mod core;
|
||||
pub mod io;
|
||||
pub mod os;
|
||||
pub mod string;
|
||||
|
||||
use crate::interpreter::{Env, Value};
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
//! 标准库:os(clock)
|
||||
|
||||
use crate::error::RuntimeError;
|
||||
use crate::interpreter::{Interpreter, Value};
|
||||
use crate::interpreter::{Runtime, Value};
|
||||
|
||||
pub fn clock(_interp: &mut Interpreter, _args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||
pub fn clock(_interp: &mut dyn Runtime, _args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||
Ok(Value::Number(
|
||||
std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//! 标准库:string(split, trim, substring, replace, contains, upper, lower, starts_with, ends_with)
|
||||
|
||||
use crate::error::RuntimeError;
|
||||
use crate::interpreter::{Interpreter, Value};
|
||||
use crate::interpreter::{Runtime, Value};
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
@@ -19,7 +19,7 @@ fn require_string(val: &Value, arg_name: &str) -> Result<String, RuntimeError> {
|
||||
// split(str, delim) → array of substrings
|
||||
// ============================================================================
|
||||
|
||||
pub fn split(_interp: &mut Interpreter, args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||
pub fn split(_interp: &mut dyn Runtime, args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||
if args.len() < 2 {
|
||||
return Err(RuntimeError::RuntimeError {
|
||||
message: "split() expects 2 arguments (string, delimiter)".into(),
|
||||
@@ -43,7 +43,7 @@ pub fn split(_interp: &mut Interpreter, args: Vec<Value>) -> Result<Value, Runti
|
||||
// trim(str) → string with leading/trailing whitespace removed
|
||||
// ============================================================================
|
||||
|
||||
pub fn trim(_interp: &mut Interpreter, args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||
pub fn trim(_interp: &mut dyn Runtime, args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||
if args.is_empty() {
|
||||
return Err(RuntimeError::RuntimeError {
|
||||
message: "trim() expects 1 argument (string)".into(),
|
||||
@@ -58,7 +58,7 @@ pub fn trim(_interp: &mut Interpreter, args: Vec<Value>) -> Result<Value, Runtim
|
||||
// substring(str, start, len?) → substring
|
||||
// ============================================================================
|
||||
|
||||
pub fn substring(_interp: &mut Interpreter, args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||
pub fn substring(_interp: &mut dyn Runtime, args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||
if args.is_empty() {
|
||||
return Err(RuntimeError::RuntimeError {
|
||||
message: "substring() expects at least 2 arguments (string, start, len?)".into(),
|
||||
@@ -81,7 +81,7 @@ pub fn substring(_interp: &mut Interpreter, args: Vec<Value>) -> Result<Value, R
|
||||
// replace(str, old, new) → string with all occurrences replaced
|
||||
// ============================================================================
|
||||
|
||||
pub fn replace(_interp: &mut Interpreter, args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||
pub fn replace(_interp: &mut dyn Runtime, args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||
if args.len() < 3 {
|
||||
return Err(RuntimeError::RuntimeError {
|
||||
message: "replace() expects 3 arguments (string, old, new)".into(),
|
||||
@@ -106,7 +106,7 @@ pub fn replace(_interp: &mut Interpreter, args: Vec<Value>) -> Result<Value, Run
|
||||
// contains(str, needle) → bool
|
||||
// ============================================================================
|
||||
|
||||
pub fn contains(_interp: &mut Interpreter, args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||
pub fn contains(_interp: &mut dyn Runtime, args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||
if args.len() < 2 {
|
||||
return Err(RuntimeError::RuntimeError {
|
||||
message: "contains() expects 2 arguments (string, needle)".into(),
|
||||
@@ -122,7 +122,7 @@ pub fn contains(_interp: &mut Interpreter, args: Vec<Value>) -> Result<Value, Ru
|
||||
// upper(str) → uppercase (ASCII)
|
||||
// ============================================================================
|
||||
|
||||
pub fn upper(_interp: &mut Interpreter, args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||
pub fn upper(_interp: &mut dyn Runtime, args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||
if args.is_empty() {
|
||||
return Err(RuntimeError::RuntimeError {
|
||||
message: "upper() expects 1 argument (string)".into(),
|
||||
@@ -137,7 +137,7 @@ pub fn upper(_interp: &mut Interpreter, args: Vec<Value>) -> Result<Value, Runti
|
||||
// lower(str) → lowercase (ASCII)
|
||||
// ============================================================================
|
||||
|
||||
pub fn lower(_interp: &mut Interpreter, args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||
pub fn lower(_interp: &mut dyn Runtime, args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||
if args.is_empty() {
|
||||
return Err(RuntimeError::RuntimeError {
|
||||
message: "lower() expects 1 argument (string)".into(),
|
||||
@@ -152,7 +152,7 @@ pub fn lower(_interp: &mut Interpreter, args: Vec<Value>) -> Result<Value, Runti
|
||||
// starts_with(str, prefix) → bool
|
||||
// ============================================================================
|
||||
|
||||
pub fn starts_with(_interp: &mut Interpreter, args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||
pub fn starts_with(_interp: &mut dyn Runtime, args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||
if args.len() < 2 {
|
||||
return Err(RuntimeError::RuntimeError {
|
||||
message: "starts_with() expects 2 arguments (string, prefix)".into(),
|
||||
@@ -168,7 +168,7 @@ pub fn starts_with(_interp: &mut Interpreter, args: Vec<Value>) -> Result<Value,
|
||||
// ends_with(str, suffix) → bool
|
||||
// ============================================================================
|
||||
|
||||
pub fn ends_with(_interp: &mut Interpreter, args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||
pub fn ends_with(_interp: &mut dyn Runtime, args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||
if args.len() < 2 {
|
||||
return Err(RuntimeError::RuntimeError {
|
||||
message: "ends_with() expects 2 arguments (string, suffix)".into(),
|
||||
|
||||
@@ -103,7 +103,7 @@ impl super::Interpreter {
|
||||
"length" => Ok(Value::Number(arr.borrow().len() as f64)),
|
||||
"push" => {
|
||||
let arr = Rc::clone(&arr);
|
||||
Ok(Value::NativeFunction(Rc::new(move |_interp: &mut Self, mut args: Vec<Value>| {
|
||||
Ok(Value::NativeFunction(Rc::new(move |_runtime: &mut dyn super::Runtime, mut args: Vec<Value>| {
|
||||
let val = args.pop().unwrap_or(Value::Nil);
|
||||
arr.borrow_mut().push(val.clone());
|
||||
Ok(val)
|
||||
@@ -111,7 +111,7 @@ impl super::Interpreter {
|
||||
}
|
||||
"pop" => {
|
||||
let arr = Rc::clone(&arr);
|
||||
Ok(Value::NativeFunction(Rc::new(move |_interp: &mut Self, _args: Vec<Value>| {
|
||||
Ok(Value::NativeFunction(Rc::new(move |_runtime: &mut dyn super::Runtime, _args: Vec<Value>| {
|
||||
arr.borrow_mut()
|
||||
.pop()
|
||||
.ok_or_else(|| RuntimeError::RuntimeError {
|
||||
@@ -129,74 +129,74 @@ impl super::Interpreter {
|
||||
"length" => Ok(Value::Number(s.chars().count() as f64)),
|
||||
"upper" => {
|
||||
let s = s.clone();
|
||||
Ok(Value::NativeFunction(Rc::new(move |_interp: &mut Self, args: Vec<Value>| {
|
||||
Ok(Value::NativeFunction(Rc::new(move |runtime: &mut dyn super::Runtime, args: Vec<Value>| {
|
||||
let mut all_args = vec![Value::String(s.clone())];
|
||||
all_args.extend(args);
|
||||
super::builtins::string::upper(_interp, all_args)
|
||||
super::builtins::string::upper(runtime, all_args)
|
||||
})))
|
||||
}
|
||||
"lower" => {
|
||||
let s = s.clone();
|
||||
Ok(Value::NativeFunction(Rc::new(move |_interp: &mut Self, args: Vec<Value>| {
|
||||
Ok(Value::NativeFunction(Rc::new(move |runtime: &mut dyn super::Runtime, args: Vec<Value>| {
|
||||
let mut all_args = vec![Value::String(s.clone())];
|
||||
all_args.extend(args);
|
||||
super::builtins::string::lower(_interp, all_args)
|
||||
super::builtins::string::lower(runtime, all_args)
|
||||
})))
|
||||
}
|
||||
"trim" => {
|
||||
let s = s.clone();
|
||||
Ok(Value::NativeFunction(Rc::new(move |_interp: &mut Self, args: Vec<Value>| {
|
||||
Ok(Value::NativeFunction(Rc::new(move |runtime: &mut dyn super::Runtime, args: Vec<Value>| {
|
||||
let mut all_args = vec![Value::String(s.clone())];
|
||||
all_args.extend(args);
|
||||
super::builtins::string::trim(_interp, all_args)
|
||||
super::builtins::string::trim(runtime, all_args)
|
||||
})))
|
||||
}
|
||||
"substring" => {
|
||||
let s = s.clone();
|
||||
Ok(Value::NativeFunction(Rc::new(move |_interp: &mut Self, args: Vec<Value>| {
|
||||
Ok(Value::NativeFunction(Rc::new(move |runtime: &mut dyn super::Runtime, args: Vec<Value>| {
|
||||
let mut all_args = vec![Value::String(s.clone())];
|
||||
all_args.extend(args);
|
||||
super::builtins::string::substring(_interp, all_args)
|
||||
super::builtins::string::substring(runtime, all_args)
|
||||
})))
|
||||
}
|
||||
"replace" => {
|
||||
let s = s.clone();
|
||||
Ok(Value::NativeFunction(Rc::new(move |_interp: &mut Self, args: Vec<Value>| {
|
||||
Ok(Value::NativeFunction(Rc::new(move |runtime: &mut dyn super::Runtime, args: Vec<Value>| {
|
||||
let mut all_args = vec![Value::String(s.clone())];
|
||||
all_args.extend(args);
|
||||
super::builtins::string::replace(_interp, all_args)
|
||||
super::builtins::string::replace(runtime, all_args)
|
||||
})))
|
||||
}
|
||||
"contains" => {
|
||||
let s = s.clone();
|
||||
Ok(Value::NativeFunction(Rc::new(move |_interp: &mut Self, args: Vec<Value>| {
|
||||
Ok(Value::NativeFunction(Rc::new(move |runtime: &mut dyn super::Runtime, args: Vec<Value>| {
|
||||
let mut all_args = vec![Value::String(s.clone())];
|
||||
all_args.extend(args);
|
||||
super::builtins::string::contains(_interp, all_args)
|
||||
super::builtins::string::contains(runtime, all_args)
|
||||
})))
|
||||
}
|
||||
"starts_with" => {
|
||||
let s = s.clone();
|
||||
Ok(Value::NativeFunction(Rc::new(move |_interp: &mut Self, args: Vec<Value>| {
|
||||
Ok(Value::NativeFunction(Rc::new(move |runtime: &mut dyn super::Runtime, args: Vec<Value>| {
|
||||
let mut all_args = vec![Value::String(s.clone())];
|
||||
all_args.extend(args);
|
||||
super::builtins::string::starts_with(_interp, all_args)
|
||||
super::builtins::string::starts_with(runtime, all_args)
|
||||
})))
|
||||
}
|
||||
"ends_with" => {
|
||||
let s = s.clone();
|
||||
Ok(Value::NativeFunction(Rc::new(move |_interp: &mut Self, args: Vec<Value>| {
|
||||
Ok(Value::NativeFunction(Rc::new(move |runtime: &mut dyn super::Runtime, args: Vec<Value>| {
|
||||
let mut all_args = vec![Value::String(s.clone())];
|
||||
all_args.extend(args);
|
||||
super::builtins::string::ends_with(_interp, all_args)
|
||||
super::builtins::string::ends_with(runtime, all_args)
|
||||
})))
|
||||
}
|
||||
"split" => {
|
||||
let s = s.clone();
|
||||
Ok(Value::NativeFunction(Rc::new(move |_interp: &mut Self, args: Vec<Value>| {
|
||||
Ok(Value::NativeFunction(Rc::new(move |runtime: &mut dyn super::Runtime, args: Vec<Value>| {
|
||||
let mut all_args = vec![Value::String(s.clone())];
|
||||
all_args.extend(args);
|
||||
super::builtins::string::split(_interp, all_args)
|
||||
super::builtins::string::split(runtime, all_args)
|
||||
})))
|
||||
}
|
||||
_ => Err(RuntimeError::RuntimeError {
|
||||
@@ -481,7 +481,7 @@ impl super::Interpreter {
|
||||
|
||||
pub fn call_function(&mut self, func_val: Value, args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||
match func_val {
|
||||
Value::NativeFunction(native_fn) => native_fn(self, args),
|
||||
Value::NativeFunction(native_fn) => native_fn(self as &mut dyn super::Runtime, args),
|
||||
Value::Function(f) => self.call_user_function(f, args),
|
||||
_ => Err(RuntimeError::RuntimeError {
|
||||
message: "Attempt to call non-function".to_string(),
|
||||
|
||||
@@ -13,7 +13,16 @@ use std::rc::Rc;
|
||||
use std::cell::RefCell;
|
||||
use std::fmt;
|
||||
|
||||
pub type NativeFn = Rc<dyn Fn(&mut super::Interpreter, Vec<Value>) -> Result<Value, crate::error::RuntimeError>>;
|
||||
/// 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 {
|
||||
|
||||
@@ -8,15 +8,20 @@
|
||||
use crate::error::RuntimeError;
|
||||
use crate::lexer::Lexer;
|
||||
use crate::parser::Parser;
|
||||
use super::{Interpreter, Env, Value, Signal};
|
||||
use super::{Interpreter, Env, Value, Signal, Runtime};
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::path::Path;
|
||||
use std::rc::Rc;
|
||||
|
||||
/// require() 的内置函数实现
|
||||
pub fn require_fn(interp: &mut Interpreter, args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||
// 1. 参数验证
|
||||
impl Runtime for Interpreter {
|
||||
fn require(&mut self, path: &str) -> Result<Value, RuntimeError> {
|
||||
require_impl(self, path)
|
||||
}
|
||||
}
|
||||
|
||||
/// require() 的内置函数实现 — 薄包装,委托给 Runtime::require
|
||||
pub fn require_fn(runtime: &mut dyn Runtime, args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||
let path_str = match args.first() {
|
||||
Some(Value::String(s)) => s.clone(),
|
||||
Some(other) => return Err(runtime_error(format!(
|
||||
@@ -24,28 +29,32 @@ pub fn require_fn(interp: &mut Interpreter, args: Vec<Value>) -> Result<Value, R
|
||||
None => return Err(runtime_error(
|
||||
"require() expects 1 argument (string path)")),
|
||||
};
|
||||
runtime.require(&path_str)
|
||||
}
|
||||
|
||||
// 2. 路径解析
|
||||
let resolved = resolve_path(&interp.current_dir, &path_str)?;
|
||||
/// require() 的内部实现 (供 Interpreter::require 使用)
|
||||
fn require_impl(interp: &mut Interpreter, path_str: &str) -> Result<Value, RuntimeError> {
|
||||
// 1. 路径解析
|
||||
let resolved = resolve_path(&interp.current_dir, path_str)?;
|
||||
|
||||
// 3. 缓存查找
|
||||
// 2. 缓存查找
|
||||
if let Some(cached) = interp.module_cache.borrow().get(&resolved) {
|
||||
return Ok(cached.clone());
|
||||
}
|
||||
|
||||
// 4. 读取文件
|
||||
// 3. 读取文件
|
||||
let src = std::fs::read_to_string(&resolved)
|
||||
.map_err(|e| runtime_error(format!(
|
||||
"Module '{}' not found: {}", path_str, e)))?;
|
||||
|
||||
// 5. 词法分析
|
||||
// 4. 词法分析
|
||||
let (tokens, lex_errors) = Lexer::new(&src).tokenize();
|
||||
if !lex_errors.is_empty() {
|
||||
return Err(runtime_error(format!(
|
||||
"Lex error in module '{}': {}", path_str, lex_errors[0])));
|
||||
}
|
||||
|
||||
// 6. 语法分析
|
||||
// 5. 语法分析
|
||||
let mut parser = Parser::new(tokens);
|
||||
let (stmts, parse_errors) = parser.parse();
|
||||
if !parse_errors.is_empty() {
|
||||
@@ -53,27 +62,26 @@ pub fn require_fn(interp: &mut Interpreter, args: Vec<Value>) -> Result<Value, R
|
||||
"Parse error in module '{}': {}", path_str, parse_errors[0])));
|
||||
}
|
||||
|
||||
// 7. 创建隔离的模块 env(父级 = builtins_env,看不到调用者的变量)
|
||||
// 6. 创建隔离的模块 env(父级 = builtins_env,看不到调用者的变量)
|
||||
let module_env = Rc::new(RefCell::new(Env::new(Some(Rc::clone(&interp.builtins_env)))));
|
||||
|
||||
// 8. 在缓存中插入占位符(支持循环 require)
|
||||
// 7. 在缓存中插入占位符(支持循环 require)
|
||||
let exports_map = Rc::new(RefCell::new(HashMap::new()));
|
||||
let exports = Value::Object(Rc::clone(&exports_map));
|
||||
interp.module_cache.borrow_mut().insert(resolved.clone(), exports.clone());
|
||||
|
||||
// 9. 保存调用者状态
|
||||
// 8. 保存调用者状态
|
||||
let previous_env = Rc::clone(&interp.env);
|
||||
let previous_dir = interp.current_dir.clone();
|
||||
|
||||
// 10. 切换到模块上下文
|
||||
// 9. 切换到模块上下文
|
||||
interp.env = module_env.clone();
|
||||
interp.current_dir = module_dir(&resolved);
|
||||
|
||||
// 11. 执行模块
|
||||
// 10. 执行模块
|
||||
for stmt in &stmts {
|
||||
match interp.execute(stmt.clone()) {
|
||||
Ok(Signal::Break) | Ok(Signal::Continue) => {
|
||||
// 恢复状态后返回错误
|
||||
interp.env = previous_env;
|
||||
interp.current_dir = previous_dir;
|
||||
interp.module_cache.borrow_mut().remove(&resolved);
|
||||
@@ -81,23 +89,20 @@ pub fn require_fn(interp: &mut Interpreter, args: Vec<Value>) -> Result<Value, R
|
||||
"break/continue outside of loop in module"));
|
||||
}
|
||||
Err(e) => {
|
||||
// 恢复状态后传播错误
|
||||
interp.env = previous_env;
|
||||
interp.current_dir = previous_dir;
|
||||
interp.module_cache.borrow_mut().remove(&resolved);
|
||||
return Err(e);
|
||||
}
|
||||
Ok(Signal::None) | Ok(Signal::Return(_)) => {
|
||||
// 正常执行或顶层 return,继续
|
||||
}
|
||||
Ok(Signal::None) | Ok(Signal::Return(_)) => {}
|
||||
}
|
||||
}
|
||||
|
||||
// 12. 恢复调用者状态
|
||||
// 11. 恢复调用者状态
|
||||
interp.env = previous_env;
|
||||
interp.current_dir = previous_dir;
|
||||
|
||||
// 13. 收集 exports(模块 env 中的所有直接绑定)
|
||||
// 12. 收集 exports(模块 env 中的所有直接绑定)
|
||||
for (name, (val, _mutable)) in module_env.borrow().values.clone() {
|
||||
exports_map.borrow_mut().insert(name, val);
|
||||
}
|
||||
@@ -109,7 +114,6 @@ pub fn require_fn(interp: &mut Interpreter, args: Vec<Value>) -> Result<Value, R
|
||||
// Helpers
|
||||
// ============================================================================
|
||||
|
||||
/// 解析模块路径:相对路径基于 current_dir,用 canonicalize 规范化
|
||||
fn resolve_path(current_dir: &str, path_str: &str) -> Result<String, RuntimeError> {
|
||||
let path = Path::new(path_str);
|
||||
let resolved = if path.is_absolute() {
|
||||
@@ -124,7 +128,6 @@ fn resolve_path(current_dir: &str, path_str: &str) -> Result<String, RuntimeErro
|
||||
path_str, resolved.display())))
|
||||
}
|
||||
|
||||
/// 提取模块文件所在目录
|
||||
fn module_dir(resolved: &str) -> String {
|
||||
Path::new(resolved)
|
||||
.parent()
|
||||
|
||||
Reference in New Issue
Block a user