diff --git a/libllvm/src/lib.rs b/libllvm/src/lib.rs index 16ee8bd..f0f9c4a 100644 --- a/libllvm/src/lib.rs +++ b/libllvm/src/lib.rs @@ -5,3 +5,4 @@ extern crate libc; pub mod wrapper; pub use wrapper::*; +pub use llvm_sys::analysis::LLVMVerifierFailureAction; \ No newline at end of file diff --git a/libllvm/src/wrapper.rs b/libllvm/src/wrapper.rs index deb43a0..963ce05 100644 --- a/libllvm/src/wrapper.rs +++ b/libllvm/src/wrapper.rs @@ -1,14 +1,15 @@ -pub use llvm_sys::prelude::{LLVMBuilderRef, LLVMContextRef, LLVMModuleRef, LLVMPassManagerRef, - LLVMTypeRef, LLVMValueRef, LLVMBasicBlockRef}; -pub use llvm_sys::execution_engine::{LLVMExecutionEngineRef, LLVMGenericValueRef, - LLVMGenericValueToFloat, LLVMRunFunction}; -pub use llvm_sys::analysis::{LLVMVerifierFailureAction, LLVMVerifyFunction}; -pub use llvm_sys::LLVMRealPredicate; +use llvm_sys::prelude::{LLVMBuilderRef, LLVMContextRef, LLVMModuleRef, LLVMPassManagerRef, + LLVMTypeRef, LLVMValueRef, LLVMBasicBlockRef}; +use llvm_sys::execution_engine::{LLVMExecutionEngineRef, LLVMGenericValueRef, + LLVMGenericValueToFloat, LLVMRunFunction}; +use llvm_sys::analysis::{LLVMVerifierFailureAction, LLVMVerifyFunction}; +use llvm_sys::LLVMRealPredicate; pub use llvm_sys::core::*; +use llvm_sys::transforms; -pub use libc::{c_char, c_uint, c_ulonglong}; -use std::char; -use std::ffi::{CString}; +use std::ptr; +use libc::{c_char, c_uint, c_ulonglong}; +use std::ffi::CString; @@ -46,6 +47,7 @@ macro_rules! make_LLVM_wrapper { make_LLVM_wrapper!(LLVMModuleRef, LLVMModule); make_LLVM_wrapper!(LLVMContextRef, LLVMContext); +make_LLVM_wrapper!(LLVMPassManagerRef, LLVMFunctionPassManager); make_LLVM_wrapper!(LLVMValueRef, LLVMValue, Copy); make_LLVM_wrapper!(LLVMValueRef, LLVMFunction, Copy); make_LLVM_wrapper!(LLVMTypeRef, LLVMType, Copy); @@ -99,6 +101,15 @@ impl LLVMContext { LLVMType(t) } + pub fn get_const_string(&self, s: &str) -> LLVMValue { + unsafe { + LLVMValue::from_ref(LLVMConstStringInContext(self.raw_ptr(), + raw_string(s), + s.len() as ::libc::c_uint, + 0)) + } + } + pub fn get_double_const(&self, val: f64) -> LLVMValue { unsafe { LLVMValue::from_ref(LLVMConstReal(self.get_double_type().raw_ptr(), @@ -157,10 +168,35 @@ impl LLVMModule { } } +impl LLVMFunctionPassManager { + pub fn init_for_module(m: &LLVMModule) -> Self { + unsafe { + let llfpm = LLVMCreateFunctionPassManagerForModule(m.raw_ptr()); + transforms::scalar::LLVMAddBasicAliasAnalysisPass(llfpm); + transforms::scalar::LLVMAddInstructionCombiningPass(llfpm); + transforms::scalar::LLVMAddReassociatePass(llfpm); + transforms::scalar::LLVMAddGVNPass(llfpm); + transforms::scalar::LLVMAddCFGSimplificationPass(llfpm); + // transforms::scalar::LLVMAddDeadStoreEliminationPass(llfpm); + transforms::scalar::LLVMAddMergedLoadStoreMotionPass(llfpm); + LLVMInitializeFunctionPassManager(llfpm); + LLVMFunctionPassManager(llfpm) + } + } + pub fn run(&self, f: &LLVMFunction) { + unsafe { + LLVMRunFunctionPassManager(self.raw_ptr(), f.raw_ptr()); + } + } +} + impl LLVMType { pub fn get_ptr(&self, address_space: usize) -> Self { unsafe { LLVMType(LLVMPointerType(self.0.clone(), address_space as c_uint)) } } + pub fn get_element(&self) -> Self { + unsafe { LLVMType(LLVMGetElementType(self.0.clone())) } + } } impl LLVMValue { @@ -172,9 +208,7 @@ impl LLVMValue { LLVMFunction::from_ref(self.0) } pub fn get_type(&self) -> LLVMType { - unsafe { - LLVMType::from_ref(LLVMTypeOf(self.0)) - } + unsafe { LLVMType::from_ref(LLVMTypeOf(self.0)) } } } @@ -197,6 +231,10 @@ impl LLVMFunction { pub fn get_entry_basic_block(&self) -> LLVMBasicBlock { unsafe { LLVMBasicBlock::from_ref(LLVMGetEntryBasicBlock(self.raw_ptr())) } } + + pub fn verify(&self, action: LLVMVerifierFailureAction) { + unsafe { LLVMVerifyFunction(self.raw_ptr(), action) }; + } } macro_rules! method_build_instr { @@ -238,11 +276,17 @@ impl LLVMBuilder { method_build_instr!(ret, LLVMBuildRet, val: &LLVMValue); method_build_instr!(bit_cast, LLVMBuildBitCast, val: &LLVMValue, dest_ty: &LLVMType => name: &str); + pub fn ret_void(&self) -> LLVMValue { + unsafe { + LLVMValue::from_ref(LLVMBuildRet(self.raw_ptr(), ptr::null_mut())) + } + } pub fn call(&self, fun: &LLVMFunction, args: &mut Vec, name: &str) -> LLVMValue { let mut _args: Vec<_> = args.iter_mut().map(|arg| arg.raw_ptr()).collect(); unsafe { + let f = fun.raw_ptr(); let ret = LLVMBuildCall(self.raw_ptr(), - fun.raw_ptr(), + f, _args.as_mut_ptr(), args.len() as c_uint, raw_string(name)); @@ -253,7 +297,8 @@ impl LLVMBuilder { pub fn struct_field_ptr(&self, ptr: &LLVMValue, idx: usize, name: &str) -> LLVMValue { unsafe { - let ret = LLVMBuildStructGEP(self.raw_ptr(), ptr.raw_ptr(), idx as u32, raw_string(name)); + let ret = + LLVMBuildStructGEP(self.raw_ptr(), ptr.raw_ptr(), idx as u32, raw_string(name)); LLVMValue::from_ref(ret) } } @@ -290,10 +335,16 @@ impl Drop for LLVMBuilder { } } } +impl Drop for LLVMFunctionPassManager { + fn drop(&mut self) { + unsafe { + LLVMDisposePassManager(self.0); + } + } +} pub type LLVMOperateBuild = unsafe extern "C" fn(LLVMBuilderRef, - LLVMValueRef, - LLVMValueRef, - *const ::libc::c_char) - -> LLVMValueRef; - + LLVMValueRef, + LLVMValueRef, + *const ::libc::c_char) + -> LLVMValueRef; diff --git a/src/codegen/emit.rs b/src/codegen/emit.rs index 6b0be2f..17f17b2 100644 --- a/src/codegen/emit.rs +++ b/src/codegen/emit.rs @@ -19,11 +19,7 @@ pub struct LLVMEmit<'i> { pub type VarEnv<'a> = SymTable<'a, Id, LLVMValue>; -fn with_var<'a, 'b: 'a, F, R>( - sym: &mut VarEnv<'a>, - var: Id, - val: LLVMValue, - mut cb: F) -> R +fn with_var<'a, 'b: 'a, F, R>(sym: &mut VarEnv<'a>, var: Id, val: LLVMValue, mut cb: F) -> R where F: FnMut(&mut VarEnv<'a>) -> R { let old = sym.insert(var, val); @@ -41,7 +37,7 @@ impl<'i> LLVMEmit<'i> { pub fn new(name: &str, interner: &'i mut Interner) -> Self { LLVMEmit { generator: LLVMCodegen::new(name), - interner + interner, } } pub fn dump(&mut self) { @@ -50,9 +46,15 @@ impl<'i> LLVMEmit<'i> { pub fn gen_top_level(&mut self, def: &FunDef, prelude: &VarEnv) { // A global function definition let fun_type = def.ref_type(); + let void_ret: bool = if let &Type::Arr(_, box Type::Void) = fun_type { + true + } else { + false + }; let llvm_fun_type = self.generator.get_llvm_type(fun_type); let def_name = def.name(); let fun = self.generator.module.get_or_add_function(def_name, &llvm_fun_type); + let arg_count = fun.count_params(); // Check redefinition @@ -66,64 +68,63 @@ impl<'i> LLVMEmit<'i> { // Create a sub environment for current function generating let mut symtbl = prelude.sub_env(); - let mut params_ref: Vec<_> = def.parameters().iter().collect(); - - let last_param: Option<&VarDecl> = if let Some(&VarDecl(_, ref _last_type)) = - def.parameters().last() { - match _last_type.body() { - &Type::Prod(..) => params_ref.pop(), - _ => None, + let param_defs = def.parameters(); + let mut param_count = param_defs.len(); + let param_allocas = self.alloca_for_vars(&fun, param_defs); + if param_allocas.len() + 1 < arg_count { + let last_formal = param_defs.last(); + if let Some(p) = last_formal { + let &VarDecl(ref id, ref ty) = p; + param_count = param_count - 1; + // Actual parameters counts more than formal, last formal parameter type is production + let flatten_count = ty.body().prod_to_vec().len(); + let last_alloca = self.alloca_for_var(&fun, p); + for i in 0..flatten_count { + let idx_name = i.to_string(); + let arg = fun.get_param(i + param_count); + let arg_name = self.trace_id(id.to_owned()).to_owned() + idx_name.as_str(); + arg.set_name(arg_name.as_str()); + let field = self.builder().struct_field_ptr(&last_alloca, i, idx_name.as_str()); + self.builder().store(&arg, &field); + } + symtbl.insert(id.to_owned(), last_alloca); } - } else { - None - }; - - - // Spread length - let len_head = params_ref.len(); - - // For each parameter, set argument name, - // create store instruction, add to - // symbol table. - for (i, param) in params_ref.into_iter().enumerate() { - let &VarDecl(pname, ref ptype) = param; + } + for i in 0..param_count { + let var = param_allocas[i]; let arg = fun.get_param(i); + let pname = param_defs[i].name(); arg.set_name(self.trace_id(pname)); - - let alloca = self.alloca_for_var(&fun, param); - - self.builder().store(&arg, &alloca); - symtbl.insert(pname, alloca); + self.builder().store(&arg, &var); + symtbl.insert(pname, var); } - if let Some(param) = last_param { - let &VarDecl(ref last_name, ref last_type) = param; - let flatten_count = last_type.body().prod_to_vec().len(); - - // Handle the last parameter - let last_alloca = self.alloca_for_var(&fun, param); - for i in 0..flatten_count { - let idx_name = i.to_string(); - let arg = fun.get_param(i + len_head); - let arg_name = self.trace_id(last_name.to_owned()).to_owned() + idx_name.as_str(); - arg.set_name(arg_name.as_str()); - let field = self.builder().struct_field_ptr(&last_alloca, i, idx_name.as_str()); - self.builder().store(&arg, &field); - } + let p_fvs = fun.get_param(arg_count - 1); + p_fvs.set_name("fvs"); + + let formal_fvs = def.fv(); + let fv_allocas = self.alloca_for_vars(&fun, formal_fvs); + let fv_tys = fv_allocas.iter().map(|v| v.get_type().get_element()).collect(); + let fv_ty_actual = self.generator.context.get_struct_type(&fv_tys, false); + let fv_ptr_actual = self.builder().bit_cast(&p_fvs, &fv_ty_actual.get_ptr(0), "fv"); + for (i, fv) in fv_allocas.into_iter().enumerate() { + let fv_id = formal_fvs[i].name(); + let fv_name = self.interner.trace(fv_id); + let fv_val_ptr = + self.builder().struct_field_ptr(&fv_ptr_actual, i, "tmp"); + let fv_val = self.builder().load(&fv_val_ptr, fv_name); + self.builder().store(&fv_val, &fv); + symtbl.insert(fv_id, fv); } let fun_body = self.gen_expr(def.body(), &mut symtbl); + self.builder().ret(&fun_body); - unsafe { - if LLVMVerifyFunction(fun.raw_ptr(), - LLVMVerifierFailureAction::LLVMPrintMessageAction) != - 0 { - println!("Function verify failed"); - } - } + fun.verify(LLVMVerifierFailureAction::LLVMPrintMessageAction); + self.generator.passer.run(&fun); } pub fn gen_expr<'a: 'b, 'b>(&mut self, term: &'a TaggedTerm, @@ -136,16 +137,10 @@ impl<'i> LLVMEmit<'i> { let var_name = self.interner.trace(vn); match symbols.lookup(&vn) { Some(v) => self.builder().load(v, var_name), - _ => unreachable!(), // global functions should be converted to closure - - // // It must be a global definition because of type check - // None => { - // let llvm_type = self.generator.get_llvm_type_or_ptr(term.ref_scheme().body()); - // self.0 - // .module - // .get_or_add_function(var_name, &llvm_type) - // .into_value() - // } + _ => { + println!("cannot find variable {}", self.interner.trace(vn)); + unreachable!() + } // global functions should be converted to closure } } Binary(op, ref lhs, ref rhs) => { @@ -167,12 +162,9 @@ impl<'i> LLVMEmit<'i> { self.builder().store(&init, &alloca); - with_var(symbols, var, alloca, |sym| { - self.gen_expr(exp.deref(), sym) - }) + with_var(symbols, var, alloca, |sym| self.gen_expr(exp.deref(), sym)) } ApplyCls(ref callee, ref args) => { - let callee_ty = self.generator.get_llvm_type(callee.ref_scheme().body()); // get the pointer to closure struct let callee_ptr = self.gen_expr(callee, symbols); //.into_function(); @@ -180,15 +172,20 @@ impl<'i> LLVMEmit<'i> { args.iter().map(|arg| self.gen_expr(arg, symbols)).collect(); // get fvs from closure struct - let fvs_ptr = self.builder().struct_field_ptr(&callee_ptr, 1, "cls.fv"); // add fv into arguments - argsv.push(fvs_ptr); + let fvs = { + let fvs_ptr = self.builder().struct_field_ptr(&callee_ptr, 1, "cls.fvptr"); + self.builder().load(&fvs_ptr, "cls.fv") + }; + argsv.push(fvs); // get actual function entry let fn_entry_ptr = self.builder().struct_field_ptr(&callee_ptr, 0, "cls.fn"); // get a void* pointer let fn_entry = self.builder().load(&fn_entry_ptr, "cls.fn.actual"); // cast to function pointer + let callee_ty = self.generator.get_llvm_type(callee.ref_scheme().body()).get_ptr(0); + // self.builder().bit_cast(&fn_entry, &callee_ty, "cls.callee") let fun = self.builder().bit_cast(&fn_entry, &callee_ty, "cls.callee").into_function(); @@ -212,15 +209,20 @@ impl<'i> LLVMEmit<'i> { // make a closure type let fv_ty: Vec = cls.fv() .into_iter() - .map(|fv_name| symbols.lookup(&fv_name).unwrap().get_type()) + .map(|fv_name| { + symbols.lookup(&fv_name) + .unwrap() + .get_type() + .get_element() + }) .collect(); let cls_actual_ty = self.generator.get_actual_cls_type(&fv_ty); // allocate for closure - let alloca = self.builder().alloca(&cls_actual_ty, "cls.actual"); + let cls_ptr = self.builder().alloca(&cls_actual_ty, "cls.actual"); // set function entry - let elm_ptr_fun = self.builder().struct_field_ptr(&alloca, 0, "cls.fn"); + let elm_ptr_fun = self.builder().struct_field_ptr(&cls_ptr, 0, "cls.fn"); let fn_ent = self.generator .module .get_or_add_function(cls.entry(), &fun_ty) @@ -233,7 +235,7 @@ impl<'i> LLVMEmit<'i> { self.builder().store(&fn_ent_ptr, &elm_ptr_fun); // store free vars - let elm_ptr_fv = self.builder().struct_field_ptr(&alloca, 1, "cls.fv"); + let elm_ptr_fv = self.builder().struct_field_ptr(&cls_ptr, 1, "cls.fv"); for (i, fv_id) in cls.fv().into_iter().enumerate() { // if variable stored a pointer, it will get (type **) // if stored a value, (type *) @@ -246,12 +248,16 @@ impl<'i> LLVMEmit<'i> { self.builder().store(&val, &fv); } - let cls_ty = self.generator.get_closure_type(); - let cls_var = self.builder().bit_cast(&alloca, &cls_ty, "cls"); + let cls_var = { + let cls_ty = self.generator.get_closure_type().get_ptr(0); + let val = self.builder().bit_cast(&cls_ptr, &cls_ty, "cls"); + self.get_value_ptr(&val) + }; - with_var(symbols, var_decl.name(), cls_var, |sym| { - self.gen_expr(exp, sym) - }) + with_var(symbols, + var_decl.name(), + cls_var, + |sym| self.gen_expr(exp, sym)) } List(_) => unimplemented!(), Unary(_, _) => unimplemented!(), @@ -270,10 +276,20 @@ impl<'i> LLVMEmit<'i> { self.generator.create_entry_block_alloca(&fun, name, ty) } + fn alloca_for_vars(&mut self, fun: &LLVMFunction, vars: &Vec) -> Vec { + vars.iter().map(|v| self.alloca_for_var(fun, v)).collect() + } + fn trace_id(&mut self, id: Id) -> &str { self.interner.trace(id) } + fn get_value_ptr(&mut self, val: &LLVMValue) -> LLVMValue { + let ty = val.get_type(); + let alloca = self.builder().alloca(&ty, "ptr"); + self.builder().store(val, &alloca); + alloca + } } impl EmitProvider for LLVMCodegen { diff --git a/src/codegen/llvm/mod.rs b/src/codegen/llvm.rs similarity index 80% rename from src/codegen/llvm/mod.rs rename to src/codegen/llvm.rs index 276727a..1876865 100644 --- a/src/codegen/llvm/mod.rs +++ b/src/codegen/llvm.rs @@ -20,6 +20,7 @@ pub struct LLVMCodegen { pub module: LLVMModule, pub builder: LLVMBuilder, pub context: LLVMContext, + pub passer: LLVMFunctionPassManager, unique: usize, } @@ -48,7 +49,7 @@ pub fn get_llvm_op(op: BinOp, operand_ty: &Type) -> LLVMOperateBuild { pub fn is_primitive_type(t: &Type) -> bool { if let &Type::Con(ref n) = t { match n.as_str() { - "Int" | "Float" | "Char" => true, + "Int" | "Float" | "Char" | "String" | "Void" => true, _ => false, } } else { @@ -61,37 +62,39 @@ impl LLVMCodegen { let context = LLVMContext::new(); let module = LLVMModule::in_ctx(name, &context); let builder = LLVMBuilder::in_ctx(&context); + let passer = LLVMFunctionPassManager::init_for_module(&module); LLVMCodegen { module, context, builder, + passer, unique: 0, } } pub fn new_symbol(&mut self) -> Result { - let f = String::new() + self.unique.to_string().as_str(); + let f = String::from("tmp") + self.unique.to_string().as_str(); self.unique = self.unique + 1; CString::new(f) } pub fn new_symbol_string(&mut self) -> String { - let f = String::new() + self.unique.to_string().as_str(); + let f = String::from("tmp") + self.unique.to_string().as_str(); self.unique = self.unique + 1; f } pub fn get_closure_type(&self) -> LLVMType { // closure = [i8*, i8*] - let mut mem = vec![self.context.get_int8_type().get_ptr(0), - self.context.get_int8_type().get_ptr(0)]; + let mem = vec![self.context.get_int8_type().get_ptr(0), + self.context.get_int8_type().get_ptr(0)]; self.context.get_struct_type(&mem, false) } pub fn get_actual_cls_type(&self, fv_ty: &Vec) -> LLVMType { - let mut mem = vec![self.context.get_int8_type().get_ptr(0), - self.context.get_struct_type(&fv_ty, false)]; + let mem = vec![self.context.get_int8_type().get_ptr(0), + self.context.get_struct_type(&fv_ty, false)]; self.context.get_struct_type(&mem, false) } @@ -115,6 +118,9 @@ impl LLVMCodegen { "Int" => self.context.get_int32_type(), "Float" => self.context.get_double_type(), "Char" => self.context.get_int8_type(), + "Bool" => self.context.get_int1_type(), + "String" => self.context.get_int8_type().get_ptr(0), + "Void" => self.context.get_void_type(), // User defined types t => self.gen_user_type(t), @@ -122,12 +128,19 @@ impl LLVMCodegen { } &Arr(box ref p, box ref ret) => { // Type of parameters and returned value should be pointer if not primitive - let cls_type = self.get_closure_type().get_ptr(0); - let retty = self.get_llvm_type_or_ptr(ret); - let psty = p.prod_to_vec(); + let fvs_ty = self.context.get_int8_type().get_ptr(0); + let retty = if let &Type::Arr(..) = ret { + self.get_closure_type().get_ptr(0) + } else { + self.get_llvm_type_or_ptr(ret) + }; + let psty = match p { + &Type::Void => vec![], + _ => p.prod_to_vec() + }; let mut llvm_psty: Vec<_> = psty.into_iter().map(|t| self.get_llvm_type_or_ptr(t)).collect(); - llvm_psty.push(cls_type); + llvm_psty.push(fvs_ty); LLVMContext::get_function_type(&retty, &llvm_psty, false) } &Void => self.context.get_void_type(), @@ -152,7 +165,7 @@ impl LLVMCodegen { &Bool(true) => self.context.get_int1_const(1), &Bool(false) => self.context.get_int1_const(0), // TODO: String represent - &Str(ref s) => unimplemented!(), + &Str(ref s) => self.context.get_const_string(s.as_str()), } } diff --git a/src/core/convert.rs b/src/core/convert.rs index ea8026d..7987cdb 100644 --- a/src/core/convert.rs +++ b/src/core/convert.rs @@ -63,7 +63,7 @@ impl<'i> K<'i> { /// Generate a name for closure fn make_cls_name(&mut self, bound: &str) -> String { - self.current.clone() + "$closure$" + bound + self.unique().to_string().as_str() + self.current.clone() + ".inner.closure." + bound + self.unique().to_string().as_str() } /// Convert a global definition to term @@ -266,23 +266,25 @@ impl<'i> K<'i> { Term::Binary(op, box self.transform(*left), box self.transform(*right)) } Let(v, val, exp) => { + let VarDecl(id, scm) = v.clone(); + let origin = self.close_var(id, scm.clone()); let exp_term = self.transform(*exp); - if let Abs(lambda) = val.node { + let ret = if let Abs(lambda) = val.node { // Handle closure let (cls_name, cls_fv) = { - let VarDecl(ref bound, ref var_ty) = v; - let origin = self.close_var(bound.to_owned(), var_ty.to_owned()); + // let VarDecl(ref bound, ref var_ty) = v; + // let origin = self.close_var(bound.to_owned(), var_ty.to_owned()); let (ps, fv, bd) = self.trans_lambda(lambda); - self.release_var(bound); - if let Some(v) = origin { - self.close_var(bound.to_owned(), v); - } + // self.release_var(bound); + // if let Some(v) = origin { + // self.close_var(bound.to_owned(), v); + // } - let bound_str = self.interner.trace(bound.to_owned()).to_owned(); + let bound_str = self.interner.trace(id).to_owned(); let _cls_name = self.make_cls_name(bound_str.as_str()); - self.define_fn(_cls_name, var_ty.clone(), ps, fv, bd) + self.define_fn(_cls_name, scm, ps, fv, bd) }; let cls = Closure::new(cls_name, cls_fv); @@ -292,7 +294,11 @@ impl<'i> K<'i> { // Normal variable bingding let val_term = self.transform(*val); Term::Let(v, box val_term, box exp_term) + }; + if let Some(v) = origin { + self.close_var(id, v); } + ret } Apply(callee, params) => { diff --git a/src/lib/base.c b/src/lib/base.c new file mode 100644 index 0000000..06b89b5 --- /dev/null +++ b/src/lib/base.c @@ -0,0 +1,16 @@ +#include "include/gsvalue.h" +#include "include/gc.h" + +#include + +void printLn(const char *s, void *fv) +{ + puts(s); +} + +void putChar(const char c, void *fv) +{ + putchar(c); +} + + diff --git a/src/runtime/gc.h b/src/lib/include/gc.h similarity index 100% rename from src/runtime/gc.h rename to src/lib/include/gc.h diff --git a/src/runtime/gc_bitmap.h b/src/lib/include/gc_bitmap.h similarity index 100% rename from src/runtime/gc_bitmap.h rename to src/lib/include/gc_bitmap.h diff --git a/src/runtime/gsvalue.h b/src/lib/include/gsvalue.h similarity index 100% rename from src/runtime/gsvalue.h rename to src/lib/include/gsvalue.h diff --git a/src/runtime/gc_bitmap.c b/src/lib/runtime/gc_bitmap.c similarity index 99% rename from src/runtime/gc_bitmap.c rename to src/lib/runtime/gc_bitmap.c index 190ffe6..1e8308a 100644 --- a/src/runtime/gc_bitmap.c +++ b/src/lib/runtime/gc_bitmap.c @@ -1,4 +1,4 @@ -#include "gc_bitmap.h" +#include "../include/gc_bitmap.h" #include diff --git a/src/main.rs b/src/main.rs index 6ff4208..4e8c40e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,6 @@ extern crate miko; use miko::utils::*; use miko::syntax::parser::*; -use miko::types::*; use miko::typeinfer::*; use miko::codegen::emit::*; use miko::core::*; @@ -16,15 +15,13 @@ fn repl() { let mut interner = Interner::new(); - let ty_op = Scheme::Poly(vec!["a".to_string()], - Type::Arr(P(Type::Prod(P(Type::Var("a".to_string())), - P(Type::Var("a".to_string())))), - P(Type::Var("a".to_string())))); + let ty_op = parse_type("forall a. a * a -> a", &mut interner); let mut _ty_env = Infer::new_env(); let prelude = { let ops = ["+", "-", "*", "/"]; - let v: Vec<_> = ops.into_iter().map(|n| (interner.intern(n), ty_op.clone())).collect(); + let mut v: Vec<_> = ops.into_iter().map(|n| (interner.intern(n), ty_op.clone())).collect(); + v.push((interner.intern("puts"), parse_type("String -> Void", &mut interner))); _ty_env.extend_n(v) }; diff --git a/src/syntax/parser/mod.rs b/src/syntax/parser/mod.rs index 8b7c738..75b472d 100644 --- a/src/syntax/parser/mod.rs +++ b/src/syntax/parser/mod.rs @@ -41,6 +41,14 @@ pub fn parse(src: &str, interner: &mut Interner) -> Result, ParseError> module(src, interner) } +use types::Scheme; +pub fn parse_type(src: &str, interner: &mut Interner) -> Scheme { + match type_scheme(src, interner) { + Ok(scm) => scm, + Err(err) => panic!("Parse type failed") + } +} + #[cfg(test)] mod tests { use super::*; @@ -160,32 +168,34 @@ mod tests { #[test] fn case_parse_function_definition() { { + let mut i = Interner::new(); let form = Form::new(Span::new(16, 22), Expr::Abs( Lambda { - param: vec![VarDecl("a".to_string(), Scheme::Slot), VarDecl("b".to_string(), Scheme::Slot)], + param: vec![VarDecl(i.intern("a"), Scheme::Slot), VarDecl(i.intern("b"), Scheme::Slot)], body: box Form::new(Span::new(16,22), Expr::Binary( BinOp::Add, - box Form::new(Span::new(16,18), Expr::Var("a".to_string())), - box Form::new(Span::new(20,22), Expr::Var("b".to_string())) + box Form::new(Span::new(16,18), Expr::Var(i.intern("a"))), + box Form::new(Span::new(20,22), Expr::Var(i.intern("b"))) )) } )); - let output = vec![Def::value(Span::new(0,22), "fuck".to_string(), box form)]; - assert_eq!(module("def fuck(a, b) = a + b", &mut Interner::new()), Ok(output)) + let output = vec![Def::value(Span::new(0,22), i.intern("fuck"), box form)]; + assert_eq!(module("def fuck(a, b) = a + b", &mut i), Ok(output)) } { + let mut i = Interner::new(); let form = Form::new(Span::new(13, 19), Expr::Abs( Lambda { - param: vec![VarDecl("a".to_string(), Scheme::Slot)], + param: vec![VarDecl(i.intern("a"), Scheme::Slot)], body: box Form::new(Span::new(13,19), Expr::Binary( BinOp::Add, - box Form::new(Span::new(13,15), Expr::Var("a".to_string())), + box Form::new(Span::new(13,15), Expr::Var(i.intern("a"))), box Form::new(Span::new(17,19), Expr::Lit(Lit::Int(1))) )) } )); - let output = vec![Def::value(Span::new(0,19), "fuck".to_string(), box form)]; - assert_eq!(module("def fuck(a) = a + 1", &mut Interner::new()), Ok(output)) + let output = vec![Def::value(Span::new(0,19), i.intern("fuck"), box form)]; + assert_eq!(module("def fuck(a) = a + 1", &mut i), Ok(output)) } { let src = diff --git a/src/typeinfer/constraint.rs b/src/typeinfer/constraint.rs index d80c13e..05bbbc8 100644 --- a/src/typeinfer/constraint.rs +++ b/src/typeinfer/constraint.rs @@ -24,7 +24,7 @@ impl Constraint { Constraint(Prod(l1, l2), Prod(r1, r2)) | Constraint(Comp(l1, l2), Comp(r1, r2)) => { let mut u1 = Constraint(*l1, *r1).unify()?; - let mut u2 = Constraint(*l2, *r2).apply(&u1).unify()?; + let u2 = Constraint(*l2, *r2).apply(&u1).unify()?; u1.apply_mut(&u2); u1.extend(u2); Ok(u1) diff --git a/src/typeinfer/infer.rs b/src/typeinfer/infer.rs index 9f3d2f6..3e3ada0 100644 --- a/src/typeinfer/infer.rs +++ b/src/typeinfer/infer.rs @@ -19,7 +19,7 @@ use std::mem; use super::subst::*; use super::constraint::{ Constraint }; -use super::error::{ TypeError }; +pub use super::error::{ TypeError }; #[derive(Debug)] pub struct Infer<'interner> { @@ -133,7 +133,11 @@ impl<'i> Infer<'i> { extends.push((p.0.to_owned(), p.1.clone())); types.push(p.1.body().clone()); } - let typaram = Type::product_n(types); + let typaram = if types.is_empty() { + Type::Void + } else { + Type::product_n(types) + }; let new_env = e.extend_n(extends); let tbody = self.infer(&new_env, fun.body.deref_mut())?; form.tag.ty = Scheme::arrow(typaram, tbody.body().clone()); @@ -315,13 +319,13 @@ impl<'i> Infer<'i> { #[cfg(test)] mod tests { - use typeinfer::infer::*; - use typeinfer::subst::*; - use typeinfer::typeenv::*; + use typeinfer::*; use syntax::form::*; + use types::*; use syntax::parser; use utils::*; use internal::*; + use internal; // use pest::*; @@ -345,7 +349,7 @@ mod tests { #[test] fn infer_lit() { let mut interner = Interner::new(); - let mut inf = Infer::new(&interner); + let mut inf = Infer::new(&mut interner); let mut env = TypeEnv::new(); assert_eq!(inf.infer(&mut env, @@ -364,51 +368,59 @@ mod tests { P(Type::Var("a".to_string())))), P(Type::Var("a".to_string())))); let PRIMITIVES: Vec<(&str, &Scheme)> = vec![("+", &ty_op)]; - let mut syn: Form = parse_expr("(a: Fuck, b) -> let c = a in { c + b }"); + let mut syn: Form = parse_expr(&mut interner, "(a, b) -> let c = a in { c + b + 1 }"); - let mut env = TypeEnv::from_iter(PRIMITIVES.iter().map(|&(n, s)| (n.to_string(), s.clone()))); + let mut env = TypeEnv::from_iter(PRIMITIVES.iter().map(|&(n, s)| (interner.intern(n), s.clone()))); let sub = { - let mut inf = Infer::new(&interner); + let mut inf = Infer::new(&mut interner); inf.infer(&mut env, &mut syn); inf.solve().unwrap() }; - + use typeinfer::subst::SubstMut; syn.apply_mut(&sub); assert_eq!(syn, Form::typed( - Span::new(0, 38), - parser::type_scheme("Fuck * Fuck -> Fuck", &mut Interner::new()).unwrap(), + Span::new(0, 36), + parser::type_scheme("Int * Int -> Int", &mut Interner::new()).unwrap(), Abs(Lambda { param: vec![ - VarDecl(interner.inter("a"), Scheme::con("Fuck")), - VarDecl(interner.inter("b"), Scheme::con("Fuck")) + VarDecl(interner.intern("a"), Scheme::con("Int")), + VarDecl(interner.intern("b"), Scheme::con("Int")) ], body: box Form::typed( - Span::new(15, 38), - Scheme::con("Fuck"), + Span::new(9, 36), + Scheme::con("Int"), Let( - VarDecl(interner.inter("c"), Mono(Type::Con(s("Fuck")))), + VarDecl(interner.intern("c"), Mono(Type::Con(s("Int")))), box Form::typed( - Span::new(23, 25), - Scheme::con("Fuck"), - Expr::Var(interner.inter("a")) + Span::new(17, 19), + Scheme::con("Int"), + Expr::Var(interner.intern("a")) ), box Form::typed( - Span::new(28, 38), - Scheme::con("Fuck"), + Span::new(22, 36), + Scheme::con("Int"), Block(vec![ box Form::typed( - Span::new(30, 36), - Scheme::con("Fuck"), + Span::new(24, 34), + Scheme::con("Int"), Binary(BinOp::Add, box Form::typed( - Span::new(30, 32), - Scheme::con("Fuck"), - Expr::Var(interner.inter("c"))), + Span::new(24, 30), + Scheme::con("Int"), + Binary(BinOp::Add, + box Form::typed( + Span::new(24, 26), + Scheme::con("Int"), + Expr::Var(interner.intern("c"))), + box Form::typed( + Span::new(28, 30), + Scheme::con("Int"), + Expr::Var(interner.intern("b"))))), box Form::typed( - Span::new(34, 36), - Scheme::con("Fuck"), - Expr::Var(interner.inter("b"))))) + Span::new(32, 34), + Scheme::con("Int"), + Expr::Lit(internal::Lit::Int(1))))) ]) ) ) diff --git a/src/typeinfer/mod.rs b/src/typeinfer/mod.rs index 38591dc..f72cd49 100644 --- a/src/typeinfer/mod.rs +++ b/src/typeinfer/mod.rs @@ -5,4 +5,3 @@ mod constraint; mod infer; pub use self::infer::*; -pub use self::error::*; diff --git a/src/types.rs b/src/types.rs index ac5e05c..166ec74 100644 --- a/src/types.rs +++ b/src/types.rs @@ -107,12 +107,17 @@ impl Type { { let mut it = ts.into_iter().rev(); - let last = it.next().unwrap(); - let mut res = last; - for ty in it { - res = Type::Prod(P(ty), P(res)); + let last = it.next(); + match last { + Some(last) => { + let mut res = last; + for ty in it { + res = Type::Prod(P(ty), P(res)); + } + res + } + _ => panic!("Empty vec to product") } - res } pub fn compose_n(ts: I) -> Type where I: IntoIterator