From ab385d772cf8039705b9633b7181f0a2e9c30996 Mon Sep 17 00:00:00 2001 From: Guilherme Chichanoski Date: Sat, 24 Nov 2018 13:44:19 -0200 Subject: [PATCH 01/19] first version from emit in gen --- src/ast.rs | 24 +- src/gen.rs | 893 ---------------------------------- src/gen/context.rs | 26 + src/gen/emit.rs | 331 +++++++++++++ src/gen/mod.rs | 890 +++++++++++++++++++++++++++++++++ src/{ => gen}/symbol_table.rs | 3 +- src/grammar/mod.lalrpop | 2 +- src/main.rs | 1 - 8 files changed, 1266 insertions(+), 904 deletions(-) delete mode 100644 src/gen.rs create mode 100644 src/gen/context.rs create mode 100644 src/gen/emit.rs create mode 100644 src/gen/mod.rs rename src/{ => gen}/symbol_table.rs (93%) diff --git a/src/ast.rs b/src/ast.rs index 2ce458e..12826ac 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -66,6 +66,13 @@ pub enum Type { Int, Bool, Str, + Void, +} + +impl Default for Type { + fn default() -> Type { + Type::Void + } } #[derive(Clone, PartialEq)] @@ -74,20 +81,20 @@ pub enum Variable { Array(String, Box), } -#[derive(PartialEq)] +#[derive(Clone, PartialEq)] pub enum Decl { Single(String, Type, Option>), Array(String, Type, u64, Option>>), Func(String, Option, Option>, Block), } -#[derive(PartialEq)] +#[derive(Clone, PartialEq)] pub enum FuncParam { Single(String, Type), Array(String, Type), } -#[derive(PartialEq)] +#[derive(Clone, PartialEq)] pub enum Stmt { Attr(Variable, Box), Stop, @@ -101,13 +108,13 @@ pub enum Stmt { For(Box, Box, Box, Block), } -#[derive(PartialEq)] +#[derive(Clone, PartialEq)] pub enum Either { Left(A), Right(B), } -#[derive(PartialEq)] +#[derive(Clone, PartialEq)] pub struct Block { pub decl: Vec, pub commands: Vec>, @@ -198,6 +205,7 @@ impl fmt::Debug for Type { Type::Int => write!(f, "Int"), Type::Bool => write!(f, "Bool"), Type::Str => write!(f, "Str"), + Type::Void => write!(f, "Void"), } } } @@ -357,7 +365,7 @@ impl fmt::Debug for Stmt { Stmt::If(expr, b, _elif, _else) => { write!( f, "(If {:?} then (\n{:width$?})", expr, b, width = width + 1)?; - if _elif.len() == 0 { + if _elif.is_empty() { write!(f, " no elseifs")?; } else { write!(f, " elseifs [")?; @@ -423,7 +431,7 @@ impl fmt::Debug for Block { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let (width, tabs) = get_tabs(f); write!(f, "{tabs}(Block", tabs = tabs)?; - if self.decl.len() == 0 { + if self.decl.is_empty() { write!(f, "\n {tabs}with no decls", tabs = tabs)?; } else { write!(f, "\n {tabs}with decls [", tabs = tabs)?; @@ -438,7 +446,7 @@ impl fmt::Debug for Block { } write!(f, "\n {tabs}]", tabs = tabs)?; } - if self.commands.len() == 0 { + if self.commands.is_empty() { write!(f, " and with no commands\n{tabs})", tabs = tabs) } else { write!(f, " and with commands [")?; diff --git a/src/gen.rs b/src/gen.rs deleted file mode 100644 index 47e2241..0000000 --- a/src/gen.rs +++ /dev/null @@ -1,893 +0,0 @@ -use ast::*; -use llvm::{core::*, prelude::*}; - -use std::{ffi::*, ptr}; -use symbol_table::*; - -macro_rules! c_str { - ($s:expr) => {{ - concat!($s, "\0").as_ptr() as *const i8 - }}; -} - -macro_rules! m_str { - ($s:expr) => {{ - concat!($s, "\0").as_ptr() as *mut i8 - }}; -} - -macro_rules! mm_str { - ($s:expr) => {{ - concat!($s, "\0").as_ptr() as *mut *mut i8 - }}; -} - -macro_rules! as_str { - ($v:ident) => { - CString::new($v.clone()).unwrap().as_ptr() as *const i8 - }; -} - -unsafe fn gen_type(context: LLVMContextRef, t: Option) -> LLVMTypeRef { - match t { - Some(Type::Bool) => LLVMInt1TypeInContext(context), - Some(Type::Int) => LLVMInt64TypeInContext(context), - Some(Type::Str) => panic!("Do not use gen_type with Strings!"), - None => LLVMVoidTypeInContext(context), - } -} - -unsafe fn gen_array_type(context: LLVMContextRef, t: &Type) -> LLVMTypeRef { - match t { - Type::Bool => LLVMPointerType(LLVMInt1TypeInContext(context), 0), - Type::Int => LLVMPointerType(LLVMInt64TypeInContext(context), 0), - Type::Str => panic!("Do not use gen_array_type with Strings!"), - } -} - -unsafe fn flatten_expr( - context: LLVMContextRef, - module: LLVMModuleRef, - symbols: &SymbolTable, - builder: LLVMBuilderRef, - e: Expr, -) -> LLVMValueRef { - let mut v = Vec::new(); - match e { - Expr::Number(n) => { - v.push(LLVMConstInt(gen_type(context, Some(Type::Int)), n, 1)); - } - Expr::Variable(Variable::Single(s)) => { - if let Ok(var) = symbols.get(&s) { - if let Symbol::Variable(mut var) = var { - let tmp = LLVMBuildLoad(builder, var, c_str!("flat")); - v.push(tmp); - } else { - panic!( - "Variable <{:?}> of a type diferent than expected!", - s - ); - } - } else { - panic!("Variable <{:?}> is used but not declared!", s); - } - } - Expr::Variable(Variable::Array(s, e)) => { - if let Ok(var) = symbols.get(&s) { - if let Symbol::ArrayRef(mut var) = var { - let index_flattened = - flatten_expr(context, module, symbols, builder, *e); - let loaded_array_ptr = - LLVMBuildLoad(builder, var, c_str!("loaded_param")); - let arr_at = LLVMBuildInBoundsGEP( - builder, - loaded_array_ptr, - [index_flattened].as_mut_ptr(), - 1, - c_str!("arr"), - ); - v.push(LLVMBuildLoad(builder, arr_at, c_str!("flat"))); - } else if let Symbol::Array(_, mut var) = var { - let flattened = - flatten_expr(context, module, symbols, builder, *e); - let arr_at = LLVMBuildGEP( - builder, - var, - [ - flattened, - LLVMConstInt( - gen_type(context, Some(Type::Int)), - 0, - 1, - ), - ] - .as_mut_ptr(), - 2, - c_str!("arr"), - ); - v.push(LLVMBuildLoad(builder, arr_at, c_str!("flat"))); - } else { - panic!("Variable <{:?}> is used but not declared!", s); - } - } else { - panic!("Variable <{:?}> is used but not declared!", s); - } - } - Expr::True => { - v.push(LLVMConstInt(gen_type(context, Some(Type::Bool)), 1, 1)); - } - Expr::False => { - v.push(LLVMConstInt(gen_type(context, Some(Type::Bool)), 0, 1)); - } - Expr::Op(lhs, op, rhs) => match op { - Opcode::Add => { - let lhs = flatten_expr(context, module, symbols, builder, *lhs); - let rhs = flatten_expr(context, module, symbols, builder, *rhs); - v.push(LLVMBuildAdd(builder, lhs, rhs, c_str!("add"))); - } - Opcode::Sub => { - let lhs = flatten_expr(context, module, symbols, builder, *lhs); - let rhs = flatten_expr(context, module, symbols, builder, *rhs); - v.push(LLVMBuildSub(builder, lhs, rhs, c_str!("sub"))); - } - Opcode::Mul => { - let lhs = flatten_expr(context, module, symbols, builder, *lhs); - let rhs = flatten_expr(context, module, symbols, builder, *rhs); - v.push(LLVMBuildMul(builder, lhs, rhs, c_str!("mul"))); - } - Opcode::Div => { - let lhs = flatten_expr(context, module, symbols, builder, *lhs); - let rhs = flatten_expr(context, module, symbols, builder, *rhs); - v.push(LLVMBuildSDiv(builder, lhs, rhs, c_str!("sdiv"))); - } - Opcode::Mod => { - let lhs = flatten_expr(context, module, symbols, builder, *lhs); - let rhs = flatten_expr(context, module, symbols, builder, *rhs); - v.push(LLVMBuildSRem(builder, lhs, rhs, c_str!("srem"))); - } - Opcode::Lesser - | Opcode::LesserOrEqual - | Opcode::Greater - | Opcode::GreaterOrEqual - | Opcode::Equal - | Opcode::Different => { - let lhs = flatten_expr(context, module, symbols, builder, *lhs); - let rhs = flatten_expr(context, module, symbols, builder, *rhs); - v.push(LLVMBuildICmp( - builder, - op.pred(), - lhs, - rhs, - c_str!("cmp"), - )); - } - Opcode::And => { - let lhs = flatten_expr(context, module, symbols, builder, *lhs); - let rhs = flatten_expr(context, module, symbols, builder, *rhs); - v.push(LLVMBuildAnd(builder, lhs, rhs, c_str!("and"))); - } - Opcode::Or => { - let lhs = flatten_expr(context, module, symbols, builder, *lhs); - let rhs = flatten_expr(context, module, symbols, builder, *rhs); - v.push(LLVMBuildOr(builder, lhs, rhs, c_str!("or"))); - } - _ => panic!("IMPOSSIBURU! Opcode<{:?}> is unary!", op), - }, - Expr::Call(n, None) => { - let called_fn = LLVMGetNamedFunction(module, as_str!(n)); - v.push(LLVMBuildCall( - builder, - called_fn, - [].as_mut_ptr(), - 0, - c_str!("fn_call"), - )); - } - Expr::Right(Opcode::Negative, rhs) => { - let rhs = flatten_expr(context, module, symbols, builder, *rhs); - v.push(LLVMBuildMul( - builder, - LLVMConstInt( - gen_type(context, Some(Type::Int)), - -1i64 as u64, - 1, - ), - rhs, - c_str!("neg"), - )); - } - Expr::Right(Opcode::Not, rhs) => { - let rhs = flatten_expr(context, module, symbols, builder, *rhs); - v.push(LLVMBuildNot(builder, rhs, c_str!("not"))); - } - Expr::Right(o, _) => { - panic!("IMPOSSIBURU! Opcode<{:?}> is binary!", o); - } - _ => println!("uninplemented!"), - } - if let Some(a) = v.last().cloned() { - a - } else { - //panic!("invalid state"); - LLVMConstInt(gen_type(context, Some(Type::Int)), 42, 1) - } -} - -unsafe fn local_add_variable( - context: LLVMContextRef, - module: LLVMModuleRef, - symbols: &mut SymbolTable, - builder: LLVMBuilderRef, - n: &str, - t: Type, - e: Option>, -) { - let t = gen_type(context, Some(t)); - let decl = LLVMBuildAlloca(builder, t, as_str!(n)); - if let Some(e) = e { - let flattened = flatten_expr(context, module, symbols, builder, *e); - LLVMBuildStore(builder, flattened, decl); - } else { - LLVMBuildStore(builder, LLVMConstInt(t, 0, 1), decl); - } - let new_symbol = Symbol::Variable(decl); - symbols.set(&n, new_symbol); -} - -unsafe fn local_add_array( - context: LLVMContextRef, - symbols: &mut SymbolTable, - builder: LLVMBuilderRef, - n: &str, - t: Type, - s: u64, - e: Option>>, -) { - let t = gen_type(context, Some(t)); - let array_type = LLVMArrayType(t, s as u32); - let decl = LLVMBuildArrayAlloca( - builder, - array_type, - LLVMConstInt(t, 0, 1), - as_str!(n), - ); - if let Some(e) = e { - for (i, e) in e.iter().enumerate() { - match **e { - Expr::Number(e) => { - let ptr = LLVMBuildGEP( - builder, - decl, - [ - LLVMConstInt( - gen_type(context, Some(Type::Int)), - i as u64, - 1, - ), - LLVMConstInt( - gen_type(context, Some(Type::Int)), - 0, - 1, - ), - ] - .as_mut_ptr(), - 2, - c_str!("ptr_get"), - ); - LLVMBuildStore(builder, LLVMConstInt(t, e, 1), ptr); - } - Expr::True => { - let ptr = LLVMBuildGEP( - builder, - decl, - [ - LLVMConstInt( - gen_type(context, Some(Type::Int)), - i as u64, - 1, - ), - LLVMConstInt( - gen_type(context, Some(Type::Int)), - 0, - 1, - ), - ] - .as_mut_ptr(), - 2, - c_str!("ptr_get"), - ); - LLVMBuildStore(builder, LLVMConstInt(t, 1, 1), ptr); - } - Expr::False => { - let ptr = LLVMBuildGEP( - builder, - decl, - [ - LLVMConstInt( - gen_type(context, Some(Type::Int)), - i as u64, - 1, - ), - LLVMConstInt( - gen_type(context, Some(Type::Int)), - 0, - 1, - ), - ] - .as_mut_ptr(), - 2, - c_str!("ptr_get"), - ); - LLVMBuildStore(builder, LLVMConstInt(t, 0, 1), ptr); - } - _ => panic!( - "Cannot initialize global value with non-const expresion!" - ), - }; - } - /* - *let mut args = e - * .iter() - * .map(|b| match **b { - * Expr::Number(e) => LLVMConstInt(t, e, 1), - * Expr::True => LLVMConstInt(t, 1, 1), - * Expr::False => LLVMConstInt(t, 0, 1), - * _ => panic!("Cannot initialize global value with non-const expresion!"), - * }) - * .collect::>(); - *let values = LLVMConstArray(t, args.as_mut_ptr(), args.len() as u32); - *LLVMBuildStore(builder, values, decl); - */ - } - let new_symbol = Symbol::Array(s as u32, decl); - - symbols.set(&n, new_symbol); -} - -unsafe fn global_add_func( - context: LLVMContextRef, - module: LLVMModuleRef, - symbols: &mut SymbolTable, - n: &str, - t: Option, // Return Type - a: Option>, - b: Block, -) { - let builder = LLVMCreateBuilderInContext(context); - let t = gen_type(context, t); - let args = if let Some(a) = a { - a.iter() - .map(|p| match p { - FuncParam::Single(n, t) => { - (n.clone(), true, gen_type(context, Some(t.clone()))) - } - FuncParam::Array(n, t) => { - (n.clone(), false, gen_array_type(context, &t.clone())) - } - }) - .collect::>() - } else { - Vec::new() - }; - let function_type = LLVMFunctionType( - t, - args.iter().map(|a| a.2).collect::>().as_mut_ptr(), - args.len() as u32, - 0, - ); - let function = LLVMAddFunction(module, as_str!(n), function_type); - - symbols.initialize_scope(); - - let entry = - LLVMAppendBasicBlockInContext(context, function, c_str!("entry")); - LLVMPositionBuilderAtEnd(builder, entry); - - for (i, e) in args.iter().enumerate() { - if e.1 { - let fn_param = LLVMGetParam(function, i as u32); - let alloced_param = LLVMBuildAlloca(builder, e.2, c_str!("param")); - LLVMBuildStore(builder, fn_param, alloced_param); - let new_symbol = Symbol::Variable(alloced_param); - symbols.set(&e.0, new_symbol); - } else { - let fn_param = LLVMGetParam(function, i as u32); - let alloced_param = LLVMBuildAlloca(builder, e.2, c_str!("param")); - LLVMBuildStore(builder, fn_param, alloced_param); - let new_symbol = Symbol::ArrayRef(alloced_param); - symbols.set(&e.0, new_symbol); - } - } - - let test = LLVMGetNamedFunction(module, c_str!("printf")); - // Stupid way of checking if the function is already defined. - let against = ptr::null::() as *mut _; - if test == against { - LLVMBuildGlobalStringPtr(builder, c_str!("%d"), c_str!("format_int")); - LLVMBuildGlobalStringPtr(builder, c_str!("%s"), c_str!("format_str")); - - let int8_type = LLVMInt8TypeInContext(context); - let int32_type = LLVMInt32TypeInContext(context); - let mut args = [LLVMPointerType(int8_type, 0)]; - let fn_type = LLVMFunctionType(int32_type, args.as_mut_ptr(), 0, 1); - - LLVMAddFunction(module, c_str!("printf"), fn_type); - LLVMAddFunction(module, c_str!("scanf"), fn_type); - } - - gen_decl(context, module, symbols, builder, b.decl, false); - gen_block( - context, module, symbols, builder, function, None, b.commands, - ); - - symbols.kill_scope(); - - LLVMDisposeBuilder(builder); - let new_symbol = Symbol::Func(n.to_string()); - - symbols.set(&n, new_symbol); -} - -unsafe fn gen_decl( - context: LLVMContextRef, - module: LLVMModuleRef, - symbols: &mut SymbolTable, - builder: LLVMBuilderRef, - decl: Vec, - allow_fn: bool, -) { - for i in decl { - match i { - Decl::Single(n, t, e) => { - local_add_variable(context, module, symbols, builder, &n, t, e) - } - Decl::Array(n, t, s, e) => { - local_add_array(context, symbols, builder, &n, t, s, e) - } - Decl::Func(_, _, _, _) => { - if allow_fn { - println!("unimplemented"); - } else { - panic!("Functions are not allowed here!"); - } - } - } - } -} - -unsafe fn build_attr( - context: LLVMContextRef, - module: LLVMModuleRef, - symbols: &SymbolTable, - builder: LLVMBuilderRef, - v: &str, - e: Expr, -) -> Result<(), String> { - if let Ok(var) = symbols.get(&v) { - if let Symbol::Variable(mut var) = var { - let flattened = flatten_expr(context, module, symbols, builder, e); - LLVMBuildStore(builder, flattened, var); - Ok(()) - } else { - Err(format!("Variable <{:?}> is used but not declared!", v)) - } - } else { - Err(format!("Variable <{:?}> is used but not declared!", v)) - } -} - -unsafe fn gen_block( - context: LLVMContextRef, - module: LLVMModuleRef, - symbols: &mut SymbolTable, - builder: LLVMBuilderRef, - parent: LLVMValueRef, - looping: Option<(LLVMBasicBlockRef, LLVMBasicBlockRef)>, - stmts: Vec>, -) { - symbols.initialize_scope(); - - for i in stmts { - match i { - Either::Left(Stmt::Attr(Variable::Single(v), e)) => { - if let Err(s) = - build_attr(context, module, symbols, builder, &v, *e) - { - panic!(s); - } - } - Either::Left(Stmt::Write(vec)) => { - for i in vec { - let flattened = - flatten_expr(context, module, symbols, builder, *i); - let format_str = - LLVMGetNamedGlobal(module, c_str!("format_int")); - let mut printf_args = [format_str, flattened]; - let printf_fn = - LLVMGetNamedFunction(module, c_str!("printf")); - LLVMBuildCall( - builder, - printf_fn, - printf_args.as_mut_ptr(), - 2, - c_str!("write"), - ); - } - } - Either::Left(Stmt::Read(Variable::Single(v))) => { - if let Ok(var) = symbols.get(&v) { - if let Symbol::Variable(mut var) = var { - let format_str = - LLVMGetNamedGlobal(module, c_str!("format_int")); - let mut scanf_args = [format_str, var]; - let scanf_fn = - LLVMGetNamedFunction(module, c_str!("scanf")); - LLVMBuildCall( - builder, - scanf_fn, - scanf_args.as_mut_ptr(), - 2, - c_str!("read"), - ); - } - } - } - Either::Left(Stmt::Read(Variable::Array(v, e))) => { - if let Ok(var) = symbols.get(&v) { - if let Symbol::ArrayRef(mut var) = var { - let flattened = - flatten_expr(context, module, symbols, builder, *e); - let arr_at = LLVMBuildGEP( - builder, - var, - [ - LLVMConstInt( - gen_type(context, Some(Type::Int)), - 0, - 1, - ), - flattened, - ] - .as_mut_ptr(), - 2, - c_str!("arr"), - ); - let format_str = - LLVMGetNamedGlobal(module, c_str!("format_int")); - let mut scanf_args = [format_str, arr_at]; - let scanf_fn = - LLVMGetNamedFunction(module, c_str!("scanf")); - LLVMBuildCall( - builder, - scanf_fn, - scanf_args.as_mut_ptr(), - 2, - c_str!("read"), - ); - } else if let Symbol::Array(_, mut var) = var { - let flattened = - flatten_expr(context, module, symbols, builder, *e); - let arr_at = LLVMBuildGEP( - builder, - var, - [ - LLVMConstInt( - gen_type(context, Some(Type::Int)), - 0, - 1, - ), - flattened, - ] - .as_mut_ptr(), - 2, - c_str!("arr"), - ); - let format_str = - LLVMGetNamedGlobal(module, c_str!("format_int")); - let mut scanf_args = [format_str, arr_at]; - let scanf_fn = - LLVMGetNamedFunction(module, c_str!("scanf")); - LLVMBuildCall( - builder, - scanf_fn, - scanf_args.as_mut_ptr(), - 2, - c_str!("read"), - ); - } - } - } - Either::Left(Stmt::Call(n, None)) => { - let called_fn = LLVMGetNamedFunction(module, as_str!(n)); - LLVMBuildCall( - builder, - called_fn, - [].as_mut_ptr(), - 0, - c_str!(""), - ); - } - Either::Left(Stmt::Skip) => { - if let Some((skip, _)) = looping { - LLVMBuildBr(builder, skip); - } else { - panic!("cannot use skip outside of a loop"); - } - } - Either::Left(Stmt::Stop) => { - if let Some((_, stop)) = looping { - LLVMBuildBr(builder, stop); - } else { - panic!("cannot use skip outside of a loop"); - } - } - Either::Left(Stmt::Return(v)) => { - if let Some(v) = v { - let flattened = - flatten_expr(context, module, symbols, builder, *v); - LLVMBuildRet(builder, flattened); - } else { - LLVMBuildRetVoid(builder); - } - } - Either::Left(Stmt::If(cond, then, else_ifs, None)) => { - let then_block = LLVMAppendBasicBlock(parent, c_str!("then")); - let merge = LLVMAppendBasicBlock(parent, c_str!("merge")); - - let cond = - flatten_expr(context, module, symbols, builder, *cond); - LLVMBuildCondBr(builder, cond, then_block, merge); - - // Build True Branch - LLVMPositionBuilderAtEnd(builder, then_block); - gen_decl(context, module, symbols, builder, then.decl, false); - gen_block( - context, - module, - symbols, - builder, - parent, - looping, - then.commands, - ); - LLVMBuildBr(builder, merge); - - // Build Merge Branch - LLVMPositionBuilderAtEnd(builder, merge); - } - Either::Left(Stmt::If(cond, then, else_ifs, Some(_else))) => { - let then_block = LLVMAppendBasicBlock(parent, c_str!("then")); - let else_block = LLVMAppendBasicBlock(parent, c_str!("else")); - let merge = LLVMAppendBasicBlock(parent, c_str!("merge")); - - let cond = - flatten_expr(context, module, symbols, builder, *cond); - LLVMBuildCondBr(builder, cond, then_block, else_block); - - // Build True Branch - LLVMPositionBuilderAtEnd(builder, then_block); - gen_decl(context, module, symbols, builder, then.decl, false); - gen_block( - context, - module, - symbols, - builder, - parent, - looping, - then.commands, - ); - LLVMBuildBr(builder, merge); - - // Build False Branch - LLVMPositionBuilderAtEnd(builder, else_block); - gen_decl(context, module, symbols, builder, _else.decl, false); - gen_block( - context, - module, - symbols, - builder, - parent, - looping, - _else.commands, - ); - LLVMBuildBr(builder, merge); - - // Build Merge Branch - LLVMPositionBuilderAtEnd(builder, merge); - } - Either::Left(Stmt::For(init, cond, step, block)) => { - let cond_block = - LLVMAppendBasicBlock(parent, c_str!("cond_loop")); - let loop_block = LLVMAppendBasicBlock(parent, c_str!("loop")); - let step_block = LLVMAppendBasicBlock(parent, c_str!("step")); - let exit_block = - LLVMAppendBasicBlock(parent, c_str!("exit_loop")); - - let init = *init; - // Build attribution before entering init_block - if let Stmt::Attr(Variable::Single(v), e) = init { - if let Err(s) = - build_attr(context, module, symbols, builder, &v, *e) - { - panic!(s); - } - } else if let Stmt::Attr(Variable::Array(v, i), e) = init { - println!("uninplemented!"); - } else { - panic!("invalid state"); - } - LLVMBuildBr(builder, cond_block); - - // Build condition inside cond_block - LLVMPositionBuilderAtEnd(builder, cond_block); - let cond = - flatten_expr(context, module, symbols, builder, *cond); - LLVMBuildCondBr(builder, cond, loop_block, exit_block); - - // Position at loop to build loop's instructions - LLVMPositionBuilderAtEnd(builder, loop_block); - gen_decl(context, module, symbols, builder, block.decl, false); - gen_block( - context, - module, - symbols, - builder, - parent, - Some((step_block, exit_block)), - block.commands, - ); - LLVMBuildBr(builder, step_block); - - LLVMPositionBuilderAtEnd(builder, step_block); - // Add step to end of loop block - let step = *step; - if let Stmt::Attr(Variable::Single(v), e) = step { - if let Err(s) = - build_attr(context, module, symbols, builder, &v, *e) - { - panic!(s); - } - } else if let Stmt::Attr(Variable::Array(v, i), e) = step { - println!("uninplemented!"); - } else { - panic!("invalid state"); - } - LLVMBuildBr(builder, cond_block); - - // Continue at exit_loop - LLVMPositionBuilderAtEnd(builder, exit_block); - } - - Either::Left(Stmt::While(cond, block)) => { - let cond_block = - LLVMAppendBasicBlock(parent, c_str!("cond_loop")); - let loop_block = LLVMAppendBasicBlock(parent, c_str!("loop")); - let exit_block = - LLVMAppendBasicBlock(parent, c_str!("exit_loop")); - - LLVMBuildBr(builder, cond_block); - - LLVMPositionBuilderAtEnd(builder, cond_block); - // Build condition inside cond_block - let cond = - flatten_expr(context, module, symbols, builder, *cond); - LLVMBuildCondBr(builder, cond, loop_block, exit_block); - - // Position at loop to build loop's instructions - LLVMPositionBuilderAtEnd(builder, loop_block); - gen_decl(context, module, symbols, builder, block.decl, false); - gen_block( - context, - module, - symbols, - builder, - parent, - Some((cond_block, exit_block)), - block.commands, - ); - LLVMBuildBr(builder, cond_block); - - // Continue at exit_loop - LLVMPositionBuilderAtEnd(builder, exit_block); - } - - Either::Left(_) => println!("uninplemented!"), - Either::Right(b) => { - for i in b.decl { - match i { - Decl::Single(n, t, e) => local_add_variable( - context, module, symbols, builder, &n, t, e, - ), - Decl::Array(n, t, s, e) => local_add_array( - context, symbols, builder, &n, t, s, e, - ), - _ => { - panic!("Cannot declare functions inside functions!") - } - } - } - gen_block( - context, module, symbols, builder, parent, looping, - b.commands, - ) - } - } - } - - symbols.kill_scope(); -} - -unsafe fn global_add_variable( - context: LLVMContextRef, - module: LLVMModuleRef, - symbols: &mut SymbolTable, - n: &str, - t: Type, - e: Option>, -) { - let t = gen_type(context, Some(t)); - let decl = LLVMAddGlobal(module, t, as_str!(n)); - if let Some(e) = e { - let b = *e; - if let Expr::Number(v) = b { - LLVMSetInitializer(decl, LLVMConstInt(t, v as u64, 1)); - } - } else { - panic!("Cannot initialize global value with non-const expresion!"); - } - let new_symbol = Symbol::Variable(decl); - symbols.set(&n, new_symbol); -} - -unsafe fn global_add_array( - context: LLVMContextRef, - module: LLVMModuleRef, - symbols: &mut SymbolTable, - n: &str, - t: Type, - s: u64, - e: Option>>, -) { - let t = gen_type(context, Some(t)); - let array_type = LLVMArrayType(t, s as u32); - let decl = LLVMAddGlobal(module, array_type, as_str!(n)); - if let Some(e) = e { - let mut args = e - .iter() - .map(|b| match **b { - Expr::Number(e) => LLVMConstInt(t, e, 1), - Expr::True => LLVMConstInt(t, 1, 1), - Expr::False => LLVMConstInt(t, 0, 1), - _ => panic!( - "Cannot initialize global value with non-const expresion!" - ), - }) - .collect::>(); - let values = LLVMConstArray(t, args.as_mut_ptr(), args.len() as u32); - LLVMSetInitializer(decl, values); - } - let new_symbol = Symbol::Array(s as u32, decl); - symbols.set(&n, new_symbol); -} - -pub unsafe fn gen(decls: Vec) { - let context = LLVMContextCreate(); - let module = LLVMModuleCreateWithNameInContext(c_str!("program"), context); - let mut symbols = SymbolTable::new(); - for i in decls { - match i { - Decl::Single(n, t, e) => { - global_add_variable(context, module, &mut symbols, &n, t, e) - } - Decl::Array(n, t, s, e) => { - global_add_array(context, module, &mut symbols, &n, t, s, e) - } - Decl::Func(n, t, a, b) => { - global_add_func(context, module, &mut symbols, &n, t, a, b) - } - } - } - LLVMDumpModule(module); - LLVMPrintModuleToFile(module, c_str!("test.ll"), mm_str!("idk")); - LLVMContextDispose(context); -} diff --git a/src/gen/context.rs b/src/gen/context.rs new file mode 100644 index 0000000..f372b06 --- /dev/null +++ b/src/gen/context.rs @@ -0,0 +1,26 @@ +use super::symbol_table::SymbolTable; +use llvm::{core::*, *}; +use std::ffi::CString; + +#[derive(Clone)] +pub struct Context { + pub symbol_table: SymbolTable, + pub module: *mut LLVMModule, + pub context: *mut LLVMContext, + pub builder: *mut LLVMBuilder, + pub actual_function: Option<*mut LLVMValue>, +} + +impl Context { + pub unsafe fn new() -> Context { + let context = LLVMContextCreate(); + + Context { + symbol_table: SymbolTable::new(), + module: LLVMModuleCreateWithName(as_str!("program")), + context, + actual_function: None, + builder: LLVMCreateBuilderInContext(context), + } + } +} diff --git a/src/gen/emit.rs b/src/gen/emit.rs new file mode 100644 index 0000000..7b0fee7 --- /dev/null +++ b/src/gen/emit.rs @@ -0,0 +1,331 @@ +use super::{super::ast::*, context::*, symbol_table::*}; +use llvm::{core::*, *}; +use std::ffi::CString; + +pub trait Emit { + unsafe fn emit(self: &Self, context: &mut Context) -> Result; +} + +impl Emit<*mut LLVMType> for Type { + unsafe fn emit( + self: &Self, + context: &mut Context, + ) -> Result<*mut LLVMType, String> { + match self { + Type::Int => Ok(LLVMInt64TypeInContext(context.context)), + Type::Bool => Ok(LLVMInt1TypeInContext(context.context)), + Type::Void => Ok(LLVMVoidTypeInContext(context.context)), + Type::Str => panic!("Not implemented"), + } + } +} + +impl Emit<*mut LLVMValue> for Variable { + unsafe fn emit( + self: &Self, + context: &mut Context, + ) -> Result<*mut LLVMValue, String> { + let builder = context.builder; + match self { + Variable::Single(identifier) => { + if let Ok(value) = context.symbol_table.get(identifier) { + match value { + Symbol::Variable(value) => Ok(*value), + _ => panic!("Variable type mismatch"), + } + } else { + Err(String::from("variabe not declared")) + } + } + Variable::Array(identifier, expression) => { + if let Ok(value) = context.clone().symbol_table.get(identifier) + { + let index = expression.emit(context).unwrap(); + + match value { + Symbol::ArrayRef(value) | Symbol::Array(_, value) => { + Ok(LLVMBuildInBoundsGEP( + builder, + *value, + [index].as_mut_ptr(), + 1, + as_str!("ptr_value"), + )) + } + _ => Err("Variable type mismatch".to_string()), + } + } else { + Err("Variable not defined".to_string()) + } + } + } + } +} + +impl Emit<*mut LLVMValue> for Expr { + unsafe fn emit( + self: &Self, + context: &mut Context, + ) -> Result<*mut LLVMValue, String> { + match self { + Expr::Number(number) => { + Ok(LLVMConstInt(Type::Int.emit(context).unwrap(), *number, 1)) + } + Expr::True => { + Ok(LLVMConstInt(Type::Bool.emit(context).unwrap(), 1, 1)) + } + Expr::False => { + Ok(LLVMConstInt(Type::Bool.emit(context).unwrap(), 0, 1)) + } + Expr::Variable(var) => { + let ptr_var = var.emit(context).unwrap(); + + Ok(LLVMBuildLoad(context.builder, ptr_var, as_str!("var_load"))) + } + Expr::Call(identifier, params) => { + let builder = context.builder; + if let Ok(function) = + context.clone().symbol_table.get(identifier) + { + match function { + // TODO Put function value in symbols table + Symbol::Func(function) => { + let function = LLVMGetNamedFunction( + context.module, + as_str!(function), + ); + let params = params.clone().unwrap_or_default(); + + Ok(LLVMBuildCall( + builder, + function, + params + .iter() + .map(|param| param.emit(context).unwrap()) + .collect::>() + .as_mut_ptr(), + params.len() as u32, + as_str!("call"), + )) + } + _ => Err("Type mismatch".to_string()), + } + } else { + Err("Identifier not declared".to_string()) + } + } + Expr::Op(lhs, op, rhs) => { + let builder = context.builder; + let lhs = lhs.emit(context).unwrap(); + let rhs = rhs.emit(context).unwrap(); + let value = match op { + Opcode::Add => { + LLVMBuildAdd(builder, lhs, rhs, as_str!("add_result")) + } + Opcode::Sub => { + LLVMBuildSub(builder, lhs, rhs, as_str!("sub_result")) + } + Opcode::Div => { + LLVMBuildUDiv(builder, lhs, rhs, as_str!("div_result")) + } + Opcode::Mul => { + LLVMBuildMul(builder, lhs, rhs, as_str!("mul_result")) + } + Opcode::Mod => panic!("Não encontrei a chamada do modulo"), + _ => panic!("Not implemented"), + }; + Ok(value) + } + Expr::Right(op, expression) => { + let builder = context.builder; + let expression = expression.emit(context).unwrap(); + let value = match op { + Opcode::Not => { + LLVMBuildNot(builder, expression, as_str!("not_result")) + } + Opcode::Negative => LLVMBuildNeg( + builder, + expression, + as_str!("negation_result"), + ), + _ => panic!("Should not do this"), + }; + Ok(value) + } + Expr::Ternary(_, _, _) => panic!("Not implemented yet"), + } + } +} + +impl Emit<()> for Stmt { + unsafe fn emit(self: &Self, context: &mut Context) -> Result<(), String> { + let builder = context.builder; + match self { + Stmt::Attr(var, expression) => { + let ptr_var = var.emit(context).unwrap(); + let expression = expression.emit(context).unwrap(); + + LLVMBuildStore(builder, ptr_var, expression); + Ok(()) + } + _ => panic!("Not implemented"), + } + } +} + +impl Emit<()> for Decl { + unsafe fn emit(self: &Self, context: &mut Context) -> Result<(), String> { + if let Some(_) = context.actual_function { + // When local + let builder = context.builder; + match self { + Decl::Single(identifier, type_of, expression) => { + let ptr_vlr = LLVMBuildAlloca( + builder, + type_of.emit(context).unwrap(), + as_str!(identifier), + ); + context + .symbol_table + .set(identifier, Symbol::Variable(ptr_vlr)); + + if let Some(expression) = expression { + LLVMBuildStore( + builder, + ptr_vlr, + expression.emit(context).unwrap(), + ); + Ok(()) + } else { + Ok(()) + } + } + _ => panic!("Not implemented!"), + } + } else { + // When global + match self { + Decl::Single(identifier, type_of, expression) => { + let decl = LLVMAddGlobal( + context.module, + type_of.emit(context).unwrap(), + as_str!(identifier), + ); + + if let Some(expression) = expression { + LLVMSetInitializer( + decl, + expression.emit(context).unwrap(), + ); + Ok(()) + } else { + Ok(()) + } + } + Decl::Func(identifier, return_type, vec_params, block) => { + let vec_params = vec_params.clone().unwrap_or_default(); + + let mut args = vec_params + .iter() + .map(|param| match param { + FuncParam::Single(_, type_of) => { + type_of.emit(context).unwrap() + } + FuncParam::Array(_, type_of) => { + type_of.emit(context).unwrap() + } + }) + .collect::>(); + + let function_type = LLVMFunctionType( + return_type + .clone() + .unwrap_or_default() + .emit(context) + .unwrap(), + args.as_mut_ptr(), + args.len() as u32, + false as i32, + ); + let function = LLVMAddFunction( + context.module, + as_str!(identifier), + function_type, + ); + + let entry_block = LLVMAppendBasicBlockInContext( + context.context, + function, + as_str!("entry"), + ); + + context.symbol_table.initialize_scope(); + + context.actual_function = Some(function); + LLVMPositionBuilderAtEnd(context.builder, entry_block); + + vec_params.iter().enumerate().for_each(|(index, param)| { + let function_param = + LLVMGetParam(function, index as u32); + + match param { + FuncParam::Single(identifier, type_of) => { + let ptr_vlr = LLVMBuildAlloca( + context.builder, + type_of.emit(context).unwrap(), + as_str!(identifier), + ); + context + .symbol_table + .set(identifier, Symbol::Variable(ptr_vlr)); + + LLVMBuildStore( + context.builder, + ptr_vlr, + function_param, + ); + } + FuncParam::Array(_identifier, _type_of) => { + panic!("Not implemented yet") + } + } + }); + + block.emit(context).unwrap(); + + context.symbol_table.kill_scope(); + + Ok(()) + } + _ => panic!("Not implemented"), + } + } + } +} + +impl Emit<()> for Block { + unsafe fn emit(self: &Self, context: &mut Context) -> Result<(), String> { + context.symbol_table.initialize_scope(); + self.decl + .iter() + .for_each(|decl| decl.emit(context).unwrap()); + + self.commands + .iter() + .for_each(|command| command.emit(context).unwrap()); + context.symbol_table.kill_scope(); + + Ok(()) + } +} + +impl Emit<()> for Either { + unsafe fn emit(self: &Self, context: &mut Context) -> Result<(), String> { + match self { + Either::Left(stmt) => stmt.emit(context).unwrap(), + Either::Right(block) => block.emit(context).unwrap(), + }; + + Ok(()) + } +} diff --git a/src/gen/mod.rs b/src/gen/mod.rs new file mode 100644 index 0000000..6f65a91 --- /dev/null +++ b/src/gen/mod.rs @@ -0,0 +1,890 @@ +use std::ffi::CString; + +#[macro_use] +macro_rules! as_str { + ($s:expr) => { + CString::new($s.clone()).unwrap().as_ptr() + }; +} + +use self::emit::Emit; +use ast::*; +use llvm::core::*; + +mod context; +mod emit; +mod symbol_table; + +//macro_rules! c_str { +// ($s:expr) => {{ +// concat!($s, "\0").as_ptr() as *const i8 +// }}; +//} +// +//macro_rules! m_str { +// ($s:expr) => {{ +// concat!($s, "\0").as_ptr() as *mut i8 +// }}; +//} +// +//macro_rules! mm_str { +// ($s:expr) => {{ +// concat!($s, "\0").as_ptr() as *mut *mut i8 +// }}; +//} +// +//unsafe fn gen_type(context: LLVMContextRef, t: Option) -> LLVMTypeRef { +// match t { +// Some(Type::Bool) => LLVMInt1TypeInContext(context), +// Some(Type::Int) => LLVMInt64TypeInContext(context), +// Some(Type::Str) => panic!("Do not use gen_type with Strings!"), +// None => LLVMVoidTypeInContext(context), +// } +//} +// +//unsafe fn gen_array_type(context: LLVMContextRef, t: &Type) -> LLVMTypeRef { +// match t { +// Type::Bool => LLVMPointerType(LLVMInt1TypeInContext(context), 0), +// Type::Int => LLVMPointerType(LLVMInt64TypeInContext(context), 0), +// Type::Str => panic!("Do not use gen_array_type with Strings!"), +// } +//} +// +//unsafe fn flatten_expr( +// context: LLVMContextRef, +// module: LLVMModuleRef, +// symbols: &SymbolTable, +// builder: LLVMBuilderRef, +// e: Expr, +//) -> LLVMValueRef { +// let mut v = Vec::new(); +// match e { +// Expr::Number(n) => { +// v.push(LLVMConstInt(gen_type(context, Some(Type::Int)), n, 1)); +// } +// Expr::Variable(Variable::Single(s)) => { +// if let Ok(var) = symbols.get(&s) { +// if let Symbol::Variable(mut var) = var { +// let tmp = LLVMBuildLoad(builder, var, c_str!("flat")); +// v.push(tmp); +// } else { +// panic!( +// "Variable <{:?}> of a type diferent than expected!", +// s +// ); +// } +// } else { +// panic!("Variable <{:?}> is used but not declared!", s); +// } +// } +// Expr::Variable(Variable::Array(s, e)) => { +// if let Ok(var) = symbols.get(&s) { +// if let Symbol::ArrayRef(mut var) = var { +// let index_flattened = +// flatten_expr(context, module, symbols, builder, *e); +// let loaded_array_ptr = +// LLVMBuildLoad(builder, var, c_str!("loaded_param")); +// let arr_at = LLVMBuildInBoundsGEP( +// builder, +// loaded_array_ptr, +// [index_flattened].as_mut_ptr(), +// 1, +// c_str!("arr"), +// ); +// v.push(LLVMBuildLoad(builder, arr_at, c_str!("flat"))); +// } else if let Symbol::Array(_, mut var) = var { +// let flattened = +// flatten_expr(context, module, symbols, builder, *e); +// let arr_at = LLVMBuildGEP( +// builder, +// var, +// [ +// flattened, +// LLVMConstInt( +// gen_type(context, Some(Type::Int)), +// 0, +// 1, +// ), +// ] +// .as_mut_ptr(), +// 2, +// c_str!("arr"), +// ); +// v.push(LLVMBuildLoad(builder, arr_at, c_str!("flat"))); +// } else { +// panic!("Variable <{:?}> is used but not declared!", s); +// } +// } else { +// panic!("Variable <{:?}> is used but not declared!", s); +// } +// } +// Expr::True => { +// v.push(LLVMConstInt(gen_type(context, Some(Type::Bool)), 1, 1)); +// } +// Expr::False => { +// v.push(LLVMConstInt(gen_type(context, Some(Type::Bool)), 0, 1)); +// } +// Expr::Op(lhs, op, rhs) => match op { +// Opcode::Add => { +// let lhs = flatten_expr(context, module, symbols, builder, *lhs); +// let rhs = flatten_expr(context, module, symbols, builder, *rhs); +// v.push(LLVMBuildAdd(builder, lhs, rhs, c_str!("add"))); +// } +// Opcode::Sub => { +// let lhs = flatten_expr(context, module, symbols, builder, *lhs); +// let rhs = flatten_expr(context, module, symbols, builder, *rhs); +// v.push(LLVMBuildSub(builder, lhs, rhs, c_str!("sub"))); +// } +// Opcode::Mul => { +// let lhs = flatten_expr(context, module, symbols, builder, *lhs); +// let rhs = flatten_expr(context, module, symbols, builder, *rhs); +// v.push(LLVMBuildMul(builder, lhs, rhs, c_str!("mul"))); +// } +// Opcode::Div => { +// let lhs = flatten_expr(context, module, symbols, builder, *lhs); +// let rhs = flatten_expr(context, module, symbols, builder, *rhs); +// v.push(LLVMBuildSDiv(builder, lhs, rhs, c_str!("sdiv"))); +// } +// Opcode::Mod => { +// let lhs = flatten_expr(context, module, symbols, builder, *lhs); +// let rhs = flatten_expr(context, module, symbols, builder, *rhs); +// v.push(LLVMBuildSRem(builder, lhs, rhs, c_str!("srem"))); +// } +// Opcode::Lesser +// | Opcode::LesserOrEqual +// | Opcode::Greater +// | Opcode::GreaterOrEqual +// | Opcode::Equal +// | Opcode::Different => { +// let lhs = flatten_expr(context, module, symbols, builder, *lhs); +// let rhs = flatten_expr(context, module, symbols, builder, *rhs); +// v.push(LLVMBuildICmp( +// builder, +// op.pred(), +// lhs, +// rhs, +// c_str!("cmp"), +// )); +// } +// Opcode::And => { +// let lhs = flatten_expr(context, module, symbols, builder, *lhs); +// let rhs = flatten_expr(context, module, symbols, builder, *rhs); +// v.push(LLVMBuildAnd(builder, lhs, rhs, c_str!("and"))); +// } +// Opcode::Or => { +// let lhs = flatten_expr(context, module, symbols, builder, *lhs); +// let rhs = flatten_expr(context, module, symbols, builder, *rhs); +// v.push(LLVMBuildOr(builder, lhs, rhs, c_str!("or"))); +// } +// _ => panic!("IMPOSSIBURU! Opcode<{:?}> is unary!", op), +// }, +// Expr::Call(n, None) => { +// let called_fn = LLVMGetNamedFunction(module, as_str!(n)); +// v.push(LLVMBuildCall( +// builder, +// called_fn, +// [].as_mut_ptr(), +// 0, +// c_str!("fn_call"), +// )); +// } +// Expr::Right(Opcode::Negative, rhs) => { +// let rhs = flatten_expr(context, module, symbols, builder, *rhs); +// v.push(LLVMBuildMul( +// builder, +// LLVMConstInt( +// gen_type(context, Some(Type::Int)), +// -1i64 as u64, +// 1, +// ), +// rhs, +// c_str!("neg"), +// )); +// } +// Expr::Right(Opcode::Not, rhs) => { +// let rhs = flatten_expr(context, module, symbols, builder, *rhs); +// v.push(LLVMBuildNot(builder, rhs, c_str!("not"))); +// } +// Expr::Right(o, _) => { +// panic!("IMPOSSIBURU! Opcode<{:?}> is binary!", o); +// } +// _ => println!("uninplemented!"), +// } +// if let Some(a) = v.last().cloned() { +// a +// } else { +// //panic!("invalid state"); +// LLVMConstInt(gen_type(context, Some(Type::Int)), 42, 1) +// } +//} +// +//unsafe fn local_add_variable( +// context: LLVMContextRef, +// module: LLVMModuleRef, +// symbols: &mut SymbolTable, +// builder: LLVMBuilderRef, +// n: &str, +// t: Type, +// e: Option>, +//) { +// let t = gen_type(context, Some(t)); +// let decl = LLVMBuildAlloca(builder, t, as_str!(n)); +// if let Some(e) = e { +// let flattened = flatten_expr(context, module, symbols, builder, *e); +// LLVMBuildStore(builder, flattened, decl); +// } else { +// LLVMBuildStore(builder, LLVMConstInt(t, 0, 1), decl); +// } +// let new_symbol = Symbol::Variable(decl); +// symbols.set(&n, new_symbol); +//} +// +//unsafe fn local_add_array( +// context: LLVMContextRef, +// symbols: &mut SymbolTable, +// builder: LLVMBuilderRef, +// n: &str, +// t: Type, +// s: u64, +// e: Option>>, +//) { +// let t = gen_type(context, Some(t)); +// let array_type = LLVMArrayType(t, s as u32); +// let decl = LLVMBuildArrayAlloca( +// builder, +// array_type, +// LLVMConstInt(t, 0, 1), +// as_str!(n), +// ); +// if let Some(e) = e { +// for (i, e) in e.iter().enumerate() { +// match **e { +// Expr::Number(e) => { +// let ptr = LLVMBuildGEP( +// builder, +// decl, +// [ +// LLVMConstInt( +// gen_type(context, Some(Type::Int)), +// i as u64, +// 1, +// ), +// LLVMConstInt( +// gen_type(context, Some(Type::Int)), +// 0, +// 1, +// ), +// ] +// .as_mut_ptr(), +// 2, +// c_str!("ptr_get"), +// ); +// LLVMBuildStore(builder, LLVMConstInt(t, e, 1), ptr); +// } +// Expr::True => { +// let ptr = LLVMBuildGEP( +// builder, +// decl, +// [ +// LLVMConstInt( +// gen_type(context, Some(Type::Int)), +// i as u64, +// 1, +// ), +// LLVMConstInt( +// gen_type(context, Some(Type::Int)), +// 0, +// 1, +// ), +// ] +// .as_mut_ptr(), +// 2, +// c_str!("ptr_get"), +// ); +// LLVMBuildStore(builder, LLVMConstInt(t, 1, 1), ptr); +// } +// Expr::False => { +// let ptr = LLVMBuildGEP( +// builder, +// decl, +// [ +// LLVMConstInt( +// gen_type(context, Some(Type::Int)), +// i as u64, +// 1, +// ), +// LLVMConstInt( +// gen_type(context, Some(Type::Int)), +// 0, +// 1, +// ), +// ] +// .as_mut_ptr(), +// 2, +// c_str!("ptr_get"), +// ); +// LLVMBuildStore(builder, LLVMConstInt(t, 0, 1), ptr); +// } +// _ => panic!( +// "Cannot initialize global value with non-const expresion!" +// ), +// }; +// } +// /* +// *let mut args = e +// * .iter() +// * .map(|b| match **b { +// * Expr::Number(e) => LLVMConstInt(t, e, 1), +// * Expr::True => LLVMConstInt(t, 1, 1), +// * Expr::False => LLVMConstInt(t, 0, 1), +// * _ => panic!("Cannot initialize global value with non-const expresion!"), +// * }) +// * .collect::>(); +// *let values = LLVMConstArray(t, args.as_mut_ptr(), args.len() as u32); +// *LLVMBuildStore(builder, values, decl); +// */ +// } +// let new_symbol = Symbol::Array(s as u32, decl); +// +// symbols.set(&n, new_symbol); +//} +// +//unsafe fn global_add_func( +// context: LLVMContextRef, +// module: LLVMModuleRef, +// symbols: &mut SymbolTable, +// n: &str, +// t: Option, // Return Type +// a: Option>, +// b: Block, +//) { +// let builder = LLVMCreateBuilderInContext(context); +// let t = gen_type(context, t); +// let args = if let Some(a) = a { +// a.iter() +// .map(|p| match p { +// FuncParam::Single(n, t) => { +// (n.clone(), true, gen_type(context, Some(t.clone()))) +// } +// FuncParam::Array(n, t) => { +// (n.clone(), false, gen_array_type(context, &t.clone())) +// } +// }) +// .collect::>() +// } else { +// Vec::new() +// }; +// let function_type = LLVMFunctionType( +// t, +// args.iter().map(|a| a.2).collect::>().as_mut_ptr(), +// args.len() as u32, +// 0, +// ); +// let function = LLVMAddFunction(module, as_str!(n), function_type); +// +// symbols.initialize_scope(); +// +// let entry = +// LLVMAppendBasicBlockInContext(context, function, c_str!("entry")); +// LLVMPositionBuilderAtEnd(builder, entry); +// +// for (i, e) in args.iter().enumerate() { +// if e.1 { +// let fn_param = LLVMGetParam(function, i as u32); +// let alloced_param = LLVMBuildAlloca(builder, e.2, c_str!("param")); +// LLVMBuildStore(builder, fn_param, alloced_param); +// let new_symbol = Symbol::Variable(alloced_param); +// symbols.set(&e.0, new_symbol); +// } else { +// let fn_param = LLVMGetParam(function, i as u32); +// let alloced_param = LLVMBuildAlloca(builder, e.2, c_str!("param")); +// LLVMBuildStore(builder, fn_param, alloced_param); +// let new_symbol = Symbol::ArrayRef(alloced_param); +// symbols.set(&e.0, new_symbol); +// } +// } +// +// let test = LLVMGetNamedFunction(module, c_str!("printf")); +// // Stupid way of checking if the function is already defined. +// let against = ptr::null::() as *mut _; +// if test == against { +// LLVMBuildGlobalStringPtr(builder, c_str!("%d"), c_str!("format_int")); +// LLVMBuildGlobalStringPtr(builder, c_str!("%s"), c_str!("format_str")); +// +// let int8_type = LLVMInt8TypeInContext(context); +// let int32_type = LLVMInt32TypeInContext(context); +// let mut args = [LLVMPointerType(int8_type, 0)]; +// let fn_type = LLVMFunctionType(int32_type, args.as_mut_ptr(), 0, 1); +// +// LLVMAddFunction(module, c_str!("printf"), fn_type); +// LLVMAddFunction(module, c_str!("scanf"), fn_type); +// } +// +// gen_decl(context, module, symbols, builder, b.decl, false); +// gen_block( +// context, module, symbols, builder, function, None, b.commands, +// ); +// +// symbols.kill_scope(); +// +// LLVMDisposeBuilder(builder); +// let new_symbol = Symbol::Func(n.to_string()); +// +// symbols.set(&n, new_symbol); +//} +// +//unsafe fn gen_decl( +// context: LLVMContextRef, +// module: LLVMModuleRef, +// symbols: &mut SymbolTable, +// builder: LLVMBuilderRef, +// decl: Vec, +// allow_fn: bool, +//) { +// for i in decl { +// match i { +// Decl::Single(n, t, e) => { +// local_add_variable(context, module, symbols, builder, &n, t, e) +// } +// Decl::Array(n, t, s, e) => { +// local_add_array(context, symbols, builder, &n, t, s, e) +// } +// Decl::Func(_, _, _, _) => { +// if allow_fn { +// println!("unimplemented"); +// } else { +// panic!("Functions are not allowed here!"); +// } +// } +// } +// } +//} +// +//unsafe fn build_attr( +// context: LLVMContextRef, +// module: LLVMModuleRef, +// symbols: &SymbolTable, +// builder: LLVMBuilderRef, +// v: &str, +// e: Expr, +//) -> Result<(), String> { +// if let Ok(var) = symbols.get(&v) { +// if let Symbol::Variable(mut var) = var { +// let flattened = flatten_expr(context, module, symbols, builder, e); +// LLVMBuildStore(builder, flattened, var); +// Ok(()) +// } else { +// Err(format!("Variable <{:?}> is used but not declared!", v)) +// } +// } else { +// Err(format!("Variable <{:?}> is used but not declared!", v)) +// } +//} +// +//unsafe fn gen_block( +// context: LLVMContextRef, +// module: LLVMModuleRef, +// symbols: &mut SymbolTable, +// builder: LLVMBuilderRef, +// parent: LLVMValueRef, +// looping: Option<(LLVMBasicBlockRef, LLVMBasicBlockRef)>, +// stmts: Vec>, +//) { +// symbols.initialize_scope(); +// +// for i in stmts { +// match i { +// Either::Left(Stmt::Attr(Variable::Single(v), e)) => { +// if let Err(s) = +// build_attr(context, module, symbols, builder, &v, *e) +// { +// panic!(s); +// } +// } +// Either::Left(Stmt::Write(vec)) => { +// for i in vec { +// let flattened = +// flatten_expr(context, module, symbols, builder, *i); +// let format_str = +// LLVMGetNamedGlobal(module, c_str!("format_int")); +// let mut printf_args = [format_str, flattened]; +// let printf_fn = +// LLVMGetNamedFunction(module, c_str!("printf")); +// LLVMBuildCall( +// builder, +// printf_fn, +// printf_args.as_mut_ptr(), +// 2, +// c_str!("write"), +// ); +// } +// } +// Either::Left(Stmt::Read(Variable::Single(v))) => { +// if let Ok(var) = symbols.get(&v) { +// if let Symbol::Variable(mut var) = var { +// let format_str = +// LLVMGetNamedGlobal(module, c_str!("format_int")); +// let mut scanf_args = [format_str, var]; +// let scanf_fn = +// LLVMGetNamedFunction(module, c_str!("scanf")); +// LLVMBuildCall( +// builder, +// scanf_fn, +// scanf_args.as_mut_ptr(), +// 2, +// c_str!("read"), +// ); +// } +// } +// } +// Either::Left(Stmt::Read(Variable::Array(v, e))) => { +// if let Ok(var) = symbols.get(&v) { +// if let Symbol::ArrayRef(mut var) = var { +// let flattened = +// flatten_expr(context, module, symbols, builder, *e); +// let arr_at = LLVMBuildGEP( +// builder, +// var, +// [ +// LLVMConstInt( +// gen_type(context, Some(Type::Int)), +// 0, +// 1, +// ), +// flattened, +// ] +// .as_mut_ptr(), +// 2, +// c_str!("arr"), +// ); +// let format_str = +// LLVMGetNamedGlobal(module, c_str!("format_int")); +// let mut scanf_args = [format_str, arr_at]; +// let scanf_fn = +// LLVMGetNamedFunction(module, c_str!("scanf")); +// LLVMBuildCall( +// builder, +// scanf_fn, +// scanf_args.as_mut_ptr(), +// 2, +// c_str!("read"), +// ); +// } else if let Symbol::Array(_, mut var) = var { +// let flattened = +// flatten_expr(context, module, symbols, builder, *e); +// let arr_at = LLVMBuildGEP( +// builder, +// var, +// [ +// LLVMConstInt( +// gen_type(context, Some(Type::Int)), +// 0, +// 1, +// ), +// flattened, +// ] +// .as_mut_ptr(), +// 2, +// c_str!("arr"), +// ); +// let format_str = +// LLVMGetNamedGlobal(module, c_str!("format_int")); +// let mut scanf_args = [format_str, arr_at]; +// let scanf_fn = +// LLVMGetNamedFunction(module, c_str!("scanf")); +// LLVMBuildCall( +// builder, +// scanf_fn, +// scanf_args.as_mut_ptr(), +// 2, +// c_str!("read"), +// ); +// } +// } +// } +// Either::Left(Stmt::Call(n, None)) => { +// let called_fn = LLVMGetNamedFunction(module, as_str!(n)); +// LLVMBuildCall( +// builder, +// called_fn, +// [].as_mut_ptr(), +// 0, +// c_str!(""), +// ); +// } +// Either::Left(Stmt::Skip) => { +// if let Some((skip, _)) = looping { +// LLVMBuildBr(builder, skip); +// } else { +// panic!("cannot use skip outside of a loop"); +// } +// } +// Either::Left(Stmt::Stop) => { +// if let Some((_, stop)) = looping { +// LLVMBuildBr(builder, stop); +// } else { +// panic!("cannot use skip outside of a loop"); +// } +// } +// Either::Left(Stmt::Return(v)) => { +// if let Some(v) = v { +// let flattened = +// flatten_expr(context, module, symbols, builder, *v); +// LLVMBuildRet(builder, flattened); +// } else { +// LLVMBuildRetVoid(builder); +// } +// } +// Either::Left(Stmt::If(cond, then, else_ifs, None)) => { +// let then_block = LLVMAppendBasicBlock(parent, c_str!("then")); +// let merge = LLVMAppendBasicBlock(parent, c_str!("merge")); +// +// let cond = +// flatten_expr(context, module, symbols, builder, *cond); +// LLVMBuildCondBr(builder, cond, then_block, merge); +// +// // Build True Branch +// LLVMPositionBuilderAtEnd(builder, then_block); +// gen_decl(context, module, symbols, builder, then.decl, false); +// gen_block( +// context, +// module, +// symbols, +// builder, +// parent, +// looping, +// then.commands, +// ); +// LLVMBuildBr(builder, merge); +// +// // Build Merge Branch +// LLVMPositionBuilderAtEnd(builder, merge); +// } +// Either::Left(Stmt::If(cond, then, else_ifs, Some(_else))) => { +// let then_block = LLVMAppendBasicBlock(parent, c_str!("then")); +// let else_block = LLVMAppendBasicBlock(parent, c_str!("else")); +// let merge = LLVMAppendBasicBlock(parent, c_str!("merge")); +// +// let cond = +// flatten_expr(context, module, symbols, builder, *cond); +// LLVMBuildCondBr(builder, cond, then_block, else_block); +// +// // Build True Branch +// LLVMPositionBuilderAtEnd(builder, then_block); +// gen_decl(context, module, symbols, builder, then.decl, false); +// gen_block( +// context, +// module, +// symbols, +// builder, +// parent, +// looping, +// then.commands, +// ); +// LLVMBuildBr(builder, merge); +// +// // Build False Branch +// LLVMPositionBuilderAtEnd(builder, else_block); +// gen_decl(context, module, symbols, builder, _else.decl, false); +// gen_block( +// context, +// module, +// symbols, +// builder, +// parent, +// looping, +// _else.commands, +// ); +// LLVMBuildBr(builder, merge); +// +// // Build Merge Branch +// LLVMPositionBuilderAtEnd(builder, merge); +// } +// Either::Left(Stmt::For(init, cond, step, block)) => { +// let cond_block = +// LLVMAppendBasicBlock(parent, c_str!("cond_loop")); +// let loop_block = LLVMAppendBasicBlock(parent, c_str!("loop")); +// let step_block = LLVMAppendBasicBlock(parent, c_str!("step")); +// let exit_block = +// LLVMAppendBasicBlock(parent, c_str!("exit_loop")); +// +// let init = *init; +// // Build attribution before entering init_block +// if let Stmt::Attr(Variable::Single(v), e) = init { +// if let Err(s) = +// build_attr(context, module, symbols, builder, &v, *e) +// { +// panic!(s); +// } +// } else if let Stmt::Attr(Variable::Array(v, i), e) = init { +// println!("uninplemented!"); +// } else { +// panic!("invalid state"); +// } +// LLVMBuildBr(builder, cond_block); +// +// // Build condition inside cond_block +// LLVMPositionBuilderAtEnd(builder, cond_block); +// let cond = +// flatten_expr(context, module, symbols, builder, *cond); +// LLVMBuildCondBr(builder, cond, loop_block, exit_block); +// +// // Position at loop to build loop's instructions +// LLVMPositionBuilderAtEnd(builder, loop_block); +// gen_decl(context, module, symbols, builder, block.decl, false); +// gen_block( +// context, +// module, +// symbols, +// builder, +// parent, +// Some((step_block, exit_block)), +// block.commands, +// ); +// LLVMBuildBr(builder, step_block); +// +// LLVMPositionBuilderAtEnd(builder, step_block); +// // Add step to end of loop block +// let step = *step; +// if let Stmt::Attr(Variable::Single(v), e) = step { +// if let Err(s) = +// build_attr(context, module, symbols, builder, &v, *e) +// { +// panic!(s); +// } +// } else if let Stmt::Attr(Variable::Array(v, i), e) = step { +// println!("uninplemented!"); +// } else { +// panic!("invalid state"); +// } +// LLVMBuildBr(builder, cond_block); +// +// // Continue at exit_loop +// LLVMPositionBuilderAtEnd(builder, exit_block); +// } +// +// Either::Left(Stmt::While(cond, block)) => { +// let cond_block = +// LLVMAppendBasicBlock(parent, c_str!("cond_loop")); +// let loop_block = LLVMAppendBasicBlock(parent, c_str!("loop")); +// let exit_block = +// LLVMAppendBasicBlock(parent, c_str!("exit_loop")); +// +// LLVMBuildBr(builder, cond_block); +// +// LLVMPositionBuilderAtEnd(builder, cond_block); +// // Build condition inside cond_block +// let cond = +// flatten_expr(context, module, symbols, builder, *cond); +// LLVMBuildCondBr(builder, cond, loop_block, exit_block); +// +// // Position at loop to build loop's instructions +// LLVMPositionBuilderAtEnd(builder, loop_block); +// gen_decl(context, module, symbols, builder, block.decl, false); +// gen_block( +// context, +// module, +// symbols, +// builder, +// parent, +// Some((cond_block, exit_block)), +// block.commands, +// ); +// LLVMBuildBr(builder, cond_block); +// +// // Continue at exit_loop +// LLVMPositionBuilderAtEnd(builder, exit_block); +// } +// +// Either::Left(_) => println!("uninplemented!"), +// Either::Right(b) => { +// for i in b.decl { +// match i { +// Decl::Single(n, t, e) => local_add_variable( +// context, module, symbols, builder, &n, t, e, +// ), +// Decl::Array(n, t, s, e) => local_add_array( +// context, symbols, builder, &n, t, s, e, +// ), +// _ => { +// panic!("Cannot declare functions inside functions!") +// } +// } +// } +// gen_block( +// context, module, symbols, builder, parent, looping, +// b.commands, +// ) +// } +// } +// } +// +// symbols.kill_scope(); +//} +// +//unsafe fn global_add_variable( +// context: LLVMContextRef, +// module: LLVMModuleRef, +// symbols: &mut SymbolTable, +// n: &str, +// t: Type, +// e: Option>, +//) { +// let t = gen_type(context, Some(t)); +// let decl = LLVMAddGlobal(module, t, as_str!(n)); +// if let Some(e) = e { +// let b = *e; +// if let Expr::Number(v) = b { +// LLVMSetInitializer(decl, LLVMConstInt(t, v as u64, 1)); +// } +// } else { +// panic!("Cannot initialize global value with non-const expresion!"); +// } +// let new_symbol = Symbol::Variable(decl); +// symbols.set(&n, new_symbol); +//} +// +//unsafe fn global_add_array( +// context: LLVMContextRef, +// module: LLVMModuleRef, +// symbols: &mut SymbolTable, +// n: &str, +// t: Type, +// s: u64, +// e: Option>>, +//) { +// let t = gen_type(context, Some(t)); +// let array_type = LLVMArrayType(t, s as u32); +// let decl = LLVMAddGlobal(module, array_type, as_str!(n)); +// if let Some(e) = e { +// let mut args = e +// .iter() +// .map(|b| match **b { +// Expr::Number(e) => LLVMConstInt(t, e, 1), +// Expr::True => LLVMConstInt(t, 1, 1), +// Expr::False => LLVMConstInt(t, 0, 1), +// _ => panic!( +// "Cannot initialize global value with non-const expresion!" +// ), +// }) +// .collect::>(); +// let values = LLVMConstArray(t, args.as_mut_ptr(), args.len() as u32); +// LLVMSetInitializer(decl, values); +// } +// let new_symbol = Symbol::Array(s as u32, decl); +// symbols.set(&n, new_symbol); +//} + +pub unsafe fn gen(decls: Vec) { + let mut context = context::Context::new(); + for i in decls { + i.emit(&mut context).expect("Cannot emit this"); + } + LLVMDumpModule(context.module); + LLVMPrintModuleToFile( + context.module, + as_str!("test.ll"), + as_str!("idk") as *mut *mut i8, + ); + LLVMContextDispose(context.context); +} diff --git a/src/symbol_table.rs b/src/gen/symbol_table.rs similarity index 93% rename from src/symbol_table.rs rename to src/gen/symbol_table.rs index 1470393..3d01cf2 100644 --- a/src/symbol_table.rs +++ b/src/gen/symbol_table.rs @@ -2,12 +2,13 @@ use std::collections::{HashMap, LinkedList}; use llvm::prelude::*; +// TODO Should store the type #[derive(Clone, Debug)] pub enum Symbol { Variable(LLVMValueRef), Array(u32, LLVMValueRef), ArrayRef(LLVMValueRef), - Func(String), + Func(String), // TODO Should store tha function value and signature } #[derive(Clone, Debug)] diff --git a/src/grammar/mod.lalrpop b/src/grammar/mod.lalrpop index 0b44a15..11936a5 100644 --- a/src/grammar/mod.lalrpop +++ b/src/grammar/mod.lalrpop @@ -1,4 +1,4 @@ -use lalrpop_util::{ ErrorRecovery, ParseError }; +use lalrpop_util::{ ErrorRecovery }; use std::str::FromStr; use ast::*; diff --git a/src/main.rs b/src/main.rs index a350ade..168eb77 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,7 +11,6 @@ extern crate llvm_sys as llvm; mod ast; mod gen; mod grammar; -mod symbol_table; use clap::{ app_from_crate, crate_authors, crate_description, crate_name, From 730b662602b11426b75121d8a650b355896a92f3 Mon Sep 17 00:00:00 2001 From: Guilherme Chichanoski Date: Sun, 25 Nov 2018 01:17:06 -0200 Subject: [PATCH 02/19] fix for and add some stmt --- src/gen/context.rs | 4 +- src/gen/emit.rs | 151 +++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 148 insertions(+), 7 deletions(-) diff --git a/src/gen/context.rs b/src/gen/context.rs index f372b06..ccc240f 100644 --- a/src/gen/context.rs +++ b/src/gen/context.rs @@ -8,7 +8,8 @@ pub struct Context { pub module: *mut LLVMModule, pub context: *mut LLVMContext, pub builder: *mut LLVMBuilder, - pub actual_function: Option<*mut LLVMValue>, + pub actual_function: Option<(*mut LLVMValue, *mut LLVMBasicBlock)>, // (function, entry) + pub actual_loop: Option<(*mut LLVMBasicBlock, *mut LLVMBasicBlock)>, // (merge, predicate) } impl Context { @@ -21,6 +22,7 @@ impl Context { context, actual_function: None, builder: LLVMCreateBuilderInContext(context), + actual_loop: None, } } } diff --git a/src/gen/emit.rs b/src/gen/emit.rs index 7b0fee7..fce03dd 100644 --- a/src/gen/emit.rs +++ b/src/gen/emit.rs @@ -132,6 +132,18 @@ impl Emit<*mut LLVMValue> for Expr { LLVMBuildMul(builder, lhs, rhs, as_str!("mul_result")) } Opcode::Mod => panic!("Não encontrei a chamada do modulo"), + Opcode::Lesser + | Opcode::LesserOrEqual + | Opcode::Greater + | Opcode::GreaterOrEqual + | Opcode::Equal + | Opcode::Different => LLVMBuildICmp( + context.builder, + op.pred(), + lhs, + rhs, + as_str!("cmp"), + ), _ => panic!("Not implemented"), }; Ok(value) @@ -165,9 +177,124 @@ impl Emit<()> for Stmt { let ptr_var = var.emit(context).unwrap(); let expression = expression.emit(context).unwrap(); - LLVMBuildStore(builder, ptr_var, expression); + LLVMBuildStore(builder, expression, ptr_var); + Ok(()) + } + Stmt::Call(identifier, expressions) => { + Expr::Call(identifier.to_string(), expressions.clone()) + .emit(context) + .unwrap(); + Ok(()) + } + Stmt::For(init, predicate, step, block) => { + init.emit(context).unwrap(); + let block_predicate = LLVMAppendBasicBlockInContext( + context.context, + context.actual_function.unwrap().0, + as_str!("predicate_for"), + ); + let block_for = LLVMAppendBasicBlockInContext( + context.context, + context.actual_function.unwrap().0, + as_str!("block_for"), + ); + let block_step = LLVMAppendBasicBlockInContext( + context.context, + context.actual_function.unwrap().0, + as_str!("block_step"), + ); + let block_merge = LLVMAppendBasicBlockInContext( + context.context, + context.actual_function.unwrap().0, + as_str!("merge_for"), + ); + context.actual_loop = Some((block_merge, block_step)); + + LLVMBuildBr(context.builder, block_predicate); + + LLVMPositionBuilderAtEnd(context.builder, block_predicate); + LLVMBuildCondBr( + context.builder, + predicate.emit(context).unwrap(), + block_for, + block_merge, + ); + + LLVMPositionBuilderAtEnd(context.builder, block_for); + block.emit(context).unwrap(); + LLVMBuildBr(context.builder, block_step); + LLVMPositionBuilderAtEnd(context.builder, block_step); + step.emit(context).unwrap(); + LLVMBuildBr(context.builder, block_predicate); + + LLVMPositionBuilderAtEnd(context.builder, block_merge); + Ok(()) } + Stmt::While(predicate, block) => { + let block_predicate = LLVMAppendBasicBlockInContext( + context.context, + context.actual_function.unwrap().0, + as_str!("predicate_for"), + ); + let block_while = LLVMAppendBasicBlockInContext( + context.context, + context.actual_function.unwrap().0, + as_str!("block_for"), + ); + let block_merge = LLVMAppendBasicBlockInContext( + context.context, + context.actual_function.unwrap().0, + as_str!("merge_for"), + ); + context.actual_loop = Some((block_merge, block_predicate)); + + LLVMBuildBr(context.builder, block_predicate); + + LLVMPositionBuilderAtEnd(context.builder, block_predicate); + LLVMBuildCondBr( + context.builder, + predicate.emit(context).unwrap(), + block_while, + block_merge, + ); + + LLVMPositionBuilderAtEnd(context.builder, block_while); + block.emit(context).unwrap(); + LLVMBuildBr(context.builder, block_predicate); + + LLVMPositionBuilderAtEnd(context.builder, block_merge); + + Ok(()) + } + Stmt::Stop => { + if let Some((merge, _)) = context.actual_loop { + LLVMBuildBr(context.builder, merge); + Ok(()) + } else { + Err("Stop not in a loop".to_string()) + } + } + Stmt::Skip => { + if let Some((_, predicate)) = context.actual_loop { + LLVMBuildBr(context.builder, predicate); + Ok(()) + } else { + Err("Skip not in a loop".to_string()) + } + } + Stmt::Return(expression) => { + if let Some(expression) = expression { + LLVMBuildRet( + context.builder, + expression.emit(context).unwrap(), + ); + Ok(()) + } else { + LLVMBuildRetVoid(context.builder); + Ok(()) + } + } _ => panic!("Not implemented"), } } @@ -175,13 +302,25 @@ impl Emit<()> for Stmt { impl Emit<()> for Decl { unsafe fn emit(self: &Self, context: &mut Context) -> Result<(), String> { - if let Some(_) = context.actual_function { + if context.actual_function.is_some() { // When local + let alloc_builder = LLVMCreateBuilderInContext(context.context); + let first_intr = + LLVMGetFirstInstruction(context.actual_function.unwrap().1); + if !first_intr.is_null() { + LLVMPositionBuilderBefore(alloc_builder, first_intr); + } else { + LLVMPositionBuilderAtEnd( + alloc_builder, + context.actual_function.unwrap().1, + ); + } + let builder = context.builder; match self { Decl::Single(identifier, type_of, expression) => { let ptr_vlr = LLVMBuildAlloca( - builder, + alloc_builder, type_of.emit(context).unwrap(), as_str!(identifier), ); @@ -192,8 +331,8 @@ impl Emit<()> for Decl { if let Some(expression) = expression { LLVMBuildStore( builder, - ptr_vlr, expression.emit(context).unwrap(), + ptr_vlr, ); Ok(()) } else { @@ -261,7 +400,7 @@ impl Emit<()> for Decl { context.symbol_table.initialize_scope(); - context.actual_function = Some(function); + context.actual_function = Some((function, entry_block)); LLVMPositionBuilderAtEnd(context.builder, entry_block); vec_params.iter().enumerate().for_each(|(index, param)| { @@ -281,8 +420,8 @@ impl Emit<()> for Decl { LLVMBuildStore( context.builder, - ptr_vlr, function_param, + ptr_vlr, ); } FuncParam::Array(_identifier, _type_of) => { From 2b4afdb7895f69dfb892bfdbebdf3fc821456bef Mon Sep 17 00:00:00 2001 From: Guilherme Chichanoski Date: Sat, 1 Dec 2018 15:05:28 -0200 Subject: [PATCH 03/19] add if stmt, need some tests --- src/gen/emit.rs | 85 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/src/gen/emit.rs b/src/gen/emit.rs index fce03dd..8e3418f 100644 --- a/src/gen/emit.rs +++ b/src/gen/emit.rs @@ -295,6 +295,91 @@ impl Emit<()> for Stmt { Ok(()) } } + Stmt::If(expression, block, elifs, else_block) => { + let block_if_predicate = LLVMAppendBasicBlockInContext( + context.context, + context.actual_function.unwrap().0, + as_str!("if_predicate"), + ); + LLVMBuildBr(context.builder, block_if_predicate); + let block_if_then = LLVMAppendBasicBlockInContext( + context.context, + context.actual_function.unwrap().0, + as_str!("if_then"), + ); + let block_merge = LLVMAppendBasicBlockInContext( + context.context, + context.actual_function.unwrap().0, + as_str!("merge_if"), + ); + let last_block = match else_block { + Some(else_block) => { + let block_if_else = LLVMAppendBasicBlockInContext( + context.context, + context.actual_function.unwrap().0, + as_str!("if_else"), + ); + LLVMPositionBuilderAtEnd( + context.builder, + block_if_else, + ); + else_block.emit(context).unwrap(); + LLVMBuildBr(context.builder, block_merge); + + block_if_else + } + None => block_merge, + }; + let block_else_to_jump = elifs.iter().rev().fold( + last_block, + |last_block, actual_block| { + let block_elif_predicate = + LLVMAppendBasicBlockInContext( + context.context, + context.actual_function.unwrap().0, + as_str!("block_elif"), + ); + let block_elif_then = LLVMAppendBasicBlockInContext( + context.context, + context.actual_function.unwrap().0, + as_str!("block_elif"), + ); + LLVMPositionBuilderAtEnd( + context.builder, + block_elif_predicate, + ); + LLVMBuildCondBr( + context.builder, + actual_block.0.emit(context).unwrap(), + block_elif_then, + last_block, + ); + LLVMPositionBuilderAtEnd( + context.builder, + block_elif_then, + ); + actual_block.1.emit(context).unwrap(); + LLVMBuildBr(context.builder, block_merge); + + block_elif_predicate + }, + ); + + LLVMPositionBuilderAtEnd(context.builder, block_if_predicate); + let cmp_expression = expression.emit(context).unwrap(); + LLVMBuildCondBr( + context.builder, + cmp_expression, + block_if_then, + block_else_to_jump, + ); + LLVMPositionBuilderAtEnd(context.builder, block_if_then); + block.emit(context).unwrap(); + LLVMBuildBr(context.builder, block_merge); + LLVMPositionBuilderAtEnd(context.builder, block_merge); + + Ok(()) + } _ => panic!("Not implemented"), } } From 6eb826443f878f7bba5f0880ba61156ef8aeb1a5 Mon Sep 17 00:00:00 2001 From: Guilherme Chichanoski Date: Sun, 2 Dec 2018 16:51:09 -0200 Subject: [PATCH 04/19] start of error handling, pass the type of emited value --- src/ast.rs | 2 + src/gen/emit.rs | 236 ++++++++++++++++++++++++++++------------ src/gen/symbol_table.rs | 21 +++- 3 files changed, 186 insertions(+), 73 deletions(-) diff --git a/src/ast.rs b/src/ast.rs index 12826ac..89c7191 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -67,6 +67,7 @@ pub enum Type { Bool, Str, Void, + Agg(Box), } impl Default for Type { @@ -206,6 +207,7 @@ impl fmt::Debug for Type { Type::Bool => write!(f, "Bool"), Type::Str => write!(f, "Str"), Type::Void => write!(f, "Void"), + Type::Agg(type_of) => write!(f, "Agg({:?})", *type_of), } } } diff --git a/src/gen/emit.rs b/src/gen/emit.rs index 8e3418f..f8fa870 100644 --- a/src/gen/emit.rs +++ b/src/gen/emit.rs @@ -16,42 +16,47 @@ impl Emit<*mut LLVMType> for Type { Type::Bool => Ok(LLVMInt1TypeInContext(context.context)), Type::Void => Ok(LLVMVoidTypeInContext(context.context)), Type::Str => panic!("Not implemented"), + Type::Agg(_) => panic!("Not implemented"), } } } -impl Emit<*mut LLVMValue> for Variable { +impl Emit<(*mut LLVMValue, Type)> for Variable { unsafe fn emit( self: &Self, context: &mut Context, - ) -> Result<*mut LLVMValue, String> { + ) -> Result<(*mut LLVMValue, Type), String> { let builder = context.builder; match self { Variable::Single(identifier) => { if let Ok(value) = context.symbol_table.get(identifier) { match value { - Symbol::Variable(value) => Ok(*value), - _ => panic!("Variable type mismatch"), + Symbol::Variable(value, type_of) => { + Ok((*value, type_of.clone())) + } + _ => Err("Variable type mismatch".to_string()), } } else { - Err(String::from("variabe not declared")) + Err("variabe not declared".to_string()) } } Variable::Array(identifier, expression) => { if let Ok(value) = context.clone().symbol_table.get(identifier) { - let index = expression.emit(context).unwrap(); + let (index, type_of_index) = + expression.emit(context).unwrap(); match value { - Symbol::ArrayRef(value) | Symbol::Array(_, value) => { - Ok(LLVMBuildInBoundsGEP( + Symbol::Array(value, type_of) => Ok(( + LLVMBuildInBoundsGEP( builder, *value, [index].as_mut_ptr(), 1, as_str!("ptr_value"), - )) - } + ), + type_of.clone(), + )), _ => Err("Variable type mismatch".to_string()), } } else { @@ -62,25 +67,35 @@ impl Emit<*mut LLVMValue> for Variable { } } -impl Emit<*mut LLVMValue> for Expr { +impl Emit<(*mut LLVMValue, Type)> for Expr { unsafe fn emit( self: &Self, context: &mut Context, - ) -> Result<*mut LLVMValue, String> { + ) -> Result<(*mut LLVMValue, Type), String> { match self { - Expr::Number(number) => { - Ok(LLVMConstInt(Type::Int.emit(context).unwrap(), *number, 1)) - } - Expr::True => { - Ok(LLVMConstInt(Type::Bool.emit(context).unwrap(), 1, 1)) - } - Expr::False => { - Ok(LLVMConstInt(Type::Bool.emit(context).unwrap(), 0, 1)) - } + Expr::Number(number) => Ok(( + LLVMConstInt(Type::Int.emit(context).unwrap(), *number, 1), + Type::Int, + )), + Expr::True => Ok(( + LLVMConstInt(Type::Bool.emit(context).unwrap(), 1, 1), + Type::Bool, + )), + Expr::False => Ok(( + LLVMConstInt(Type::Bool.emit(context).unwrap(), 0, 1), + Type::Bool, + )), Expr::Variable(var) => { - let ptr_var = var.emit(context).unwrap(); + let (ptr_var, type_of) = var.emit(context).unwrap(); - Ok(LLVMBuildLoad(context.builder, ptr_var, as_str!("var_load"))) + Ok(( + LLVMBuildLoad( + context.builder, + ptr_var, + as_str!("var_load"), + ), + type_of, + )) } Expr::Call(identifier, params) => { let builder = context.builder; @@ -89,23 +104,29 @@ impl Emit<*mut LLVMValue> for Expr { { match function { // TODO Put function value in symbols table - Symbol::Func(function) => { - let function = LLVMGetNamedFunction( - context.module, - as_str!(function), - ); + Symbol::Func(function, function_signature) => { let params = params.clone().unwrap_or_default(); - - Ok(LLVMBuildCall( - builder, - function, - params - .iter() - .map(|param| param.emit(context).unwrap()) - .collect::>() - .as_mut_ptr(), - params.len() as u32, - as_str!("call"), + let function_signature = function_signature.clone(); + + Ok(( + LLVMBuildCall( + builder, + *function, + params + .iter() + .zip(function_signature.1) + .map(|(param, param_expected_type)| { + let (value, type_of) = + param.emit(context).unwrap(); + // TODO Check type_of with function_signature + value + }) + .collect::>() + .as_mut_ptr(), + params.len() as u32, + as_str!("call"), + ), + function_signature.0, )) } _ => Err("Type mismatch".to_string()), @@ -116,8 +137,8 @@ impl Emit<*mut LLVMValue> for Expr { } Expr::Op(lhs, op, rhs) => { let builder = context.builder; - let lhs = lhs.emit(context).unwrap(); - let rhs = rhs.emit(context).unwrap(); + let (lhs, type_of_lhs) = lhs.emit(context).unwrap(); + let (rhs, type_of_rhs) = rhs.emit(context).unwrap(); let value = match op { Opcode::Add => { LLVMBuildAdd(builder, lhs, rhs, as_str!("add_result")) @@ -146,11 +167,11 @@ impl Emit<*mut LLVMValue> for Expr { ), _ => panic!("Not implemented"), }; - Ok(value) + Ok((value, Type::Int)) // FIXME type_of depend on the operand } Expr::Right(op, expression) => { let builder = context.builder; - let expression = expression.emit(context).unwrap(); + let (expression, type_of) = expression.emit(context).unwrap(); let value = match op { Opcode::Not => { LLVMBuildNot(builder, expression, as_str!("not_result")) @@ -162,7 +183,7 @@ impl Emit<*mut LLVMValue> for Expr { ), _ => panic!("Should not do this"), }; - Ok(value) + Ok((value, Type::Int)) // FIXME type_of depend on the operand } Expr::Ternary(_, _, _) => panic!("Not implemented yet"), } @@ -174,8 +195,9 @@ impl Emit<()> for Stmt { let builder = context.builder; match self { Stmt::Attr(var, expression) => { - let ptr_var = var.emit(context).unwrap(); - let expression = expression.emit(context).unwrap(); + let (ptr_var, type_of) = var.emit(context).unwrap(); + let (expression, type_of_expression) = + expression.emit(context).unwrap(); LLVMBuildStore(builder, expression, ptr_var); Ok(()) @@ -212,10 +234,12 @@ impl Emit<()> for Stmt { LLVMBuildBr(context.builder, block_predicate); + let (predicate, type_of_predicate) = + predicate.emit(context).unwrap(); LLVMPositionBuilderAtEnd(context.builder, block_predicate); LLVMBuildCondBr( context.builder, - predicate.emit(context).unwrap(), + predicate, block_for, block_merge, ); @@ -251,10 +275,12 @@ impl Emit<()> for Stmt { LLVMBuildBr(context.builder, block_predicate); + let (predicate, type_of_predicate) = + predicate.emit(context).unwrap(); LLVMPositionBuilderAtEnd(context.builder, block_predicate); LLVMBuildCondBr( context.builder, - predicate.emit(context).unwrap(), + predicate, block_while, block_merge, ); @@ -285,10 +311,9 @@ impl Emit<()> for Stmt { } Stmt::Return(expression) => { if let Some(expression) = expression { - LLVMBuildRet( - context.builder, - expression.emit(context).unwrap(), - ); + let (expression, type_of) = + expression.emit(context).unwrap(); + LLVMBuildRet(context.builder, expression); Ok(()) } else { LLVMBuildRetVoid(context.builder); @@ -348,9 +373,12 @@ impl Emit<()> for Stmt { context.builder, block_elif_predicate, ); + let (elif_predicate, type_of_elif_predicate) = + actual_block.0.emit(context).unwrap(); + LLVMBuildCondBr( context.builder, - actual_block.0.emit(context).unwrap(), + elif_predicate, block_elif_then, last_block, ); @@ -366,7 +394,8 @@ impl Emit<()> for Stmt { ); LLVMPositionBuilderAtEnd(context.builder, block_if_predicate); - let cmp_expression = expression.emit(context).unwrap(); + let (cmp_expression, type_of) = + expression.emit(context).unwrap(); LLVMBuildCondBr( context.builder, cmp_expression, @@ -411,20 +440,38 @@ impl Emit<()> for Decl { ); context .symbol_table - .set(identifier, Symbol::Variable(ptr_vlr)); + .set(identifier, Symbol::Variable(ptr_vlr, type_of.clone())) + .expect("Can't set the variable, probably the variable is already declared"); if let Some(expression) = expression { - LLVMBuildStore( - builder, - expression.emit(context).unwrap(), - ptr_vlr, - ); + let (expression, type_of_expression) = + expression.emit(context).unwrap(); + LLVMBuildStore(builder, expression, ptr_vlr); Ok(()) } else { Ok(()) } } - _ => panic!("Not implemented!"), + Decl::Array(identifier, type_of, size, list_expression) => { + let (expression_size, _) = + Expr::Number(*size).emit(context).unwrap(); + + let ptr_vlr = LLVMBuildArrayAlloca( + context.builder, + type_of.emit(context).unwrap(), + expression_size, + as_str!(identifier), + ); + context + .symbol_table + .set(identifier, Symbol::Variable(ptr_vlr, type_of.clone())) + .expect("Can't set the variable, probably the variable is already declared"); + + // TODO Initialization + + Ok(()) + } + _ => Err("Function not expected".to_string()), } } else { // When global @@ -436,16 +483,45 @@ impl Emit<()> for Decl { as_str!(identifier), ); + context + .symbol_table + .set( + identifier, + Symbol::Variable(decl, type_of.clone()), + ) + .unwrap(); + if let Some(expression) = expression { - LLVMSetInitializer( - decl, - expression.emit(context).unwrap(), - ); + let (value, type_of) = + expression.emit(context).unwrap(); + + LLVMSetInitializer(decl, value); Ok(()) } else { Ok(()) } } + Decl::Array(identifier, type_of, size, list_expression) => { + let array_type = LLVMArrayType( + type_of.emit(context).unwrap(), + *size as u32, + ); + + let decl = LLVMAddGlobal( + context.module, + array_type, + as_str!(identifier), + ); + + context + .symbol_table + .set(identifier, Symbol::Array(decl, type_of.clone())) + .unwrap(); + + // TODO Initialization + + Ok(()) + } Decl::Func(identifier, return_type, vec_params, block) => { let vec_params = vec_params.clone().unwrap_or_default(); @@ -477,6 +553,32 @@ impl Emit<()> for Decl { function_type, ); + context + .symbol_table + .set( + identifier, + Symbol::Func( + function, + ( + return_type.clone().unwrap_or_default(), + vec_params + .iter() + .map(|param| match param { + FuncParam::Single(_, type_of) => { + type_of.clone() + } + FuncParam::Array(_, type_of) => { + Type::Agg(Box::new( + type_of.clone(), + )) + } + }) + .collect::>(), + ), + ), + ) + .unwrap(); + let entry_block = LLVMAppendBasicBlockInContext( context.context, function, @@ -501,7 +603,8 @@ impl Emit<()> for Decl { ); context .symbol_table - .set(identifier, Symbol::Variable(ptr_vlr)); + .set(identifier, Symbol::Variable(ptr_vlr, type_of.clone())) + .expect("Can't set the variable, probably the variable is already declared"); LLVMBuildStore( context.builder, @@ -521,7 +624,6 @@ impl Emit<()> for Decl { Ok(()) } - _ => panic!("Not implemented"), } } } diff --git a/src/gen/symbol_table.rs b/src/gen/symbol_table.rs index 3d01cf2..f5a6870 100644 --- a/src/gen/symbol_table.rs +++ b/src/gen/symbol_table.rs @@ -1,3 +1,4 @@ +use super::super::ast::Type; use std::collections::{HashMap, LinkedList}; use llvm::prelude::*; @@ -5,10 +6,9 @@ use llvm::prelude::*; // TODO Should store the type #[derive(Clone, Debug)] pub enum Symbol { - Variable(LLVMValueRef), - Array(u32, LLVMValueRef), - ArrayRef(LLVMValueRef), - Func(String), // TODO Should store tha function value and signature + Variable(LLVMValueRef, Type), + Array(LLVMValueRef, Type), + Func(LLVMValueRef, (Type, Vec)), // TODO Should store tha function value and signature } #[derive(Clone, Debug)] @@ -46,8 +46,17 @@ impl SymbolTable { /// This function only set a identifier in the scope, possibly it will /// overwrite the value thats is current in the actual scope - pub fn set(self: &mut Self, identifier: &str, symbol: Symbol) { + pub fn set( + self: &mut Self, + identifier: &str, + symbol: Symbol, + ) -> Result<(), ()> { let front = self.list.front_mut().unwrap(); - front.insert(identifier.to_string(), symbol); + if front.get(identifier).is_some() { + Err(()) + } else { + front.insert(identifier.to_string(), symbol); + Ok(()) + } } } From 6f3d77d08c43dcd099b5fc2443b2102f1556a86b Mon Sep 17 00:00:00 2001 From: Guilherme Chichanoski Date: Sun, 2 Dec 2018 16:51:09 -0200 Subject: [PATCH 05/19] start of error handling, pass the type of emited value --- src/ast.rs | 2 + src/gen/emit.rs | 244 +++++++++++++++++++++++++++++----------- src/gen/symbol_table.rs | 21 +++- 3 files changed, 193 insertions(+), 74 deletions(-) diff --git a/src/ast.rs b/src/ast.rs index 12826ac..89c7191 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -67,6 +67,7 @@ pub enum Type { Bool, Str, Void, + Agg(Box), } impl Default for Type { @@ -206,6 +207,7 @@ impl fmt::Debug for Type { Type::Bool => write!(f, "Bool"), Type::Str => write!(f, "Str"), Type::Void => write!(f, "Void"), + Type::Agg(type_of) => write!(f, "Agg({:?})", *type_of), } } } diff --git a/src/gen/emit.rs b/src/gen/emit.rs index 8e3418f..8f828ce 100644 --- a/src/gen/emit.rs +++ b/src/gen/emit.rs @@ -16,43 +16,54 @@ impl Emit<*mut LLVMType> for Type { Type::Bool => Ok(LLVMInt1TypeInContext(context.context)), Type::Void => Ok(LLVMVoidTypeInContext(context.context)), Type::Str => panic!("Not implemented"), + Type::Agg(_) => panic!("Not implemented"), } } } -impl Emit<*mut LLVMValue> for Variable { +impl Emit<(*mut LLVMValue, Type)> for Variable { unsafe fn emit( self: &Self, context: &mut Context, - ) -> Result<*mut LLVMValue, String> { + ) -> Result<(*mut LLVMValue, Type), String> { let builder = context.builder; match self { Variable::Single(identifier) => { if let Ok(value) = context.symbol_table.get(identifier) { match value { - Symbol::Variable(value) => Ok(*value), - _ => panic!("Variable type mismatch"), + Symbol::Variable(value, type_of) => { + Ok((*value, type_of.clone())) + } + _ => Err(format!( + "Variable {} type mismatch", + identifier + )), } } else { - Err(String::from("variabe not declared")) + Err("variabe not declared".to_string()) } } Variable::Array(identifier, expression) => { if let Ok(value) = context.clone().symbol_table.get(identifier) { - let index = expression.emit(context).unwrap(); + let (index, type_of_index) = + expression.emit(context).unwrap(); match value { - Symbol::ArrayRef(value) | Symbol::Array(_, value) => { - Ok(LLVMBuildInBoundsGEP( + Symbol::Array(value, type_of) => Ok(( + LLVMBuildInBoundsGEP( builder, *value, [index].as_mut_ptr(), 1, as_str!("ptr_value"), - )) - } - _ => Err("Variable type mismatch".to_string()), + ), + type_of.clone(), + )), + _ => Err(format!( + "Variable {} type mismatch", + identifier + )), } } else { Err("Variable not defined".to_string()) @@ -62,25 +73,35 @@ impl Emit<*mut LLVMValue> for Variable { } } -impl Emit<*mut LLVMValue> for Expr { +impl Emit<(*mut LLVMValue, Type)> for Expr { unsafe fn emit( self: &Self, context: &mut Context, - ) -> Result<*mut LLVMValue, String> { + ) -> Result<(*mut LLVMValue, Type), String> { match self { - Expr::Number(number) => { - Ok(LLVMConstInt(Type::Int.emit(context).unwrap(), *number, 1)) - } - Expr::True => { - Ok(LLVMConstInt(Type::Bool.emit(context).unwrap(), 1, 1)) - } - Expr::False => { - Ok(LLVMConstInt(Type::Bool.emit(context).unwrap(), 0, 1)) - } + Expr::Number(number) => Ok(( + LLVMConstInt(Type::Int.emit(context).unwrap(), *number, 1), + Type::Int, + )), + Expr::True => Ok(( + LLVMConstInt(Type::Bool.emit(context).unwrap(), 1, 1), + Type::Bool, + )), + Expr::False => Ok(( + LLVMConstInt(Type::Bool.emit(context).unwrap(), 0, 1), + Type::Bool, + )), Expr::Variable(var) => { - let ptr_var = var.emit(context).unwrap(); + let (ptr_var, type_of) = var.emit(context).unwrap(); - Ok(LLVMBuildLoad(context.builder, ptr_var, as_str!("var_load"))) + Ok(( + LLVMBuildLoad( + context.builder, + ptr_var, + as_str!("var_load"), + ), + type_of, + )) } Expr::Call(identifier, params) => { let builder = context.builder; @@ -89,23 +110,29 @@ impl Emit<*mut LLVMValue> for Expr { { match function { // TODO Put function value in symbols table - Symbol::Func(function) => { - let function = LLVMGetNamedFunction( - context.module, - as_str!(function), - ); + Symbol::Func(function, function_signature) => { let params = params.clone().unwrap_or_default(); - - Ok(LLVMBuildCall( - builder, - function, - params - .iter() - .map(|param| param.emit(context).unwrap()) - .collect::>() - .as_mut_ptr(), - params.len() as u32, - as_str!("call"), + let function_signature = function_signature.clone(); + + Ok(( + LLVMBuildCall( + builder, + *function, + params + .iter() + .zip(function_signature.1) + .map(|(param, param_expected_type)| { + let (value, type_of) = + param.emit(context).unwrap(); + // TODO Check type_of with function_signature + value + }) + .collect::>() + .as_mut_ptr(), + params.len() as u32, + as_str!("call"), + ), + function_signature.0, )) } _ => Err("Type mismatch".to_string()), @@ -116,8 +143,8 @@ impl Emit<*mut LLVMValue> for Expr { } Expr::Op(lhs, op, rhs) => { let builder = context.builder; - let lhs = lhs.emit(context).unwrap(); - let rhs = rhs.emit(context).unwrap(); + let (lhs, type_of_lhs) = lhs.emit(context).unwrap(); + let (rhs, type_of_rhs) = rhs.emit(context).unwrap(); let value = match op { Opcode::Add => { LLVMBuildAdd(builder, lhs, rhs, as_str!("add_result")) @@ -146,11 +173,11 @@ impl Emit<*mut LLVMValue> for Expr { ), _ => panic!("Not implemented"), }; - Ok(value) + Ok((value, Type::Int)) // FIXME type_of depend on the operand } Expr::Right(op, expression) => { let builder = context.builder; - let expression = expression.emit(context).unwrap(); + let (expression, type_of) = expression.emit(context).unwrap(); let value = match op { Opcode::Not => { LLVMBuildNot(builder, expression, as_str!("not_result")) @@ -162,7 +189,7 @@ impl Emit<*mut LLVMValue> for Expr { ), _ => panic!("Should not do this"), }; - Ok(value) + Ok((value, Type::Int)) // FIXME type_of depend on the operand } Expr::Ternary(_, _, _) => panic!("Not implemented yet"), } @@ -174,8 +201,9 @@ impl Emit<()> for Stmt { let builder = context.builder; match self { Stmt::Attr(var, expression) => { - let ptr_var = var.emit(context).unwrap(); - let expression = expression.emit(context).unwrap(); + let (ptr_var, type_of) = var.emit(context).unwrap(); + let (expression, type_of_expression) = + expression.emit(context).unwrap(); LLVMBuildStore(builder, expression, ptr_var); Ok(()) @@ -213,9 +241,11 @@ impl Emit<()> for Stmt { LLVMBuildBr(context.builder, block_predicate); LLVMPositionBuilderAtEnd(context.builder, block_predicate); + let (predicate, type_of_predicate) = + predicate.emit(context).unwrap(); LLVMBuildCondBr( context.builder, - predicate.emit(context).unwrap(), + predicate, block_for, block_merge, ); @@ -251,10 +281,12 @@ impl Emit<()> for Stmt { LLVMBuildBr(context.builder, block_predicate); + let (predicate, type_of_predicate) = + predicate.emit(context).unwrap(); LLVMPositionBuilderAtEnd(context.builder, block_predicate); LLVMBuildCondBr( context.builder, - predicate.emit(context).unwrap(), + predicate, block_while, block_merge, ); @@ -285,10 +317,9 @@ impl Emit<()> for Stmt { } Stmt::Return(expression) => { if let Some(expression) = expression { - LLVMBuildRet( - context.builder, - expression.emit(context).unwrap(), - ); + let (expression, type_of) = + expression.emit(context).unwrap(); + LLVMBuildRet(context.builder, expression); Ok(()) } else { LLVMBuildRetVoid(context.builder); @@ -348,9 +379,12 @@ impl Emit<()> for Stmt { context.builder, block_elif_predicate, ); + let (elif_predicate, type_of_elif_predicate) = + actual_block.0.emit(context).unwrap(); + LLVMBuildCondBr( context.builder, - actual_block.0.emit(context).unwrap(), + elif_predicate, block_elif_then, last_block, ); @@ -366,7 +400,8 @@ impl Emit<()> for Stmt { ); LLVMPositionBuilderAtEnd(context.builder, block_if_predicate); - let cmp_expression = expression.emit(context).unwrap(); + let (cmp_expression, type_of) = + expression.emit(context).unwrap(); LLVMBuildCondBr( context.builder, cmp_expression, @@ -411,20 +446,38 @@ impl Emit<()> for Decl { ); context .symbol_table - .set(identifier, Symbol::Variable(ptr_vlr)); + .set(identifier, Symbol::Variable(ptr_vlr, type_of.clone())) + .expect("Can't set the variable, probably the variable is already declared"); if let Some(expression) = expression { - LLVMBuildStore( - builder, - expression.emit(context).unwrap(), - ptr_vlr, - ); + let (expression, type_of_expression) = + expression.emit(context).unwrap(); + LLVMBuildStore(builder, expression, ptr_vlr); Ok(()) } else { Ok(()) } } - _ => panic!("Not implemented!"), + Decl::Array(identifier, type_of, size, list_expression) => { + let (expression_size, _) = + Expr::Number(*size).emit(context).unwrap(); + + let ptr_vlr = LLVMBuildArrayAlloca( + context.builder, + type_of.emit(context).unwrap(), + expression_size, + as_str!(identifier), + ); + context + .symbol_table + .set(identifier, Symbol::Array(ptr_vlr, type_of.clone())) + .expect("Can't set the variable, probably the variable is already declared"); + + // TODO Initialization + + Ok(()) + } + _ => Err("Function not expected".to_string()), } } else { // When global @@ -436,16 +489,45 @@ impl Emit<()> for Decl { as_str!(identifier), ); + context + .symbol_table + .set( + identifier, + Symbol::Variable(decl, type_of.clone()), + ) + .unwrap(); + if let Some(expression) = expression { - LLVMSetInitializer( - decl, - expression.emit(context).unwrap(), - ); + let (value, type_of) = + expression.emit(context).unwrap(); + + LLVMSetInitializer(decl, value); Ok(()) } else { Ok(()) } } + Decl::Array(identifier, type_of, size, list_expression) => { + let array_type = LLVMArrayType( + type_of.emit(context).unwrap(), + *size as u32, + ); + + let decl = LLVMAddGlobal( + context.module, + array_type, + as_str!(identifier), + ); + + context + .symbol_table + .set(identifier, Symbol::Array(decl, type_of.clone())) + .unwrap(); + + // TODO Initialization + + Ok(()) + } Decl::Func(identifier, return_type, vec_params, block) => { let vec_params = vec_params.clone().unwrap_or_default(); @@ -477,6 +559,32 @@ impl Emit<()> for Decl { function_type, ); + context + .symbol_table + .set( + identifier, + Symbol::Func( + function, + ( + return_type.clone().unwrap_or_default(), + vec_params + .iter() + .map(|param| match param { + FuncParam::Single(_, type_of) => { + type_of.clone() + } + FuncParam::Array(_, type_of) => { + Type::Agg(Box::new( + type_of.clone(), + )) + } + }) + .collect::>(), + ), + ), + ) + .unwrap(); + let entry_block = LLVMAppendBasicBlockInContext( context.context, function, @@ -501,7 +609,8 @@ impl Emit<()> for Decl { ); context .symbol_table - .set(identifier, Symbol::Variable(ptr_vlr)); + .set(identifier, Symbol::Variable(ptr_vlr, type_of.clone())) + .expect("Can't set the variable, probably the variable is already declared"); LLVMBuildStore( context.builder, @@ -521,7 +630,6 @@ impl Emit<()> for Decl { Ok(()) } - _ => panic!("Not implemented"), } } } diff --git a/src/gen/symbol_table.rs b/src/gen/symbol_table.rs index 3d01cf2..f5a6870 100644 --- a/src/gen/symbol_table.rs +++ b/src/gen/symbol_table.rs @@ -1,3 +1,4 @@ +use super::super::ast::Type; use std::collections::{HashMap, LinkedList}; use llvm::prelude::*; @@ -5,10 +6,9 @@ use llvm::prelude::*; // TODO Should store the type #[derive(Clone, Debug)] pub enum Symbol { - Variable(LLVMValueRef), - Array(u32, LLVMValueRef), - ArrayRef(LLVMValueRef), - Func(String), // TODO Should store tha function value and signature + Variable(LLVMValueRef, Type), + Array(LLVMValueRef, Type), + Func(LLVMValueRef, (Type, Vec)), // TODO Should store tha function value and signature } #[derive(Clone, Debug)] @@ -46,8 +46,17 @@ impl SymbolTable { /// This function only set a identifier in the scope, possibly it will /// overwrite the value thats is current in the actual scope - pub fn set(self: &mut Self, identifier: &str, symbol: Symbol) { + pub fn set( + self: &mut Self, + identifier: &str, + symbol: Symbol, + ) -> Result<(), ()> { let front = self.list.front_mut().unwrap(); - front.insert(identifier.to_string(), symbol); + if front.get(identifier).is_some() { + Err(()) + } else { + front.insert(identifier.to_string(), symbol); + Ok(()) + } } } From ce60c72acdafa29c43fd8f54a525e648ee958a3d Mon Sep 17 00:00:00 2001 From: Guilherme Chichanoski Date: Sun, 2 Dec 2018 22:47:30 -0200 Subject: [PATCH 06/19] add location and types to handle errors --- src/ast.rs | 136 ++++++++++++--------- src/gen/emit.rs | 160 +++++++++++++++---------- src/grammar/mod.lalrpop | 260 +++++++++++++++++++++++++++++----------- 3 files changed, 367 insertions(+), 189 deletions(-) diff --git a/src/ast.rs b/src/ast.rs index 89c7191..8a601e1 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -1,6 +1,10 @@ use llvm::LLVMIntPredicate; use std::fmt; +use codespan::{ByteIndex, Span}; + +pub type Location = Span; + #[macro_export] macro_rules! flatten { ($v:ident) => { @@ -24,14 +28,14 @@ fn get_tabs(f: &fmt::Formatter) -> (usize, String) { #[derive(Clone, PartialEq)] pub enum Expr { - Number(u64), - Variable(Variable), - True, - False, - Call(String, Option>>), - Op(Box, Opcode, Box), - Right(Opcode, Box), - Ternary(Box, Box, Box), + Number(u64, Location), + Variable(Variable, Location), + True(Location), + False(Location), + Call(String, Option>>, Location), + Op(Box, Opcode, Box, Location), + Right(Opcode, Box, Location), + Ternary(Box, Box, Box, Location), } #[derive(Clone, PartialEq)] @@ -78,35 +82,47 @@ impl Default for Type { #[derive(Clone, PartialEq)] pub enum Variable { - Single(String), - Array(String, Box), + Single(String, Location), + Array(String, Box, Location), } #[derive(Clone, PartialEq)] pub enum Decl { - Single(String, Type, Option>), - Array(String, Type, u64, Option>>), - Func(String, Option, Option>, Block), + Single(String, Type, Option>, Location), + Array(String, Type, u64, Option>>, Location), + Func( + String, + Option, + Option>, + Block, + Location, + ), } #[derive(Clone, PartialEq)] pub enum FuncParam { - Single(String, Type), - Array(String, Type), + Single(String, Type, Location), + Array(String, Type, Location), } #[derive(Clone, PartialEq)] pub enum Stmt { - Attr(Variable, Box), - Stop, - Skip, - Return(Option>), - Read(Variable), - Write(Vec>), - Call(String, Option>>), - If(Box, Block, Vec<(Box, Block)>, Option), - While(Box, Block), - For(Box, Box, Box, Block), + Attr(Variable, Box, Location), + Stop(Location), + Skip(Location), + Return(Option>, Location), + Read(Variable, Location), + Write(Vec>, Location), + Call(String, Option>>, Location), + If( + Box, + Block, + Vec<(Box, Block)>, + Option, + Location, + ), + While(Box, Block, Location), + For(Box, Box, Box, Block, Location), } #[derive(Clone, PartialEq)] @@ -125,26 +141,28 @@ impl fmt::Debug for Expr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let (width, tabs) = get_tabs(f); match self { - Expr::Number(i) => write!(f, "${:?}", i), - Expr::Variable(v) => { + Expr::Number(i, _) => write!(f, "${:?}", i), + Expr::Variable(v, _) => { write!(f, "{tabs}{:width$?}", v, tabs = tabs, width = width + 1) } - Expr::True => write!(f, "$true"), - Expr::False => write!(f, "$false"), + Expr::True(_) => write!(f, "$true"), + Expr::False(_) => write!(f, "$false"), - Expr::Call(fun, Some(p)) => write!( + Expr::Call(fun, Some(p), _) => write!( f, "(Call {:width$?} with params {:?})", fun, p, width = width + 1 ), - Expr::Call(fun, _) => { + Expr::Call(fun, _, _) => { write!(f, "(Call {:width$?})", fun, width = width + 1) } - Expr::Op(l, o, r) => write!(f, "({:?} of {:?} and {:?})", o, l, r,), - Expr::Right(o, e) => write!( + Expr::Op(l, o, r, _) => { + write!(f, "({:?} of {:?} and {:?})", o, l, r,) + } + Expr::Right(o, e, _) => write!( f, "{tabs}({:width$?} of {:width$?})", o, @@ -152,7 +170,7 @@ impl fmt::Debug for Expr { tabs = tabs, width = width + 1 ), - Expr::Ternary(c, t, _f) => write!( + Expr::Ternary(c, t, _f, _) => write!( f, "{tabs}(If {:?} Then {:?} Else {:?})", c, @@ -215,8 +233,10 @@ impl fmt::Debug for Type { impl fmt::Debug for Variable { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - Variable::Single(i) => write!(f, "(Var {:?})", i), - Variable::Array(i, s) => write!(f, "(Arr {:?} at pos {:?})", i, s), + Variable::Single(i, _) => write!(f, "(Var {:?})", i), + Variable::Array(i, s, _) => { + write!(f, "(Arr {:?} at pos {:?})", i, s) + } } } } @@ -225,7 +245,7 @@ impl fmt::Debug for Decl { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let (width, tabs) = get_tabs(f); match self { - Decl::Single(i, t, Some(e)) => write!( + Decl::Single(i, t, Some(e), _) => write!( f, "{tabs}({:width$?} of type {:width$?} with value {:width$?})", i, @@ -235,7 +255,7 @@ impl fmt::Debug for Decl { width = width + 1 ), - Decl::Single(i, t, _) => write!( + Decl::Single(i, t, _, _) => write!( f, "{tabs}({:width$?} of type {:width$?})", i, @@ -244,7 +264,7 @@ impl fmt::Debug for Decl { width = width + 1 ), - Decl::Array(i, t, s, Some(e)) => write!( + Decl::Array(i, t, s, Some(e), _) => write!( f, "{tabs}([{:width$?}] of size {:width$?} of type {:width$?} with values {:width$?})", i, @@ -255,7 +275,7 @@ impl fmt::Debug for Decl { width = width + 1 ), - Decl::Array(i, t, s, _) => write!( + Decl::Array(i, t, s, _, _) => write!( f, "{tabs}([{:width$?}] of size {:width$?} of type {:width$?})", i, @@ -265,7 +285,7 @@ impl fmt::Debug for Decl { width = width + 1 ), - Decl::Func(i, Some(t), Some(p), b) => write!( + Decl::Func(i, Some(t), Some(p), b, _) => write!( f, "{tabs}(func {:?}\n {tabs}with params ({:?})\n {tabs}returning ({:width$?})\n {tabs}executing (\n{:width$?}\n {tabs}))", i, @@ -276,7 +296,7 @@ impl fmt::Debug for Decl { width = width + 3 ), - Decl::Func(i, Some(t), _, b) => write!( + Decl::Func(i, Some(t), _, b, _) => write!( f, "{tabs}(func {:?} with no params\n {tabs}returning ({:width$?})\n {tabs}executing (\n{:width$?})\n {tabs})", i, @@ -286,7 +306,7 @@ impl fmt::Debug for Decl { width = width + 3 ), - Decl::Func(i, _, Some(p), b) => write!( + Decl::Func(i, _, Some(p), b, _) => write!( f, "{tabs}(proc {:?}\n {tabs}with params ({:?})\n {tabs}executing (\n{:width$?})\n {tabs})", i, @@ -296,7 +316,7 @@ impl fmt::Debug for Decl { width = width + 3 ), - Decl::Func(i, _, _, b) => write!( + Decl::Func(i, _, _, b, _) => write!( f, "{tabs}(proc {:?} with no params executing (\n{:width$?})\n {tabs})", i, @@ -312,7 +332,7 @@ impl fmt::Debug for FuncParam { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let (width, tabs) = get_tabs(f); match self { - FuncParam::Single(i, t) => write!( + FuncParam::Single(i, t, _) => write!( f, "{tabs}(Param {:width$?}, {:width$?})", i, @@ -320,7 +340,7 @@ impl fmt::Debug for FuncParam { tabs = tabs, width = width + 1 ), - FuncParam::Array(i, t) => write!( + FuncParam::Array(i, t, _) => write!( f, "{tabs}(Param {:width$?}[], {:width$?})", i, @@ -336,36 +356,36 @@ impl fmt::Debug for Stmt { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let (width, tabs) = get_tabs(f); match self { - Stmt::Attr(v, e) => write!( + Stmt::Attr(v, e, _) => write!( f, "(Attr {:?} receives {:?})", v, e, ), - Stmt::Stop => write!(f, "Stop"), - Stmt::Skip => write!(f, "Skip"), + Stmt::Stop(_) => write!(f, "Stop"), + Stmt::Skip(_) => write!(f, "Skip"), - Stmt::Return(Some(a)) => { + Stmt::Return(Some(a), _) => { write!(f, "(Return {:?})", a) } - Stmt::Return(_) => write!(f, "Return"), + Stmt::Return(_, _) => write!(f, "Return"), - Stmt::Read(v) => write!(f, "(Read {:?})", v), - Stmt::Write(v) => write!(f, "(Write {:?})", v), + Stmt::Read(v, _) => write!(f, "(Read {:?})", v), + Stmt::Write(v, _) => write!(f, "(Write {:?})", v), - Stmt::Call(fun, Some(p)) => write!( + Stmt::Call(fun, Some(p), _) => write!( f, "(Call {:width$?} with params {:?})", fun, p, width = width + 1 ), - Stmt::Call(fun, _) => { + Stmt::Call(fun, _, _) => { write!(f, "(Call {:width$?})", fun, width = width + 1) } - Stmt::If(expr, b, _elif, _else) => { + Stmt::If(expr, b, _elif, _else, _) => { write!( f, "(If {:?} then (\n{:width$?})", expr, b, width = width + 1)?; if _elif.is_empty() { write!(f, " no elseifs")?; @@ -384,7 +404,7 @@ impl fmt::Debug for Stmt { } }, - Stmt::While(e, b) => write!( + Stmt::While(e, b, _) => write!( f, "(While {:?} do(\n{:width$?}\n{tabs}))", e, @@ -392,7 +412,7 @@ impl fmt::Debug for Stmt { tabs = tabs, width = width + 1 ), - Stmt::For(i, t, s, b) => { + Stmt::For(i, t, s, b, _) => { write!( f, "(For\n {tabs}with init {:?}\n {tabs}and with test {:?}\n {tabs}and with step {:?}\n {tabs}then do(\n{:width$?}\n{tabs}))", diff --git a/src/gen/emit.rs b/src/gen/emit.rs index 8f828ce..91f55a2 100644 --- a/src/gen/emit.rs +++ b/src/gen/emit.rs @@ -3,14 +3,17 @@ use llvm::{core::*, *}; use std::ffi::CString; pub trait Emit { - unsafe fn emit(self: &Self, context: &mut Context) -> Result; + unsafe fn emit( + self: &Self, + context: &mut Context, + ) -> Result; } impl Emit<*mut LLVMType> for Type { unsafe fn emit( self: &Self, context: &mut Context, - ) -> Result<*mut LLVMType, String> { + ) -> Result<*mut LLVMType, (String, Location)> { match self { Type::Int => Ok(LLVMInt64TypeInContext(context.context)), Type::Bool => Ok(LLVMInt1TypeInContext(context.context)), @@ -25,25 +28,25 @@ impl Emit<(*mut LLVMValue, Type)> for Variable { unsafe fn emit( self: &Self, context: &mut Context, - ) -> Result<(*mut LLVMValue, Type), String> { + ) -> Result<(*mut LLVMValue, Type), (String, Location)> { let builder = context.builder; match self { - Variable::Single(identifier) => { + Variable::Single(identifier, location) => { if let Ok(value) = context.symbol_table.get(identifier) { match value { Symbol::Variable(value, type_of) => { Ok((*value, type_of.clone())) } - _ => Err(format!( - "Variable {} type mismatch", - identifier + _ => Err(( + format!("Variable {} type mismatch", identifier), + *location, )), } } else { - Err("variabe not declared".to_string()) + Err(("variabe not declared".to_string(), *location)) } } - Variable::Array(identifier, expression) => { + Variable::Array(identifier, expression, location) => { if let Ok(value) = context.clone().symbol_table.get(identifier) { let (index, type_of_index) = @@ -60,13 +63,13 @@ impl Emit<(*mut LLVMValue, Type)> for Variable { ), type_of.clone(), )), - _ => Err(format!( - "Variable {} type mismatch", - identifier + _ => Err(( + format!("Variable {} type mismatch", identifier), + *location, )), } } else { - Err("Variable not defined".to_string()) + Err(("Variable not defined".to_string(), *location)) } } } @@ -77,21 +80,21 @@ impl Emit<(*mut LLVMValue, Type)> for Expr { unsafe fn emit( self: &Self, context: &mut Context, - ) -> Result<(*mut LLVMValue, Type), String> { + ) -> Result<(*mut LLVMValue, Type), (String, Location)> { match self { - Expr::Number(number) => Ok(( + Expr::Number(number, location) => Ok(( LLVMConstInt(Type::Int.emit(context).unwrap(), *number, 1), Type::Int, )), - Expr::True => Ok(( + Expr::True(location) => Ok(( LLVMConstInt(Type::Bool.emit(context).unwrap(), 1, 1), Type::Bool, )), - Expr::False => Ok(( + Expr::False(location) => Ok(( LLVMConstInt(Type::Bool.emit(context).unwrap(), 0, 1), Type::Bool, )), - Expr::Variable(var) => { + Expr::Variable(var, location) => { let (ptr_var, type_of) = var.emit(context).unwrap(); Ok(( @@ -103,7 +106,7 @@ impl Emit<(*mut LLVMValue, Type)> for Expr { type_of, )) } - Expr::Call(identifier, params) => { + Expr::Call(identifier, params, location) => { let builder = context.builder; if let Ok(function) = context.clone().symbol_table.get(identifier) @@ -135,13 +138,13 @@ impl Emit<(*mut LLVMValue, Type)> for Expr { function_signature.0, )) } - _ => Err("Type mismatch".to_string()), + _ => Err(("Type mismatch".to_string(), *location)), } } else { - Err("Identifier not declared".to_string()) + Err(("Identifier not declared".to_string(), *location)) } } - Expr::Op(lhs, op, rhs) => { + Expr::Op(lhs, op, rhs, location) => { let builder = context.builder; let (lhs, type_of_lhs) = lhs.emit(context).unwrap(); let (rhs, type_of_rhs) = rhs.emit(context).unwrap(); @@ -175,7 +178,7 @@ impl Emit<(*mut LLVMValue, Type)> for Expr { }; Ok((value, Type::Int)) // FIXME type_of depend on the operand } - Expr::Right(op, expression) => { + Expr::Right(op, expression, location) => { let builder = context.builder; let (expression, type_of) = expression.emit(context).unwrap(); let value = match op { @@ -191,16 +194,21 @@ impl Emit<(*mut LLVMValue, Type)> for Expr { }; Ok((value, Type::Int)) // FIXME type_of depend on the operand } - Expr::Ternary(_, _, _) => panic!("Not implemented yet"), + Expr::Ternary(_predicate, _then, _else, _location) => { + panic!("Not implemented yet") + } } } } impl Emit<()> for Stmt { - unsafe fn emit(self: &Self, context: &mut Context) -> Result<(), String> { + unsafe fn emit( + self: &Self, + context: &mut Context, + ) -> Result<(), (String, Location)> { let builder = context.builder; match self { - Stmt::Attr(var, expression) => { + Stmt::Attr(var, expression, location) => { let (ptr_var, type_of) = var.emit(context).unwrap(); let (expression, type_of_expression) = expression.emit(context).unwrap(); @@ -208,13 +216,17 @@ impl Emit<()> for Stmt { LLVMBuildStore(builder, expression, ptr_var); Ok(()) } - Stmt::Call(identifier, expressions) => { - Expr::Call(identifier.to_string(), expressions.clone()) - .emit(context) - .unwrap(); + Stmt::Call(identifier, expressions, location) => { + Expr::Call( + identifier.to_string(), + expressions.clone(), + *location, + ) + .emit(context) + .unwrap(); Ok(()) } - Stmt::For(init, predicate, step, block) => { + Stmt::For(init, predicate, step, block, location) => { init.emit(context).unwrap(); let block_predicate = LLVMAppendBasicBlockInContext( context.context, @@ -261,7 +273,7 @@ impl Emit<()> for Stmt { Ok(()) } - Stmt::While(predicate, block) => { + Stmt::While(predicate, block, location) => { let block_predicate = LLVMAppendBasicBlockInContext( context.context, context.actual_function.unwrap().0, @@ -299,23 +311,23 @@ impl Emit<()> for Stmt { Ok(()) } - Stmt::Stop => { + Stmt::Stop(location) => { if let Some((merge, _)) = context.actual_loop { LLVMBuildBr(context.builder, merge); Ok(()) } else { - Err("Stop not in a loop".to_string()) + Err(("Stop not in a loop".to_string(), *location)) } } - Stmt::Skip => { + Stmt::Skip(location) => { if let Some((_, predicate)) = context.actual_loop { LLVMBuildBr(context.builder, predicate); Ok(()) } else { - Err("Skip not in a loop".to_string()) + Err(("Skip not in a loop".to_string(), *location)) } } - Stmt::Return(expression) => { + Stmt::Return(expression, location) => { if let Some(expression) = expression { let (expression, type_of) = expression.emit(context).unwrap(); @@ -326,7 +338,7 @@ impl Emit<()> for Stmt { Ok(()) } } - Stmt::If(expression, block, elifs, else_block) => { + Stmt::If(expression, block, elifs, else_block, location) => { let block_if_predicate = LLVMAppendBasicBlockInContext( context.context, context.actual_function.unwrap().0, @@ -421,7 +433,10 @@ impl Emit<()> for Stmt { } impl Emit<()> for Decl { - unsafe fn emit(self: &Self, context: &mut Context) -> Result<(), String> { + unsafe fn emit( + self: &Self, + context: &mut Context, + ) -> Result<(), (String, Location)> { if context.actual_function.is_some() { // When local let alloc_builder = LLVMCreateBuilderInContext(context.context); @@ -438,7 +453,7 @@ impl Emit<()> for Decl { let builder = context.builder; match self { - Decl::Single(identifier, type_of, expression) => { + Decl::Single(identifier, type_of, expression, location) => { let ptr_vlr = LLVMBuildAlloca( alloc_builder, type_of.emit(context).unwrap(), @@ -458,9 +473,15 @@ impl Emit<()> for Decl { Ok(()) } } - Decl::Array(identifier, type_of, size, list_expression) => { + Decl::Array( + identifier, + type_of, + size, + list_expression, + location, + ) => { let (expression_size, _) = - Expr::Number(*size).emit(context).unwrap(); + Expr::Number(*size, *location).emit(context).unwrap(); let ptr_vlr = LLVMBuildArrayAlloca( context.builder, @@ -477,12 +498,12 @@ impl Emit<()> for Decl { Ok(()) } - _ => Err("Function not expected".to_string()), + _ => panic!("Function not expected".to_string()), } } else { // When global match self { - Decl::Single(identifier, type_of, expression) => { + Decl::Single(identifier, type_of, expression, location) => { let decl = LLVMAddGlobal( context.module, type_of.emit(context).unwrap(), @@ -502,12 +523,17 @@ impl Emit<()> for Decl { expression.emit(context).unwrap(); LLVMSetInitializer(decl, value); - Ok(()) - } else { - Ok(()) } + + Ok(()) } - Decl::Array(identifier, type_of, size, list_expression) => { + Decl::Array( + identifier, + type_of, + size, + list_expression, + location, + ) => { let array_type = LLVMArrayType( type_of.emit(context).unwrap(), *size as u32, @@ -528,16 +554,22 @@ impl Emit<()> for Decl { Ok(()) } - Decl::Func(identifier, return_type, vec_params, block) => { + Decl::Func( + identifier, + return_type, + vec_params, + block, + location, + ) => { let vec_params = vec_params.clone().unwrap_or_default(); let mut args = vec_params .iter() .map(|param| match param { - FuncParam::Single(_, type_of) => { + FuncParam::Single(_, type_of, _) => { type_of.emit(context).unwrap() } - FuncParam::Array(_, type_of) => { + FuncParam::Array(_, type_of, _) => { type_of.emit(context).unwrap() } }) @@ -570,10 +602,12 @@ impl Emit<()> for Decl { vec_params .iter() .map(|param| match param { - FuncParam::Single(_, type_of) => { - type_of.clone() - } - FuncParam::Array(_, type_of) => { + FuncParam::Single( + _, + type_of, + _, + ) => type_of.clone(), + FuncParam::Array(_, type_of, _) => { Type::Agg(Box::new( type_of.clone(), )) @@ -601,7 +635,7 @@ impl Emit<()> for Decl { LLVMGetParam(function, index as u32); match param { - FuncParam::Single(identifier, type_of) => { + FuncParam::Single(identifier, type_of, location) => { let ptr_vlr = LLVMBuildAlloca( context.builder, type_of.emit(context).unwrap(), @@ -609,7 +643,7 @@ impl Emit<()> for Decl { ); context .symbol_table - .set(identifier, Symbol::Variable(ptr_vlr, type_of.clone())) + .set(&identifier, Symbol::Variable(ptr_vlr, type_of.clone())) .expect("Can't set the variable, probably the variable is already declared"); LLVMBuildStore( @@ -618,7 +652,7 @@ impl Emit<()> for Decl { ptr_vlr, ); } - FuncParam::Array(_identifier, _type_of) => { + FuncParam::Array(_identifier, _type_of, location) => { panic!("Not implemented yet") } } @@ -636,7 +670,10 @@ impl Emit<()> for Decl { } impl Emit<()> for Block { - unsafe fn emit(self: &Self, context: &mut Context) -> Result<(), String> { + unsafe fn emit( + self: &Self, + context: &mut Context, + ) -> Result<(), (String, Location)> { context.symbol_table.initialize_scope(); self.decl .iter() @@ -652,7 +689,10 @@ impl Emit<()> for Block { } impl Emit<()> for Either { - unsafe fn emit(self: &Self, context: &mut Context) -> Result<(), String> { + unsafe fn emit( + self: &Self, + context: &mut Context, + ) -> Result<(), (String, Location)> { match self { Either::Left(stmt) => stmt.emit(context).unwrap(), Either::Right(block) => block.emit(context).unwrap(), diff --git a/src/grammar/mod.lalrpop b/src/grammar/mod.lalrpop index 11936a5..db09872 100644 --- a/src/grammar/mod.lalrpop +++ b/src/grammar/mod.lalrpop @@ -1,4 +1,5 @@ use lalrpop_util::{ ErrorRecovery }; +use codespan::{ ByteIndex, Span }; use std::str::FromStr; use ast::*; @@ -57,12 +58,24 @@ Num: u64 = r"[0-9]+" => u64::from_str(<>).unwrap(); Id: String = r"[a-zA-Z_][a-zA-Z0-9_]*" => String::from(<>); Var: Variable = { - OPEN_BRACKET CLOSE_BRACKET => Variable::Array(<>), - => Variable::Single(<>), + OPEN_BRACKET CLOSE_BRACKET => { + let location = Span::new(ByteIndex(l as u32), ByteIndex(r as u32)); + + Variable::Array(i, e, location) + }, + => { + let location = Span::new(ByteIndex(l as u32), ByteIndex(r as u32)); + + Variable::Single(i, location) + } }; Tier: Box = { - Tier Op Next => Box::new(Expr::Op(<>)), + > => { + let location = Span::new(ByteIndex(l as u32), ByteIndex(r as u32)); + + Box::new(Expr::Op(e1, o, e2, location)) + }, Next, }; @@ -88,23 +101,51 @@ Either: (Option, Option) = { }; Term: Box = { - TRUE => Box::new(Expr::True), - FALSE => Box::new(Expr::False), - Num => Box::new(Expr::Number(<>)), - Var => Box::new(Expr::Variable(<>)), - OPEN_PARENS ?> CLOSE_PARENS => Box::new(Expr::Call(<>)), + TRUE => { + let location = Span::new(ByteIndex(l as u32), ByteIndex(r as u32)); + + Box::new(Expr::True(location)) + }, + FALSE => { + let location = Span::new(ByteIndex(l as u32), ByteIndex(r as u32)); + + Box::new(Expr::False(location)) + }, + => { + let location = Span::new(ByteIndex(l as u32), ByteIndex(r as u32)); + + Box::new(Expr::Number(n, location)) + }, + => { + let location = Span::new(ByteIndex(l as u32), ByteIndex(r as u32)); + + Box::new(Expr::Variable(v, location)) + }, + OPEN_PARENS ?> CLOSE_PARENS => { + let location = Span::new(ByteIndex(l as u32), ByteIndex(r as u32)); + + Box::new(Expr::Call(i, e, location)) + }, OPEN_PARENS CLOSE_PARENS, }; NegativeOp: Opcode = MINUS => Opcode::Negative; Negative: Box = { - NegativeOp Term => Box::new(Expr::Right(<>)), + => { + let location = Span::new(ByteIndex(l as u32), ByteIndex(r as u32)); + + Box::new(Expr::Right(o, e, location)) + }, Term, }; NotOp: Opcode = EXCLAMATION => Opcode::Not; Not: Box = { - NotOp Negative=> Box::new(Expr::Right(<>)), + => { + let location = Span::new(ByteIndex(l as u32), ByteIndex(r as u32)); + + Box::new(Expr::Right(o, e, location)) + }, Negative, }; @@ -146,7 +187,11 @@ OrOp: Opcode = PIPE PIPE => Opcode::Or; Or = Tier; Ternary: Box = { - QUESTION COLON => Box::new(Expr::Ternary(<>)), + QUESTION COLON => { + let location = Span::new(ByteIndex(l as u32), ByteIndex(r as u32)); + + Box::new(Expr::Ternary(p, t, e, location)) + }, Or, }; @@ -158,15 +203,30 @@ Type: Type = { STR => Type::Str, }; -VarArrayDecl: (String, u64, Option>>) = { - // TODO Possible error recovery is when a user insert an expression in place of a number - OPEN_BRACKET CLOSE_BRACKET EQUAL OPEN_BRACE > CLOSE_BRACE => (a, n, Some(f)), - OPEN_BRACKET CLOSE_BRACKET => (a, n, None), +VarArrayDecl: (String, u64, Option>>, Span) = { + OPEN_BRACKET CLOSE_BRACKET EQUAL OPEN_BRACE > CLOSE_BRACE => { + let location = Span::new(ByteIndex(l as u32), ByteIndex(r as u32)); + + (a, n, Some(f), location) + }, + OPEN_BRACKET CLOSE_BRACKET => { + let location = Span::new(ByteIndex(l as u32), ByteIndex(r as u32)); + + (a, n, None, location) + } }; -VarSingleDecl: (String, Option>) = { - EQUAL => (i, Some(e)), - => (<>, None), +VarSingleDecl: (String, Option>, Span) = { + EQUAL => { + let location = Span::new(ByteIndex(l as u32), ByteIndex(r as u32)); + + (i, Some(e), location) + }, + => { + let location = Span::new(ByteIndex(l as u32), ByteIndex(r as u32)); + + (i, None, location) + } }; VarDeclList = Comma>; @@ -176,39 +236,47 @@ VarDecl: Vec = { let mut f = Vec::new(); for i in d { if let Some(j) = i.0 { - f.push(Decl::Single(j.0, t.clone(), j.1)); + f.push(Decl::Single(j.0, t.clone(), j.1, j.2)); } else if let Some(j) = i.1 { - f.push(Decl::Array(j.0, t.clone(), j.1, j.2)); + f.push(Decl::Array(j.0, t.clone(), j.1, j.2, j.3)); } } f }, }; -ParamArrayDecl: String = { - OPEN_BRACKET CLOSE_BRACKET => <>, +ParamArrayDecl: (String, Span) = { + OPEN_BRACKET CLOSE_BRACKET => { + let location = Span::new(ByteIndex(l as u32), ByteIndex(r as u32)); + + (i, location) + }, }; -ParamSingleDecl: String = { - => <>, +ParamSingleDecl: (String, Span) = { + => { + let location = Span::new(ByteIndex(l as u32), ByteIndex(r as u32)); + + (i, location) + }, }; ParamDeclList = Comma>; -FuncDecl: Decl = DEF OPEN_PARENS COLON )>?> CLOSE_PARENS )?> => { - // TODO Register the location of function declaration to show to the user in case of redeclaration +FuncDecl: Decl = DEF OPEN_PARENS COLON )>?> CLOSE_PARENS )?> => { let mut parameters_vector = Vec::new(); + let location = Span::new(ByteIndex(l as u32), ByteIndex(r as u32)); + if let Some(parameter_list) = p { for parameter in parameter_list { // parameter is an tuple of (list, type) - let declaration_list = parameter.0; - let type_of = parameter.1; + let ( declaration_list, type_of ) = parameter; for declaration in declaration_list { // !! The declaration is a parser Either not an AST::Either - if let Some(identifier) = declaration.0 { // If either is fullfiled in the left is a single variable - parameters_vector.push(FuncParam::Single(identifier, type_of.clone())); - } else if let Some(identifier) = declaration.1 { // Else if is fullfiled in the right side is an array - parameters_vector.push(FuncParam::Array(identifier, type_of.clone())); + if let Some((identifier, location)) = declaration.0 { // If either is fullfiled in the left is a single variable + parameters_vector.push(FuncParam::Single(identifier, type_of.clone(), location)); + } else if let Some((identifier, location)) = declaration.1 { // Else if is fullfiled in the right side is an array + parameters_vector.push(FuncParam::Array(identifier, type_of.clone(), location)); } } } @@ -216,9 +284,9 @@ FuncDecl: Decl = DEF OPEN_PARENS COLON function return type, could be None, when it's a procedure // parameter_list -- Could be None, when it does not have any parameter // b -> function block - Decl::Func(i, t, Some(parameters_vector), b) // When have parameters + Decl::Func(i, t, Some(parameters_vector), b, location) // When have parameters } else { - Decl::Func(i, t, None, b) // When does not have parameter + Decl::Func(i, t, None, b, location) // When does not have parameter } }; @@ -227,8 +295,12 @@ Decl: Vec = { FuncDecl => vec![<>], }; -Attr: (Variable, Box) = { - => (v.clone(), Box::new(Expr::Op(Box::new(Expr::Variable(v)), o, e))), +Attr: (Variable, Box, Span) = { + => { + let location = Span::new(ByteIndex(l as u32), ByteIndex(r as u32)); + + (v.clone(), Box::new(Expr::Op(Box::new(Expr::Variable(v, location)), o, e, location)), location) + } }; AddEqual: Opcode = PLUS EQUAL => Opcode::Add; @@ -238,52 +310,98 @@ DivEqual: Opcode = SLASH EQUAL => Opcode::Div; ModEqual: Opcode = PERCENT EQUAL => Opcode::Mod; AllAttr: Stmt = { - EQUAL => Stmt::Attr(v, e), - PLUS PLUS => Stmt::Attr( - v.clone(), - Box::new( - Expr::Op( - Box::new(Expr::Variable(v)), - Opcode::Add, - Box::new(Expr::Number(1)) - ) + EQUAL => { + let location = Span::new(ByteIndex(l as u32), ByteIndex(r as u32)); + + Stmt::Attr(v, e, location) + }, + PLUS PLUS => { + let location = Span::new(ByteIndex(l as u32), ByteIndex(r as u32)); + + Stmt::Attr( + v.clone(), + Box::new( + Expr::Op( + Box::new(Expr::Variable(v, location)), + Opcode::Add, + Box::new(Expr::Number(1, location)), + location + ) + ), + location ) - ), - MINUS MINUS => Stmt::Attr( - v.clone(), - Box::new( - Expr::Op( - Box::new(Expr::Variable(v)), - Opcode::Sub, - Box::new(Expr::Number(1)) - ) + }, + MINUS MINUS => { + let location = Span::new(ByteIndex(l as u32), ByteIndex(r as u32)); + + Stmt::Attr( + v.clone(), + Box::new( + Expr::Op( + Box::new(Expr::Variable(v, location)), + Opcode::Sub, + Box::new(Expr::Number(1, location)), + location + ) + ), + location ) - ), - > => Stmt::Attr(a.0, a.1), - > => Stmt::Attr(a.0, a.1), - > => Stmt::Attr(a.0, a.1), - > => Stmt::Attr(a.0, a.1), - > => Stmt::Attr(a.0, a.1), + }, + > => Stmt::Attr(a.0, a.1, a.2), + > => Stmt::Attr(a.0, a.1, a.2), + > => Stmt::Attr(a.0, a.1, a.2), + > => Stmt::Attr(a.0, a.1, a.2), + > => Stmt::Attr(a.0, a.1, a.2), }; Stmt: Stmt = { SEMICOLON => <>, - SKIP SEMICOLON => Stmt::Skip, - STOP SEMICOLON => Stmt::Stop, - RETURN SEMICOLON => Stmt::Return(<>), + SKIP SEMICOLON => { + let location = Span::new(ByteIndex(l as u32), ByteIndex(r as u32)); - READ SEMICOLON => Stmt::Read(<>), - WRITE > SEMICOLON => Stmt::Write(<>), + Stmt::Skip(location) + }, + STOP SEMICOLON => { + let location = Span::new(ByteIndex(l as u32), ByteIndex(r as u32)); - // FIXME Function call is an expression not an statement - OPEN_PARENS ?> CLOSE_PARENS SEMICOLON => Stmt::Call(<>), + Stmt::Stop(location) + }, + RETURN SEMICOLON => { + let location = Span::new(ByteIndex(l as u32), ByteIndex(r as u32)); + + Stmt::Return(e, location) + }, + READ SEMICOLON => { + let location = Span::new(ByteIndex(l as u32), ByteIndex(r as u32)); - IF OPEN_PARENS CLOSE_PARENS <(ELSE IF OPEN_PARENS CLOSE_PARENS )*> <(ELSE )?> => Stmt::If(<>), + Stmt::Read(v, location) + }, + WRITE > SEMICOLON => { + let location = Span::new(ByteIndex(l as u32), ByteIndex(r as u32)); - WHILE OPEN_PARENS CLOSE_PARENS => Stmt::While(<>), - // TODO If for does not accpet an a empty initialization or step recovery from error and print to user - FOR OPEN_PARENS SEMICOLON SEMICOLON CLOSE_PARENS => Stmt::For(Box::new(i), e, Box::new(s), b), + Stmt::Write(e, location) + }, + OPEN_PARENS ?> CLOSE_PARENS SEMICOLON => { + let location = Span::new(ByteIndex(l as u32), ByteIndex(r as u32)); + + Stmt::Call(i, e, location) + }, + IF OPEN_PARENS CLOSE_PARENS CLOSE_PARENS )*> )?> => { + let location = Span::new(ByteIndex(l as u32), ByteIndex(r as u32)); + + Stmt::If(e, b, elifs, e_block, location) + }, + WHILE OPEN_PARENS CLOSE_PARENS => { + let location = Span::new(ByteIndex(l as u32), ByteIndex(r as u32)); + + Stmt::While(e, b, location) + }, + FOR OPEN_PARENS SEMICOLON SEMICOLON CLOSE_PARENS => { + let location = Span::new(ByteIndex(l as u32), ByteIndex(r as u32)); + + Stmt::For(Box::new(i), e, Box::new(s), b, location) + } }; Commands: Either = { From 88935eaebe995eb514b5b501eb1b4453fe09db97 Mon Sep 17 00:00:00 2001 From: Guilherme Chichanoski Date: Wed, 5 Dec 2018 22:31:03 -0200 Subject: [PATCH 07/19] write working in lli --- src/gen/context.rs | 38 ++++++++++++++++++- src/gen/emit.rs | 94 ++++++++++++++++++++++++++++++++-------------- src/gen/mod.rs | 1 + 3 files changed, 104 insertions(+), 29 deletions(-) diff --git a/src/gen/context.rs b/src/gen/context.rs index ccc240f..efa77e5 100644 --- a/src/gen/context.rs +++ b/src/gen/context.rs @@ -1,4 +1,7 @@ -use super::symbol_table::SymbolTable; +use super::{ + super::ast::Type, + symbol_table::{Symbol, SymbolTable}, +}; use llvm::{core::*, *}; use std::ffi::CString; @@ -25,4 +28,37 @@ impl Context { actual_loop: None, } } + + pub unsafe fn declare_printf_scanf(self: &mut Self) { + let format_int = LLVMConstString(as_str!("%d"), 3, 1); + let format_str = LLVMConstString(as_str!("%s"), 3, 1); + + self.symbol_table + .set("0format_int", Symbol::Variable(format_int, Type::Str)) + .unwrap(); + + self.symbol_table + .set("0format_str", Symbol::Variable(format_str, Type::Str)) + .unwrap(); + + let int8_type = LLVMInt8TypeInContext(self.context); + let int32_type = LLVMInt32TypeInContext(self.context); + let mut args = [LLVMPointerType(int8_type, 0)]; + let fn_type = LLVMFunctionType(int32_type, args.as_mut_ptr(), 1, 1); + + let printf_fn = + LLVMAddFunction(self.module, as_str!("printf"), fn_type); + let scanf_fn = LLVMAddFunction(self.module, as_str!("scanf"), fn_type); + + self.symbol_table + .set( + "0printf", + Symbol::Func(printf_fn, (Type::Int, vec![Type::Str])), + ) + .unwrap(); + + self.symbol_table + .set("0scanf", Symbol::Func(scanf_fn, (Type::Int, vec![]))) + .unwrap(); + } } diff --git a/src/gen/emit.rs b/src/gen/emit.rs index 91f55a2..4dcd5ef 100644 --- a/src/gen/emit.rs +++ b/src/gen/emit.rs @@ -2,18 +2,20 @@ use super::{super::ast::*, context::*, symbol_table::*}; use llvm::{core::*, *}; use std::ffi::CString; +pub type SemanticError = (String, Location); + pub trait Emit { unsafe fn emit( self: &Self, context: &mut Context, - ) -> Result; + ) -> Result; } impl Emit<*mut LLVMType> for Type { unsafe fn emit( self: &Self, context: &mut Context, - ) -> Result<*mut LLVMType, (String, Location)> { + ) -> Result<*mut LLVMType, SemanticError> { match self { Type::Int => Ok(LLVMInt64TypeInContext(context.context)), Type::Bool => Ok(LLVMInt1TypeInContext(context.context)), @@ -28,7 +30,7 @@ impl Emit<(*mut LLVMValue, Type)> for Variable { unsafe fn emit( self: &Self, context: &mut Context, - ) -> Result<(*mut LLVMValue, Type), (String, Location)> { + ) -> Result<(*mut LLVMValue, Type), SemanticError> { let builder = context.builder; match self { Variable::Single(identifier, location) => { @@ -49,8 +51,7 @@ impl Emit<(*mut LLVMValue, Type)> for Variable { Variable::Array(identifier, expression, location) => { if let Ok(value) = context.clone().symbol_table.get(identifier) { - let (index, type_of_index) = - expression.emit(context).unwrap(); + let (index, type_of_index) = expression.emit(context)?; match value { Symbol::Array(value, type_of) => Ok(( @@ -83,19 +84,17 @@ impl Emit<(*mut LLVMValue, Type)> for Expr { ) -> Result<(*mut LLVMValue, Type), (String, Location)> { match self { Expr::Number(number, location) => Ok(( - LLVMConstInt(Type::Int.emit(context).unwrap(), *number, 1), + LLVMConstInt(Type::Int.emit(context)?, *number, 1), Type::Int, )), - Expr::True(location) => Ok(( - LLVMConstInt(Type::Bool.emit(context).unwrap(), 1, 1), - Type::Bool, - )), - Expr::False(location) => Ok(( - LLVMConstInt(Type::Bool.emit(context).unwrap(), 0, 1), - Type::Bool, - )), + Expr::True(location) => { + Ok((LLVMConstInt(Type::Bool.emit(context)?, 1, 1), Type::Bool)) + } + Expr::False(location) => { + Ok((LLVMConstInt(Type::Bool.emit(context)?, 0, 1), Type::Bool)) + } Expr::Variable(var, location) => { - let (ptr_var, type_of) = var.emit(context).unwrap(); + let (ptr_var, type_of) = var.emit(context)?; Ok(( LLVMBuildLoad( @@ -125,12 +124,12 @@ impl Emit<(*mut LLVMValue, Type)> for Expr { .iter() .zip(function_signature.1) .map(|(param, param_expected_type)| { - let (value, type_of) = - param.emit(context).unwrap(); - // TODO Check type_of with function_signature - value + match param.emit(context) { + Ok((value, type_of)) => Ok(value), + Err(e) => Err(e), + } }) - .collect::>() + .collect::, _>>()? .as_mut_ptr(), params.len() as u32, as_str!("call"), @@ -146,8 +145,8 @@ impl Emit<(*mut LLVMValue, Type)> for Expr { } Expr::Op(lhs, op, rhs, location) => { let builder = context.builder; - let (lhs, type_of_lhs) = lhs.emit(context).unwrap(); - let (rhs, type_of_rhs) = rhs.emit(context).unwrap(); + let (lhs, type_of_lhs) = lhs.emit(context)?; + let (rhs, type_of_rhs) = rhs.emit(context)?; let value = match op { Opcode::Add => { LLVMBuildAdd(builder, lhs, rhs, as_str!("add_result")) @@ -180,7 +179,7 @@ impl Emit<(*mut LLVMValue, Type)> for Expr { } Expr::Right(op, expression, location) => { let builder = context.builder; - let (expression, type_of) = expression.emit(context).unwrap(); + let (expression, type_of) = expression.emit(context)?; let value = match op { Opcode::Not => { LLVMBuildNot(builder, expression, as_str!("not_result")) @@ -209,9 +208,9 @@ impl Emit<()> for Stmt { let builder = context.builder; match self { Stmt::Attr(var, expression, location) => { - let (ptr_var, type_of) = var.emit(context).unwrap(); + let (ptr_var, type_of) = var.emit(context)?; let (expression, type_of_expression) = - expression.emit(context).unwrap(); + expression.emit(context)?; LLVMBuildStore(builder, expression, ptr_var); Ok(()) @@ -222,12 +221,11 @@ impl Emit<()> for Stmt { expressions.clone(), *location, ) - .emit(context) - .unwrap(); + .emit(context)?; Ok(()) } Stmt::For(init, predicate, step, block, location) => { - init.emit(context).unwrap(); + init.emit(context)?; let block_predicate = LLVMAppendBasicBlockInContext( context.context, context.actual_function.unwrap().0, @@ -427,6 +425,45 @@ impl Emit<()> for Stmt { Ok(()) } + Stmt::Write(list_expr, location) => { + let printf_fn = + match context.symbol_table.get("0printf").unwrap() { + Symbol::Func(value, _type_of) => value, + _ => panic!("What"), + }; + + let format_str = LLVMBuildGlobalStringPtr( + context.builder, + as_str!("%s"), + as_str!("format_str"), + ); + + let format_int = LLVMBuildGlobalStringPtr( + context.builder, + as_str!("%d"), + as_str!("format_int"), + ); + + list_expr.iter().for_each(|expr| { + let (value, type_of) = + expr.emit(&mut context.clone()).unwrap(); + + match type_of { + Type::Int => { + LLVMBuildCall( + context.builder, + *printf_fn, + vec![format_int, value].as_mut_ptr(), + 2, + as_str!("call_write"), + ); + } + _ => panic!("Not implemented"), + } + }); + + Ok(()) + } _ => panic!("Not implemented"), } } @@ -662,6 +699,7 @@ impl Emit<()> for Decl { context.symbol_table.kill_scope(); + context.actual_function = None; Ok(()) } } diff --git a/src/gen/mod.rs b/src/gen/mod.rs index 6f65a91..cf2d3fb 100644 --- a/src/gen/mod.rs +++ b/src/gen/mod.rs @@ -877,6 +877,7 @@ mod symbol_table; pub unsafe fn gen(decls: Vec) { let mut context = context::Context::new(); + context.declare_printf_scanf(); for i in decls { i.emit(&mut context).expect("Cannot emit this"); } From de1f15e19cc7337d880972dfbbe5794199cba293 Mon Sep 17 00:00:00 2001 From: Guilherme Chichanoski Date: Thu, 6 Dec 2018 22:15:09 -0200 Subject: [PATCH 08/19] =?UTF-8?q?t=C3=A1=20printando=20porra,=20mas=20vamo?= =?UTF-8?q?s=20precisar=20de=20um=20writeln?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ast.rs | 2 ++ src/gen/emit.rs | 72 +++++++++++++++++++++++++++++++++-------- src/grammar/mod.lalrpop | 6 ++++ 3 files changed, 67 insertions(+), 13 deletions(-) diff --git a/src/ast.rs b/src/ast.rs index 8a601e1..1ac3742 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -29,6 +29,7 @@ fn get_tabs(f: &fmt::Formatter) -> (usize, String) { #[derive(Clone, PartialEq)] pub enum Expr { Number(u64, Location), + StringLitteral(String, Location), Variable(Variable, Location), True(Location), False(Location), @@ -142,6 +143,7 @@ impl fmt::Debug for Expr { let (width, tabs) = get_tabs(f); match self { Expr::Number(i, _) => write!(f, "${:?}", i), + Expr::StringLitteral(s, _) => write!(f, "${:?}", s), Expr::Variable(v, _) => { write!(f, "{tabs}{:width$?}", v, tabs = tabs, width = width + 1) } diff --git a/src/gen/emit.rs b/src/gen/emit.rs index 4dcd5ef..7a498bc 100644 --- a/src/gen/emit.rs +++ b/src/gen/emit.rs @@ -87,6 +87,14 @@ impl Emit<(*mut LLVMValue, Type)> for Expr { LLVMConstInt(Type::Int.emit(context)?, *number, 1), Type::Int, )), + Expr::StringLitteral(string, location) => Ok(( + LLVMBuildGlobalStringPtr( + context.builder, + as_str!(string), + as_str!("string"), + ), + Type::Str, + )), Expr::True(location) => { Ok((LLVMConstInt(Type::Bool.emit(context)?, 1, 1), Type::Bool)) } @@ -444,6 +452,12 @@ impl Emit<()> for Stmt { as_str!("format_int"), ); + let format_barra_n = LLVMBuildGlobalStringPtr( + context.builder, + as_str!("\n"), + as_str!("barra_n"), + ); + list_expr.iter().for_each(|expr| { let (value, type_of) = expr.emit(&mut context.clone()).unwrap(); @@ -458,9 +472,25 @@ impl Emit<()> for Stmt { as_str!("call_write"), ); } + Type::Str => { + LLVMBuildCall( + context.builder, + *printf_fn, + vec![format_str, value].as_mut_ptr(), + 2, + as_str!("call_write"), + ); + } _ => panic!("Not implemented"), } }); + LLVMBuildCall( + context.builder, + *printf_fn, + vec![format_barra_n].as_mut_ptr(), + 1, + as_str!("call_write"), + ); Ok(()) } @@ -491,23 +521,39 @@ impl Emit<()> for Decl { let builder = context.builder; match self { Decl::Single(identifier, type_of, expression, location) => { - let ptr_vlr = LLVMBuildAlloca( - alloc_builder, - type_of.emit(context).unwrap(), - as_str!(identifier), - ); - context + if *type_of == Type::Str { + if let Some(expression) = expression { + let (string, _) = expression.emit(context)?; + context + .symbol_table + .set(identifier, Symbol::Variable(string, type_of.clone())) + .expect("Can't set the variable, probably the variable is already declared"); + Ok(()) + } else { + Err(( + "String must be initialized".to_string(), + *location, + )) + } + } else { + let ptr_vlr = LLVMBuildAlloca( + alloc_builder, + type_of.emit(context).unwrap(), + as_str!(identifier), + ); + context .symbol_table .set(identifier, Symbol::Variable(ptr_vlr, type_of.clone())) .expect("Can't set the variable, probably the variable is already declared"); - if let Some(expression) = expression { - let (expression, type_of_expression) = - expression.emit(context).unwrap(); - LLVMBuildStore(builder, expression, ptr_vlr); - Ok(()) - } else { - Ok(()) + if let Some(expression) = expression { + let (expression, type_of_expression) = + expression.emit(context).unwrap(); + LLVMBuildStore(builder, expression, ptr_vlr); + Ok(()) + } else { + Ok(()) + } } } Decl::Array( diff --git a/src/grammar/mod.lalrpop b/src/grammar/mod.lalrpop index db09872..73264c8 100644 --- a/src/grammar/mod.lalrpop +++ b/src/grammar/mod.lalrpop @@ -56,6 +56,7 @@ match { Num: u64 = r"[0-9]+" => u64::from_str(<>).unwrap(); Id: String = r"[a-zA-Z_][a-zA-Z0-9_]*" => String::from(<>); +String_Litteral: String = => s[1..s.len()-1].to_string(); Var: Variable = { OPEN_BRACKET CLOSE_BRACKET => { @@ -116,6 +117,11 @@ Term: Box = { Box::new(Expr::Number(n, location)) }, + => { + let location = Span::new(ByteIndex(l as u32), ByteIndex(r as u32)); + + Box::new(Expr::StringLitteral(s, location)) + }, => { let location = Span::new(ByteIndex(l as u32), ByteIndex(r as u32)); From af06517826591fa513935622403649e3b0aae142 Mon Sep 17 00:00:00 2001 From: Guilherme Chichanoski Date: Fri, 7 Dec 2018 09:08:26 -0200 Subject: [PATCH 09/19] fix scope of loops and functions --- src/gen/context.rs | 13 ----------- src/gen/emit.rs | 52 +++++++++++++++++++++++++++++++++-------- src/gen/symbol_table.rs | 1 + 3 files changed, 43 insertions(+), 23 deletions(-) diff --git a/src/gen/context.rs b/src/gen/context.rs index efa77e5..f695a4c 100644 --- a/src/gen/context.rs +++ b/src/gen/context.rs @@ -12,7 +12,6 @@ pub struct Context { pub context: *mut LLVMContext, pub builder: *mut LLVMBuilder, pub actual_function: Option<(*mut LLVMValue, *mut LLVMBasicBlock)>, // (function, entry) - pub actual_loop: Option<(*mut LLVMBasicBlock, *mut LLVMBasicBlock)>, // (merge, predicate) } impl Context { @@ -25,22 +24,10 @@ impl Context { context, actual_function: None, builder: LLVMCreateBuilderInContext(context), - actual_loop: None, } } pub unsafe fn declare_printf_scanf(self: &mut Self) { - let format_int = LLVMConstString(as_str!("%d"), 3, 1); - let format_str = LLVMConstString(as_str!("%s"), 3, 1); - - self.symbol_table - .set("0format_int", Symbol::Variable(format_int, Type::Str)) - .unwrap(); - - self.symbol_table - .set("0format_str", Symbol::Variable(format_str, Type::Str)) - .unwrap(); - let int8_type = LLVMInt8TypeInContext(self.context); let int32_type = LLVMInt32TypeInContext(self.context); let mut args = [LLVMPointerType(int8_type, 0)]; diff --git a/src/gen/emit.rs b/src/gen/emit.rs index 7a498bc..e28d9cf 100644 --- a/src/gen/emit.rs +++ b/src/gen/emit.rs @@ -254,7 +254,16 @@ impl Emit<()> for Stmt { context.actual_function.unwrap().0, as_str!("merge_for"), ); - context.actual_loop = Some((block_merge, block_step)); + + context.symbol_table.initialize_scope(); + context + .symbol_table + .set("0loop_merge", Symbol::JumpBlock(block_merge)) + .unwrap(); + context + .symbol_table + .set("0loop_step", Symbol::JumpBlock(block_step)) + .unwrap(); LLVMBuildBr(context.builder, block_predicate); @@ -274,6 +283,7 @@ impl Emit<()> for Stmt { LLVMPositionBuilderAtEnd(context.builder, block_step); step.emit(context).unwrap(); LLVMBuildBr(context.builder, block_predicate); + context.symbol_table.kill_scope(); LLVMPositionBuilderAtEnd(context.builder, block_merge); @@ -295,7 +305,16 @@ impl Emit<()> for Stmt { context.actual_function.unwrap().0, as_str!("merge_for"), ); - context.actual_loop = Some((block_merge, block_predicate)); + + context.symbol_table.initialize_scope(); + context + .symbol_table + .set("0loop_merge", Symbol::JumpBlock(block_merge)) + .unwrap(); + context + .symbol_table + .set("0loop_step", Symbol::JumpBlock(block_predicate)) + .unwrap(); LLVMBuildBr(context.builder, block_predicate); @@ -312,23 +331,32 @@ impl Emit<()> for Stmt { LLVMPositionBuilderAtEnd(context.builder, block_while); block.emit(context).unwrap(); LLVMBuildBr(context.builder, block_predicate); + context.symbol_table.kill_scope(); LLVMPositionBuilderAtEnd(context.builder, block_merge); Ok(()) } Stmt::Stop(location) => { - if let Some((merge, _)) = context.actual_loop { - LLVMBuildBr(context.builder, merge); - Ok(()) + if let Ok(merge) = context.symbol_table.get("0loop_merge") { + if let Symbol::JumpBlock(merge) = merge { + LLVMBuildBr(context.builder, *merge); + Ok(()) + } else { + Err(("Impossibru!!".to_string(), *location)) + } } else { Err(("Stop not in a loop".to_string(), *location)) } } Stmt::Skip(location) => { - if let Some((_, predicate)) = context.actual_loop { - LLVMBuildBr(context.builder, predicate); - Ok(()) + if let Ok(predicate) = context.symbol_table.get("0loop_step") { + if let Symbol::JumpBlock(predicate) = predicate { + LLVMBuildBr(context.builder, *predicate); + Ok(()) + } else { + Err(("Impossibru!!".to_string(), *location)) + } } else { Err(("Skip not in a loop".to_string(), *location)) } @@ -372,7 +400,9 @@ impl Emit<()> for Stmt { context.builder, block_if_else, ); + context.symbol_table.initialize_scope(); else_block.emit(context).unwrap(); + context.symbol_table.kill_scope(); LLVMBuildBr(context.builder, block_merge); block_if_else @@ -410,7 +440,9 @@ impl Emit<()> for Stmt { context.builder, block_elif_then, ); + context.symbol_table.initialize_scope(); actual_block.1.emit(context).unwrap(); + context.symbol_table.kill_scope(); LLVMBuildBr(context.builder, block_merge); block_elif_predicate @@ -427,7 +459,9 @@ impl Emit<()> for Stmt { block_else_to_jump, ); LLVMPositionBuilderAtEnd(context.builder, block_if_then); + context.symbol_table.initialize_scope(); block.emit(context).unwrap(); + context.symbol_table.kill_scope(); LLVMBuildBr(context.builder, block_merge); LLVMPositionBuilderAtEnd(context.builder, block_merge); @@ -758,7 +792,6 @@ impl Emit<()> for Block { self: &Self, context: &mut Context, ) -> Result<(), (String, Location)> { - context.symbol_table.initialize_scope(); self.decl .iter() .for_each(|decl| decl.emit(context).unwrap()); @@ -766,7 +799,6 @@ impl Emit<()> for Block { self.commands .iter() .for_each(|command| command.emit(context).unwrap()); - context.symbol_table.kill_scope(); Ok(()) } diff --git a/src/gen/symbol_table.rs b/src/gen/symbol_table.rs index f5a6870..58c43f2 100644 --- a/src/gen/symbol_table.rs +++ b/src/gen/symbol_table.rs @@ -8,6 +8,7 @@ use llvm::prelude::*; pub enum Symbol { Variable(LLVMValueRef, Type), Array(LLVMValueRef, Type), + JumpBlock(LLVMBasicBlockRef), Func(LLVMValueRef, (Type, Vec)), // TODO Should store tha function value and signature } From 11d0449057930c49036961ba971a8a33b6e3e97f Mon Sep 17 00:00:00 2001 From: Guilherme Chichanoski Date: Fri, 7 Dec 2018 09:36:24 -0200 Subject: [PATCH 10/19] better support for string --- README.md | 7 +++ src/gen/emit.rs | 112 ++++++++++++++++++++++++++++++++---------------- 2 files changed, 81 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index 3d6fdb1..a9a3c2f 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,9 @@ # nanilang Repositório para o Trabalho de Implementação de Linguagens de Programação + +## Not Working + +- Array initialization +- Array of string +- Read +- Ternary diff --git a/src/gen/emit.rs b/src/gen/emit.rs index e28d9cf..b67c942 100644 --- a/src/gen/emit.rs +++ b/src/gen/emit.rs @@ -104,14 +104,17 @@ impl Emit<(*mut LLVMValue, Type)> for Expr { Expr::Variable(var, location) => { let (ptr_var, type_of) = var.emit(context)?; - Ok(( - LLVMBuildLoad( - context.builder, - ptr_var, - as_str!("var_load"), - ), - type_of, - )) + match type_of { + Type::Str => Ok((ptr_var, type_of)), + _ => Ok(( + LLVMBuildLoad( + context.builder, + ptr_var, + as_str!("var_load"), + ), + type_of, + )), + } } Expr::Call(identifier, params, location) => { let builder = context.builder; @@ -555,38 +558,71 @@ impl Emit<()> for Decl { let builder = context.builder; match self { Decl::Single(identifier, type_of, expression, location) => { - if *type_of == Type::Str { - if let Some(expression) = expression { - let (string, _) = expression.emit(context)?; - context - .symbol_table - .set(identifier, Symbol::Variable(string, type_of.clone())) - .expect("Can't set the variable, probably the variable is already declared"); - Ok(()) - } else { - Err(( - "String must be initialized".to_string(), - *location, - )) + match type_of { + Type::Str => { + if let Some(expression) = expression { + let (string, _) = expression.emit(context)?; + + if context + .symbol_table + .set( + identifier, + Symbol::Variable( + string, + type_of.clone(), + ), + ) + .is_err() + { + return Err(( + format!( + "Identifier {} already declared", + identifier + ), + *location, + )); + } + + Ok(()) + } else { + Err(( + "String must be initialized".to_string(), + *location, + )) + } } - } else { - let ptr_vlr = LLVMBuildAlloca( - alloc_builder, - type_of.emit(context).unwrap(), - as_str!(identifier), - ); - context - .symbol_table - .set(identifier, Symbol::Variable(ptr_vlr, type_of.clone())) - .expect("Can't set the variable, probably the variable is already declared"); + _ => { + let ptr_vlr = LLVMBuildAlloca( + alloc_builder, + type_of.emit(context).unwrap(), + as_str!(identifier), + ); - if let Some(expression) = expression { - let (expression, type_of_expression) = - expression.emit(context).unwrap(); - LLVMBuildStore(builder, expression, ptr_vlr); - Ok(()) - } else { - Ok(()) + if context + .symbol_table + .set( + identifier, + Symbol::Variable(ptr_vlr, type_of.clone()), + ) + .is_err() + { + return Err(( + format!( + "Identifier {} already declared", + identifier + ), + *location, + )); + } + + if let Some(expression) = expression { + let (expression, type_of_expression) = + expression.emit(context).unwrap(); + LLVMBuildStore(builder, expression, ptr_vlr); + Ok(()) + } else { + Ok(()) + } } } } From ec95f244110e8a0653587466f59c511db292629f Mon Sep 17 00:00:00 2001 From: Guilherme Chichanoski Date: Fri, 7 Dec 2018 09:44:26 -0200 Subject: [PATCH 11/19] remove tiago codegen --- src/gen/mod.rs | 860 ------------------------------------------------- 1 file changed, 860 deletions(-) diff --git a/src/gen/mod.rs b/src/gen/mod.rs index cf2d3fb..4e4c0bb 100644 --- a/src/gen/mod.rs +++ b/src/gen/mod.rs @@ -15,866 +15,6 @@ mod context; mod emit; mod symbol_table; -//macro_rules! c_str { -// ($s:expr) => {{ -// concat!($s, "\0").as_ptr() as *const i8 -// }}; -//} -// -//macro_rules! m_str { -// ($s:expr) => {{ -// concat!($s, "\0").as_ptr() as *mut i8 -// }}; -//} -// -//macro_rules! mm_str { -// ($s:expr) => {{ -// concat!($s, "\0").as_ptr() as *mut *mut i8 -// }}; -//} -// -//unsafe fn gen_type(context: LLVMContextRef, t: Option) -> LLVMTypeRef { -// match t { -// Some(Type::Bool) => LLVMInt1TypeInContext(context), -// Some(Type::Int) => LLVMInt64TypeInContext(context), -// Some(Type::Str) => panic!("Do not use gen_type with Strings!"), -// None => LLVMVoidTypeInContext(context), -// } -//} -// -//unsafe fn gen_array_type(context: LLVMContextRef, t: &Type) -> LLVMTypeRef { -// match t { -// Type::Bool => LLVMPointerType(LLVMInt1TypeInContext(context), 0), -// Type::Int => LLVMPointerType(LLVMInt64TypeInContext(context), 0), -// Type::Str => panic!("Do not use gen_array_type with Strings!"), -// } -//} -// -//unsafe fn flatten_expr( -// context: LLVMContextRef, -// module: LLVMModuleRef, -// symbols: &SymbolTable, -// builder: LLVMBuilderRef, -// e: Expr, -//) -> LLVMValueRef { -// let mut v = Vec::new(); -// match e { -// Expr::Number(n) => { -// v.push(LLVMConstInt(gen_type(context, Some(Type::Int)), n, 1)); -// } -// Expr::Variable(Variable::Single(s)) => { -// if let Ok(var) = symbols.get(&s) { -// if let Symbol::Variable(mut var) = var { -// let tmp = LLVMBuildLoad(builder, var, c_str!("flat")); -// v.push(tmp); -// } else { -// panic!( -// "Variable <{:?}> of a type diferent than expected!", -// s -// ); -// } -// } else { -// panic!("Variable <{:?}> is used but not declared!", s); -// } -// } -// Expr::Variable(Variable::Array(s, e)) => { -// if let Ok(var) = symbols.get(&s) { -// if let Symbol::ArrayRef(mut var) = var { -// let index_flattened = -// flatten_expr(context, module, symbols, builder, *e); -// let loaded_array_ptr = -// LLVMBuildLoad(builder, var, c_str!("loaded_param")); -// let arr_at = LLVMBuildInBoundsGEP( -// builder, -// loaded_array_ptr, -// [index_flattened].as_mut_ptr(), -// 1, -// c_str!("arr"), -// ); -// v.push(LLVMBuildLoad(builder, arr_at, c_str!("flat"))); -// } else if let Symbol::Array(_, mut var) = var { -// let flattened = -// flatten_expr(context, module, symbols, builder, *e); -// let arr_at = LLVMBuildGEP( -// builder, -// var, -// [ -// flattened, -// LLVMConstInt( -// gen_type(context, Some(Type::Int)), -// 0, -// 1, -// ), -// ] -// .as_mut_ptr(), -// 2, -// c_str!("arr"), -// ); -// v.push(LLVMBuildLoad(builder, arr_at, c_str!("flat"))); -// } else { -// panic!("Variable <{:?}> is used but not declared!", s); -// } -// } else { -// panic!("Variable <{:?}> is used but not declared!", s); -// } -// } -// Expr::True => { -// v.push(LLVMConstInt(gen_type(context, Some(Type::Bool)), 1, 1)); -// } -// Expr::False => { -// v.push(LLVMConstInt(gen_type(context, Some(Type::Bool)), 0, 1)); -// } -// Expr::Op(lhs, op, rhs) => match op { -// Opcode::Add => { -// let lhs = flatten_expr(context, module, symbols, builder, *lhs); -// let rhs = flatten_expr(context, module, symbols, builder, *rhs); -// v.push(LLVMBuildAdd(builder, lhs, rhs, c_str!("add"))); -// } -// Opcode::Sub => { -// let lhs = flatten_expr(context, module, symbols, builder, *lhs); -// let rhs = flatten_expr(context, module, symbols, builder, *rhs); -// v.push(LLVMBuildSub(builder, lhs, rhs, c_str!("sub"))); -// } -// Opcode::Mul => { -// let lhs = flatten_expr(context, module, symbols, builder, *lhs); -// let rhs = flatten_expr(context, module, symbols, builder, *rhs); -// v.push(LLVMBuildMul(builder, lhs, rhs, c_str!("mul"))); -// } -// Opcode::Div => { -// let lhs = flatten_expr(context, module, symbols, builder, *lhs); -// let rhs = flatten_expr(context, module, symbols, builder, *rhs); -// v.push(LLVMBuildSDiv(builder, lhs, rhs, c_str!("sdiv"))); -// } -// Opcode::Mod => { -// let lhs = flatten_expr(context, module, symbols, builder, *lhs); -// let rhs = flatten_expr(context, module, symbols, builder, *rhs); -// v.push(LLVMBuildSRem(builder, lhs, rhs, c_str!("srem"))); -// } -// Opcode::Lesser -// | Opcode::LesserOrEqual -// | Opcode::Greater -// | Opcode::GreaterOrEqual -// | Opcode::Equal -// | Opcode::Different => { -// let lhs = flatten_expr(context, module, symbols, builder, *lhs); -// let rhs = flatten_expr(context, module, symbols, builder, *rhs); -// v.push(LLVMBuildICmp( -// builder, -// op.pred(), -// lhs, -// rhs, -// c_str!("cmp"), -// )); -// } -// Opcode::And => { -// let lhs = flatten_expr(context, module, symbols, builder, *lhs); -// let rhs = flatten_expr(context, module, symbols, builder, *rhs); -// v.push(LLVMBuildAnd(builder, lhs, rhs, c_str!("and"))); -// } -// Opcode::Or => { -// let lhs = flatten_expr(context, module, symbols, builder, *lhs); -// let rhs = flatten_expr(context, module, symbols, builder, *rhs); -// v.push(LLVMBuildOr(builder, lhs, rhs, c_str!("or"))); -// } -// _ => panic!("IMPOSSIBURU! Opcode<{:?}> is unary!", op), -// }, -// Expr::Call(n, None) => { -// let called_fn = LLVMGetNamedFunction(module, as_str!(n)); -// v.push(LLVMBuildCall( -// builder, -// called_fn, -// [].as_mut_ptr(), -// 0, -// c_str!("fn_call"), -// )); -// } -// Expr::Right(Opcode::Negative, rhs) => { -// let rhs = flatten_expr(context, module, symbols, builder, *rhs); -// v.push(LLVMBuildMul( -// builder, -// LLVMConstInt( -// gen_type(context, Some(Type::Int)), -// -1i64 as u64, -// 1, -// ), -// rhs, -// c_str!("neg"), -// )); -// } -// Expr::Right(Opcode::Not, rhs) => { -// let rhs = flatten_expr(context, module, symbols, builder, *rhs); -// v.push(LLVMBuildNot(builder, rhs, c_str!("not"))); -// } -// Expr::Right(o, _) => { -// panic!("IMPOSSIBURU! Opcode<{:?}> is binary!", o); -// } -// _ => println!("uninplemented!"), -// } -// if let Some(a) = v.last().cloned() { -// a -// } else { -// //panic!("invalid state"); -// LLVMConstInt(gen_type(context, Some(Type::Int)), 42, 1) -// } -//} -// -//unsafe fn local_add_variable( -// context: LLVMContextRef, -// module: LLVMModuleRef, -// symbols: &mut SymbolTable, -// builder: LLVMBuilderRef, -// n: &str, -// t: Type, -// e: Option>, -//) { -// let t = gen_type(context, Some(t)); -// let decl = LLVMBuildAlloca(builder, t, as_str!(n)); -// if let Some(e) = e { -// let flattened = flatten_expr(context, module, symbols, builder, *e); -// LLVMBuildStore(builder, flattened, decl); -// } else { -// LLVMBuildStore(builder, LLVMConstInt(t, 0, 1), decl); -// } -// let new_symbol = Symbol::Variable(decl); -// symbols.set(&n, new_symbol); -//} -// -//unsafe fn local_add_array( -// context: LLVMContextRef, -// symbols: &mut SymbolTable, -// builder: LLVMBuilderRef, -// n: &str, -// t: Type, -// s: u64, -// e: Option>>, -//) { -// let t = gen_type(context, Some(t)); -// let array_type = LLVMArrayType(t, s as u32); -// let decl = LLVMBuildArrayAlloca( -// builder, -// array_type, -// LLVMConstInt(t, 0, 1), -// as_str!(n), -// ); -// if let Some(e) = e { -// for (i, e) in e.iter().enumerate() { -// match **e { -// Expr::Number(e) => { -// let ptr = LLVMBuildGEP( -// builder, -// decl, -// [ -// LLVMConstInt( -// gen_type(context, Some(Type::Int)), -// i as u64, -// 1, -// ), -// LLVMConstInt( -// gen_type(context, Some(Type::Int)), -// 0, -// 1, -// ), -// ] -// .as_mut_ptr(), -// 2, -// c_str!("ptr_get"), -// ); -// LLVMBuildStore(builder, LLVMConstInt(t, e, 1), ptr); -// } -// Expr::True => { -// let ptr = LLVMBuildGEP( -// builder, -// decl, -// [ -// LLVMConstInt( -// gen_type(context, Some(Type::Int)), -// i as u64, -// 1, -// ), -// LLVMConstInt( -// gen_type(context, Some(Type::Int)), -// 0, -// 1, -// ), -// ] -// .as_mut_ptr(), -// 2, -// c_str!("ptr_get"), -// ); -// LLVMBuildStore(builder, LLVMConstInt(t, 1, 1), ptr); -// } -// Expr::False => { -// let ptr = LLVMBuildGEP( -// builder, -// decl, -// [ -// LLVMConstInt( -// gen_type(context, Some(Type::Int)), -// i as u64, -// 1, -// ), -// LLVMConstInt( -// gen_type(context, Some(Type::Int)), -// 0, -// 1, -// ), -// ] -// .as_mut_ptr(), -// 2, -// c_str!("ptr_get"), -// ); -// LLVMBuildStore(builder, LLVMConstInt(t, 0, 1), ptr); -// } -// _ => panic!( -// "Cannot initialize global value with non-const expresion!" -// ), -// }; -// } -// /* -// *let mut args = e -// * .iter() -// * .map(|b| match **b { -// * Expr::Number(e) => LLVMConstInt(t, e, 1), -// * Expr::True => LLVMConstInt(t, 1, 1), -// * Expr::False => LLVMConstInt(t, 0, 1), -// * _ => panic!("Cannot initialize global value with non-const expresion!"), -// * }) -// * .collect::>(); -// *let values = LLVMConstArray(t, args.as_mut_ptr(), args.len() as u32); -// *LLVMBuildStore(builder, values, decl); -// */ -// } -// let new_symbol = Symbol::Array(s as u32, decl); -// -// symbols.set(&n, new_symbol); -//} -// -//unsafe fn global_add_func( -// context: LLVMContextRef, -// module: LLVMModuleRef, -// symbols: &mut SymbolTable, -// n: &str, -// t: Option, // Return Type -// a: Option>, -// b: Block, -//) { -// let builder = LLVMCreateBuilderInContext(context); -// let t = gen_type(context, t); -// let args = if let Some(a) = a { -// a.iter() -// .map(|p| match p { -// FuncParam::Single(n, t) => { -// (n.clone(), true, gen_type(context, Some(t.clone()))) -// } -// FuncParam::Array(n, t) => { -// (n.clone(), false, gen_array_type(context, &t.clone())) -// } -// }) -// .collect::>() -// } else { -// Vec::new() -// }; -// let function_type = LLVMFunctionType( -// t, -// args.iter().map(|a| a.2).collect::>().as_mut_ptr(), -// args.len() as u32, -// 0, -// ); -// let function = LLVMAddFunction(module, as_str!(n), function_type); -// -// symbols.initialize_scope(); -// -// let entry = -// LLVMAppendBasicBlockInContext(context, function, c_str!("entry")); -// LLVMPositionBuilderAtEnd(builder, entry); -// -// for (i, e) in args.iter().enumerate() { -// if e.1 { -// let fn_param = LLVMGetParam(function, i as u32); -// let alloced_param = LLVMBuildAlloca(builder, e.2, c_str!("param")); -// LLVMBuildStore(builder, fn_param, alloced_param); -// let new_symbol = Symbol::Variable(alloced_param); -// symbols.set(&e.0, new_symbol); -// } else { -// let fn_param = LLVMGetParam(function, i as u32); -// let alloced_param = LLVMBuildAlloca(builder, e.2, c_str!("param")); -// LLVMBuildStore(builder, fn_param, alloced_param); -// let new_symbol = Symbol::ArrayRef(alloced_param); -// symbols.set(&e.0, new_symbol); -// } -// } -// -// let test = LLVMGetNamedFunction(module, c_str!("printf")); -// // Stupid way of checking if the function is already defined. -// let against = ptr::null::() as *mut _; -// if test == against { -// LLVMBuildGlobalStringPtr(builder, c_str!("%d"), c_str!("format_int")); -// LLVMBuildGlobalStringPtr(builder, c_str!("%s"), c_str!("format_str")); -// -// let int8_type = LLVMInt8TypeInContext(context); -// let int32_type = LLVMInt32TypeInContext(context); -// let mut args = [LLVMPointerType(int8_type, 0)]; -// let fn_type = LLVMFunctionType(int32_type, args.as_mut_ptr(), 0, 1); -// -// LLVMAddFunction(module, c_str!("printf"), fn_type); -// LLVMAddFunction(module, c_str!("scanf"), fn_type); -// } -// -// gen_decl(context, module, symbols, builder, b.decl, false); -// gen_block( -// context, module, symbols, builder, function, None, b.commands, -// ); -// -// symbols.kill_scope(); -// -// LLVMDisposeBuilder(builder); -// let new_symbol = Symbol::Func(n.to_string()); -// -// symbols.set(&n, new_symbol); -//} -// -//unsafe fn gen_decl( -// context: LLVMContextRef, -// module: LLVMModuleRef, -// symbols: &mut SymbolTable, -// builder: LLVMBuilderRef, -// decl: Vec, -// allow_fn: bool, -//) { -// for i in decl { -// match i { -// Decl::Single(n, t, e) => { -// local_add_variable(context, module, symbols, builder, &n, t, e) -// } -// Decl::Array(n, t, s, e) => { -// local_add_array(context, symbols, builder, &n, t, s, e) -// } -// Decl::Func(_, _, _, _) => { -// if allow_fn { -// println!("unimplemented"); -// } else { -// panic!("Functions are not allowed here!"); -// } -// } -// } -// } -//} -// -//unsafe fn build_attr( -// context: LLVMContextRef, -// module: LLVMModuleRef, -// symbols: &SymbolTable, -// builder: LLVMBuilderRef, -// v: &str, -// e: Expr, -//) -> Result<(), String> { -// if let Ok(var) = symbols.get(&v) { -// if let Symbol::Variable(mut var) = var { -// let flattened = flatten_expr(context, module, symbols, builder, e); -// LLVMBuildStore(builder, flattened, var); -// Ok(()) -// } else { -// Err(format!("Variable <{:?}> is used but not declared!", v)) -// } -// } else { -// Err(format!("Variable <{:?}> is used but not declared!", v)) -// } -//} -// -//unsafe fn gen_block( -// context: LLVMContextRef, -// module: LLVMModuleRef, -// symbols: &mut SymbolTable, -// builder: LLVMBuilderRef, -// parent: LLVMValueRef, -// looping: Option<(LLVMBasicBlockRef, LLVMBasicBlockRef)>, -// stmts: Vec>, -//) { -// symbols.initialize_scope(); -// -// for i in stmts { -// match i { -// Either::Left(Stmt::Attr(Variable::Single(v), e)) => { -// if let Err(s) = -// build_attr(context, module, symbols, builder, &v, *e) -// { -// panic!(s); -// } -// } -// Either::Left(Stmt::Write(vec)) => { -// for i in vec { -// let flattened = -// flatten_expr(context, module, symbols, builder, *i); -// let format_str = -// LLVMGetNamedGlobal(module, c_str!("format_int")); -// let mut printf_args = [format_str, flattened]; -// let printf_fn = -// LLVMGetNamedFunction(module, c_str!("printf")); -// LLVMBuildCall( -// builder, -// printf_fn, -// printf_args.as_mut_ptr(), -// 2, -// c_str!("write"), -// ); -// } -// } -// Either::Left(Stmt::Read(Variable::Single(v))) => { -// if let Ok(var) = symbols.get(&v) { -// if let Symbol::Variable(mut var) = var { -// let format_str = -// LLVMGetNamedGlobal(module, c_str!("format_int")); -// let mut scanf_args = [format_str, var]; -// let scanf_fn = -// LLVMGetNamedFunction(module, c_str!("scanf")); -// LLVMBuildCall( -// builder, -// scanf_fn, -// scanf_args.as_mut_ptr(), -// 2, -// c_str!("read"), -// ); -// } -// } -// } -// Either::Left(Stmt::Read(Variable::Array(v, e))) => { -// if let Ok(var) = symbols.get(&v) { -// if let Symbol::ArrayRef(mut var) = var { -// let flattened = -// flatten_expr(context, module, symbols, builder, *e); -// let arr_at = LLVMBuildGEP( -// builder, -// var, -// [ -// LLVMConstInt( -// gen_type(context, Some(Type::Int)), -// 0, -// 1, -// ), -// flattened, -// ] -// .as_mut_ptr(), -// 2, -// c_str!("arr"), -// ); -// let format_str = -// LLVMGetNamedGlobal(module, c_str!("format_int")); -// let mut scanf_args = [format_str, arr_at]; -// let scanf_fn = -// LLVMGetNamedFunction(module, c_str!("scanf")); -// LLVMBuildCall( -// builder, -// scanf_fn, -// scanf_args.as_mut_ptr(), -// 2, -// c_str!("read"), -// ); -// } else if let Symbol::Array(_, mut var) = var { -// let flattened = -// flatten_expr(context, module, symbols, builder, *e); -// let arr_at = LLVMBuildGEP( -// builder, -// var, -// [ -// LLVMConstInt( -// gen_type(context, Some(Type::Int)), -// 0, -// 1, -// ), -// flattened, -// ] -// .as_mut_ptr(), -// 2, -// c_str!("arr"), -// ); -// let format_str = -// LLVMGetNamedGlobal(module, c_str!("format_int")); -// let mut scanf_args = [format_str, arr_at]; -// let scanf_fn = -// LLVMGetNamedFunction(module, c_str!("scanf")); -// LLVMBuildCall( -// builder, -// scanf_fn, -// scanf_args.as_mut_ptr(), -// 2, -// c_str!("read"), -// ); -// } -// } -// } -// Either::Left(Stmt::Call(n, None)) => { -// let called_fn = LLVMGetNamedFunction(module, as_str!(n)); -// LLVMBuildCall( -// builder, -// called_fn, -// [].as_mut_ptr(), -// 0, -// c_str!(""), -// ); -// } -// Either::Left(Stmt::Skip) => { -// if let Some((skip, _)) = looping { -// LLVMBuildBr(builder, skip); -// } else { -// panic!("cannot use skip outside of a loop"); -// } -// } -// Either::Left(Stmt::Stop) => { -// if let Some((_, stop)) = looping { -// LLVMBuildBr(builder, stop); -// } else { -// panic!("cannot use skip outside of a loop"); -// } -// } -// Either::Left(Stmt::Return(v)) => { -// if let Some(v) = v { -// let flattened = -// flatten_expr(context, module, symbols, builder, *v); -// LLVMBuildRet(builder, flattened); -// } else { -// LLVMBuildRetVoid(builder); -// } -// } -// Either::Left(Stmt::If(cond, then, else_ifs, None)) => { -// let then_block = LLVMAppendBasicBlock(parent, c_str!("then")); -// let merge = LLVMAppendBasicBlock(parent, c_str!("merge")); -// -// let cond = -// flatten_expr(context, module, symbols, builder, *cond); -// LLVMBuildCondBr(builder, cond, then_block, merge); -// -// // Build True Branch -// LLVMPositionBuilderAtEnd(builder, then_block); -// gen_decl(context, module, symbols, builder, then.decl, false); -// gen_block( -// context, -// module, -// symbols, -// builder, -// parent, -// looping, -// then.commands, -// ); -// LLVMBuildBr(builder, merge); -// -// // Build Merge Branch -// LLVMPositionBuilderAtEnd(builder, merge); -// } -// Either::Left(Stmt::If(cond, then, else_ifs, Some(_else))) => { -// let then_block = LLVMAppendBasicBlock(parent, c_str!("then")); -// let else_block = LLVMAppendBasicBlock(parent, c_str!("else")); -// let merge = LLVMAppendBasicBlock(parent, c_str!("merge")); -// -// let cond = -// flatten_expr(context, module, symbols, builder, *cond); -// LLVMBuildCondBr(builder, cond, then_block, else_block); -// -// // Build True Branch -// LLVMPositionBuilderAtEnd(builder, then_block); -// gen_decl(context, module, symbols, builder, then.decl, false); -// gen_block( -// context, -// module, -// symbols, -// builder, -// parent, -// looping, -// then.commands, -// ); -// LLVMBuildBr(builder, merge); -// -// // Build False Branch -// LLVMPositionBuilderAtEnd(builder, else_block); -// gen_decl(context, module, symbols, builder, _else.decl, false); -// gen_block( -// context, -// module, -// symbols, -// builder, -// parent, -// looping, -// _else.commands, -// ); -// LLVMBuildBr(builder, merge); -// -// // Build Merge Branch -// LLVMPositionBuilderAtEnd(builder, merge); -// } -// Either::Left(Stmt::For(init, cond, step, block)) => { -// let cond_block = -// LLVMAppendBasicBlock(parent, c_str!("cond_loop")); -// let loop_block = LLVMAppendBasicBlock(parent, c_str!("loop")); -// let step_block = LLVMAppendBasicBlock(parent, c_str!("step")); -// let exit_block = -// LLVMAppendBasicBlock(parent, c_str!("exit_loop")); -// -// let init = *init; -// // Build attribution before entering init_block -// if let Stmt::Attr(Variable::Single(v), e) = init { -// if let Err(s) = -// build_attr(context, module, symbols, builder, &v, *e) -// { -// panic!(s); -// } -// } else if let Stmt::Attr(Variable::Array(v, i), e) = init { -// println!("uninplemented!"); -// } else { -// panic!("invalid state"); -// } -// LLVMBuildBr(builder, cond_block); -// -// // Build condition inside cond_block -// LLVMPositionBuilderAtEnd(builder, cond_block); -// let cond = -// flatten_expr(context, module, symbols, builder, *cond); -// LLVMBuildCondBr(builder, cond, loop_block, exit_block); -// -// // Position at loop to build loop's instructions -// LLVMPositionBuilderAtEnd(builder, loop_block); -// gen_decl(context, module, symbols, builder, block.decl, false); -// gen_block( -// context, -// module, -// symbols, -// builder, -// parent, -// Some((step_block, exit_block)), -// block.commands, -// ); -// LLVMBuildBr(builder, step_block); -// -// LLVMPositionBuilderAtEnd(builder, step_block); -// // Add step to end of loop block -// let step = *step; -// if let Stmt::Attr(Variable::Single(v), e) = step { -// if let Err(s) = -// build_attr(context, module, symbols, builder, &v, *e) -// { -// panic!(s); -// } -// } else if let Stmt::Attr(Variable::Array(v, i), e) = step { -// println!("uninplemented!"); -// } else { -// panic!("invalid state"); -// } -// LLVMBuildBr(builder, cond_block); -// -// // Continue at exit_loop -// LLVMPositionBuilderAtEnd(builder, exit_block); -// } -// -// Either::Left(Stmt::While(cond, block)) => { -// let cond_block = -// LLVMAppendBasicBlock(parent, c_str!("cond_loop")); -// let loop_block = LLVMAppendBasicBlock(parent, c_str!("loop")); -// let exit_block = -// LLVMAppendBasicBlock(parent, c_str!("exit_loop")); -// -// LLVMBuildBr(builder, cond_block); -// -// LLVMPositionBuilderAtEnd(builder, cond_block); -// // Build condition inside cond_block -// let cond = -// flatten_expr(context, module, symbols, builder, *cond); -// LLVMBuildCondBr(builder, cond, loop_block, exit_block); -// -// // Position at loop to build loop's instructions -// LLVMPositionBuilderAtEnd(builder, loop_block); -// gen_decl(context, module, symbols, builder, block.decl, false); -// gen_block( -// context, -// module, -// symbols, -// builder, -// parent, -// Some((cond_block, exit_block)), -// block.commands, -// ); -// LLVMBuildBr(builder, cond_block); -// -// // Continue at exit_loop -// LLVMPositionBuilderAtEnd(builder, exit_block); -// } -// -// Either::Left(_) => println!("uninplemented!"), -// Either::Right(b) => { -// for i in b.decl { -// match i { -// Decl::Single(n, t, e) => local_add_variable( -// context, module, symbols, builder, &n, t, e, -// ), -// Decl::Array(n, t, s, e) => local_add_array( -// context, symbols, builder, &n, t, s, e, -// ), -// _ => { -// panic!("Cannot declare functions inside functions!") -// } -// } -// } -// gen_block( -// context, module, symbols, builder, parent, looping, -// b.commands, -// ) -// } -// } -// } -// -// symbols.kill_scope(); -//} -// -//unsafe fn global_add_variable( -// context: LLVMContextRef, -// module: LLVMModuleRef, -// symbols: &mut SymbolTable, -// n: &str, -// t: Type, -// e: Option>, -//) { -// let t = gen_type(context, Some(t)); -// let decl = LLVMAddGlobal(module, t, as_str!(n)); -// if let Some(e) = e { -// let b = *e; -// if let Expr::Number(v) = b { -// LLVMSetInitializer(decl, LLVMConstInt(t, v as u64, 1)); -// } -// } else { -// panic!("Cannot initialize global value with non-const expresion!"); -// } -// let new_symbol = Symbol::Variable(decl); -// symbols.set(&n, new_symbol); -//} -// -//unsafe fn global_add_array( -// context: LLVMContextRef, -// module: LLVMModuleRef, -// symbols: &mut SymbolTable, -// n: &str, -// t: Type, -// s: u64, -// e: Option>>, -//) { -// let t = gen_type(context, Some(t)); -// let array_type = LLVMArrayType(t, s as u32); -// let decl = LLVMAddGlobal(module, array_type, as_str!(n)); -// if let Some(e) = e { -// let mut args = e -// .iter() -// .map(|b| match **b { -// Expr::Number(e) => LLVMConstInt(t, e, 1), -// Expr::True => LLVMConstInt(t, 1, 1), -// Expr::False => LLVMConstInt(t, 0, 1), -// _ => panic!( -// "Cannot initialize global value with non-const expresion!" -// ), -// }) -// .collect::>(); -// let values = LLVMConstArray(t, args.as_mut_ptr(), args.len() as u32); -// LLVMSetInitializer(decl, values); -// } -// let new_symbol = Symbol::Array(s as u32, decl); -// symbols.set(&n, new_symbol); -//} - pub unsafe fn gen(decls: Vec) { let mut context = context::Context::new(); context.declare_printf_scanf(); From fcce44b4266b764a2c1dc511c7e790e6961063d7 Mon Sep 17 00:00:00 2001 From: andrmng Date: Sat, 8 Dec 2018 20:34:24 -0200 Subject: [PATCH 12/19] tratamento de erro --- rustfmt.toml | 2 +- src/gen/emit.rs | 147 ++++++++++++++++++++++++++++++++++++++++-------- src/gen/mod.rs | 19 ++++++- src/main.rs | 122 +--------------------------------------- 4 files changed, 143 insertions(+), 147 deletions(-) diff --git a/rustfmt.toml b/rustfmt.toml index c7a80ee..425954b 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -49,7 +49,7 @@ use_field_init_shorthand = false force_explicit_abi = true condense_wildcard_suffixes = false color = "Auto" -required_version = "0.99.6" +required_version = "1.0.0" unstable_features = false disable_all_formatting = false skip_children = false diff --git a/src/gen/emit.rs b/src/gen/emit.rs index b67c942..a7b8185 100644 --- a/src/gen/emit.rs +++ b/src/gen/emit.rs @@ -70,7 +70,10 @@ impl Emit<(*mut LLVMValue, Type)> for Variable { )), } } else { - Err(("Variable not defined".to_string(), *location)) + Err(( + format!("Variable {} not defined", identifier), + *location, + )) } } } @@ -136,7 +139,13 @@ impl Emit<(*mut LLVMValue, Type)> for Expr { .zip(function_signature.1) .map(|(param, param_expected_type)| { match param.emit(context) { - Ok((value, type_of)) => Ok(value), + Ok((value, type_of)) => { + //if type_of == param_expected_type { + // Err(("Parametro diferente do esperado", *location)) + //} + // else { Ok(value) }, + Ok(value) + } Err(e) => Err(e), } }) @@ -158,17 +167,72 @@ impl Emit<(*mut LLVMValue, Type)> for Expr { let builder = context.builder; let (lhs, type_of_lhs) = lhs.emit(context)?; let (rhs, type_of_rhs) = rhs.emit(context)?; + let mut type_of_result; let value = match op { Opcode::Add => { + if type_of_lhs != Type::Int { + return Err(( + "Lado esquerda da soma não é inteiro" + .to_string(), + *location, + )); + } + if type_of_rhs != Type::Int { + return Err(( + "Lado direito da soma não é inteiro" + .to_string(), + *location, + )); + } + type_of_result = Type::Int; LLVMBuildAdd(builder, lhs, rhs, as_str!("add_result")) } Opcode::Sub => { + if type_of_lhs != Type::Int { + return Err(( + "Lado esquerda da subtração não é inteiro" + .to_string(), + *location, + )); + } + if type_of_rhs != Type::Int { + return Err(( + "Lado direito da subtração não é inteiro" + .to_string(), + *location, + )); + } + type_of_result = Type::Int; LLVMBuildSub(builder, lhs, rhs, as_str!("sub_result")) } Opcode::Div => { + if type_of_lhs != Type::Int { + return Err(( + "Lado esquerda da divisão não é inteiro" + .to_string(), + *location, + )); + } + if type_of_rhs != Type::Int { + return Err(( + "Lado direito da divisão não é inteiro" + .to_string(), + *location, + )); + } + type_of_result = Type::Int; + LLVMBuildUDiv(builder, lhs, rhs, as_str!("div_result")) } Opcode::Mul => { + if type_of_lhs != Type::Int { + return Err(("Lado esquerda da multiplicação não é inteiro".to_string(), *location)); + } + if type_of_rhs != Type::Int { + return Err(("Lado direito da multiplicação não é inteiro".to_string(), *location)); + } + type_of_result = Type::Int; + LLVMBuildMul(builder, lhs, rhs, as_str!("mul_result")) } Opcode::Mod => panic!("Não encontrei a chamada do modulo"), @@ -177,16 +241,33 @@ impl Emit<(*mut LLVMValue, Type)> for Expr { | Opcode::Greater | Opcode::GreaterOrEqual | Opcode::Equal - | Opcode::Different => LLVMBuildICmp( - context.builder, - op.pred(), - lhs, - rhs, - as_str!("cmp"), - ), + | Opcode::Different => { + if type_of_lhs != Type::Int { + return Err(( + "Lado esquerda da comparação não é inteiro" + .to_string(), + *location, + )); + } + if type_of_rhs != Type::Int { + return Err(( + "Lado direito da comparação não é inteiro" + .to_string(), + *location, + )); + } + type_of_result = Type::Bool; + LLVMBuildICmp( + context.builder, + op.pred(), + lhs, + rhs, + as_str!("cmp"), + ) + } _ => panic!("Not implemented"), }; - Ok((value, Type::Int)) // FIXME type_of depend on the operand + Ok((value, type_of_result)) // FIXME type_of depend on the operand } Expr::Right(op, expression, location) => { let builder = context.builder; @@ -222,6 +303,9 @@ impl Emit<()> for Stmt { let (ptr_var, type_of) = var.emit(context)?; let (expression, type_of_expression) = expression.emit(context)?; + if type_of_expression != type_of { + return Err(("Atribuição inválida".to_string(), *location)); + } LLVMBuildStore(builder, expression, ptr_var); Ok(()) @@ -273,6 +357,9 @@ impl Emit<()> for Stmt { LLVMPositionBuilderAtEnd(context.builder, block_predicate); let (predicate, type_of_predicate) = predicate.emit(context).unwrap(); + if type_of_predicate != Type::Bool { + return Err(("Predicado não é booleano".to_string(), *location)); + } LLVMBuildCondBr( context.builder, predicate, @@ -321,8 +408,15 @@ impl Emit<()> for Stmt { LLVMBuildBr(context.builder, block_predicate); - let (predicate, type_of_predicate) = - predicate.emit(context).unwrap(); + let (predicate, type_of_predicate) = predicate.emit(context)?; + + if type_of_predicate != Type::Bool { + return Err(( + "Predicado não é booleano".to_string(), + *location, + )); + } + LLVMPositionBuilderAtEnd(context.builder, block_predicate); LLVMBuildCondBr( context.builder, @@ -453,8 +547,14 @@ impl Emit<()> for Stmt { ); LLVMPositionBuilderAtEnd(context.builder, block_if_predicate); - let (cmp_expression, type_of) = - expression.emit(context).unwrap(); + let (cmp_expression, type_of) = expression.emit(context)?; + if type_of != Type::Bool { + return Err(( + "Predicado não é booleano".to_string(), + *location, + )); + } + LLVMBuildCondBr( context.builder, cmp_expression, @@ -811,7 +911,7 @@ impl Emit<()> for Decl { } }); - block.emit(context).unwrap(); + block.emit(context)?; context.symbol_table.kill_scope(); @@ -828,13 +928,12 @@ impl Emit<()> for Block { self: &Self, context: &mut Context, ) -> Result<(), (String, Location)> { - self.decl - .iter() - .for_each(|decl| decl.emit(context).unwrap()); - - self.commands - .iter() - .for_each(|command| command.emit(context).unwrap()); + for decl in self.decl.iter() { + decl.emit(context)?; + } + for command in self.commands.iter() { + command.emit(context)?; + } Ok(()) } @@ -846,8 +945,8 @@ impl Emit<()> for Either { context: &mut Context, ) -> Result<(), (String, Location)> { match self { - Either::Left(stmt) => stmt.emit(context).unwrap(), - Either::Right(block) => block.emit(context).unwrap(), + Either::Left(stmt) => stmt.emit(context)?, + Either::Right(block) => block.emit(context)?, }; Ok(()) diff --git a/src/gen/mod.rs b/src/gen/mod.rs index 4e4c0bb..43fca3c 100644 --- a/src/gen/mod.rs +++ b/src/gen/mod.rs @@ -1,3 +1,9 @@ +use codespan::CodeMap; +use codespan_reporting::{ + emit, + termcolor::{ColorChoice, StandardStream}, + Diagnostic, Label, +}; use std::ffi::CString; #[macro_use] @@ -15,11 +21,20 @@ mod context; mod emit; mod symbol_table; -pub unsafe fn gen(decls: Vec) { +pub unsafe fn gen(decls: Vec, code_map: &CodeMap) { let mut context = context::Context::new(); context.declare_printf_scanf(); for i in decls { - i.emit(&mut context).expect("Cannot emit this"); + let writer = StandardStream::stderr(ColorChoice::Always); + match i.emit(&mut context) { + Err((msg, span)) => { + let diagnostic = Diagnostic::new_error(msg); + let label = Label::new_primary(span); + emit(writer, &code_map, &diagnostic.with_label(label)); + panic!("Paro"); + } + _ => {} + } } LLVMDumpModule(context.module); LLVMPrintModuleToFile( diff --git a/src/main.rs b/src/main.rs index 168eb77..1a65e68 100644 --- a/src/main.rs +++ b/src/main.rs @@ -60,7 +60,7 @@ fn main() { unsafe { let mut erros = vec![]; match grammar::ProgramParser::new().parse(&mut erros, &file.src()) { - Ok(expr) => gen::gen(expr), + Ok(expr) => gen::gen(expr, &code_map), Err(err) => match err { ParseError::UnrecognizedToken { token, expected } => { let (start, token, end) = match token { @@ -126,122 +126,4 @@ fn main() { }, } } -} - -#[test] -fn parse_var_decl_with_init() { - let mut errors = vec![]; - - let var_decl = grammar::ProgramParser::new() - .parse(&mut errors, "let a = 2 : int;") - .unwrap(); - - assert_eq!( - var_decl, - [ast::Decl::Single( - "a".to_string(), - ast::Type::Int, - Some(Box::new(ast::Expr::Number(2))) - )] - ); -} - -#[test] -fn parse_var_decl_without_init() { - let mut errors = vec![]; - - let var_decl = grammar::ProgramParser::new() - .parse(&mut errors, "let a : int;") - .unwrap(); - - assert_eq!( - var_decl, - [ast::Decl::Single("a".to_string(), ast::Type::Int, None)] - ); -} - -#[test] -fn parse_var_multi_decl_without_init() { - let mut errors = vec![]; - - let var_decl = grammar::ProgramParser::new() - .parse(&mut errors, "let a, b,c : int;") - .unwrap(); - - assert_eq!( - var_decl, - [ - ast::Decl::Single("a".to_string(), ast::Type::Int, None), - ast::Decl::Single("b".to_string(), ast::Type::Int, None), - ast::Decl::Single("c".to_string(), ast::Type::Int, None) - ] - ); -} - -#[test] -fn parse_var_multi_decl_with_init() { - let mut errors = vec![]; - - let var_decl = grammar::ProgramParser::new() - .parse(&mut errors, "let a = 1, b =2,c = 3 : int;") - .unwrap(); - - assert_eq!( - var_decl, - [ - ast::Decl::Single( - "a".to_string(), - ast::Type::Int, - Some(Box::new(ast::Expr::Number(1))) - ), - ast::Decl::Single( - "b".to_string(), - ast::Type::Int, - Some(Box::new(ast::Expr::Number(2))) - ), - ast::Decl::Single( - "c".to_string(), - ast::Type::Int, - Some(Box::new(ast::Expr::Number(3))) - ) - ] - ); -} - -#[test] -fn parse_var_decl_with_expr_init() { - let mut errors = vec![]; - - let var_decl = grammar::ProgramParser::new() - .parse(&mut errors, "let a = b + 1 : int;") - .unwrap(); - - assert_eq!( - var_decl, - [ast::Decl::Single( - "a".to_string(), - ast::Type::Int, - Some(Box::new(ast::Expr::Op( - Box::new(ast::Expr::Variable(ast::Variable::Single( - "b".to_string() - ))), - ast::Opcode::Add, - Box::new(ast::Expr::Number(1)) - ))) - )] - ); -} - -#[test] -fn parse_var_decl_array_int_without_init() { - let mut errors = vec![]; - - let var_decl = grammar::ProgramParser::new() - .parse(&mut errors, "let v[10] : int;") - .unwrap(); - - assert_eq!( - var_decl, - [ast::Decl::Array("v".to_string(), ast::Type::Int, 10, None)] - ); -} +} \ No newline at end of file From 929295ea6764a7565e737324a9c6357abbae60e1 Mon Sep 17 00:00:00 2001 From: Guilherme Chichanoski Date: Mon, 10 Dec 2018 23:24:42 -0200 Subject: [PATCH 13/19] remove tests try to fix array param --- src/gen/emit.rs | 159 ++++++++++++++++++++++++++++++++-------- src/gen/mod.rs | 1 - src/grammar/mod.lalrpop | 2 +- src/main.rs | 119 +----------------------------- 4 files changed, 131 insertions(+), 150 deletions(-) diff --git a/src/gen/emit.rs b/src/gen/emit.rs index b67c942..7ff721a 100644 --- a/src/gen/emit.rs +++ b/src/gen/emit.rs @@ -21,7 +21,9 @@ impl Emit<*mut LLVMType> for Type { Type::Bool => Ok(LLVMInt1TypeInContext(context.context)), Type::Void => Ok(LLVMVoidTypeInContext(context.context)), Type::Str => panic!("Not implemented"), - Type::Agg(_) => panic!("Not implemented"), + Type::Agg(type_of) => { + Ok(LLVMPointerType(type_of.emit(context)?, 0)) + } } } } @@ -36,7 +38,8 @@ impl Emit<(*mut LLVMValue, Type)> for Variable { Variable::Single(identifier, location) => { if let Ok(value) = context.symbol_table.get(identifier) { match value { - Symbol::Variable(value, type_of) => { + Symbol::Variable(value, type_of) + | Symbol::Array(value, type_of) => { Ok((*value, type_of.clone())) } _ => Err(( @@ -171,6 +174,12 @@ impl Emit<(*mut LLVMValue, Type)> for Expr { Opcode::Mul => { LLVMBuildMul(builder, lhs, rhs, as_str!("mul_result")) } + Opcode::And => { + LLVMBuildAnd(builder, lhs, rhs, as_str!("and_result")) + } + Opcode::Or => { + LLVMBuildOr(builder, lhs, rhs, as_str!("or_result")) + } Opcode::Mod => panic!("Não encontrei a chamada do modulo"), Opcode::Lesser | Opcode::LesserOrEqual @@ -271,8 +280,9 @@ impl Emit<()> for Stmt { LLVMBuildBr(context.builder, block_predicate); LLVMPositionBuilderAtEnd(context.builder, block_predicate); - let (predicate, type_of_predicate) = - predicate.emit(context).unwrap(); + + let (predicate, type_of_predicate) = predicate.emit(context)?; + LLVMBuildCondBr( context.builder, predicate, @@ -321,9 +331,9 @@ impl Emit<()> for Stmt { LLVMBuildBr(context.builder, block_predicate); + LLVMPositionBuilderAtEnd(context.builder, block_predicate); let (predicate, type_of_predicate) = predicate.emit(context).unwrap(); - LLVMPositionBuilderAtEnd(context.builder, block_predicate); LLVMBuildCondBr( context.builder, predicate, @@ -531,6 +541,32 @@ impl Emit<()> for Stmt { Ok(()) } + Stmt::Read(variable, location) => { + let format_int = LLVMBuildGlobalStringPtr( + context.builder, + as_str!("%d"), + as_str!("format_int"), + ); + + let scanf_fn = match context.symbol_table.get("0scanf").unwrap() + { + Symbol::Func(value, _type_of) => value, + _ => panic!("What"), + }; + + let (variable_ptr, type_of) = + variable.emit(&mut context.clone())?; + + LLVMBuildCall( + context.builder, + *scanf_fn, + vec![format_int, variable_ptr].as_mut_ptr(), + 1, + as_str!("call_read"), + ); + + Ok(()) + } _ => panic!("Not implemented"), } } @@ -642,10 +678,22 @@ impl Emit<()> for Decl { expression_size, as_str!(identifier), ); - context + if context .symbol_table - .set(identifier, Symbol::Array(ptr_vlr, type_of.clone())) - .expect("Can't set the variable, probably the variable is already declared"); + .set( + identifier, + Symbol::Array(ptr_vlr, type_of.clone()), + ) + .is_err() + { + return Err(( + format!( + "Identifier {} already declared", + identifier + ), + *location, + )); + } // TODO Initialization @@ -663,13 +711,22 @@ impl Emit<()> for Decl { as_str!(identifier), ); - context + if context .symbol_table .set( identifier, Symbol::Variable(decl, type_of.clone()), ) - .unwrap(); + .is_err() + { + return Err(( + format!( + "Identifier {} already declared", + identifier + ), + *location, + )); + } if let Some(expression) = expression { let (value, type_of) = @@ -698,10 +755,19 @@ impl Emit<()> for Decl { as_str!(identifier), ); - context + if context .symbol_table .set(identifier, Symbol::Array(decl, type_of.clone())) - .unwrap(); + .is_err() + { + return Err(( + format!( + "Identifier {} already declared", + identifier + ), + *location, + )); + } // TODO Initialization @@ -714,6 +780,7 @@ impl Emit<()> for Decl { block, location, ) => { + dbg!(vec_params); let vec_params = vec_params.clone().unwrap_or_default(); let mut args = vec_params @@ -744,7 +811,7 @@ impl Emit<()> for Decl { function_type, ); - context + if context .symbol_table .set( identifier, @@ -754,23 +821,24 @@ impl Emit<()> for Decl { return_type.clone().unwrap_or_default(), vec_params .iter() - .map(|param| match param { - FuncParam::Single( - _, - type_of, - _, - ) => type_of.clone(), - FuncParam::Array(_, type_of, _) => { - Type::Agg(Box::new( - type_of.clone(), - )) - } + .map(|param| match param { + FuncParam::Single( _, type_of, _,) + | FuncParam::Array(_, type_of, _) => type_of.clone(), }) .collect::>(), ), ), ) - .unwrap(); + .is_err() + { + return Err(( + format!( + "Identifier {} already declared", + identifier + ), + *location, + )); + } let entry_block = LLVMAppendBasicBlockInContext( context.context, @@ -788,7 +856,11 @@ impl Emit<()> for Decl { LLVMGetParam(function, index as u32); match param { - FuncParam::Single(identifier, type_of, location) => { + FuncParam::Single( + identifier, + type_of, + location, + ) => { let ptr_vlr = LLVMBuildAlloca( context.builder, type_of.emit(context).unwrap(), @@ -796,8 +868,14 @@ impl Emit<()> for Decl { ); context .symbol_table - .set(&identifier, Symbol::Variable(ptr_vlr, type_of.clone())) - .expect("Can't set the variable, probably the variable is already declared"); + .set( + &identifier, + Symbol::Variable( + ptr_vlr, + type_of.clone(), + ), + ) + .unwrap(); LLVMBuildStore( context.builder, @@ -805,8 +883,25 @@ impl Emit<()> for Decl { ptr_vlr, ); } - FuncParam::Array(_identifier, _type_of, location) => { - panic!("Not implemented yet") + FuncParam::Array(identifier, type_of, location) => { + let ptr_vlr = LLVMBuildAlloca( + context.builder, + type_of.emit(context).unwrap(), + as_str!(identifier), + ); + context + .symbol_table + .set( + &identifier, + Symbol::Array(ptr_vlr, type_of.clone()), + ) + .unwrap(); + + LLVMBuildStore( + context.builder, + function_param, + ptr_vlr, + ); } } }); @@ -815,6 +910,10 @@ impl Emit<()> for Decl { context.symbol_table.kill_scope(); + if !return_type.is_some() { + LLVMBuildRetVoid(context.builder); + } + context.actual_function = None; Ok(()) } diff --git a/src/gen/mod.rs b/src/gen/mod.rs index 4e4c0bb..868c4f6 100644 --- a/src/gen/mod.rs +++ b/src/gen/mod.rs @@ -21,7 +21,6 @@ pub unsafe fn gen(decls: Vec) { for i in decls { i.emit(&mut context).expect("Cannot emit this"); } - LLVMDumpModule(context.module); LLVMPrintModuleToFile( context.module, as_str!("test.ll"), diff --git a/src/grammar/mod.lalrpop b/src/grammar/mod.lalrpop index 73264c8..f1178b0 100644 --- a/src/grammar/mod.lalrpop +++ b/src/grammar/mod.lalrpop @@ -282,7 +282,7 @@ FuncDecl: Decl = DEF OPEN_PARENS COL if let Some((identifier, location)) = declaration.0 { // If either is fullfiled in the left is a single variable parameters_vector.push(FuncParam::Single(identifier, type_of.clone(), location)); } else if let Some((identifier, location)) = declaration.1 { // Else if is fullfiled in the right side is an array - parameters_vector.push(FuncParam::Array(identifier, type_of.clone(), location)); + parameters_vector.push(FuncParam::Array(identifier, Type::Agg(Box::new(type_of.clone())), location)); } } } diff --git a/src/main.rs b/src/main.rs index 168eb77..c3b6565 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ #![allow(unknown_lints)] #![warn(clippy::all)] +#![feature(dbg_macro)] extern crate clap; extern crate codespan; @@ -127,121 +128,3 @@ fn main() { } } } - -#[test] -fn parse_var_decl_with_init() { - let mut errors = vec![]; - - let var_decl = grammar::ProgramParser::new() - .parse(&mut errors, "let a = 2 : int;") - .unwrap(); - - assert_eq!( - var_decl, - [ast::Decl::Single( - "a".to_string(), - ast::Type::Int, - Some(Box::new(ast::Expr::Number(2))) - )] - ); -} - -#[test] -fn parse_var_decl_without_init() { - let mut errors = vec![]; - - let var_decl = grammar::ProgramParser::new() - .parse(&mut errors, "let a : int;") - .unwrap(); - - assert_eq!( - var_decl, - [ast::Decl::Single("a".to_string(), ast::Type::Int, None)] - ); -} - -#[test] -fn parse_var_multi_decl_without_init() { - let mut errors = vec![]; - - let var_decl = grammar::ProgramParser::new() - .parse(&mut errors, "let a, b,c : int;") - .unwrap(); - - assert_eq!( - var_decl, - [ - ast::Decl::Single("a".to_string(), ast::Type::Int, None), - ast::Decl::Single("b".to_string(), ast::Type::Int, None), - ast::Decl::Single("c".to_string(), ast::Type::Int, None) - ] - ); -} - -#[test] -fn parse_var_multi_decl_with_init() { - let mut errors = vec![]; - - let var_decl = grammar::ProgramParser::new() - .parse(&mut errors, "let a = 1, b =2,c = 3 : int;") - .unwrap(); - - assert_eq!( - var_decl, - [ - ast::Decl::Single( - "a".to_string(), - ast::Type::Int, - Some(Box::new(ast::Expr::Number(1))) - ), - ast::Decl::Single( - "b".to_string(), - ast::Type::Int, - Some(Box::new(ast::Expr::Number(2))) - ), - ast::Decl::Single( - "c".to_string(), - ast::Type::Int, - Some(Box::new(ast::Expr::Number(3))) - ) - ] - ); -} - -#[test] -fn parse_var_decl_with_expr_init() { - let mut errors = vec![]; - - let var_decl = grammar::ProgramParser::new() - .parse(&mut errors, "let a = b + 1 : int;") - .unwrap(); - - assert_eq!( - var_decl, - [ast::Decl::Single( - "a".to_string(), - ast::Type::Int, - Some(Box::new(ast::Expr::Op( - Box::new(ast::Expr::Variable(ast::Variable::Single( - "b".to_string() - ))), - ast::Opcode::Add, - Box::new(ast::Expr::Number(1)) - ))) - )] - ); -} - -#[test] -fn parse_var_decl_array_int_without_init() { - let mut errors = vec![]; - - let var_decl = grammar::ProgramParser::new() - .parse(&mut errors, "let v[10] : int;") - .unwrap(); - - assert_eq!( - var_decl, - [ast::Decl::Array("v".to_string(), ast::Type::Int, 10, None)] - ); -} From 116cc755dd22d4569f142c3a3ed635c8d8e5be72 Mon Sep 17 00:00:00 2001 From: Guilherme Chichanoski Date: Tue, 11 Dec 2018 00:02:49 -0200 Subject: [PATCH 14/19] refactor gen --- src/gen/mod.rs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/gen/mod.rs b/src/gen/mod.rs index 937e122..33039d8 100644 --- a/src/gen/mod.rs +++ b/src/gen/mod.rs @@ -4,7 +4,7 @@ use codespan_reporting::{ termcolor::{ColorChoice, StandardStream}, Diagnostic, Label, }; -use std::ffi::CString; +use std::{ffi::CString, process::exit}; #[macro_use] macro_rules! as_str { @@ -26,14 +26,11 @@ pub unsafe fn gen(decls: Vec, code_map: &CodeMap) { context.declare_printf_scanf(); for i in decls { let writer = StandardStream::stderr(ColorChoice::Always); - match i.emit(&mut context) { - Err((msg, span)) => { - let diagnostic = Diagnostic::new_error(msg); - let label = Label::new_primary(span); - emit(writer, &code_map, &diagnostic.with_label(label)); - panic!("Paro"); - } - _ => {} + if let Err((msg, span)) = i.emit(&mut context) { + let diagnostic = Diagnostic::new_error(msg); + let label = Label::new_primary(span); + emit(writer, &code_map, &diagnostic.with_label(label)).unwrap(); + exit(127); } } LLVMPrintModuleToFile( From 668409319b9bf488d6cd3e043a88115952e43bf7 Mon Sep 17 00:00:00 2001 From: Guilherme Chichanoski Date: Tue, 11 Dec 2018 00:15:08 -0200 Subject: [PATCH 15/19] fix procedure call --- src/gen/emit.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/gen/emit.rs b/src/gen/emit.rs index 68c40f4..2da043f 100644 --- a/src/gen/emit.rs +++ b/src/gen/emit.rs @@ -133,6 +133,13 @@ impl Emit<(*mut LLVMValue, Type)> for Expr { let params = params.clone().unwrap_or_default(); let function_signature = function_signature.clone(); + let mut name = if function_signature.0 == Type::Void + { + "".to_string() + } else { + "call".to_string() + }; + Ok(( LLVMBuildCall( builder, @@ -155,7 +162,7 @@ impl Emit<(*mut LLVMValue, Type)> for Expr { .collect::, _>>()? .as_mut_ptr(), params.len() as u32, - as_str!("call"), + as_str!(name), ), function_signature.0, )) From b3a9c85df2c00e04b7f88495e89f2531f2c79a6b Mon Sep 17 00:00:00 2001 From: Guilherme Chichanoski Date: Tue, 11 Dec 2018 01:04:12 -0200 Subject: [PATCH 16/19] add more errors and broke some array, tiago will solve it --- src/gen/emit.rs | 195 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 130 insertions(+), 65 deletions(-) diff --git a/src/gen/emit.rs b/src/gen/emit.rs index 2da043f..1533ab9 100644 --- a/src/gen/emit.rs +++ b/src/gen/emit.rs @@ -55,6 +55,12 @@ impl Emit<(*mut LLVMValue, Type)> for Variable { if let Ok(value) = context.clone().symbol_table.get(identifier) { let (index, type_of_index) = expression.emit(context)?; + if type_of_index != Type::Int { + return Err(( + "array index must be an integer".to_string(), + *location, + )); + } match value { Symbol::Array(value, type_of) => Ok(( @@ -89,11 +95,11 @@ impl Emit<(*mut LLVMValue, Type)> for Expr { context: &mut Context, ) -> Result<(*mut LLVMValue, Type), (String, Location)> { match self { - Expr::Number(number, location) => Ok(( + Expr::Number(number, _location) => Ok(( LLVMConstInt(Type::Int.emit(context)?, *number, 1), Type::Int, )), - Expr::StringLitteral(string, location) => Ok(( + Expr::StringLitteral(string, _location) => Ok(( LLVMBuildGlobalStringPtr( context.builder, as_str!(string), @@ -101,13 +107,13 @@ impl Emit<(*mut LLVMValue, Type)> for Expr { ), Type::Str, )), - Expr::True(location) => { + Expr::True(_location) => { Ok((LLVMConstInt(Type::Bool.emit(context)?, 1, 1), Type::Bool)) } - Expr::False(location) => { + Expr::False(_location) => { Ok((LLVMConstInt(Type::Bool.emit(context)?, 0, 1), Type::Bool)) } - Expr::Variable(var, location) => { + Expr::Variable(var, _location) => { let (ptr_var, type_of) = var.emit(context)?; match type_of { @@ -147,17 +153,12 @@ impl Emit<(*mut LLVMValue, Type)> for Expr { params .iter() .zip(function_signature.1) - .map(|(param, param_expected_type)| { - match param.emit(context) { - Ok((value, type_of)) => { - //if type_of == param_expected_type { - // Err(("Parametro diferente do esperado", *location)) - //} - // else { Ok(value) }, - Ok(value) - } - Err(e) => Err(e), + .map::, _>(|(param, param_expected_type)| { + let (value, type_of) = param.emit(context)?; + if type_of == param_expected_type { + Err(("Tipo do parametro diferente do esperado".to_string(), *location)) } + else { Ok(value) } }) .collect::, _>>()? .as_mut_ptr(), @@ -315,18 +316,37 @@ impl Emit<(*mut LLVMValue, Type)> for Expr { Expr::Right(op, expression, location) => { let builder = context.builder; let (expression, type_of) = expression.emit(context)?; - let value = match op { + match op { Opcode::Not => { - LLVMBuildNot(builder, expression, as_str!("not_result")) + if type_of == Type::Bool { + Ok(( + LLVMBuildNot( + builder, + expression, + as_str!("not_result"), + ), + Type::Bool, + )) + } else { + Err(("Should be a boolean".to_string(), *location)) + } } - Opcode::Negative => LLVMBuildNeg( - builder, - expression, - as_str!("negation_result"), - ), - _ => panic!("Should not do this"), - }; - Ok((value, Type::Int)) // FIXME type_of depend on the operand + Opcode::Negative => { + if type_of == Type::Int { + Ok(( + LLVMBuildNeg( + builder, + expression, + as_str!("negation_result"), + ), + Type::Int, + )) + } else { + Err(("Should be an integer".to_string(), *location)) + } + } + _ => Err(("Should not reach this".to_string(), *location)), + } } Expr::Ternary(_predicate, _then, _else, _location) => { panic!("Not implemented yet") @@ -505,9 +525,10 @@ impl Emit<()> for Stmt { Err(("Skip not in a loop".to_string(), *location)) } } - Stmt::Return(expression, location) => { + Stmt::Return(expression, _location) => { + // TODO Check return expression type match function return type if let Some(expression) = expression { - let (expression, type_of) = + let (expression, _type_of) = expression.emit(context).unwrap(); LLVMBuildRet(context.builder, expression); Ok(()) @@ -553,7 +574,7 @@ impl Emit<()> for Stmt { } None => block_merge, }; - let block_else_to_jump = elifs.iter().rev().fold( + let block_else_to_jump = elifs.iter().rev().try_fold( last_block, |last_block, actual_block| { let block_elif_predicate = @@ -572,7 +593,14 @@ impl Emit<()> for Stmt { block_elif_predicate, ); let (elif_predicate, type_of_elif_predicate) = - actual_block.0.emit(context).unwrap(); + actual_block.0.emit(context)?; + + if type_of_elif_predicate != Type::Bool { + return Err(( + "predicate is not an boolean".to_string(), + *location, + )); + } LLVMBuildCondBr( context.builder, @@ -585,13 +613,13 @@ impl Emit<()> for Stmt { block_elif_then, ); context.symbol_table.initialize_scope(); - actual_block.1.emit(context).unwrap(); + actual_block.1.emit(context)?; context.symbol_table.kill_scope(); LLVMBuildBr(context.builder, block_merge); - block_elif_predicate + Ok(block_elif_predicate) }, - ); + )?; LLVMPositionBuilderAtEnd(context.builder, block_if_predicate); let (cmp_expression, type_of) = expression.emit(context)?; @@ -610,7 +638,7 @@ impl Emit<()> for Stmt { ); LLVMPositionBuilderAtEnd(context.builder, block_if_then); context.symbol_table.initialize_scope(); - block.emit(context).unwrap(); + block.emit(context)?; context.symbol_table.kill_scope(); LLVMBuildBr(context.builder, block_merge); LLVMPositionBuilderAtEnd(context.builder, block_merge); @@ -642,32 +670,42 @@ impl Emit<()> for Stmt { as_str!("barra_n"), ); - list_expr.iter().for_each(|expr| { - let (value, type_of) = - expr.emit(&mut context.clone()).unwrap(); + list_expr + .iter() + .try_for_each::<_, Result<(), SemanticError>>(|expr| { + let (value, type_of) = + expr.emit(&mut context.clone())?; + + match type_of { + Type::Int | Type::Bool => { + LLVMBuildCall( + context.builder, + *printf_fn, + vec![format_int, value].as_mut_ptr(), + 2, + as_str!("call_write"), + ); + } + Type::Str => { + LLVMBuildCall( + context.builder, + *printf_fn, + vec![format_str, value].as_mut_ptr(), + 2, + as_str!("call_write"), + ); + } + _ => { + return Err(( + "type not writeable".to_string(), + *location, + )); + } + }; + + Ok(()) + })?; - match type_of { - Type::Int | Type::Bool => { - LLVMBuildCall( - context.builder, - *printf_fn, - vec![format_int, value].as_mut_ptr(), - 2, - as_str!("call_write"), - ); - } - Type::Str => { - LLVMBuildCall( - context.builder, - *printf_fn, - vec![format_str, value].as_mut_ptr(), - 2, - as_str!("call_write"), - ); - } - _ => panic!("Not implemented"), - } - }); LLVMBuildCall( context.builder, *printf_fn, @@ -694,6 +732,13 @@ impl Emit<()> for Stmt { let (variable_ptr, type_of) = variable.emit(&mut context.clone())?; + if type_of != Type::Int { + return Err(( + "Output must be an integer".to_string(), + *location, + )); + } + LLVMBuildCall( context.builder, *scanf_fn, @@ -704,7 +749,6 @@ impl Emit<()> for Stmt { Ok(()) } - _ => panic!("Not implemented"), } } } @@ -791,6 +835,13 @@ impl Emit<()> for Decl { if let Some(expression) = expression { let (expression, type_of_expression) = expression.emit(context).unwrap(); + if type_of_expression != *type_of { + return Err(( + "Type of expression mismatch variable" + .to_string(), + *location, + )); + } LLVMBuildStore(builder, expression, ptr_vlr); Ok(()) } else { @@ -803,9 +854,10 @@ impl Emit<()> for Decl { identifier, type_of, size, - list_expression, + _list_expression, location, ) => { + // TODO Initialize array let (expression_size, _) = Expr::Number(*size, *location).emit(context).unwrap(); @@ -866,8 +918,16 @@ impl Emit<()> for Decl { } if let Some(expression) = expression { - let (value, type_of) = - expression.emit(context).unwrap(); + let (value, type_of_expression) = + expression.emit(context)?; + + if *type_of != type_of_expression { + return Err(( + "Initializer type mismtach variable type" + .to_string(), + *location, + )); + } LLVMSetInitializer(decl, value); } @@ -878,9 +938,10 @@ impl Emit<()> for Decl { identifier, type_of, size, - list_expression, + _list_expression, location, ) => { + // TODO Initialize array let array_type = LLVMArrayType( type_of.emit(context).unwrap(), *size as u32, @@ -995,7 +1056,7 @@ impl Emit<()> for Decl { FuncParam::Single( identifier, type_of, - location, + _location, ) => { let ptr_vlr = LLVMBuildAlloca( context.builder, @@ -1019,7 +1080,11 @@ impl Emit<()> for Decl { ptr_vlr, ); } - FuncParam::Array(identifier, type_of, location) => { + FuncParam::Array( + identifier, + type_of, + _location, + ) => { let ptr_vlr = LLVMBuildAlloca( context.builder, type_of.emit(context).unwrap(), From 0c78e1a1c91d63fbab130fae628e63ffeabe947d Mon Sep 17 00:00:00 2001 From: Guilherme Chichanoski Date: Tue, 11 Dec 2018 12:44:58 -0200 Subject: [PATCH 17/19] fix examples --- examples/arr.nani | 22 +++++++++++++++------- examples/arr2.nani | 4 ++++ 2 files changed, 19 insertions(+), 7 deletions(-) create mode 100644 examples/arr2.nani diff --git a/examples/arr.nani b/examples/arr.nani index 40a5f49..888b5fc 100644 --- a/examples/arr.nani +++ b/examples/arr.nani @@ -1,16 +1,24 @@ -let i[2] = { 1, 2 }: int; -let j[2] = { false, true }: bool; +let i[2] : int; +let j[2] : bool; def array_with_expr_index() { - let i[3] = { 3, 4, 5 }: int; - let k: int; + let i[3] : int; + let k = 0: int; + + i[0] = 3; + i[1] = 4; + i[2] = 5; write i[k], i[k + 1]; - return; } def main(): int { - let i[2] = { 3, 4 }: int; - let j[2] = { false, true }: bool; + let i[2]: int; + let j[2] : bool; + i[0] = 3; + i[1] = 4; + + j[0] = false; + j[1] = true; write i[0], i[1]; write j[0], j[1]; diff --git a/examples/arr2.nani b/examples/arr2.nani new file mode 100644 index 0000000..faf994c --- /dev/null +++ b/examples/arr2.nani @@ -0,0 +1,4 @@ +def main(v[]: int; a: int): int { + var x = v[a] : int; + a++; +} From d7bdc5f43d7c1bbd72b02fdf416ded541358c9a3 Mon Sep 17 00:00:00 2001 From: andrmng Date: Tue, 11 Dec 2018 19:14:08 -0200 Subject: [PATCH 18/19] =?UTF-8?q?exemplos=20e=20tern=C3=A1rio?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/arr.nani | 8 +-- examples/aspas1aspas.nani | 4 ++ examples/fibonacci.nani | 11 ++++ examples/for.nani | 2 +- examples/ifs.nani | 5 +- examples/jarroba.nani | 3 ++ examples/ternary.nani | 12 +++++ src/gen/context.rs | 4 +- src/gen/emit.rs | 106 +++++++++++++++++++++++++++++--------- src/main.rs | 2 +- 10 files changed, 124 insertions(+), 33 deletions(-) create mode 100644 examples/aspas1aspas.nani create mode 100644 examples/fibonacci.nani create mode 100644 examples/jarroba.nani create mode 100644 examples/ternary.nani diff --git a/examples/arr.nani b/examples/arr.nani index 40a5f49..c112648 100644 --- a/examples/arr.nani +++ b/examples/arr.nani @@ -2,15 +2,15 @@ let i[2] = { 1, 2 }: int; let j[2] = { false, true }: bool; def array_with_expr_index() { - let i[3] = { 3, 4, 5 }: int; - let k: int; + var i[3] = { 3, 4, 5 }: int; + var k: int; write i[k], i[k + 1]; return; } def main(): int { - let i[2] = { 3, 4 }: int; - let j[2] = { false, true }: bool; + var i[2] = { 3, 4 }: int; + var j[2] = { false, true }: bool; write i[0], i[1]; write j[0], j[1]; diff --git a/examples/aspas1aspas.nani b/examples/aspas1aspas.nani new file mode 100644 index 0000000..a3a2bb2 --- /dev/null +++ b/examples/aspas1aspas.nani @@ -0,0 +1,4 @@ +def main(): int { + var i: int; + i = "1"; +} diff --git a/examples/fibonacci.nani b/examples/fibonacci.nani new file mode 100644 index 0000000..948dd97 --- /dev/null +++ b/examples/fibonacci.nani @@ -0,0 +1,11 @@ +def main(): int { + var a = 1, b = 1, aux, i: int; + write "fibonacci"; + while (b <= 100){ + write a; + aux = a; + a = b; + b = b + aux; + } + return 0; +} diff --git a/examples/for.nani b/examples/for.nani index f42db81..9ad3904 100644 --- a/examples/for.nani +++ b/examples/for.nani @@ -1,5 +1,5 @@ def main(): int { - let i: int; + var i: int; for (i = 0; i < 10; i += 1) { write i; diff --git a/examples/ifs.nani b/examples/ifs.nani index 8d34215..3a5289a 100644 --- a/examples/ifs.nani +++ b/examples/ifs.nani @@ -1,8 +1,8 @@ def main(): int { - let x = true: bool; + var x = true: bool; if (x == true) { - let i: int; + var i: int; read i; write i + 10; } else { @@ -11,3 +11,4 @@ def main(): int { return 0; } + diff --git a/examples/jarroba.nani b/examples/jarroba.nani new file mode 100644 index 0000000..0ba8e9f --- /dev/null +++ b/examples/jarroba.nani @@ -0,0 +1,3 @@ +def main(): int { + var j@: int; +} diff --git a/examples/ternary.nani b/examples/ternary.nani new file mode 100644 index 0000000..fd3035e --- /dev/null +++ b/examples/ternary.nani @@ -0,0 +1,12 @@ +def main(): int { + var a = false: bool; + + var b = (a ? 1 : 2): int; + var c: int; + c = false ? 10 : 20; + + write b; + write c; + + return 0; +} diff --git a/src/gen/context.rs b/src/gen/context.rs index f695a4c..8879c19 100644 --- a/src/gen/context.rs +++ b/src/gen/context.rs @@ -11,7 +11,7 @@ pub struct Context { pub module: *mut LLVMModule, pub context: *mut LLVMContext, pub builder: *mut LLVMBuilder, - pub actual_function: Option<(*mut LLVMValue, *mut LLVMBasicBlock)>, // (function, entry) + pub current_function: Option<(*mut LLVMValue, *mut LLVMBasicBlock)>, // (function, entry) } impl Context { @@ -22,7 +22,7 @@ impl Context { symbol_table: SymbolTable::new(), module: LLVMModuleCreateWithName(as_str!("program")), context, - actual_function: None, + current_function: None, builder: LLVMCreateBuilderInContext(context), } } diff --git a/src/gen/emit.rs b/src/gen/emit.rs index 1533ab9..47b6b6e 100644 --- a/src/gen/emit.rs +++ b/src/gen/emit.rs @@ -348,8 +348,68 @@ impl Emit<(*mut LLVMValue, Type)> for Expr { _ => Err(("Should not reach this".to_string(), *location)), } } - Expr::Ternary(_predicate, _then, _else, _location) => { - panic!("Not implemented yet") + Expr::Ternary(predicate, truehs, falsehs, location) => { + let builder = context.builder; + + let block_predicate = LLVMAppendBasicBlockInContext( + context.context, + context.current_function.unwrap().0, + as_str!("ternary_predicate"), + ); + LLVMBuildBr(context.builder, block_predicate); + let block_truehs = LLVMAppendBasicBlockInContext( + context.context, + context.current_function.unwrap().0, + as_str!("ternary_truehs"), + ); + let block_falsehs = LLVMAppendBasicBlockInContext( + context.context, + context.current_function.unwrap().0, + as_str!("ternary_falsehs"), + ); + let block_merge = LLVMAppendBasicBlockInContext( + context.context, + context.current_function.unwrap().0, + as_str!("ternary_merge"), + ); + + LLVMPositionBuilderAtEnd(context.builder, block_predicate); + let (predicate, type_of_predicate) = predicate.emit(context)?; + if type_of_predicate != Type::Bool { + return Err(( + "Predicado do ternário não é do tipo booleano" + .to_string(), + *location, + )); + } + LLVMBuildCondBr( + context.builder, + predicate, + block_truehs, + block_falsehs, + ); + + LLVMPositionBuilderAtEnd(context.builder, block_truehs); + let (truehs, type_of_truehs) = truehs.emit(context)?; + LLVMBuildBr(context.builder, block_merge); + + LLVMPositionBuilderAtEnd(context.builder, block_falsehs); + let (falsehs, type_of_falsehs) = falsehs.emit(context)?; + LLVMBuildBr(context.builder, block_merge); + + if type_of_truehs != type_of_falsehs { + return Err(( + "Caso positivo do ternario não é do mesmo tipo do caso negativo" + .to_string(), + *location, + )); + } + + LLVMPositionBuilderAtEnd(context.builder, block_merge); + let phi = LLVMBuildPhi(builder, type_of_truehs.emit(context)?, as_str!("phi_result")); + LLVMAddIncoming(phi, [truehs, falsehs].as_mut_ptr(), [block_truehs, block_falsehs].as_mut_ptr(), 2); + + Ok((phi, type_of_truehs)) } } } @@ -389,22 +449,22 @@ impl Emit<()> for Stmt { init.emit(context)?; let block_predicate = LLVMAppendBasicBlockInContext( context.context, - context.actual_function.unwrap().0, + context.current_function.unwrap().0, as_str!("predicate_for"), ); let block_for = LLVMAppendBasicBlockInContext( context.context, - context.actual_function.unwrap().0, + context.current_function.unwrap().0, as_str!("block_for"), ); let block_step = LLVMAppendBasicBlockInContext( context.context, - context.actual_function.unwrap().0, + context.current_function.unwrap().0, as_str!("block_step"), ); let block_merge = LLVMAppendBasicBlockInContext( context.context, - context.actual_function.unwrap().0, + context.current_function.unwrap().0, as_str!("merge_for"), ); @@ -450,17 +510,17 @@ impl Emit<()> for Stmt { Stmt::While(predicate, block, location) => { let block_predicate = LLVMAppendBasicBlockInContext( context.context, - context.actual_function.unwrap().0, + context.current_function.unwrap().0, as_str!("predicate_for"), ); let block_while = LLVMAppendBasicBlockInContext( context.context, - context.actual_function.unwrap().0, + context.current_function.unwrap().0, as_str!("block_for"), ); let block_merge = LLVMAppendBasicBlockInContext( context.context, - context.actual_function.unwrap().0, + context.current_function.unwrap().0, as_str!("merge_for"), ); @@ -540,25 +600,25 @@ impl Emit<()> for Stmt { Stmt::If(expression, block, elifs, else_block, location) => { let block_if_predicate = LLVMAppendBasicBlockInContext( context.context, - context.actual_function.unwrap().0, + context.current_function.unwrap().0, as_str!("if_predicate"), ); LLVMBuildBr(context.builder, block_if_predicate); let block_if_then = LLVMAppendBasicBlockInContext( context.context, - context.actual_function.unwrap().0, + context.current_function.unwrap().0, as_str!("if_then"), ); let block_merge = LLVMAppendBasicBlockInContext( context.context, - context.actual_function.unwrap().0, + context.current_function.unwrap().0, as_str!("merge_if"), ); let last_block = match else_block { Some(else_block) => { let block_if_else = LLVMAppendBasicBlockInContext( context.context, - context.actual_function.unwrap().0, + context.current_function.unwrap().0, as_str!("if_else"), ); LLVMPositionBuilderAtEnd( @@ -576,16 +636,16 @@ impl Emit<()> for Stmt { }; let block_else_to_jump = elifs.iter().rev().try_fold( last_block, - |last_block, actual_block| { + |last_block, current_block| { let block_elif_predicate = LLVMAppendBasicBlockInContext( context.context, - context.actual_function.unwrap().0, + context.current_function.unwrap().0, as_str!("block_elif"), ); let block_elif_then = LLVMAppendBasicBlockInContext( context.context, - context.actual_function.unwrap().0, + context.current_function.unwrap().0, as_str!("block_elif"), ); LLVMPositionBuilderAtEnd( @@ -593,7 +653,7 @@ impl Emit<()> for Stmt { block_elif_predicate, ); let (elif_predicate, type_of_elif_predicate) = - actual_block.0.emit(context)?; + current_block.0.emit(context)?; if type_of_elif_predicate != Type::Bool { return Err(( @@ -613,7 +673,7 @@ impl Emit<()> for Stmt { block_elif_then, ); context.symbol_table.initialize_scope(); - actual_block.1.emit(context)?; + current_block.1.emit(context)?; context.symbol_table.kill_scope(); LLVMBuildBr(context.builder, block_merge); @@ -758,17 +818,17 @@ impl Emit<()> for Decl { self: &Self, context: &mut Context, ) -> Result<(), (String, Location)> { - if context.actual_function.is_some() { + if context.current_function.is_some() { // When local let alloc_builder = LLVMCreateBuilderInContext(context.context); let first_intr = - LLVMGetFirstInstruction(context.actual_function.unwrap().1); + LLVMGetFirstInstruction(context.current_function.unwrap().1); if !first_intr.is_null() { LLVMPositionBuilderBefore(alloc_builder, first_intr); } else { LLVMPositionBuilderAtEnd( alloc_builder, - context.actual_function.unwrap().1, + context.current_function.unwrap().1, ); } @@ -1045,7 +1105,7 @@ impl Emit<()> for Decl { context.symbol_table.initialize_scope(); - context.actual_function = Some((function, entry_block)); + context.current_function = Some((function, entry_block)); LLVMPositionBuilderAtEnd(context.builder, entry_block); vec_params.iter().enumerate().for_each(|(index, param)| { @@ -1115,7 +1175,7 @@ impl Emit<()> for Decl { LLVMBuildRetVoid(context.builder); } - context.actual_function = None; + context.current_function = None; Ok(()) } } diff --git a/src/main.rs b/src/main.rs index ee1596a..f05bf19 100644 --- a/src/main.rs +++ b/src/main.rs @@ -118,7 +118,7 @@ fn main() { .unwrap(); let diagnostic = - Diagnostic::new_error("invalid line or EOF"); + Diagnostic::new_error("Token inválido"); let label = Label::new_primary(span); emit(writer, &code_map, &diagnostic.with_label(label)) From 64ab1c5381a02f1a5ae9a966b2487a0effa37e2d Mon Sep 17 00:00:00 2001 From: Guilherme Chichanoski Date: Tue, 11 Dec 2018 19:40:35 -0200 Subject: [PATCH 19/19] initialize array --- src/gen/emit.rs | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/src/gen/emit.rs b/src/gen/emit.rs index 47b6b6e..c861d41 100644 --- a/src/gen/emit.rs +++ b/src/gen/emit.rs @@ -406,8 +406,17 @@ impl Emit<(*mut LLVMValue, Type)> for Expr { } LLVMPositionBuilderAtEnd(context.builder, block_merge); - let phi = LLVMBuildPhi(builder, type_of_truehs.emit(context)?, as_str!("phi_result")); - LLVMAddIncoming(phi, [truehs, falsehs].as_mut_ptr(), [block_truehs, block_falsehs].as_mut_ptr(), 2); + let phi = LLVMBuildPhi( + builder, + type_of_truehs.emit(context)?, + as_str!("phi_result"), + ); + LLVMAddIncoming( + phi, + [truehs, falsehs].as_mut_ptr(), + [block_truehs, block_falsehs].as_mut_ptr(), + 2, + ); Ok((phi, type_of_truehs)) } @@ -914,7 +923,7 @@ impl Emit<()> for Decl { identifier, type_of, size, - _list_expression, + list_expression, location, ) => { // TODO Initialize array @@ -944,7 +953,26 @@ impl Emit<()> for Decl { )); } - // TODO Initialization + if let Some(list_expression) = list_expression { + list_expression.iter().enumerate().try_for_each( + |(index, element)| { + Stmt::Attr( + Variable::Array( + identifier.to_owned(), + Box::new(Expr::Number( + index as u64, + *location, + )), + *location, + ), + element.clone(), + *location, + ) + .emit(context)?; + Ok(()) + }, + )?; + } Ok(()) }