parse return types, disallow nested functions

This commit is contained in:
2025-05-31 16:12:18 +02:00
parent 2c92cbe0b2
commit f98ca8075d
4 changed files with 42 additions and 11 deletions

View File

@@ -1,4 +1,4 @@
func main[] func main[] : I64
let a: I64 = 0 let a: I64 = 0
let b: I64 = 1 let b: I64 = 1

View File

@@ -16,7 +16,7 @@ impl Env {
pub fn new() -> Env { pub fn new() -> Env {
Env { Env {
scopes: vec![HashMap::new()], scopes: vec![HashMap::new()],
next_offset: 1, next_offset: 8,
} }
} }
@@ -30,7 +30,7 @@ impl Env {
pub fn define_var(&mut self, name: String, var_type: String) -> usize { pub fn define_var(&mut self, name: String, var_type: String) -> usize {
let offset = self.next_offset; let offset = self.next_offset;
self.next_offset += 1; self.next_offset += 8;
self.scopes.last_mut().unwrap().insert(name, Var { self.scopes.last_mut().unwrap().insert(name, Var {
var_type, var_type,
stack_offset: offset, stack_offset: offset,

View File

@@ -72,7 +72,7 @@ print:
self.compile_expr(env, initializer)?; self.compile_expr(env, initializer)?;
let offset = env.define_var(name.lexeme.clone(), var_type.lexeme); let offset = env.define_var(name.lexeme.clone(), var_type.lexeme);
writeln!(&mut self.output, " mov QWORD [rbp-{}], rax", offset * 8)?; writeln!(&mut self.output, " mov QWORD [rbp-{}], rax", offset)?;
} }
Stmt::Block(statements) => { Stmt::Block(statements) => {
env.push_scope(); env.push_scope();
@@ -110,8 +110,14 @@ print:
writeln!(&mut self.output, " jmp {}", begin_label)?; writeln!(&mut self.output, " jmp {}", begin_label)?;
writeln!(&mut self.output, "{}:", end_label)?; writeln!(&mut self.output, "{}:", end_label)?;
} }
Stmt::Function { name, params, body } => { Stmt::Function {
name,
params,
return_type,
body,
} => {
assert!(params.is_empty()); // TODO assert!(params.is_empty()); // TODO
assert!(return_type.lexeme == "I64");
writeln!(&mut self.output, "global {}", name.lexeme)?; writeln!(&mut self.output, "global {}", name.lexeme)?;
writeln!(&mut self.output, "{}:", name.lexeme)?; writeln!(&mut self.output, "{}:", name.lexeme)?;
@@ -222,7 +228,7 @@ print:
writeln!( writeln!(
&mut self.output, &mut self.output,
" mov rax, QWORD [rbp-{}]", " mov rax, QWORD [rbp-{}]",
var.stack_offset * 8 var.stack_offset
)? )?
} }
Expr::Assign { name, value } => { Expr::Assign { name, value } => {
@@ -237,7 +243,7 @@ print:
writeln!( writeln!(
&mut self.output, &mut self.output,
" mov QWORD [rbp-{}], rax", " mov QWORD [rbp-{}], rax",
var.stack_offset * 8 var.stack_offset
)?; )?;
} }
Expr::Call { Expr::Call {

View File

@@ -29,6 +29,7 @@ pub enum Stmt {
Function { Function {
name: Token, name: Token,
params: Vec<Param>, params: Vec<Param>,
return_type: Token,
body: Box<Stmt>, body: Box<Stmt>,
}, },
Return(Expr), Return(Expr),
@@ -62,11 +63,16 @@ pub enum Expr {
pub struct Parser { pub struct Parser {
tokens: Vec<Token>, tokens: Vec<Token>,
current: usize, current: usize,
is_inside_function: bool,
} }
impl Parser { impl Parser {
pub fn new(tokens: Vec<Token>) -> Parser { pub fn new(tokens: Vec<Token>) -> Parser {
Parser { tokens, current: 0 } Parser {
tokens,
current: 0,
is_inside_function: false,
}
} }
pub fn parse(mut self) -> Result<Vec<Stmt>, Box<dyn Error>> { pub fn parse(mut self) -> Result<Vec<Stmt>, Box<dyn Error>> {
@@ -78,11 +84,19 @@ impl Parser {
} }
fn declaration(&mut self) -> Result<Stmt, Box<dyn Error>> { fn declaration(&mut self) -> Result<Stmt, Box<dyn Error>> {
if !self.is_inside_function {
if self.match_token(&[TokenType::KeywordFunc]) {
return self.func_declaration();
}
return error!(
self.peek().loc,
"statements not allowed outside function body"
);
}
// TODO: synchronization after parse error // TODO: synchronization after parse error
if self.match_token(&[TokenType::KeywordLet]) { if self.match_token(&[TokenType::KeywordLet]) {
self.let_declaration() self.let_declaration()
} else if self.match_token(&[TokenType::KeywordFunc]) {
self.func_declaration()
} else { } else {
self.statement() self.statement()
} }
@@ -107,8 +121,19 @@ impl Parser {
} }
self.consume(TokenType::RightBracket, "expected ']' after arguments")?; self.consume(TokenType::RightBracket, "expected ']' after arguments")?;
self.consume(TokenType::Colon, "expected ':' after '['")?;
let return_type = self.consume(TokenType::Identifier, "expected return type")?;
self.is_inside_function = true;
let body = Box::new(self.block()?); let body = Box::new(self.block()?);
Ok(Stmt::Function { name, params, body }) self.is_inside_function = false;
Ok(Stmt::Function {
name,
params,
return_type,
body,
})
} }
fn let_declaration(&mut self) -> Result<Stmt, Box<dyn Error>> { fn let_declaration(&mut self) -> Result<Stmt, Box<dyn Error>> {