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