diff --git a/src/codegen/emit.rs b/src/codegen/emit.rs index 8159029..8ad33fa 100644 --- a/src/codegen/emit.rs +++ b/src/codegen/emit.rs @@ -9,7 +9,7 @@ use std::ops::Deref; pub trait EmitProvider { - fn gen_module(&mut self, module: T) where T: IntoIterator; + fn gen_module(&mut self, module: T) where T: IntoIterator; } pub struct LLVMEmit(LLVMCodegen); @@ -22,7 +22,7 @@ impl LLVMEmit { pub fn dump(&mut self) { self.0.module.dump() } - pub fn gen_top_level(&mut self, def: &Definition, prelude: &VarEnv) { + pub fn gen_top_level(&mut self, def: &FunDef, prelude: &VarEnv) { unsafe { // A global function definition let fun_type = def.ref_type(); @@ -70,13 +70,13 @@ impl LLVMEmit { symtbl.insert(pname.as_str(), alloca); } - if let Some(&VarDecl(ref last_name, ref _last_type)) = last_param { - let last_type_flat = _last_type.body().prod_to_vec(); + if let Some(&VarDecl(ref last_name, ref last_type)) = last_param { + let flatten_count = last_type.body().prod_to_vec().len(); // Handle the last parameter let last_alloca = - self.0.create_entry_block_alloca(&fun, last_name.as_str(), _last_type.body()); - println!("fuck: {:?}", last_type_flat.clone()); - for (i, ty) in last_type_flat.into_iter().enumerate() { + self.0.create_entry_block_alloca(&fun, last_name.as_str(), last_type.body()); + // println!("fuck: {:?}", last_type_flat.clone()); + for i in 0..flatten_count { let idx_name = i.to_string(); let arg = fun.get_param(i + len_head); let arg_name = last_name.clone() + idx_name.as_str(); @@ -179,5 +179,5 @@ impl LLVMEmit { } impl EmitProvider for LLVMCodegen { - fn gen_module(&mut self, module: T) where T: IntoIterator {} + fn gen_module(&mut self, module: T) where T: IntoIterator {} } diff --git a/src/codegen/llvm/mod.rs b/src/codegen/llvm/mod.rs new file mode 100644 index 0000000..1401723 --- /dev/null +++ b/src/codegen/llvm/mod.rs @@ -0,0 +1,183 @@ +mod wrapper; + +use std::char; +use std::ffi::{CString, NulError}; +use std::io::{self, BufReader, Read, Write}; +use std::ptr; +use std::collections::HashMap; +use std::iter::*; + +use std::ops::Deref; + +use core::*; +use internal::*; +use types::*; +use utils::*; + +pub use codegen::llvm::wrapper::*; + + +#[derive(Debug, Clone)] +pub struct LLVMCodegen { + pub module: LLVMModule, + pub builder: LLVMBuilder, + pub context: LLVMContext, + unique: usize, +} + + +pub fn get_llvm_op(op: BinOp, operand_ty: &Type) -> LLVMOperateBuild { + use self::BinOp::*; + use self::Type::*; + if let &Con(ref ty_name) = operand_ty { + let name_ref = ty_name.as_str(); + match (op, name_ref) { + (Add, "Int") => LLVMBuildAdd, + (Add, "Float") => LLVMBuildFAdd, + (Sub, "Int") => LLVMBuildSub, + (Sub, "Float") => LLVMBuildFSub, + (Mul, "Int") => LLVMBuildMul, + (Mul, "Float") => LLVMBuildFMul, + (Div, _) => LLVMBuildFDiv, // TODO: I dont know exactly which builder + (Rem, _) => LLVMBuildURem, // should I use for these two + _ => unimplemented!(), + } + } else { + unreachable!() + } +} + +pub fn is_primitive_type(t: &Type) -> bool { + if let &Type::Con(ref n) = t { + match n.as_str() { + "Int" | "Float" | "Char" => true, + _ => false, + } + } else { + false + } +} + +impl LLVMCodegen { + pub fn new(name: &str) -> LLVMCodegen { + unsafe { + let context = LLVMContext::new(); + let module = LLVMModule::in_ctx(name, &context); + let builder = LLVMBuilder::in_ctx(&context); + LLVMCodegen { module, context, builder, unique: 0 } + } + } + + + pub fn new_symbol(&mut self) -> Result { + let f = String::new() + 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(); + self.unique = self.unique + 1; + f + } + + fn get_closure_type(&self) -> LLVMType { + let ptr = self.context.get_int8_type().get_ptr(0); + let mem = vec![self.context.get_int16_type(), ptr]; + self.context.get_struct_type(&mem, false) + } + + /// Get a pointer type if the type is not primitive + pub fn get_llvm_type_or_ptr(&self, ty: &Type) -> LLVMType { + let ret = self.get_llvm_type(ty); + if !is_primitive_type(ty) { + ret.get_ptr(0) + } else { + ret + } + } + + pub fn get_llvm_type(&self, ty: &Type) -> LLVMType { + use self::Type::*; + match ty { + &Con(ref n) => { + match n.as_str() { + + // Primary types + "Int" => self.context.get_int32_type(), + "Float" => self.context.get_double_type(), + "Char" => self.context.get_int8_type(), + + // User defined types + t => self.gen_user_type(t), + } + } + &Arr(box ref p, box ref ret) => { + // Type of parameters and returned value should be pointer if not primitive + let mut cls_type = self.get_closure_type().get_ptr(0); + let mut retty = self.get_llvm_type_or_ptr(ret); + let psty = 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); + LLVMContext::get_function_type(&retty, &llvm_psty, false) + } + &Void => self.context.get_void_type(), + &Prod(..) => { + let mut tys: Vec<_> = ty.prod_to_vec() + .iter() + .map(|t| self.get_llvm_type(t)) + .collect(); + self.context.get_struct_type(&tys, true) + } + &Comp(ref c, ref p) => unimplemented!(), // TODO: determine the type + + &Var(..) => panic!("Unmaterized type"), + } + } + + pub fn gen_lit(&mut self, lit: &Lit) -> LLVMValue { + use self::Lit::*; + match lit { + &Float(f) => self.context.get_double_const(f), + &Int(i) => self.context.get_int32_const(i), + &Bool(true) => self.context.get_int1_const(1), + &Bool(false) => self.context.get_int1_const(0), + // TODO: String represent + &Str(ref s) => unimplemented!(), + } + } + + pub fn gen_user_type(&self, tyname: &str) -> LLVMType { + // TODO: make a user defined type definition + unimplemented!() + } + + pub unsafe fn create_entry_block_alloca(&self, + fun: &LLVMFunction, + var_name: &str, + ty: &Type) + -> LLVMValue { + let builder = LLVMBuilder::in_ctx(&self.context); + let block = fun.get_entry_basic_block(); + let fi = block.get_first_instr(); + let llvm_ty = self.get_llvm_type(ty); + builder.set_position(&block, &fi); + builder.alloca(&llvm_ty, var_name) + } + + pub fn bin_operator(&mut self, + op: BinOp, + lhs: LLVMValue, + rhs: LLVMValue, + operand_ty: &Type) + -> LLVMValue { + let fun = get_llvm_op(op, operand_ty); + unsafe { + LLVMValue::from_ref(fun(self.builder.raw_ptr(), + lhs.raw_ptr(), + rhs.raw_ptr(), + self.new_symbol().unwrap().into_raw())) + } + } +} diff --git a/src/codegen/llvm.rs b/src/codegen/llvm/wrapper.rs similarity index 51% rename from src/codegen/llvm.rs rename to src/codegen/llvm/wrapper.rs index 8a07f1e..ce2568d 100644 --- a/src/codegen/llvm.rs +++ b/src/codegen/llvm/wrapper.rs @@ -1,14 +1,3 @@ -use std::char; -use std::ffi::{CString, NulError}; -use std::io::{self, BufReader, Read, Write}; -use std::ptr; -use std::collections::HashMap; -use std::iter::*; - -use std::ops::Deref; -pub use libc::{c_char, c_uint, c_ulonglong}; - - pub use llvm_sys::prelude::{LLVMBuilderRef, LLVMContextRef, LLVMModuleRef, LLVMPassManagerRef, LLVMTypeRef, LLVMValueRef, LLVMBasicBlockRef}; pub use llvm_sys::execution_engine::{LLVMExecutionEngineRef, LLVMGenericValueRef, @@ -17,36 +6,41 @@ pub use llvm_sys::analysis::{LLVMVerifierFailureAction, LLVMVerifyFunction}; pub use llvm_sys::LLVMRealPredicate; pub use llvm_sys::core::*; -// use codegen::llvm::*; -use core::*; -use internal::*; -use types::*; -use utils::*; - - -#[derive(Debug, Clone)] -pub struct LLVMModule(LLVMModuleRef); -#[derive(Debug, Clone)] -pub struct LLVMContext(LLVMContextRef); -#[derive(Debug, Clone)] -pub struct LLVMValue(LLVMValueRef); -#[derive(Debug, Clone)] -pub struct LLVMFunction(LLVMValueRef); -#[derive(Debug, Clone)] -pub struct LLVMType(LLVMTypeRef); -#[derive(Debug, Clone)] -pub struct LLVMBuilder(LLVMBuilderRef); -#[derive(Debug, Clone)] -pub struct LLVMBasicBlock(LLVMBasicBlockRef); - - -macro_rules! method_raw_ptr { - ($raw_type: ty) => { - pub fn raw_ptr(&self) -> $raw_type { - self.0.clone() +pub use libc::{c_char, c_uint, c_ulonglong}; +use std::char; +use std::ffi::{CString, NulError}; +use std::ptr; + + + +pub trait LLVMWrapper { + fn from_ref(ptr: T) -> Self; + fn raw_ptr(&self) -> T; +} + +macro_rules! make_LLVM_wrapper { + ($origin:ty, $wrapper:ident) => { + #[derive(Debug, Clone)] + pub struct $wrapper($origin); + impl LLVMWrapper<$origin> for $wrapper { + fn from_ref(ptr: $origin) -> Self { + $wrapper(ptr) + } + fn raw_ptr(&self) -> $origin { + self.0.clone() + } } - }; + } } + +make_LLVM_wrapper!(LLVMModuleRef, LLVMModule); +make_LLVM_wrapper!(LLVMContextRef, LLVMContext); +make_LLVM_wrapper!(LLVMValueRef, LLVMValue); +make_LLVM_wrapper!(LLVMValueRef, LLVMFunction); +make_LLVM_wrapper!(LLVMTypeRef, LLVMType); +make_LLVM_wrapper!(LLVMBuilderRef, LLVMBuilder); +make_LLVM_wrapper!(LLVMBasicBlockRef, LLVMBasicBlock); + macro_rules! method_get_type { ($name: ident, $fun: ident) => { pub fn $name(&self) -> LLVMType { @@ -57,11 +51,16 @@ macro_rules! method_get_type { }; } +pub unsafe fn raw_string(s: &str) -> *mut c_char { + CString::new(s).unwrap().into_raw() +} + + + impl LLVMContext { pub fn new() -> Self { unsafe { LLVMContext(LLVMContextCreate()) } } - method_raw_ptr!(LLVMContextRef); method_get_type!(get_int1_type, LLVMInt1TypeInContext); method_get_type!(get_int8_type, LLVMInt8TypeInContext); method_get_type!(get_int16_type, LLVMInt16TypeInContext); @@ -129,7 +128,6 @@ impl LLVMModule { pub fn in_ctx(name: &str, ctx: &LLVMContext) -> Self { unsafe { LLVMModule(LLVMModuleCreateWithNameInContext(raw_string(name), ctx.raw_ptr())) } } - method_raw_ptr!(LLVMModuleRef); pub fn dump(&self) { unsafe { LLVMDumpModule(self.raw_ptr()) } } @@ -149,22 +147,12 @@ impl LLVMModule { } impl LLVMType { - pub fn from_ref(ptr: LLVMTypeRef) -> Self { - LLVMType(ptr) - } - method_raw_ptr!(LLVMTypeRef); - pub fn get_ptr(&self, address_space: usize) -> Self { unsafe { LLVMType(LLVMPointerType(self.0.clone(), address_space as c_uint)) } } } impl LLVMValue { - pub fn from_ref(ptr: LLVMValueRef) -> Self { - LLVMValue(ptr) - } - method_raw_ptr!(LLVMValueRef); - pub fn set_name(&self, name: &str) { unsafe { LLVMSetValueName(self.0.clone(), raw_string(name)) } } @@ -175,10 +163,6 @@ impl LLVMValue { } impl LLVMFunction { - method_raw_ptr!(LLVMValueRef); - pub fn from_ref(ptr: LLVMValueRef) -> Self { - unsafe { LLVMFunction(ptr) } - } pub fn into_value(self) -> LLVMValue { LLVMValue::from_ref(self.0) } @@ -220,7 +204,6 @@ impl LLVMBuilder { pub fn in_ctx(ctx: &LLVMContext) -> Self { unsafe { LLVMBuilder(LLVMCreateBuilderInContext(ctx.raw_ptr())) } } - method_raw_ptr!(LLVMBuilderRef); pub fn set_position(&self, block: &LLVMBasicBlock, instr: &LLVMValue) { unsafe { LLVMPositionBuilder(self.raw_ptr(), block.raw_ptr(), instr.raw_ptr()) } @@ -241,31 +224,25 @@ impl LLVMBuilder { 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 { - LLVMValue::from_ref(LLVMBuildCall(self.raw_ptr(), - fun.raw_ptr(), - _args.as_mut_ptr(), - args.len() as c_uint, - raw_string(name))) + let ret = LLVMBuildCall(self.raw_ptr(), + fun.raw_ptr(), + _args.as_mut_ptr(), + args.len() as c_uint, + raw_string(name)); + LLVMValue::from_ref(ret) } } pub fn struct_field(&self, ptr: &LLVMValue, idx: u32, name: &str) -> LLVMValue { unsafe { - LLVMValue::from_ref(LLVMBuildStructGEP(self.raw_ptr(), - ptr.raw_ptr(), - idx, - raw_string(name))) + let ret = LLVMBuildStructGEP(self.raw_ptr(), ptr.raw_ptr(), idx, raw_string(name)); + LLVMValue::from_ref(ret) } } } impl LLVMBasicBlock { - pub fn from_ref(ptr: LLVMBasicBlockRef) -> Self { - LLVMBasicBlock(ptr) - } - method_raw_ptr!(LLVMBasicBlockRef); - pub fn get_parent(&self) -> LLVMFunction { unsafe { LLVMFunction::from_ref(LLVMGetBasicBlockParent(self.raw_ptr())) } } @@ -297,184 +274,9 @@ impl Drop for LLVMBuilder { } } -#[derive(Debug, Clone)] -pub struct LLVMCodegen { - pub module: LLVMModule, - pub builder: LLVMBuilder, - pub context: LLVMContext, - unique: usize, -} - - -type LLVMOperateBuild = unsafe extern "C" fn(LLVMBuilderRef, +pub type LLVMOperateBuild = unsafe extern "C" fn(LLVMBuilderRef, LLVMValueRef, LLVMValueRef, *const ::libc::c_char) -> LLVMValueRef; -pub fn get_llvm_op(op: BinOp, operand_ty: &Type) -> LLVMOperateBuild { - use self::BinOp::*; - use self::Type::*; - if let &Con(ref ty_name) = operand_ty { - let name_ref = ty_name.as_str(); - match (op, name_ref) { - (Add, "Int") => LLVMBuildAdd, - (Add, "Float") => LLVMBuildFAdd, - (Sub, "Int") => LLVMBuildSub, - (Sub, "Float") => LLVMBuildFSub, - (Mul, "Int") => LLVMBuildMul, - (Mul, "Float") => LLVMBuildFMul, - (Div, _) => LLVMBuildFDiv, // TODO: I dont know exactly which builder - (Rem, _) => LLVMBuildURem, // should I use for these two - _ => unimplemented!(), - } - } else { - unreachable!() - } -} - -pub fn is_primitive_type(t: &Type) -> bool { - if let &Type::Con(ref n) = t { - match n.as_str() { - "Int" | "Float" | "Char" => true, - _ => false, - } - } else { - false - } -} - -pub unsafe fn raw_string(s: &str) -> *mut c_char { - CString::new(s).unwrap().into_raw() -} - -impl LLVMCodegen { - pub fn new(name: &str) -> LLVMCodegen { - unsafe { - let ctx = LLVMContext::new(); - let modu = LLVMModule::in_ctx(name, &ctx); - let builder = LLVMBuilder::in_ctx(&ctx); - LLVMCodegen { - module: modu, - context: ctx, - builder: builder, - unique: 0, - } - } - } - - - pub fn new_symbol(&mut self) -> Result { - let f = String::new() + 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(); - self.unique = self.unique + 1; - f - } - - fn get_closure_type(&self) -> LLVMType { - unsafe { - - let ptr = self.context.get_int8_type().get_ptr(0); - let mem = vec![self.context.get_int16_type(), ptr]; - self.context.get_struct_type(&mem, false) - } - } - - pub fn get_llvm_type_or_ptr(&self, ty: &Type) -> LLVMType { - let ret = self.get_llvm_type(ty); - if !is_primitive_type(ty) { - ret.get_ptr(0) - } else { - ret - } - } - - pub fn get_llvm_type(&self, ty: &Type) -> LLVMType { - use self::Type::*; - match ty { - &Con(ref n) => { - match n.as_str() { - - // Primary types - "Int" => self.context.get_int32_type(), - "Float" => self.context.get_double_type(), - "Char" => self.context.get_int8_type(), - - // User defined types - t => self.gen_user_type(t), - } - } - &Arr(box ref p, box ref ret) => { - // Type of parameters and returned value should be pointer if not primitive - let mut cls_type = self.get_closure_type().get_ptr(0); - let mut retty = self.get_llvm_type_or_ptr(ret); - let psty = 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); - LLVMContext::get_function_type(&retty, &llvm_psty, false) - } - &Void => self.context.get_void_type(), - &Prod(..) => { - let mut tys: Vec<_> = ty.prod_to_vec() - .iter() - .map(|t| self.get_llvm_type(t)) - .collect(); - self.context.get_struct_type(&tys, true) - } - &Comp(ref c, ref p) => unimplemented!(), // TODO: determine the type - - &Var(..) => panic!("Unmaterized type"), - } - } - - pub fn gen_lit(&mut self, lit: &Lit) -> LLVMValue { - use self::Lit::*; - match lit { - &Float(f) => self.context.get_double_const(f), - &Int(i) => self.context.get_int32_const(i), - &Bool(true) => self.context.get_int1_const(1), - &Bool(false) => self.context.get_int1_const(0), - // TODO: String represent - &Str(ref s) => unimplemented!(), - } - } - - pub fn gen_user_type(&self, tyname: &str) -> LLVMType { - // TODO: make a user defined type definition - unimplemented!() - } - - pub unsafe fn create_entry_block_alloca(&self, - fun: &LLVMFunction, - var_name: &str, - ty: &Type) - -> LLVMValue { - let builder = LLVMBuilder::in_ctx(&self.context); - let block = fun.get_entry_basic_block(); - let fi = block.get_first_instr(); - let llvm_ty = self.get_llvm_type(ty); - builder.set_position(&block, &fi); - builder.alloca(&llvm_ty, var_name) - } - - pub fn bin_operator(&mut self, - op: BinOp, - lhs: LLVMValue, - rhs: LLVMValue, - operand_ty: &Type) - -> LLVMValue { - let fun = get_llvm_op(op, operand_ty); - unsafe { - LLVMValue::from_ref(fun(self.builder.raw_ptr(), - lhs.raw_ptr(), - rhs.raw_ptr(), - self.new_symbol().unwrap().into_raw())) - } - } -} diff --git a/src/core/convert.rs b/src/core/convert.rs index 66b6cc3..2945eb9 100644 --- a/src/core/convert.rs +++ b/src/core/convert.rs @@ -18,31 +18,28 @@ use core::term::*; pub struct K { count: usize, env: HashMap, - global: HashMap>, - cur_name: String, + global: HashMap>, + types: HashMap>, + current: String, } impl K { /// Do transformation on a syntax module, /// generate core term representation - pub fn go(module: I) -> HashMap> + pub fn go(module: I) -> (HashMap>, HashMap>) where I: IntoIterator> { - let mut runner = K { - count: 0, - env: HashMap::new(), - global: HashMap::new(), - cur_name: "".to_string(), - }; + let mut runner = K::default(); { let b = &mut runner; for def in module.into_iter() { - b.convert_fun_def(*def); + b.convert_def(*def); } } - runner.global + let K { global, types, .. } = runner; + (global, types) } /// Get a unique id, then increase the counter @@ -58,19 +55,18 @@ impl K { /// Generate a name for closure fn make_cls_name(&mut self, bound: &str) -> String { - self.cur_name.clone() + "$closure$" + bound + self.unique().to_string().as_str() + self.current.clone() + "$closure$" + bound + self.unique().to_string().as_str() } /// Convert a global definition to term - fn convert_fun_def(&mut self, def: Def) { + fn convert_def(&mut self, def: Def) { let Def { ident, node, .. } = def; match node { - Item::Form(form) => { - let _form = *form; - let Form { node, tag } = _form; + Item::Form(box form) => { + let Form { node, tag } = form; let ty = tag.ty; - self.cur_name = ident; - let def_name = self.cur_name.clone(); + self.current = ident; + let def_name = self.current.clone(); match node { Expr::Abs(lambda) => { @@ -82,7 +78,14 @@ impl K { _ => unreachable!(), } } - _ => {} + Item::Alg(ps, vs) => { + let d = box TypeDef::new(ident.clone(), ps, TypeKind::Algebra(vs)); + self.types.insert(ident, d); + } + Item::Alias(ps, t) => { + let d = box TypeDef::new(ident.clone(), ps, TypeKind::Alias(t)); + self.types.insert(ident, d); + } } } @@ -91,10 +94,10 @@ impl K { name: String, ty: Scheme, params: Vec, - freevars: Vec, + free: Vec, body: TaggedTerm) -> (&'b str, Vec<&'b str>) { - let fun = Definition::new(name.clone(), ty, params, freevars, body); + let fun = FunDef::new(name.clone(), ty, params, free, body); let ent = self.global.entry(name).or_insert(P(fun)); (&(*ent).name(), (*ent) diff --git a/src/core/term.rs b/src/core/term.rs index 7948c4a..5812951 100644 --- a/src/core/term.rs +++ b/src/core/term.rs @@ -16,23 +16,41 @@ type Node = Box; #[derive(Clone, PartialEq, Debug)] -pub struct Definition { +pub struct TypeDef { + name: Name, + params: Vec, + body: TypeKind +} + +#[derive(Clone, PartialEq, Debug)] +pub enum TypeKind { + Alias(P), + Algebra(Vec) +} + +impl TypeDef { + pub fn new(name: String, params: Vec, body: TypeKind) -> Self { + TypeDef { name, params, body } + } +} + +#[derive(Clone, PartialEq, Debug)] +pub struct FunDef { name: Name, params: Vec, freevars: Vec, body: Node, ty: Scheme, -// inst: Option>, } -impl Definition { +impl FunDef { pub fn new(name: String, ty: Scheme, params: Vec, freevars: Vec, body: TaggedTerm) - -> Definition { - Definition { + -> FunDef { + FunDef { name: name, params: params, freevars: freevars, diff --git a/src/main.rs b/src/main.rs index ff3d257..13f6efd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -47,7 +47,7 @@ fn repl() { println!("Typed AST:"); println!("{:?}", res); println!("Core term:"); - let top = K::go(res); + let (top, tys) = K::go(res); println!("{:?}", top); println!("LLVM IR:"); for def in top.values() { @@ -63,9 +63,5 @@ fn repl() { } fn main() { - // println!("{:?}", type_term(Span::new("(a) * ASDBCa * Fuck * Shit * c"))); - // println!("{:?}", type_factor(Span::new("shit"))); - // println!("{:?}", type_factor(Span::new("Fuck"))); - // println!("{:?}", type_expr(Span::new("a"))); repl(); } \ No newline at end of file diff --git a/src/syntax/form.rs b/src/syntax/form.rs index 5040f90..442a6f0 100644 --- a/src/syntax/form.rs +++ b/src/syntax/form.rs @@ -89,8 +89,8 @@ impl Def { #[derive(Clone, PartialEq, Debug)] pub enum Item { Form(E), - Alias(P), - Alg(Vec), + Alias(Vec, P), + Alg(Vec, Vec), }