diff --git a/examples/crust.rs b/examples/crust.rs index b86dcf20e6727e4a39116b98715f6c09c0ad8324..61af057e3c3a589ab11c12e2539fcfde6083f6f7 100644 --- a/examples/crust.rs +++ b/examples/crust.rs @@ -33,7 +33,8 @@ fn main() -> Result<(), Box<dyn Error>> { match parse_block(Span::new( " { - return 2 + 3 + let abba : i32 = 7; + return 2 + abba } ", )) { @@ -50,6 +51,7 @@ fn main() -> Result<(), Box<dyn Error>> { builder: &builder, module: &module, fn_value_opt: Some(function), + variables: HashMap::new(), //&fpm, }; let res = compiler.compile_block(prog); @@ -74,8 +76,7 @@ pub struct Compiler<'a> { // pub fpm: &'a PassManager<FunctionValue>, pub module: &'a Module, // pub function: &'a Func<'a>, - - // variables: HashMap<String, PointerValue>, + variables: HashMap<String, PointerValue>, fn_value_opt: Option<FunctionValue>, } @@ -94,6 +95,16 @@ impl<'a> Compiler<'a> { fn compile_expr(&self, expr: &SpanExpr) -> IntValue { match expr.1.clone() { + Expr::Id(id) => match self.variables.get(&id) { + Some(var) => { + self.builder.build_load(*var, &id).into_int_value() + } + None => panic!( + "Could not find a matching variable. + {} in {:?}", + id, self.variables + ), + }, Expr::Num(i) => self.context.i32_type().const_int(i as u64, false), Expr::BinOp(op, l, r) => { @@ -109,7 +120,7 @@ impl<'a> Compiler<'a> { } /// Creates a new stack allocation instruction in the entry block of the function. - fn create_entry_block_alloca(&self, name: &str) -> PointerValue { + fn create_entry_block_alloca(&mut self, name: &str) -> PointerValue { let builder = self.context.create_builder(); let entry = self.fn_value().get_first_basic_block().unwrap(); @@ -118,12 +129,13 @@ impl<'a> Compiler<'a> { Some(first_instr) => builder.position_before(&first_instr), None => builder.position_at_end(&entry), } - - builder.build_alloca(self.context.f64_type(), name) + let alloca = builder.build_alloca(self.context.i32_type(), name); + self.variables.insert(name.to_string(), alloca); + alloca } - fn compile_cmd(&self, cmd: &Cmd) -> (InstructionValue, bool) { - println!("{:?}", cmd); + fn compile_cmd(&mut self, cmd: &Cmd) -> (InstructionValue, bool) { + // println!("{:?}", cmd); match cmd { // Cmd::Assign(lexp, rexp) => { // let rval = eval_expr(rexp, mem, venv, fenv); @@ -146,33 +158,22 @@ impl<'a> Compiler<'a> { // } // } // } - // 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::Let(_, id, _, exp) => { + let exp = self.compile_expr(exp); + println!("\n-- let id.fragment {}\n", id.fragment); + let alloca = self.create_entry_block_alloca(id.fragment); + let store = self.builder.build_store(alloca, exp); + (store, false) + } 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 { + pub fn compile_block(&mut self, cmds: Vec<Cmd>) -> InstructionValue { for c in &cmds { let (cmd, ret) = self.compile_cmd(c); if ret { diff --git a/src/parse.rs b/src/parse.rs index 50897e99051e75eef0e7467472988f4acb4d0cd7..4d05e49ba2a35c9d24f75155abbdc7e3f9dff7c6 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -6,7 +6,9 @@ use std::slice::Iter; use nom::{ branch::alt, bytes::complete::tag, - character::complete::{alpha1, alphanumeric0, char, digit1, multispace0, multispace1}, + character::complete::{ + alpha1, alphanumeric0, char, digit1, multispace0, multispace1, + }, combinator::{cut, map, opt}, error::ParseError, multi::{many1, separated_list}, @@ -15,7 +17,8 @@ use nom::{ }; use crate::ast::{ - Block, Cmd, Expr, Func, Item, Mutability, Op, Prog, Span, SpanCmd, SpanExpr, SpanId, Type, + Block, Cmd, Expr, Func, Item, Mutability, Op, Prog, Span, SpanCmd, + SpanExpr, SpanId, Type, }; pub fn parse_i32(i: Span) -> IResult<Span, (Span, i32)> { @@ -55,9 +58,13 @@ pub fn parse_id(i: Span) -> IResult<Span, Span> { // an identifier needs to start with one or more alphas (head) // followed by zero or more alphanumerics (tail) map( - preceded(multispace0, tuple((alpha1, alphanumeric0))), + preceded(multispace0, tuple((alpha1, alphanumeric0, tag("")))), // we concatenate the head and tail into a single String - |(_, _)| i, // head.to_string() + &tail.to_string(), + |(_, _, end): (Span, Span, Span)| { + let mut res = i; + res.fragment = &i.fragment[..(end.offset - i.offset)]; + res + }, )(i) } @@ -67,7 +74,10 @@ fn parse_terminal(i: Span) -> IResult<Span, SpanToken> { map(tag("true"), |s| (s, Token::Bool(true))), map(tag("false"), |s| (s, Token::Bool(false))), map( - tuple((parse_id, parse_par(separated_list(char(','), parse_tokens)))), + tuple(( + parse_id, + parse_par(separated_list(char(','), parse_tokens)), + )), |(s, t)| (s, Token::Call(s.to_string(), t)), ), map(parse_id, |s: Span| (s, Token::Id(s.to_string()))), @@ -103,12 +113,17 @@ fn compute_atom<'a>(t: &mut Peekable<Iter<SpanToken<'a>>>) -> SpanExpr<'a> { .collect(); (*s, Expr::Call(id.to_string(), v)) } - Some((s, Token::Op(op))) => (*s, Expr::UnaryOp(*op, Box::new(climb(t, 4)))), // assume highest precedence + Some((s, Token::Op(op))) => { + (*s, Expr::UnaryOp(*op, Box::new(climb(t, 4)))) + } // assume highest precedence _ => panic!("error in compute atom"), } } -fn climb<'a>(t: &mut Peekable<Iter<SpanToken<'a>>>, min_prec: u8) -> SpanExpr<'a> { +fn climb<'a>( + t: &mut Peekable<Iter<SpanToken<'a>>>, + min_prec: u8, +) -> SpanExpr<'a> { let mut result: SpanExpr = compute_atom(t); loop { @@ -154,7 +169,9 @@ fn parse_if(i: Span) -> IResult<Span, Cmd> { opt(preceded(preceded(multispace0, tag("else")), parse_block)), ))), ), - |(pred, true_branch, maybe_false_branch)| Cmd::If(pred, true_branch, maybe_false_branch), + |(pred, true_branch, maybe_false_branch)| { + Cmd::If(pred, true_branch, maybe_false_branch) + }, )(i) } @@ -307,22 +324,34 @@ fn get_prec(op: &Op) -> (u8, Ass) { } // helpers -fn parse_par<'a, O, F, E>(inner: F) -> impl Fn(Span<'a>) -> IResult<Span<'a>, O, E> +fn parse_par<'a, O, F, E>( + inner: F, +) -> impl Fn(Span<'a>) -> IResult<Span<'a>, O, E> where F: Fn(Span<'a>) -> IResult<Span<'a>, O, E>, E: ParseError<Span<'a>>, { // delimited allows us to split up the input // cut allwos us to consume the input (and prevent backtracking) - delimited(char('('), preceded(multispace0, inner), cut(char(')'))) + delimited( + char('('), + preceded(multispace0, inner), + cut(preceded(multispace0, char(')'))), + ) } -fn parse_sem<'a, O, F, E>(inner: F) -> impl Fn(Span<'a>) -> IResult<Span<'a>, O, E> +fn parse_sem<'a, O, F, E>( + inner: F, +) -> impl Fn(Span<'a>) -> IResult<Span<'a>, O, E> where F: Fn(Span<'a>) -> IResult<Span<'a>, O, E>, E: ParseError<Span<'a>>, { // delimited allows us to split up the input // cut allwos us to consume the input (and prevent backtracking) - delimited(char('{'), preceded(multispace0, inner), cut(char('}'))) + delimited( + char('{'), + preceded(multispace0, inner), + cut(preceded(multispace0, char('}'))), + ) }