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