assignment

This commit is contained in:
2025-05-29 19:59:34 +02:00
parent 0c38b0b6a0
commit 01cc38f31d
3 changed files with 49 additions and 6 deletions

View File

@@ -2,11 +2,11 @@ use std::{collections::HashMap, error::Error, fmt::Write};
use crate::{ use crate::{
parser::{Expr, Stmt}, parser::{Expr, Stmt},
tokenizer::TokenType, tokenizer::{MotError, TokenType, error},
}; };
pub struct Env { pub struct Env {
locals: HashMap<String, i32>, locals: HashMap<String, usize>,
} }
impl Env { impl Env {
@@ -79,7 +79,7 @@ section .note.GNU-stack
} }
Stmt::Var { name, initializer } => { Stmt::Var { name, initializer } => {
self.compile_expr(env, initializer)?; self.compile_expr(env, initializer)?;
let offset = (env.locals.len() as i32 + 1) * 8; let offset = (env.locals.len() + 1) * 8;
env.locals.insert(name.lexeme, offset); env.locals.insert(name.lexeme, offset);
writeln!(&mut self.output, " mov QWORD [rbp-{}], rax", offset)?; writeln!(&mut self.output, " mov QWORD [rbp-{}], rax", offset)?;
} }
@@ -136,10 +136,24 @@ section .note.GNU-stack
} }
} }
Expr::Variable(name) => { Expr::Variable(name) => {
// TODO: handle error let offset = match env.locals.get(&name.lexeme) {
let offset = env.locals.get(&name.lexeme).unwrap(); 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-{}]", offset)?
} }
Expr::Assign { name, value } => {
self.compile_expr(env, *value)?;
let offset = 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)?;
}
} }
Ok(()) Ok(())
} }

View File

@@ -21,6 +21,10 @@ pub enum Expr {
right: Box<Expr>, right: Box<Expr>,
}, },
Variable(Token), Variable(Token),
Assign {
name: Token,
value: Box<Expr>,
},
} }
pub struct Parser { pub struct Parser {
@@ -66,7 +70,26 @@ impl Parser {
} }
fn expression(&mut self) -> Result<Expr, MotError> { fn expression(&mut self) -> Result<Expr, MotError> {
self.equality() self.assignment()
}
fn assignment(&mut self) -> Result<Expr, MotError> {
let expr = self.equality()?;
if self.match_token(&[TokenType::Equal]) {
let equals = self.previous().clone();
let value = self.assignment()?;
return match expr {
Expr::Variable(name) => Ok(Expr::Assign {
name,
value: Box::new(value),
}),
_ => return error!(equals.loc, "invalid assignment target"),
};
}
Ok(expr)
} }
fn equality(&mut self) -> Result<Expr, MotError> { fn equality(&mut self) -> Result<Expr, MotError> {

6
test.mot Normal file
View File

@@ -0,0 +1,6 @@
let a = 5
let b = 7
print(b - a)
a = 4
print(b - a)
print(b)