diff --git a/src/ast.rs b/src/ast.rs index ab94427e471898fc233a2268e3b9ed0f3cfad7b4..b56d136e09385a31dfd2184c700a82b0c36fb98f 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -5,14 +5,18 @@ pub use stmt::{*}; pub use exp::{*}; pub use decl::{*}; // AST for CompUnit -/// CompUnit ::= FuncDef; +/// CompUnit ::= [CompUnit] (Decl | FuncDef); #[derive(Debug)] pub struct CompUnit { - pub func_def: Vec<FuncDef>, + pub comp_defs: Vec<CompDef>, } - +#[derive(Debug)] +pub enum CompDef { + FuncDef(FuncDef), + Decl(Decl) +} /// FuncDef ::= FuncType IDENT "(" [FuncFParams] ")" Block; diff --git a/src/codegen/asmwriter.rs b/src/codegen/asmwriter.rs index 1021b65679773d5f8029ed53e01d93fa2a157cf1..48c6dc6303f48d818ff9bad14e0c39474d5bb438 100644 --- a/src/codegen/asmwriter.rs +++ b/src/codegen/asmwriter.rs @@ -66,6 +66,12 @@ impl AsmWriter { } pub fn load(&self, f: &mut File, context: &mut ProgramContext, value : &Value, tmp: &str) -> CResult<()> { + if let Some(v) = context.search_global_var(value) { + writeln!(f, "{SPACE}la {}, {}", tmp, v); + writeln!(f, "{SPACE}lw {}, 0({})", tmp, tmp); + return Ok(()); + } + match context.get_value_data(value).kind() { ValueKind::Integer(v) => { writeln!(f,"{SPACE}li {}, {}", tmp, v.value())?; @@ -85,6 +91,11 @@ impl AsmWriter { Ok(()) } pub fn store(&self, f: &mut File, context: &mut ProgramContext, value : &Value, tmp: &str) -> CResult<()> { + if let Some(v) = context.search_global_var(value) { + writeln!(f, "la t3, {}", v); + writeln!(f, "sw {}, 0(t3)", tmp); + return Ok(()); + } let pos = context.get_value_position(value)?; match pos { FuncVar::Stack(p) => { diff --git a/src/codegen/context.rs b/src/codegen/context.rs index ec883445967b8a65abe3cc1ef7c7490ea657a8b2..2f49d5a4cda81ed6aea652accb8e73bdb33e8f7d 100644 --- a/src/codegen/context.rs +++ b/src/codegen/context.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use koopa::ir::{Program, BasicBlock, Value, entities::ValueData, Function}; use super::{func::{FunctionHandler,FuncVar}, CResult}; @@ -8,9 +10,10 @@ macro_rules! function_handler { }; } pub struct ProgramContext<'p> { - program: &'p Program, + pub program: &'p Program, pub cur_func : Option<FunctionHandler>, pub func : Option<Function>, + pub global_var : HashMap<Value, String>, function_cnt : usize, } @@ -21,6 +24,7 @@ impl<'p> ProgramContext<'p> { program, cur_func: None, func : None, + global_var : HashMap::new(), function_cnt : 0 } } @@ -28,6 +32,14 @@ impl<'p> ProgramContext<'p> { self.program } + pub fn add_global_var(&mut self, value : Value, name: &str) { + self.global_var.insert(value, name.into()); + } + + pub fn search_global_var(&mut self, value: &Value) -> Option<&str> { + self.global_var.get(value).map(|x| x.as_str()) + } + /// get function handler pub fn get_func_handler(&'p mut self) -> Option<&mut FunctionHandler> { self.cur_func.as_mut() diff --git a/src/codegen/gen.rs b/src/codegen/gen.rs index 2f4621b6ebd5460aaa33a117de7d1ac551ca787f..42a70f5675190b296818f5ba45cc283212de30c7 100644 --- a/src/codegen/gen.rs +++ b/src/codegen/gen.rs @@ -8,6 +8,7 @@ use super::{CResult}; use super::context::ProgramContext; use super::func::FunctionHandler; use std::fs::File; +use std::io::Write; use std::cmp; // A unified trait for all the memory structure in Program @@ -22,8 +23,17 @@ impl<'p> GenerateAsm<'p> for Program { type Out = (); fn generate_asm(&self, f : &'p mut File, context : &'p mut ProgramContext) -> CResult<Self::Out> { - - + // generate global allocation + for &value in self.inst_layout() { + let data = self.borrow_value(value); + let name = &data.name().as_ref().unwrap()[1..]; + context.add_global_var(value, name); + writeln!(f, " .data")?; + writeln!(f, " .globl {}",name)?; + writeln!(f, "{}:", name)?; + data.generate_asm(f, context, &value)?; + writeln!(f)?; + } // generate function for &func in self.func_layout() { context.func = Some(func); diff --git a/src/codegen/gen/valuegen.rs b/src/codegen/gen/valuegen.rs index 07f71480be7285405a89accb3e75f162470c2571..32deff865a57011688ecfd4034c4cd161e39215d 100644 --- a/src/codegen/gen/valuegen.rs +++ b/src/codegen/gen/valuegen.rs @@ -9,27 +9,9 @@ use crate::codegen::CResult; #[allow(unused_imports)] use super::GenerateAsm; use std::fs::File; +use std::io::Write; - -/* -impl GenerateAsm for Return { - type Out = (); - fn generate_asm(&self, f : &mut File, handler : &mut ProgramContext) -> crate::codegen::Result<Self::Out> { - match self.value() { - Some(v) => { - - writeln!(f," li a0, {}", 0)?; - } - None => () - }; - - writeln!(f," ret")?; - Ok(()) - } -} -*/ - pub trait GenerateAsmValue<'p> { type Out; fn generate_asm(&self, f : &'p mut File, context : &'p mut ProgramContext, value : &Value) -> CResult<Self::Out>; @@ -45,6 +27,7 @@ impl<'p> GenerateAsmValue<'p> for ValueData { ValueKind::Branch(v) => v.generate_asm(f, context, value), ValueKind::Binary(v) => v.generate_asm(f, context, value), ValueKind::Call(v) => v.generate_asm(f, context, value), + ValueKind::GlobalAlloc(v) => v.generate_asm(f, context, value), /* ValueKind::Binary(v) => v.generate(f, info, self), @@ -56,7 +39,22 @@ impl<'p> GenerateAsmValue<'p> for ValueData { } } +impl<'p> GenerateAsmValue<'p> for GlobalAlloc { + type Out = (); + fn generate_asm(&self, f : &'p mut File, context : &'p mut ProgramContext, _value : &Value) -> CResult<Self::Out> { + match context.program.borrow_value(self.init()).kind() { + ValueKind::Integer(a) => { + writeln!(f, " .word {}", a.value())?; + }, + ValueKind::ZeroInit(_z) => { + writeln!(f, " .zero 4")?; + }, + _ => unreachable!() + }; + Ok(()) + } +} impl<'p> GenerateAsmValue<'p> for Jump { type Out = (); diff --git a/src/irgen.rs b/src/irgen.rs index d31074043e0b90eb3bd9ed28e9df6596db5edeec..f5e649d13d8981a52d51874ec1b973b2a4664b89 100644 --- a/src/irgen.rs +++ b/src/irgen.rs @@ -2,6 +2,7 @@ mod gen; //mod _func; mod func; mod scopes; +mod constcalc; use crate::ast::CompUnit; use gen::GenerateIR; use koopa::ir::Program; @@ -18,6 +19,8 @@ pub enum IRError { AdvancedEvaluation(String), VoidValue, UndefinedLVal(String), + EvaluateConstWithCall, + EvaluateConstWithVar, } @@ -27,7 +30,9 @@ impl fmt::Display for IRError { Self::VoidValue => write!(f,"use void value in an expression"), Self::AdvancedEvaluation(s) => write!(f, "wrong when evaluate binary operator: {}", s), Self::UndefinedLVal(s) => write!(f, "{} is undefined", s), - Self::NotMemory => write!(f, "store val in a place not memory") + Self::NotMemory => write!(f, "store val in a place not memory"), + Self::EvaluateConstWithCall => write!(f, "can not use function call in const variable defination"), + Self::EvaluateConstWithVar => write!(f, "can not use variable in const variable defination") } } } diff --git a/src/irgen/constcalc.rs b/src/irgen/constcalc.rs new file mode 100644 index 0000000000000000000000000000000000000000..1e15ecc42eb20c2bc74eabb36c05a5466f788460 --- /dev/null +++ b/src/irgen/constcalc.rs @@ -0,0 +1,153 @@ +use crate::ast::*; + +use crate::irgen::scopes::Scopes; +use crate::irgen::IResult; +use crate::irgen::IRError; + + +use super::scopes::RecValue; + +// just calculate the result to the primitive type : i32 +pub trait PreCalculate<'ast> { + fn calculate(&'ast self, scope :&mut Scopes<'ast>) -> IResult<i32>; +} + +impl<'ast> PreCalculate<'ast> for Exp { + fn calculate(&'ast self, scope :&mut Scopes<'ast>) -> IResult<i32> { + self.lor.calculate(scope) + } +} + +impl<'ast> PreCalculate<'ast> for LOrExp { + fn calculate(&'ast self, scope :&mut Scopes<'ast>) -> IResult<i32> { + match self { + Self::LAndAusdruck(a) => a.calculate(scope), + Self::LOrAusdruck(lhs, rhs) => { + Ok((lhs.calculate(scope)? != 0 || rhs.calculate(scope)? != 0) as i32) + } + } + } +} + +impl<'ast> PreCalculate<'ast> for LAndExp { + fn calculate(&'ast self, scope :&mut Scopes<'ast>) -> IResult<i32> { + match self { + Self::EqAusdruck(a) => a.calculate(scope), + Self::LAndAusdruck(lhs, rhs) => { + Ok((lhs.calculate(scope)? != 0 && rhs.calculate(scope)? != 0) as i32) + } + } + } +} + +impl<'ast> PreCalculate<'ast> for EqExp { + fn calculate(&'ast self, scope :&mut Scopes<'ast>) -> IResult<i32> { + match self { + Self::RelAusdruck(a) => a.calculate(scope), + Self::EqAusdruck(lhs, op, rhs) => { + let (a,b) = + (lhs.calculate(scope)?, rhs.calculate(scope)?); + + match op { + EqOp::Eq => Ok((a == b) as i32), + EqOp::NotEq => Ok((a != b) as i32) + } + } + } + } +} + +impl<'ast> PreCalculate<'ast> for RelExp { + fn calculate(&'ast self, scope :&mut Scopes<'ast>) -> IResult<i32> { + match self { + Self::AddAusdruck(a) => a.calculate(scope), + Self::RelAusdruck(lhs, op, rhs) => { + let (a, b) = (lhs.calculate(scope)?, rhs.calculate(scope)?); + + match op { + RelOp::Ge => Ok((a >= b) as i32), + RelOp::Gt => Ok((a > b) as i32), + RelOp::Le => Ok((a <= b) as i32), + RelOp::Lt => Ok((a < b) as i32) + } + + } + + } + } +} + +impl<'ast> PreCalculate<'ast> for AddExp { + fn calculate(&'ast self, scope :&mut Scopes<'ast>) -> IResult<i32> { + match self { + Self::MulAusdruck(e) => e.calculate(scope), + Self::AddAusdruck(lhs, op, rhs) => { + let (a,b) = (lhs.calculate(scope)?, rhs.calculate(scope)?); + + match op { + AddOp::Add => Ok(a + b), + AddOp::Sub => Ok(a - b) + } + } + } + } +} + +impl<'ast> PreCalculate<'ast> for MulExp { + fn calculate(&'ast self, scope :&mut Scopes<'ast>) -> IResult<i32> { + match self { + Self::UnaryAusdruck(e) => e.calculate(scope), + Self::MulAusdruck(lhs, op, rhs) => { + let (a, b) = (lhs.calculate(scope)?, rhs.calculate(scope)?); + + match op { + MulOp::Div => Ok(a / b), + MulOp::Mod => Ok(a % b), + MulOp::Mul => Ok(a * b) + } + } + } + } +} + +impl<'ast> PreCalculate<'ast> for UnaryExp { + fn calculate(&'ast self, scope :&mut Scopes<'ast>) -> IResult<i32> { + match self { + Self::PrimaryAusdruck(e) => e.calculate(scope), + Self::Call(_) => Err(IRError::EvaluateConstWithCall), + Self::UnaryAusdruck(op, num) => { + let a = num.calculate(scope)?; + match op { + UnaryOp::LNot => Ok(!(a == 0) as i32), + UnaryOp::Negative => Ok(-a), + UnaryOp::Positive => Ok(a) + } + } + } + } +} + +impl<'ast> PreCalculate<'ast> for PrimaryExp { + fn calculate(&'ast self, scope :&mut Scopes<'ast>) -> IResult<i32> { + match self { + Self::Ausdruck(e) => e.calculate(scope), + Self::LVal(v) => v.calculate(scope), + Self::Number(n) => Ok(*n) + } + } +} + +impl<'ast> PreCalculate<'ast> for LVal { + fn calculate(&'ast self, scope :&mut Scopes<'ast>) -> IResult<i32> { + match scope.retrieve_val(self.id.as_str()) { + Some(val) => { + match val { + RecValue::Const(v) => Ok(v), + RecValue::IrValue(_) => Err(IRError::EvaluateConstWithVar) + } + }, + None => Err(IRError::UndefinedLVal(self.id.clone())) + + } + } +} \ No newline at end of file diff --git a/src/irgen/gen.rs b/src/irgen/gen.rs index d4e8c1febfff469ea6f087743444ec85029967b9..7111e3e029349ba5e6f501964077cbf223732e2d 100644 --- a/src/irgen/gen.rs +++ b/src/irgen/gen.rs @@ -4,6 +4,8 @@ mod declgen; mod stmtgen; mod funcgen; + +pub use expgen::ExpResult; use crate::ast::*; use koopa::ir::{Type}; @@ -36,13 +38,40 @@ impl<'ast> GenerateIR<'ast> for CompUnit { scopes.decl_func("starttime", vec![], Type::get_unit()); scopes.decl_func("stoptime", vec![], Type::get_unit()); - - for func in &self.func_def { - func.function_generate_forepart(scopes)?; - } - for func in &self.func_def { - func.generate(scopes)?; - } + println!("the length of compdefs {}",self.comp_defs.len()); + self.comp_defs + .iter() + .try_for_each(|s| match s { + CompDef::FuncDef(f) => { + //println!("generate function {}",f.ident); + f.function_generate_forepart(scopes) + }, + _ => Ok(()) + } + )?; + // global level + scopes.add_level(); + + // generate all variable first + let _ = self.comp_defs + .iter() + .try_for_each(|s| match s { + CompDef::Decl(d) => { + d.generate(scopes) + }, + _ => Ok(()) + })?; + + self.comp_defs + .iter() + .try_for_each(|s| match s { + CompDef::FuncDef(f) => { + f.generate(scopes) + }, + _ => Ok(()) + })?; + + scopes.minus_level(); Ok(()) } } diff --git a/src/irgen/gen/declgen.rs b/src/irgen/gen/declgen.rs index 141b3900bbce66697aa895d847417a1c05c9fc19..6da74402ae519cb8587d7552d93491c32a11e80c 100644 --- a/src/irgen/gen/declgen.rs +++ b/src/irgen/gen/declgen.rs @@ -1,4 +1,5 @@ use crate::ast::*; +use crate::irgen::constcalc::PreCalculate; use koopa::ir::builder_traits::*; use koopa::ir::{Type}; @@ -35,17 +36,42 @@ impl<'ast> GenerateIR<'ast> for VarDef { type Out = (); fn generate(&'ast self, scopes : &mut Scopes<'ast>) -> IResult<Self::Out> { - - let tar = scopes.create_initial_variable(Type::get_i32(), Some(&self.id)); - scopes.add_variable_name(&self.id, tar); - match &self.init_val { - Some(e) => { - let res = e.generate(scopes)?.into_int(scopes)?; - let store = scopes.new_value().store(res, tar); - scopes.function_push_inst(store); + let value = match scopes.is_global() { + true => { + let alloc_val = + match &self.init_val { + Some(v) => { + let res = v.exp.calculate(scopes)?; + scopes.program.new_value().integer(res) + + }, + None => scopes.program.new_value().zero_init(Type::get_i32()) + }; + let v = scopes + .program + .new_value() + .global_alloc( + alloc_val + ); + scopes.program.set_value_name(v, Some(format!("@{}", self.id))); + v }, - None => () - } + false => { + let tar = scopes.create_initial_variable(Type::get_i32(), Some(&self.id)); + + match &self.init_val { + Some(e) => { + let res = e.generate(scopes)?.into_int(scopes)?; + let store = scopes.new_value().store(res, tar); + scopes.function_push_inst(store); + }, + None => () + } + tar + } + }; + + scopes.add_variable_name(&self.id, value); Ok(()) } } @@ -73,19 +99,15 @@ impl<'ast> GenerateIR<'ast> for ConstDef { fn generate(&'ast self, scopes : &mut Scopes<'ast>) -> IResult<Self::Out> { // a temporary method, treat const as variable - let tar = scopes.create_initial_variable(Type::get_i32(), Some(&self.id)); - scopes.add_variable_name(&self.id, tar); - let res = self.init_val.generate(scopes)?.into_int(scopes)?; - let store = scopes.new_value().store(res, tar); - - scopes.function_push_inst(store); + let v = self.init_val.generate(scopes)?; + scopes.add_const_value_name(self.id.as_str(), v); Ok(()) } } // generate IR for const val impl<'ast> GenerateIR<'ast> for ConstInitVal { - type Out = ExpResult; + type Out = i32; fn generate(&'ast self, scopes : &mut Scopes<'ast>) -> IResult<Self::Out> { self.exp.generate(scopes) diff --git a/src/irgen/gen/expgen.rs b/src/irgen/gen/expgen.rs index e393da5e4cb79db2d57bf83eea100242f7405934..7d877950e86f1dbe524cc8c35dba947dc18b3ae8 100644 --- a/src/irgen/gen/expgen.rs +++ b/src/irgen/gen/expgen.rs @@ -1,9 +1,10 @@ use crate::ast::*; +use crate::irgen::constcalc::PreCalculate; -use koopa::ir::builder_traits::*; +use koopa::ir::{builder_traits::*, TypeKind}; use koopa::ir::{Value, Type, BinaryOp}; -use crate::irgen::scopes::{Scopes}; +use crate::irgen::scopes::{Scopes, RecValue}; use crate::irgen::{IResult, GenerateIR}; use crate::irgen::IRError; use paste::paste; @@ -51,7 +52,24 @@ impl<'ast> GenerateIR<'ast> for LVal { let var = scopes.retrieve_val(&self.id).ok_or(IRError::UndefinedLVal(self.id.clone()))?; - Ok(ExpResult::IntPtr(var)) + + match var { + RecValue::Const(v) => Ok(ExpResult::Int( + scopes.new_value().integer(v) + )), + RecValue::IrValue(v) => { + match scopes.get_value_type(v).kind() { + TypeKind::Pointer(_) => { + Ok(ExpResult::IntPtr(v)) + }, + TypeKind::Array(_, _) => unimplemented!(), + TypeKind::Int32 => { + Ok(ExpResult::Int(v)) + }, + _ => unreachable!() + } + } + } } } @@ -65,10 +83,10 @@ impl<'ast> GenerateIR<'ast> for Exp { impl<'ast> GenerateIR<'ast> for ConstExp { - type Out = ExpResult; + type Out = i32; fn generate(&'ast self, scopes : &mut Scopes<'ast>) -> IResult<Self::Out> { - self.exp.generate(scopes) + self.exp.calculate(scopes) } } @@ -271,93 +289,7 @@ impl<'ast> $trait_name<'ast> for [<$cur Exp>] { scopes.function_push_inst(load_result); Ok(ExpResult::Int(load_result)) - /* - let mut zero: Option<Value> = None; - let mut one: Option<Value> = None; - let mut final_result: Option<Value> = None; - let mut binary_op: Option<BinaryOp> = None; - { - let local_handler = LocalHandler::new(program, scopes); - - // zero and one - zero = Some(local_handler.new_value().integer(0)); - one = Some(local_handler.new_value().integer(1)); - - - // choosee binary operator for land - binary_op = Some(if stringify!($cur) == "LAnd" { - BinaryOp::NotEq - } else { - BinaryOp::Eq - }); - - // generate a initial variable(global in this function) to store the result - // for LAnd, lhs != 0 failed, the result is 0, and we go to end directly - // for LOr, lhs == 0 failed, the result is 1, and we go to end directly - - final_result = Some(local_handler.create_initial_variable(Type::get_i32(), None)); - - let store = if stringify!($cur) == "LAnd" { - local_handler.new_value().store(zero.unwrap(), final_result.unwrap()) - } else { - local_handler.new_value().store(one.unwrap(), final_result.unwrap()) - }; - // 1.push the initial result in current block - local_handler.push_inst(program, store); - } - - - let lhs_result = lhs.generate(program, scopes)?; - - { - let lhs_comp_result = cur_func!(scopes).new_value(program).binary(binary_op, zero, lhs_result); - - // 2.add compare result in current block - cur_func!(scopes).push_inst(program, lhs_comp_result); - - - // For LAnd and LOr - // if lhs is true, we need to test rhs - // or else we go to end block directly - - let next_block = cur_func!(scopes).create_new_block(program, Some(concat!("%", stringify!($cur), "_next").to_string())); - let end_block = cur_func!(scopes).create_new_block(program, Some(concat!("%", stringify!($cur),"_end").to_string())); - - let br = cur_func!(scopes).new_value(program).branch(lhs_comp_result, next_block, end_block); - // 3.add branch to the current block - cur_func!(scopes).push_inst(program, br); - - // 4. add next_block, now next_block is current block - cur_func!(scopes).add_new_block(program, next_block); - } - // 5. calculate right hand side and add instruction in next_block - let rhs_result = rhs.generate(program, scopes)?; - - { - let rhs_comp_result = cur_func!(scopes).new_value(program).binary(binary_op, zero, rhs_result); - - cur_func!(scopes).push_inst(program, rhs_comp_result); - - // 6. store the right hand result in final result - - let store_rhs = cur_func!(scopes).new_value(program).store(rhs_comp_result, final_result); - - cur_func!(scopes).push_inst(program, store_rhs); - - // 7. from next_block jump to the end block - let jump_to_end = cur_func!(scopes).new_value(program).jump(end_block); - - cur_func!(scopes).push_inst(program, jump_to_end); - - // 8. add end_block as current block - cur_func!(scopes).add_new_block(program, end_block); - } - /*// 9. load the final result - let load_result = cur_func!(scopes).new_value(program).load(final_result); - cur_func!(scopes).push_inst(program, load_result);*/ - Ok(ExpResult::IntPtr(final_result.unwrap())) - */ } } diff --git a/src/irgen/scopes.rs b/src/irgen/scopes.rs index ac0bb4cfce9592eedaccca79776fa9449e96bd6c..e61f697dfedf0e9ccb79eabbc315f25ca47126a5 100644 --- a/src/irgen/scopes.rs +++ b/src/irgen/scopes.rs @@ -5,12 +5,17 @@ use std::collections::HashMap; use std::vec::Vec; use super::func::FunctionInfo; +#[derive(Clone)] +pub enum RecValue { + Const(i32), + IrValue(Value) +} // Value: ValueId // Function: FunctionId // both need program to find their entities pub struct Scopes<'ast> { - val_level: Vec<HashMap<&'ast str, Value>>, + val_level: Vec<HashMap<&'ast str, RecValue>>, function_map: HashMap<&'ast str, Function>, pub program: &'ast mut Program, pub cur_func: Option<FunctionInfo>, @@ -92,16 +97,22 @@ impl<'ast> Scopes<'ast> { // get value type from current function pub fn get_value_type(&self, value: Value) -> Type { - self - .program - .func(self.get_func_id()) - .dfg() - .value(value) - .ty() - .clone() + // if the value is the global variable + if value.is_global() { + self.program.borrow_value(value).ty().clone() + } else { + self + .program + .func(self.get_func_id()) + .dfg() + .value(value) + .ty() + .clone() + } } - pub fn retrieve_val(&self, s: &str) -> Option<Value>{ + // symbol table function + pub fn retrieve_val(&self, s: &str) -> Option<RecValue>{ for h in self.val_level.iter().rev() { if let Some(v) = h.get(s) { return Some(v.clone()); @@ -117,6 +128,7 @@ impl<'ast> Scopes<'ast> { .new_value() } + // close entry of a function pub fn close_entry(&mut self, next: BasicBlock) { let jump = self.new_value().jump(next); @@ -193,12 +205,19 @@ impl<'ast> Scopes<'ast> { .basic_block(name) } - // add const val into hash set - pub fn add_variable_name(&mut self, name: &'ast str, val: Value) { + // add const variable into hash set + pub fn add_const_value_name(&mut self, name: &'ast str, val: i32) { + self.val_level + .last_mut() + .unwrap() + .insert(name, RecValue::Const(val)); + } + + pub fn add_variable_name(&mut self, name: &'ast str, val : Value) { self.val_level .last_mut() .unwrap() - .insert(name, val); + .insert(name, RecValue::IrValue(val)); } // declare sysl library function @@ -210,4 +229,10 @@ impl<'ast> Scopes<'ast> { .function_map .insert(name, func); } + + // check if it is the global scope + + pub fn is_global(&self) -> bool { + self.val_level.len() == 1 + } } diff --git a/src/sysy.lalrpop b/src/sysy.lalrpop index ab40a41575c1814e85e458467b50647aad57bd1b..f6e5194f903376308dc1553bb92285252556bd94 100644 --- a/src/sysy.lalrpop +++ b/src/sysy.lalrpop @@ -17,24 +17,28 @@ match { // Full program -pub CompUnit: CompUnit = <func_def : (FuncDef)* > => CompUnit { <> }; +pub CompUnit: CompUnit = <comp_defs : (CompDef)* > => CompUnit { <> }; +CompDef: CompDef = { + FuncDef => CompDef::FuncDef(<>), + Decl => CompDef::Decl(<>) +} + // Declare variable or const Decl : Decl = { ConstDecl => Decl::Const(<>), VarDecl => Decl::Var(<>) } -BType : String = "int" => <>.to_string(); -ConstDecl : ConstDecl = "const" BType <def : ConstDef> <mut defs : ("," <ConstDef>)*> ";"=> { +ConstDecl : ConstDecl = "const" "int" <def : ConstDef> <mut defs : ("," <ConstDef>)*> ";"=> { defs.insert(0, def); ConstDecl{defs} }; -// VarDecl ::= BType VarDef {"," VarDef} ";"; -VarDecl : VarDecl = BType <def : VarDef> <mut defs : ("," <VarDef>)*> ";" => { +// VarDecl ::= "int" VarDef {"," VarDef} ";"; +VarDecl : VarDecl = "int" <def : VarDef> <mut defs : ("," <VarDef>)*> ";" => { defs.insert(0, def); VarDecl{defs} }; @@ -58,27 +62,28 @@ InitVal : InitVal = <exp : Exp> => InitVal {<>}; // Function Define , Parameter and Type FuncFParam : FuncFParam = { - BType <id: Ident> => { + "int" <id: Ident> => { FuncFParam { <> } } } FuncDef: FuncDef = { - <ty: FuncType> <ident : Ident> "(" ")" <block : Block> => { - FuncDef {ty , ident , params : Vec::new(), block} + <head : FuncDefHead> ")" <block : Block> => { + FuncDef {ty : head.0 , ident: head.1 , params : Vec::new(), block} }, - <ty: FuncType> <ident : Ident> "(" + <head : FuncDefHead> <func_param : FuncFParam> <mut func_params : ("," <FuncFParam>)*> ")" <block: Block> => { func_params.insert(0, func_param); - FuncDef {ty , ident, params : func_params, block} + FuncDef {ty: head.0 , ident: head.1 , params : func_params, block} } } -FuncType: FuncType = { - "int" => FuncType::Int, - "void" => FuncType::Void + +FuncDefHead : (FuncType, String) = { + "int" <id: Ident> "(" => (FuncType::Int, id), + "void" <id: Ident> "(" => (FuncType::Void, id) } // Block