Skip to content
Snippets Groups Projects
Commit 97ec6d48 authored by Per's avatar Per
Browse files

block works (to some extent)

parent 134b920c
No related branches found
No related tags found
No related merge requests found
......@@ -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 {
......
......@@ -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('}'))),
)
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment