feat: IDE支持 — workspace拆分、LSP服务器、VS Code扩展
**Workspace 拆分** - aster-core: 纯库,zero-dependency,包含 lexer/parser/ast/interpreter/error/analysis - aster: REPL 二进制,薄封装 aster-core - aster-lsp: LSP 语言服务器 **VS Code 扩展 (vscode-ext/)** - TextMate 语法高亮 (.ast 文件) - 语言配置 (注释切换、括号配对、自动缩进) - LSP 客户端 (extension.js) **LSP 服务端功能** - Diagnostics: 实时显示 lex/parse 错误红色波浪线 - Completion: 关键字 + 内置函数 + 用户定义符号补全 - Hover: 悬停显示变量/函数信息 - Signature Help: 函数参数提示 - Goto Definition: Ctrl+Click 跳转到声明处 - Find References: 查找所有引用位置 - Rename: F2 重命名符号 **新增 analysis 模块** - collect_symbols: AST 遍历收集符号 - find_declaration/find_all_references: Token 扫描定位声明和引用
This commit is contained in:
@@ -0,0 +1,192 @@
|
||||
use crate::ast::*;
|
||||
use crate::error::RuntimeError;
|
||||
use crate::interpreter::Signal;
|
||||
use super::{Value, Env, Function};
|
||||
use std::rc::Rc;
|
||||
use std::cell::RefCell;
|
||||
|
||||
impl super::Interpreter {
|
||||
// ========================================================================
|
||||
// execute — dispatcher
|
||||
// ========================================================================
|
||||
|
||||
pub fn execute(&mut self, stmt: Stmt) -> Result<Signal, RuntimeError> {
|
||||
match stmt {
|
||||
Stmt::Let { name, initializer, mutable } => self.exec_let(name, initializer, mutable),
|
||||
Stmt::ExprStmt(expr) => self.exec_expr_stmt(expr),
|
||||
Stmt::Block(stmts) => self.exec_block(stmts),
|
||||
Stmt::If { condition, then_branch, else_branch } => {
|
||||
self.exec_if(condition, *then_branch, else_branch.map(|b| *b))
|
||||
}
|
||||
Stmt::While { condition, body } => self.exec_while(condition, *body),
|
||||
Stmt::For { initializer, condition, step, body } => {
|
||||
self.exec_for(initializer, condition, step, *body)
|
||||
}
|
||||
Stmt::ForIn { var_name, iterable, body } => self.exec_for_in(var_name, iterable, *body),
|
||||
Stmt::Function { name, params, body } => self.exec_function(name, params, body),
|
||||
Stmt::Return(expr_opt) => self.exec_return(expr_opt),
|
||||
Stmt::Break => Ok(Signal::Break),
|
||||
Stmt::Continue => Ok(Signal::Continue),
|
||||
}
|
||||
}
|
||||
|
||||
// ========================================================================
|
||||
// exec_* methods
|
||||
// ========================================================================
|
||||
|
||||
fn exec_let(&mut self, name: String, initializer: Expr, mutable: bool) -> Result<Signal, RuntimeError> {
|
||||
let val = self.evaluate(initializer)?;
|
||||
self.env.borrow_mut().define(name, val, mutable);
|
||||
Ok(Signal::None)
|
||||
}
|
||||
|
||||
fn exec_expr_stmt(&mut self, expr: Expr) -> Result<Signal, RuntimeError> {
|
||||
self.evaluate(expr)?;
|
||||
Ok(Signal::None)
|
||||
}
|
||||
|
||||
fn exec_block(&mut self, stmts: Vec<Stmt>) -> Result<Signal, RuntimeError> {
|
||||
let previous = Rc::clone(&self.env);
|
||||
self.env = Rc::new(RefCell::new(Env::new(Some(previous))));
|
||||
let mut signal = Signal::None;
|
||||
for s in stmts {
|
||||
signal = self.execute(s)?;
|
||||
if !matches!(signal, Signal::None) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
let parent = self.env.borrow().parent.as_ref().unwrap().clone();
|
||||
self.env = parent;
|
||||
Ok(signal)
|
||||
}
|
||||
|
||||
fn exec_if(
|
||||
&mut self,
|
||||
condition: Expr,
|
||||
then_branch: Stmt,
|
||||
else_branch: Option<Stmt>,
|
||||
) -> Result<Signal, RuntimeError> {
|
||||
let cond_val = self.evaluate(condition)?;
|
||||
if self.is_truthy(&cond_val) {
|
||||
self.execute(then_branch)
|
||||
} else if let Some(else_branch) = else_branch {
|
||||
self.execute(else_branch)
|
||||
} else {
|
||||
Ok(Signal::None)
|
||||
}
|
||||
}
|
||||
|
||||
fn exec_while(&mut self, condition: Expr, body: Stmt) -> Result<Signal, RuntimeError> {
|
||||
loop {
|
||||
let cond_val = self.evaluate(condition.clone())?;
|
||||
if !self.is_truthy(&cond_val) {
|
||||
break;
|
||||
}
|
||||
match self.execute(body.clone())? {
|
||||
Signal::Break => break,
|
||||
Signal::Continue => continue,
|
||||
sig @ Signal::Return(_) => return Ok(sig),
|
||||
Signal::None => {}
|
||||
}
|
||||
}
|
||||
Ok(Signal::None)
|
||||
}
|
||||
|
||||
fn exec_for(
|
||||
&mut self,
|
||||
initializer: Option<Box<Stmt>>,
|
||||
condition: Option<Expr>,
|
||||
step: Option<Expr>,
|
||||
body: Stmt,
|
||||
) -> Result<Signal, RuntimeError> {
|
||||
if let Some(init) = initializer {
|
||||
self.execute(*init)?;
|
||||
}
|
||||
loop {
|
||||
if let Some(cond) = &condition {
|
||||
let cond_val = self.evaluate(cond.clone())?;
|
||||
if !self.is_truthy(&cond_val) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
match self.execute(body.clone())? {
|
||||
Signal::Break => break,
|
||||
Signal::Continue => {
|
||||
if let Some(step) = &step {
|
||||
self.evaluate(step.clone())?;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
sig @ Signal::Return(_) => return Ok(sig),
|
||||
Signal::None => {}
|
||||
}
|
||||
if let Some(step) = &step {
|
||||
self.evaluate(step.clone())?;
|
||||
}
|
||||
}
|
||||
Ok(Signal::None)
|
||||
}
|
||||
|
||||
fn exec_for_in(
|
||||
&mut self,
|
||||
var_name: String,
|
||||
iterable: Expr,
|
||||
body: Stmt,
|
||||
) -> Result<Signal, RuntimeError> {
|
||||
let iter_val = self.evaluate(iterable)?;
|
||||
let items: Vec<Value> = match &iter_val {
|
||||
Value::Array(arr) => arr.borrow().clone(),
|
||||
Value::Object(obj) => obj.borrow().keys().map(|k| Value::String(k.clone())).collect(),
|
||||
Value::String(s) => s.chars().map(|c| Value::String(c.to_string())).collect(),
|
||||
_ => {
|
||||
return Err(RuntimeError::RuntimeError {
|
||||
message: "for-in requires an array, object, or string".into(),
|
||||
token: None,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
let mut signal = Signal::None;
|
||||
for item in items {
|
||||
let previous = Rc::clone(&self.env);
|
||||
self.env = Rc::new(RefCell::new(Env::new(Some(previous))));
|
||||
self.env.borrow_mut().define(var_name.clone(), item, true);
|
||||
|
||||
signal = self.execute(body.clone())?;
|
||||
let parent = self.env.borrow().parent.as_ref().unwrap().clone();
|
||||
self.env = parent;
|
||||
|
||||
match signal {
|
||||
Signal::Break => { signal = Signal::None; break; }
|
||||
Signal::Continue => { signal = Signal::None; continue; }
|
||||
sig @ Signal::Return(_) => return Ok(sig),
|
||||
Signal::None => {}
|
||||
}
|
||||
}
|
||||
Ok(signal)
|
||||
}
|
||||
|
||||
fn exec_function(
|
||||
&mut self,
|
||||
name: String,
|
||||
params: Vec<String>,
|
||||
body: Vec<Stmt>,
|
||||
) -> Result<Signal, RuntimeError> {
|
||||
let func = Value::Function(Rc::new(Function {
|
||||
params,
|
||||
body,
|
||||
env: Rc::clone(&self.env),
|
||||
name: Some(name.clone()),
|
||||
}));
|
||||
self.env.borrow_mut().define(name, func, true);
|
||||
Ok(Signal::None)
|
||||
}
|
||||
|
||||
fn exec_return(&mut self, expr_opt: Option<Expr>) -> Result<Signal, RuntimeError> {
|
||||
if let Some(expr) = expr_opt {
|
||||
Ok(Signal::Return(self.evaluate(expr)?))
|
||||
} else {
|
||||
Ok(Signal::Return(Value::Nil))
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user