feat: 添加break和continue语句的支持,更新解析器、解释器和词法分析器以处理相关语法
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
use crate::ast::*;
|
||||
use crate::error::RuntimeError;
|
||||
use crate::interpreter::Signal;
|
||||
use super::{Value, Env, Function};
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
@@ -23,26 +24,30 @@ impl Interpreter {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn execute(&mut self, stmt: Stmt) -> Result<Option<Value>, RuntimeError> {
|
||||
fn execute(&mut self, stmt: Stmt) -> Result<Signal, RuntimeError> {
|
||||
match stmt {
|
||||
Stmt::Let { name, initializer } => {
|
||||
let val = self.evaluate(initializer)?;
|
||||
self.env.borrow_mut().define(name, val);
|
||||
Ok(None)
|
||||
Ok(Signal::None)
|
||||
}
|
||||
Stmt::ExprStmt(expr) => {
|
||||
Ok(Some(self.evaluate(expr)?))
|
||||
self.evaluate(expr)?;
|
||||
Ok(Signal::None)
|
||||
}
|
||||
Stmt::Block(stmts) => {
|
||||
let previous = Rc::clone(&self.env);
|
||||
self.env = Rc::new(RefCell::new(Env::new(Some(previous))));
|
||||
let mut result = None;
|
||||
let mut signal = Signal::None;
|
||||
for s in stmts {
|
||||
result = self.execute(s)?;
|
||||
signal = self.execute(s)?;
|
||||
if !matches!(signal, Signal::None) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
let parent = self.env.borrow().parent.as_ref().unwrap().clone();
|
||||
self.env = parent;
|
||||
Ok(result)
|
||||
Ok(signal)
|
||||
}
|
||||
Stmt::If { condition, then_branch, else_branch } => {
|
||||
let cond_val = self.evaluate(condition)?;
|
||||
@@ -51,7 +56,7 @@ impl Interpreter {
|
||||
} else if let Some(else_branch) = else_branch {
|
||||
self.execute(*else_branch)
|
||||
} else {
|
||||
Ok(None)
|
||||
Ok(Signal::None)
|
||||
}
|
||||
}
|
||||
Stmt::While { condition, body } => {
|
||||
@@ -60,25 +65,42 @@ impl Interpreter {
|
||||
if !self.is_truthy(&cond_val) {
|
||||
break;
|
||||
}
|
||||
self.execute(*body.clone())?;
|
||||
match self.execute(*body.clone())? {
|
||||
Signal::Break => break,
|
||||
Signal::Continue => continue,
|
||||
sig @ Signal::Return(_) => return Ok(sig),
|
||||
Signal::None => {}
|
||||
}
|
||||
}
|
||||
Ok(None)
|
||||
Ok(Signal::None)
|
||||
}
|
||||
Stmt::For { initializer, condition, step, body } => {
|
||||
if let Some(init) = initializer {
|
||||
self.execute(*init)?;
|
||||
}
|
||||
while let Some(cond) = &condition {
|
||||
let cond_val = self.evaluate(cond.clone())?;
|
||||
if !self.is_truthy(&cond_val) {
|
||||
break;
|
||||
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 => {}
|
||||
}
|
||||
self.execute(*body.clone())?;
|
||||
if let Some(step) = &step {
|
||||
self.evaluate(step.clone())?;
|
||||
}
|
||||
}
|
||||
Ok(None)
|
||||
Ok(Signal::None)
|
||||
}
|
||||
Stmt::Function { name, params, body } => {
|
||||
let func = Value::Function(Rc::new(Function {
|
||||
@@ -88,15 +110,17 @@ impl Interpreter {
|
||||
name: Some(name.clone()),
|
||||
}));
|
||||
self.env.borrow_mut().define(name, func);
|
||||
Ok(None)
|
||||
Ok(Signal::None)
|
||||
}
|
||||
Stmt::Return(expr_opt) => {
|
||||
if let Some(expr) = expr_opt {
|
||||
Ok(Some(self.evaluate(expr)?))
|
||||
Ok(Signal::Return(self.evaluate(expr)?))
|
||||
} else {
|
||||
Ok(Some(Value::Nil))
|
||||
Ok(Signal::Return(Value::Nil))
|
||||
}
|
||||
}
|
||||
Stmt::Break => Ok(Signal::Break),
|
||||
Stmt::Continue => Ok(Signal::Continue),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -327,9 +351,15 @@ impl Interpreter {
|
||||
self.env = env;
|
||||
let mut ret = Value::Nil;
|
||||
for stmt in &f.body {
|
||||
if let Some(val) = self.execute(stmt.clone())? {
|
||||
ret = val;
|
||||
break;
|
||||
match self.execute(stmt.clone())? {
|
||||
Signal::Return(val) => { ret = val; break; }
|
||||
Signal::None => {}
|
||||
Signal::Break | Signal::Continue => {
|
||||
return Err(RuntimeError::RuntimeError {
|
||||
message: "break/continue outside of loop".to_string(),
|
||||
token: None,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
self.env = previous;
|
||||
|
||||
Reference in New Issue
Block a user