diff --git a/src/codegen.rs b/src/codegen.rs index 836cb07..fc6ee65 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use std::collections::{hash_map, HashMap}; use crate::{ llvm_ir::{IRBlock, IRModule, Value, ValueType}, @@ -8,21 +8,46 @@ use crate::{ }, }; +pub struct Scope<'a> { + pub block: IRBlock<'a>, + named_vars: HashMap, +} + +impl<'a> Scope<'a> { + pub fn from(block: IRBlock<'a>) -> Self { + Scope { + block, + named_vars: HashMap::new(), + } + } + + pub fn get(&self, name: &String) -> Option<&Value> { + self.named_vars.get(name) + } + + pub fn set(&mut self, name: String, val: Value) -> Result<(), ()> { + if let hash_map::Entry::Vacant(e) = self.named_vars.entry(name) { + e.insert(val); + Ok(()) + } else { + Err(()) // TODO! Error Handling! + } + } +} + pub fn codegen(statements: Vec) { let mut c = IRModule::new(); for statement in statements { match statement { TopLevelStatement::FunctionDefinition(FunctionDefinition(sig, block)) => { - let mut named_vars: HashMap = HashMap::new(); - let func = c.create_func(sig.name, ValueType::I32); - let mut c_block = c.create_block(); + let mut scope = Scope::from(c.create_block()); for stmt in block.0 { match stmt { BlockLevelStatement::Let(let_statement) => { - let value = codegen_exp(&mut c_block, &named_vars, let_statement.1); - named_vars.insert(let_statement.0, value); + let value = codegen_exp(&mut scope, let_statement.1); + scope.set(let_statement.0, value).unwrap(); } BlockLevelStatement::Return(_) => panic!("Should never exist!"), BlockLevelStatement::Import(_) => {} @@ -31,35 +56,31 @@ pub fn codegen(statements: Vec) { } let value = if let Some(exp) = block.1 { - codegen_exp(&mut c_block, &named_vars, exp) + codegen_exp(&mut scope, exp) } else { - c_block.get_const(&Literal::I32(0)) + scope.block.get_const(&Literal::I32(0)) }; - func.add_definition(value, c_block); + func.add_definition(value, scope.block); } TopLevelStatement::Import(_) => {} } } } -fn codegen_exp( - c_block: &mut IRBlock, - named_vars: &HashMap, - expression: Expression, -) -> Value { +fn codegen_exp(scope: &mut Scope, expression: Expression) -> Value { use Expression::*; match expression { Binop(op, lhs, rhs) => match op { BinaryOperator::Add => { - let lhs = codegen_exp(c_block, named_vars, *lhs); - let rhs = codegen_exp(c_block, named_vars, *rhs); - c_block.add(lhs, rhs).unwrap() + let lhs = codegen_exp(scope, *lhs); + let rhs = codegen_exp(scope, *rhs); + scope.block.add(lhs, rhs).unwrap() } BinaryOperator::Mult => panic!("Not implemented!"), }, BlockExpr(_) => panic!("Not implemented!"), FunctionCall(_) => panic!("Not implemented!"), - VariableName(name) => named_vars.get(&name).cloned().unwrap(), - Literal(lit) => c_block.get_const(&lit), + VariableName(name) => scope.get(&name).cloned().unwrap(), + Literal(lit) => scope.block.get_const(&lit), } }