diff --git a/src/ast.rs b/src/ast.rs index 47ca9fb..9086abf 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -1,5 +1,5 @@ // This is an auto-generated file. Any changes made to this file may be overwritten. -// This file was created at: 2024-10-21 15:09:43 +// This file was created at: 2024-10-21 15:50:12 #![allow(dead_code)] use std::fmt::Debug; use std::any::Any; @@ -127,7 +127,7 @@ pub struct FunctionExpr { pub lparen: Token, pub params: Vec<(Token, Option)>, pub return_type: Option, - pub body: Vec, + pub body: BlockExpr, pub rbrace: Token, } diff --git a/src/compiler.rs b/src/compiler.rs index 5f6e9d4..7893ea9 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -943,13 +943,18 @@ impl ExprVisitor for Compiler<'_> { } // compile body - for stmt in &expr.body { + for stmt in &expr.body.stmts { self.compile_stmt(stmt)?; } - // always end with a "return nil" - let nil = self.insert_constant(Nil::create())?; - self.emit(end_line, Op::PushConstant(nil)); + // compile the last expression in the block and compile that as the return value + if let Some(expr) = expr.body.return_expr.as_ref() { + self.compile_expr(expr)?; + } else { + // otherwise end with a "return nil" + let nil = self.insert_constant(Nil::create())?; + self.emit(end_line, Op::PushConstant(nil)); + } self.emit(end_line, Op::Return); self.end_scope(end_line); diff --git a/src/compiler/visitors.rs b/src/compiler/visitors.rs index 987ff57..413101c 100644 --- a/src/compiler/visitors.rs +++ b/src/compiler/visitors.rs @@ -165,11 +165,14 @@ pub(super) struct LocalAssignCollector { } impl LocalAssignCollector { - pub fn collect(body: &Vec) -> HashSet { + pub fn collect(block: &BlockExpr) -> HashSet { let mut collector = Self::default(); - for stmt in body { + for stmt in &block.stmts { stmt.accept(&mut collector).unwrap(); } + if let Some(expr) = block.return_expr.as_ref() { + expr.accept(&mut collector).unwrap(); + } collector.names } } @@ -319,11 +322,14 @@ pub(super) struct LocalNameCollector { } impl LocalNameCollector { - pub fn collect(body: &Vec) -> HashSet { + pub fn collect(block: &BlockExpr) -> HashSet { let mut collector = Self::default(); - for stmt in body { + for stmt in &block.stmts { stmt.accept(&mut collector).unwrap(); } + if let Some(expr) = block.return_expr.as_ref() { + expr.accept(&mut collector).unwrap(); + } collector.names } } diff --git a/src/parser.rs b/src/parser.rs index 534eee7..599118c 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -995,7 +995,7 @@ impl Parser { } self.expect("expect '{' after function signature", TokenKind::LBrace)?; - let body = self.block()?; + let body = self.block_expr()?; let rbrace = self.prev.clone().unwrap(); Ok(Box::new(FunctionExpr { diff --git a/tools/genast.py b/tools/genast.py index 7eff05e..a6d1dd9 100755 --- a/tools/genast.py +++ b/tools/genast.py @@ -243,7 +243,7 @@ GENERATE = [ "lparen: Token", "params: Vec<(Token, Option)>", "return_type: Option", - "body: Vec", + "body: BlockExpr", "rbrace: Token", ], )