fix tail expression
This commit is contained in:
parent
bc02423fbd
commit
06b97d3132
5 changed files with 47 additions and 14 deletions
|
@ -38,6 +38,7 @@ pub enum Statement {
|
|||
Let(String, Expr),
|
||||
// Type(String, Type),
|
||||
Expr(Expr),
|
||||
TailExpr(Expr),
|
||||
Func(Func),
|
||||
// Break,
|
||||
// Continue,
|
||||
|
|
|
@ -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,12 +193,13 @@ 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");
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
@ -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!());
|
||||
|
|
14
src/main.rs
14
src/main.rs
|
@ -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());
|
||||
|
||||
|
|
|
@ -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::Symbol(Symbol::Semicolon)) => self.next_tok(),
|
||||
Some(Token::CloseBrace) => break,
|
||||
Some(tok) => return Err(Error::SyntaxError(format!("unexpected token {tok:?}"))),
|
||||
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::CloseBrace) => break,
|
||||
// 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")),
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue