assignment
This commit is contained in:
@@ -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(())
|
||||
}
|
||||
|
||||
@@ -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> {
|
||||
|
||||
Reference in New Issue
Block a user