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::{
parser::{Expr, Stmt},
tokenizer::TokenType,
tokenizer::{MotError, TokenType, error},
};
pub struct Env {
locals: HashMap<String, i32>,
locals: HashMap<String, usize>,
}
impl Env {
@@ -79,7 +79,7 @@ section .note.GNU-stack
}
Stmt::Var { name, 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);
writeln!(&mut self.output, " mov QWORD [rbp-{}], rax", offset)?;
}
@@ -136,10 +136,24 @@ section .note.GNU-stack
}
}
Expr::Variable(name) => {
// TODO: handle error
let offset = env.locals.get(&name.lexeme).unwrap();
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 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(())
}

View File

@@ -21,6 +21,10 @@ pub enum Expr {
right: Box<Expr>,
},
Variable(Token),
Assign {
name: Token,
value: Box<Expr>,
},
}
pub struct Parser {
@@ -66,7 +70,26 @@ impl Parser {
}
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> {