Files
aster/aster-core/src/interpreter/builtins/core.rs
T
elmma d854b22006 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加速)
2026-06-25 01:08:49 +08:00

85 lines
2.7 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! 标准库:corelen, typeof, push, pop
use crate::error::RuntimeError;
use crate::interpreter::{Runtime, Value};
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(),
token: None,
});
}
match &args[0] {
Value::String(s) => Ok(Value::Number(s.chars().count() as f64)),
Value::Array(arr) => Ok(Value::Number(arr.borrow().len() as f64)),
Value::Object(obj) => Ok(Value::Number(obj.borrow().len() as f64)),
_ => Err(RuntimeError::RuntimeError {
message: "len() expects a string, array, or object".into(),
token: None,
}),
}
}
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(),
token: None,
});
}
let s = match &args[0] {
Value::Number(_) => "number",
Value::String(_) => "string",
Value::Bool(_) => "bool",
Value::Nil => "nil",
Value::Object(_) => "object",
Value::Array(_) => "array",
Value::Function(_) => "function",
Value::NativeFunction(_) => "native_function",
};
Ok(Value::String(s.into()))
}
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(),
token: None,
});
}
let val = args[1].clone();
match &args[0] {
Value::Array(arr) => {
arr.borrow_mut().push(val.clone());
Ok(val)
}
_ => Err(RuntimeError::RuntimeError {
message: "push() expects an array as first argument".into(),
token: None,
}),
}
}
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(),
token: None,
});
}
match &args[0] {
Value::Array(arr) => arr
.borrow_mut()
.pop()
.ok_or_else(|| RuntimeError::RuntimeError {
message: "pop() on empty array".into(),
token: None,
}),
_ => Err(RuntimeError::RuntimeError {
message: "pop() expects an array as first argument".into(),
token: None,
}),
}
}