Implement return values
This commit is contained in:
parent
638610d310
commit
e0c72003f9
@ -119,6 +119,7 @@ pub enum Statement {
|
||||
If(If),
|
||||
Print(Expression),
|
||||
FunDecl(String, Vec<String>, Ast),
|
||||
Return(Expression),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Default)]
|
||||
|
||||
@ -8,6 +8,11 @@ pub enum Value {
|
||||
String(Rc<String>),
|
||||
}
|
||||
|
||||
pub enum RunEnd {
|
||||
Return(Value),
|
||||
End,
|
||||
}
|
||||
|
||||
pub struct Interpreter {
|
||||
// Variable table stores the runtime values of variables
|
||||
vartable: HashMap<String, Value>,
|
||||
@ -36,13 +41,17 @@ impl Interpreter {
|
||||
self.run(&ast);
|
||||
}
|
||||
|
||||
pub fn run(&mut self, prog: &Ast) {
|
||||
pub fn run(&mut self, prog: &Ast) -> RunEnd {
|
||||
for stmt in &prog.prog {
|
||||
match stmt {
|
||||
Statement::Expr(expr) => {
|
||||
self.resolve_expr(expr);
|
||||
}
|
||||
|
||||
Statement::Return(expr) => {
|
||||
return RunEnd::Return(self.resolve_expr(expr));
|
||||
}
|
||||
|
||||
Statement::Loop(looop) => {
|
||||
// loop runs as long condition != 0
|
||||
loop {
|
||||
@ -50,7 +59,10 @@ impl Interpreter {
|
||||
break;
|
||||
}
|
||||
|
||||
self.run(&looop.body);
|
||||
match self.run(&looop.body) {
|
||||
RunEnd::Return(val) => return RunEnd::Return(val),
|
||||
RunEnd::End => (),
|
||||
}
|
||||
|
||||
if let Some(adv) = &looop.advancement {
|
||||
self.resolve_expr(&adv);
|
||||
@ -64,18 +76,23 @@ impl Interpreter {
|
||||
}
|
||||
|
||||
Statement::If(If {condition, body_true, body_false}) => {
|
||||
if matches!(self.resolve_expr(condition), Value::I64(0)) {
|
||||
self.run(body_false);
|
||||
let end = if matches!(self.resolve_expr(condition), Value::I64(0)) {
|
||||
self.run(body_false)
|
||||
} else {
|
||||
self.run(body_true);
|
||||
self.run(body_true)
|
||||
};
|
||||
match end {
|
||||
RunEnd::Return(val) => return RunEnd::Return(val),
|
||||
RunEnd::End => (),
|
||||
}
|
||||
}
|
||||
Statement::FunDecl(name, args, body) => {
|
||||
self.funtable.insert(name.clone(), (args.clone(), body.clone()).into());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
RunEnd::End
|
||||
}
|
||||
|
||||
fn resolve_expr(&mut self, expr: &Expression) -> Value {
|
||||
@ -96,9 +113,11 @@ impl Interpreter {
|
||||
panic!("Invalid number of arguments for function");
|
||||
}
|
||||
|
||||
self.run(&fun.borrow().1);
|
||||
|
||||
Value::I64(0)
|
||||
let end = self.run(&fun.borrow().1);
|
||||
match end {
|
||||
RunEnd::Return(val) => val,
|
||||
RunEnd::End => Value::I64(0),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -191,6 +191,7 @@ impl<'a> Lexer<'a> {
|
||||
"if" => Token::If,
|
||||
"else" => Token::Else,
|
||||
"fun" => Token::Fun,
|
||||
"return" => Token::Return,
|
||||
|
||||
// If it doesn't match a keyword, it is a normal identifier
|
||||
_ => Token::Ident(ident),
|
||||
|
||||
@ -52,6 +52,19 @@ impl<T: Iterator<Item = Token>> Parser<T> {
|
||||
Statement::Print(expr)
|
||||
}
|
||||
|
||||
Token::Return => {
|
||||
self.next();
|
||||
|
||||
let expr = self.parse_expr();
|
||||
|
||||
// After a statement, there must be a semicolon
|
||||
if !matches!(self.next(), Token::Semicolon) {
|
||||
panic!("Expected semicolon after statement");
|
||||
}
|
||||
|
||||
Statement::Return(expr)
|
||||
}
|
||||
|
||||
Token::If => Statement::If(self.parse_if()),
|
||||
|
||||
Token::Fun => {
|
||||
|
||||
@ -27,6 +27,8 @@ pub enum Token {
|
||||
|
||||
Comma,
|
||||
|
||||
Return,
|
||||
|
||||
/// Left Parenthesis ('(')
|
||||
LParen,
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user