From 134b920c133094d65ffdca9cec3f5ce907f665bd Mon Sep 17 00:00:00 2001 From: Per <Per Lindgren> Date: Thu, 10 Oct 2019 15:29:38 +0200 Subject: [PATCH] return command --- examples/crust.rs | 132 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 103 insertions(+), 29 deletions(-) diff --git a/examples/crust.rs b/examples/crust.rs index 917e799..b86dcf2 100644 --- a/examples/crust.rs +++ b/examples/crust.rs @@ -1,5 +1,5 @@ use crust::{ - ast::{Expr, Func, Op, Span, SpanExpr}, + ast::{Block, Cmd, Expr, Func, Op, Span, SpanExpr}, parse::{parse_block, parse_expr}, }; @@ -11,7 +11,8 @@ use inkwell::{ passes::PassManager, types::BasicTypeEnum, values::{ - BasicValueEnum, FloatValue, FunctionValue, IntValue, PointerValue, + BasicValueEnum, FloatValue, FunctionValue, InstructionValue, IntValue, + PointerValue, }, FloatPredicate, OptimizationLevel, }; @@ -29,16 +30,15 @@ fn main() -> Result<(), Box<dyn Error>> { let execution_engine = module.create_jit_execution_engine(OptimizationLevel::None)?; - // match parse_block(Span::new( - // " - // { - // return = 2 + 3; - // } - // ", - // )) - match parse_expr(Span::new("2 + 3")) { - Ok((_, expr)) => { - println!("{:?}", &expr); + match parse_block(Span::new( + " + { + return 2 + 3 + } + ", + )) { + Ok((_, prog)) => { + println!("{:?}", &prog); let u32_type = context.i32_type(); let fn_type = u32_type.fn_type(&[], false); let function = module.add_function("expr", fn_type, None); @@ -49,10 +49,11 @@ fn main() -> Result<(), Box<dyn Error>> { context: &context, builder: &builder, module: &module, + fn_value_opt: Some(function), //&fpm, }; - let res = compiler.compile_expr(&expr); - builder.build_return(Some(&res)); + let res = compiler.compile_block(prog); + // builder.build_return(Some(&res)); let fun_expr: JitFunction<ExprFunc> = unsafe { execution_engine.get_function("expr").ok().unwrap() }; @@ -75,10 +76,22 @@ pub struct Compiler<'a> { // pub function: &'a Func<'a>, // variables: HashMap<String, PointerValue>, - // fn_value_opt: Option<FunctionValue>, + fn_value_opt: Option<FunctionValue>, } impl<'a> Compiler<'a> { + /// Gets a defined function given its name. + #[inline] + fn get_function(&self, name: &str) -> Option<FunctionValue> { + self.module.get_function(name) + } + + /// Returns the `FunctionValue` representing the function being compiled. + #[inline] + fn fn_value(&self) -> FunctionValue { + self.fn_value_opt.unwrap() + } + fn compile_expr(&self, expr: &SpanExpr) -> IntValue { match expr.1.clone() { Expr::Num(i) => self.context.i32_type().const_int(i as u64, false), @@ -87,26 +100,87 @@ impl<'a> Compiler<'a> { let lv = self.compile_expr(&l); let rv = self.compile_expr(&r); match op { - Op::Add => self.builder.build_int_add(lv, rv, "sum") - , - // Op::Sub => lv - rv, - // Op::Mul => lv * rv, - // Op::Div => lv / rv, - // Op::Pow => lv.pow(rv as u32), - _ => unimplemented!(), - } + Op::Add => self.builder.build_int_add(lv, rv, "sum"), + _ => unimplemented!(), + } } - // Expr::UnaryOp(op, e) => { - // let e = eval_expr(&e); - // match op { - // Op::Add => e, - // Op::Sub => -e, - // _ => unimplemented!(), + _ => unimplemented!(), + } + } + + /// Creates a new stack allocation instruction in the entry block of the function. + fn create_entry_block_alloca(&self, name: &str) -> PointerValue { + let builder = self.context.create_builder(); + + let entry = self.fn_value().get_first_basic_block().unwrap(); + + match entry.get_first_instruction() { + Some(first_instr) => builder.position_before(&first_instr), + None => builder.position_at_end(&entry), + } + + builder.build_alloca(self.context.f64_type(), name) + } + + fn compile_cmd(&self, cmd: &Cmd) -> (InstructionValue, bool) { + println!("{:?}", cmd); + match cmd { + // Cmd::Assign(lexp, rexp) => { + // let rval = eval_expr(rexp, mem, venv, fenv); + // println!("val {:?}", rval); + // let addr = eval_lvalue(lexp, mem, venv, fenv); + // // println!("lval {:?}", lval); + // // let addr = venv.get(&lval).unwrap(); + + // mem.Menv.insert(addr, rval); + // None + // } + // Cmd::If(exp, then_block, opt_else) => { + // if get_bool(eval_expr(exp, mem, venv, fenv)) { + // eval_body(then_block.to_vec(), mem, venv, fenv) + // } else { + // if let Some(else_block) = opt_else { + // eval_body(else_block.to_vec(), mem, venv, fenv) + // } else { + // None + // } + // } // } + // Cmd::Let(_, id, _, exp) => { + // let val = eval_expr(exp, stack, fenv); + // println!("val {:?}", val); + + // // let addr = mem.alloc(); // get new allocation slot + // // mem.Menv.insert(addr, val); // write the new value + // // venv.insert(id.to_owned(), addr); + // // dump("after Let", mem, venv); + // None // } + Cmd::Return(exp) => { + let expr = self.compile_expr(exp); + (self.builder.build_return(Some(&expr)), true) + } + // Cmd::While(exp, body) => { + // while get_bool(eval_expr(exp, mem, venv, fenv)) { + // if let Some(retv) = eval_body(body.to_vec(), mem, venv, fenv) { + // return Some(retv); + // } + // } + // None + // } _ => unimplemented!(), } } + + pub fn compile_block(&self, cmds: Vec<Cmd>) -> InstructionValue { + for c in &cmds { + let (cmd, ret) = self.compile_cmd(c); + if ret { + return cmd; + } + } + panic!(); + } } // fn main() { -- GitLab