diff --git a/examples/fib.zr b/examples/fib.zr
index 37344da..a199d24 100644
--- a/examples/fib.zr
+++ b/examples/fib.zr
@@ -1,4 +1,4 @@
-func main[]
+func main[] : I64
let a: I64 = 0
let b: I64 = 1
diff --git a/src/codegen.rs b/src/codegen.rs
index 778a5ac..73111a1 100644
--- a/src/codegen.rs
+++ b/src/codegen.rs
@@ -16,7 +16,7 @@ impl Env {
pub fn new() -> Env {
Env {
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 {
let offset = self.next_offset;
- self.next_offset += 1;
+ self.next_offset += 8;
self.scopes.last_mut().unwrap().insert(name, Var {
var_type,
stack_offset: offset,
diff --git a/src/codegen_x86_64.rs b/src/codegen_x86_64.rs
index 7a4e719..8b4539c 100644
--- a/src/codegen_x86_64.rs
+++ b/src/codegen_x86_64.rs
@@ -72,7 +72,7 @@ print:
self.compile_expr(env, initializer)?;
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) => {
env.push_scope();
@@ -110,8 +110,14 @@ print:
writeln!(&mut self.output, " jmp {}", begin_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!(return_type.lexeme == "I64");
writeln!(&mut self.output, "global {}", name.lexeme)?;
writeln!(&mut self.output, "{}:", name.lexeme)?;
@@ -222,7 +228,7 @@ print:
writeln!(
&mut self.output,
" mov rax, QWORD [rbp-{}]",
- var.stack_offset * 8
+ var.stack_offset
)?
}
Expr::Assign { name, value } => {
@@ -237,7 +243,7 @@ print:
writeln!(
&mut self.output,
" mov QWORD [rbp-{}], rax",
- var.stack_offset * 8
+ var.stack_offset
)?;
}
Expr::Call {
diff --git a/src/parser.rs b/src/parser.rs
index 1d1e879..5f4b406 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -29,6 +29,7 @@ pub enum Stmt {
Function {
name: Token,
params: Vec,
+ return_type: Token,
body: Box,
},
Return(Expr),
@@ -62,11 +63,16 @@ pub enum Expr {
pub struct Parser {
tokens: Vec,
current: usize,
+ is_inside_function: bool,
}
impl Parser {
pub fn new(tokens: Vec) -> Parser {
- Parser { tokens, current: 0 }
+ Parser {
+ tokens,
+ current: 0,
+ is_inside_function: false,
+ }
}
pub fn parse(mut self) -> Result, Box> {
@@ -78,11 +84,19 @@ impl Parser {
}
fn declaration(&mut self) -> Result> {
+ 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
if self.match_token(&[TokenType::KeywordLet]) {
self.let_declaration()
- } else if self.match_token(&[TokenType::KeywordFunc]) {
- self.func_declaration()
} else {
self.statement()
}
@@ -107,8 +121,19 @@ impl Parser {
}
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()?);
- 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> {