diff --git a/src/codegen.rs b/src/codegen.rs index f6984ef..33a6206 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -5,8 +5,13 @@ use crate::{ tokenizer::{MotError, TokenType, error}, }; +struct Var { + var_type: String, + stack_offset: usize, +} + pub struct Env { - locals: HashMap, + locals: HashMap, } impl Env { @@ -77,10 +82,20 @@ section .note.GNU-stack call printf" )?; } - Stmt::Var { name, initializer } => { + Stmt::Var { + name, + var_type, + initializer, + } => { + // TODO + assert!(var_type.lexeme == "I64"); + self.compile_expr(env, initializer)?; let offset = (env.locals.len() + 1) * 8; - env.locals.insert(name.lexeme, offset); + env.locals.insert(name.lexeme, Var { + var_type: var_type.lexeme, + stack_offset: offset, + }); writeln!(&mut self.output, " mov QWORD [rbp-{}], rax", offset)?; } Stmt::Block(statements) => { @@ -151,23 +166,31 @@ section .note.GNU-stack } } Expr::Variable(name) => { - let offset = match env.locals.get(&name.lexeme) { + let var = match env.locals.get(&name.lexeme) { Some(x) => x, None => { return error!(name.loc, format!("undefined variable: {}", &name.lexeme)); } }; - writeln!(&mut self.output, " mov rax, QWORD [rbp-{}]", offset)? + writeln!( + &mut self.output, + " mov rax, QWORD [rbp-{}]", + var.stack_offset + )? } Expr::Assign { name, value } => { self.compile_expr(env, *value)?; - let offset = match env.locals.get(&name.lexeme) { + let var = match env.locals.get(&name.lexeme) { Some(x) => x, None => { return error!(name.loc, format!("undefined variable: {}", &name.lexeme)); } }; - writeln!(&mut self.output, " mov QWORD [rbp-{}], rax", offset)?; + writeln!( + &mut self.output, + " mov QWORD [rbp-{}], rax", + var.stack_offset + )?; } } Ok(()) diff --git a/src/parser.rs b/src/parser.rs index 42e96d2..080330b 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -8,6 +8,7 @@ pub enum Stmt { Print(Expr), Var { name: Token, + var_type: Token, initializer: Expr, }, Block(Vec), @@ -71,9 +72,15 @@ impl Parser { fn let_declaration(&mut self) -> Result> { let name = self.consume(TokenType::Identifier, "expected variable name")?; - self.consume(TokenType::Equal, "expected '=' after variable name")?; + self.consume(TokenType::Colon, "expected ':' after variable name")?; + let var_type = self.consume(TokenType::Identifier, "expected variable type")?; + self.consume(TokenType::Equal, "expected '=' after variable type")?; let initializer = self.expression()?; - Ok(Stmt::Var { name, initializer }) + Ok(Stmt::Var { + name, + var_type, + initializer, + }) } fn block(&mut self) -> Result> { diff --git a/test.mot b/test.mot index f2f9708..3718e7e 100644 --- a/test.mot +++ b/test.mot @@ -1,6 +1,6 @@ -let a = 0 -let b = 1 -let temp = 0 +let a: I64 = 0 +let b: I64 = 1 +let temp: I64 = 0 while a < 10000 print a