fix tail expression

This commit is contained in:
tezlm 2023-10-02 15:35:35 -07:00
parent bc02423fbd
commit 06b97d3132
Signed by: tezlm
GPG key ID: 649733FCD94AFBBA
5 changed files with 47 additions and 14 deletions

View file

@ -38,6 +38,7 @@ pub enum Statement {
Let(String, Expr),
// Type(String, Type),
Expr(Expr),
TailExpr(Expr),
Func(Func),
// Break,
// Continue,

View file

@ -26,7 +26,7 @@ impl Generator {
Statement::Func(Func { name, ret, params, .. }) => {
ctx.funcs.insert(name.clone(), (params.clone(), ret.clone()));
}
Statement::Let(..) | Statement::Expr(..) => {
Statement::Let(..) | Statement::TailExpr(..) | Statement::Expr (..) => {
return Err(Error::syn("incorrect top level statement"))
}
};
@ -34,7 +34,7 @@ impl Generator {
for stmt in stmts {
match stmt {
Statement::Func(func) => self.write_func(&ctx, func)?,
Statement::Let(..) | Statement::Expr(..) => {
_ => {
return Err(Error::syn("incorrect top level statement"))
}
};
@ -193,11 +193,12 @@ fn gen_expr(expr: &Expr, ctx: &Context) {
Expr::Block(b) => {
for (i, stmt) in b.0.iter().enumerate() {
match stmt {
Statement::TailExpr(expr) => {
gen_expr(expr, &ctx);
}
Statement::Expr(expr) => {
gen_expr(expr, &ctx);
if i < b.0.len() - 1 {
println!("drop");
}
println!("drop");
}
_ => {}
}
@ -212,6 +213,7 @@ fn gen_expr(expr: &Expr, ctx: &Context) {
};
}
// FIXME: block scoped variables
fn get_locals(expr: &Expr, ctx: &mut Context, exprs: &mut Vec<(String, Expr)>) {
match expr {
Expr::Block(b) => {
@ -222,6 +224,7 @@ fn get_locals(expr: &Expr, ctx: &mut Context, exprs: &mut Vec<(String, Expr)>) {
ctx.locals.insert(name.clone(), ty);
exprs.push((name.clone(), expr.clone()));
}
Statement::TailExpr(expr) => get_locals(&expr, ctx, exprs),
Statement::Expr(expr) => get_locals(&expr, ctx, exprs),
Statement::Func(Func { name, ret, .. }) => {
ctx.locals.insert(name.clone(), todo!());

View file

@ -54,11 +54,19 @@ fn main() {
// ".into());
let mut lexer = lexer::Lexer::new("
fn main() -> i32 {
add_three(30)
if is_three(add_four(-1)) {
20
} else {
30
}
}
fn add_three(n: i32) -> i32 {
n + 3
fn add_four(n: i32) -> i32 {
n + 4
}
fn is_three(n: i32) -> bool {
n == 3
}
".into());

View file

@ -55,6 +55,7 @@ impl Parser {
let name = self.parse_ident()?;
self.eat(Token::Symbol(Symbol::Set))?;
let expr = self.parse_expr(0)?;
self.eat(Token::Symbol(Symbol::Semicolon))?;
Statement::Let(name, expr)
}
Token::Fn => {
@ -87,7 +88,15 @@ impl Parser {
self.eat(Token::CloseBrace)?;
Statement::Func(Func { name, params, ret, block })
}
_ => Statement::Expr(self.parse_expr(0)?),
_ => {
let expr = self.parse_expr(0)?;
if self.peek_tok().is_some_and(|tk| tk == &Token::Symbol(Symbol::Semicolon)) {
self.eat(Token::Symbol(Symbol::Semicolon))?;
Statement::Expr(expr)
} else {
Statement::TailExpr(expr)
}
}
};
Ok(Some(stmt))
}
@ -99,6 +108,7 @@ impl Parser {
match tok {
Token::Ident(ident) => match ident.as_str() {
"i32" => Ok(Type::Integer),
"bool" => Ok(Type::Boolean),
_ => return Err(Error::TypeError(format!("unknown type {ident}"))),
},
_ => todo!(),
@ -127,11 +137,22 @@ impl Parser {
Some(_) => (),
None => return Err(Error::syn("missing closing brace")),
};
statements.push(self.parse_statement()?.unwrap());
match self.parse_statement()?.unwrap() {
stmt @ Statement::TailExpr(..) => {
statements.push(stmt);
match self.peek_tok() {
Some(Token::CloseBrace) => break,
tok => return Err(Error::SyntaxError(format!("unexpected token {tok:?}"))),
None => return Err(Error::syn("unexpected eof")),
};
}
stmt => statements.push(stmt),
}
match self.peek_tok() {
Some(Token::Symbol(Symbol::Semicolon)) => self.next_tok(),
Some(Token::CloseBrace) => break,
Some(tok) => return Err(Error::SyntaxError(format!("unexpected token {tok:?}"))),
// Some(_) => return Err(Error::SyntaxError(format!("unexpected token {tok:?}"))),
// tok => return Err(Error::SyntaxError(format!("unexpected token {tok:?}"))),
_ => (),
None => return Err(Error::syn("unexpected eof")),
};
}
@ -184,7 +205,7 @@ impl Parser {
self.eat(Token::CloseBrace)?;
b
}
Some(Token::If) => Some(Block(vec![Statement::Expr(self.parse_expr(0)?)])),
Some(Token::If) => Some(Block(vec![Statement::TailExpr(self.parse_expr(0)?)])),
Some(_) => return Err(Error::syn("unexpected token")),
None => return Err(Error::syn("unexpected eof, wanted body for else")),
}

View file

@ -129,7 +129,7 @@ impl Block {
let mut ty = Type::empty();
for statement in &self.0 {
match statement {
Statement::Expr(expr) => ty = expr.infer(&ctx)?,
Statement::TailExpr(expr) => ty = expr.infer(&ctx)?,
Statement::Let(name, expr) => {
let var_ty = expr.infer(&ctx)?;
ctx.locals.insert(name.clone(), var_ty);