diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..8750962 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,4 @@ +reorder_modules = true +imports_layout = "Vertical" +imports_granularity = "One" + diff --git a/src/builtins.rs b/src/builtins.rs index a09f45f..7c073c9 100644 --- a/src/builtins.rs +++ b/src/builtins.rs @@ -1,21 +1,59 @@ -use crate::types::{Type, TypeVariable, Kind}; -use crate::interner::intern; -use crate::renamer::{name, Name}; -use crate::renamer::typ::*; +use crate::{ + renamer::{ + name, + typ::*, + Name, + }, + types::{ + Kind, + Type, + TypeVariable, + }, +}; ///Returns an array of all the compiler primitves which exist (not including numeric primitives atm) pub fn builtins() -> Vec<(&'static str, Type)> { - let var = Type::Generic(TypeVariable { id: intern("a"), kind: Kind::Star, age: 0 } ); - let var2 = Type::Generic(TypeVariable { id: intern("b"), kind: Kind::Star, age: 0 } ); - vec![("error", function_type_(list_type(char_type()), var.clone())), - ("seq", function_type_(var.clone(), function_type_(var2.clone(), var2.clone()))), - ("readFile", function_type_(list_type(char_type()), io(list_type(char_type())))), - ("io_bind", function_type_(io(var.clone()), - function_type_(function_type_(var.clone(), io(var2.clone())), - io(var2.clone())))), - ("io_return", function_type_(var.clone(), io(var.clone()))), - ("putStrLn", function_type_(list_type(char_type()), io(unit()))), - ("#compare_tags", function_type_(var.clone(), function_type_(var.clone(), Type::new_op(name("Ordering"), Vec::new())))), + let var = Type::Generic(TypeVariable { + id: "a".into(), + kind: Kind::Star, + age: 0, + }); + let var2 = Type::Generic(TypeVariable { + id: "b".into(), + kind: Kind::Star, + age: 0, + }); + vec![ + ("error", function_type_(list_type(char_type()), var.clone())), + ( + "seq", + function_type_(var.clone(), function_type_(var2.clone(), var2.clone())), + ), + ( + "readFile", + function_type_(list_type(char_type()), io(list_type(char_type()))), + ), + ( + "io_bind", + function_type_( + io(var.clone()), + function_type_( + function_type_(var.clone(), io(var2.clone())), + io(var2.clone()), + ), + ), + ), + ("io_return", function_type_(var.clone(), io(var.clone()))), + ( + "putStrLn", + function_type_(list_type(char_type()), io(unit())), + ), + ( + "#compare_tags", + function_type_( + var.clone(), + function_type_(var.clone(), Type::new_op(name("Ordering"), vec![])), + ), + ), ] } - diff --git a/src/compiler.rs b/src/compiler.rs index 9ad03e2..a0dafef 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -1,16 +1,37 @@ -use crate::interner::*; -use crate::core::*; -use crate::core::Expr::*; -use crate::types::{qualified, extract_applied_type}; -use crate::typecheck::{Types, DataTypes, TypeEnvironment, find_specialized_instances}; -use crate::scoped_map::ScopedMap; -use std::borrow::ToOwned; - -use crate::core::translate::{translate_module, translate_modules}; -use crate::lambda_lift::do_lambda_lift; -use crate::renamer::rename_module; -use crate::renamer::typ::*; -use crate::builtins::builtins; +use { + crate::{ + core::{ + Expr::*, + *, + }, + interner::*, + scoped_map::ScopedMap, + typecheck::{ + find_specialized_instances, + DataTypes, + TypeEnvironment, + Types, + }, + types::{ + extract_applied_type, + qualified, + }, + }, + std::borrow::ToOwned, +}; + +use crate::{ + builtins::builtins, + core::translate::{ + translate_module, + translate_modules, + }, + lambda_lift::do_lambda_lift, + renamer::{ + rename_module, + typ::*, + }, +}; use self::Instruction::*; @@ -59,18 +80,18 @@ pub enum Instruction { PushBuiltin(usize), MkapDictionary, ConstructDictionary(usize), - PushDictionaryRange(usize, usize) + PushDictionaryRange(usize, usize), } -#[derive(Debug)] +#[derive(Debug, Clone)] enum Var<'a> { Stack(usize), Global(usize), Constructor(u16, u16), Class(&'a Type, &'a [Constraint], &'a TypeVariable), - Constraint(usize, &'a Type, &'a[Constraint]), + Constraint(usize, &'a Type, &'a [Constraint]), Builtin(usize), Primitive(usize, Instruction), - Newtype + Newtype, } static UNARY_PRIMITIVES: &'static [(&'static str, Instruction)] = &[ @@ -101,28 +122,12 @@ static BINARY_PRIMITIVES: &'static [(&'static str, Instruction)] = &[ ("primDoubleGE", DoubleGE), ]; - -impl <'a> Clone for Var<'a> { - fn clone(&self) -> Var<'a> { - match *self { - Var::Stack(x) => Var::Stack(x), - Var::Global(x) => Var::Global(x), - Var::Constructor(x, y) => Var::Constructor(x, y), - Var::Class(x, y, z) => Var::Class(x, y, z), - Var::Constraint(x, y, z) => Var::Constraint(x, y, z), - Var::Builtin(x) => Var::Builtin(x), - Var::Primitive(x, y) => Var::Primitive(x, y), - Var::Newtype => Var::Newtype - } - } -} - pub struct SuperCombinator { - pub arity : usize, + pub arity: usize, pub name: Name, pub assembly_id: usize, - pub instructions : Vec, - pub typ: Qualified, Name> + pub instructions: Vec, + pub typ: Qualified, Name>, } pub struct Assembly { pub super_combinators: Vec, @@ -130,7 +135,7 @@ pub struct Assembly { pub classes: Vec>, pub instances: Vec<(Vec>, Type)>, pub data_definitions: Vec>, - pub offset: usize + pub offset: usize, } trait Globals { @@ -144,24 +149,28 @@ impl Globals for Assembly { for class in self.classes.iter() { for decl in class.declarations.iter() { if decl.name == name { - return Some(Var::Class(&decl.typ.value, &*decl.typ.constraints, &class.variable)); + return Some( + Var::Class(&decl.typ.value, &decl.typ.constraints, &class.variable) + ); } } } - - let mut index = 0; - for sc in self.super_combinators.iter() { - if name == sc.name { - if sc.typ.constraints.len() > 0 { - return Some(Var::Constraint(self.offset + index, &sc.typ.value, &*sc.typ.constraints)); - } - else { - return Some(Var::Global(self.offset + index)); - } - } - index += 1; + + if let Some((index, sc)) = self + .super_combinators + .iter() + .enumerate() + .find(|(_, sc)| sc.name == name) + { + return Some(if !sc.typ.constraints.is_empty() { + Var::Constraint(self.offset + index, &sc.typ.value, &sc.typ.constraints) + } else { + Var::Global(self.offset + index) + }); } - self.find_constructor(name).map(|(tag, arity)| Var::Constructor(tag, arity)) + + self.find_constructor(name) + .map(|(tag, arity)| Var::Constructor(tag, arity)) } fn find_constructor(&self, name: Name) -> Option<(u16, u16)> { for data_def in self.data_definitions.iter() { @@ -176,7 +185,6 @@ impl Globals for Assembly { } fn find_global<'a>(module: &'a Module, offset: usize, name: Name) -> Option> { - for class in module.classes.iter() { for decl in class.declarations.iter() { if decl.name == name { @@ -186,34 +194,41 @@ fn find_global<'a>(module: &'a Module, offset: usize, name: Name) -> Option< } let mut global_index = 0; - module.bindings.iter() - .chain(module.instances.iter().flat_map(|instance| instance.bindings.iter())) + module + .bindings + .iter() + .chain( + module + .instances + .iter() + .flat_map(|instance| instance.bindings.iter()), + ) .chain(module.classes.iter().flat_map(|c| c.bindings.iter())) - .find(|bind| { global_index += 1; bind.name.name == name }) + .find(|bind| { + global_index += 1; + bind.name.name == name + }) .map(|bind| { global_index -= 1; let typ = bind.expression.get_type(); let constraints = &bind.name.typ.constraints; - if constraints.len() > 0 { - Var::Constraint(offset + global_index, typ, &**constraints) - } - else { + if !constraints.is_empty() { + Var::Constraint(offset + global_index, typ, constraints) + } else { Var::Global(offset + global_index) } }) .or_else(|| { - module.newtypes.iter() + module + .newtypes + .iter() .find(|newtype| newtype.constructor_name == name) .map(|_| Var::Newtype) }) - .or_else(|| { - find_constructor(module, name) - .map(|(tag, arity)| Var::Constructor(tag, arity)) - }) + .or_else(|| find_constructor(module, name).map(|(tag, arity)| Var::Constructor(tag, arity))) } fn find_constructor(module: &Module, name: Name) -> Option<(u16, u16)> { - for data_def in module.data_definitions.iter() { for ctor in data_def.constructors.iter() { if name == ctor.name { @@ -226,10 +241,8 @@ fn find_constructor(module: &Module, name: Name) -> Option<(u16, u16)> { impl Types for Module { fn find_type<'a>(&'a self, name: &Name) -> Option<&'a Qualified, Name>> { - for bind in self.bindings.iter() { - if bind.name.name == *name { - return Some(&bind.name.typ); - } + if let Some(bind) = self.bindings.iter().find(|bind| bind.name.name == *name) { + return Some(&bind.name.typ); } for class in self.classes.iter() { @@ -246,26 +259,43 @@ impl Types for Module { } } } - self.newtypes.iter() + self.newtypes + .iter() .find(|newtype| newtype.constructor_name == *name) .map(|newtype| &newtype.constructor_type) } - fn find_class<'a>(&'a self, name: Name) -> Option<(&'a [Constraint], &'a TypeVariable, &'a [TypeDeclaration])> { - self.classes.iter() + fn find_class<'a>( + &'a self, + name: Name, + ) -> Option<( + &'a [Constraint], + &'a TypeVariable, + &'a [TypeDeclaration], + )> { + self.classes + .iter() .find(|class| name == class.name) - .map(|class| (class.constraints.as_ref(), &class.variable, class.declarations.as_ref())) + .map(|class| { + ( + class.constraints.as_ref(), + &class.variable, + class.declarations.as_ref(), + ) + }) } - fn find_instance<'a>(&'a self, classname: Name, typ: &Type) -> Option<(&'a [Constraint], &'a Type)> { + fn find_instance<'a>( + &'a self, + classname: Name, + typ: &Type, + ) -> Option<(&'a [Constraint], &'a Type)> { for instance in self.instances.iter() { - let y = match extract_applied_type(&instance.typ) { - &Type::Constructor(ref x) => x, - _ => panic!() + let Type::Constructor(ref y) = extract_applied_type(&instance.typ) else { + panic!(); }; - let z = match extract_applied_type(typ) { - &Type::Constructor(ref x) => x, - _ => panic!() + let Type::Constructor(ref z) = extract_applied_type(typ) else { + panic!(); }; if classname == instance.classname && y.name == z.name { return Some((instance.constraints.as_ref(), &instance.typ)); @@ -283,7 +313,7 @@ impl Types for Assembly { return Some(&sc.typ); } } - + for class in self.classes.iter() { for decl in class.declarations.iter() { if *name == decl.name { @@ -299,35 +329,48 @@ impl Types for Assembly { } } } - return None; + None } - fn find_class<'a>(&'a self, name: Name) -> Option<(&'a [Constraint], &'a TypeVariable, &'a [TypeDeclaration])> { - self.classes.iter() + fn find_class<'a>( + &'a self, + name: Name, + ) -> Option<( + &'a [Constraint], + &'a TypeVariable, + &'a [TypeDeclaration], + )> { + self.classes + .iter() .find(|class| name == class.name) - .map(|class| (class.constraints.as_ref(), &class.variable, class.declarations.as_ref())) + .map(|class| { + ( + class.constraints.as_ref(), + &class.variable, + class.declarations.as_ref(), + ) + }) } - fn find_instance<'a>(&'a self, classname: Name, typ: &Type) -> Option<(&'a [Constraint], &'a Type)> { + fn find_instance<'a>( + &'a self, + classname: Name, + typ: &Type, + ) -> Option<(&'a [Constraint], &'a Type)> { for &(ref constraints, ref op) in self.instances.iter() { - match op { - &Type::Application(ref op, ref t) => { - let x = match extract_applied_type(&**op) { - &Type::Constructor(ref x) => x, - _ => panic!() - }; - let y = match extract_applied_type(&**t) { - &Type::Constructor(ref x) => x, - _ => panic!() - }; - let z = match extract_applied_type(typ) { - &Type::Constructor(ref x) => x, - _ => panic!() - }; - if classname.name == x.name && y.name == z.name { - return Some((constraints.as_ref(), &**t)); - } - } - _ => () + let &Type::Application(ref op, ref t) = op else { + continue; + }; + let Type::Constructor(ref x) = extract_applied_type(op) else { + panic!(); + }; + let Type::Constructor(ref y) = extract_applied_type(t) else { + panic!(); + }; + let Type::Constructor(ref z) = extract_applied_type(typ) else { + panic!(); + }; + if classname.name == x.name && y.name == z.name { + return Some((constraints.as_ref(), t)); } } None @@ -346,91 +389,107 @@ impl DataTypes for Assembly { } enum ArgList<'a> { - Cons(&'a Expr, &'a ArgList<'a>), - Nil + Cons(&'a Expr, &'a Self), + Nil, } pub struct Compiler<'a> { ///Hashmap containging class names mapped to the functions it contains pub instance_dictionaries: Vec<(Vec<(Name, Type)>, Vec)>, - pub stack_size : usize, + pub stack_size: usize, ///Array of all the assemblies which can be used to lookup functions in pub assemblies: Vec<&'a Assembly>, module: Option<&'a Module>, variables: ScopedMap>, - context: Vec> + context: Vec>, } - -impl <'a> Compiler<'a> { - pub fn new() -> Compiler<'a> { +impl<'a> Compiler<'a> { + pub fn new() -> Self { let mut variables = ScopedMap::new(); for (i, &(name, _)) in builtins().iter().enumerate() { - variables.insert(Name { name: intern(name), uid: 0}, Var::Builtin(i)); + variables.insert(name.into(), Var::Builtin(i)); } for &(name, instruction) in BINARY_PRIMITIVES.iter() { - variables.insert(Name { name: intern(name), uid: 0 }, Var::Primitive(2, instruction)); + variables.insert(name.into(), Var::Primitive(2, instruction)); } for &(name, instruction) in UNARY_PRIMITIVES.iter() { - variables.insert(Name { name: intern(name), uid: 0 }, Var::Primitive(1, instruction)); + variables.insert(name.into(), Var::Primitive(1, instruction)); } - Compiler { instance_dictionaries: Vec::new(), - stack_size : 0, assemblies: Vec::new(), + Self { + instance_dictionaries: vec![], + stack_size: 0, + assemblies: vec![], module: None, - variables: variables, - context: Vec::new() + variables, + context: vec![], } } - - pub fn compile_module(&mut self, module : &'a Module) -> Assembly { + + pub fn compile_module(&mut self, module: &'a Module) -> Assembly { self.module = Some(module); - let mut super_combinators = Vec::new(); - let mut instance_dictionaries = Vec::new(); - let mut data_definitions = Vec::new(); + let mut super_combinators = vec![]; + let mut instance_dictionaries = vec![]; + let mut data_definitions = vec![]; for def in module.data_definitions.iter() { - let mut constructors = Vec::new(); + let mut constructors = vec![]; for ctor in def.constructors.iter() { constructors.push(ctor.clone()); } data_definitions.push(def.clone()); } - let bindings = module.bindings.iter() + let bindings = module + .bindings + .iter() .chain(module.instances.iter().flat_map(|i| i.bindings.iter())) - .chain(module.classes.iter().flat_map(|class| class.bindings.iter())); + .chain( + module + .classes + .iter() + .flat_map(|class| class.bindings.iter()), + ); for bind in bindings { let sc = self.compile_binding(bind); super_combinators.push(sc); } - for &(_, ref dict) in self.instance_dictionaries.iter() { instance_dictionaries.push(dict.clone()); } self.module = None; Assembly { - super_combinators: super_combinators, - instance_dictionaries: instance_dictionaries, - offset: self.assemblies.iter().fold(0, |sum, assembly| sum + assembly.super_combinators.len()), + super_combinators, + instance_dictionaries, + offset: self + .assemblies + .iter() + .fold(0, |sum, assembly| sum + assembly.super_combinators.len()), classes: module.classes.clone(), - instances: module.instances.iter() - .map(|x| (x.constraints.clone(), Type::new_op(x.classname, vec![x.typ.clone()]))) - .collect() - , - data_definitions: data_definitions + instances: module + .instances + .iter() + .map(|x| { + ( + x.constraints.clone(), + Type::new_op(x.classname, vec![x.typ.clone()]), + ) + }) + .collect(), + data_definitions, } } - fn compile_binding(&mut self, bind : &Binding) -> SuperCombinator { + fn compile_binding(&mut self, bind: &Binding) -> SuperCombinator { debug!("Compiling binding {:?} :: {:?}", bind.name, bind.name.typ); - let dict_arg = if bind.name.typ.constraints.len() > 0 { 1 } else { 0 }; + let dict_arg: usize = (!bind.name.typ.constraints.is_empty()).into(); self.context = bind.name.typ.constraints.clone(); - let mut instructions = Vec::new(); + let mut instructions = vec![]; let mut arity = 0; self.scope(&mut |this| { if dict_arg == 1 { - this.new_stack_var(Name { name: intern("$dict"), uid: 0 }); + this.new_stack_var("$dict".into()); } debug!("{:?} {:?}\n {:?}", bind.name, dict_arg, bind.expression); arity = this.compile_lambda_binding(&bind.expression, &mut instructions) + dict_arg; @@ -440,21 +499,28 @@ impl <'a> Compiler<'a> { } instructions.push(Unwind); }); - debug!("{:?} :: {:?} compiled as:\n{:?}", bind.name, bind.name.typ, instructions); + debug!( + "{:?} :: {:?} compiled as:\n{:?}", + bind.name, bind.name.typ, instructions + ); SuperCombinator { assembly_id: self.assemblies.len(), typ: bind.name.typ.clone(), name: bind.name.name, - arity: arity, - instructions: instructions + arity, + instructions, } } - fn compile_lambda_binding(&mut self, expr: &Expr, instructions: &mut Vec) -> usize { + fn compile_lambda_binding( + &mut self, + expr: &Expr, + instructions: &mut Vec, + ) -> usize { match expr { &Lambda(ref ident, ref body) => { self.new_stack_var(ident.name.clone()); - 1 + self.compile_lambda_binding(&**body, instructions) + 1 + self.compile_lambda_binding(body, instructions) } _ => { self.compile(expr, instructions, true); @@ -462,90 +528,95 @@ impl <'a> Compiler<'a> { } } } - + ///Find a variable by walking through the stack followed by all globals - fn find(&self, identifier : Name) -> Option> { - self.variables.find(&identifier).map(|x| x.clone()) - .or_else(|| { - match self.module { + fn find(&self, identifier: Name) -> Option> { + self.variables + .find(&identifier) + .map(|x| x.clone()) + .or_else(|| match self.module { Some(ref module) => { let n = self.assemblies.len(); let offset = if n > 0 { let assembly = self.assemblies[n - 1]; assembly.offset + assembly.super_combinators.len() - } - else { + } else { 0 }; find_global(*module, offset, identifier) } - None => None - } - }) - .or_else(|| { - for assembly in self.assemblies.iter() { - match assembly.find_global(identifier) { - Some(var) => return Some(var), - None => () - } - } - None - }).or_else(|| { - Compiler::find_builtin_constructor(identifier.name) - .map(|(x, y)| Var::Constructor(x, y)) - }) + None => None, + }) + .or_else(|| { + self.assemblies + .iter() + .find_map(|assembly| assembly.find_global(identifier)) + }) + .or_else(|| { + Compiler::find_builtin_constructor(identifier.name) + .map(|(x, y)| Var::Constructor(x, y)) + }) } - fn find_constructor(&self, identifier : Name) -> Option<(u16, u16)> { - self.module.and_then(|module| find_constructor(module, identifier)) - .or_else(|| { - for assembly in self.assemblies.iter() { - match assembly.find_constructor(identifier) { - Some(var) => return Some(var), - None => () - } - } - None - }).or_else(|| { - Compiler::find_builtin_constructor(identifier.name) - }) + fn find_constructor(&self, identifier: Name) -> Option<(u16, u16)> { + self.module + .and_then(|module| find_constructor(module, identifier)) + .or_else(|| { + self.assemblies + .iter() + .find_map(|assembly| assembly.find_constructor(identifier)) + }) + .or_else(|| Compiler::find_builtin_constructor(identifier.name)) } fn find_builtin_constructor(identifier: InternedStr) -> Option<(u16, u16)> { let identifier = identifier.as_ref(); - if identifier.len() >= 2 && identifier.starts_with('(') - && identifier.ends_with(')') - && identifier.chars().skip(1).take(identifier.len() - 2).all(|c| c == ',') { - let num_args = - if identifier.len() == 2 { 0 }//unit - else { identifier.len() - 1 };//tuple + if identifier.len() >= 2 + && identifier.starts_with('(') + && identifier.ends_with(')') + && identifier + .chars() + .skip(1) + .take(identifier.len() - 2) + .all(|c| c == ',') + { + let num_args = if identifier.len() == 2 { + 0 + } + //unit + else { + identifier.len() - 1 + }; //tuple return Some((0, num_args as u16)); } match identifier { "[]" => Some((0, 0)), ":" => Some((1, 2)), - _ => None + _ => None, } } - fn find_class(&self, name: Name) -> Option<(&[Constraint], &TypeVariable, &[TypeDeclaration])> { - self.module.and_then(|m| m.find_class(name)) - .or_else(|| { + fn find_class( + &self, + name: Name, + ) -> Option<(&[Constraint], &TypeVariable, &[TypeDeclaration])> { + self.module.and_then(|m| m.find_class(name)).or_else(|| { for types in self.assemblies.iter() { match types.find_class(name) { Some(result) => return Some(result), - None => () + None => (), } } None }) } - fn new_stack_var(&mut self, identifier : Name) { - self.variables.insert(identifier, Var::Stack(self.stack_size)); + fn new_stack_var(&mut self, identifier: Name) { + self.variables + .insert(identifier, Var::Stack(self.stack_size)); self.stack_size += 1; } - fn new_var_at(&mut self, identifier : Name, index: usize) { + fn new_var_at(&mut self, identifier: Name, index: usize) { self.variables.insert(identifier, Var::Stack(index)); } @@ -558,57 +629,58 @@ impl <'a> Compiler<'a> { } ///Compile an expression by appending instructions to the instruction vector - fn compile(&mut self, expr : &Expr, instructions : &mut Vec, strict: bool) { + fn compile(&mut self, expr: &Expr, instructions: &mut Vec, strict: bool) { match expr { &Identifier(_) => { self.compile_apply(expr, ArgList::Nil, instructions, strict); } - &Literal(ref literal) => { - match &literal.value { - &Integral(i) => { - if literal.typ == int_type() { - instructions.push(PushInt(i)); - } - else if literal.typ == double_type() { - instructions.push(PushFloat(i as f64)); - } - else { - let from_integer = Identifier(Id { - name: Name { name: intern("fromInteger"), uid: 0 }, - typ: qualified(vec![], function_type_(int_type(), literal.typ.clone())), - }); - let number = Literal(LiteralData { typ: int_type(), value: Integral(i) }); - let apply = Apply(Box::new(from_integer), Box::new(number)); - self.compile(&apply, instructions, strict); - } + &Literal(ref literal) => match &literal.value { + &Integral(i) => { + if literal.typ == int_type() { + instructions.push(PushInt(i)); + } else if literal.typ == double_type() { + instructions.push(PushFloat(i as f64)); + } else { + let from_integer = Identifier(Id { + name: "fromInteger".into(), + typ: qualified(vec![], function_type_(int_type(), literal.typ.clone())), + }); + let number = Literal(LiteralData { + typ: int_type(), + value: Integral(i), + }); + let apply = Apply(from_integer.into(), number.into()); + self.compile(&apply, instructions, strict); } - &Fractional(f) => { - if literal.typ == double_type() { - instructions.push(PushFloat(f)); - } - else { - let from_rational = Identifier(Id { - name: Name { name: intern("fromRational"), uid: 0 }, - typ: qualified(vec![], function_type_(double_type(), literal.typ.clone())), - }); - let number = Literal(LiteralData { - typ: double_type(), - value: Fractional(f) - }); - let apply = Apply(Box::new(from_rational), Box::new(number)); - self.compile(&apply, instructions, strict); - } + } + &Fractional(f) => { + if literal.typ == double_type() { + instructions.push(PushFloat(f)); + } else { + let from_rational = Identifier(Id { + name: "fromRational".into(), + typ: qualified( + vec![], + function_type_(double_type(), literal.typ.clone()), + ), + }); + let number = Literal(LiteralData { + typ: double_type(), + value: Fractional(f), + }); + let apply = Apply(from_rational.into(), number.into()); + self.compile(&apply, instructions, strict); } - &String(ref s) => { - instructions.push(Pack(0, 0)); - for c in s.as_ref().chars().rev() { - instructions.push(PushChar(c)); - instructions.push(Pack(1, 2)); - } + } + &String(ref s) => { + instructions.push(Pack(0, 0)); + for c in s.as_ref().chars().rev() { + instructions.push(PushChar(c)); + instructions.push(Pack(1, 2)); } - &Char(c) => instructions.push(PushChar(c)) } - } + &Char(c) => instructions.push(PushChar(c)), + }, &Apply(..) => { self.compile_apply(expr, ArgList::Nil, instructions, strict); } @@ -622,41 +694,44 @@ impl <'a> Compiler<'a> { this.compile(&bind.expression, instructions, false); this.stack_size += 1; } - this.compile(&**body, instructions, strict); + this.compile(body, instructions, strict); instructions.push(Slide(bindings.len())); }); } &Case(ref body, ref alternatives) => { - self.compile(&**body, instructions, true); + self.compile(body, instructions, true); self.stack_size += 1; //Dummy variable for the case expression //Storage for all the jumps that should go to the end of the case expression - let mut end_branches = Vec::new(); + let mut end_branches = vec![]; for i in 0..alternatives.len() { let alt = &alternatives[i]; self.scope(&mut |this| { let pattern_start = instructions.len() as isize; - let mut branches = Vec::new(); + let mut branches = vec![]; let i = this.stack_size - 1; - let stack_increase = this.compile_pattern(&alt.pattern, &mut branches, instructions, i); + let stack_increase = + this.compile_pattern(&alt.pattern, &mut branches, instructions, i); let pattern_end = instructions.len() as isize; this.compile(&alt.expression, instructions, strict); instructions.push(Slide(stack_increase)); - instructions.push(Jump(0));//Should jump to the end + instructions.push(Jump(0)); //Should jump to the end end_branches.push(instructions.len() - 1); //Here the current branch ends and the next one starts //We need to set all the jump instructions to their actual location //and append Slide instructions to bring the stack back to normal if the match fails - for j in ((pattern_start+1)..(pattern_end+1)).rev() { + for j in ((pattern_start + 1)..(pattern_end + 1)).rev() { match instructions[j as usize] { Jump(_) => { instructions[j as usize] = Jump(instructions.len()); } - JumpFalse(_) => instructions[j as usize] = JumpFalse(instructions.len()), + JumpFalse(_) => { + instructions[j as usize] = JumpFalse(instructions.len()) + } Split(size) => instructions.push(Pop(size)), - _ => () + _ => (), } } }); @@ -670,16 +745,22 @@ impl <'a> Compiler<'a> { instructions.push(Eval); } } - &Lambda(_, _) => panic!("Error: Found non-lifted lambda when compiling expression") + &Lambda(_, _) => panic!("Error: Found non-lifted lambda when compiling expression"), } } - fn compile_apply(&mut self, expr: &Expr, args: ArgList, instructions: &mut Vec, strict: bool) { + fn compile_apply( + &mut self, + expr: &Expr, + args: ArgList, + instructions: &mut Vec, + strict: bool, + ) { //Unroll the applications until the function is found match *expr { Apply(ref func, ref arg) => { - return self.compile_apply(&**func, ArgList::Cons(&**arg, &args), instructions, strict) + return self.compile_apply(func, ArgList::Cons(arg, &args), instructions, strict) } - _ => () + _ => (), } //Tracks if the application is a regular function in which case we need to add Mkap instructions at the end let mut is_function = true; @@ -688,38 +769,66 @@ impl <'a> Compiler<'a> { Identifier(ref name) => { //When compiling a variable which has constraints a new instance dictionary //might be created which is returned here and added to the assembly - let mut is_primitive = false; - let var = self.find(name.name) + let var = self + .find(name.name) .unwrap_or_else(|| panic!("Error: Undefined variable {:?}", *name)); - match var { - Var::Primitive(..) => is_primitive = true, - _ => () - } + + let is_primitive = matches!(var, Var::Primitive(..)); arg_length = self.compile_args(&args, instructions, is_primitive); match var { - Var::Stack(index) => { instructions.push(Push(index)); } - Var::Global(index) => { instructions.push(PushGlobal(index)); } + Var::Stack(index) => { + instructions.push(Push(index)); + } + Var::Global(index) => { + instructions.push(PushGlobal(index)); + } Var::Constructor(tag, arity) => { instructions.push(Pack(tag, arity)); is_function = false; } - Var::Builtin(index) => { instructions.push(PushBuiltin(index)); } + Var::Builtin(index) => { + instructions.push(PushBuiltin(index)); + } Var::Class(typ, constraints, var) => { - debug!("Var::Class ({:?}, {:?}, {:?}) {:?}", typ, constraints, var, expr.get_type()); - self.compile_instance_variable(expr.get_type(), instructions, name.name, typ, constraints, var); + debug!( + "Var::Class ({:?}, {:?}, {:?}) {:?}", + typ, + constraints, + var, + expr.get_type() + ); + self.compile_instance_variable( + expr.get_type(), + instructions, + name.name, + typ, + constraints, + var, + ); } Var::Constraint(index, bind_type, constraints) => { - debug!("Var::Constraint {:?} ({:?}, {:?}, {:?})", name, index, bind_type, constraints); - self.compile_with_constraints(name.name, expr.get_type(), bind_type, constraints, instructions); + debug!( + "Var::Constraint {:?} ({:?}, {:?}, {:?})", + name, index, bind_type, constraints + ); + self.compile_with_constraints( + name.name, + expr.get_type(), + bind_type, + constraints, + instructions, + ); instructions.push(PushGlobal(index)); instructions.push(Mkap); } Var::Primitive(num_args, instruction) => { if num_args == arg_length { instructions.push(instruction); - } - else { - panic!("Expected {:?} arguments for {:?}, got {:?}", num_args, name, arg_length) + } else { + panic!( + "Expected {:?} arguments for {:?}, got {:?}", + num_args, name, arg_length + ) } is_function = false; } @@ -730,13 +839,13 @@ impl <'a> Compiler<'a> { } ArgList::Nil => { //translate into id application - let x = self.find(Name { name: intern("id"), uid: 0 }) + let x = self.find("id".into()) .expect("Compiler error: Prelude.id must be in scope for compilation of newtype"); match x { Var::Global(index) => { instructions.push(PushGlobal(index)); } - _ => panic!() + _ => panic!(), } } } @@ -760,7 +869,12 @@ impl <'a> Compiler<'a> { } } - fn compile_args(&mut self, args: &ArgList, instructions: &mut Vec, strict: bool) -> usize { + fn compile_args( + &mut self, + args: &ArgList, + instructions: &mut Vec, + strict: bool, + ) -> usize { match *args { ArgList::Cons(arg, rest) => { let i = self.compile_args(rest, instructions, strict); @@ -769,46 +883,74 @@ impl <'a> Compiler<'a> { self.stack_size += 1; i + 1 } - ArgList::Nil => 0 + ArgList::Nil => 0, } } ///Compile a function which is defined in a class - fn compile_instance_variable(&mut self, actual_type: &Type, instructions: &mut Vec, name: Name, function_type: &Type, constraints: &[Constraint], var: &TypeVariable) { - match try_find_instance_type(var, function_type, actual_type) { - Some(typename) => { - //We should be able to retrieve the instance directly - let mut b = "#".to_string(); - b.push_str(typename); - b.push_str(name.as_ref()); - let instance_fn_name = Name { name: intern(b.as_ref()), uid: name.uid }; - match self.find(instance_fn_name) { - Some(Var::Global(index)) => { - instructions.push(PushGlobal(index)); - } - Some(Var::Constraint(index, function_type, constraints)) => { - self.compile_with_constraints(instance_fn_name, actual_type, function_type, constraints, instructions); - instructions.push(PushGlobal(index)); - instructions.push(Mkap); - } - _ => panic!("Unregistered instance function {:?}", instance_fn_name) + fn compile_instance_variable( + &mut self, + actual_type: &Type, + instructions: &mut Vec, + name: Name, + function_type: &Type, + constraints: &[Constraint], + var: &TypeVariable, + ) { + if let Some(typename) = try_find_instance_type(var, function_type, actual_type) { + //We should be able to retrieve the instance directly + let mut b = "#".to_string(); + b.push_str(typename); + b.push_str(name.as_ref()); + let instance_fn_name = Name { + name: intern(b.as_ref()), + uid: name.uid, + }; + match self.find(instance_fn_name) { + Some(Var::Global(index)) => { + instructions.push(PushGlobal(index)); } + Some(Var::Constraint(index, function_type, constraints)) => { + self.compile_with_constraints( + instance_fn_name, + actual_type, + function_type, + constraints, + instructions, + ); + instructions.push(PushGlobal(index)); + instructions.push(Mkap); + } + _ => panic!("Unregistered instance function {:?}", instance_fn_name), } - None => { - self.compile_with_constraints(name, actual_type, function_type, constraints, instructions) - } + } else { + self.compile_with_constraints( + name, + actual_type, + function_type, + constraints, + instructions, + ) } } ///Compile the loading of a variable which has constraints and will thus need to load a dictionary with functions as well - fn compile_with_constraints(&mut self, name: Name, actual_type: &Type, function_type: &Type, constraints: &[Constraint], instructions: &mut Vec) { - match self.find(Name { name: intern("$dict"), uid: 0}) { + fn compile_with_constraints( + &mut self, + name: Name, + actual_type: &Type, + function_type: &Type, + constraints: &[Constraint], + instructions: &mut Vec, + ) { + match self.find("$dict".into()) { Some(Var::Stack(_)) => { //Push dictionary or member of dictionary match self.push_dictionary_member(constraints, name) { Some(index) => instructions.push(PushDictionaryMember(index)), None => { - let dictionary_key = find_specialized_instances(function_type, actual_type, constraints); + let dictionary_key = + find_specialized_instances(function_type, actual_type, constraints); self.push_dictionary(constraints, &*dictionary_key, instructions); } } @@ -816,24 +958,36 @@ impl <'a> Compiler<'a> { _ => { //get dictionary index //push dictionary - let dictionary_key = find_specialized_instances(function_type, actual_type, constraints); + let dictionary_key = + find_specialized_instances(function_type, actual_type, constraints); self.push_dictionary(constraints, &*dictionary_key, instructions); } } } - - fn push_dictionary(&mut self, context: &[Constraint], constraints: &[(Name, Type)], instructions: &mut Vec) { + + fn push_dictionary( + &mut self, + context: &[Constraint], + constraints: &[(Name, Type)], + instructions: &mut Vec, + ) { debug!("Push dictionary {:?} ==> {:?}", context, constraints); for &(ref class, ref typ) in constraints.iter() { self.fold_dictionary(*class, typ, instructions); instructions.push(ConstructDictionary(constraints.len())); } } - + //Writes instructions which pushes a dictionary for the type to the top of the stack - fn fold_dictionary(&mut self, class: Name, typ: &Type, instructions: &mut Vec) { + fn fold_dictionary( + &mut self, + class: Name, + typ: &Type, + instructions: &mut Vec, + ) { match *typ { - Type::Constructor(ref ctor) => {//Simple + Type::Constructor(ref ctor) => { + //Simple debug!("Simple for {:?}", ctor); //Push static dictionary to the top of the stack let index = self.find_dictionary_index(&[(class.clone(), typ.clone())]); @@ -843,8 +997,8 @@ impl <'a> Compiler<'a> { debug!("App for ({:?} {:?})", lhs, rhs); //For function in functions // Mkap function fold_dictionary(rhs) - self.fold_dictionary(class, &**lhs, instructions); - self.fold_dictionary(class, &**rhs, instructions); + self.fold_dictionary(class, lhs, instructions); + self.fold_dictionary(class, rhs, instructions); instructions.push(MkapDictionary); } Type::Variable(ref var) => { @@ -854,43 +1008,53 @@ impl <'a> Compiler<'a> { for constraint in self.context.iter() { if constraint.variables[0] == *var && constraint.class == class { has_constraint = true; - break + break; } let (_, _, decls) = self.find_class(constraint.class).unwrap(); index += decls.len(); } if has_constraint { //Found the variable in the constraints - let num_class_functions = self.find_class(class) + let num_class_functions = self + .find_class(class) .map(|(_, _, decls)| decls.len()) .unwrap(); - debug!("Use previous dict for {:?} at {:?}..{:?}", var, index, num_class_functions); + debug!( + "Use previous dict for {:?} at {:?}..{:?}", + var, index, num_class_functions + ); instructions.push(PushDictionaryRange(index, num_class_functions)); - } - else { + } else { debug!("No dict for {:?}", var); } } - _ => panic!("Did not expect generic") + _ => panic!("Did not expect generic"), } } ///Lookup which index in the instance dictionary that holds the function called 'name' - fn push_dictionary_member(&self, constraints: &[Constraint], name: Name) -> Option { - if constraints.len() == 0 { - panic!("Attempted to push dictionary member '{:?}' with no constraints", name) - } + fn push_dictionary_member( + &self, + constraints: &[Constraint], + name: Name, + ) -> Option { + assert!( + !constraints.is_empty(), + "Attempted to push dictionary member '{:?}' with no constraints", + name + ); let mut ii = 0; for c in constraints.iter() { - let result = self.walk_classes(c.class, &mut |declarations| -> Option { - for decl in declarations.iter() { - if decl.name == name { - return Some(ii) + let result = + self.walk_classes(c.class, &mut |declarations| -> Option { + for decl in declarations.iter() { + if decl.name == name { + return Some(ii); + } + ii += 1; } - ii += 1; - } - None - }); + None + }); if result.is_some() { return result; } @@ -900,11 +1064,17 @@ impl <'a> Compiler<'a> { ///Walks through the class and all of its super classes, calling 'f' on each of them ///Returning Some(..) from the function quits and returns that value - fn walk_classes(&self, class: Name, f: &mut dyn FnMut(&[TypeDeclaration]) -> Option) -> Option { - let (constraints, _, declarations) = self.find_class(class) + fn walk_classes( + &self, + class: Name, + f: &mut dyn FnMut(&[TypeDeclaration]) -> Option, + ) -> Option { + let (constraints, _, declarations) = self + .find_class(class) .expect("Compiler error: Expected class"); //Look through the functions in any super classes first - constraints.iter() + constraints + .iter() .filter_map(|constraint| self.walk_classes(constraint.class, f)) .next() .or_else(|| (*f)(declarations)) @@ -921,37 +1091,41 @@ impl <'a> Compiler<'a> { } } - if constraints.len() == 0 { - panic!("Error: Attempted to compile dictionary with no constraints at "); - } - let mut function_indexes = Vec::new(); + assert!( + !constraints.is_empty(), + "Error: Attempted to compile dictionary with no constraints at " + ); + let mut function_indexes = vec![]; self.add_class(constraints, &mut function_indexes); - self.instance_dictionaries.push((constraints.to_owned(), function_indexes)); + self.instance_dictionaries + .push((constraints.to_owned(), function_indexes)); dict_len } fn add_class(&self, constraints: &[(Name, Type)], function_indexes: &mut Vec) { - for &(ref class_name, ref typ) in constraints.iter() { self.walk_classes(*class_name, &mut |declarations| -> Option<()> { for decl in declarations.iter() { let x = match extract_applied_type(typ) { &Type::Constructor(ref x) => x, - _ => panic!("{:?}", typ) + _ => panic!("{:?}", typ), }; let mut b = "#".to_string(); b.push_str(x.name.as_ref()); b.push_str(decl.name.as_ref()); let f = intern(b.as_ref()); - let name = Name { name: f, uid: decl.name.uid }; + let name = Name { + name: f, + uid: decl.name.uid, + }; match self.find(name) { Some(Var::Global(index)) => { function_indexes.push(index as usize); } Some(Var::Constraint(index, _, _)) => { - function_indexes.push(index as usize);//TODO this is not really correct since this function requires a dictionary + function_indexes.push(index as usize); //TODO this is not really correct since this function requires a dictionary } - var => panic!("Did not find function {:?} {:?}", name, var) + var => panic!("Did not find function {:?} {:?}", name, var), } } None @@ -962,7 +1136,13 @@ impl <'a> Compiler<'a> { ///Compiles a pattern. ///An index to the Jump instruction which is taken when the match fails is stored in the branches vector ///These instructions will need to be updated later with the correct jump location. - fn compile_pattern(&mut self, pattern: &Pattern, branches: &mut Vec, instructions: &mut Vec, stack_size: usize) -> usize { + fn compile_pattern( + &mut self, + pattern: &Pattern, + branches: &mut Vec, + instructions: &mut Vec, + stack_size: usize, + ) -> usize { debug!("Pattern {:?} at {:?}", pattern, stack_size); match pattern { &Pattern::Constructor(ref name, ref patterns) => { @@ -973,7 +1153,7 @@ impl <'a> Compiler<'a> { branches.push(instructions.len()); instructions.push(Jump(0)); } - _ => panic!("Undefined constructor {:?}", *name) + _ => panic!("Undefined constructor {:?}", *name), } instructions.push(Split(patterns.len())); self.stack_size += patterns.len(); @@ -995,21 +1175,24 @@ impl <'a> Compiler<'a> { self.new_var_at(ident.name.clone(), stack_size); 0 } - &Pattern::WildCard => { - 0 - } + &Pattern::WildCard => 0, } } } ///Attempts to find the actual type of the for the variable which has a constraint -fn try_find_instance_type<'a>(class_var: &TypeVariable, class_type: &Type, actual_type: &'a Type) -> Option<&'a str> { +fn try_find_instance_type<'a>( + class_var: &TypeVariable, + class_type: &Type, + actual_type: &'a Type, +) -> Option<&'a str> { match (class_type, actual_type) { (&Type::Variable(ref var), _) if var == class_var => { //Found the class variable so return the name of the type - match extract_applied_type(actual_type) { - &Type::Constructor(ref op) => { Some(op.name.as_ref()) } - _ => None + if let Type::Constructor(ref op) = extract_applied_type(actual_type) { + Some(op.name.as_ref()) + } else { + None } } (&Type::Constructor(ref class_op), &Type::Constructor(ref actual_op)) => { @@ -1017,10 +1200,10 @@ fn try_find_instance_type<'a>(class_var: &TypeVariable, class_type: &Type, None } (&Type::Application(ref lhs1, ref rhs1), &Type::Application(ref lhs2, ref rhs2)) => { - try_find_instance_type(class_var, &**lhs1, &**lhs2) - .or_else(|| try_find_instance_type(class_var, &**rhs1, &**rhs2)) + try_find_instance_type(class_var, lhs1, lhs2) + .or_else(|| try_find_instance_type(class_var, rhs1, rhs2)) } - _ => None + _ => None, } } @@ -1030,16 +1213,22 @@ pub fn compile(contents: &str) -> Result { compile_with_type_env(&mut type_env, &[], contents) } #[allow(dead_code)] -pub fn compile_with_type_env<'a>(type_env: &mut TypeEnvironment<'a>, assemblies: &[&'a Assembly], contents: &str) -> Result { +pub fn compile_with_type_env<'a>( + type_env: &mut TypeEnvironment<'a>, + assemblies: &[&'a Assembly], + contents: &str, +) -> Result { use crate::parser::Parser; - let mut parser = Parser::new(contents.chars()); + let mut parser = Parser::new(contents.chars()); let module = parser.module().map_err(|e| format!("{:?}", e))?; let mut module = rename_module(module).map_err(|e| format!("{}", e))?; for assem in assemblies.iter() { type_env.add_types(*assem); } - type_env.typecheck_module(&mut module).map_err(|e| format!("{}", e))?; + type_env + .typecheck_module(&mut module) + .map_err(|e| format!("{}", e))?; let core_module = do_lambda_lift(translate_module(module)); let mut compiler = Compiler::new(); for assem in assemblies.iter() { @@ -1062,12 +1251,14 @@ pub fn compile_module(module: &str) -> Result, ::std::string::Stri compile_module_(modules) } -fn compile_module_(modules: Vec>) -> Result, ::std::string::String> { +fn compile_module_( + modules: Vec>, +) -> Result, ::std::string::String> { let core_modules: Vec>> = translate_modules(modules) .into_iter() .map(|module| do_lambda_lift(module)) .collect(); - let mut assemblies = Vec::new(); + let mut assemblies = vec![]; for module in core_modules.iter() { let x = { let mut compiler = Compiler::new(); @@ -1084,145 +1275,285 @@ fn compile_module_(modules: Vec>) -> Result Assembly { - super::compile(contents).unwrap() -} + use { + crate::{ + compiler::{ + compile_with_type_env, + Assembly, + Compiler, + Instruction::*, + }, + interner::*, + typecheck::TypeEnvironment, + }, + std::{ + fs::File, + io::Read, + path::Path, + }, + test::Bencher, + }; + + fn compile(contents: &str) -> Assembly { + super::compile(contents).unwrap() + } -#[test] -fn add() { - let file = "main = primIntAdd 1 2"; - let assembly = compile(file); + #[test] + fn add() { + let file = "main = primIntAdd 1 2"; + let assembly = compile(file); - assert_eq!(assembly.super_combinators[0].instructions, vec![PushInt(2), PushInt(1), Add, Update(0), Unwind]); -} + assert_eq!( + assembly.super_combinators[0].instructions, + vec![PushInt(2), PushInt(1), Add, Update(0), Unwind] + ); + } -#[test] -fn add_double() { - let file = -r"add x y = primDoubleAdd x y + #[test] + fn add_double() { + let file = r"add x y = primDoubleAdd x y main = add 2. 3."; - let assembly = compile(file); - - assert_eq!(assembly.super_combinators[0].instructions, vec![Push(1), Eval, Push(0), Eval, DoubleAdd, Update(0), Pop(2), Unwind]); - assert_eq!(assembly.super_combinators[1].instructions, vec![PushFloat(3.), PushFloat(2.), PushGlobal(0), Mkap, Mkap, Eval, Update(0), Unwind]); -} -#[test] -fn push_num_double() { - let file = -r"main = primDoubleAdd 2 3"; - let assembly = compile(file); - - assert_eq!(assembly.super_combinators[0].instructions, vec![PushFloat(3.), PushFloat(2.), DoubleAdd, Update(0), Unwind]); -} + let assembly = compile(file); + + assert_eq!( + assembly.super_combinators[0].instructions, + vec![ + Push(1), + Eval, + Push(0), + Eval, + DoubleAdd, + Update(0), + Pop(2), + Unwind + ] + ); + assert_eq!( + assembly.super_combinators[1].instructions, + vec![ + PushFloat(3.), + PushFloat(2.), + PushGlobal(0), + Mkap, + Mkap, + Eval, + Update(0), + Unwind + ] + ); + } + #[test] + fn push_num_double() { + let file = r"main = primDoubleAdd 2 3"; + let assembly = compile(file); + + assert_eq!( + assembly.super_combinators[0].instructions, + vec![PushFloat(3.), PushFloat(2.), DoubleAdd, Update(0), Unwind] + ); + } -#[test] -fn application() { - let file = -r"add x y = primIntAdd x y + #[test] + fn application() { + let file = r"add x y = primIntAdd x y main = add 2 3"; - let assembly = compile(file); - - assert_eq!(assembly.super_combinators[1].instructions, vec![PushInt(3), PushInt(2), PushGlobal(0), Mkap, Mkap, Eval, Update(0), Unwind]); -} - -#[test] -fn compile_constructor() { - let file = -r"main = primIntAdd 1 0 : []"; - let assembly = compile(file); - - assert_eq!(assembly.super_combinators[0].instructions, vec![Pack(0, 0), PushInt(0), PushInt(1), Add, Pack(1, 2), Update(0), Unwind]); -} + let assembly = compile(file); + + assert_eq!( + assembly.super_combinators[1].instructions, + vec![ + PushInt(3), + PushInt(2), + PushGlobal(0), + Mkap, + Mkap, + Eval, + Update(0), + Unwind + ] + ); + } -#[test] -fn compile_tuple() { - let file = -r"test x y = (primIntAdd 0 1, x, y)"; - let assembly = compile(file); + #[test] + fn compile_constructor() { + let file = r"main = primIntAdd 1 0 : []"; + let assembly = compile(file); + + assert_eq!( + assembly.super_combinators[0].instructions, + vec![ + Pack(0, 0), + PushInt(0), + PushInt(1), + Add, + Pack(1, 2), + Update(0), + Unwind + ] + ); + } - assert_eq!(assembly.super_combinators[0].instructions, vec![Push(1), Push(0), PushInt(1), PushInt(0), Add, Pack(0, 3), Update(0), Pop(2), Unwind]); -} + #[test] + fn compile_tuple() { + let file = r"test x y = (primIntAdd 0 1, x, y)"; + let assembly = compile(file); + + assert_eq!( + assembly.super_combinators[0].instructions, + vec![ + Push(1), + Push(0), + PushInt(1), + PushInt(0), + Add, + Pack(0, 3), + Update(0), + Pop(2), + Unwind + ] + ); + } -#[test] -fn compile_case() { - let file = -r"main = case [primIntAdd 1 0] of + #[test] + fn compile_case() { + let file = r"main = case [primIntAdd 1 0] of x:xs -> x [] -> 2"; - let assembly = compile(file); - - - assert_eq!(assembly.super_combinators[0].instructions, vec![Pack(0, 0), PushInt(0), PushInt(1), Add, Pack(1, 2), - Push(0), CaseJump(1), Jump(14), Split(2), Push(1), Eval, Slide(2), Jump(22), Pop(2), - Push(0), CaseJump(0), Jump(22), Split(0), PushInt(2), Slide(0), Jump(22), Pop(0), Slide(1), Eval, Update(0), Unwind]); -} + let assembly = compile(file); + + assert_eq!( + assembly.super_combinators[0].instructions, + vec![ + Pack(0, 0), + PushInt(0), + PushInt(1), + Add, + Pack(1, 2), + Push(0), + CaseJump(1), + Jump(14), + Split(2), + Push(1), + Eval, + Slide(2), + Jump(22), + Pop(2), + Push(0), + CaseJump(0), + Jump(22), + Split(0), + PushInt(2), + Slide(0), + Jump(22), + Pop(0), + Slide(1), + Eval, + Update(0), + Unwind + ] + ); + } -#[test] -fn compile_class_constraints() { - let file = -r"class Test a where + #[test] + fn compile_class_constraints() { + let file = r"class Test a where test :: a -> Int instance Test Int where test x = x main = test (primIntAdd 6 0)"; - let assembly = compile(file); - - let main = &assembly.super_combinators[0]; - assert_eq!(main.name.name, intern("main")); - assert_eq!(main.instructions, vec![PushInt(0), PushInt(6), Add, PushGlobal(1), Mkap, Eval, Update(0), Unwind]); -} + let assembly = compile(file); + + let main = &assembly.super_combinators[0]; + assert_eq!(main.name.name, intern("main")); + assert_eq!( + main.instructions, + vec![ + PushInt(0), + PushInt(6), + Add, + PushGlobal(1), + Mkap, + Eval, + Update(0), + Unwind + ] + ); + } -#[test] -fn compile_class_constraints_unknown() { - let file = -r"class Test a where + #[test] + fn compile_class_constraints_unknown() { + let file = r"class Test a where test :: a -> Int instance Test Int where test x = x main x = primIntAdd (test x) 6"; - let assembly = compile(file); - - let main = &assembly.super_combinators[0]; - assert_eq!(main.name.name, intern("main")); - assert_eq!(main.instructions, vec![PushInt(6), Push(1), PushDictionaryMember(0), Mkap, Eval, Add, Update(0), Pop(2), Unwind]); -} - -#[test] -fn compile_prelude() { - let prelude; - let mut type_env = TypeEnvironment::new(); - let mut contents = ::std::string::String::new(); - File::open("Prelude.hs").and_then(|mut f| f.read_to_string(&mut contents)).unwrap(); - prelude = compile_with_type_env(&mut type_env, &[], &contents).unwrap(); - - let assembly = compile_with_type_env(&mut type_env, &[&prelude], r"main = id (primIntAdd 2 0)").unwrap(); + let assembly = compile(file); + + let main = &assembly.super_combinators[0]; + assert_eq!(main.name.name, intern("main")); + assert_eq!( + main.instructions, + vec![ + PushInt(6), + Push(1), + PushDictionaryMember(0), + Mkap, + Eval, + Add, + Update(0), + Pop(2), + Unwind + ] + ); + } - let sc = &assembly.super_combinators[0]; - let id_index = prelude.super_combinators.iter().position(|sc| sc.name.name == intern("id")).unwrap(); - assert_eq!(sc.instructions, vec![PushInt(0), PushInt(2), Add, PushGlobal(id_index), Mkap, Eval, Update(0), Unwind]); -} + #[test] + fn compile_prelude() { + let prelude; + let mut type_env = TypeEnvironment::new(); + let mut contents = ::std::string::String::new(); + File::open("Prelude.hs") + .and_then(|mut f| f.read_to_string(&mut contents)) + .unwrap(); + prelude = compile_with_type_env(&mut type_env, &[], &contents).unwrap(); + + let assembly = + compile_with_type_env(&mut type_env, &[&prelude], r"main = id (primIntAdd 2 0)") + .unwrap(); + + let sc = &assembly.super_combinators[0]; + let id_index = prelude + .super_combinators + .iter() + .position(|sc| sc.name.name == intern("id")) + .unwrap(); + assert_eq!( + sc.instructions, + vec![ + PushInt(0), + PushInt(2), + Add, + PushGlobal(id_index), + Mkap, + Eval, + Update(0), + Unwind + ] + ); + } -#[test] -fn generics_do_not_propagate() { - //Test that the type of 'i' does not get overwritten by the use inside the let binding - //after typechecking the let binding, retrieving the type for 'i' the second time should - //not make the typechecker instantiate a new variable but keep using the original one - //This is something the typechecker should notice but for now the compiler will have to do it - compile( -r" + #[test] + fn generics_do_not_propagate() { + //Test that the type of 'i' does not get overwritten by the use inside the let binding + //after typechecking the let binding, retrieving the type for 'i' the second time should + //not make the typechecker instantiate a new variable but keep using the original one + //This is something the typechecker should notice but for now the compiler will have to do it + compile( + r" class Num a where fromInteger :: Int -> a instance Num Int where @@ -1238,48 +1569,57 @@ showInt i = let i2 = i `rem` 10 in showInt (i `rem` 7) -"); -} +", + ); + } -#[test] -fn binding_pattern() { - compile(r" + #[test] + fn binding_pattern() { + compile( + r" test f (x:xs) = f x : test f xs test _ [] = [] -"); -} +", + ); + } -#[test] -fn newtype() { - //Test that the newtype constructor is newer constucted - let file = -r" + #[test] + fn newtype() { + //Test that the newtype constructor is newer constucted + let file = r" newtype Test a = Test [a] test = Test [1::Int]"; - let assembly = compile(file); + let assembly = compile(file); - let test = &assembly.super_combinators[0]; - assert_eq!(test.instructions, vec![Pack(0, 0), PushInt(1), Pack(1, 2), Update(0), Unwind]); -} + let test = &assembly.super_combinators[0]; + assert_eq!( + test.instructions, + vec![Pack(0, 0), PushInt(1), Pack(1, 2), Update(0), Unwind] + ); + } -#[bench] -fn bench_prelude(b: &mut Bencher) { - use crate::lambda_lift::do_lambda_lift; - use crate::core::translate::translate_module; - use crate::renamer::tests::rename_module; - use crate::parser::Parser; + #[bench] + fn bench_prelude(b: &mut Bencher) { + use crate::{ + core::translate::translate_module, + lambda_lift::do_lambda_lift, + parser::Parser, + renamer::tests::rename_module, + }; - let path = &Path::new("Prelude.hs"); - let mut contents = ::std::string::String::new(); - File::open(path).and_then(|mut f| f.read_to_string(&mut contents)).unwrap(); - let mut parser = Parser::new(contents.chars()); - let mut module = rename_module(parser.module().unwrap()); - let mut type_env = TypeEnvironment::new(); - type_env.typecheck_module_(&mut module); - let core_module = do_lambda_lift(translate_module(module)); - b.iter(|| { - let mut compiler = Compiler::new(); - compiler.compile_module(&core_module) - }); -} + let path = &Path::new("Prelude.hs"); + let mut contents = ::std::string::String::new(); + File::open(path) + .and_then(|mut f| f.read_to_string(&mut contents)) + .unwrap(); + let mut parser = Parser::new(contents.chars()); + let mut module = rename_module(parser.module().unwrap()); + let mut type_env = TypeEnvironment::new(); + type_env.typecheck_module_(&mut module); + let core_module = do_lambda_lift(translate_module(module)); + b.iter(|| { + let mut compiler = Compiler::new(); + compiler.compile_module(&core_module) + }); + } } diff --git a/src/core.rs b/src/core.rs index 4657723..e61196b 100644 --- a/src/core.rs +++ b/src/core.rs @@ -1,19 +1,40 @@ -use std::fmt; -pub use crate::types::{Qualified, TypeVariable, Type, Constraint}; -pub use crate::types::Type::{Application, Variable}; -pub use crate::module::{Constructor, DataDefinition, TypeDeclaration, Newtype}; -pub use crate::module::LiteralData::{Integral, Fractional, String, Char}; -use crate::typecheck::TcType; -use crate::module; -use crate::interner::*; -pub use crate::renamer::Name; +pub use crate::{ + module::{ + DataDefinition, + LiteralData::{ + Char, + Fractional, + Integral, + String, + }, + Newtype, + TypeDeclaration, + }, + renamer::Name, + types::{ + Constraint, + Qualified, + Type::{ + self, + }, + TypeVariable, + }, +}; +use { + crate::{ + interner::*, + module, + typecheck::TcType, + }, + std::fmt, +}; pub struct Module { pub classes: Vec>, pub data_definitions: Vec>, pub newtypes: Vec>, pub instances: Vec>, - pub bindings: Vec> + pub bindings: Vec>, } impl Module { @@ -21,12 +42,12 @@ impl Module { Module { classes: vec![], data_definitions: vec![], - newtypes: Vec::new(), + newtypes: vec![], instances: vec![], bindings: vec![Binding { - name: Id::new(Name { name: intern("main"), uid: 0 }, expr.get_type().clone(), vec![]), - expression: expr - }] + name: Id::new("main".into(), expr.get_type().clone(), vec![]), + expression: expr, + }], } } } @@ -34,30 +55,30 @@ impl Module { #[derive(Clone, Debug, PartialEq)] pub struct Class { pub constraints: Vec>, - pub name : Name, - pub variable : TypeVariable, - pub declarations : Vec>, - pub bindings: Vec> + pub name: Name, + pub variable: TypeVariable, + pub declarations: Vec>, + pub bindings: Vec>, } #[derive(Clone, Debug)] pub struct Instance { - pub bindings : Vec>, - pub constraints : Vec>, - pub typ : TcType, - pub classname : Name + pub bindings: Vec>, + pub constraints: Vec>, + pub typ: TcType, + pub classname: Name, } #[derive(Clone, Debug, PartialEq)] pub struct Binding { pub name: Ident, - pub expression: Expr + pub expression: Expr, } #[derive(Clone, Debug, PartialEq)] pub struct Alternative { - pub pattern : Pattern, - pub expression : Expr + pub pattern: Pattern, + pub expression: Expr, } #[derive(Clone, Debug, PartialEq)] @@ -65,25 +86,23 @@ pub enum Pattern { Constructor(Ident, Vec), Identifier(Ident), Number(isize), - WildCard + WildCard, } #[derive(Clone, Debug, PartialEq)] pub struct LiteralData { pub typ: TcType, - pub value: Literal_ + pub value: module::LiteralData, } -pub type Literal_ = module::LiteralData; - #[derive(Clone, Debug, PartialEq)] pub enum Expr { Identifier(Ident), - Apply(Box>, Box>), + Apply(Box, Box), Literal(LiteralData), - Lambda(Ident, Box>), - Let(Vec>, Box>), - Case(Box>, Vec>) + Lambda(Ident, Box), + Let(Vec>, Box), + Case(Box, Vec>), } impl fmt::Display for LiteralData { @@ -92,36 +111,36 @@ impl fmt::Display for LiteralData { } } -impl fmt::Display for Binding { +impl fmt::Display for Binding { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{} = {}", self.name, self.expression) } } -impl fmt::Display for Expr { +impl fmt::Display for Expr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use self::Expr::*; write_core_expr!(*self, f,) } } -impl fmt::Display for Alternative { +impl fmt::Display for Alternative { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{} -> {}", self.pattern, self.expression) } } -impl fmt::Display for Pattern { +impl fmt::Display for Pattern { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - Pattern::Identifier(ref s) => write!(f, "{}", s), - Pattern::Number(ref i) => write!(f, "{}", i), - Pattern::Constructor(ref name, ref patterns) => { + Self::Identifier(ref s) => write!(f, "{}", s), + Self::Number(ref i) => write!(f, "{}", i), + Self::Constructor(ref name, ref patterns) => { write!(f, "({} ", name)?; for p in patterns.iter() { write!(f, " {}", p)?; } write!(f, ")") } - Pattern::WildCard => write!(f, "_") + Self::WildCard => write!(f, "_"), } } } @@ -132,32 +151,33 @@ pub trait Typed { fn get_type<'a>(&'a self) -> &'a Type; } -impl > Typed for Expr { +impl> Typed for Expr { type Id = Name; fn get_type<'a>(&'a self) -> &'a Type { match self { - &Expr::Identifier(ref i) => i.get_type(), - &Expr::Literal(ref lit) => &lit.typ, - &Expr::Apply(ref func, _) => { + &Self::Identifier(ref i) => i.get_type(), + &Self::Literal(ref lit) => &lit.typ, + &Self::Apply(ref func, _) => { match func.get_type() { - &Type::Application(_, ref a) => { &**a } - x => panic!("The function in Apply must be a type application, found {}", x) + &Type::Application(_, ref a) => a, + x => panic!( + "The function in Apply must be a type application, found {}", + x + ), } } - &Expr::Lambda(ref arg, _) => arg.get_type(), - &Expr::Let(_, ref body) => body.get_type(), - &Expr::Case(_, ref alts) => alts[0].expression.get_type() + &Self::Lambda(ref arg, _) => arg.get_type(), + &Self::Let(_, ref body) => body.get_type(), + &Self::Case(_, ref alts) => alts[0].expression.get_type(), } } } -impl Typed for Pattern { +impl Typed for Pattern { type Id = Ident::Id; fn get_type<'a>(&'a self) -> &'a Type { match *self { - Pattern::Identifier(ref name) => name.get_type(), - Pattern::Constructor(ref name, _) => name.get_type(), - Pattern::Number(_) => panic!(), - Pattern::WildCard => panic!() + Self::Identifier(ref name) | Self::Constructor(ref name, _) => name.get_type(), + Self::Number(_) | Self::WildCard => panic!(), } } } @@ -172,7 +192,7 @@ impl PartialEq for Name { #[derive(PartialEq, Eq, Hash, Clone, Debug)] pub struct Id { pub name: T, - pub typ: Qualified + pub typ: Qualified, } impl fmt::Display for Id { @@ -181,9 +201,12 @@ impl fmt::Display for Id { } } -impl Id { - pub fn new(name: T, typ: TcType, constraints: Vec>) -> Id { - Id { name: name, typ: module::qualified(constraints, typ) } +impl Id { + pub fn new(name: T, typ: TcType, constraints: Vec>) -> Self { + Self { + name, + typ: module::qualified(constraints, typ), + } } } @@ -193,29 +216,29 @@ impl AsRef for Id { } } -impl Typed for Id { +impl Typed for Id { type Id = Name; fn get_type(&self) -> &Type { &self.typ.value } } - pub mod ref_ { - use super::*; - use super::Expr::*; + use super::{ + Expr::*, + *, + }; ///Visitor for the types in the core language. ///visit_ is called at the every value in the tree, if it is overriden ///the appropriate walk_ methods need to be called to continue walking - pub trait Visitor : Sized { + pub trait Visitor: Sized { fn visit_expr(&mut self, expr: &Expr) { walk_expr(self, expr) } fn visit_alternative(&mut self, alt: &Alternative) { walk_alternative(self, alt) } - fn visit_pattern(&mut self, _pattern: &Pattern) { - } + fn visit_pattern(&mut self, _pattern: &Pattern) {} fn visit_binding(&mut self, binding: &Binding) { walk_binding(self, binding); } @@ -237,23 +260,23 @@ pub mod ref_ { pub fn walk_expr, Ident>(visitor: &mut V, expr: &Expr) { match expr { &Apply(ref func, ref arg) => { - visitor.visit_expr(&**func); - visitor.visit_expr(&**arg); + visitor.visit_expr(func); + visitor.visit_expr(arg); } - &Lambda(_, ref body) => visitor.visit_expr(&**body), + &Lambda(_, ref body) => visitor.visit_expr(body), &Let(ref binds, ref e) => { for b in binds.iter() { visitor.visit_binding(b); } - visitor.visit_expr(&**e); + visitor.visit_expr(e); } &Case(ref e, ref alts) => { - visitor.visit_expr(&**e); + visitor.visit_expr(e); for alt in alts.iter() { visitor.visit_alternative(alt); } } - _ => () + _ => (), } } @@ -263,9 +286,11 @@ pub mod ref_ { } pub mod mutable { - use super::*; - use super::Expr::*; - + use super::{ + Expr::*, + *, + }; + pub trait Visitor: Sized { fn visit_expr(&mut self, expr: &mut Expr) { walk_expr(self, expr) @@ -273,8 +298,7 @@ pub mod mutable { fn visit_alternative(&mut self, alt: &mut Alternative) { walk_alternative(self, alt) } - fn visit_pattern(&mut self, _pattern: &mut Pattern) { - } + fn visit_pattern(&mut self, _pattern: &mut Pattern) {} fn visit_binding(&mut self, binding: &mut Binding) { walk_binding(self, binding); } @@ -296,38 +320,43 @@ pub mod mutable { pub fn walk_expr>(visitor: &mut V, expr: &mut Expr) { match expr { &mut Apply(ref mut func, ref mut arg) => { - visitor.visit_expr(&mut **func); - visitor.visit_expr(&mut **arg); + visitor.visit_expr(func); + visitor.visit_expr(arg); } - &mut Lambda(_, ref mut body) => visitor.visit_expr(&mut **body), + &mut Lambda(_, ref mut body) => visitor.visit_expr(body), &mut Let(ref mut binds, ref mut e) => { for b in binds.iter_mut() { visitor.visit_binding(b); } - visitor.visit_expr(&mut **e); + visitor.visit_expr(e); } &mut Case(ref mut e, ref mut alts) => { - visitor.visit_expr(&mut **e); + visitor.visit_expr(e); for alt in alts.iter_mut() { visitor.visit_alternative(alt); } } - _ => () + _ => (), } } - pub fn walk_alternative>(visitor: &mut V, alt: &mut Alternative) { + pub fn walk_alternative>( + visitor: &mut V, + alt: &mut Alternative, + ) { visitor.visit_expr(&mut alt.expression); } } pub mod result { - use super::*; - use super::Expr::*; + use super::{ + Expr::*, + *, + }; ///A visitor which takes the structs as values and in turn expects a value in return ///so that it can rebuild the tree - pub trait Visitor : Sized { + pub trait Visitor: Sized { fn visit_expr(&mut self, expr: Expr) -> Expr { walk_expr(self, expr) } @@ -345,20 +374,27 @@ pub mod result { } } - pub fn walk_module, Ident>(visitor: &mut V, mut module: Module) -> Module { + pub fn walk_module, Ident>( + visitor: &mut V, + mut module: Module, + ) -> Module { let mut bindings = vec![]; ::std::mem::swap(&mut module.bindings, &mut bindings); - module.bindings = bindings.into_iter() + module.bindings = bindings + .into_iter() .map(|bind| visitor.visit_binding(bind)) .collect(); module } - pub fn walk_binding, Ident>(visitor: &mut V, binding: Binding) -> Binding { + pub fn walk_binding, Ident>( + visitor: &mut V, + binding: Binding, + ) -> Binding { let Binding { name, expression } = binding; Binding { - name: name, - expression: visitor.visit_expr(expression) + name, + expression: visitor.visit_expr(expression), } } @@ -367,600 +403,829 @@ pub mod result { Apply(func, arg) => { let f = visitor.visit_expr(*func); let a = visitor.visit_expr(*arg); - Apply(Box::new(f), Box::new(a)) + Apply(f.into(), a.into()) } - Lambda(x, body) => Lambda(x, Box::new(visitor.visit_expr(*body))), + Lambda(x, body) => Lambda(x, visitor.visit_expr(*body).into()), Let(binds, e) => { - let bs: Vec> = binds.into_iter().map(|b| { - visitor.visit_binding(b) - }).collect(); - Let(bs, Box::new(visitor.visit_expr(*e))) + let bs: Vec> = binds + .into_iter() + .map(|b| visitor.visit_binding(b)) + .collect(); + Let(bs, visitor.visit_expr(*e).into()) } Case(e, alts) => { let e2 = visitor.visit_expr(*e); - let alts2: Vec> = alts.into_iter() + let alts2: Vec> = alts + .into_iter() .map(|alt| visitor.visit_alternative(alt)) .collect(); - Case(Box::new(e2), alts2) + Case(e2.into(), alts2) } - expr => expr + expr => expr, } } - pub fn walk_alternative, Ident>(visitor: &mut V, alt: Alternative) -> Alternative { - let Alternative { pattern, expression } = alt; - Alternative { pattern: visitor.visit_pattern(pattern), expression: visitor.visit_expr(expression) } + pub fn walk_alternative, Ident>( + visitor: &mut V, + alt: Alternative, + ) -> Alternative { + let Alternative { + pattern, + expression, + } = alt; + Alternative { + pattern: visitor.visit_pattern(pattern), + expression: visitor.visit_expr(expression), + } } } ///The translate module takes the AST and translates it into the simpler core language. pub mod translate { - use crate::module; - use crate::core::*; - use crate::core::Expr::*; - use crate::typecheck::TcType; - use crate::renamer::NameSupply; - use crate::renamer::typ::*; - use crate::deriving::*; - use std::collections::HashMap; + use { + crate::{ + core::{ + Expr::*, + *, + }, + deriving::*, + module, + renamer::{ + typ::*, + NameSupply, + }, + typecheck::TcType, + }, + std::collections::HashMap, + }; struct Translator<'a> { name_supply: NameSupply, - functions_in_class: &'a mut (dyn FnMut(Name) -> (&'a TypeVariable, &'a [TypeDeclaration]) + 'a) + functions_in_class: + &'a mut (dyn FnMut(Name) -> (&'a TypeVariable, &'a [TypeDeclaration]) + 'a), } - + #[derive(Debug)] - struct Equation<'a>(&'a [(Id, Pattern>)], (&'a [Binding>], &'a module::Match)); + struct Equation<'a>( + &'a [(Id, Pattern>)], + (&'a [Binding>], &'a module::Match), + ); pub fn translate_expr(expr: module::TypedExpr) -> Expr> { - let mut translator = Translator { name_supply: NameSupply::new(), functions_in_class: &mut |_| panic!() }; + let mut translator = Translator { + name_supply: NameSupply::new(), + functions_in_class: &mut |_| panic!(), + }; translator.translate_expr(expr) } pub fn translate_modules(modules: Vec>) -> Vec>> { let mut map = HashMap::new(); for class in modules.iter().flat_map(|m| m.classes.iter()) { - map.insert(class.name.clone(), (class.variable.clone(), class.declarations.clone())); + map.insert( + class.name.clone(), + (class.variable.clone(), class.declarations.clone()), + ); } - let mut translator = Translator { - name_supply: NameSupply::new(), - functions_in_class: &mut |name| { - let &(ref var, ref decls) = map.get(&name).unwrap(); - (var, decls.as_ref()) - } - }; - modules.into_iter() + let mut translator = + Translator { + name_supply: NameSupply::new(), + functions_in_class: &mut |name| { + let &(ref var, ref decls) = map.get(&name).unwrap(); + (var, decls.as_ref()) + }, + }; + modules + .into_iter() .map(|module| translate_module_(&mut translator, module)) .collect() } pub fn translate_module(module: module::Module) -> Module> { - translate_modules(vec!(module)).pop().unwrap() + translate_modules(vec![module]).pop().unwrap() } - fn translate_module_<'a>(translator: &mut Translator<'a>, module: module::Module) -> Module> { - let module::Module { name : _name, - imports : _imports, + fn translate_module_<'a>( + translator: &mut Translator<'a>, + module: module::Module, + ) -> Module> { + let module::Module { + name: _name, + imports: _imports, bindings, - type_declarations : _type_declarations, + type_declarations: _type_declarations, newtypes, classes, instances, data_definitions, - fixity_declarations : _fixity_declarations + fixity_declarations: _fixity_declarations, } = module; - let mut new_instances: Vec>> = Vec::new(); + let mut new_instances: Vec>> = vec![]; - let classes2 : Vec> = classes.into_iter().map(|class| { - let module::Class { - constraints, - name, - variable, - declarations, - bindings - } = class; - Class { - constraints: constraints, - name: name, - variable: variable, - declarations: declarations, - bindings: translator.translate_bindings(bindings) - } - }).collect(); + let classes2: Vec> = classes + .into_iter() + .map(|class| { + let module::Class { + constraints, + name, + variable, + declarations, + bindings, + } = class; + Class { + constraints, + name, + variable, + declarations, + bindings: translator.translate_bindings(bindings), + } + }) + .collect(); for instance in instances.into_iter() { let module::Instance { classname, typ, constraints, - bindings + bindings, } = instance; - let bs: Vec>> = translator.translate_bindings(bindings).into_iter().collect(); + let bs: Vec>> = translator + .translate_bindings(bindings) + .into_iter() + .collect(); new_instances.push(Instance { - constraints: constraints, - typ: typ, - classname: classname, - bindings: bs + constraints, + typ, + classname, + bindings: bs, }); } - let bs: Vec>> = translator.translate_bindings(bindings).into_iter().collect(); + let bs: Vec>> = translator + .translate_bindings(bindings) + .into_iter() + .collect(); for data in data_definitions.iter() { generate_deriving(&mut new_instances, data); } for instance in new_instances.iter_mut() { let (class_var, class_decls) = (translator.functions_in_class)(instance.classname); let defaults = create_default_stubs(class_var, class_decls, instance); - let mut temp = Vec::new(); + let mut temp = vec![]; ::std::mem::swap(&mut temp, &mut instance.bindings); - let vec: Vec>> = temp.into_iter().chain(defaults.into_iter()).collect(); + let vec: Vec>> = + temp.into_iter().chain(defaults.into_iter()).collect(); instance.bindings = vec; } Module { classes: classes2, - data_definitions: data_definitions, - newtypes: newtypes, + data_definitions, + newtypes, bindings: bs, - instances: new_instances + instances: new_instances, } } ///Creates stub functions for each undeclared function in the instance - fn create_default_stubs(class_var: &TypeVariable, class_decls: &[TypeDeclaration], instance: &Instance>) -> Vec>> { - class_decls.iter() - .filter(|decl| instance.bindings.iter().find(|bind| bind.name.as_ref().ends_with(decl.name.as_ref())).is_none()) + fn create_default_stubs( + class_var: &TypeVariable, + class_decls: &[TypeDeclaration], + instance: &Instance>, + ) -> Vec>> { + class_decls + .iter() + .filter(|decl| { + instance + .bindings + .iter() + .find(|bind| bind.name.as_ref().ends_with(decl.name.as_ref())) + .is_none() + }) .map(|decl| { - debug!("Create default function for {} ({}) {}", instance.classname, instance.typ, decl.name); + debug!( + "Create default function for {} ({}) {}", + instance.classname, instance.typ, decl.name + ); //The stub functions will naturally have the same type as the function in the class but with the variable replaced //with the instance's type let mut typ = decl.typ.clone(); crate::typecheck::replace_var(&mut typ.value, class_var, &instance.typ); { - let context = ::std::mem::replace(&mut typ.constraints, Vec::new()); + let context = ::std::mem::replace(&mut typ.constraints, vec![]); //Remove all constraints which refer to the class's variable - let vec_context: Vec> = context.into_iter() + let vec_context: Vec> = context + .into_iter() .filter(|c| c.variables[0] != *class_var) .collect(); typ.constraints = vec_context; } - let Qualified { value: typ, constraints } = typ; - let default_name = module::encode_binding_identifier(instance.classname.name, decl.name.name); + let Qualified { + value: typ, + constraints, + } = typ; + let default_name = + module::encode_binding_identifier(instance.classname.name, decl.name.name); let typ_name = module::extract_applied_type(&instance.typ).ctor().name.name; let instance_fn_name = module::encode_binding_identifier(typ_name, decl.name.name); //Example stub for undeclared (/=) //(/=) = #Eq/= Binding { - name: Id::new(Name { name: instance_fn_name, uid: decl.name.uid }, typ.clone(), constraints.clone()), - expression: Identifier(Id::new(Name { name: default_name, uid: decl.name.uid }, typ, constraints)) + name: Id::new( + Name { + name: instance_fn_name, + uid: decl.name.uid, + }, + typ.clone(), + constraints.clone(), + ), + expression: Identifier(Id::new( + Name { + name: default_name, + uid: decl.name.uid, + }, + typ, + constraints, + )), } }) .collect() } -impl <'a> Translator<'a> { - fn translate_match(&mut self, matches: module::Match) -> Expr> { - match matches { - module::Match::Simple(e) => self.translate_expr(e), - module::Match::Guards(ref gs) => self.translate_guards(unmatched_guard(), &**gs) + impl<'a> Translator<'a> { + fn translate_match(&mut self, matches: module::Match) -> Expr> { + match matches { + module::Match::Simple(e) => self.translate_expr(e), + module::Match::Guards(ref gs) => self.translate_guards(unmatched_guard(), gs), + } } - } - pub fn translate_expr(&mut self, input_expr: module::TypedExpr) -> Expr> { - //Checks if the expression is lambda not bound by a let binding - //if it is then we wrap the lambda in a let binding - let is_lambda = match &input_expr.expr { - &module::Expr::Lambda(_, _) => true, - _ => false - }; - if is_lambda { - let module::TypedExpr { typ, expr, ..} = input_expr; - match expr { - module::Expr::Lambda(arg, body) => { - //TODO need to make unique names for the lambdas created here - let argname = match arg { + pub fn translate_expr(&mut self, input_expr: module::TypedExpr) -> Expr> { + //Checks if the expression is lambda not bound by a let binding + //if it is then we wrap the lambda in a let binding + let is_lambda = matches!(&input_expr.expr, &module::Expr::Lambda(_, _)); + if is_lambda { + let module::TypedExpr { typ, expr, .. } = input_expr; + match expr { + module::Expr::Lambda(arg, body) => { + //TODO need to make unique names for the lambdas created here + let argname = match arg { module::Pattern::Identifier(arg) => arg, module::Pattern::WildCard => Name { name: intern("_"), uid: usize::max_value() }, _ => panic!("Core translation of pattern matches in lambdas are not implemented") }; - let l = Lambda(Id::new(argname, typ.clone(), vec![]), Box::new(self.translate_expr_rest(*body))); - let id = Id::new(self.name_supply.from_str("#lambda"), typ.clone(), vec![]); - let bind = Binding { name: id.clone(), expression: l }; - Let(vec![bind], Box::new(Identifier(id))) + let l = Lambda( + Id::new(argname, typ.clone(), vec![]), + Box::new(self.translate_expr_rest(*body)), + ); + let id = Id::new(self.name_supply.from_str("#lambda"), typ.clone(), vec![]); + let bind = Binding { + name: id.clone(), + expression: l, + }; + Let(vec![bind], Box::new(Identifier(id))) + } + _ => panic!(), } - _ => panic!() + } else { + self.translate_expr_rest(input_expr) } } - else { - self.translate_expr_rest(input_expr) - } - } - fn translate_expr_rest(&mut self, input_expr: module::TypedExpr) -> Expr> { - let module::TypedExpr { typ, expr, ..} = input_expr; - match expr { - module::Expr::Identifier(s) => Identifier(Id::new(s, typ, vec![])), - module::Expr::Apply(func, arg) => Apply(Box::new(self.translate_expr(*func)), Box::new(self.translate_expr(*arg))), - module::Expr::OpApply(lhs, op, rhs) => { - let l = Box::new(self.translate_expr(*lhs)); - let r = Box::new(self.translate_expr(*rhs)); - let func_type = function_type_(l.get_type().clone(), - function_type_(r.get_type().clone(), - typ)); - Apply(Box::new(Apply(Box::new(Identifier(Id::new(op, func_type, vec![]))), l)), r) - } - module::Expr::Literal(l) => Literal(LiteralData { typ: typ, value: l }), - module::Expr::Lambda(arg, body) => { - match arg { - module::Pattern::Identifier(arg) => Lambda(Id::new(arg, typ, vec![]), Box::new(self.translate_expr_rest(*body))), - module::Pattern::WildCard => Lambda(Id::new(Name { name: intern("_"), uid: usize::max_value() }, typ, vec![]), Box::new(self.translate_expr_rest(*body))), - _ => panic!("Core translation of pattern matches in lambdas are not implemented") + fn translate_expr_rest(&mut self, input_expr: module::TypedExpr) -> Expr> { + let module::TypedExpr { typ, expr, .. } = input_expr; + match expr { + module::Expr::Identifier(s) => Identifier(Id::new(s, typ, vec![])), + module::Expr::Apply(func, arg) => Apply( + Box::new(self.translate_expr(*func)), + Box::new(self.translate_expr(*arg)), + ), + module::Expr::OpApply(lhs, op, rhs) => { + let l = Box::new(self.translate_expr(*lhs)); + let r = Box::new(self.translate_expr(*rhs)); + let func_type = function_type_( + l.get_type().clone(), + function_type_(r.get_type().clone(), typ), + ); + Apply( + Apply(Identifier(Id::new(op, func_type, vec![])).into(), l).into(), + r, + ) } - } - module::Expr::Let(bindings, body) => { - let bs = self.translate_bindings(bindings); - Let(bs, Box::new(self.translate_expr(*body))) - } - module::Expr::Case(expr, alts) => { - self.translate_case(*expr, alts) - } - module::Expr::IfElse(pred, if_true, if_false) => { - Case(Box::new(self.translate_expr(*pred)), vec![ - Alternative { pattern: bool_pattern("True"), expression: self.translate_expr(*if_true) }, - Alternative { pattern: bool_pattern("False"), expression: self.translate_expr(*if_false) } - ]) - } - module::Expr::Do(bindings, expr) => { - let mut result = self.translate_expr(*expr); - for bind in bindings.into_iter().rev() { - result = match bind { - module::DoBinding::DoExpr(e) => { - let core = self.translate_expr(e); - let x = self.do_bind2_id(core.get_type().clone(), result.get_type().clone()); - Apply(Box::new(Apply(Box::new(x), Box::new(core))), Box::new(result)) - } - module::DoBinding::DoBind(pattern, e) => { - let e2 = self.translate_expr(e); - self.do_bind_translate(pattern.node, e2, result) - } - module::DoBinding::DoLet(bs) => { - Let(self.translate_bindings(bs), Box::new(result)) + module::Expr::Literal(l) => Literal(LiteralData { typ, value: l }), + module::Expr::Lambda(arg, body) => { + match arg { + module::Pattern::Identifier(arg) => Lambda( + Id::new(arg, typ, vec![]), + self.translate_expr_rest(*body).into(), + ), + module::Pattern::WildCard => Lambda( + Id::new( + Name { + name: intern("_"), + uid: usize::max_value(), + }, + typ, + vec![], + ), + self.translate_expr_rest(*body).into(), + ), + _ => { + panic!("Core translation of pattern matches in lambdas are not implemented") } - }; + } + } + module::Expr::Let(bindings, body) => { + let bs = self.translate_bindings(bindings); + Let(bs, Box::new(self.translate_expr(*body))) } - result + module::Expr::Case(expr, alts) => self.translate_case(*expr, alts), + module::Expr::IfElse(pred, if_true, if_false) => Case( + Box::new(self.translate_expr(*pred)), + vec![ + Alternative { + pattern: bool_pattern("True"), + expression: self.translate_expr(*if_true), + }, + Alternative { + pattern: bool_pattern("False"), + expression: self.translate_expr(*if_false), + }, + ], + ), + module::Expr::Do(bindings, expr) => { + let mut result = self.translate_expr(*expr); + for bind in bindings.into_iter().rev() { + result = match bind { + module::DoBinding::DoExpr(e) => { + let core = self.translate_expr(e); + let x = self.do_bind2_id( + core.get_type().clone(), + result.get_type().clone(), + ); + Apply(Box::new(Apply(x.into(), core.into())), result.into()) + } + module::DoBinding::DoBind(pattern, e) => { + let e2 = self.translate_expr(e); + self.do_bind_translate(pattern.node, e2, result) + } + module::DoBinding::DoLet(bs) => { + Let(self.translate_bindings(bs), result.into()) + } + }; + } + result + } + module::Expr::TypeSig(expr, _) => self.translate_expr(*expr), + module::Expr::Paren(expr) => self.translate_expr(*expr), } - module::Expr::TypeSig(expr, _) => self.translate_expr(*expr), - module::Expr::Paren(expr) => self.translate_expr(*expr) } - } - ///Translates - ///do { expr; stmts } = expr >> do { stmts; } - fn do_bind2_id(&mut self, m_a: TcType, m_b: TcType) -> Expr> { - debug!("m_a {}", m_a); - let c = match *m_a.appl() { - Type::Variable(ref var) => vec![Constraint { class: Name { name: intern("Monad"), uid: 0 }, variables: vec![var.clone()] }], - _ => vec![] - }; - let typ = function_type_(m_a, function_type_(m_b.clone(), m_b)); - Identifier(Id::new(Name { name: intern(">>"), uid: 0}, typ, c)) - } - ///Translates - ///do {p <- e; stmts} = - /// let ok p = do {stmts} - /// ok _ = fail "..." - /// in e >>= ok - fn do_bind_translate(&mut self, pattern: module::Pattern, expr: Expr>, result: Expr>) -> Expr> { - - let m_a = expr.get_type().clone(); - let a = m_a.appr().clone(); - let m_b = result.get_type().clone(); - debug!("m_a {}", m_a); - let c = match *m_a.appl() { - Type::Variable(ref var) => vec![Constraint { class: Name { name: intern("Monad"), uid: 0 }, variables: vec![var.clone()] }], - _ => vec![] - }; - let arg2_type = function_type_(a.clone(), m_b.clone()); - let bind_typ = function_type_(m_a, function_type_(arg2_type.clone(), m_b.clone())); - let bind_ident = Identifier(Id::new(Name { name: intern(">>="), uid: 0}, bind_typ, c.clone())); - - //Create ok binding - let func_ident = Id::new( - self.name_supply.from_str("#ok"), - arg2_type.clone(), - c.clone() - );//TODO unique id - let var = Id::new(self.name_supply.from_str("p"), function_type_(a, m_b.clone()), c.clone());//Constraints for a - let fail_ident = Identifier(Id::new(Name { name: intern("fail"), uid: 0 }, function_type_(list_type(char_type()), m_b), c)); - let func = Lambda(var.clone(), Box::new(Case(Box::new(Identifier(var)), - vec![Alternative { pattern: self.translate_pattern(pattern), expression: result } - , Alternative { pattern: Pattern::WildCard, expression: Apply(Box::new(fail_ident), Box::new(string("Unmatched pattern in let"))) } ]))); - let bind = Binding { name: func_ident.clone(), expression: func }; - - Let(vec![bind], Box::new(apply(bind_ident, (vec![expr, Identifier(func_ident)]).into_iter()))) - } + ///Translates + ///do { expr; stmts } = expr >> do { stmts; } + fn do_bind2_id(&mut self, m_a: TcType, m_b: TcType) -> Expr> { + debug!("m_a {}", m_a); + let c = + match *m_a.appl() { + Type::Variable(ref var) => vec![Constraint { + class: "Monad".into(), + variables: vec![var.clone()], + }], + _ => vec![], + }; + let typ = function_type_(m_a, function_type_(m_b.clone(), m_b)); + Identifier(Id::new(">>".into(), typ, c)) + } + ///Translates + ///do {p <- e; stmts} = + /// let ok p = do {stmts} + /// ok _ = fail "..." + /// in e >>= ok + fn do_bind_translate( + &mut self, + pattern: module::Pattern, + expr: Expr>, + result: Expr>, + ) -> Expr> { + let m_a = expr.get_type().clone(); + let a = m_a.appr().clone(); + let m_b = result.get_type().clone(); + debug!("m_a {}", m_a); + let c = + match *m_a.appl() { + Type::Variable(ref var) => vec![Constraint { + class: "Monad".into(), + variables: vec![var.clone()], + }], + _ => vec![], + }; + let arg2_type = function_type_(a.clone(), m_b.clone()); + let bind_typ = function_type_(m_a, function_type_(arg2_type.clone(), m_b.clone())); + let bind_ident = Identifier(Id::new(">>=".into(), bind_typ, c.clone())); + + //Create ok binding + let func_ident = Id::new( + self.name_supply.from_str("#ok"), + arg2_type.clone(), + c.clone(), + ); //TODO unique id + let var = Id::new( + self.name_supply.from_str("p"), + function_type_(a, m_b.clone()), + c.clone(), + ); //Constraints for a + let fail_ident = Identifier(Id::new( + "fail".into(), + function_type_(list_type(char_type()), m_b), + c, + )); + let func = Lambda( + var.clone(), + Box::new(Case( + Box::new(Identifier(var)), + vec![ + Alternative { + pattern: self.translate_pattern(pattern), + expression: result, + }, + Alternative { + pattern: Pattern::WildCard, + expression: Apply( + fail_ident.into(), + Box::new(string("Unmatched pattern in let")), + ), + }, + ], + )), + ); + let bind = Binding { + name: func_ident.clone(), + expression: func, + }; - fn translate_bindings(&mut self, bindings: Vec>) -> Vec>> { - let mut result = Vec::new(); - let mut vec: Vec> = Vec::new(); - for bind in bindings.into_iter() { - if vec.len() > 0 && vec[0].name != bind.name { + Let( + vec![bind], + Box::new(apply(bind_ident, (vec![expr, Identifier(func_ident)]).into_iter())), + ) + } + + fn translate_bindings( + &mut self, + bindings: Vec>, + ) -> Vec>> { + let mut result = vec![]; + let mut vec: Vec> = vec![]; + for bind in bindings.into_iter() { + if !vec.is_empty() && vec[0].name != bind.name { + result.push(self.translate_matching_groups(vec)); + vec = vec![]; + } + vec.push(bind); + } + if !vec.is_empty() { result.push(self.translate_matching_groups(vec)); - vec = Vec::new(); } - vec.push(bind); - } - if vec.len() > 0 { - result.push(self.translate_matching_groups(vec)); + result } - result - } - - fn unwrap_pattern(&mut self, uid: usize, id: Id, pattern: module::Pattern, result: &mut Vec<(Id, Pattern>)>) { - match pattern { - module::Pattern::Constructor(ctor_name, mut patterns) => { - let index = result.len(); - let mut name = id.name.name.to_string(); - let base_length = name.len(); - result.push((id, Pattern::Number(0)));//Dummy - for (i, p) in patterns.iter_mut().enumerate() { - let x = match *p { - module::Pattern::Constructor(..) | module::Pattern::Number(..) => { - //HACK, by making the variable have the same uid as - //the index the newly generated pattern will be recognized - //as the same since their binding variable are the same - name.truncate(base_length); - name.push('_'); - name.push_str(&*i.to_string()); - - let n = Name { name: intern(name.as_ref()), uid: uid }; - Some(module::Pattern::Identifier(n)) - } - _ => None - }; - match x { - Some(mut x) => { - ::std::mem::swap(p, &mut x); - let id = match *p { - module::Pattern::Identifier(ref n) => Id::new(n.clone(), Type::new_var(intern("a")), vec![]), - _ => panic!() - }; - self.unwrap_pattern(uid, id, x, result); + + fn unwrap_pattern( + &mut self, + uid: usize, + id: Id, + pattern: module::Pattern, + result: &mut Vec<(Id, Pattern>)>, + ) { + match pattern { + module::Pattern::Constructor(ctor_name, mut patterns) => { + let index = result.len(); + let mut name = id.name.name.to_string(); + let base_length = name.len(); + result.push((id, Pattern::Number(0))); //Dummy + for (i, p) in patterns.iter_mut().enumerate() { + let x = match *p { + module::Pattern::Constructor(..) | module::Pattern::Number(..) => { + //HACK, by making the variable have the same uid as + //the index the newly generated pattern will be recognized + //as the same since their binding variable are the same + name.truncate(base_length); + name.push('_'); + name.push_str(&*i.to_string()); + + let n = Name { + name: intern(name.as_ref()), + uid, + }; + Some(module::Pattern::Identifier(n)) + } + _ => None, + }; + match x { + Some(mut x) => { + ::std::mem::swap(p, &mut x); + let id = match *p { + module::Pattern::Identifier(ref n) => { + Id::new(n.clone(), "a".into(), vec![]) + } + _ => panic!(), + }; + self.unwrap_pattern(uid, id, x, result); + } + None => (), } - None => () } + result[index].1 = + self.translate_pattern(module::Pattern::Constructor(ctor_name, patterns)); } - result[index].1 = self.translate_pattern(module::Pattern::Constructor(ctor_name, patterns)); + _ => result.push((id, self.translate_pattern(pattern))), } - _ => result.push((id, self.translate_pattern(pattern))) - } - } - ///Translates a pattern list of patterns into a list of patterns which are not nested. - ///The first argument of each tuple is the identifier that is expected to be passed to the case. - fn unwrap_patterns(&mut self, uid: usize, arg_ids: &[Id], arguments: &[module::Pattern]) -> Vec<(Id, Pattern>)> { - let mut result = Vec::new(); - for (p, id) in arguments.iter().zip(arg_ids.iter()) { - self.unwrap_pattern(uid, id.clone(), p.clone(), &mut result); } - result - } - - ///Translates a case expression into the core language. - ///Since the core language do not have nested patterns the patterns are unwrapped into - ///multiple case expressions. - fn translate_case(&mut self, expr: module::TypedExpr, alts: Vec>) -> Expr> { - let mut vec = Vec::new(); - let dummy_var = &[Id::new(self.name_supply.anonymous(), Type::new_var(intern("a")), vec![])]; - let uid = self.name_supply.next_id(); - for module::Alternative { pattern, matches, where_bindings } in alts.into_iter() { - let bindings = where_bindings.map_or(Vec::new(), |bs| self.translate_bindings(bs)); - vec.push((self.unwrap_patterns(uid, dummy_var, &[pattern.node]), bindings, matches)); - } - let mut x = self.translate_equations_(vec); - match x { - Case(ref mut body, _) => { - **body = self.translate_expr(expr); + ///Translates a pattern list of patterns into a list of patterns which are not nested. + ///The first argument of each tuple is the identifier that is expected to be passed to the case. + fn unwrap_patterns( + &mut self, + uid: usize, + arg_ids: &[Id], + arguments: &[module::Pattern], + ) -> Vec<(Id, Pattern>)> { + let mut result = vec![]; + for (p, id) in arguments.iter().zip(arg_ids.iter()) { + self.unwrap_pattern(uid, id.clone(), p.clone(), &mut result); } - _ => panic!("Not case") + result } - x - } - ///Translates a binding group such as - ///map f (x:xs) = e1 - ///map f [] = e2 - fn translate_matching_groups(&mut self, mut bindings: Vec>) -> Binding> { - //If the binding group is simple (no patterns and only one binding) - //then we do a simple translation to preserve the names for the arguments. - if bindings.len() == 1 && simple_binding(&bindings[0]) { - let module::Binding { - name, - arguments, + + ///Translates a case expression into the core language. + ///Since the core language do not have nested patterns the patterns are unwrapped into + ///multiple case expressions. + fn translate_case( + &mut self, + expr: module::TypedExpr, + alts: Vec>, + ) -> Expr> { + let mut vec = vec![]; + let dummy_var = &[Id::new(self.name_supply.anonymous(), "a".into(), vec![])]; + let uid = self.name_supply.next_id(); + for module::Alternative { + pattern, matches, - typ: module::Qualified { constraints, value: typ, }, - where_bindings - } = bindings.pop().unwrap(); - let arg_iterator = arguments.into_iter().map(|p| { - match p { - module::Pattern::Identifier(n) => n, - module::Pattern::WildCard => Name { name: intern("_"), uid: usize::max_value() }, - _ => panic!("simple_binding fail") + where_bindings, + } in alts.into_iter() + { + let bindings = where_bindings.map_or(vec![], |bs| self.translate_bindings(bs)); + vec.push(( + self.unwrap_patterns(uid, dummy_var, &[pattern.node]), + bindings, + matches, + )); + } + let mut x = self.translate_equations_(vec); + match x { + Case(ref mut body, _) => { + **body = self.translate_expr(expr); } - }); - let expr = { - let lambda_ids = lambda_iterator(&typ) - .zip(arg_iterator) - .map(|(typ, arg)| { - Id::new(arg, typ.clone(), vec![]) - }); - let where_bindings_binds = where_bindings.map_or(Vec::new(), |bs| self.translate_bindings(bs).into_iter().collect()); - make_lambda(lambda_ids, make_let(where_bindings_binds, self.translate_match(matches))) - }; - return Binding { - name: Id::new(name, typ, constraints), - expression: expr + _ => panic!("Not case"), } + x } - //Generate new names for each of the arguments (since it is likely that not all arguments have a name) - let mut arg_ids = Vec::new(); - let name; - { - let binding0 = &bindings[0]; - name = Id::new(binding0.name.clone(), binding0.typ.value.clone(), binding0.typ.constraints.clone()); - let mut typ = &binding0.typ.value; - for _ in 0..binding0.arguments.len() { - arg_ids.push(Id::new(self.name_supply.from_str("arg"), typ.clone(), vec![])); - typ = match *typ { - Type::Application(_, ref next) => &**next, - _ => typ//We dont actually have a function type which we need, so we are likely in a unittest - //just reuse the same type so we do not crash + ///Translates a binding group such as + ///map f (x:xs) = e1 + ///map f [] = e2 + fn translate_matching_groups( + &mut self, + mut bindings: Vec>, + ) -> Binding> { + //If the binding group is simple (no patterns and only one binding) + //then we do a simple translation to preserve the names for the arguments. + if bindings.len() == 1 && simple_binding(&bindings[0]) { + let module::Binding { + name, + arguments, + matches, + typ: + module::Qualified { + constraints, + value: typ, + }, + where_bindings, + } = bindings.pop().unwrap(); + let arg_iterator = arguments.into_iter().map(|p| match p { + module::Pattern::Identifier(n) => n, + module::Pattern::WildCard => Name { + name: intern("_"), + uid: usize::max_value(), + }, + _ => panic!("simple_binding fail"), + }); + let expr = { + let lambda_ids = lambda_iterator(&typ) + .zip(arg_iterator) + .map(|(typ, arg)| Id::new(arg, typ.clone(), vec![])); + let where_bindings_binds = where_bindings.map_or(vec![], |bs| { + self.translate_bindings(bs).into_iter().collect() + }); + make_lambda( + lambda_ids, + make_let(where_bindings_binds, self.translate_match(matches)), + ) + }; + return Binding { + name: Id::new(name, typ, constraints), + expression: expr, }; } + //Generate new names for each of the arguments (since it is likely that not all arguments have a name) + let mut arg_ids = vec![]; + let name; + { + let binding0 = &bindings[0]; + name = Id::new( + binding0.name.clone(), + binding0.typ.value.clone(), + binding0.typ.constraints.clone(), + ); + let mut typ = &binding0.typ.value; + for _ in 0..binding0.arguments.len() { + arg_ids.push(Id::new(self.name_supply.from_str("arg"), typ.clone(), vec![])); + typ = match *typ { + Type::Application(_, ref next) => next, + _ => typ, //We dont actually have a function type which we need, so we are likely in a unittest + //just reuse the same type so we do not crash + }; + } + } + //First we flatten all the patterns that occur in each equation + //(2:xs) -> [(x:xs), 2] + let uid = self.name_supply.next_id(); + let equations: Vec<_> = bindings + .into_iter() + .map(|bind| { + let module::Binding { + arguments, + matches, + where_bindings, + .. + } = bind; + let where_bindings_binds = + where_bindings.map_or(vec![], |bs| self.translate_bindings(bs)); + ( + self.unwrap_patterns(uid, arg_ids.as_ref(), &*arguments), + where_bindings_binds, + matches, + ) + }) + .collect(); + let mut expr = self.translate_equations_(equations); + expr = make_lambda(arg_ids.into_iter(), expr); + debug!("Desugared {} :: {}\n {}", name.name, name.typ, expr); + Binding { + name, + expression: expr, + } } - //First we flatten all the patterns that occur in each equation - //(2:xs) -> [(x:xs), 2] - let uid = self.name_supply.next_id(); - let equations: Vec<_> = bindings.into_iter().map(|bind| { - let module::Binding { - arguments, - matches, - where_bindings, - .. - } = bind; - let where_bindings_binds = where_bindings.map_or(Vec::new(), |bs| self.translate_bindings(bs)); - (self.unwrap_patterns(uid, arg_ids.as_ref(), &*arguments), where_bindings_binds, matches) - }).collect(); - let mut expr = self.translate_equations_(equations); - expr = make_lambda(arg_ids.into_iter(), expr); - debug!("Desugared {} :: {}\n {}", name.name, name.typ, expr); - Binding { - name: name, - expression: expr - } - } - fn translate_equations_(&mut self, equations: Vec<(Vec<(Id, Pattern>)>, Vec>>, module::Match)>) -> Expr> { - let mut eqs: Vec = Vec::new(); - for &(ref ps, ref bs, ref e) in equations.iter() { - eqs.push(Equation(ps.as_ref(), (bs.as_ref(), e))); - } - for e in eqs.iter() { - debug!("{:?}", e); + fn translate_equations_( + &mut self, + equations: Vec<( + Vec<(Id, Pattern>)>, + Vec>>, + module::Match, + )>, + ) -> Expr> { + let mut eqs: Vec = vec![]; + for &(ref ps, ref bs, ref e) in equations.iter() { + eqs.push(Equation(ps.as_ref(), (bs.as_ref(), e))); + } + for e in eqs.iter() { + debug!("{:?}", e); + } + self.translate_equations(eqs.as_ref()) } - self.translate_equations(eqs.as_ref()) - } - ///Translates a list of guards, if no guards matches then the result argument will be the result - fn translate_guards(&mut self, mut result: Expr>, guards: &[module::Guard]) -> Expr> { - for guard in guards.iter().rev() { - let predicate = Box::new(self.translate_expr(guard.predicate.clone())); - result = Case(predicate, vec![ - Alternative { pattern: bool_pattern("True"), expression: self.translate_expr(guard.expression.clone()) }, - Alternative { pattern: bool_pattern("False"), expression: result }, - ]); + ///Translates a list of guards, if no guards matches then the result argument will be the result + fn translate_guards( + &mut self, + mut result: Expr>, + guards: &[module::Guard], + ) -> Expr> { + for guard in guards.iter().rev() { + let predicate = Box::new(self.translate_expr(guard.predicate.clone())); + result = Case( + predicate, + vec![ + Alternative { + pattern: bool_pattern("True"), + expression: self.translate_expr(guard.expression.clone()), + }, + Alternative { + pattern: bool_pattern("False"), + expression: result, + }, + ], + ); + } + result } - result - } - fn translate_equations(&mut self, equations: &[Equation]) -> Expr> { - ///Returns true if the two patterns would match for the same values - fn matching(lhs: &(T, Pattern), rhs: &(T, Pattern)) -> bool { - if lhs.0 != rhs.0 { - return false; - } - match (&lhs.1, &rhs.1) { - (&Pattern::Constructor(ref l, _), &Pattern::Constructor(ref r, _)) => *l == *r, - (&Pattern::Constructor(..), &Pattern::Number(..)) => false, - (&Pattern::Number(..), &Pattern::Constructor(..)) => false, - _ => true + fn translate_equations(&mut self, equations: &[Equation]) -> Expr> { + ///Returns true if the two patterns would match for the same values + fn matching(lhs: &(T, Pattern), rhs: &(T, Pattern)) -> bool { + lhs.0 == rhs.0 + && match (&lhs.1, &rhs.1) { + (&Pattern::Constructor(ref l, _), &Pattern::Constructor(ref r, _)) => { + *l == *r + } + (&Pattern::Constructor(..), &Pattern::Number(..)) + | (&Pattern::Number(..), &Pattern::Constructor(..)) => false, + _ => true, + } } - } - debug!("In {:?}", equations); - let &Equation(ps, (where_bindings_bindings, e)) = &equations[0]; - if ps.len() == 0 { - assert_eq!(equations.len(), 1);//Otherwise multiple matches for this group - let bindings = where_bindings_bindings.iter().map(|x| x.clone()).collect(); - return make_let(bindings, self.translate_match((*e).clone())); - } - if ps.len() == 1 { - let mut alts: Vec>> = Vec::new(); - for (i, &Equation(ps, (where_bindings_bindings, m))) in equations.iter().enumerate() { + debug!("In {:?}", equations); + let &Equation(ps, (where_bindings_bindings, e)) = &equations[0]; + if ps.is_empty() { + assert_eq!(equations.len(), 1); //Otherwise multiple matches for this group let bindings = where_bindings_bindings.iter().map(|x| x.clone()).collect(); - match *m { - module::Match::Simple(ref e) => { - let alt = if ps.len() == 0 { - Alternative { - pattern: Pattern::WildCard, expression: - make_let(bindings, self.translate_expr((*e).clone())) - } + return make_let(bindings, self.translate_match((*e).clone())); + } + if ps.len() == 1 { + let mut alts: Vec>> = vec![]; + for (i, &Equation(ps, (where_bindings_bindings, m))) in equations.iter().enumerate() + { + let bindings = where_bindings_bindings.iter().map(|x| x.clone()).collect(); + match *m { + module::Match::Simple(ref e) => { + let pattern = + ps.first().map(|x| x.1.clone()).unwrap_or(Pattern::WildCard); + + alts.push(Alternative { + pattern, + expression: make_let(bindings, self.translate_expr((*e).clone())), + }); } - else { - Alternative { + module::Match::Guards(ref guards) => { + let fallthrough = if equations.len() == i + 1 { + unmatched_guard() + } else { + self.translate_equations(&equations[i + 1..]) + }; + alts.push(Alternative { pattern: ps[0].1.clone(), - expression: make_let(bindings, self.translate_expr((*e).clone())) - } - }; - alts.push(alt); - } - module::Match::Guards(ref guards) => { - let fallthrough = if equations.len() == i + 1 { - unmatched_guard() + expression: make_let( + bindings, + self.translate_guards(fallthrough, guards), + ), + }); } - else { - self.translate_equations(&equations[i + 1..]) - }; - alts.push(Alternative { - pattern: ps[0].1.clone(), - expression: make_let(bindings, self.translate_guards(fallthrough, &**guards)) - }); } } + let body = Box::new(Identifier(ps[0].0.clone())); + return Case(body, alts); } - let body = Box::new(Identifier(ps[0].0.clone())); - return Case(body, alts); - } - - let mut last_index = 0; - let mut vec: Vec = Vec::new(); - let mut alts: Vec>> = Vec::new(); - let mut visited = Vec::new(); - loop { - //Find the first pattern which does a test and is not already used - let mut pattern_test = None; - while last_index < equations.len() { - let &Equation(ps, _) = &equations[last_index]; - if ps.len() > 0 { - match ps[0].1 { - Pattern::Constructor(..) | Pattern::Number(..) => { - if visited.iter().find(|x| matching(**x, &ps[0])).is_none() { - pattern_test = Some(&ps[0]); - visited.push(&ps[0]); - last_index += 1; - break; + + let mut last_index = 0; + let mut vec: Vec = vec![]; + let mut alts: Vec>> = vec![]; + let mut visited = vec![]; + loop { + //Find the first pattern which does a test and is not already used + let mut pattern_test = None; + while last_index < equations.len() { + let &Equation(ps, _) = &equations[last_index]; + if let Some(head) = ps.first() { + match head.1 { + Pattern::Constructor(..) | Pattern::Number(..) => { + if visited.iter().find(|x| matching(**x, &head)).is_none() { + pattern_test = Some(head); + visited.push(&head); + last_index += 1; + break; + } } + _ => (), } - _ => () } + last_index += 1; } - last_index += 1; - } - match pattern_test { - Some(pattern_test) => { + if let Some(pattern_test) = pattern_test { vec.clear(); - let mut variable_bindings = Vec::new(); + let mut variable_bindings = vec![]; //Gather all patterns which matches the pattern for &Equation(patterns, expr) in equations.iter() { - if patterns.len() > 0 && matching(pattern_test, &patterns[0]) { + if !patterns.is_empty() && matching(pattern_test, &patterns[0]) { vec.push(Equation(&patterns[1..], expr)); //If the patter_test is a constructor we need to add the variables //of the other patterns in a let binding to make sure that all names exist match (&patterns[0].1, &pattern_test.1) { - (&Pattern::Constructor(_, ref l_vars), &Pattern::Constructor(_, ref r_vars)) => { + ( + &Pattern::Constructor(_, ref l_vars), + &Pattern::Constructor(_, ref r_vars), + ) => { for (l_var, r_var) in l_vars.iter().zip(r_vars.iter()) { if l_var != r_var { - variable_bindings.push(Binding { name: l_var.clone(), expression: Identifier(r_var.clone()) }); + variable_bindings.push(Binding { + name: l_var.clone(), + expression: Identifier(r_var.clone()), + }); } } } - _ => () + _ => (), } - } - else if patterns.len() == 0 { + } else if patterns.is_empty() { vec.push(Equation(patterns, expr)); } } @@ -971,153 +1236,183 @@ impl <'a> Translator<'a> { let bs = needed_variables(arg_id, equations); alts.push(Alternative { pattern: pattern_test.1.clone(), - expression: make_let(bs, e) + expression: make_let(bs, e), }); + } else { + break; } - None => break - } - } - if alts.len() == 0 { - for &Equation(patterns, expr) in equations.iter() { - vec.push(Equation(&patterns[1..], expr)); } - let &Equation(ps, _) = &equations[0]; - let arg_id = &ps[0].0; - let bs = needed_variables(arg_id, equations); - make_let(bs, self.translate_equations(vec.as_ref())) - } - else { - let defaults: Vec = equations.iter() - .filter(|& &Equation(ps, _)| ps.len() > 0 && (match ps[0].1 { Pattern::WildCard | Pattern::Identifier(..) => true, _ => false })) - .map(|&Equation(ps, e)| Equation(&ps[1..], e)) - .collect(); - if defaults.len() != 0 { + if alts.is_empty() { + for &Equation(patterns, expr) in equations.iter() { + vec.push(Equation(&patterns[1..], expr)); + } + let &Equation(ps, _) = &equations[0]; let arg_id = &ps[0].0; let bs = needed_variables(arg_id, equations); - let e = make_let(bs, self.translate_equations(defaults.as_ref())); - alts.push(Alternative { - pattern: Pattern::WildCard, - expression: e - }); + make_let(bs, self.translate_equations(vec.as_ref())) + } else { + let defaults: Vec = equations + .iter() + .filter(|&&Equation(ps, _)| { + !ps.is_empty() + && matches!(ps[0].1, Pattern::WildCard | Pattern::Identifier(..)) + }) + .map(|&Equation(ps, e)| Equation(&ps[1..], e)) + .collect(); + if !defaults.is_empty() { + let arg_id = &ps[0].0; + let bs = needed_variables(arg_id, equations); + let e = make_let(bs, self.translate_equations(defaults.as_ref())); + alts.push(Alternative { + pattern: Pattern::WildCard, + expression: e, + }); + } + let &Equation(ps, _) = &equations[0]; + let body = Box::new(Identifier(ps[0].0.clone())); + Case(body, alts) } - let &Equation(ps, _) = &equations[0]; - let body = Box::new(Identifier(ps[0].0.clone())); - Case(body, alts) } - } - fn translate_pattern(&mut self, pattern: module::Pattern) -> Pattern> { - match pattern { - module::Pattern::Identifier(i) => Pattern::Identifier(Id::new(i, Type::new_var(intern("a")), vec![])), - module::Pattern::Number(n) => Pattern::Number(n), - module::Pattern::Constructor(name, patterns) => { - let ps = patterns.into_iter().map(|pat| { - match pat { - module::Pattern::Identifier(name) => Id::new(name, Type::new_var(intern("a")), vec![]), - module::Pattern::WildCard => Id::new(Name { name: intern("_"), uid: usize::max_value() }, Type::new_var(intern("a")), vec![]), - _ => panic!("Nested pattern") - } - }).collect(); - Pattern::Constructor(Id::new(name, Type::new_var(intern("a")), vec![]), ps) + fn translate_pattern(&mut self, pattern: module::Pattern) -> Pattern> { + match pattern { + module::Pattern::Identifier(i) => { + Pattern::Identifier(Id::new(i, "a".into(), vec![])) + } + module::Pattern::Number(n) => Pattern::Number(n), + module::Pattern::Constructor(name, patterns) => { + let ps = patterns + .into_iter() + .map(|pat| match pat { + module::Pattern::Identifier(name) => Id::new(name, "a".into(), vec![]), + module::Pattern::WildCard => Id::new( + Name { + name: "_".into(), + uid: usize::max_value(), + }, + "a".into(), + vec![], + ), + _ => panic!("Nested pattern"), + }) + .collect(); + Pattern::Constructor(Id::new(name, "a".into(), vec![]), ps) + } + module::Pattern::WildCard => Pattern::WildCard, } - module::Pattern::WildCard => Pattern::WildCard } } -} fn bool_pattern(s: &str) -> Pattern> { - Pattern::Constructor(Id::new(Name { name: intern(s), uid: 0 }, bool_type(), vec![]), vec![]) + Pattern::Constructor(Id::new(s.into(), bool_type(), vec![]), vec![]) } struct LambdaIterator<'a, Id: 'a> { - typ: &'a Type + typ: &'a Type, } - impl <'a, Id: AsRef> Iterator for LambdaIterator<'a, Id> { + impl<'a, Id: AsRef> Iterator for LambdaIterator<'a, Id> { type Item = &'a Type; fn next(&mut self) -> Option<&'a Type> { - match *self.typ { - Type::Application(ref lhs, ref rhs) => { - match **lhs { - Type::Application(ref func, _) => { - match **func { - Type::Constructor(ref op) if op.name.as_ref() == "->" => { - let func = self.typ; - self.typ = &**rhs; - Some(func) - } - _ => None - } - } - _ => None - } - } - _ => None + let Type::Application(ref lhs, ref rhs) = self.typ else { + return None; + }; + + let Type::Application(ref func, _) = **lhs else { + return None; + }; + + let Type::Constructor(ref op) = **func else { + return None; + }; + + if op.name.as_ref() != "->" { + return None; } + std::mem::replace(&mut self.typ, rhs).into() } } //Creates an iterator which walks through all the function types that are needed //when creating a lambda with make_lambda //Ex: (a -> b -> c) generates [(a -> b -> c), (b -> c)] fn lambda_iterator<'a, Id: AsRef>(typ: &'a Type) -> LambdaIterator<'a, Id> { - LambdaIterator { typ: typ } + LambdaIterator { typ } } ///Tests that the binding has no patterns for its arguments fn simple_binding(binding: &module::Binding) -> bool { binding.arguments.iter().all(|arg| { - match *arg { - module::Pattern::WildCard | module::Pattern::Identifier(..) => true, - _ => false - } + matches!( + *arg, + module::Pattern::WildCard | module::Pattern::Identifier(..) + ) }) } ///Creates a lambda from an iterator of its arguments and body - fn make_lambda>(mut iter: I, body: Expr) -> Expr { + fn make_lambda>(mut iter: I, body: Expr) -> Expr { match iter.next() { Some(arg) => Lambda(arg, Box::new(make_lambda(iter, body))), - None => body + None => body, } } ///Creates a function application from a function and its arguments - fn apply>>(mut func: Expr, iter: I) -> Expr { + fn apply>>(mut func: Expr, iter: I) -> Expr { for arg in iter { - func = Apply(Box::new(func), Box::new(arg)); + func = Apply(func.into(), arg.into()); } func } ///Creates a let binding, but if there is no bindings the let is omitted fn make_let(bindings: Vec>, expr: Expr) -> Expr { - if bindings.len() == 0 { + if bindings.is_empty() { expr - } - else { - Let(bindings, Box::new(expr)) + } else { + Let(bindings, expr.into()) } } ///Takes a id of the variable passed to the case and returns a vector ///of bindings which need to be added to make sure no variables are missing fn needed_variables(arg_id: &Id, equations: &[Equation]) -> Vec>> { - equations.iter() - .filter(|& &Equation(ps, _)| ps.len() > 0 && (match ps[0].1 { Pattern::WildCard | Pattern::Identifier(..) => true, _ => false })) + equations + .iter() + .filter(|&&Equation(ps, _)| { + !ps.is_empty() && matches!(ps[0].1, Pattern::WildCard | Pattern::Identifier(..)) + }) .map(|eq| { - let &Equation(ps, _) = eq; - let other_id = match ps[0].1 { - Pattern::Identifier(ref name) => name.clone(), - Pattern::WildCard => Id::new(Name { name: intern("_"), uid: usize::max_value() }, Type::new_var(intern("a")), vec![]), - _ => panic!() - }; - Binding { name: other_id, expression: Identifier(arg_id.clone()) } - }).collect() + let &Equation(ps, _) = eq; + let other_id = match ps[0].1 { + Pattern::Identifier(ref name) => name.clone(), + Pattern::WildCard => Id::new( + Name { + name: intern("_"), + uid: usize::max_value(), + }, + "a".into(), + vec![], + ), + _ => panic!(), + }; + Binding { + name: other_id, + expression: Identifier(arg_id.clone()), + } + }) + .collect() } ///Creates a string literal expressions from a &str fn string(s: &str) -> Expr> { - Literal(LiteralData { typ: list_type(char_type()), value: String(intern(s)) }) + Literal(LiteralData { + typ: list_type(char_type()), + value: String(s.into()), + }) } ///Creates an expression which reports an unmatched guard error when executed fn unmatched_guard() -> Expr> { - let error_ident = Identifier(Id::new(Name { name: intern("error"), uid: 0 }, function_type_(list_type(char_type()), Type::new_var(intern("a"))), vec![])); - Apply(Box::new(error_ident), Box::new(string("Unmatched guard"))) + let error_ident = Identifier(Id::new( + "error".into(), + function_type_(list_type(char_type()), "a".into()), + vec![], + )); + Apply(error_ident.into(), Box::new(string("Unmatched guard"))) } - } diff --git a/src/deriving.rs b/src/deriving.rs index 8bdf204..6768023 100644 --- a/src/deriving.rs +++ b/src/deriving.rs @@ -1,61 +1,82 @@ -use crate::module::encode_binding_identifier; -use crate::core::*; -use crate::core::Expr::*; -use crate::renamer::{name, NameSupply}; -use crate::renamer::typ::*; -use crate::interner::{intern, InternedStr}; +use crate::{ + core::{ + Expr::*, + *, + }, + interner::{ + intern, + InternedStr, + }, + module::encode_binding_identifier, + renamer::{ + name, + typ::*, + NameSupply, + }, +}; pub fn generate_deriving(instances: &mut Vec>>, data: &DataDefinition) { - let mut gen = DerivingGen { name_supply: NameSupply::new() }; + let mut gen = + DerivingGen { + name_supply: NameSupply::new(), + }; for deriving in data.deriving.iter() { match deriving.as_ref() { "Eq" => { - let mut bindings = Vec::new(); + let mut bindings = vec![]; bindings.push(gen.generate_eq(data)); instances.push(Instance { - constraints: Vec::new(), + constraints: vec![], typ: data.typ.value.clone(), - classname: Name { name: intern("Eq"), uid: 0 }, - bindings: bindings + classname: "Eq".into(), + bindings, }); } "Ord" => { - let mut bindings = Vec::new(); + let mut bindings = vec![]; let b = gen.generate_ord(data); debug!("Generated Ord {:?} ->>\n{:?}", data.typ, b); bindings.push(b); instances.push(Instance { - constraints: Vec::new(), + constraints: vec![], typ: data.typ.value.clone(), - classname: Name { name: intern("Ord"), uid: 0 }, - bindings: bindings + classname: "Ord".into(), + bindings, }); } - x => panic!("Cannot generate instance for class {:?}", x) + x => panic!("Cannot generate instance for class {:?}", x), } } } struct DerivingGen { - name_supply: NameSupply + name_supply: NameSupply, } impl DerivingGen { fn generate_eq(&mut self, data: &DataDefinition) -> Binding> { self.make_binop("Eq", "==", data, &mut |this, id_l, id_r| { - let alts = this.match_same_constructors(data, &id_r, &mut |this, l, r| this.eq_fields(l, r)); - Case(Box::new(Identifier(id_l.clone())), alts) + let alts = + this.match_same_constructors(data, &id_r, &mut |this, l, r| this.eq_fields(l, r)); + Case(Identifier(id_l.clone()).into(), alts) }) } fn eq_fields(&mut self, args_l: &[Id], args_r: &[Id]) -> Expr> { if args_l.len() >= 1 { - let first = bool_binop("==", Identifier(args_l[0].clone()), Identifier(args_r[0].clone())); - args_l.iter().skip(1).zip(args_r.iter().skip(1)).fold(first, |acc, (l, r)| { - let test = bool_binop("==", Identifier(l.clone()), Identifier(r.clone())); - bool_binop("&&", acc, test) - }) - } - else { + let first = bool_binop( + "==", + Identifier(args_l[0].clone()), + Identifier(args_r[0].clone()), + ); + args_l + .iter() + .skip(1) + .zip(args_r.iter().skip(1)) + .fold(first, |acc, (l, r)| { + let test = bool_binop("==", Identifier(l.clone()), Identifier(r.clone())); + bool_binop("&&", acc, test) + }) + } else { true_expr() } } @@ -64,7 +85,8 @@ impl DerivingGen { self.make_binop("Ord", "compare", data, &mut |this, id_l, id_r| { //We first compare the tags of the arguments since this would otherwise the last of the alternatives let when_eq = { - let alts = this.match_same_constructors(data, &id_r, &mut |this, l, r| this.ord_fields(l, r)); + let alts = this + .match_same_constructors(data, &id_r, &mut |this, l, r| this.ord_fields(l, r)); Case(Box::new(Identifier(id_l.clone())), alts) }; let cmp = compare_tags(Identifier(id_l), Identifier(id_r)); @@ -73,132 +95,222 @@ impl DerivingGen { } fn ord_fields(&mut self, args_l: &[Id], args_r: &[Id]) -> Expr> { - let ordering = Type::new_op(name("Ordering"), Vec::new()); + let ordering = Type::new_op(name("Ordering"), vec![]); if args_l.len() >= 1 { let mut iter = args_l.iter().zip(args_r.iter()).rev(); let (x, y) = iter.next().unwrap(); - let last = binop("compare", Identifier(x.clone()), Identifier(y.clone()), ordering.clone()); + let last = binop( + "compare", + Identifier(x.clone()), + Identifier(y.clone()), + ordering.clone(), + ); iter.fold(last, |acc, (l, r)| { let test = bool_binop("compare", Identifier(l.clone()), Identifier(r.clone())); self.eq_or_default(test, acc) }) - } - else { + } else { Identifier(id("EQ", ordering)) } } ///Creates a binary function binding with the name 'funcname' which is a function in an instance for 'data' ///This function takes two parameters of the type of 'data' - fn make_binop(&mut self, class: &str, funcname: &str, data: &DataDefinition, func: &mut dyn FnMut(&mut DerivingGen, Id, Id) -> Expr>) -> Binding> { + fn make_binop( + &mut self, + class: &str, + funcname: &str, + data: &DataDefinition, + func: &mut dyn FnMut(&mut DerivingGen, Id, Id) -> Expr>, + ) -> Binding> { let arg_l = self.name_supply.anonymous(); let arg_r = self.name_supply.anonymous(); let mut id_r = Id::new(arg_r, data.typ.value.clone(), data.typ.constraints.clone()); let mut id_l = Id::new(arg_l, data.typ.value.clone(), data.typ.constraints.clone()); let expr = func(self, id_l.clone(), id_r.clone()); id_r.typ.value = function_type_(data.typ.value.clone(), bool_type()); - id_l.typ.value = function_type_(data.typ.value.clone(), function_type_(data.typ.value.clone(), bool_type())); - let lambda_expr = Lambda(id_l, Box::new(Lambda(id_r, Box::new(expr))));//TODO types + id_l.typ.value = function_type_( + data.typ.value.clone(), + function_type_(data.typ.value.clone(), bool_type()), + ); + let lambda_expr = Lambda(id_l, Box::new(Lambda(id_r, expr.into()))); //TODO types let data_name = extract_applied_type(&data.typ.value).ctor().name; let name = encode_binding_identifier(data_name.name, intern(funcname)); //Create a constraint for each type parameter - fn make_constraints(mut result: Vec>, class: InternedStr, typ: &Type) -> Vec> { + fn make_constraints( + mut result: Vec>, + class: InternedStr, + typ: &Type, + ) -> Vec> { match typ { &Type::Application(ref f, ref param) => { - result.push(Constraint { class: Name { name: class, uid: 0 }, variables: vec![param.var().clone()] }); - make_constraints(result, class, &**f) + result.push(Constraint { + class: Name { + name: class, + uid: 0, + }, + variables: vec![param.var().clone()], + }); + make_constraints(result, class, f) } - _ => result + _ => result, } } - let constraints = make_constraints(Vec::new(), intern(class), &data.typ.value); + let constraints = make_constraints(vec![], intern(class), &data.typ.value); Binding { - name: Id::new(Name { name: name, uid: 0 }, lambda_expr.get_type().clone(), constraints), - expression: lambda_expr + name: Id::new( + Name { name, uid: 0 }, + lambda_expr.get_type().clone(), + constraints, + ), + expression: lambda_expr, } } fn eq_or_default(&mut self, cmp: Expr>, def: Expr>) -> Expr> { - let match_id = Id::new(self.name_supply.anonymous(), Type::new_op(name("Ordering"), Vec::new()), Vec::new()); - Case(Box::new(cmp), vec![ - Alternative { - pattern: Pattern::Constructor(id("EQ", Type::new_op(name("Ordering"), Vec::new())), Vec::new()), - expression: def - }, - Alternative { pattern: Pattern::Identifier(match_id.clone()), expression: Identifier(match_id) } - ]) + let match_id = Id::new( + self.name_supply.anonymous(), + Type::new_op(name("Ordering"), vec![]), + vec![], + ); + Case( + cmp.into(), + vec![ + Alternative { + pattern: Pattern::Constructor( + id("EQ", Type::new_op(name("Ordering"), vec![])), + vec![], + ), + expression: def, + }, + Alternative { + pattern: Pattern::Identifier(match_id.clone()), + expression: Identifier(match_id), + }, + ], + ) } - fn match_same_constructors(&mut self, data: &DataDefinition, id_r: &Id, f: &mut dyn FnMut(&mut DerivingGen, &[Id], &[Id]) -> Expr>) -> Vec>> { - let alts: Vec>> = data.constructors.iter().map(|constructor| { - let args_l: Vec> = - ArgIterator { typ: &constructor.typ.value } - .map(|arg| Id::new(self.name_supply.anonymous(), arg.clone(), constructor.typ.constraints.clone())) - .collect(); - let mut iter = ArgIterator { typ: &constructor.typ.value }; - let args_r: Vec> = iter.by_ref() - .map(|arg| Id::new(self.name_supply.anonymous(), arg.clone(), constructor.typ.constraints.clone())) + fn match_same_constructors( + &mut self, + data: &DataDefinition, + id_r: &Id, + f: &mut dyn FnMut(&mut DerivingGen, &[Id], &[Id]) -> Expr>, + ) -> Vec>> { + let alts: Vec>> = data + .constructors + .iter() + .map(|constructor| { + let args_l: Vec> = ArgIterator { + typ: &constructor.typ.value, + } + .map(|arg| { + Id::new( + self.name_supply.anonymous(), + arg.clone(), + constructor.typ.constraints.clone(), + ) + }) .collect(); - let ctor_id = Id::new(constructor.name, iter.typ.clone(), constructor.typ.constraints.clone()); - let expr = f(self, &*args_l, &*args_r); - let pattern_r = Pattern::Constructor(ctor_id.clone(), args_r); - let inner = Case(Box::new(Identifier(id_r.clone())), vec![ - Alternative { pattern: pattern_r, expression: expr }, - Alternative { - pattern: Pattern::WildCard, - expression: Identifier(Id::new(Name { uid: 0, name: intern("False") }, bool_type(), Vec::new())) + let mut iter = ArgIterator { + typ: &constructor.typ.value, + }; + let args_r: Vec> = iter + .by_ref() + .map(|arg| { + Id::new( + self.name_supply.anonymous(), + arg.clone(), + constructor.typ.constraints.clone(), + ) + }) + .collect(); + let ctor_id = Id::new( + constructor.name, + iter.typ.clone(), + constructor.typ.constraints.clone(), + ); + let expr = f(self, &*args_l, &*args_r); + let pattern_r = Pattern::Constructor(ctor_id.clone(), args_r); + let inner = Case( + Box::new(Identifier(id_r.clone())), + vec![ + Alternative { + pattern: pattern_r, + expression: expr, + }, + Alternative { + pattern: Pattern::WildCard, + expression: Identifier(Id::new("False".into(), bool_type(), vec![])), + }, + ], + ); + Alternative { + pattern: Pattern::Constructor(ctor_id, args_l), + expression: inner, } - ]); - Alternative { pattern: Pattern::Constructor(ctor_id, args_l), expression: inner } - }).collect(); + }) + .collect(); alts } } - fn id(s: &str, typ: Type) -> Id { - Id::new(Name {name: intern(s), uid: 0 }, typ, Vec::new()) + Id::new(s.into(), typ, vec![]) } fn compare_tags(lhs: Expr>, rhs: Expr>) -> Expr> { - let var = Type::new_var(intern("a")); - let typ = function_type_(var.clone(), function_type_(var.clone(), Type::new_op(name("Ordering"), Vec::new()))); - let id = Id::new(name("#compare_tags"), typ, Vec::new()); - Apply(Box::new(Apply(Box::new(Identifier(id)), Box::new(lhs))), Box::new(rhs)) + let var: Type<_> = "a".into(); + let typ = function_type_( + var.clone(), + function_type_(var.clone(), Type::new_op(name("Ordering"), vec![])), + ); + let id = Id::new(name("#compare_tags"), typ, vec![]); + Apply( + Box::new(Apply(Box::new(Identifier(id)), lhs.into())), + rhs.into(), + ) } fn bool_binop(op: &str, lhs: Expr>, rhs: Expr>) -> Expr> { binop(op, lhs, rhs, bool_type()) } -fn binop(op: &str, lhs: Expr>, rhs: Expr>, return_type: Type) -> Expr> { - let typ = function_type_(lhs.get_type().clone(), function_type_(rhs.get_type().clone(), return_type)); - let f = Identifier(Id::new(name(op), typ, Vec::new())); - Apply(Box::new(Apply(Box::new(f), Box::new(lhs))), Box::new(rhs)) +fn binop( + op: &str, + lhs: Expr>, + rhs: Expr>, + return_type: Type, +) -> Expr> { + let typ = function_type_( + lhs.get_type().clone(), + function_type_(rhs.get_type().clone(), return_type), + ); + let f = Identifier(Id::new(name(op), typ, vec![])); + Apply(Apply(f.into(), lhs.into()).into(), rhs.into()) } -fn true_expr() -> Expr> { - Identifier(Id::new(name("True"), bool_type(), Vec::new())) +fn true_expr() -> Expr> { + Identifier(Id::new(name("True"), bool_type(), vec![])) } struct ArgIterator<'a> { - typ: &'a Type + typ: &'a Type, } -impl <'a> Iterator for ArgIterator<'a> { +impl<'a> Iterator for ArgIterator<'a> { type Item = &'a Type; fn next(&mut self) -> Option<&'a Type> { use crate::types::try_get_function; - match try_get_function(self.typ) { - Some((arg, rest)) => { - self.typ = rest; - Some(arg) - } - None => None + if let Some((arg, rest)) = try_get_function(self.typ) { + self.typ = rest; + Some(arg) + } else { + None } } } fn extract_applied_type<'a, Id>(typ: &'a Type) -> &'a Type { match typ { - &Type::Application(ref lhs, _) => extract_applied_type(&**lhs), - _ => typ + &Type::Application(ref lhs, _) => extract_applied_type(lhs), + _ => typ, } } diff --git a/src/graph.rs b/src/graph.rs index b528e53..c914c3a 100644 --- a/src/graph.rs +++ b/src/graph.rs @@ -1,8 +1,7 @@ +use std::cmp::min; ///Graph module, contains a simple graph structure which is when typechecking to find ///functions which are mutually recursive - use std::iter::repeat; -use std::cmp::min; #[derive(PartialEq, Copy, Clone, Debug)] pub struct VertexIndex(usize); @@ -10,40 +9,52 @@ pub struct VertexIndex(usize); pub struct EdgeIndex(usize); impl VertexIndex { - fn get(&self) -> usize { let VertexIndex(v) = *self; v } + fn get(&self) -> usize { + self.0 + } } impl EdgeIndex { - fn get(&self) -> usize { let EdgeIndex(v) = *self; v } + fn get(&self) -> usize { + self.0 + } } pub struct Vertex { pub value: T, - edges: Vec + edges: Vec, } pub struct Edge { from: VertexIndex, - to: VertexIndex + to: VertexIndex, } pub struct Graph { edges: Vec, - vertices: Vec> + vertices: Vec>, } -impl Graph { +impl Graph { ///Creates a new graph - pub fn new() -> Graph { - Graph { edges: Vec::new(), vertices: Vec::new() } + pub fn new() -> Self { + Self { + edges: vec![], + vertices: vec![], + } } ///Creates a new vertex and returns the index which refers to it pub fn new_vertex(&mut self, value: T) -> VertexIndex { - self.vertices.push(Vertex { edges:Vec::new(), value: value }); + self.vertices.push(Vertex { + edges: vec![], + value, + }); VertexIndex(self.vertices.len() - 1) } - + ///Connects two vertices with an edge pub fn connect(&mut self, from: VertexIndex, to: VertexIndex) { - self.vertices[from.get()].edges.push(EdgeIndex(self.edges.len())); + self.vertices[from.get()] + .edges + .push(EdgeIndex(self.edges.len())); self.edges.push(Edge { from: from, to: to }); } ///Returns the vertex at the index @@ -65,12 +76,14 @@ impl Graph { ///Analyzes the graph for strongly connect components. ///Returns a vector of indices where each group is a separte vector pub fn strongly_connected_components(graph: &Graph) -> Vec> { - - let mut tarjan = TarjanComponents { graph: graph, index: 1, stack: Vec::new(), connections: Vec::new(), + let mut tarjan = TarjanComponents { + graph, + index: 1, + stack: vec![], + connections: vec![], valid: repeat(0).take(graph.len()).collect(), - lowlink: repeat(0).take(graph.len()).collect() + lowlink: repeat(0).take(graph.len()).collect(), }; - for vert in 0..graph.len() { if tarjan.valid[vert] == 0 { @@ -81,16 +94,16 @@ pub fn strongly_connected_components(graph: &Graph) -> Vec{ +struct TarjanComponents<'a, T: 'a> { index: usize, graph: &'a Graph, valid: Vec, lowlink: Vec, stack: Vec, - connections: Vec> + connections: Vec>, } ///Implementation of "Tarjan's strongly connected components algorithm" -impl <'a, T> TarjanComponents<'a, T> { +impl<'a, T> TarjanComponents<'a, T> { fn strong_connect(&mut self, v: VertexIndex) { self.valid[v.get()] = self.index; self.lowlink[v.get()] = self.index; @@ -101,21 +114,19 @@ impl <'a, T> TarjanComponents<'a, T> { let edge = self.graph.get_edge(*edge_index); if self.valid[edge.to.get()] == 0 { self.strong_connect(edge.to); - self.lowlink[v.get()] = min(self.lowlink[v.get()], self.lowlink[edge.to.get()]); - } - else if self.stack.iter().any(|x| *x == edge.to) { + self.lowlink[v.get()] = min(self.lowlink[v.get()], self.lowlink[edge.to.get()]); + } else if self.stack.iter().any(|x| *x == edge.to) { self.lowlink[v.get()] = min(self.lowlink[v.get()], self.valid[edge.to.get()]); } } if self.lowlink.get(v.get()) == self.valid.get(v.get()) { - let mut connected = Vec::new(); + let mut connected = vec![]; loop { - let w = self.stack.pop().unwrap(); connected.push(w); if w == v { - break + break; } } self.connections.push(connected); @@ -123,7 +134,6 @@ impl <'a, T> TarjanComponents<'a, T> { } } - #[test] fn test_tarjan() { let mut graph = Graph::new(); diff --git a/src/infix.rs b/src/infix.rs index 3f99e94..ba97cef 100644 --- a/src/infix.rs +++ b/src/infix.rs @@ -1,46 +1,56 @@ -use crate::module::*; -use crate::renamer::Name; -use crate::interner::intern; -use std::collections::HashMap; +use { + crate::{ + interner::intern, + module::*, + renamer::Name, + }, + std::collections::HashMap, +}; -pub struct PrecedenceVisitor { precedence: HashMap } +pub struct PrecedenceVisitor { + precedence: HashMap, +} impl MutVisitor for PrecedenceVisitor { fn visit_expr(&mut self, expr: &mut TypedExpr) { walk_expr_mut(self, expr); match expr.expr { Expr::OpApply(..) => { - let mut temp = TypedExpr::new(Expr::Identifier(Name { uid: usize::max_value(), name: intern("") })); + let mut temp = TypedExpr::new(Expr::Identifier(Name { + uid: usize::max_value(), + name: intern(""), + })); ::std::mem::swap(&mut temp, expr); - temp = self.rewrite(Box::new(temp)); + temp = self.rewrite(temp.into()); ::std::mem::swap(&mut temp, expr); } - _ => () + _ => (), } } fn visit_module(&mut self, module: &mut Module) { for fixity in module.fixity_declarations.iter() { for op in fixity.operators.iter() { - self.precedence.insert(op.clone(), (fixity.precedence, fixity.assoc)); + self.precedence + .insert(op.clone(), (fixity.precedence, fixity.assoc)); } } walk_module_mut(self, module); } } impl PrecedenceVisitor { - - pub fn new() -> PrecedenceVisitor { - let mut map = HashMap::new(); - map.insert(Name { uid: 0, name: intern(":") }, (5, Assoc::Right)); - PrecedenceVisitor { precedence: map } + pub fn new() -> Self { + Self { + precedence: [(":".into(), (5, Assoc::Right))].into_iter().collect(), + } } fn get_precedence(&self, name: &Name) -> (isize, Assoc) { - self.precedence.get(name) + self.precedence + .get(name) .map(|x| *x) .unwrap_or_else(|| (9, Assoc::Left)) } - + ///Takes a operator expression the is in the form (1 + (2 * (3 - 4))) and rewrites it using the ///operators real precedences fn rewrite(&self, mut input: Box>) -> TypedExpr { @@ -51,57 +61,64 @@ impl PrecedenceVisitor { let rhs = expr_stack.pop().unwrap(); let lhs = expr_stack.pop().unwrap(); let loc = lhs.location; - expr_stack.push(Box::new(TypedExpr::with_location(Expr::OpApply(lhs, op, rhs), loc))); + expr_stack.push(Box::new(TypedExpr::with_location( + Expr::OpApply(lhs, op, rhs), + loc, + ))); } - let mut expr_stack = Vec::new(); - let mut op_stack = Vec::new(); + let mut expr_stack = vec![]; + let mut op_stack = vec![]; loop { //FIXME should destructure instead of clone - let TypedExpr { typ, location, expr } = (*input).clone(); + let TypedExpr { + typ, + location, + expr, + } = (*input).clone(); match expr { Expr::OpApply(l, op, r) => { expr_stack.push(l); input = r; loop { - match op_stack.last().map(|x| *x) { - Some(previous_op) => { - let (op_prec, op_assoc) = self.get_precedence(&op); - let (prev_prec, prev_assoc) = self.get_precedence(&previous_op); - if op_prec > prev_prec { - op_stack.push(op); - break - } - else if op_prec == prev_prec { - match (op_assoc, prev_assoc) { - (Assoc::Left, Assoc::Left) => { - reduce(&mut expr_stack, &mut op_stack); - } - (Assoc::Right, Assoc::Right) => { - debug!("Shift op {:?}", op); - op_stack.push(op); - break - } - _ => panic!("Syntax error: mismatched associativity") + if let Some(previous_op) = op_stack.last() { + let (op_prec, op_assoc) = self.get_precedence(&op); + let (prev_prec, prev_assoc) = self.get_precedence(&previous_op); + if op_prec > prev_prec { + op_stack.push(op); + break; + } else if op_prec == prev_prec { + match (op_assoc, prev_assoc) { + (Assoc::Left, Assoc::Left) => { + reduce(&mut expr_stack, &mut op_stack); } + (Assoc::Right, Assoc::Right) => { + debug!("Shift op {:?}", op); + op_stack.push(op); + break; + } + _ => panic!("Syntax error: mismatched associativity"), } - else { - reduce(&mut expr_stack, &mut op_stack); - } - } - None => { - op_stack.push(op); - break + } else { + reduce(&mut expr_stack, &mut op_stack); } + } else { + op_stack.push(op); + break; } } } rhs => { - let mut result = TypedExpr { typ: typ, location: location, expr: rhs }; - while op_stack.len() != 0 { - assert!(expr_stack.len() >= 1); - let lhs = expr_stack.pop().unwrap(); + let mut result = TypedExpr { + typ, + location, + expr: rhs, + }; + while let Some(lhs) = expr_stack.pop() { let op = op_stack.pop().unwrap(); - result = TypedExpr::with_location(Expr::OpApply(lhs, op, Box::new(result)), location); + result = TypedExpr::with_location( + Expr::OpApply(lhs, op, result.into()), + location, + ); } return result; } @@ -112,51 +129,76 @@ impl PrecedenceVisitor { #[cfg(test)] mod tests { - use crate::parser::*; - use crate::module::*; - use crate::interner::intern; - use crate::typecheck::*; - use crate::infix::PrecedenceVisitor; - use crate::renamer::tests::{rename_expr, rename_modules}; + use crate::{ + infix::PrecedenceVisitor, + interner::intern, + module::*, + parser::*, + renamer::tests::{ + rename_expr, + rename_modules, + }, + typecheck::*, + }; #[test] - fn operator_precedence() - { + fn operator_precedence() { let m = parse_string( -r"import Prelude -test = 3 * 4 - 5 * 6").unwrap(); + r"import Prelude +test = 3 * 4 - 5 * 6", + ) + .unwrap(); let mut modules = rename_modules(m); let mut v = PrecedenceVisitor::new(); for module in modules.iter_mut() { v.visit_module(module); } - assert_eq!(modules.last().unwrap().bindings[0].matches, Match::Simple(rename_expr(op_apply( - op_apply(number(3), intern("*"), number(4)), - intern("-"), - op_apply(number(5), intern("*"), number(6)))))); + assert_eq!( + modules.last().unwrap().bindings[0].matches, + Match::Simple(rename_expr(op_apply( + op_apply(number(3), intern("*"), number(4)), + intern("-"), + op_apply(number(5), intern("*"), number(6)) + ))) + ); } #[test] - fn operator_precedence_parens() - { + fn operator_precedence_parens() { let m = parse_string( -r"import Prelude -test = 3 * 4 * (5 - 6)").unwrap(); + r"import Prelude +test = 3 * 4 * (5 - 6)", + ) + .unwrap(); let mut modules = rename_modules(m); let mut v = PrecedenceVisitor::new(); for module in modules.iter_mut() { v.visit_module(module); } - assert_eq!(modules.last().unwrap().bindings[0].matches, Match::Simple(rename_expr(op_apply( - op_apply(number(3), intern("*"), number(4)), - intern("*"), - paren(op_apply(number(5), intern("-"), number(6))))))); + assert_eq!( + modules.last().unwrap().bindings[0].matches, + Match::Simple(rename_expr(op_apply( + op_apply(number(3), intern("*"), number(4)), + intern("*"), + paren(op_apply(number(5), intern("-"), number(6))) + ))) + ); } #[test] fn rewrite_operators() { - let mut expr = rename_expr(op_apply(number(1), intern("*"), op_apply(number(2), intern("+"), number(3)))); + let mut expr = rename_expr(op_apply( + number(1), + intern("*"), + op_apply(number(2), intern("+"), number(3)), + )); PrecedenceVisitor::new().visit_expr(&mut expr); - assert_eq!(expr, rename_expr(op_apply(op_apply(number(1), intern("*"), number(2)), intern("+"), number(3)))); + assert_eq!( + expr, + rename_expr(op_apply( + op_apply(number(1), intern("*"), number(2)), + intern("+"), + number(3) + )) + ); } - } diff --git a/src/interner.rs b/src/interner.rs index 5a7d0b7..54e5073 100644 --- a/src/interner.rs +++ b/src/interner.rs @@ -1,42 +1,39 @@ -use std::collections::HashMap; -use std::rc::Rc; -use std::cell::RefCell; -use std::ops::Deref; -use std::fmt; +use std::{ + cell::RefCell, + collections::HashMap, + fmt, + ops::Deref, + rc::Rc, +}; #[derive(Eq, PartialEq, Clone, Copy, Default, Hash, Debug)] pub struct InternedStr(usize); pub struct Interner { indexes: HashMap, - strings: Vec + strings: Vec, } impl Interner { - - pub fn new() -> Interner { - Interner { indexes: HashMap::new(), strings: Vec::new() } + pub fn new() -> Self { + Self { + indexes: HashMap::new(), + strings: vec![], + } } pub fn intern(&mut self, s: &str) -> InternedStr { - match self.indexes.get(s).map(|x| *x) { - Some(index) => InternedStr(index), - None => { - let index = self.strings.len(); - self.indexes.insert(s.to_string(), index); - self.strings.push(s.to_string()); - InternedStr(index) - } - } + InternedStr(self.indexes.get(s).cloned().unwrap_or_else(|| { + let index = self.strings.len(); + self.indexes.insert(s.to_string(), index); + self.strings.push(s.to_string()); + index + })) } pub fn get_str<'a>(&'a self, InternedStr(i): InternedStr) -> &'a str { - if i < self.strings.len() { - &*self.strings[i] - } - else { - panic!("Invalid InternedStr {:?}", i) - } + assert!(i < self.strings.len(), "Invalid InternedStr {:?}", i); + &self.strings[i] } } @@ -47,9 +44,21 @@ pub fn get_local_interner() -> Rc> { } pub fn intern(s: &str) -> InternedStr { - let i = get_local_interner(); - let mut i = i.borrow_mut(); - i.intern(s) + s.into() +} + +impl From<&str> for InternedStr { + fn from(s: &str) -> Self { + let i = get_local_interner(); + let mut i = i.borrow_mut(); + i.intern(s) + } +} + +impl PartialEq for InternedStr { + fn eq(&self, other: &str) -> bool { + self == &intern(other) + } } impl Deref for InternedStr { diff --git a/src/lambda_lift.rs b/src/lambda_lift.rs index 0dfa33c..8a10619 100644 --- a/src/lambda_lift.rs +++ b/src/lambda_lift.rs @@ -1,9 +1,19 @@ -use std::collections::HashMap; -use std::collections::hash_map::Entry; -use crate::core::*; -use crate::core::Expr::*; -use crate::renamer::NameSupply; -use crate::renamer::typ::*; +use { + crate::{ + core::{ + Expr::*, + *, + }, + renamer::{ + typ::*, + NameSupply, + }, + }, + std::collections::{ + hash_map::Entry, + HashMap, + }, +}; pub type TypeAndStr = Id; @@ -12,7 +22,7 @@ pub fn do_lambda_lift(module: Module) -> Module { } struct FreeVariables { - name_supply: NameSupply + name_supply: NameSupply, } fn each_pattern_variables(pattern: &Pattern, f: &mut dyn FnMut(&Name)) { @@ -23,144 +33,161 @@ fn each_pattern_variables(pattern: &Pattern, f: &mut dyn FnMut(&Name)) { (*f)(&p.name); } } - _ => () + _ => (), } } - impl FreeVariables { - -//Walks through an expression and notes all the free variables and for each lambda, adds the -//free variables to its arguments and performs an immediate application -//@variables All the local variables in scope, values are how many of the name there exists -//@free_vars The free variables for the returned expression -fn free_variables(&mut self, variables: &mut HashMap, free_vars: &mut HashMap, expr: &mut Expr) { - match *expr { - Identifier(ref mut i) => { - //If the identifier is a local, add it to the free variables - if variables.get(&i.name).map(|x| *x > 0).unwrap_or(false) { - free_vars.insert(i.name.clone(), i.clone()); + //Walks through an expression and notes all the free variables and for each lambda, adds the + //free variables to its arguments and performs an immediate application + //@variables All the local variables in scope, values are how many of the name there exists + //@free_vars The free variables for the returned expression + fn free_variables( + &mut self, + variables: &mut HashMap, + free_vars: &mut HashMap, + expr: &mut Expr, + ) { + match *expr { + Identifier(ref mut i) => { + //If the identifier is a local, add it to the free variables + if variables.get(&i.name).map(|x| *x > 0).unwrap_or(false) { + free_vars.insert(i.name.clone(), i.clone()); + } } - } - Apply(ref mut func, ref mut arg) => { - self.free_variables(variables, free_vars, &mut **func); - self.free_variables(variables, free_vars, &mut **arg); - } - Lambda(ref mut arg, ref mut body) => { - match variables.entry(arg.name.clone()) { - Entry::Vacant(entry) => { entry.insert(1); } - Entry::Occupied(mut entry) => *entry.get_mut() += 1 + Apply(ref mut func, ref mut arg) => { + self.free_variables(variables, free_vars, func); + self.free_variables(variables, free_vars, arg); } - self.free_variables(variables, free_vars, &mut **body); - *variables.get_mut(&arg.name).unwrap() -= 1; - free_vars.remove(&arg.name);//arg was not actually a free variable - } - Let(ref mut bindings, ref mut expr) => { - for bind in bindings.iter() { - match variables.entry(bind.name.name.clone()) { - Entry::Vacant(entry) => { entry.insert(1); } - Entry::Occupied(mut entry) => *entry.get_mut() += 1 + Lambda(ref mut arg, ref mut body) => { + match variables.entry(arg.name.clone()) { + Entry::Vacant(entry) => { + entry.insert(1); + } + Entry::Occupied(mut entry) => *entry.get_mut() += 1, } + self.free_variables(variables, free_vars, body); + *variables.get_mut(&arg.name).unwrap() -= 1; + free_vars.remove(&arg.name); //arg was not actually a free variable } - let mut free_vars2 = HashMap::new(); - for bind in bindings.iter_mut() { - free_vars2.clear(); - self.free_variables(variables, &mut free_vars2, &mut bind.expression); - //free_vars2 is the free variables for this binding - for (k, v) in free_vars2.iter() { - free_vars.insert(k.clone(), v.clone()); + Let(ref mut bindings, ref mut expr) => { + for bind in bindings.iter() { + match variables.entry(bind.name.name.clone()) { + Entry::Vacant(entry) => { + entry.insert(1); + } + Entry::Occupied(mut entry) => *entry.get_mut() += 1, + } } - self.abstract_(&free_vars2, &mut bind.expression); - } - self.free_variables(variables, free_vars, &mut **expr); - for bind in bindings.iter() { - *variables.get_mut(&bind.name.name).unwrap() -= 1; - free_vars.remove(&bind.name.name); - } - } - Case(ref mut expr, ref mut alts) => { - self.free_variables(variables, free_vars, &mut **expr); - for alt in alts.iter_mut() { - each_pattern_variables(&alt.pattern, &mut |name| { - match variables.entry(name.clone()) { - Entry::Vacant(entry) => { entry.insert(1); } - Entry::Occupied(mut entry) => *entry.get_mut() += 1 + let mut free_vars2 = HashMap::new(); + for bind in bindings.iter_mut() { + free_vars2.clear(); + self.free_variables(variables, &mut free_vars2, &mut bind.expression); + //free_vars2 is the free variables for this binding + for (k, v) in free_vars2.iter() { + free_vars.insert(k.clone(), v.clone()); } - }); - self.free_variables(variables, free_vars, &mut alt.expression); - each_pattern_variables(&alt.pattern, &mut |name| { - *variables.get_mut(name).unwrap() -= 1; - free_vars.remove(name);//arg was not actually a free variable - }); + self.abstract_(&free_vars2, &mut bind.expression); + } + self.free_variables(variables, free_vars, expr); + for bind in bindings.iter() { + *variables.get_mut(&bind.name.name).unwrap() -= 1; + free_vars.remove(&bind.name.name); + } + } + Case(ref mut expr, ref mut alts) => { + self.free_variables(variables, free_vars, expr); + for alt in alts.iter_mut() { + each_pattern_variables(&alt.pattern, &mut |name| match variables + .entry(name.clone()) + { + Entry::Vacant(entry) => { + entry.insert(1); + } + Entry::Occupied(mut entry) => *entry.get_mut() += 1, + }); + self.free_variables(variables, free_vars, &mut alt.expression); + each_pattern_variables(&alt.pattern, &mut |name| { + *variables.get_mut(name).unwrap() -= 1; + free_vars.remove(name); //arg was not actually a free variable + }); + } } + _ => (), } - _ => () } -} -///Adds the free variables, if any, to the expression -fn abstract_(&mut self, free_vars: &HashMap, input_expr: &mut Expr) { - if free_vars.len() != 0 { - let mut temp = Literal(LiteralData { typ: Type::new_var(self.name_supply.from_str("a").name), value: Integral(0) }); - ::std::mem::swap(&mut temp, input_expr); - let mut e = { - let mut rhs = temp; - let mut typ = rhs.get_type().clone(); + ///Adds the free variables, if any, to the expression + fn abstract_( + &mut self, + free_vars: &HashMap, + input_expr: &mut Expr, + ) { + if !free_vars.is_empty() { + let mut temp = Literal(LiteralData { + typ: Type::new_var(self.name_supply.from_str("a").name), + value: Integral(0), + }); + ::std::mem::swap(&mut temp, input_expr); + let mut e = { + let mut rhs = temp; + let mut typ = rhs.get_type().clone(); + for (_, var) in free_vars.iter() { + rhs = Lambda(var.clone(), rhs.into()); + typ = function_type_(var.get_type().clone(), typ); + } + let id = Id::new(self.name_supply.from_str("#sc"), typ.clone(), vec![]); + let bind = Binding { + name: id.clone(), + expression: rhs, + }; + Let(vec![bind], Identifier(id).into()) + }; for (_, var) in free_vars.iter() { - rhs = Lambda(var.clone(), Box::new(rhs)); - typ = function_type_(var.get_type().clone(), typ); + e = Apply(e.into(), Identifier(var.clone()).into()); } - let id = Id::new(self.name_supply.from_str("#sc"), typ.clone(), Vec::new()); - let bind = Binding { - name: id.clone(), - expression: rhs - }; - Let(vec![bind], Box::new(Identifier(id))) - }; - for (_, var) in free_vars.iter() { - e = Apply(Box::new(e), Box::new(Identifier(var.clone()))); + *input_expr = e } - *input_expr = e } } -} ///Lifts all lambdas in the module to the top level of the program pub fn lift_lambdas(mut module: Module) -> Module { use crate::core::mutable::*; - struct LambdaLifter { out_lambdas: Vec> } - impl Visitor for LambdaLifter { + struct LambdaLifter { + out_lambdas: Vec>, + } + impl Visitor for LambdaLifter { fn visit_expr(&mut self, expr: &mut Expr) { match *expr { Let(ref mut bindings, ref mut body) => { - let mut new_binds = Vec::new(); + let mut new_binds = vec![]; let mut bs = vec![]; ::std::mem::swap(&mut bs, bindings); for mut bind in bs.into_iter() { - let is_lambda = match bind.expression { - Lambda(..) => true, - _ => false - }; + let is_lambda = matches!(bind.expression, Lambda(..)); walk_expr(self, &mut bind.expression); if is_lambda { self.out_lambdas.push(bind); - } - else { + } else { new_binds.push(bind); } } *bindings = new_binds; - self.visit_expr(&mut **body); + self.visit_expr(body); } - _ => walk_expr(self, expr) + _ => walk_expr(self, expr), } remove_empty_let(expr); } } - let mut visitor = LambdaLifter { out_lambdas: Vec::new() }; + let mut visitor = LambdaLifter { + out_lambdas: vec![], + }; visitor.visit_module(&mut module); - let mut temp = Vec::new(); + let mut temp = vec![]; ::std::mem::swap(&mut temp, &mut module.bindings); - let vec : Vec> = temp.into_iter() + let vec: Vec> = temp + .into_iter() .chain(visitor.out_lambdas.into_iter()) .collect(); module.bindings = vec; @@ -172,14 +199,13 @@ fn remove_empty_let(expr: &mut Expr) { ::std::mem::swap(&mut temp, expr); temp = match temp { Let(bindings, e) => { - if bindings.len() == 0 { + if bindings.is_empty() { *e - } - else { + } else { Let(bindings, e) } } - temp => temp + temp => temp, }; ::std::mem::swap(&mut temp, expr); ::std::mem::forget(temp); @@ -190,30 +216,41 @@ pub fn abstract_module(mut module: Module) -> Module { use crate::core::mutable::*; impl Visitor for FreeVariables { fn visit_binding(&mut self, bind: &mut Binding) { - let mut variables = HashMap::new(); - let mut free_vars = HashMap::new(); - self.free_variables(&mut variables, &mut free_vars, &mut bind.expression); + self.free_variables( + &mut <_>::default(), + &mut <_>::default(), + &mut bind.expression, + ); } } - let mut this = FreeVariables { name_supply: NameSupply::new() }; + let mut this = + FreeVariables { + name_supply: NameSupply::new(), + }; this.visit_module(&mut module); module } #[cfg(test)] mod tests { - use test::Bencher; - use crate::interner::*; - use crate::lambda_lift::*; - use std::collections::HashSet; - use crate::parser::Parser; - use crate::core::ref_::*; - use crate::core::translate::translate_module; - use crate::renamer::tests::rename_module; - use crate::typecheck::TypeEnvironment; + use { + crate::{ + core::{ + ref_::*, + translate::translate_module, + }, + interner::*, + lambda_lift::*, + parser::Parser, + renamer::tests::rename_module, + typecheck::TypeEnvironment, + }, + std::collections::HashSet, + test::Bencher, + }; struct CheckUniques { - found: HashSet + found: HashSet, } impl Visitor for CheckUniques { @@ -226,7 +263,7 @@ mod tests { &Lambda(ref i, _) => { assert!(self.found.insert(i.clone())); } - _ => () + _ => (), } walk_expr(self, expr) } @@ -234,9 +271,12 @@ mod tests { #[test] fn all_uniques() { - let mut visitor = CheckUniques { found: HashSet::new() }; + let mut visitor = + CheckUniques { + found: HashSet::new(), + }; let mut parser = Parser::new( -r"add x y = 2 + r"add x y = 2 test = 3.14 test2 x = let @@ -244,39 +284,41 @@ test2 x = f x = let g y = add x (f y) in add x test - in f x".chars()); + in f x" + .chars(), + ); let module = translate_module(rename_module(parser.module().unwrap())); visitor.visit_module(&module); } fn check_args(expr: &Expr, args: &[InternedStr]) -> bool { match expr { - &Lambda(ref arg, ref body) => arg.name.name == args[0] && check_args(&**body, &args[1..]), - _ => args.len() == 0 + &Lambda(ref arg, ref body) => arg.name.name == args[0] && check_args(body, &args[1..]), + _ => args.is_empty(), } } struct CheckAbstract { - count: isize + count: isize, } - + fn get_let<'a>(expr: &'a Expr, args: &mut Vec) -> &'a Expr { match expr { &Apply(ref f, ref arg) => { match **arg { Identifier(ref i) => args.push(i.name.name), - _ => panic!("Expected identifier as argument") + _ => panic!("Expected identifier as argument"), } - get_let(&**f, args) + get_let(f, args) } - _ => expr + _ => expr, } } impl Visitor for CheckAbstract { fn visit_binding(&mut self, bind: &Binding) { if intern("f") == bind.name.name.name { - let mut args = Vec::new(); + let mut args = vec![]; match get_let(&bind.expression, &mut args) { &Let(ref binds, ref body) => { //Push the argument of the function itself @@ -284,19 +326,18 @@ test2 x = assert!(check_args(&binds[0].expression, args.as_ref())); assert_eq!(Identifier(binds[0].name.clone()), **body); } - _ => assert!(false, "Expected Let, found {:?}", bind.expression) + _ => assert!(false, "Expected Let, found {:?}", bind.expression), } self.count += 1; - } - else if intern("g") == bind.name.name.name { - let mut args = Vec::new(); + } else if intern("g") == bind.name.name.name { + let mut args = vec![]; match get_let(&bind.expression, &mut args) { &Let(ref binds, ref body) => { args.push(intern("y")); assert!(check_args(&binds[0].expression, args.as_ref())); assert_eq!(Identifier(binds[0].name.clone()), **body); } - _ => assert!(false, "Expected Let") + _ => assert!(false, "Expected Let"), } self.count += 1; } @@ -308,7 +349,7 @@ test2 x = fn all_free_vars() { let mut visitor = CheckAbstract { count: 0 }; let mut parser = Parser::new( -r"add x y = 2 + r"add x y = 2 test = 3.14 test2 x = let @@ -316,7 +357,9 @@ test2 x = f x = let g y = add x (f y) in add x test - in f x".chars()); + in f x" + .chars(), + ); let mut module = rename_module(parser.module().unwrap()); TypeEnvironment::new() .typecheck_module(&mut module) @@ -329,11 +372,11 @@ test2 x = struct NoLambdas; - impl Visitor for NoLambdas { + impl Visitor for NoLambdas { fn visit_expr(&mut self, expr: &Expr) { match expr { &Lambda(..) => assert!(false, "Found lambda in expression"), - _ => () + _ => (), } walk_expr(self, expr); } @@ -342,14 +385,14 @@ test2 x = fn no_local_lambdas() { fn skip_lambdas(expr: &Expr) -> &Expr { match expr { - &Lambda(_, ref body) => skip_lambdas(&**body), - _ => expr + &Lambda(_, ref body) => skip_lambdas(body), + _ => expr, } } let mut visitor = NoLambdas; let mut parser = Parser::new( -r"add x y = 2 + r"add x y = 2 test = 3.14 test2 x = let @@ -357,7 +400,9 @@ test2 x = f x = let g y = add x (f y) in add x test - in f x".chars()); + in f x" + .chars(), + ); let m = translate_module(rename_module(parser.module().unwrap())); let module = lift_lambdas(m); for bind in module.bindings.iter() { @@ -367,17 +412,21 @@ test2 x = #[bench] fn bench(b: &mut Bencher) { - use std::fs::File; - use std::io::Read; - use std::path::Path; - use crate::typecheck::test::do_typecheck; + use { + crate::typecheck::test::do_typecheck, + std::{ + fs::File, + io::Read, + path::Path, + }, + }; let path = &Path::new("Prelude.hs"); let mut contents = ::std::string::String::new(); - File::open(path).and_then(|mut f| f.read_to_string(&mut contents)).unwrap(); + File::open(path) + .and_then(|mut f| f.read_to_string(&mut contents)) + .unwrap(); let module = do_typecheck(&contents); - b.iter(|| { - do_lambda_lift(translate_module(module.clone())) - }); + b.iter(|| do_lambda_lift(translate_module(module.clone()))); } } diff --git a/src/lexer.rs b/src/lexer.rs index 9bda7c0..86b914c 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -1,46 +1,50 @@ -use std::fmt; -use std::collections::VecDeque; -use std::iter::Peekable; -use std::rc::Rc; -use std::cell::RefCell; -use crate::interner::*; +use { + crate::interner::*, + std::{ + cell::RefCell, + collections::VecDeque, + fmt, + iter::Peekable, + rc::Rc, + }, +}; use self::TokenEnum::*; #[derive(Clone, Copy, Eq, PartialEq, Debug)] pub enum TokenEnum { - EOF, - NAME, - OPERATOR, - NUMBER, - FLOAT, + EOF, + NAME, + OPERATOR, + NUMBER, + FLOAT, STRING, CHAR, - LPARENS, - RPARENS, - LBRACKET, - RBRACKET, - LBRACE, - RBRACE, - INDENTSTART, - INDENTLEVEL, - COMMA, + LPARENS, + RPARENS, + LBRACKET, + RBRACKET, + LBRACE, + RBRACE, + INDENTSTART, + INDENTLEVEL, + COMMA, PIPE, CONTEXTARROW, - EQUALSSIGN, - SEMICOLON, - MODULE, - CLASS, - INSTANCE, - WHERE, - LET, - IN, - CASE, - OF, - ARROW, + EQUALSSIGN, + SEMICOLON, + MODULE, + CLASS, + INSTANCE, + WHERE, + LET, + IN, + CASE, + OF, + ARROW, LARROW, - TYPEDECL, - DATA, + TYPEDECL, + DATA, NEWTYPE, LAMBDA, DO, @@ -51,34 +55,38 @@ pub enum TokenEnum { DERIVING, IF, THEN, - ELSE + ELSE, } -#[derive(Clone, Copy, PartialEq, Debug)] +#[derive(Clone, Copy, PartialEq, Debug, Default)] pub struct Location { - pub column : isize, - pub row : isize, - pub absolute : isize + pub column: isize, + pub row: isize, + pub absolute: isize, } impl Location { - pub fn eof() -> Location { - Location { column: -1, row: -1, absolute: -1 } + pub fn eof() -> Self { + Self { + column: -1, + row: -1, + absolute: -1, + } } } #[derive(Clone, Debug)] pub struct Located { pub location: Location, - pub node: T + pub node: T, } -impl PartialEq for Located { +impl PartialEq for Located { fn eq(&self, o: &Located) -> bool { self.node == o.node } } - -impl fmt::Display for Located { + +impl fmt::Display for Located { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}: {}", self.location, self.node) } @@ -92,33 +100,41 @@ impl fmt::Display for Location { #[derive(Clone, Debug)] pub struct Token { - pub token : TokenEnum, - pub value : InternedStr, - pub location : Location + pub token: TokenEnum, + pub value: InternedStr, + pub location: Location, } impl Token { - fn eof() -> Token { - Token { token : EOF, value : intern(""), location : Location { column : -1, row : -1, absolute : -1} } + fn eof() -> Self { + Self { + token: EOF, + value: intern(""), + location: Location::eof(), + } } - fn new(interner: &Rc>, token : TokenEnum, value : &str, loc : Location) -> Token { - Token { token: token, value: (**interner).borrow_mut().intern(value), location: loc } + fn new(interner: &Rc>, token: TokenEnum, value: &str, loc: Location) -> Self { + Self { + token, + value: interner.borrow_mut().intern(value), + location: loc, + } } #[cfg(test)] - fn new_(token : TokenEnum, value : &str) -> Token { - Token::new(&get_local_interner(), token, value, Location { column : -1, row : -1, absolute : -1 }) + fn new_(token: TokenEnum, value: &str) -> Self { + Self::new(&get_local_interner(), token, value, Location::eof()) } } impl PartialEq for Token { - fn eq(&self, rhs : &Token) -> bool { + fn eq(&self, rhs: &Self) -> bool { self.token == rhs.token && self.value == rhs.value } } ///Takes a string which can be an identifier or a keyword and returns the correct TokenEnum -fn name_or_keyword(tok : &str) -> TokenEnum { +fn name_or_keyword(tok: &str) -> TokenEnum { match tok { "module" => MODULE, "class" => CLASS, @@ -140,49 +156,45 @@ fn name_or_keyword(tok : &str) -> TokenEnum { "if" => IF, "then" => THEN, "else" => ELSE, - _ => NAME + _ => NAME, } } ///Returns whether the character is a haskell operator -fn is_operator(first_char : char) -> bool { - match first_char { - '+' | '-' | '*' | '/' | '.' | '$' | - ':' | '=' | '<' | '>' | '|' | '&' | '!' => true, - _ => false - } +fn is_operator(first_char: char) -> bool { + matches!( + first_char, + '+' | '-' | '*' | '/' | '.' | '$' | ':' | '=' | '<' | '>' | '|' | '&' | '!' + ) } -pub struct Lexer> { +pub struct Lexer> { ///The input which the lexer processes - input : Peekable, + input: Peekable, ///The current location of the lexer - location : Location, + location: Location, ///All the current unprocessed tokens stored on a stack - unprocessed_tokens : Vec, + unprocessed_tokens: Vec, ///The token buffer which contains the last n produced tokens. - tokens : VecDeque, + tokens: VecDeque, ///A stack which contains the indentation levels of automatically inserted '{' - indent_levels : Vec, + indent_levels: Vec, ///The offset into the token buffer at which the current token is at - offset : usize, + offset: usize, ///The string interner, cached here for efficency - interner: Rc> + interner: Rc>, } - -impl > Lexer { - +impl> Lexer { ///Constructs a new lexer with a default sized token buffer and the local string interner - pub fn new(input : Stream) -> Lexer { - let start = Location { column : 0, row : 0, absolute : 0}; - Lexer { - input : input.peekable(), - location : start, - unprocessed_tokens : Vec::new(), - tokens : VecDeque::with_capacity(20), - indent_levels : Vec::new(), - offset : 0, - interner: get_local_interner() + pub fn new(input: Stream) -> Self { + Self { + input: input.peekable(), + location: <_>::default(), + unprocessed_tokens: vec![], + tokens: VecDeque::with_capacity(20), + indent_levels: vec![], + offset: 0, + interner: get_local_interner(), } } ///Returns a new token with some special rules necessary for the parsing of the module declaration @@ -195,12 +207,14 @@ impl > Lexer { let loc = self.unprocessed_tokens.last().unwrap().location; if new_token != LBRACE && new_token != MODULE { - self.unprocessed_tokens.push(Token::new(&self.interner, INDENTSTART, "{n}", loc)); + self.unprocessed_tokens + .push(Token::new(&self.interner, INDENTSTART, "{n}", loc)); } if newline { - self.unprocessed_tokens.push(Token::new(&self.interner, INDENTLEVEL, "", loc)); + self.unprocessed_tokens + .push(Token::new(&self.interner, INDENTLEVEL, "", loc)); } - + self.layout_independent_token(); self.current() } @@ -212,33 +226,29 @@ impl > Lexer { } &self.tokens[self.tokens.len() - self.offset] } - + ///Returns the next token in the lexer pub fn next<'a>(&'a mut self) -> &'a Token { if self.offset > 0 { //backtrack has been used so simply return the next token from the buffer self.offset -= 1; - match self.tokens.get(self.tokens.len() - 1 - self.offset) { - Some(token) => token, - None => panic!("Impossible empty tokens stream") - } - } - else if self.unprocessed_tokens.len() > 0 { + self.tokens + .get(self.tokens.len() - 1 - self.offset) + .expect("Impossible empty tokens stream") + } else if !self.unprocessed_tokens.is_empty() { //Some previous call to next produced more than one token so process those first self.layout_independent_token(); self.tokens.back().unwrap() - } - else { + } else { self.next_token() } } ///Returns a reference to the current token pub fn current<'a>(&'a self) -> &'a Token { - match self.tokens.get(self.tokens.len() - 1 - self.offset) { - Some(token) => token, - None => panic!("Attempted to access Lexer::current() on when tokens is empty") - } + self.tokens + .get(self.tokens.len() - 1 - self.offset) + .expect("Attempted to access Lexer::current() on when tokens is empty") } ///Moves the lexer back one token @@ -249,7 +259,7 @@ impl > Lexer { ///Returns true if the lexer is still valid (it has not hit EOF) pub fn valid(&self) -> bool { - self.offset > 0 || match self.tokens.back() { None => true, Some(x) => x.token != EOF } + self.offset > 0 || self.tokens.back().map(|x| x.token != EOF).unwrap_or(true) } ///Peeks at the next character in the input @@ -259,44 +269,36 @@ impl > Lexer { ///Reads a character from the input and increments the current position fn read_char(&mut self) -> Option { - match self.input.next() { - Some(c) => { - self.location.absolute += 1; - self.location.column += 1; - if c == '\n' || c == '\r' { - self.location.column = 0; - self.location.row += 1; - //If this is a \n\r line ending skip the next char without increasing the location - let x = '\n'; - if c == '\r' && self.input.peek() == Some(&x) { - self.input.next(); - } + self.input.next().map(|c| { + self.location.absolute += 1; + self.location.column += 1; + if matches!(c, '\n' | '\r') { + self.location.column = 0; + self.location.row += 1; + //If this is a \n\r line ending skip the next char without increasing the location + if c == '\r' && self.input.peek() == Some(&'\n') { + self.input.next(); } - Some(c) } - None => None - } + c + }) } ///Scans digits into a string fn scan_digits(&mut self) -> String { let mut result = String::new(); - loop { - match self.peek_char() { - Some(x) => { - if !x.is_digit(10) { - break; - } - self.read_char(); - result.push(x) - } - None => break + + while let Some(x) = self.peek_char() { + if !x.is_digit(10) { + break; } + self.read_char(); + result.push(x) } result } ///Scans a number, float or isizeeger and returns the appropriate token - fn scan_number(&mut self, c : char, location : Location) -> Token { + fn scan_number(&mut self, c: char, location: Location) -> Token { let mut number = c.to_string(); number.push_str(self.scan_digits().as_ref()); let mut token = NUMBER; @@ -307,26 +309,26 @@ impl > Lexer { number.push('.'); number.push_str(self.scan_digits().as_ref()); } - _ => () + _ => (), } Token::new(&self.interner, token, number.as_ref(), location) } ///Scans an identifier or a keyword fn scan_identifier(&mut self, c: char, start_location: Location) -> Token { let mut result = c.to_string(); - loop { - match self.peek_char() { - Some(ch) => { - if !ch.is_alphanumeric() && ch != '_' { - break; - } - self.read_char(); - result.push(ch); - } - None => break + while let Some(ch) = self.peek_char() { + if !ch.is_alphanumeric() && ch != '_' { + break; } + self.read_char(); + result.push(ch); } - return Token::new(&self.interner, name_or_keyword(result.as_ref()), result.as_ref(), start_location); + Token::new( + &self.interner, + name_or_keyword(result.as_ref()), + result.as_ref(), + start_location, + ) } ///Returns the next token but if it is not an '}' it will attempt to insert a '}' automatically @@ -335,14 +337,19 @@ impl > Lexer { //before the current token and set the current token to the '}' //Credits to the HUGS source code for the solution if self.next().token != RBRACE { - if self.indent_levels.len() != 0 { + if !self.indent_levels.is_empty() { //L (t:ts) (m:ms) = } : (L (t:ts) ms) if m /= 0 and parse-error(t) let m = *self.indent_levels.last().unwrap(); - if m != 0 {//If not a explicit '}' - debug!("ParseError on token {:?}, inserting }}", self.current().token); + if m != 0 { + //If not a explicit '}' + debug!( + "ParseError on token {:?}, inserting }}", + self.current().token + ); self.indent_levels.pop(); let loc = self.current().location; - self.tokens.push_back(Token::new(&self.interner, RBRACE, "}", loc)); + self.tokens + .push_back(Token::new(&self.interner, RBRACE, "}", loc)); let len = self.tokens.len(); self.tokens.swap(len - 2, len - 1); self.backtrack(); @@ -351,7 +358,7 @@ impl > Lexer { } self.current() } - + ///Scans and returns the next token from the input stream, taking into account the indentation rules fn next_token<'a>(&'a mut self) -> &'a Token { let mut newline = false; @@ -362,18 +369,20 @@ impl > Lexer { if new_token != LBRACE { match self.tokens.back() { Some(tok) => { - if tok.token == LET || tok.token == WHERE || tok.token == OF || tok.token == DO { + if tok.token == LET || tok.token == WHERE || tok.token == OF || tok.token == DO + { let loc = self.unprocessed_tokens.last().unwrap().location; let indentstart = Token::new(&self.interner, INDENTSTART, "{n}", loc); self.unprocessed_tokens.push(indentstart); } } - None => () + None => (), } } if newline { let loc = self.unprocessed_tokens.last().unwrap().location; - self.unprocessed_tokens.push(Token::new(&self.interner, INDENTLEVEL, "", loc)); + self.unprocessed_tokens + .push(Token::new(&self.interner, INDENTLEVEL, "", loc)); } self.layout_independent_token(); self.tokens.back().unwrap() @@ -382,114 +391,135 @@ impl > Lexer { ///Looks at the next unprocessed token and applies the indentation rules on it ///and returns a token which is not affected by indentation fn layout_independent_token(&mut self) { - if self.unprocessed_tokens.len() > 0 { - let tok = self.unprocessed_tokens.last().unwrap().clone();//TODO dont use clone + //TODO dont use clone + if let Some(tok) = self.unprocessed_tokens.last().cloned() { match tok.token { INDENTLEVEL => { - if self.indent_levels.len() > 0 { + if let Some(m) = self.indent_levels.last().cloned() { //m:ms - let m = *self.indent_levels.last().unwrap(); //m == n if m == tok.location.column { debug!("Indents are same, inserted semicolon"); - self.tokens.push_back(Token::new(&self.interner, SEMICOLON, ";", tok.location)); + self.tokens.push_back(Token::new( + &self.interner, + SEMICOLON, + ";", + tok.location, + )); self.unprocessed_tokens.pop(); return; - } - else if tok.location.column < m { + } else if tok.location.column < m { //n < m //TODO debug!("n < m, insert }}"); self.indent_levels.pop(); - self.tokens.push_back(Token::new(&self.interner, RBRACE, "}", tok.location)); + self.tokens.push_back(Token::new( + &self.interner, + RBRACE, + "}", + tok.location, + )); return; } } self.unprocessed_tokens.pop(); - if self.unprocessed_tokens.len() == 0 { + if self.unprocessed_tokens.is_empty() { self.next_token(); return; - } - else { + } else { return self.layout_independent_token(); } } INDENTSTART => { //{n} token let n = tok.location.column; - if self.indent_levels.len() != 0 { + if !self.indent_levels.is_empty() { //m:ms let m = *self.indent_levels.last().unwrap(); if n > m { debug!("n > m + INDENTSTART, insert {{"); self.unprocessed_tokens.pop(); - self.tokens.push_back(Token::new(&self.interner, LBRACE, "{", tok.location)); + self.tokens.push_back(Token::new( + &self.interner, + LBRACE, + "{", + tok.location, + )); self.indent_levels.push(n); return; } } if n > 0 { - self.tokens.push_back(Token::new(&self.interner, LBRACE, "{", tok.location)); + self.tokens.push_back(Token::new( + &self.interner, + LBRACE, + "{", + tok.location, + )); self.unprocessed_tokens.pop(); self.indent_levels.push(n); return; } - self.tokens.push_back(Token::new(&self.interner, LBRACE, "{", tok.location)); - self.tokens.push_back(Token::new(&self.interner, RBRACE, "}", tok.location)); + self.tokens + .push_back(Token::new(&self.interner, LBRACE, "{", tok.location)); + self.tokens + .push_back(Token::new(&self.interner, RBRACE, "}", tok.location)); self.unprocessed_tokens.pop(); - self.unprocessed_tokens.push(Token::new(&self.interner, INDENTLEVEL, "", tok.location)); + self.unprocessed_tokens + .push(Token::new(&self.interner, INDENTLEVEL, "", tok.location)); self.offset += 1; return; } RBRACE => { - if self.indent_levels.len() > 0 && *self.indent_levels.last().unwrap() == 0 { - self.tokens.push_back(self.unprocessed_tokens.pop().unwrap()); + if !self.indent_levels.is_empty() && *self.indent_levels.last().unwrap() == 0 { + self.tokens + .push_back(self.unprocessed_tokens.pop().unwrap()); self.indent_levels.pop(); return; - } - else { - return;//parse-error + } else { + return; //parse-error } } LBRACE => { - self.tokens.push_back(self.unprocessed_tokens.pop().unwrap()); + self.tokens + .push_back(self.unprocessed_tokens.pop().unwrap()); self.indent_levels.push(0); return; } - _ => () + _ => (), } - self.tokens.push_back(self.unprocessed_tokens.pop().unwrap()); + self.tokens + .push_back(self.unprocessed_tokens.pop().unwrap()); return; - } - else { - if self.indent_levels.len() == 0 { + } else { + if self.indent_levels.is_empty() { //End of stream return; - } - else if *self.indent_levels.last().unwrap() != 0 { + } else if *self.indent_levels.last().unwrap() != 0 { //Keep pusing right brackets self.indent_levels.pop(); - self.tokens.push_back(Token::new(&self.interner, RBRACE, "}", self.location)); + self.tokens + .push_back(Token::new(&self.interner, RBRACE, "}", self.location)); return; } } } - + ///Scans the character stream for the next token ///Return EOF token if the token stream has ehas ended - fn next_indent_token(&mut self, newline : &mut bool) -> Token { + fn next_indent_token(&mut self, newline: &mut bool) -> Token { let mut c = ' '; //Skip all whitespace before the token while c.is_whitespace() { - match self.read_char() { - Some(x) => { - c = x; - if self.location.column == 0 {//newline detected - *newline = true; - } + if let Some(x) = self.read_char() { + c = x; + if self.location.column == 0 { + //newline detected + *newline = true; } - None => { return Token::eof() } + } else { + return Token::eof(); } } let start_location = self.location; @@ -498,73 +528,58 @@ impl > Lexer { //ie if its an operator then more operators will follow if is_operator(c) { let mut result = c.to_string(); - loop { - match self.peek_char() { - Some(ch) => { - if !is_operator(ch) { - break; - } - self.read_char(); - result.push(ch); - } - None => { break; } + + while let Some(ch) = self.peek_char() { + if !is_operator(ch) { + break; } + self.read_char(); + result.push(ch); } let tok = match result.as_ref() { - "=" => EQUALSSIGN, + "=" => EQUALSSIGN, "->" => ARROW, "<-" => LARROW, "::" => TYPEDECL, "=>" => CONTEXTARROW, - "|" => PIPE, - _ => OPERATOR + "|" => PIPE, + _ => OPERATOR, }; return Token::new(&self.interner, tok, result.as_ref(), start_location); - } - else if c.is_digit(10) { + } else if c.is_digit(10) { return self.scan_number(c, start_location); - } - else if c.is_alphabetic() || c == '_' { + } else if c.is_alphabetic() || c == '_' { return self.scan_identifier(c, start_location); - } - else if c == '`' { + } else if c == '`' { let x = self.read_char().expect("Unexpected end of input"); - if !x.is_alphabetic() && x != '_' { - panic!("Parse error on '{:?}'", x); - } + assert!(x.is_alphanumeric() || x == '_', "Parse error on '{:?}'", x); let mut token = self.scan_identifier(x, start_location); let end_tick = self.read_char(); match end_tick { Some('`') => (), Some(x) => panic!("Parse error on '{:?}'", x), - None => panic!("Unexpected end of input") + None => panic!("Unexpected end of input"), } token.token = OPERATOR; return token; - } - else if c == '"' { + } else if c == '"' { let mut string = String::new(); loop { match self.read_char() { - Some('"') => return Token::new(&self.interner, STRING, string.as_ref(), start_location), + Some('"') => { + return Token::new(&self.interner, STRING, string.as_ref(), start_location) + } Some(x) => string.push(x), - None => panic!("Unexpected EOF") + None => panic!("Unexpected EOF"), } } - } - else if c == '\'' { - match self.read_char() { - Some(x) => { - if self.read_char() == Some('\'') { - //FIXME: Slow - return Token::new(&self.interner, CHAR, &*x.to_string(), start_location); - } - else { - panic!("Multi char character") - } - } - None => panic!("Unexpected EOF") + } else if c == '\'' { + let x = self.read_char().expect("Unexpected EOF"); + if self.read_char() != Some('\'') { + panic!("Multi char character") } + //FIXME: Slow + return Token::new(&self.interner, CHAR, &x.to_string(), start_location); } let tok = match c { ';' => SEMICOLON, @@ -575,8 +590,8 @@ impl > Lexer { '{' => LBRACE, '}' => RBRACE, ',' => COMMA, - '\\'=> LAMBDA, - _ => EOF + '\\' => LAMBDA, + _ => EOF, }; //FIXME: Slow Token::new(&self.interner, tok, c.to_string().as_ref(), start_location) @@ -586,31 +601,32 @@ impl > Lexer { #[cfg(test)] mod tests { -use crate::lexer::*; + use crate::lexer::*; -#[test] -fn simple() { - let mut lexer = Lexer::new("test 2 + 3".chars()); + #[test] + fn simple() { + let mut lexer = Lexer::new("test 2 + 3".chars()); - assert_eq!(*lexer.next(), Token::new_(NAME, "test")); - assert_eq!(*lexer.next(), Token::new_(NUMBER, "2")); - assert_eq!(*lexer.next(), Token::new_(OPERATOR, "+")); - assert_eq!(*lexer.next(), Token::new_(NUMBER, "3")); -} -#[test] -fn let_bind() { - let mut lexer = Lexer::new( -r"let + assert_eq!(*lexer.next(), Token::new_(NAME, "test")); + assert_eq!(*lexer.next(), Token::new_(NUMBER, "2")); + assert_eq!(*lexer.next(), Token::new_(OPERATOR, "+")); + assert_eq!(*lexer.next(), Token::new_(NUMBER, "3")); + } + #[test] + fn let_bind() { + let mut lexer = Lexer::new( + r"let test = 2 + 3 -in test".chars()); - - assert_eq!(*lexer.next(), Token::new_(LET, "let")); - assert_eq!(*lexer.next(), Token::new_(LBRACE, "{")); - assert_eq!(*lexer.next(), Token::new_(NAME, "test")); - assert_eq!(*lexer.next(), Token::new_(EQUALSSIGN, "=")); - assert_eq!(*lexer.next(), Token::new_(NUMBER, "2")); - assert_eq!(*lexer.next(), Token::new_(OPERATOR, "+")); - assert_eq!(*lexer.next(), Token::new_(NUMBER, "3")); -} - +in test" + .chars(), + ); + + assert_eq!(*lexer.next(), Token::new_(LET, "let")); + assert_eq!(*lexer.next(), Token::new_(LBRACE, "{")); + assert_eq!(*lexer.next(), Token::new_(NAME, "test")); + assert_eq!(*lexer.next(), Token::new_(EQUALSSIGN, "=")); + assert_eq!(*lexer.next(), Token::new_(NUMBER, "2")); + assert_eq!(*lexer.next(), Token::new_(OPERATOR, "+")); + assert_eq!(*lexer.next(), Token::new_(NUMBER, "3")); + } } diff --git a/src/main.rs b/src/main.rs index 303e7d0..ea7de50 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,10 +6,10 @@ extern crate getopts; #[cfg(test)] extern crate test; -#[cfg(not(test))] -use vm::execute_main_module; #[cfg(not(test))] use getopts::Options; +#[cfg(not(test))] +use vm::execute_main_module; macro_rules! write_core_expr( ($e:expr, $f:expr, $($p:pat),*) => ({ @@ -37,24 +37,24 @@ macro_rules! write_core_expr( }) ); -mod types; -mod module; +mod builtins; mod compiler; -mod typecheck; -mod lexer; -mod parser; -mod graph; -mod vm; -mod scoped_map; mod core; -mod lambda_lift; -mod renamer; +mod deriving; +mod graph; mod infix; -mod builtins; mod interner; -mod deriving; +mod lambda_lift; +mod lexer; +mod module; +mod parser; +mod renamer; #[cfg(not(test))] mod repl; +mod scoped_map; +mod typecheck; +mod types; +mod vm; #[cfg(not(test))] fn main() { @@ -82,10 +82,9 @@ fn main() { return; } - let modulename = &*matches.free[0]; + let modulename = &matches.free[0]; match execute_main_module(modulename.as_ref()).unwrap() { Some(x) => println!("{:?}", x), - None => println!("Error running module {}", modulename) + None => println!("Error running module {}", modulename), } } - diff --git a/src/module.rs b/src/module.rs index 7add02c..15c3df2 100644 --- a/src/module.rs +++ b/src/module.rs @@ -1,23 +1,37 @@ -use std::fmt; -use std::collections::HashMap; -use crate::interner::{intern, InternedStr}; -use crate::lexer::{Location, Located}; -pub use std::default::Default; -pub use crate::types::*; +pub use { + crate::types::*, + std::default::Default, +}; +use { + crate::{ + interner::{ + intern, + InternedStr, + }, + lexer::{ + Located, + Location, + }, + }, + std::{ + collections::HashMap, + fmt, + }, +}; use self::Expr::*; #[derive(Clone, Debug)] pub struct Module { - pub name : Ident, + pub name: Ident, pub imports: Vec>, - pub bindings : Vec>, - pub type_declarations : Vec>, - pub classes : Vec>, - pub instances : Vec>, - pub data_definitions : Vec>, - pub newtypes : Vec>, - pub fixity_declarations : Vec> + pub bindings: Vec>, + pub type_declarations: Vec>, + pub classes: Vec>, + pub instances: Vec>, + pub data_definitions: Vec>, + pub newtypes: Vec>, + pub fixity_declarations: Vec>, } #[derive(Clone, Debug)] @@ -25,49 +39,49 @@ pub struct Import { pub module: InternedStr, //None if 'import Name' //Some(names) if 'import Name (names)' - pub imports: Option> + pub imports: Option>, } #[derive(Clone, Debug)] pub struct Class { pub constraints: Vec>, - pub name : Ident, - pub variable : TypeVariable, - pub declarations : Vec>, - pub bindings: Vec> + pub name: Ident, + pub variable: TypeVariable, + pub declarations: Vec>, + pub bindings: Vec>, } #[derive(Clone, Debug)] pub struct Instance { - pub bindings : Vec>, - pub constraints : Vec>, - pub typ : Type, - pub classname : Ident + pub bindings: Vec>, + pub constraints: Vec>, + pub typ: Type, + pub classname: Ident, } #[derive(Clone, Debug, PartialEq)] pub struct Binding { - pub name : Ident, + pub name: Ident, pub arguments: Vec>, pub matches: Match, - pub where_bindings : Option>>, - pub typ: Qualified, Ident> + pub where_bindings: Option>>, + pub typ: Qualified, Ident>, } #[derive(PartialEq, Eq, Clone, Debug)] pub struct Constructor { - pub name : Ident, - pub typ : Qualified, Ident>, - pub tag : isize, - pub arity : isize + pub name: Ident, + pub typ: Qualified, Ident>, + pub tag: isize, + pub arity: isize, } #[derive(PartialEq, Clone, Debug)] pub struct DataDefinition { - pub constructors : Vec>, - pub typ : Qualified, Ident>, - pub parameters : HashMap, - pub deriving: Vec + pub constructors: Vec>, + pub typ: Qualified, Ident>, + pub parameters: HashMap, + pub deriving: Vec, } #[derive(PartialEq, Clone, Debug)] @@ -75,68 +89,75 @@ pub struct Newtype { pub typ: Qualified, pub constructor_name: Ident, pub constructor_type: Qualified, Ident>, - pub deriving: Vec + pub deriving: Vec, } #[derive(PartialEq, Clone, Copy, Debug)] pub enum Assoc { Left, Right, - No + No, } #[derive(PartialEq, Clone, Debug)] pub struct FixityDeclaration { pub assoc: Assoc, pub precedence: isize, - pub operators: Vec + pub operators: Vec, } #[derive(Clone, Debug, PartialEq, Eq, Default)] pub struct TypeDeclaration { - pub typ : Qualified, Ident>, - pub name : Ident + pub typ: Qualified, Ident>, + pub name: Ident, } -impl > fmt::Display for TypeDeclaration { +impl> fmt::Display for TypeDeclaration { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{} :: {}", self.name, self.typ) } } - #[derive(Clone, Debug)] pub struct TypedExpr { - pub expr : Expr, - pub typ : Type, - pub location : Location + pub expr: Expr, + pub typ: Type, + pub location: Location, } -impl PartialEq for TypedExpr { - fn eq(&self, other : &TypedExpr) -> bool { +impl PartialEq for TypedExpr { + fn eq(&self, other: &TypedExpr) -> bool { self.expr == other.expr } } -impl > fmt::Display for TypedExpr { +impl> fmt::Display for TypedExpr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{} :: {}", self.expr, self.typ) } } impl TypedExpr { - pub fn new>(expr : Expr) -> TypedExpr { - TypedExpr { expr : expr, typ : Type::new_var(intern("a")), location : Location { column : -1, row : -1, absolute : -1 } } - } - pub fn with_location>(expr : Expr, loc : Location) -> TypedExpr { - TypedExpr { expr : expr, typ : Type::new_var(intern("a")), location : loc } + pub fn new>(expr: Expr) -> TypedExpr { + TypedExpr::with_location(expr, Location::eof()) + } + + pub fn with_location>( + expr: Expr, + loc: Location, + ) -> TypedExpr { + TypedExpr { + expr, + typ: "a".into(), + location: loc, + } } } #[derive(Clone, Debug, PartialEq)] pub struct Alternative { - pub pattern : Located>, + pub pattern: Located>, pub matches: Match, - pub where_bindings : Option>> + pub where_bindings: Option>>, } #[derive(Clone, Debug, PartialOrd, PartialEq, Eq)] @@ -144,19 +165,19 @@ pub enum Pattern { Number(isize), Identifier(Ident), Constructor(Ident, Vec>), - WildCard + WildCard, } #[derive(Clone, Debug, PartialEq)] pub enum Match { Guards(Vec>), - Simple(TypedExpr) + Simple(TypedExpr), } -impl Match { +impl Match { pub fn location<'a>(&'a self) -> &'a Location { match *self { - Match::Guards(ref gs) => &gs[0].predicate.location, - Match::Simple(ref e) => &e.location + Self::Guards(ref gs) => &gs[0].predicate.location, + Self::Simple(ref e) => &e.location, } } } @@ -164,14 +185,14 @@ impl Match { #[derive(Clone, Debug, PartialEq)] pub struct Guard { pub predicate: TypedExpr, - pub expression: TypedExpr + pub expression: TypedExpr, } #[derive(Clone, Debug, PartialEq)] pub enum DoBinding { DoLet(Vec>), DoBind(Located>, TypedExpr), - DoExpr(TypedExpr) + DoExpr(TypedExpr), } #[derive(Clone, Debug, PartialEq)] @@ -179,7 +200,7 @@ pub enum LiteralData { Integral(isize), Fractional(f64), String(InternedStr), - Char(char) + Char(char), } #[derive(Clone, Debug, PartialEq)] pub enum Expr { @@ -190,18 +211,22 @@ pub enum Expr { Lambda(Pattern, Box>), Let(Vec>, Box>), Case(Box>, Vec>), - IfElse(Box>, Box>, Box>), + IfElse( + Box>, + Box>, + Box>, + ), Do(Vec>, Box>), TypeSig(Box>, Qualified, Ident>), - Paren(Box>) + Paren(Box>), } -impl > fmt::Display for Binding { +impl> fmt::Display for Binding { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{} = {}", self.name, self.matches) } } -impl > fmt::Display for Expr { +impl> fmt::Display for Expr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write_core_expr!(*self, f, _)?; match *self { @@ -217,7 +242,7 @@ impl > fmt::Display for Expr { write!(f, "}}\n")?; } DoBinding::DoBind(ref p, ref e) => write!(f, "; {} <- {}\n", p.node, *e)?, - DoBinding::DoExpr(ref e) => write!(f, "; {}\n", *e)? + DoBinding::DoExpr(ref e) => write!(f, "; {}\n", *e)?, } } write!(f, "{} }}", *expr) @@ -225,37 +250,37 @@ impl > fmt::Display for Expr { OpApply(ref lhs, ref op, ref rhs) => write!(f, "({} {} {})", lhs, op, rhs), TypeSig(ref expr, ref typ) => write!(f, "{} {}", expr, typ), Paren(ref expr) => write!(f, "({})", expr), - _ => Ok(()) + _ => Ok(()), } } } -impl > fmt::Display for Pattern { +impl> fmt::Display for Pattern { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - &Pattern::Identifier(ref s) => write!(f, "{}", s), - &Pattern::Number(ref i) => write!(f, "{}", i), - &Pattern::Constructor(ref name, ref patterns) => { + &Self::Identifier(ref s) => write!(f, "{}", s), + &Self::Number(ref i) => write!(f, "{}", i), + &Self::Constructor(ref name, ref patterns) => { write!(f, "({} ", name)?; for p in patterns.iter() { write!(f, " {}", p)?; } write!(f, ")") } - &Pattern::WildCard => write!(f, "_") + &Self::WildCard => write!(f, "_"), } } } -impl > fmt::Display for Alternative { +impl> fmt::Display for Alternative { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{} -> {}", self.pattern.node, self.matches) } } -impl > fmt::Display for Match { +impl> fmt::Display for Match { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - Match::Simple(ref e) => write!(f, "{}", *e), - Match::Guards(ref gs) => { + Self::Simple(ref e) => write!(f, "{}", *e), + Self::Guards(ref gs) => { for g in gs.iter() { write!(f, "| {} -> {}\n", g.predicate, g.expression)?; } @@ -267,10 +292,10 @@ impl > fmt::Display for Match { impl fmt::Display for LiteralData { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - LiteralData::Integral(i) => write!(f, "{}", i), - LiteralData::Fractional(v) => write!(f, "{}", v), - LiteralData::String(ref s) => write!(f, "\"{}\"", *s), - LiteralData::Char(c) => write!(f, "'{}'", c) + Self::Integral(i) => write!(f, "{}", i), + Self::Fractional(v) => write!(f, "{}", v), + Self::String(ref s) => write!(f, "\"{}\"", *s), + Self::Char(c) => write!(f, "'{}'", c), } } } @@ -279,7 +304,7 @@ impl fmt::Display for LiteralData { ///The tree will be walked through automatically, calling the appropriate visit_ function ///If a visit_ function is overridden it will need to call the appropriate walk_function to ///recurse deeper into the AST -pub trait Visitor : Sized { +pub trait Visitor: Sized { fn visit_expr(&mut self, expr: &TypedExpr) { walk_expr(self, expr) } @@ -309,37 +334,37 @@ pub fn walk_module>(visitor: &mut V, module: &Module>(visitor: &mut V, binding: &Binding) { match binding.matches { Match::Simple(ref e) => visitor.visit_expr(e), - _ => panic!() + _ => panic!(), } } pub fn walk_expr>(visitor: &mut V, expr: &TypedExpr) { match &expr.expr { &Apply(ref func, ref arg) => { - visitor.visit_expr(&**func); - visitor.visit_expr(&**arg); + visitor.visit_expr(func); + visitor.visit_expr(arg); } &OpApply(ref lhs, _, ref rhs) => { - visitor.visit_expr(&**lhs); - visitor.visit_expr(&**rhs); + visitor.visit_expr(lhs); + visitor.visit_expr(rhs); } - &Lambda(_, ref body) => visitor.visit_expr(&**body), + &Lambda(_, ref body) => visitor.visit_expr(body), &Let(ref binds, ref e) => { for b in binds.iter() { visitor.visit_binding(b); } - visitor.visit_expr(&**e); + visitor.visit_expr(e); } &Case(ref e, ref alts) => { - visitor.visit_expr(&**e); + visitor.visit_expr(e); for alt in alts.iter() { visitor.visit_alternative(alt); } } &IfElse(ref pred, ref if_true, ref if_false) => { - visitor.visit_expr(&**pred); - visitor.visit_expr(&**if_true); - visitor.visit_expr(&**if_false); + visitor.visit_expr(pred); + visitor.visit_expr(if_true); + visitor.visit_expr(if_false); } &Do(ref binds, ref expr) => { for bind in binds.iter() { @@ -353,14 +378,14 @@ pub fn walk_expr>(visitor: &mut V, expr: &TypedExpr visitor.visit_expr(e) + DoBinding::DoExpr(ref e) => visitor.visit_expr(e), } } - visitor.visit_expr(&**expr); + visitor.visit_expr(expr); } - &TypeSig(ref expr, _) => visitor.visit_expr(&**expr), - &Paren(ref expr) => visitor.visit_expr(&**expr), - &Literal(..) | &Identifier(..) => () + &TypeSig(ref expr, _) => visitor.visit_expr(expr), + &Paren(ref expr) => visitor.visit_expr(expr), + &Literal(..) | &Identifier(..) => (), } } @@ -381,24 +406,19 @@ pub fn walk_alternative>(visitor: &mut V, alt: &Alterna visitor.visit_binding(bind); } } - None => () + None => (), } } pub fn walk_pattern>(visitor: &mut V, pattern: &Pattern) { - match pattern { - &Pattern::Constructor(_, ref ps) => { - for p in ps.iter() { - visitor.visit_pattern(p); - } + if let &Pattern::Constructor(_, ref ps) = pattern { + for p in ps.iter() { + visitor.visit_pattern(p); } - _ => () } } - - -pub trait MutVisitor : Sized { +pub trait MutVisitor: Sized { fn visit_expr(&mut self, expr: &mut TypedExpr) { walk_expr_mut(self, expr) } @@ -417,7 +437,11 @@ pub trait MutVisitor : Sized { } pub fn walk_module_mut>(visitor: &mut V, module: &mut Module) { - for bind in module.instances.iter_mut().flat_map(|i| i.bindings.iter_mut()) { + for bind in module + .instances + .iter_mut() + .flat_map(|i| i.bindings.iter_mut()) + { visitor.visit_binding(bind); } for bind in module.bindings.iter_mut() { @@ -425,7 +449,10 @@ pub fn walk_module_mut>(visitor: &mut V, module: &mu } } -pub fn walk_binding_mut>(visitor: &mut V, binding: &mut Binding) { +pub fn walk_binding_mut>( + visitor: &mut V, + binding: &mut Binding, +) { match binding.matches { Match::Simple(ref mut e) => visitor.visit_expr(e), Match::Guards(ref mut gs) => { @@ -440,30 +467,30 @@ pub fn walk_binding_mut>(visitor: &mut V, binding: & pub fn walk_expr_mut>(visitor: &mut V, expr: &mut TypedExpr) { match expr.expr { Apply(ref mut func, ref mut arg) => { - visitor.visit_expr(&mut **func); - visitor.visit_expr(&mut **arg); + visitor.visit_expr(func); + visitor.visit_expr(arg); } OpApply(ref mut lhs, _, ref mut rhs) => { - visitor.visit_expr(&mut **lhs); - visitor.visit_expr(&mut **rhs); + visitor.visit_expr(lhs); + visitor.visit_expr(rhs); } - Lambda(_, ref mut body) => visitor.visit_expr(&mut **body), + Lambda(_, ref mut body) => visitor.visit_expr(body), Let(ref mut binds, ref mut e) => { for b in binds.iter_mut() { visitor.visit_binding(b); } - visitor.visit_expr(&mut **e); + visitor.visit_expr(e); } Case(ref mut e, ref mut alts) => { - visitor.visit_expr(&mut **e); + visitor.visit_expr(e); for alt in alts.iter_mut() { visitor.visit_alternative(alt); } } IfElse(ref mut pred, ref mut if_true, ref mut if_false) => { - visitor.visit_expr(&mut **pred); - visitor.visit_expr(&mut **if_true); - visitor.visit_expr(&mut **if_false); + visitor.visit_expr(pred); + visitor.visit_expr(if_true); + visitor.visit_expr(if_false); } Do(ref mut binds, ref mut expr) => { for bind in binds.iter_mut() { @@ -477,18 +504,21 @@ pub fn walk_expr_mut>(visitor: &mut V, expr: &mut Ty visitor.visit_pattern(&mut pattern.node); visitor.visit_expr(e); } - DoBinding::DoExpr(ref mut e) => visitor.visit_expr(e) + DoBinding::DoExpr(ref mut e) => visitor.visit_expr(e), } } - visitor.visit_expr(&mut **expr); + visitor.visit_expr(expr); } - TypeSig(ref mut expr, _) => visitor.visit_expr(&mut **expr), - Paren(ref mut expr) => visitor.visit_expr(&mut **expr), - Literal(..) | Identifier(..) => () + TypeSig(ref mut expr, _) => visitor.visit_expr(expr), + Paren(ref mut expr) => visitor.visit_expr(expr), + Literal(..) | Identifier(..) => (), } } -pub fn walk_alternative_mut>(visitor: &mut V, alt: &mut Alternative) { +pub fn walk_alternative_mut>( + visitor: &mut V, + alt: &mut Alternative, +) { visitor.visit_pattern(&mut alt.pattern.node); match alt.matches { Match::Simple(ref mut e) => visitor.visit_expr(e), @@ -499,46 +529,42 @@ pub fn walk_alternative_mut>(visitor: &mut V, alt: & } } } - match alt.where_bindings { - Some(ref mut bindings) => { - for bind in bindings.iter_mut() { - visitor.visit_binding(bind); - } + if let Some(ref mut bindings) = alt.where_bindings { + for bind in bindings.iter_mut() { + visitor.visit_binding(bind); } - None => () } } -pub fn walk_pattern_mut>(visitor: &mut V, pattern: &mut Pattern) { - match *pattern { - Pattern::Constructor(_, ref mut ps) => { - for p in ps.iter_mut() { - visitor.visit_pattern(p); - } +pub fn walk_pattern_mut>( + visitor: &mut V, + pattern: &mut Pattern, +) { + if let Pattern::Constructor(_, ref mut ps) = pattern { + for p in ps.iter_mut() { + visitor.visit_pattern(p); } - _ => () } } pub struct Binds<'a, Ident: 'a> { - vec: &'a [Binding] + vec: &'a [Binding], } - -impl <'a, Ident: Eq> Iterator for Binds<'a, Ident> { +impl<'a, Ident: Eq> Iterator for Binds<'a, Ident> { type Item = &'a [Binding]; fn next(&mut self) -> Option<&'a [Binding]> { - if self.vec.len() == 0 { - None - } - else { - let end = self.vec.iter() - .position(|bind| bind.name != self.vec[0].name) - .unwrap_or(self.vec.len()); - let head = &self.vec[..end]; - self.vec = &self.vec[end..]; - Some(head) + if self.vec.is_empty() { + return None; } + let end = self + .vec + .iter() + .position(|bind| bind.name != self.vec[0].name) + .unwrap_or(self.vec.len()); + let head = &self.vec[..end]; + self.vec = &self.vec[end..]; + Some(head) } } @@ -555,11 +581,10 @@ pub fn binding_groups<'a, Ident: Eq>(bindings: &'a [Binding]) -> Binds<'a ///Since bindings in instances have the same name as any other instance for the same class we ///Give it a new name which is '# Type name' (no spaces) -pub fn encode_binding_identifier(instancename : InternedStr, bindingname : InternedStr) -> InternedStr { - let mut buffer = String::new(); - buffer.push_str("#"); - buffer.push_str(&instancename); - buffer.push_str(&bindingname); +pub fn encode_binding_identifier( + instancename: InternedStr, + bindingname: InternedStr, +) -> InternedStr { + let buffer = ["#", &instancename, &bindingname].join(""); intern(buffer.as_ref()) } - diff --git a/src/parser.rs b/src/parser.rs index abcdd2c..183953e 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,17 +1,32 @@ -use std::mem::{swap}; -use std::io; -use std::io::Read; -use std::fs::File; -use std::collections::{HashSet, HashMap}; -use std::str::FromStr; -use std::fmt; -use std::error; -use crate::lexer::*; -use crate::lexer::TokenEnum::*; -use crate::module::*; -use crate::module::Expr::*; -use crate::module::LiteralData::*; -use crate::interner::*; +use { + crate::{ + interner::*, + lexer::{ + TokenEnum::*, + *, + }, + module::{ + Expr::*, + LiteralData::*, + *, + }, + }, + std::{ + collections::{ + HashMap, + HashSet, + }, + error, + fmt, + fs::File, + io::{ + self, + Read, + }, + mem::swap, + str::FromStr, + }, +}; ///The Parser is a recursive descent parser which has a method for each production ///in the AST. By calling such a production method it is expected that the parser is @@ -20,14 +35,14 @@ use crate::interner::*; ///If the methods returns an Option it will instead return None. ///In any case it is expected that a production method will place the parser in a position where_bindings ///it can continue parsing without having to move the lexer's position. -pub struct Parser> { - lexer : Lexer, +pub struct Parser> { + lexer: Lexer, } #[derive(Debug, Eq, PartialEq)] enum Error { UnexpectedToken(&'static [TokenEnum], TokenEnum), - Message(::std::string::String) + Message(::std::string::String), } #[derive(Debug, PartialEq)] @@ -37,7 +52,10 @@ pub type ParseResult = Result; impl From for ParseError { fn from(io_error: io::Error) -> ParseError { - ParseError(Located { location: Location::eof(), node: Error::Message(io_error.to_string()) }) + ParseError(Located { + location: Location::eof(), + node: Error::Message(io_error.to_string()), + }) } } @@ -45,53 +63,50 @@ impl fmt::Display for ParseError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.0.node { Error::UnexpectedToken(unexpected, expected) => { - write!(f, "Expected token {:?}, but found {:?}", unexpected, expected) + write!( + f, + "Expected token {:?}, but found {:?}", + unexpected, expected + ) } - Error::Message(ref message) => write!(f, "{}", message) + Error::Message(ref message) => write!(f, "{}", message), } } } impl error::Error for ParseError { - fn description(&self) -> &str { "parse error" } + fn description(&self) -> &str { + "parse error" + } } enum BindOrTypeDecl { Binding(Binding), - TypeDecl(TypeDeclaration) + TypeDecl(TypeDeclaration), } macro_rules! expect { - ($e: expr, $p: ident (..)) => ({ + ($e: expr, $p: ident (..)) => {{ match $e.next($p).token { $p(..) => $e.lexer.current(), - actual => unexpected!($e, actual, $p) + actual => unexpected!($e, actual, $p), } - }); - ($e: expr, $p: ident) => ({ + }}; + ($e: expr, $p: ident) => {{ match $e.next($p).token { $p => $e.lexer.current(), - actual => unexpected!($e, actual, $p) + actual => unexpected!($e, actual, $p), } - }) + }}; } macro_rules! expect1 { - ($e: expr, $p: ident ($x: ident)) => ({ + ($e: expr, $p: ident ($x: ident)) => {{ match $e.next().token { $p($x) => $x, - actual => unexpected!($e, actual, $p) + actual => unexpected!($e, actual, $p), } - }) -} - -macro_rules! matches { - ($e: expr, $p: pat) => ( - match $e { - $p => true, - _ => false - } - ) + }}; } macro_rules! unexpected ( @@ -103,1038 +118,1115 @@ macro_rules! unexpected ( } } ); +impl> Parser { + pub fn new(iterator: Iter) -> Self { + Self { + lexer: Lexer::new(iterator), + } + } -impl > Parser { - -pub fn new(iterator : Iter) -> Parser { - Parser { lexer : Lexer::new(iterator) } -} + fn next<'a>(&'a mut self, expected: TokenEnum) -> &'a Token { + if expected == RBRACE { + self.lexer.next_end() + } else { + self.lexer.next() + } + } -fn next<'a>(&'a mut self, expected : TokenEnum) -> &'a Token { - if expected == RBRACE { - self.lexer.next_end() + fn error(&self, message: ::std::string::String) -> ParseResult { + Err(ParseError(Located { + location: self.lexer.current().location, + node: Error::Message(message), + })) } - else { - self.lexer.next() + fn unexpected_token(&self, expected: &'static [TokenEnum], actual: TokenEnum) -> ParseError { + ParseError(Located { + location: self.lexer.current().location, + node: Error::UnexpectedToken(expected, actual), + }) } -} -fn error(&self, message: ::std::string::String) -> ParseResult { - Err(ParseError(Located { - location: self.lexer.current().location, - node: Error::Message(message) - })) -} -fn unexpected_token(&self, expected: &'static [TokenEnum], actual: TokenEnum) -> ParseError { - ParseError(Located { - location: self.lexer.current().location, - node: Error::UnexpectedToken(expected, actual) - }) -} + pub fn module(&mut self) -> ParseResult { + let modulename = match self.lexer.module_next().token { + MODULE => { + let modulename = expect!(self, NAME).value.clone(); + expect!(self, WHERE); + expect!(self, LBRACE); + modulename + } + LBRACE => { + //No module declaration was found so default to Main + intern("Main") + } + _ => unexpected!(self, [LBRACE]), + }; -pub fn module(&mut self) -> ParseResult { - let modulename = match self.lexer.module_next().token { - MODULE => { - let modulename = expect!(self, NAME).value.clone(); - expect!(self, WHERE); - expect!(self, LBRACE); - modulename - } - LBRACE => { - //No module declaration was found so default to Main - intern("Main") - } - _ => unexpected!(self, [LBRACE]) - }; + let mut imports = vec![]; - let mut imports = Vec::new(); - loop { - if self.lexer.peek().token == IMPORT { + while self.lexer.peek().token == IMPORT { imports.push(self.import()?); if self.lexer.peek().token == SEMICOLON { self.lexer.next(); - } - else { - break + } else { + break; } } - else { - break - } - } - let mut classes = Vec::new(); - let mut bindings = Vec::new(); - let mut instances = Vec::new(); - let mut type_declarations = Vec::new(); - let mut data_definitions = Vec::new(); - let mut newtypes = Vec::new(); - let mut fixity_declarations = Vec::new(); - loop { - //Do a lookahead to see what the next top level binding is - let token = self.lexer.peek().token; - if token == NAME || token == LPARENS { - match self.binding_or_type_declaration()? { - BindOrTypeDecl::Binding(bind) => bindings.push(bind), - BindOrTypeDecl::TypeDecl(decl) => type_declarations.push(decl) + let mut classes = vec![]; + let mut bindings = vec![]; + let mut instances = vec![]; + let mut type_declarations = vec![]; + let mut data_definitions = vec![]; + let mut newtypes = vec![]; + let mut fixity_declarations = vec![]; + loop { + //Do a lookahead to see what the next top level binding is + let token = self.lexer.peek().token; + + match token { + NAME | LPARENS => match self.binding_or_type_declaration()? { + BindOrTypeDecl::Binding(bind) => bindings.push(bind), + BindOrTypeDecl::TypeDecl(decl) => type_declarations.push(decl), + }, + CLASS => classes.push(self.class()?), + INSTANCE => instances.push(self.instance()?), + DATA => data_definitions.push(self.data_definition()?), + NEWTYPE => newtypes.push(self.newtype()?), + INFIXL | INFIXR | INFIX => fixity_declarations.push(self.fixity_declaration()?), + _ => { + self.lexer.next(); + break; + } + } + + let semicolon = self.lexer.next(); + debug!("More bindings? {:?}", semicolon.token); + if semicolon.token != SEMICOLON { + break; } - } - else if token == CLASS { - classes.push(self.class()?); - } - else if token == INSTANCE { - instances.push(self.instance()?); - } - else if token == DATA { - data_definitions.push(self.data_definition()?); - } - else if token == NEWTYPE { - newtypes.push(self.newtype()?); - } - else if token == INFIXL || token == INFIXR || token == INFIX { - fixity_declarations.push(self.fixity_declaration()?); - } - else { - self.lexer.next(); - break; - } - let semicolon = self.lexer.next(); - debug!("More bindings? {:?}", semicolon.token); - if semicolon.token != SEMICOLON { - break; } - } - self.lexer.backtrack(); - expect!(self, RBRACE); - expect!(self, EOF); - - Ok(Module { - name : modulename, - imports : imports, - bindings : bindings, - type_declarations : type_declarations, - classes : classes, - instances : instances, - data_definitions : data_definitions, - newtypes: newtypes, - fixity_declarations : fixity_declarations - }) -} + self.lexer.backtrack(); + expect!(self, RBRACE); + expect!(self, EOF); + + Ok(Module { + name: modulename, + imports, + bindings, + type_declarations, + classes, + instances, + data_definitions, + newtypes, + fixity_declarations, + }) + } -fn import(&mut self) -> ParseResult> { - expect!(self, IMPORT); - let module_name = expect!(self, NAME).value; - let imports = if self.lexer.peek().token == LPARENS { - self.lexer.next(); - let x = if self.lexer.peek().token == RPARENS { + fn import(&mut self) -> ParseResult> { + expect!(self, IMPORT); + let module_name = expect!(self, NAME).value; + let imports = if self.lexer.peek().token == LPARENS { self.lexer.next(); - Vec::new() - } - else { - let imports = self.sep_by_1(|this| Ok(expect!(this, NAME).value), COMMA)?; - expect!(self, RPARENS); - imports + let x = if self.lexer.peek().token == RPARENS { + self.lexer.next(); + vec![] + } else { + let imports = self.sep_by_1(|this| Ok(expect!(this, NAME).value), COMMA)?; + expect!(self, RPARENS); + imports + }; + Some(x) + } else { + None }; - Some(x) + Ok(Import { + module: module_name, + imports, + }) } - else { - None - }; - Ok(Import { module: module_name, imports: imports }) -} -fn class(&mut self) -> ParseResult { - expect!(self, CLASS); - let (constraints, typ) = self.constrained_type()?; - - expect!(self, WHERE); - expect!(self, LBRACE); - let x = self.sep_by_1(|this| this.binding_or_type_declaration(), SEMICOLON)?; - let mut bindings = Vec::new(); - let mut declarations = Vec::new(); - for decl_or_binding in x.into_iter() { - match decl_or_binding { - BindOrTypeDecl::Binding(mut bind) => { - //Bindings need to have their name altered to distinguish them from - //the declarations name - match typ { - Type::Application(ref op, _) => { - let classname = match **op { - Type::Constructor(ref ctor) => ctor.name, - _ => return self.error("Expected type operator".to_string()) - }; - bind.name = encode_binding_identifier(classname, bind.name); - } - _ => return self.error("The name of the class must start with an uppercase letter".to_string()) + fn class(&mut self) -> ParseResult { + expect!(self, CLASS); + let (constraints, typ) = self.constrained_type()?; + + expect!(self, WHERE); + expect!(self, LBRACE); + let x = self.sep_by_1(|this| this.binding_or_type_declaration(), SEMICOLON)?; + let mut bindings = vec![]; + let mut declarations = vec![]; + for decl_or_binding in x.into_iter() { + match decl_or_binding { + BindOrTypeDecl::Binding(mut bind) => { + //Bindings need to have their name altered to distinguish them from + //the declarations name + + let Type::Application(ref op, _) = typ else { + return self.error( + "The name of the class must start with an uppercase letter".to_string(), + ); + }; + + let Type::Constructor(ref ctor) = **op else { + return self.error("Expected type operator".to_string()); + }; + bind.name = encode_binding_identifier(ctor.name, bind.name); + bindings.push(bind) } - bindings.push(bind) + BindOrTypeDecl::TypeDecl(decl) => declarations.push(decl), } - BindOrTypeDecl::TypeDecl(decl) => declarations.push(decl) } + + expect!(self, RBRACE); + + let Type::Application(l, r) = typ else { + return self.error("Parse error in class declaration header".to_string()); + }; + let (Type::Constructor(classname), Type::Variable(var)) = (*l, *r) else { + return self.error("Parse error in class declaration header".to_string()); + }; + Ok(Class { + constraints, + name: classname.name, + variable: var, + declarations, + bindings, + }) } - - expect!(self, RBRACE); - - match typ { - Type::Application(l, r) => { - match (*l, *r) { - (Type::Constructor(classname), Type::Variable(var)) => { - return Ok(Class { - constraints: constraints, - name: classname.name, - variable: var, - declarations: declarations, - bindings: bindings - }); + + fn instance(&mut self) -> ParseResult { + expect!(self, INSTANCE); + + let (constraints, instance_type) = self.constrained_type()?; + match instance_type { + Type::Application(op, arg) => { + let classname = match *op { + Type::Constructor(TypeConstructor { + name: classname, .. + }) => classname, + _ => return self.error("Expected type operator".to_string()), + }; + expect!(self, WHERE); + expect!(self, LBRACE); + + let mut bindings = self.sep_by_1(|this| this.binding(), SEMICOLON)?; + { + let inner_type = extract_applied_type(&arg); + for bind in bindings.iter_mut() { + bind.name = encode_binding_identifier(inner_type.ctor().name, bind.name); + } } - _ => () + + expect!(self, RBRACE); + Ok(Instance { + typ: *arg, + classname, + bindings, + constraints, + }) } + _ => return self.error("TypeVariable in instance".to_string()), } - _ => () } - self.error("Parse error in class declaration header".to_string()) -} -fn instance(&mut self) -> ParseResult { - expect!(self, INSTANCE); - - let (constraints, instance_type) = self.constrained_type()?; - match instance_type { - Type::Application(op, arg) => { - let classname = match *op { - Type::Constructor(TypeConstructor { name: classname, ..}) => classname, - _ => return self.error("Expected type operator".to_string()) - }; - expect!(self, WHERE); - expect!(self, LBRACE); + pub fn expression_(&mut self) -> ParseResult { + match self.expression()? { + Some(expr) => Ok(expr), + None => Err(ParseError(Located { + location: self.lexer.current().location, + node: Error::Message(format!( + "Failed to parse expression at {:?}", + self.lexer.current().location + )), + })), + } + } - let mut bindings = self.sep_by_1(|this| this.binding(), SEMICOLON)?; - { - let inner_type = extract_applied_type(&*arg); - for bind in bindings.iter_mut() { - bind.name = encode_binding_identifier(inner_type.ctor().name, bind.name); + pub fn expression(&mut self) -> ParseResult> { + let app = self.application()?; + match self.binary_expression(app)? { + Some(expr) => { + //Try to parse a type signature on this expression + if self.lexer.next().token == TYPEDECL { + let (constraints, typ) = self.constrained_type()?; + let loc = expr.location; + Ok(Some(TypedExpr::with_location( + TypeSig( + expr.into(), + Qualified { + constraints, + value: typ, + }, + ), + loc, + ))) + } else { + self.lexer.backtrack(); + Ok(Some(expr)) } } - - expect!(self, RBRACE); - Ok(Instance { typ : *arg, classname : classname, bindings : bindings, constraints: constraints }) + None => Ok(None), } - _ => return self.error("TypeVariable in instance".to_string()) - } -} - -pub fn expression_(&mut self) -> ParseResult { - match self.expression()? { - Some(expr) => Ok(expr), - None => Err(ParseError(Located { - location: self.lexer.current().location, - node: Error::Message(format!("Failed to parse expression at {:?}", self.lexer.current().location)) - })) } -} -pub fn expression(&mut self) -> ParseResult> { - let app = self.application()?; - match self.binary_expression(app)? { - Some(expr) => { - //Try to parse a type signature on this expression - if self.lexer.next().token == TYPEDECL { - let (constraints, typ) = self.constrained_type()?; - let loc = expr.location; - Ok(Some(TypedExpr::with_location( - TypeSig(Box::new(expr), Qualified { constraints: constraints, value: typ }), - loc))) - } - else { + fn list(&mut self) -> ParseResult { + let mut expressions = vec![]; + while let Some(expr) = self.expression()? { + expressions.push(expr); + let comma = self.lexer.next().token; + if comma != COMMA { self.lexer.backtrack(); - Ok(Some(expr)) + break; } } - None => Ok(None) + expect!(self, RBRACKET); + + let nil = TypedExpr::new(Identifier(intern("[]"))); + Ok(expressions + .into_iter() + .rev() + .fold(nil, |application, expr| { + let arguments = vec![expr, application]; + make_application( + TypedExpr::new(Identifier(intern(":"))), + arguments.into_iter(), + ) + })) } -} - -fn list(&mut self) -> ParseResult { - let mut expressions = Vec::new(); - loop { - match self.expression()? { - Some(expr) => expressions.push(expr), - None => break - } - let comma = self.lexer.next().token; - if comma != COMMA { - self.lexer.backtrack(); - break; - } - } - expect!(self, RBRACKET); - - let nil = TypedExpr::new(Identifier(intern("[]"))); - Ok(expressions.into_iter().rev().fold(nil, |application, expr| { - let arguments = vec![expr, application]; - make_application(TypedExpr::new(Identifier(intern(":"))), arguments.into_iter()) - })) -} + fn sub_expression(&mut self) -> ParseResult> { + let token = self.lexer.next().token; + debug!("Begin SubExpr {:?}", self.lexer.current()); + Ok(match token { + LPARENS => { + let location = self.lexer.current().location; + if self.lexer.peek().token == RPARENS { + self.lexer.next(); + Some(TypedExpr::with_location(Identifier(intern("()")), location)) + } else { + let mut expressions = self.sep_by_1(|this| this.expression_(), COMMA)?; + expect!(self, RPARENS); + Some(if expressions.len() == 1 { + let expr = expressions.pop().unwrap(); + let loc = expr.location; + TypedExpr::with_location(Paren(expr.into()), loc) + } else { + new_tuple(expressions) + }) + } + } + LBRACKET => Some(self.list()?), + LET => { + let binds = self.let_bindings()?; -fn sub_expression(&mut self) -> ParseResult> { - let token = self.lexer.next().token; - debug!("Begin SubExpr {:?}", self.lexer.current()); - let expr = match token { - LPARENS => { - let location = self.lexer.current().location; - if self.lexer.peek().token == RPARENS { - self.lexer.next(); - Some(TypedExpr::with_location(Identifier(intern("()")), location)) + expect!(self, IN); + self.expression()? + .map(|e| TypedExpr::new(Let(binds, e.into()))) } - else { - let mut expressions = self.sep_by_1(|this| this.expression_(), COMMA)?; - expect!(self, RPARENS); - if expressions.len() == 1 { - let expr = expressions.pop().unwrap(); - let loc = expr.location; - Some(TypedExpr::with_location(Paren(Box::new(expr)), loc)) + CASE => { + let location = self.lexer.current().location; + let expr = self.expression()?; + + expect!(self, OF); + expect!(self, LBRACE); + let alts = self.sep_by_1(|this| this.alternative(), SEMICOLON)?; + expect!(self, RBRACE); + expr.map(|e| TypedExpr::with_location(Case(e.into(), alts), location)) + } + IF => { + let location = self.lexer.current().location; + let pred = self.expression_()?; + if self.lexer.peek().token == SEMICOLON { + self.lexer.next(); } - else { - Some(new_tuple(expressions)) + expect!(self, THEN); + let if_true = self.expression_()?; + if self.lexer.peek().token == SEMICOLON { + self.lexer.next(); } + expect!(self, ELSE); + let if_false = self.expression_()?; + Some(TypedExpr::with_location( + IfElse(pred.into(), if_true.into(), if_false.into()), + location, + )) } - } - LBRACKET => Some(self.list()?), - LET => { - let binds = self.let_bindings()?; - - expect!(self, IN); - match self.expression()? { - Some(e) => { - Some(TypedExpr::new(Let(binds, Box::new(e)))) - } - None => None + LAMBDA => { + let args = self.pattern_arguments()?; + expect!(self, ARROW); + Some(make_lambda(args.into_iter(), self.expression_()?)) } - } - CASE => { - let location = self.lexer.current().location; - let expr = self.expression()?; - - expect!(self, OF); - expect!(self, LBRACE); - - let alts = self.sep_by_1(|this| this.alternative(), SEMICOLON)?; - expect!(self, RBRACE); - match expr { - Some(e) => Some(TypedExpr::with_location(Case(Box::new(e), alts), location)), - None => None + DO => { + let location = self.lexer.current().location; + expect!(self, LBRACE); + let mut bindings = self.sep_by_1(|this| this.do_binding(), SEMICOLON)?; + expect!(self, RBRACE); + + let Some(expr) = bindings.pop() else { + return Err(ParseError(Located { + location: self.lexer.current().location, + node: Error::Message(format!( + "{:?}: Parse error: Empty do", + self.lexer.current().location + )), + })); + }; + + let DoBinding::DoExpr(expr) = expr else { + return self.error( + "Parse error: Last binding in do must be an expression".to_string(), + ); + }; + + Some(TypedExpr::with_location( + Do(bindings, expr.into()), + location, + )) } - } - IF => { - let location = self.lexer.current().location; - let pred = self.expression_()?; - if self.lexer.peek().token == SEMICOLON { - self.lexer.next(); + NAME => { + let token = self.lexer.current(); + Some(TypedExpr::with_location( + Identifier(token.value.clone()), + token.location, + )) } - expect!(self, THEN); - let if_true = self.expression_()?; - if self.lexer.peek().token == SEMICOLON { - self.lexer.next(); + NUMBER => { + let token = self.lexer.current(); + Some(TypedExpr::with_location( + Literal(Integral(FromStr::from_str(token.value.as_ref()).unwrap())), + token.location, + )) } - expect!(self, ELSE); - let if_false = self.expression_()?; - Some(TypedExpr::with_location(IfElse(Box::new(pred), Box::new(if_true), Box::new(if_false)), location)) - } - LAMBDA => { - let args = self.pattern_arguments()?; - expect!(self, ARROW); - Some(make_lambda(args.into_iter(), self.expression_()?)) - } - DO => { - let location = self.lexer.current().location; - expect!(self, LBRACE); - let mut bindings = self.sep_by_1(|this| this.do_binding(), SEMICOLON)?; - expect!(self, RBRACE); - if bindings.len() == 0 { - return Err(ParseError(Located { - location: self.lexer.current().location, - node: Error::Message(format!("{:?}: Parse error: Empty do", self.lexer.current().location)) - })); + FLOAT => { + let token = self.lexer.current(); + Some(TypedExpr::with_location( + Literal(Fractional(FromStr::from_str(token.value.as_ref()).unwrap())), + token.location, + )) } - let expr = match bindings.pop().unwrap() { - DoBinding::DoExpr(e) => e, - _ => return self.error("Parse error: Last binding in do must be an expression".to_string()) - }; - Some(TypedExpr::with_location(Do(bindings, Box::new(expr)), location)) - } - NAME => { - let token = self.lexer.current(); - Some(TypedExpr::with_location(Identifier(token.value.clone()), token.location)) - } - NUMBER => { - let token = self.lexer.current(); - Some(TypedExpr::with_location(Literal(Integral(FromStr::from_str(token.value.as_ref()).unwrap())), token.location)) - } - FLOAT => { - let token = self.lexer.current(); - Some(TypedExpr::with_location(Literal(Fractional(FromStr::from_str(token.value.as_ref()).unwrap())), token.location)) - } - STRING => { - let token = self.lexer.current(); - Some(TypedExpr::with_location(Literal(String(token.value.clone())), token.location)) - } - CHAR => { - let token = self.lexer.current(); - Some(TypedExpr::with_location(Literal(Char(token.value.chars().next().expect("char at 0"))), token.location)) - } - _ => { - self.lexer.backtrack(); - None - } - }; - Ok(expr) -} - -fn do_binding(&mut self) -> ParseResult { - if self.lexer.next().token == LET { - return self.let_bindings().map(DoBinding::DoLet); - } - debug!("Do binding {:?}", self.lexer.current()); - self.lexer.backtrack(); - let mut lookahead = 0; - loop { - lookahead += 1; - match self.lexer.next().token { - SEMICOLON | RBRACE => { - for _ in 0..lookahead { self.lexer.backtrack(); } - return self.expression_().map(DoBinding::DoExpr); + STRING => { + let token = self.lexer.current(); + Some(TypedExpr::with_location( + Literal(String(token.value.clone())), + token.location, + )) } - LARROW => { - for _ in 0..lookahead { self.lexer.backtrack(); } - let p = self.located_pattern()?; - self.lexer.next();//Skip <- - return self.expression_().map(move |e| DoBinding::DoBind(p, e)); + CHAR => { + let token = self.lexer.current(); + Some(TypedExpr::with_location( + Literal(Char(token.value.chars().next().expect("char at 0"))), + token.location, + )) } - EOF => { - return Err(ParseError(Located { - location: self.lexer.current().location, - node: Error::Message("Unexpected EOF".to_string()) - })) + _ => { + self.lexer.backtrack(); + None } - _ => { debug!("Lookahead {:?}", self.lexer.current()); } - } + }) } -} -fn let_bindings(&mut self) -> ParseResult> { + fn do_binding(&mut self) -> ParseResult { + if self.lexer.next().token == LET { + return self.let_bindings().map(DoBinding::DoLet); + } + debug!("Do binding {:?}", self.lexer.current()); + self.lexer.backtrack(); + let mut lookahead = 0; + loop { + lookahead += 1; + match self.lexer.next().token { + SEMICOLON | RBRACE => { + for _ in 0..lookahead { + self.lexer.backtrack(); + } + return self.expression_().map(DoBinding::DoExpr); + } + LARROW => { + for _ in 0..lookahead { + self.lexer.backtrack(); + } + let p = self.located_pattern()?; + self.lexer.next(); //Skip <- + return self.expression_().map(move |e| DoBinding::DoBind(p, e)); + } + EOF => { + return Err(ParseError(Located { + location: self.lexer.current().location, + node: Error::Message("Unexpected EOF".to_string()), + })) + } + _ => { + debug!("Lookahead {:?}", self.lexer.current()); + } + } + } + } - expect!(self, LBRACE); + fn let_bindings(&mut self) -> ParseResult> { + expect!(self, LBRACE); - let binds = self.sep_by_1(|this| this.binding(), SEMICOLON)?; - self.lexer.next_end(); - Ok(binds) -} + let binds = self.sep_by_1(|this| this.binding(), SEMICOLON)?; + self.lexer.next_end(); + Ok(binds) + } -fn alternative(&mut self) -> ParseResult { - let pat = self.located_pattern()?; - static GUARD_TOKENS: &'static [TokenEnum] = &[ARROW, PIPE]; - let matches = self.expr_or_guards(GUARD_TOKENS)?; - let where_bindings = if self.lexer.peek().token == WHERE { - self.lexer.next(); - Some(self.let_bindings()?) + fn alternative(&mut self) -> ParseResult { + let pattern = self.located_pattern()?; + static GUARD_TOKENS: &'static [TokenEnum] = &[ARROW, PIPE]; + let matches = self.expr_or_guards(GUARD_TOKENS)?; + let where_bindings = if self.lexer.peek().token == WHERE { + self.lexer.next(); + Some(self.let_bindings()?) + } else { + None + }; + Ok(Alternative { + pattern, + matches, + where_bindings, + }) } - else { - None - }; - Ok(Alternative { pattern : pat, matches: matches, where_bindings: where_bindings }) -} -fn binary_expression(&mut self, lhs : Option) -> ParseResult> { - debug!("Parse operator expression, {:?}", self.lexer.current()); - if self.lexer.next().token == OPERATOR { - let op = self.lexer.current().value; + fn binary_expression(&mut self, lhs: Option) -> ParseResult> { + debug!("Parse operator expression, {:?}", self.lexer.current()); + if self.lexer.next().token != OPERATOR { + self.lexer.backtrack(); + return Ok(lhs); + }; + let op = self.lexer.current().value; let loc = self.lexer.current().location; - let rhs = self.application()?; + let rhs = self.application()?; let rhs = self.binary_expression(rhs)?; - let expr = match (lhs, rhs) { + Ok(match (lhs, rhs) { (Some(lhs), Some(rhs)) => { - Some(TypedExpr::with_location(OpApply(Box::new(lhs), op, Box::new(rhs)), loc)) + Some(TypedExpr::with_location( + OpApply(lhs.into(), op, rhs.into()), + loc, + )) } (Some(lhs), None) => { - let name = TypedExpr::with_location(Identifier(op), loc); - Some(TypedExpr::with_location(Apply(Box::new(name), Box::new(lhs)), loc)) + let name = TypedExpr::with_location(Identifier(op), loc); + Some(TypedExpr::with_location( + Apply(name.into(), lhs.into()), + loc, + )) } (None, Some(rhs)) => { if op == intern("-") { - let name = TypedExpr::with_location(Identifier(intern("negate")), loc); + let name = TypedExpr::with_location(Identifier(intern("negate")), loc); let args = vec![rhs]; Some(make_application(name, args.into_iter())) - } - else { - let name = TypedExpr::with_location(Identifier(intern("negate")), loc); + } else { + let name = TypedExpr::with_location(Identifier(intern("negate")), loc); let args = vec![TypedExpr::with_location(Identifier(intern("#")), loc), rhs]; let mut apply = make_application(name, args.into_iter()); apply.location = loc; let params = vec![intern("#")]; - Some(make_lambda(params.into_iter().map(|a| Pattern::Identifier(a)), apply)) + Some(make_lambda( + params.into_iter().map(|a| Pattern::Identifier(a)), + apply, + )) } } - (None, None) => return Ok(None) - }; - Ok(expr) - } - else { - self.lexer.backtrack(); - Ok(lhs) + (None, None) => return Ok(None), + }) } -} -fn application(&mut self) -> ParseResult> { - let e = self.sub_expression()?; - match e { - Some(mut lhs) => { - let mut expressions = Vec::new(); - loop { - let expr = self.sub_expression()?; - match expr { - Some(e) => expressions.push(e), - None => break - } + fn application(&mut self) -> ParseResult> { + Ok(if let Some(mut lhs) = self.sub_expression()? { + let mut expressions = vec![]; + while let Some(expr) = self.sub_expression()? { + expressions.push(expr); } - if expressions.len() > 0 { + if !expressions.is_empty() { let loc = lhs.location; - lhs = make_application(lhs, expressions.into_iter());//, loc); + lhs = make_application(lhs, expressions.into_iter()); //, loc); lhs.location = loc; } - Ok(Some(lhs)) - } - None => Ok(None) + Some(lhs) + } else { + None + }) } -} -fn constructor(&mut self, data_def : &DataDefinition) -> ParseResult { - let name = expect!(self, NAME).value.clone(); - let mut arity = 0; - let typ = self.constructor_type(&mut arity, data_def)?; - self.lexer.backtrack(); - Ok(Constructor { name : name, typ : qualified(vec![], typ), tag : 0, arity : arity }) -} - -fn binding(&mut self) -> ParseResult { - debug!("Begin binding"); - //name1 = expr - //or - //name2 x y = expr - let name_token = self.lexer.next().token; - let mut name = self.lexer.current().value.clone(); - if name_token == LPARENS { - //Parse a name within parentheses - let function_name = self.lexer.next().token; - if function_name != NAME && function_name != OPERATOR { - unexpected!(self, [NAME, OPERATOR]); - } - name = self.lexer.current().value.clone(); - expect!(self, RPARENS); - } - else if name_token != NAME { - unexpected!(self, [NAME]); - } - - //Parse the arguments for the binding - let arguments = self.pattern_arguments()?; - static GUARD_TOKENS: &'static [TokenEnum] = &[EQUALSSIGN, PIPE]; - let matches = self.expr_or_guards(GUARD_TOKENS)?; - let where_bindings = if self.lexer.peek().token == WHERE { - self.lexer.next(); - Some(self.let_bindings()?) - } - else { - None - }; - Ok(Binding { - name : name.clone(), - typ: Default::default(), - arguments: arguments, - where_bindings : where_bindings, - matches : matches, - }) -} - -fn binding_or_type_declaration(&mut self) -> ParseResult { - //Since the token indicates an identifier it will be a function declaration or a function definition - //We can disambiguate this by looking wether the '::' token appear. - let token = self.lexer.next().token; - let maybe_type_decl = if token == LPARENS { - expect!(self, OPERATOR); - expect!(self, RPARENS); - let tok = self.lexer.next().token; - self.lexer.backtrack(); - self.lexer.backtrack(); - self.lexer.backtrack(); - self.lexer.backtrack(); - tok - } - else { - let tok = self.lexer.next().token; + fn constructor(&mut self, data_def: &DataDefinition) -> ParseResult { + let name = expect!(self, NAME).value.clone(); + let mut arity = 0; + let typ = self.constructor_type(&mut arity, data_def)?; self.lexer.backtrack(); - self.lexer.backtrack(); - tok - }; - - if maybe_type_decl == TYPEDECL { - self.type_declaration().map(BindOrTypeDecl::TypeDecl) + Ok(Constructor { + name, + typ: qualified(vec![], typ), + tag: 0, + arity, + }) } - else { - self.binding().map(BindOrTypeDecl::Binding) - } -} -fn fixity_declaration(&mut self) -> ParseResult { - let assoc = { - match self.lexer.next().token { - INFIXL => Assoc::Left, - INFIXR => Assoc::Right, - INFIX => Assoc::No, - _ => unexpected!(self, [INFIXL, INFIXR, INFIX]) - } - }; - let precedence = match self.lexer.next().token { - NUMBER => FromStr::from_str(self.lexer.current().value.as_ref()).unwrap(), - _ => { - self.lexer.backtrack(); - 9 + fn binding(&mut self) -> ParseResult { + debug!("Begin binding"); + //name1 = expr + //or + //name2 x y = expr + let name_token = self.lexer.next().token; + let mut name = self.lexer.current().value.clone(); + if name_token == LPARENS { + //Parse a name within parentheses + let function_name = self.lexer.next().token; + if function_name != NAME && function_name != OPERATOR { + unexpected!(self, [NAME, OPERATOR]); + } + name = self.lexer.current().value.clone(); + expect!(self, RPARENS); + } else if name_token != NAME { + unexpected!(self, [NAME]); } - }; - let operators = self.sep_by_1(|this| Ok(expect!(this, OPERATOR).value), COMMA)?; - Ok(FixityDeclaration { assoc: assoc, precedence: precedence, operators: operators }) -} -fn expr_or_guards(&mut self, end_token_and_pipe: &'static [TokenEnum]) -> ParseResult { - let end_token = end_token_and_pipe[0]; - let token = self.lexer.next().token; - if token == PIPE { - self.sep_by_1(|this| { - let p = this.expression_()?; - if this.lexer.next().token != end_token { - this.lexer.backtrack(); - return Err(this.unexpected_token(&end_token_and_pipe[..1], this.lexer.current().token)); - } - this.expression_().map(move |e| Guard { predicate: p, expression: e }) - }, PIPE).map(Match::Guards) - } - else if token == end_token { - self.expression_().map(|e| Match::Simple(e)) - } - else { - self.lexer.backtrack(); - Err(self.unexpected_token(end_token_and_pipe, self.lexer.current().token)) + //Parse the arguments for the binding + let arguments = self.pattern_arguments()?; + static GUARD_TOKENS: &'static [TokenEnum] = &[EQUALSSIGN, PIPE]; + let matches = self.expr_or_guards(GUARD_TOKENS)?; + let where_bindings = if self.lexer.peek().token == WHERE { + self.lexer.next(); + Some(self.let_bindings()?) + } else { + None + }; + Ok(Binding { + name: name.clone(), + typ: <_>::default(), + arguments, + where_bindings, + matches, + }) } -} -fn make_pattern(&mut self, name: InternedStr, args: F) -> ParseResult - where F: FnOnce(&mut Parser) -> ParseResult> { - let c = name.chars().next().expect("char at 0"); - if c.is_uppercase() || name == intern(":") { - args(self).map(|ps| Pattern::Constructor(name, ps)) - } - else if c == '_' { - Ok(Pattern::WildCard) - } - else { - Ok(Pattern::Identifier(name)) + fn binding_or_type_declaration(&mut self) -> ParseResult { + //Since the token indicates an identifier it will be a function declaration or a function definition + //We can disambiguate this by looking wether the '::' token appear. + let token = self.lexer.next().token; + let maybe_type_decl = if token == LPARENS { + expect!(self, OPERATOR); + expect!(self, RPARENS); + let tok = self.lexer.next().token; + self.lexer.backtrack(); + self.lexer.backtrack(); + self.lexer.backtrack(); + self.lexer.backtrack(); + tok + } else { + let tok = self.lexer.next().token; + self.lexer.backtrack(); + self.lexer.backtrack(); + tok + }; + + if maybe_type_decl == TYPEDECL { + self.type_declaration().map(BindOrTypeDecl::TypeDecl) + } else { + self.binding().map(BindOrTypeDecl::Binding) + } } -} -fn pattern_arguments(&mut self) -> ParseResult> { - let mut parameters = Vec::new(); - loop { - let token = self.lexer.next().token; - match token { - NAME => { - let name = self.lexer.current().value; - let p = self.make_pattern(name, |_| Ok(vec![]))?; - parameters.push(p); + fn fixity_declaration(&mut self) -> ParseResult { + let assoc = { + match self.lexer.next().token { + INFIXL => Assoc::Left, + INFIXR => Assoc::Right, + INFIX => Assoc::No, + _ => unexpected!(self, [INFIXL, INFIXR, INFIX]), } - NUMBER => parameters.push(Pattern::Number(FromStr::from_str(self.lexer.current().value.as_ref()).unwrap())), - LPARENS => { + }; + let precedence = match self.lexer.next().token { + NUMBER => FromStr::from_str(self.lexer.current().value.as_ref()).unwrap(), + _ => { self.lexer.backtrack(); - parameters.push(self.pattern()?); - } - LBRACKET => { - expect!(self, RBRACKET); - parameters.push(Pattern::Constructor(intern("[]"), vec![])); + 9 } - _ => { break; } - } - } - self.lexer.backtrack(); - Ok(parameters) -} + }; + let operators = self.sep_by_1(|this| Ok(expect!(this, OPERATOR).value), COMMA)?; + Ok(FixityDeclaration { + assoc, + precedence, + operators, + }) + } -fn located_pattern(&mut self) -> ParseResult> { - let location = self.lexer.next().location; - self.lexer.backtrack(); - self.pattern() - .map(|pattern| Located { location: location, node: pattern }) -} + fn expr_or_guards(&mut self, end_token_and_pipe: &'static [TokenEnum]) -> ParseResult { + let end_token = end_token_and_pipe[0]; + let token = self.lexer.next().token; + if token == PIPE { + self.sep_by_1( + |this| { + let p = this.expression_()?; + if this.lexer.next().token != end_token { + this.lexer.backtrack(); + return Err(this.unexpected_token( + &end_token_and_pipe[..1], + this.lexer.current().token, + )); + } + this.expression_().map(move |e| Guard { + predicate: p, + expression: e, + }) + }, + PIPE, + ) + .map(Match::Guards) + } else if token == end_token { + self.expression_().map(|e| Match::Simple(e)) + } else { + self.lexer.backtrack(); + Err(self.unexpected_token(end_token_and_pipe, self.lexer.current().token)) + } + } -fn pattern(&mut self) -> ParseResult { - let name_token = self.lexer.next().token; - let name = self.lexer.current().value.clone(); - let pat = match name_token { - LBRACKET => { - expect!(self, RBRACKET); - Pattern::Constructor(intern("[]"), vec![]) + fn make_pattern(&mut self, name: InternedStr, args: F) -> ParseResult + where + F: FnOnce(&mut Parser) -> ParseResult>, + { + let c = name.chars().next().expect("char at 0"); + if c.is_uppercase() || name == intern(":") { + args(self).map(|ps| Pattern::Constructor(name, ps)) + } else if c == '_' { + Ok(Pattern::WildCard) + } else { + Ok(Pattern::Identifier(name)) } - NAME => self.make_pattern(name, |this| this.pattern_arguments())?, - NUMBER => Pattern::Number(FromStr::from_str(name.as_ref()).unwrap()), - LPARENS => { - if self.lexer.peek().token == RPARENS { - self.lexer.next(); - Pattern::Constructor(intern("()"), vec![]) - } - else { - let mut tuple_args = self.sep_by_1(|this| this.pattern(), COMMA)?; - expect!(self, RPARENS); - if tuple_args.len() == 1 { - tuple_args.pop().unwrap() + } + + fn pattern_arguments(&mut self) -> ParseResult> { + let mut parameters = vec![]; + loop { + let token = self.lexer.next().token; + match token { + NAME => { + let name = self.lexer.current().value; + let p = self.make_pattern(name, |_| Ok(vec![]))?; + parameters.push(p); + } + NUMBER => parameters.push(Pattern::Number( + FromStr::from_str(self.lexer.current().value.as_ref()).unwrap(), + )), + LPARENS => { + self.lexer.backtrack(); + parameters.push(self.pattern()?); } - else { - Pattern::Constructor(intern(tuple_name(tuple_args.len()).as_ref()), tuple_args) + LBRACKET => { + expect!(self, RBRACKET); + parameters.push(Pattern::Constructor(intern("[]"), vec![])); + } + _ => { + break; } } } - _ => unexpected!(self, [LBRACKET, NAME, NUMBER, LPARENS]) - }; - self.lexer.next(); - if self.lexer.current().token == OPERATOR && self.lexer.current().value.as_ref() == ":" { - Ok(Pattern::Constructor(self.lexer.current().value, vec![pat, self.pattern()?])) + self.lexer.backtrack(); + Ok(parameters) } - else { + + fn located_pattern(&mut self) -> ParseResult> { + let location = self.lexer.next().location; self.lexer.backtrack(); - Ok(pat) + self.pattern().map(|pattern| Located { + location, + node: pattern, + }) } -} -fn type_declaration(&mut self) -> ParseResult { - let mut name; - { + fn pattern(&mut self) -> ParseResult { let name_token = self.lexer.next().token; - name = self.lexer.current().value.clone(); - if name_token == LPARENS { - //Parse a name within parentheses - let function_name = self.lexer.next().token; - if function_name != NAME && function_name != OPERATOR { - unexpected!(self, [NAME, OPERATOR]); + let name = self.lexer.current().value.clone(); + let pat = match name_token { + LBRACKET => { + expect!(self, RBRACKET); + Pattern::Constructor(intern("[]"), vec![]) } - name = self.lexer.current().value.clone(); - expect!(self, RPARENS); - } - else if name_token != NAME { - unexpected!(self, [LPARENS, NAME]); + NAME => self.make_pattern(name, |this| this.pattern_arguments())?, + NUMBER => Pattern::Number(FromStr::from_str(name.as_ref()).unwrap()), + LPARENS => { + if self.lexer.peek().token == RPARENS { + self.lexer.next(); + Pattern::Constructor(intern("()"), vec![]) + } else { + let mut tuple_args = self.sep_by_1(|this| this.pattern(), COMMA)?; + expect!(self, RPARENS); + if tuple_args.len() == 1 { + tuple_args.pop().unwrap() + } else { + Pattern::Constructor( + intern(tuple_name(tuple_args.len()).as_ref()), + tuple_args, + ) + } + } + } + _ => unexpected!(self, [LBRACKET, NAME, NUMBER, LPARENS]), + }; + self.lexer.next(); + if self.lexer.current().token == OPERATOR && self.lexer.current().value.as_ref() == ":" { + Ok(Pattern::Constructor( + self.lexer.current().value, + vec![pat, self.pattern()?], + )) + } else { + self.lexer.backtrack(); + Ok(pat) } } - expect!(self, TYPEDECL); - let (context, typ) = self.constrained_type()?; - Ok(TypeDeclaration { name : name, typ : Qualified { constraints : context, value: typ } }) -} -fn constrained_type(&mut self) -> ParseResult<(Vec, Type)> { - debug!("Parse constrained type"); - let mut maybe_constraints = if self.lexer.next().token == LPARENS { - if self.lexer.peek().token == RPARENS { - self.lexer.next(); - vec![] - } - else { - let t = self.sep_by_1(|this| this.parse_type(), COMMA)?; - expect!(self, RPARENS); - t + fn type_declaration(&mut self) -> ParseResult { + let mut name; + { + let name_token = self.lexer.next().token; + name = self.lexer.current().value.clone(); + if name_token == LPARENS { + //Parse a name within parentheses + let function_name = self.lexer.next().token; + if function_name != NAME && function_name != OPERATOR { + unexpected!(self, [NAME, OPERATOR]); + } + name = self.lexer.current().value.clone(); + expect!(self, RPARENS); + } else if name_token != NAME { + unexpected!(self, [LPARENS, NAME]); + } } + expect!(self, TYPEDECL); + let (constraints, typ) = self.constrained_type()?; + Ok(TypeDeclaration { + name, + typ: Qualified { + constraints, + value: typ, + }, + }) } - else { - self.lexer.backtrack(); - vec![self.parse_type()?] - }; - debug!("{:?}", maybe_constraints); - //If there is => arrow we proceed to parse the type - let typ = match self.lexer.next().token{ - CONTEXTARROW => self.parse_type(), - ARROW => { - self.lexer.backtrack(); - let mut args = Vec::new(); - swap(&mut args, &mut maybe_constraints); - self.parse_return_type(make_tuple_type(args)) - } - _ => {//If no => was found, translate the constraint list into a type - self.lexer.backtrack(); - let mut args = Vec::new(); - swap(&mut args, &mut maybe_constraints); - Ok(make_tuple_type(args)) - } - }; - Ok((make_constraints(maybe_constraints), typ?)) -} -fn constructor_type(&mut self, arity : &mut isize, data_def: &DataDefinition) -> ParseResult { - debug!("Parse constructor type"); - let token = self.lexer.next().token; - let typ = if token == NAME { - *arity += 1; - let arg = if self.lexer.current().value.chars().next().expect("char at 0").is_lowercase() { - Type::new_var(self.lexer.current().value) - } - else { - Type::new_op(self.lexer.current().value.clone(), Vec::new()) + fn constrained_type(&mut self) -> ParseResult<(Vec, Type)> { + debug!("Parse constrained type"); + let mut maybe_constraints = if self.lexer.next().token == LPARENS { + if self.lexer.peek().token == RPARENS { + self.lexer.next(); + vec![] + } else { + let t = self.sep_by_1(|this| this.parse_type(), COMMA)?; + expect!(self, RPARENS); + t + } + } else { + self.lexer.backtrack(); + vec![self.parse_type()?] }; - function_type_(arg, self.constructor_type(arity, data_def)?) - } - else if token == LPARENS { - *arity += 1; - let arg = self.parse_type()?; - expect!(self, RPARENS); - function_type_(arg, self.constructor_type(arity, data_def)?) - } - else { - data_def.typ.value.clone() - }; - Ok(typ) -} - + debug!("{:?}", maybe_constraints); + //If there is => arrow we proceed to parse the type + let typ = match self.lexer.next().token { + CONTEXTARROW => self.parse_type(), + ARROW => { + self.lexer.backtrack(); + let mut args = vec![]; + swap(&mut args, &mut maybe_constraints); + self.parse_return_type(make_tuple_type(args)) + } + _ => { + //If no => was found, translate the constraint list into a type + self.lexer.backtrack(); + let mut args = vec![]; + swap(&mut args, &mut maybe_constraints); + Ok(make_tuple_type(args)) + } + }; + Ok((make_constraints(maybe_constraints), typ?)) + } -fn data_definition(&mut self) -> ParseResult { - expect!(self, DATA); + fn constructor_type( + &mut self, + arity: &mut isize, + data_def: &DataDefinition, + ) -> ParseResult { + debug!("Parse constructor type"); + let token = self.lexer.next().token; + let typ = if token == NAME { + *arity += 1; + let arg = if self + .lexer + .current() + .value + .chars() + .next() + .expect("char at 0") + .is_lowercase() + { + Type::new_var(self.lexer.current().value) + } else { + Type::new_op(self.lexer.current().value.clone(), vec![]) + }; + function_type_(arg, self.constructor_type(arity, data_def)?) + } else if token == LPARENS { + *arity += 1; + let arg = self.parse_type()?; + expect!(self, RPARENS); + function_type_(arg, self.constructor_type(arity, data_def)?) + } else { + data_def.typ.value.clone() + }; + Ok(typ) + } - let mut definition = DataDefinition { - constructors : Vec::new(), - typ : qualified(vec![], Type::new_var(intern("a"))), - parameters : HashMap::new(), - deriving: Vec::new() - }; - definition.typ.value = self.data_lhs()?; - expect!(self, EQUALSSIGN); - - definition.constructors = self.sep_by_1_func(|this| this.constructor(&definition), - |t : &Token| t.token == PIPE)?; - for ii in 0..definition.constructors.len() { - definition.constructors[ii].tag = ii as isize; - } - definition.deriving = self.deriving()?; - Ok(definition) -} + fn data_definition(&mut self) -> ParseResult { + expect!(self, DATA); -fn newtype(&mut self) -> ParseResult { - debug!("Parsing newtype"); - expect!(self, NEWTYPE); - let typ = self.data_lhs()?; - expect!(self, EQUALSSIGN); - let name = expect!(self, NAME).value; - let arg_type = match self.sub_type()? { - Some(t) => t, - None => return self.error("Parse error when parsing argument to new type".to_string()) - }; - - Ok(Newtype { - typ: qualified(Vec::new(), typ.clone()), - constructor_name: name, - constructor_type: qualified(Vec::new(), function_type_(arg_type, typ)), - deriving: self.deriving()? - }) -} + let mut definition = + DataDefinition { + constructors: vec![], + typ: qualified(vec![], "a".into()), + parameters: HashMap::new(), + deriving: vec![], + }; + definition.typ.value = self.data_lhs()?; + expect!(self, EQUALSSIGN); + + definition.constructors = + self.sep_by_1_func( + |this| this.constructor(&definition), + |t: &Token| t.token == PIPE, + )?; + for ii in 0..definition.constructors.len() { + definition.constructors[ii].tag = ii as isize; + } + definition.deriving = self.deriving()?; + Ok(definition) + } -fn data_lhs(&mut self) -> ParseResult { - let name = expect!(self, NAME).value.clone(); - let mut typ = Type::Constructor(TypeConstructor { name: name, kind: Kind::Star.clone() }); - while self.lexer.next().token == NAME { - typ = Type::Application(Box::new(typ), Box::new(Type::new_var(self.lexer.current().value))); - } - self.lexer.backtrack(); - Parser::::set_kind(&mut typ, 1); - Ok(typ) -} + fn newtype(&mut self) -> ParseResult { + debug!("Parsing newtype"); + expect!(self, NEWTYPE); + let typ = self.data_lhs()?; + expect!(self, EQUALSSIGN); + let name = expect!(self, NAME).value; + let arg_type = match self.sub_type()? { + Some(t) => t, + None => return self.error("Parse error when parsing argument to new type".to_string()), + }; -fn deriving(&mut self) -> ParseResult> { - if self.lexer.next().token == DERIVING { - expect!(self, LPARENS); - let vec = self.sep_by_1(|this| Ok(expect!(this, NAME).value), COMMA)?; - expect!(self, RPARENS); - Ok(vec) - } - else { - self.lexer.backtrack(); - Ok(Vec::new()) + Ok(Newtype { + typ: qualified(vec![], typ.clone()), + constructor_name: name, + constructor_type: qualified(vec![], function_type_(arg_type, typ)), + deriving: self.deriving()?, + }) } -} -fn set_kind(typ: &mut Type, kind: isize) { - match typ { - &mut Type::Application(ref mut lhs, _) => { - Parser::::set_kind(&mut **lhs, kind + 1) - } - _ => { - *typ.mut_kind() = Kind::new(kind) + fn data_lhs(&mut self) -> ParseResult { + let name = expect!(self, NAME).value.clone(); + let mut typ = Type::Constructor(TypeConstructor { + name, + kind: Kind::Star.clone(), + }); + while self.lexer.next().token == NAME { + typ = Type::Application(typ.into(), Type::new_var(self.lexer.current().value).into()); } + self.lexer.backtrack(); + Parser::::set_kind(&mut typ, 1); + Ok(typ) } -} -fn sub_type(&mut self) -> ParseResult> { - let token = (*self.lexer.next()).clone(); - let t = match token.token { - LBRACKET => { - self.lexer.backtrack(); - Some(self.parse_type()?) - } - LPARENS => { + fn deriving(&mut self) -> ParseResult> { + if self.lexer.next().token == DERIVING { + expect!(self, LPARENS); + let vec = self.sep_by_1(|this| Ok(expect!(this, NAME).value), COMMA)?; + expect!(self, RPARENS); + Ok(vec) + } else { self.lexer.backtrack(); - Some(self.parse_type()?) - } - NAME => { - if token.value.chars().next().expect("char at 0").is_uppercase() { - Some(Type::new_op(token.value, Vec::new())) - } - else { - Some(Type::new_var(token.value)) - } - } - _ => { self.lexer.backtrack(); None } - }; - Ok(t) -} + Ok(vec![]) + } + } -fn parse_type(&mut self) -> ParseResult { - let token = (*self.lexer.next()).clone(); - match token.token { - LBRACKET => { - if self.lexer.next().token == RBRACKET { - let list = Type::new_op_kind(intern("[]"), vec![], Kind::new(2)); - self.parse_return_type(list) + fn set_kind(typ: &mut Type, kind: isize) { + match typ { + &mut Type::Application(ref mut lhs, _) => Parser::::set_kind(lhs, kind + 1), + _ => *typ.mut_kind() = Kind::new(kind), + } + } + + fn sub_type(&mut self) -> ParseResult> { + let token = (*self.lexer.next()).clone(); + let t = match token.token { + LBRACKET => { + self.lexer.backtrack(); + Some(self.parse_type()?) } - else { + LPARENS => { self.lexer.backtrack(); - let t = self.parse_type()?; - expect!(self, RBRACKET); - let list = list_type(t); - self.parse_return_type(list) + Some(self.parse_type()?) } - } - LPARENS => { - if self.lexer.peek().token == RPARENS { - self.lexer.next(); - self.parse_return_type(Type::new_op(intern("()"), vec![])) + NAME => { + if token + .value + .chars() + .next() + .expect("char at 0") + .is_uppercase() + { + Some(Type::new_op(token.value, vec![])) + } else { + Some(Type::new_var(token.value)) + } } - else { - let t = self.parse_type()?; - match self.lexer.next().token { - COMMA => { - let mut tuple_args: Vec = self.sep_by_1(|this| this.parse_type(), COMMA)?; - tuple_args.insert(0, t); - expect!(self, RPARENS); - - self.parse_return_type(make_tuple_type(tuple_args)) - } - RPARENS => { - self.parse_return_type(t) - } - _ => { - unexpected!(self, [COMMA, RPARENS]) - } + _ => { + self.lexer.backtrack(); + None + } + }; + Ok(t) + } + + fn parse_type(&mut self) -> ParseResult { + let token = (*self.lexer.next()).clone(); + match token.token { + LBRACKET => { + if self.lexer.next().token == RBRACKET { + let list = Type::new_op_kind(intern("[]"), vec![], Kind::new(2)); + self.parse_return_type(list) + } else { + self.lexer.backtrack(); + let t = self.parse_type()?; + expect!(self, RBRACKET); + let list = list_type(t); + self.parse_return_type(list) } } - } - NAME => { - let mut type_arguments = Vec::new(); - loop { - match self.sub_type()? { - Some(typ) => type_arguments.push(typ), - None => break + LPARENS => { + if self.lexer.peek().token == RPARENS { + self.lexer.next(); + self.parse_return_type(Type::new_op(intern("()"), vec![])) + } else { + let t = self.parse_type()?; + match self.lexer.next().token { + COMMA => { + let mut tuple_args: Vec = + self.sep_by_1(|this| this.parse_type(), COMMA)?; + tuple_args.insert(0, t); + expect!(self, RPARENS); + + self.parse_return_type(make_tuple_type(tuple_args)) + } + RPARENS => self.parse_return_type(t), + _ => { + unexpected!(self, [COMMA, RPARENS]) + } + } } } + NAME => { + let mut type_arguments = vec![]; - let this_type = if token.value.chars().next().expect("char at 0").is_uppercase() { - Type::new_op(token.value, type_arguments) - } - else { - Type::new_var_args(token.value, type_arguments) - }; - self.parse_return_type(this_type) - } - _ => unexpected!(self, [LBRACKET, LPARENS, NAME]) - } -} + while let Some(typ) = self.sub_type()? { + type_arguments.push(typ); + } -fn parse_return_type(&mut self, typ : Type) -> ParseResult { - let arrow = self.lexer.next().token; - if arrow == ARROW { - Ok(function_type_(typ, self.parse_type()?)) - } - else { - self.lexer.backtrack(); - Ok(typ) + let this_type = if token + .value + .chars() + .next() + .expect("char at 0") + .is_uppercase() + { + Type::new_op(token.value, type_arguments) + } else { + Type::new_var_args(token.value, type_arguments) + }; + self.parse_return_type(this_type) + } + _ => unexpected!(self, [LBRACKET, LPARENS, NAME]), + } } -} - -fn sep_by_1(&mut self, f : F, sep : TokenEnum) -> ParseResult> - where F: FnMut(&mut Parser) -> ParseResult { - self.sep_by_1_func(f, |tok| tok.token == sep) -} -fn sep_by_1_func(&mut self, mut f : F, mut sep: P) -> ParseResult> - where F: FnMut(&mut Parser) -> ParseResult, P : FnMut(&Token) -> bool { - let mut result = Vec::new(); - loop { - result.push(f(self)?); - if !sep(self.lexer.next()) { + fn parse_return_type(&mut self, typ: Type) -> ParseResult { + let arrow = self.lexer.next().token; + if arrow == ARROW { + Ok(function_type_(typ, self.parse_type()?)) + } else { self.lexer.backtrack(); - break; + Ok(typ) } } - Ok(result) -} -}//end impl Parser -fn make_constraints(types: Vec) -> Vec { - types.into_iter().map(|typ| { - match typ { - Type::Application(lhs, rhs) => { - Constraint { class: lhs.ctor().name.clone(), variables: vec![rhs.var().clone()] } + fn sep_by_1(&mut self, f: F, sep: TokenEnum) -> ParseResult> + where + F: FnMut(&mut Parser) -> ParseResult, + { + self.sep_by_1_func(f, |tok| tok.token == sep) + } + + fn sep_by_1_func(&mut self, mut f: F, mut sep: P) -> ParseResult> + where + F: FnMut(&mut Parser) -> ParseResult, + P: FnMut(&Token) -> bool, + { + let mut result = vec![]; + loop { + result.push(f(self)?); + if !sep(self.lexer.next()) { + self.lexer.backtrack(); + break; } - _ => panic!("Parse error in constraint, non applied type") } - }).collect() -} + Ok(result) + } +} //end impl Parser -fn make_application>(f : TypedExpr, args : I) -> TypedExpr { +fn make_constraints(types: Vec) -> Vec { + types + .into_iter() + .map(|typ| match typ { + Type::Application(lhs, rhs) => Constraint { + class: lhs.ctor().name.clone(), + variables: vec![rhs.var().clone()], + }, + _ => panic!("Parse error in constraint, non applied type"), + }) + .collect() +} + +fn make_application>(f: TypedExpr, args: I) -> TypedExpr { let mut func = f; - for a in args { + for a in args { let loc = func.location.clone(); - func = TypedExpr::with_location(Apply(Box::new(func), Box::new(a)), loc); - } + func = TypedExpr::with_location(Apply(func.into(), a.into()), loc); + } func } -fn make_lambda>>(args : Iter, body : TypedExpr) -> TypedExpr { - let mut body = body; - for a in args.rev() { +fn make_lambda>>( + args: Iter, + body: TypedExpr, +) -> TypedExpr { + let mut body = body; + for a in args.rev() { let loc = body.location.clone(); - body = TypedExpr::with_location(Lambda(a, Box::new(body)), loc); - } + body = TypedExpr::with_location(Lambda(a, body.into()), loc); + } body } //Create a tuple with the constructor name inferred from the number of arguments passed in -fn new_tuple(arguments : Vec) -> TypedExpr { - let name = TypedExpr::new(Identifier(intern(tuple_name(arguments.len()).as_ref()))); - make_application(name, arguments.into_iter()) +fn new_tuple(arguments: Vec) -> TypedExpr { + let name = TypedExpr::new(Identifier(intern(tuple_name(arguments.len()).as_ref()))); + make_application(name, arguments.into_iter()) } -fn make_tuple_type(mut types : Vec) -> Type { +fn make_tuple_type(mut types: Vec) -> Type { if types.len() == 1 { types.pop().unwrap() - } - else { - Type::new_op(intern(tuple_name(types.len()).as_ref()), types) + } else { + Type::new_op(intern(tuple_name(types.len()).as_ref()), types) } } pub fn parse_string(contents: &str) -> ParseResult> { - let mut modules = Vec::new(); + let mut modules = vec![]; let mut visited = HashSet::new(); parse_modules_(&mut visited, &mut modules, "", contents)?; Ok(modules) @@ -1143,7 +1235,7 @@ pub fn parse_string(contents: &str) -> ParseResult> { ///Parses a module and all its imports ///If the modules contain a cyclic dependency fail is called. pub fn parse_modules(modulename: &str) -> ParseResult> { - let mut modules = Vec::new(); + let mut modules = vec![]; let mut visited = HashSet::new(); let contents = get_contents(modulename)?; parse_modules_(&mut visited, &mut modules, modulename, contents.as_ref())?; @@ -1159,7 +1251,12 @@ fn get_contents(modulename: &str) -> io::Result<::std::string::String> { Ok(contents) } -fn parse_modules_(visited: &mut HashSet, modules: &mut Vec, modulename: &str, contents: &str) -> ParseResult<()> { +fn parse_modules_( + visited: &mut HashSet, + modules: &mut Vec, + modulename: &str, + contents: &str, +) -> ParseResult<()> { let mut parser = Parser::new(contents.chars()); let module = parser.module()?; let interned_name = intern(modulename); @@ -1167,8 +1264,7 @@ fn parse_modules_(visited: &mut HashSet, modules: &mut Vec, for import in module.imports.iter() { if visited.contains(&import.module) { return parser.error("Cyclic dependency in modules".to_string()); - } - else if modules.iter().all(|m| m.name != import.module) { + } else if modules.iter().all(|m| m.name != import.module) { //parse the module if it is not parsed let import_module = import.module.as_ref(); let contents_next = get_contents(import_module)?; @@ -1183,265 +1279,388 @@ fn parse_modules_(visited: &mut HashSet, modules: &mut Vec, #[cfg(test)] mod tests { -use crate::interner::*; -use crate::lexer::{Location, Located }; -use crate::parser::*; -use crate::typecheck::{identifier, apply, op_apply, number, rational, let_, case, if_else}; -use std::path::Path; -use std::io::Read; -use std::fs::File; -use test::Bencher; - - -#[test] -fn simple() -{ - let mut parser = Parser::new("2 + 3".chars()); - let expr = parser.expression_().unwrap(); - assert_eq!(expr, op_apply(number(2), intern("+"), number(3))); -} -#[test] -fn binding() -{ - let mut parser = Parser::new("test x = x + 3".chars()); - let bind = parser.binding().unwrap(); - assert_eq!(bind.arguments, vec![Pattern::Identifier(intern("x"))]); - assert_eq!(bind.matches, Match::Simple(op_apply(identifier("x"), intern("+"), number(3)))); - assert_eq!(bind.name, intern("test")); -} + use { + crate::{ + interner::*, + lexer::{ + Located, + Location, + }, + parser::*, + typecheck::{ + apply, + case, + identifier, + if_else, + let_, + number, + op_apply, + rational, + }, + }, + std::{ + fs::File, + io::Read, + path::Path, + }, + test::Bencher, + }; -#[test] -fn double() -{ - let mut parser = Parser::new("test = 3.14".chars()); - let bind = parser.binding().unwrap(); - assert_eq!(bind.matches, Match::Simple(rational(3.14))); - assert_eq!(bind.name, intern("test")); -} + #[test] + fn simple() { + let mut parser = Parser::new("2 + 3".chars()); + let expr = parser.expression_().unwrap(); + assert_eq!(expr, op_apply(number(2), intern("+"), number(3))); + } + #[test] + fn binding() { + let mut parser = Parser::new("test x = x + 3".chars()); + let bind = parser.binding().unwrap(); + assert_eq!(bind.arguments, vec![Pattern::Identifier(intern("x"))]); + assert_eq!( + bind.matches, + Match::Simple(op_apply(identifier("x"), intern("+"), number(3))) + ); + assert_eq!(bind.name, intern("test")); + } + + #[test] + fn double() { + let mut parser = Parser::new("test = 3.14".chars()); + let bind = parser.binding().unwrap(); + assert_eq!(bind.matches, Match::Simple(rational(3.14))); + assert_eq!(bind.name, intern("test")); + } -#[test] -fn parse_let() { - let mut parser = Parser::new( -r" + #[test] + fn parse_let() { + let mut parser = Parser::new( + r" let test = add 3 2 -in test - 2".chars()); - let expr = parser.expression_().unwrap(); - let bind = Binding { arguments: vec![], name: intern("test"), typ: Default::default(), - matches: Match::Simple(apply(apply(identifier("add"), number(3)), number(2))), where_bindings: None }; - assert_eq!(expr, let_(vec![bind], op_apply(identifier("test"), intern("-"), number(2)))); -} +in test - 2" + .chars(), + ); + let expr = parser.expression_().unwrap(); + let bind = + Binding { + arguments: vec![], + name: intern("test"), + typ: <_>::default(), + matches: Match::Simple(apply(apply(identifier("add"), number(3)), number(2))), + where_bindings: None, + }; + assert_eq!( + expr, + let_( + vec![bind], + op_apply(identifier("test"), intern("-"), number(2)) + ) + ); + } -#[test] -fn parse_case() { - let mut parser = Parser::new( -r"case [] of + #[test] + fn parse_case() { + let mut parser = Parser::new( + r"case [] of x:xs -> x [] -> 2 -".chars()); - let expression = parser.expression_().unwrap(); - let alt = Alternative { - pattern: Located { - location: Location::eof(), - node: Pattern::Constructor(intern(":"), vec![Pattern::Identifier(intern("x")), Pattern::Identifier(intern("xs"))]) - }, - matches: Match::Simple(identifier("x")), - where_bindings: None - }; - let alt2 = Alternative { - pattern: Located { location: Location::eof(), node: Pattern::Constructor(intern("[]"), vec![]) }, - matches: Match::Simple(number(2)), - where_bindings: None - }; - assert_eq!(expression, case(identifier("[]"), vec![alt, alt2])); -} +" + .chars(), + ); + let expression = parser.expression_().unwrap(); + let alt = Alternative { + pattern: Located { + location: Location::eof(), + node: Pattern::Constructor( + intern(":"), + vec![ + Pattern::Identifier(intern("x")), + Pattern::Identifier(intern("xs")), + ], + ), + }, + matches: Match::Simple(identifier("x")), + where_bindings: None, + }; + let alt2 = Alternative { + pattern: Located { + location: Location::eof(), + node: Pattern::Constructor(intern("[]"), vec![]), + }, + matches: Match::Simple(number(2)), + where_bindings: None, + }; + assert_eq!(expression, case(identifier("[]"), vec![alt, alt2])); + } -#[test] -fn parse_type() { - let mut parser = Parser::new( -r"(.) :: (b -> c) -> (a -> b) -> (a -> c)".chars()); - let type_decl = parser.type_declaration().unwrap(); - let a = &Type::new_var(intern("a")); - let b = &Type::new_var(intern("b")); - let c = &Type::new_var(intern("c")); - let f = function_type(&function_type(b, c), &function_type(&function_type(a, b), &function_type(a, c))); - - assert_eq!(type_decl.name, intern(".")); - assert_eq!(type_decl.typ.value, f); -} -#[test] -fn parse_data() { - let mut parser = Parser::new( -r"data Bool = True | False".chars()); - let data = parser.data_definition() - .unwrap(); - - let b = qualified(vec![], bool_type()); - let t = Constructor { name: intern("True"), tag:0, arity:0, typ: b.clone() }; - let f = Constructor { name: intern("False"), tag:1, arity:0, typ: b.clone() }; - assert_eq!(data.typ, b); - assert_eq!(data.constructors[0], t); - assert_eq!(data.constructors[1], f); -} + #[test] + fn parse_type() { + let mut parser = Parser::new(r"(.) :: (b -> c) -> (a -> b) -> (a -> c)".chars()); + let type_decl = parser.type_declaration().unwrap(); + let a = &"a".into(); + let b = &Type::new_var("b".into()); + let c = &Type::new_var("c".into()); + let f = function_type( + &function_type(b, c), + &function_type(&function_type(a, b), &function_type(a, c)), + ); + + assert_eq!(type_decl.name, intern(".")); + assert_eq!(type_decl.typ.value, f); + } + #[test] + fn parse_data() { + let mut parser = Parser::new(r"data Bool = True | False".chars()); + let data = parser.data_definition().unwrap(); + + let b = qualified(vec![], bool_type()); + let t = + Constructor { + name: intern("True"), + tag: 0, + arity: 0, + typ: b.clone(), + }; + let f = Constructor { + name: intern("False"), + tag: 1, + arity: 0, + typ: b.clone(), + }; + assert_eq!(data.typ, b); + assert_eq!(data.constructors[0], t); + assert_eq!(data.constructors[1], f); + } -#[test] -fn parse_data_2() { - let mut parser = Parser::new( -r"data List a = Cons a (List a) | Nil".chars()); - let data = parser.data_definition() - .unwrap(); - - let list = Type::new_op(intern("List"), vec![Type::new_var(intern("a"))]); - let cons = Constructor { name: intern("Cons"), tag:0, arity:2, typ: qualified(vec![], function_type(&Type::new_var(intern("a")), &function_type(&list, &list))) }; - let nil = Constructor { name: intern("Nil"), tag:1, arity:0, typ: qualified(vec![], list.clone()) }; - assert_eq!(data.typ.value, list); - assert_eq!(data.constructors[0], cons); - assert_eq!(data.constructors[1], nil); -} + #[test] + fn parse_data_2() { + let mut parser = Parser::new(r"data List a = Cons a (List a) | Nil".chars()); + let data = parser.data_definition().unwrap(); + + let list = Type::new_op(intern("List"), vec!["a".into()]); + let cons = Constructor { + name: intern("Cons"), + tag: 0, + arity: 2, + typ: qualified( + vec![], + function_type(&"a".into(), &function_type(&list, &list)), + ), + }; + let nil = Constructor { + name: intern("Nil"), + tag: 1, + arity: 0, + typ: qualified(vec![], list.clone()), + }; + assert_eq!(data.typ.value, list); + assert_eq!(data.constructors[0], cons); + assert_eq!(data.constructors[1], nil); + } -#[test] -fn parse_tuple() { - let mut parser = Parser::new( -r"(1, x)".chars()); - let expr = parser.expression_().unwrap(); + #[test] + fn parse_tuple() { + let mut parser = Parser::new(r"(1, x)".chars()); + let expr = parser.expression_().unwrap(); - assert_eq!(expr, apply(apply(identifier("(,)"), number(1)), identifier("x"))); -} + assert_eq!( + expr, + apply(apply(identifier("(,)"), number(1)), identifier("x")) + ); + } -#[test] -fn parse_unit() { - let mut parser = Parser::new( -r"case () :: () of - () -> 1".chars()); - let expr = parser.expression_().unwrap(); - - assert_eq!(expr, case(TypedExpr::new(TypeSig(Box::new(identifier("()")), qualified(vec![], Type::new_op(intern("()"), vec![])))), - vec![Alternative { - pattern: Located { location: Location::eof(), node: Pattern::Constructor(intern("()"), vec![]) }, - matches: Match::Simple(number(1)), - where_bindings: None - } ])); -} + #[test] + fn parse_unit() { + let mut parser = Parser::new( + r"case () :: () of + () -> 1" + .chars(), + ); + let expr = parser.expression_().unwrap(); + + assert_eq!( + expr, + case( + TypedExpr::new(TypeSig( + identifier("()").into(), + qualified(vec![], Type::new_op(intern("()"), vec![])) + )), + vec![Alternative { + pattern: Located { + location: Location::eof(), + node: Pattern::Constructor(intern("()"), vec![]) + }, + matches: Match::Simple(number(1)), + where_bindings: None + }] + ) + ); + } -#[test] -fn test_operators() { - let mut parser = Parser::new("1 : 2 : []".chars()); - let expr = parser.expression_().unwrap(); - assert_eq!(expr, op_apply(number(1), intern(":"), op_apply(number(2), intern(":"), identifier("[]")))); -} + #[test] + fn test_operators() { + let mut parser = Parser::new("1 : 2 : []".chars()); + let expr = parser.expression_().unwrap(); + assert_eq!( + expr, + op_apply( + number(1), + intern(":"), + op_apply(number(2), intern(":"), identifier("[]")) + ) + ); + } -#[test] -fn parse_instance_class() { - let mut parser = Parser::new( -r"class Eq a where + #[test] + fn parse_instance_class() { + let mut parser = Parser::new( + r"class Eq a where (==) :: a -> a -> Bool (/=) x y = not (x == y) (/=) :: a -> a -> Bool instance Eq a => Eq [a] where - (==) xs ys = undefined".chars()); - let module = parser.module().unwrap(); - - assert_eq!(module.classes[0].name, intern("Eq")); - assert_eq!(module.classes[0].bindings[0].name, intern("#Eq/=")); - assert_eq!(module.classes[0].bindings.len(), 1); - assert_eq!(module.classes[0].declarations[0].name, intern("==")); - assert_eq!(module.classes[0].declarations[1].name, intern("/=")); - assert_eq!(module.instances[0].classname, intern("Eq")); - assert_eq!(module.instances[0].constraints[0].class, intern("Eq")); - assert_eq!(module.instances[0].typ, list_type(Type::new_var(intern("a")))); -} -#[test] -fn parse_super_class() { - let mut parser = Parser::new( -r"class Eq a => Ord a where + (==) xs ys = undefined" + .chars(), + ); + let module = parser.module().unwrap(); + + assert_eq!(module.classes[0].name, intern("Eq")); + assert_eq!(module.classes[0].bindings[0].name, intern("#Eq/=")); + assert_eq!(module.classes[0].bindings.len(), 1); + assert_eq!(module.classes[0].declarations[0].name, intern("==")); + assert_eq!(module.classes[0].declarations[1].name, intern("/=")); + assert_eq!(module.instances[0].classname, intern("Eq")); + assert_eq!(module.instances[0].constraints[0].class, intern("Eq")); + assert_eq!(module.instances[0].typ, list_type("a".into())); + } + #[test] + fn parse_super_class() { + let mut parser = Parser::new( + r"class Eq a => Ord a where (<) :: a -> a -> Bool -".chars()); - let module = parser.module().unwrap(); - - let cls = &module.classes[0]; - let a = TypeVariable::new(intern("a")); - assert_eq!(cls.name, intern("Ord")); - assert_eq!(cls.variable, a); - assert_eq!(cls.constraints[0].class, intern("Eq")); - assert_eq!(cls.constraints[0].variables[0], a); -} -#[test] -fn parse_do_expr() { - let mut parser = Parser::new( -r"main = do +" + .chars(), + ); + let module = parser.module().unwrap(); + + let cls = &module.classes[0]; + let a = TypeVariable::new("a".into()); + assert_eq!(cls.name, intern("Ord")); + assert_eq!(cls.variable, a); + assert_eq!(cls.constraints[0].class, intern("Eq")); + assert_eq!(cls.constraints[0].variables[0], a); + } + #[test] + fn parse_do_expr() { + let mut parser = + Parser::new( + r"main = do putStrLn test s <- getContents return s -".chars()); - let module = parser.module().unwrap(); - - let b = TypedExpr::new(Do(vec![ - DoBinding::DoExpr(apply(identifier("putStrLn"), identifier("test"))), - DoBinding::DoBind(Located { location: Location::eof(), node: Pattern::Identifier(intern("s")) }, identifier("getContents")) - ], Box::new(apply(identifier("return"), identifier("s"))))); - assert_eq!(module.bindings[0].matches, Match::Simple(b)); -} -#[test] -fn lambda_pattern() { - let mut parser = Parser::new(r"\(x, _) -> x".chars()); - let expr = parser.expression_().unwrap(); - let pattern = Pattern::Constructor(intern("(,)"), vec![Pattern::Identifier(intern("x")), Pattern::WildCard]); - assert_eq!(expr, TypedExpr::new(Lambda(pattern, Box::new(identifier("x"))))); -} - +" + .chars(), + ); + let module = parser.module().unwrap(); + + let b = TypedExpr::new(Do( + vec![ + DoBinding::DoExpr(apply(identifier("putStrLn"), identifier("test"))), + DoBinding::DoBind( + Located { + location: Location::eof(), + node: Pattern::Identifier(intern("s")), + }, + identifier("getContents"), + ), + ], + apply(identifier("return"), identifier("s")).into(), + )); + assert_eq!(module.bindings[0].matches, Match::Simple(b)); + } + #[test] + fn lambda_pattern() { + let mut parser = Parser::new(r"\(x, _) -> x".chars()); + let expr = parser.expression_().unwrap(); + let pattern = Pattern::Constructor( + intern("(,)"), + vec![Pattern::Identifier(intern("x")), Pattern::WildCard], + ); + assert_eq!( + expr, + TypedExpr::new(Lambda(pattern, identifier("x").into())).into() + ); + } -#[test] -fn parse_imports() { - let mut parser = Parser::new( -r"import Hello + #[test] + fn parse_imports() { + let mut parser = Parser::new( + r"import Hello import World () import Prelude (id, sum) -".chars()); - let module = parser.module().unwrap(); - - assert_eq!(module.imports[0].module.as_ref(), "Hello"); - assert_eq!(module.imports[0].imports, None); - assert_eq!(module.imports[1].module.as_ref(), "World"); - assert_eq!(module.imports[1].imports, Some(Vec::new())); - assert_eq!(module.imports[2].module.as_ref(), "Prelude"); - assert_eq!(module.imports[2].imports, Some(vec![intern("id"), intern("sum")])); -} -#[test] -fn parse_module_imports() { - let modules = parse_modules("Test").unwrap(); +" + .chars(), + ); + let module = parser.module().unwrap(); + + assert_eq!(module.imports[0].module.as_ref(), "Hello"); + assert_eq!(module.imports[0].imports, None); + assert_eq!(module.imports[1].module.as_ref(), "World"); + assert_eq!(module.imports[1].imports, Some(vec![])); + assert_eq!(module.imports[2].module.as_ref(), "Prelude"); + assert_eq!( + module.imports[2].imports, + Some(vec![intern("id"), intern("sum")]) + ); + } + #[test] + fn parse_module_imports() { + let modules = parse_modules("Test").unwrap(); - assert_eq!(modules[0].name.as_ref(), "Prelude"); - assert_eq!(modules[1].name.as_ref(), "Test"); - assert_eq!(modules[1].imports[0].module.as_ref(), "Prelude"); -} + assert_eq!(modules[0].name.as_ref(), "Prelude"); + assert_eq!(modules[1].name.as_ref(), "Test"); + assert_eq!(modules[1].imports[0].module.as_ref(), "Prelude"); + } -#[test] -fn parse_guards() { - let mut parser = Parser::new( -r" + #[test] + fn parse_guards() { + let mut parser = Parser::new( + r" test x | x = 1 | otherwise = 0 -".chars()); - let binding = parser.binding().unwrap(); - let b2 = Binding { arguments: vec![Pattern::Identifier(intern("x"))], name: intern("test"), typ: Default::default(), - matches: Match::Guards(vec![ - Guard { predicate: identifier("x"), expression: number(1) }, - Guard { predicate: identifier("otherwise"), expression: number(0) }, - ]), - where_bindings: None - }; - assert_eq!(binding, b2); -} +" + .chars(), + ); + let binding = parser.binding().unwrap(); + let b2 = Binding { + arguments: vec![Pattern::Identifier(intern("x"))], + name: intern("test"), + typ: <_>::default(), + matches: Match::Guards(vec![ + Guard { + predicate: identifier("x"), + expression: number(1), + }, + Guard { + predicate: identifier("otherwise"), + expression: number(0), + }, + ]), + where_bindings: None, + }; + assert_eq!(binding, b2); + } -#[test] -fn parse_fixity() { - let mut parser = Parser::new( -r" + #[test] + fn parse_fixity() { + let mut parser = Parser::new( + r" test x y = 2 infixr 5 `test` @@ -1449,51 +1668,77 @@ infixr 5 `test` infixr 6 `test2`, |< test2 x y = 1 -".chars()); - let module = parser.module().unwrap(); - assert_eq!(module.fixity_declarations, [ - FixityDeclaration { assoc: Assoc::Right, precedence: 5, operators: vec![intern("test")] }, - FixityDeclaration { assoc: Assoc::Right, precedence: 6, operators: vec![intern("test2"), intern("|<")] }, - ]); -} +" + .chars(), + ); + let module = parser.module().unwrap(); + assert_eq!( + module.fixity_declarations, + [ + FixityDeclaration { + assoc: Assoc::Right, + precedence: 5, + operators: vec![intern("test")] + }, + FixityDeclaration { + assoc: Assoc::Right, + precedence: 6, + operators: vec![intern("test2"), intern("|<")] + }, + ] + ); + } -#[test] -fn deriving() { - let mut parser = Parser::new( -r"data Test = A | B + #[test] + fn deriving() { + let mut parser = Parser::new( + r"data Test = A | B deriving(Eq, Debug) dummy = 1 -".chars()); - let module = parser.module().unwrap(); - let data = &module.data_definitions[0]; - assert_eq!(data.typ, qualified(Vec::new(), Type::new_op(intern("Test"), Vec::new()))); - assert_eq!(data.deriving, [intern("Eq"), intern("Debug")]); -} +" + .chars(), + ); + let module = parser.module().unwrap(); + let data = &module.data_definitions[0]; + assert_eq!( + data.typ, + qualified(vec![], Type::new_op(intern("Test"), vec![])) + ); + assert_eq!(data.deriving, [intern("Eq"), intern("Debug")]); + } -#[test] -fn test_if_else() { - let mut parser = Parser::new( -r" + #[test] + fn test_if_else() { + let mut parser = Parser::new( + r" if test 1 then 1 else if True then 2 else 3 + 2 -".chars()); - let e = parser.expression_().unwrap(); - assert_eq!(e, - if_else(apply(identifier("test"), number(1)) - , number(1) - , if_else(identifier("True") - , number(2) - , op_apply(number(3), intern("+"), number(2))))); -} +" + .chars(), + ); + let e = parser.expression_().unwrap(); + assert_eq!( + e, + if_else( + apply(identifier("test"), number(1)), + number(1), + if_else( + identifier("True"), + number(2), + op_apply(number(3), intern("+"), number(2)) + ) + ) + ); + } -#[test] -fn where_bindings() { - let mut parser = Parser::new( -r" + #[test] + fn where_bindings() { + let mut parser = Parser::new( + r" test = case a of x:y:xs -> z where @@ -1503,64 +1748,84 @@ test = case a of where z = 0 where a = [] -".chars()); - let bind = parser.binding().unwrap(); - match bind.matches { - Match::Simple(ref e) => { - match e.expr { +" + .chars(), + ); + let bind = parser.binding().unwrap(); + match bind.matches { + Match::Simple(ref e) => match e.expr { Case(_, ref alts) => { let w = alts[0].where_bindings.as_ref().expect("Expected where"); assert_eq!(w[0].name, intern("z")); - assert_eq!(w[0].matches, Match::Simple(op_apply(identifier("x"), intern("+"), identifier("y")))); - let w2 = alts[2].where_bindings.as_ref().expect("Expected where_bindings"); + assert_eq!( + w[0].matches, + Match::Simple(op_apply(identifier("x"), intern("+"), identifier("y"))) + ); + let w2 = alts[2] + .where_bindings + .as_ref() + .expect("Expected where_bindings"); assert_eq!(w2[0].name, intern("z")); assert_eq!(w2[0].matches, Match::Simple(number(0))); } - _ => panic!("Expected case") - } + _ => panic!("Expected case"), + }, + _ => panic!("Expected simple binding"), } - _ => panic!("Expected simple binding") + let binds = bind + .where_bindings + .as_ref() + .expect("Expected where_bindings"); + assert_eq!(binds[0].name, intern("a")); + assert_eq!(binds[0].matches, Match::Simple(identifier("[]"))); } - let binds = bind.where_bindings.as_ref().expect("Expected where_bindings"); - assert_eq!(binds[0].name, intern("a")); - assert_eq!(binds[0].matches, Match::Simple(identifier("[]"))); -} -#[test] -fn parse_newtype() { - let s = -r" + #[test] + fn parse_newtype() { + let s = r" newtype IntPair a = IntPair (a, Int) "; - let module = Parser::new(s.chars()).module().unwrap(); - let a = Type::new_var(intern("a")); - let typ = Type::new_op(intern("IntPair"), vec![a.clone()]); - assert_eq!(module.newtypes[0].typ, qualified(Vec::new(), typ.clone())); - assert_eq!(module.newtypes[0].constructor_type.value, function_type_(Type::new_op(intern("(,)"), vec![a, int_type()]), typ)); -} - -#[test] -fn parse_prelude() { - let path = &Path::new("Prelude.hs"); - let mut contents = ::std::string::String::new(); - File::open(path).and_then(|mut f| f.read_to_string(&mut contents)).unwrap(); - let mut parser = Parser::new(contents.chars()); - let module = parser.module().unwrap(); - - assert!(module.bindings.iter().any(|bind| bind.name == intern("foldl"))); - assert!(module.bindings.iter().any(|bind| bind.name == intern("id"))); - assert!(module.classes.iter().any(|class| class.name == intern("Eq"))); -} + let module = Parser::new(s.chars()).module().unwrap(); + let a: Type<_> = "a".into(); + let typ = Type::new_op(intern("IntPair"), vec![a.clone()]); + assert_eq!(module.newtypes[0].typ, qualified(vec![], typ.clone())); + assert_eq!( + module.newtypes[0].constructor_type.value, + function_type_(Type::new_op(intern("(,)"), vec![a, int_type()]), typ) + ); + } -#[bench] -fn bench_prelude(b: &mut Bencher) { - let path = &Path::new("Prelude.hs"); - let mut contents = ::std::string::String::new(); - File::open(path).and_then(|mut f| f.read_to_string(&mut contents)).unwrap(); - b.iter(|| { + #[test] + fn parse_prelude() { + let path = &Path::new("Prelude.hs"); + let mut contents = ::std::string::String::new(); + File::open(path) + .and_then(|mut f| f.read_to_string(&mut contents)) + .unwrap(); let mut parser = Parser::new(contents.chars()); - parser.module().unwrap(); - }); -} + let module = parser.module().unwrap(); + + assert!(module + .bindings + .iter() + .any(|bind| bind.name == intern("foldl"))); + assert!(module.bindings.iter().any(|bind| bind.name == intern("id"))); + assert!(module + .classes + .iter() + .any(|class| class.name == intern("Eq"))); + } + #[bench] + fn bench_prelude(b: &mut Bencher) { + let path = &Path::new("Prelude.hs"); + let mut contents = ::std::string::String::new(); + File::open(path) + .and_then(|mut f| f.read_to_string(&mut contents)) + .unwrap(); + b.iter(|| { + let mut parser = Parser::new(contents.chars()); + parser.module().unwrap(); + }); + } } diff --git a/src/renamer.rs b/src/renamer.rs index d76a995..af34598 100644 --- a/src/renamer.rs +++ b/src/renamer.rs @@ -1,19 +1,34 @@ -use std::fmt; -use std::error; -use crate::module::*; -use crate::lexer::Located; -use crate::scoped_map::ScopedMap; -use crate::interner::*; +use { + crate::{ + interner::*, + lexer::Located, + module::*, + scoped_map::ScopedMap, + }, + std::{ + error, + fmt, + }, +}; ///A Name is a reference to a specific identifier in the program, guaranteed to be unique #[derive(Eq, Hash, Clone, Copy, Debug)] pub struct Name { pub name: InternedStr, - pub uid: usize + pub uid: usize, } pub fn name(s: &str) -> Name { - Name { uid: 0, name: intern(s) } + s.into() +} + +impl From<&str> for Name { + fn from(s: &str) -> Self { + Self { + uid: 0, + name: intern(s), + } + } } impl PartialEq for Name { @@ -32,7 +47,6 @@ impl PartialEq for InternedStr { } } - impl AsRef for Name { fn as_ref(&self) -> &str { self.name.as_ref() @@ -48,31 +62,37 @@ impl ::std::fmt::Display for Name { ///Generic struct which can store and report errors #[derive(Debug)] pub struct Errors { - errors: Vec + errors: Vec, } -impl Errors { - pub fn new() -> Errors { - Errors { errors: Vec::new() } +impl Errors { + pub fn new() -> Self { + Self { errors: vec![] } } + pub fn insert(&mut self, e: T) { self.errors.push(e); } + pub fn has_errors(&self) -> bool { - self.errors.len() != 0 + !self.errors.is_empty() } pub fn into_result(&mut self, value: V) -> Result> { if self.has_errors() { Err(::std::mem::replace(self, Errors::new())) - } - else { + } else { Ok(value) } } } -impl Errors { +impl Errors { pub fn report_errors(&self, f: &mut fmt::Formatter, pass: &str) -> fmt::Result { - write!(f, "Found {} errors in compiler pass: {}", self.errors.len(), pass)?; + write!( + f, + "Found {} errors in compiler pass: {}", + self.errors.len(), + pass + )?; for error in self.errors.iter() { write!(f, "{}", error)?; } @@ -90,7 +110,9 @@ impl fmt::Display for RenamerError { } impl error::Error for RenamerError { - fn description(&self) -> &str { "renaming error" } + fn description(&self) -> &str { + "renaming error" + } } #[derive(Debug)] @@ -102,33 +124,39 @@ enum Error { impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - Error::MultipleDefinitions(s) => write!(f, "{} is defined multiple times", s), - Error::UndefinedModule(s) => write!(f, "Module {} is not defined", s) + Self::MultipleDefinitions(s) => write!(f, "{} is defined multiple times", s), + Self::UndefinedModule(s) => write!(f, "Module {} is not defined", s), } } } ///A NameSupply can turn simple strings into unique Names pub struct NameSupply { - unique_id: usize + unique_id: usize, } impl NameSupply { - - pub fn new() -> NameSupply { - NameSupply { unique_id: 1 } + pub fn new() -> Self { + Self { unique_id: 1 } } + ///Create a unique Name which are anonymous pub fn anonymous(&mut self) -> Name { self.from_str("_a") } + ///Takes a string and returns a new Name which is unique pub fn from_str(&mut self, s: &str) -> Name { self.from_interned(intern(s)) } + ///Takes a string and returns a new Name which is unique pub fn from_interned(&mut self, s: InternedStr) -> Name { - Name { name: s, uid: self.next_id() } + Name { + name: s, + uid: self.next_id(), + } } + pub fn next_id(&mut self) -> usize { self.unique_id += 1; self.unique_id @@ -147,23 +175,40 @@ struct Renamer { uniques: ScopedMap, name_supply: NameSupply, ///All errors found while renaming are stored here - errors: Errors + errors: Errors, } - impl Renamer { - fn new() -> Renamer { - Renamer { uniques: ScopedMap::new(), name_supply: NameSupply::new(), errors: Errors::new() } + fn new() -> Self { + Self { + uniques: ScopedMap::new(), + name_supply: NameSupply::new(), + errors: Errors::new(), + } } - fn import_globals(&mut self, module: &Module, str_fn: &mut dyn FnMut(T) -> InternedStr, uid: usize) { - let names = module.data_definitions.iter() + fn import_globals( + &mut self, + module: &Module, + str_fn: &mut dyn FnMut(T) -> InternedStr, + uid: usize, + ) { + let names = module + .data_definitions + .iter() .flat_map(|data| data.constructors.iter().map(|ctor| ctor.name)) - .chain(module.newtypes.iter().map(|newtype| newtype.constructor_name)) - .chain(module.classes.iter().flat_map(|class| - Some(class.name).into_iter() - .chain(class.declarations.iter().map(|decl| decl.name)) - .chain(binding_groups(&*class.bindings).map(|binds| binds[0].name)))) + .chain( + module + .newtypes + .iter() + .map(|newtype| newtype.constructor_name), + ) + .chain(module.classes.iter().flat_map(|class| { + Some(class.name) + .into_iter() + .chain(class.declarations.iter().map(|decl| decl.name)) + .chain(binding_groups(&class.bindings).map(|binds| binds[0].name)) + })) .chain(binding_groups(module.bindings.as_ref()).map(|binds| binds[0].name)); for name in names { self.declare_global(str_fn(name), uid); @@ -179,11 +224,15 @@ impl Renamer { ///Puts the globals of `module_env` into the current scope of the renamer. ///This includes putting all globals from the imports and the the globals of the module itself ///into scope - fn insert_globals(&mut self, module_env: &[Module], module: &Module, uid: usize) { + fn insert_globals( + &mut self, + module_env: &[Module], + module: &Module, + uid: usize, + ) { self.import_globals(module, &mut |name| name, uid); for import in module.imports.iter() { - let imported_module = module_env.iter() - .find(|m| m.name.name == import.module); + let imported_module = module_env.iter().find(|m| m.name.name == import.module); let imported_module = match imported_module { Some(x) => x, None => { @@ -192,107 +241,148 @@ impl Renamer { } }; let uid = imported_module.name.uid; - match import.imports { - Some(ref imports) => { - for &imported_str in imports.iter() { - self.declare_global(imported_str, uid); - } - } - None => {//Import everything - self.import_globals(imported_module, &mut |name| name.name, imported_module.name.uid) + if let Some(ref imports) = import.imports { + for &imported_str in imports.iter() { + self.declare_global(imported_str, uid); } + } else { + //Import everything + self.import_globals( + imported_module, + &mut |name| name.name, + imported_module.name.uid, + ) } } } - fn rename_bindings(&mut self, bindings: Vec>, is_global: bool) -> Vec> { + fn rename_bindings( + &mut self, + bindings: Vec>, + is_global: bool, + ) -> Vec> { //Add all bindings in the scope if !is_global { for bind in binding_groups(bindings.as_ref()) { self.make_unique(bind[0].name.clone()); } } - bindings.into_iter().map(|binding| { - let Binding { name, arguments, matches, typ, where_bindings } = binding; - let n = self.uniques.find(&name) - .map(|u| u.clone()) - .unwrap_or_else(|| unreachable!("Variable {} should already have been defined", name)); - self.uniques.enter_scope(); - let b = Binding { - name: n, - arguments: self.rename_arguments(arguments), - where_bindings: where_bindings.map(|bs| self.rename_bindings(bs, false)), - matches: self.rename_matches(matches), - typ: self.rename_qualified_type(typ) - }; - self.uniques.exit_scope(); - b - }).collect() + bindings + .into_iter() + .map(|binding| { + let Binding { + name, + arguments, + matches, + typ, + where_bindings, + } = binding; + let n = self.uniques.find(&name).map(|u| u.clone()).unwrap_or_else( + || unreachable!("Variable {} should already have been defined", name) + ); + self.uniques.enter_scope(); + let b = Binding { + name: n, + arguments: self.rename_arguments(arguments), + where_bindings: where_bindings.map(|bs| self.rename_bindings(bs, false)), + matches: self.rename_matches(matches), + typ: self.rename_qualified_type(typ), + }; + self.uniques.exit_scope(); + b + }) + .collect() } - + fn rename(&mut self, input_expr: TypedExpr) -> TypedExpr { - use crate::module::Expr::*; - use crate::module::DoBinding::*; - let TypedExpr { expr, typ, location } = input_expr; + use crate::module::{ + DoBinding::*, + Expr::*, + }; + let TypedExpr { + expr, + typ, + location, + } = input_expr; let e = match expr { Literal(l) => Literal(l), Identifier(i) => Identifier(self.get_name(i)), - Apply(func, arg) => Apply(Box::new(self.rename(*func)), Box::new(self.rename(*arg))), - OpApply(lhs, op, rhs) => OpApply(Box::new(self.rename(*lhs)), self.get_name(op), Box::new(self.rename(*rhs))), + Apply(func, arg) => Apply(self.rename(*func).into(), self.rename(*arg).into()), + OpApply(lhs, op, rhs) => OpApply( + self.rename(*lhs).into(), + self.get_name(op), + self.rename(*rhs).into(), + ), Lambda(arg, body) => { self.uniques.enter_scope(); - let l = Lambda(self.rename_pattern(arg), Box::new(self.rename(*body))); + let l = Lambda(self.rename_pattern(arg), self.rename(*body).into()); self.uniques.exit_scope(); l } Let(bindings, expr) => { self.uniques.enter_scope(); let bs = self.rename_bindings(bindings, false); - let l = Let(bs, Box::new(self.rename(*expr))); + let l = Let(bs, self.rename(*expr).into()); self.uniques.exit_scope(); l } Case(expr, alts) => { - let a: Vec> = alts.into_iter().map(|alt| { - let Alternative { - pattern: Located { location: loc, node: pattern }, - matches, - where_bindings - } = alt; - self.uniques.enter_scope(); - let a = Alternative { - pattern: Located { location: loc, node: self.rename_pattern(pattern) }, - where_bindings: where_bindings.map(|bs| self.rename_bindings(bs, false)), - matches: self.rename_matches(matches) - }; - self.uniques.exit_scope(); - a - }).collect(); + let a: Vec> = alts + .into_iter() + .map(|alt| { + let Alternative { + pattern: + Located { + location: loc, + node: pattern, + }, + matches, + where_bindings, + } = alt; + self.uniques.enter_scope(); + let a = Alternative { + pattern: Located { + location: loc, + node: self.rename_pattern(pattern), + }, + where_bindings: where_bindings + .map(|bs| self.rename_bindings(bs, false)), + matches: self.rename_matches(matches), + }; + self.uniques.exit_scope(); + a + }) + .collect(); Case(Box::new(self.rename(*expr)), a) } - IfElse(pred, if_true, if_false) => { - IfElse(Box::new(self.rename(*pred)), - Box::new(self.rename(*if_true)), - Box::new(self.rename(*if_false))) - } + IfElse(pred, if_true, if_false) => IfElse( + Box::new(self.rename(*pred)), + Box::new(self.rename(*if_true)), + Box::new(self.rename(*if_false)), + ), Do(bindings, expr) => { - let bs: Vec> = bindings.into_iter().map(|bind| { - match bind { + let bs: Vec> = bindings + .into_iter() + .map(|bind| match bind { DoExpr(expr) => DoExpr(self.rename(expr)), DoLet(bs) => DoLet(self.rename_bindings(bs, false)), DoBind(pattern, expr) => { let Located { location, node } = pattern; - let loc = Located { location: location, node: self.rename_pattern(node) }; + let loc = Located { + location, + node: self.rename_pattern(node), + }; DoBind(loc, self.rename(expr)) } - } - }).collect(); + }) + .collect(); Do(bs, Box::new(self.rename(*expr))) } - TypeSig(expr, sig) => { - TypeSig(Box::new(self.rename(*expr)), self.rename_qualified_type(sig)) - } - Paren(expr) => Paren(Box::new(self.rename(*expr))) + TypeSig(expr, sig) => TypeSig( + Box::new(self.rename(*expr)), + self.rename_qualified_type(sig), + ), + Paren(expr) => Paren(Box::new(self.rename(*expr))), }; let mut t = TypedExpr::with_location(e, location); t.typ = self.rename_type(typ); @@ -303,49 +393,76 @@ impl Renamer { match pattern { Pattern::Number(i) => Pattern::Number(i), Pattern::Constructor(s, ps) => { - let ps2: Vec> = ps.into_iter().map(|p| self.rename_pattern(p)).collect(); + let ps2: Vec> = + ps.into_iter().map(|p| self.rename_pattern(p)).collect(); Pattern::Constructor(self.get_name(s), ps2) } Pattern::Identifier(s) => Pattern::Identifier(self.make_unique(s)), - Pattern::WildCard => Pattern::WildCard + Pattern::WildCard => Pattern::WildCard, } } ///Turns the string into the Name which is currently in scope ///If the name was not found it is assumed to be global - fn get_name(&self, s: InternedStr) -> Name { - match self.uniques.find(&s) { - Some(&Name { uid, .. }) => Name { name: s, uid: uid }, - None => Name { name: s, uid: 0 }//Primitive + fn get_name(&self, name: InternedStr) -> Name { + Name { + name, + uid: self.uniques.find(&name).map(|n| n.uid).unwrap_or(0), // 0 -> Primitive } } fn rename_matches(&mut self, matches: Match) -> Match { match matches { Match::Simple(e) => Match::Simple(self.rename(e)), - Match::Guards(gs) => Match::Guards(gs.into_iter() - .map(|Guard { predicate: p, expression: e }| - Guard { predicate: self.rename(p), expression: self.rename(e) } - ) - .collect()) + Match::Guards(gs) => Match::Guards( + gs.into_iter() + .map( + |Guard { + predicate: p, + expression: e, + }| Guard { + predicate: self.rename(p), + expression: self.rename(e), + }, + ) + .collect(), + ), } } fn rename_arguments(&mut self, arguments: Vec>) -> Vec> { - arguments.into_iter().map(|a| self.rename_pattern(a)).collect() + arguments + .into_iter() + .map(|a| self.rename_pattern(a)) + .collect() } - fn rename_qualified_type(&mut self, typ: Qualified, InternedStr>) -> Qualified, Name> { - let Qualified { constraints, value: typ } = typ; - let constraints2: Vec> = constraints.into_iter() - .map(|Constraint { class, variables }| { - Constraint { class: self.get_name(class), variables: variables } + fn rename_qualified_type( + &mut self, + typ: Qualified, InternedStr>, + ) -> Qualified, Name> { + let Qualified { + constraints, + value: typ, + } = typ; + let constraints2: Vec<_> = constraints + .into_iter() + .map(|Constraint { class, variables }| Constraint { + class: self.get_name(class), + variables, }) .collect(); qualified(constraints2, self.rename_type(typ)) } - fn rename_type_declarations(&mut self, decls: Vec>) -> Vec> { - let decls2: Vec> = decls.into_iter() - .map(|decl| TypeDeclaration { name: self.get_name(decl.name), typ: self.rename_qualified_type(decl.typ) }) + fn rename_type_declarations( + &mut self, + decls: Vec>, + ) -> Vec> { + let decls2: Vec> = decls + .into_iter() + .map(|decl| TypeDeclaration { + name: self.get_name(decl.name), + typ: self.rename_qualified_type(decl.typ), + }) .collect(); decls2 } @@ -356,8 +473,7 @@ impl Renamer { if self.uniques.in_current_scope(&name) { self.errors.insert(Error::MultipleDefinitions(name)); self.uniques.find(&name).map(|x| x.clone()).unwrap() - } - else { + } else { let u = self.name_supply.from_interned(name.clone()); self.uniques.insert(name, u.clone()); u @@ -378,17 +494,19 @@ impl Renamer { pub fn rename_expr(expr: TypedExpr) -> Result, RenamerError> { let mut renamer = Renamer::new(); let expr = renamer.rename(expr); - renamer.errors.into_result(expr) - .map_err(RenamerError) + renamer.errors.into_result(expr).map_err(RenamerError) } pub fn rename_module(module: Module) -> Result, RenamerError> { let mut renamer = Renamer::new(); let m = rename_module_(&mut renamer, &[], module); - renamer.errors.into_result(m) - .map_err(RenamerError) + renamer.errors.into_result(m).map_err(RenamerError) } -fn rename_module_(renamer: &mut Renamer, module_env: &[Module], module: Module) -> Module { +fn rename_module_( + renamer: &mut Renamer, + module_env: &[Module], + module: Module, +) -> Module { let mut name = renamer.make_unique(module.name); if name.as_ref() == "Prelude" { renamer.uniques.find_mut(&name.name).unwrap().uid = 0; @@ -405,181 +523,230 @@ fn rename_module_(renamer: &mut Renamer, module_env: &[Module], module: Mo type_declarations, bindings, instances, - fixity_declarations + fixity_declarations, } = module; - let imports2: Vec> = imports.into_iter().map(|import| { - let imports = import.imports.as_ref().map(|x| { - let is: Vec = x.iter() - .map(|&x| renamer.get_name(x)) + let imports2: Vec> = imports + .into_iter() + .map(|import| { + let imports = import.imports.as_ref().map(|x| { + let is: Vec = x.iter().map(|&x| renamer.get_name(x)).collect(); + is + }); + Import { + module: import.module, + imports, + } + }) + .collect(); + + let data_definitions2: Vec> = data_definitions + .into_iter() + .map(|data| { + let DataDefinition { + constructors, + typ, + parameters, + deriving, + } = data; + let c: Vec> = constructors + .into_iter() + .map(|ctor| { + let Constructor { + name, + typ, + tag, + arity, + } = ctor; + Constructor { + name: renamer.get_name(name), + typ: renamer.rename_qualified_type(typ), + tag, + arity, + } + }) .collect(); - is - }); - Import { module: import.module, imports: imports } - }).collect(); - - let data_definitions2 : Vec> = data_definitions.into_iter().map(|data| { - let DataDefinition { - constructors, - typ, - parameters, - deriving - } = data; - let c: Vec> = constructors.into_iter().map(|ctor| { - let Constructor { - name, + let d: Vec = deriving.into_iter().map(|s| renamer.get_name(s)).collect(); + + DataDefinition { + typ: renamer.rename_qualified_type(typ), + parameters, + constructors: c, + deriving: d, + } + }) + .collect(); + + let newtypes2: Vec> = newtypes + .into_iter() + .map(|newtype| { + let Newtype { + typ, + constructor_name, + constructor_type, + deriving, + } = newtype; + let deriving2: Vec = deriving.into_iter().map(|s| renamer.get_name(s)).collect(); + Newtype { typ, - tag, - arity - } = ctor; - Constructor { - name : renamer.get_name(name), - typ : renamer.rename_qualified_type(typ), - tag : tag, - arity : arity + constructor_name: renamer.get_name(constructor_name), + constructor_type: renamer.rename_qualified_type(constructor_type), + deriving: deriving2, } - }).collect(); - let d: Vec = deriving.into_iter().map(|s| { - renamer.get_name(s) - }).collect(); - - DataDefinition { - typ : renamer.rename_qualified_type(typ), - parameters : parameters, - constructors : c, - deriving : d - } - }).collect(); - - let newtypes2: Vec> = newtypes.into_iter().map(|newtype| { - let Newtype { typ, constructor_name, constructor_type, deriving } = newtype; - let deriving2: Vec = deriving.into_iter().map(|s| { - renamer.get_name(s) - }).collect(); - Newtype { - typ: typ, - constructor_name: renamer.get_name(constructor_name), - constructor_type: renamer.rename_qualified_type(constructor_type), - deriving: deriving2 - } - }).collect(); - - let instances2: Vec> = instances.into_iter().map(|instance| { - let Instance { - bindings, - constraints, - typ, - classname - } = instance; - let constraints2: Vec> = constraints.into_iter() - .map(|Constraint { class, variables }| { - Constraint { class: renamer.get_name(class), variables: variables } - }) - .collect(); - Instance { - bindings : renamer.rename_bindings(bindings, true), - constraints : constraints2, - typ : renamer.rename_type(typ), - classname : renamer.get_name(classname) - } - }).collect(); + }) + .collect(); - - let classes2 : Vec> = classes.into_iter().map(|class| { - let Class { - constraints, - name, - variable, - declarations, - bindings - } = class; - let constraints2: Vec> = constraints.into_iter() - .map(|Constraint { class, variables }| { - Constraint { class: renamer.get_name(class), variables: variables } - }) - .collect(); - Class { - constraints: constraints2, - name: renamer.get_name(name), - variable: variable, - declarations: renamer.rename_type_declarations(declarations), - bindings: renamer.rename_bindings(bindings, true) - } - }).collect(); - - let bindings2 = renamer.rename_bindings(bindings, true); + let instances2: Vec> = instances + .into_iter() + .map(|instance| { + let Instance { + bindings, + constraints, + typ, + classname, + } = instance; + let constraints2: Vec> = constraints + .into_iter() + .map(|Constraint { class, variables }| Constraint { + class: renamer.get_name(class), + variables, + }) + .collect(); + Instance { + bindings: renamer.rename_bindings(bindings, true), + constraints: constraints2, + typ: renamer.rename_type(typ), + classname: renamer.get_name(classname), + } + }) + .collect(); - let fixity_declarations2: Vec> = fixity_declarations.into_iter() - .map(|FixityDeclaration { assoc, precedence, operators }| { - - let ops: Vec = operators.into_iter() - .map(|s| renamer.get_name(s)) + let classes2: Vec> = classes + .into_iter() + .map(|class| { + let Class { + constraints, + name, + variable, + declarations, + bindings, + } = class; + let constraints2: Vec> = constraints + .into_iter() + .map(|Constraint { class, variables }| Constraint { + class: renamer.get_name(class), + variables, + }) .collect(); - FixityDeclaration { assoc: assoc, precedence: precedence, - operators: ops + Class { + constraints: constraints2, + name: renamer.get_name(name), + variable, + declarations: renamer.rename_type_declarations(declarations), + bindings: renamer.rename_bindings(bindings, true), } }) .collect(); + + let bindings2 = renamer.rename_bindings(bindings, true); + + let fixity_declarations2: Vec> = fixity_declarations + .into_iter() + .map( + |FixityDeclaration { + assoc, + precedence, + operators, + }| { + let ops: Vec = operators.into_iter().map(|s| renamer.get_name(s)).collect(); + FixityDeclaration { + assoc, + precedence, + operators: ops, + } + }, + ) + .collect(); let decls2 = renamer.rename_type_declarations(type_declarations); renamer.uniques.exit_scope(); Module { - name: name, + name, imports: imports2, - classes : classes2, + classes: classes2, data_definitions: data_definitions2, type_declarations: decls2, - bindings : bindings2, + bindings: bindings2, instances: instances2, newtypes: newtypes2, - fixity_declarations: fixity_declarations2 + fixity_declarations: fixity_declarations2, } } pub fn prelude_name(s: &str) -> Name { - Name { name: intern(s), uid: 0 } + Name { + name: intern(s), + uid: 0, + } } ///Renames a vector of modules. ///If any errors are encounterd while renaming, an error message is output and fail is called -pub fn rename_modules(modules: Vec>) -> Result>, RenamerError> { +pub fn rename_modules( + modules: Vec>, +) -> Result>, RenamerError> { let mut renamer = Renamer::new(); - let mut ms = Vec::new(); + let mut ms = vec![]; for module in modules.into_iter() { let m = rename_module_(&mut renamer, ms.as_ref(), module); ms.push(m); } - renamer.errors.into_result(ms) - .map_err(RenamerError) + renamer.errors.into_result(ms).map_err(RenamerError) } pub mod typ { - use std::iter::repeat; - use crate::types::{Kind, Type, TypeVariable}; - use super::{name, Name}; - use crate::interner::intern; + use { + super::{ + name, + Name, + }, + crate::{ + interner::intern, + types::{ + Kind, + Type, + TypeVariable, + }, + }, + std::iter::repeat, + }; ///Constructs a string which holds the name of an n-tuple pub fn tuple_name(n: usize) -> String { let commas = if n == 0 { 0 } else { n - 1 }; - Some('(').into_iter() + Some('(') + .into_iter() .chain(repeat(',').take(commas)) .chain(Some(')').into_iter()) .collect() } ///Returns the type of an n-tuple constructor as well as the name of the tuple pub fn tuple_type(n: usize) -> (String, Type) { - let mut var_list = Vec::new(); + let mut var_list = vec![]; assert!(n < 26); for i in 0..n { let c = (('a' as u8) + i as u8) as char; - let var = TypeVariable::new_var_kind(intern(c.to_string().as_ref()), Kind::Star.clone()); + let var = + TypeVariable::new_var_kind(intern(c.to_string().as_ref()), Kind::Star.clone()); var_list.push(Type::Generic(var)); } let ident = tuple_name(n); let mut typ = Type::new_op(name(ident.as_ref()), var_list); for i in (0..n).rev() { let c = (('a' as u8) + i as u8) as char; - typ = function_type_(Type::Generic(TypeVariable::new(intern(c.to_string().as_ref()))), typ); + typ = function_type_( + Type::Generic(TypeVariable::new(intern(c.to_string().as_ref()))), + typ, + ); } (ident, typ) } @@ -610,7 +777,7 @@ pub mod typ { } ///Creates a function type - pub fn function_type_(func : Type, arg : Type) -> Type { + pub fn function_type_(func: Type, arg: Type) -> Type { Type::new_op(name("->"), vec![func, arg]) } @@ -624,41 +791,45 @@ pub mod typ { } } - #[cfg(test)] pub mod tests { - use super::Name; - use crate::interner::InternedStr; - use crate::module::{TypedExpr, Module}; - use crate::parser::*; + use { + super::Name, + crate::{ + interner::InternedStr, + module::{ + Module, + TypedExpr, + }, + parser::*, + }, + }; pub fn rename_modules(modules: Vec>) -> Vec> { - super::rename_modules(modules) - .unwrap() + super::rename_modules(modules).unwrap() } pub fn rename_module(module: Module) -> Module { - super::rename_module(module) - .unwrap() + super::rename_module(module).unwrap() } pub fn rename_expr(expr: TypedExpr) -> TypedExpr { - super::rename_expr(expr) - .unwrap() + super::rename_expr(expr).unwrap() } #[test] #[should_panic] fn duplicate_binding() { let mut parser = Parser::new( -r"main = 1 + r"main = 1 test = [] -main = 2".chars()); +main = 2" + .chars(), + ); let module = parser.module().unwrap(); - rename_modules(vec!(module)); + rename_modules(vec![module]); } #[test] fn import_binding() { - let file = -r" + let file = r" import Prelude (id) main = id"; let modules = parse_string(file).unwrap(); @@ -668,10 +839,12 @@ main = id"; #[should_panic] fn missing_import() { let mut parser = Parser::new( -r" + r" import Prelude () -main = id".chars()); +main = id" + .chars(), + ); let module = parser.module().unwrap(); - rename_modules(vec!(module)); + rename_modules(vec![module]); } } diff --git a/src/repl.rs b/src/repl.rs index 5e7cf95..67eeb34 100644 --- a/src/repl.rs +++ b/src/repl.rs @@ -1,25 +1,32 @@ use std::io::BufRead; -use crate::compiler::*; -use crate::typecheck::*; -use crate::vm::*; -use crate::interner::*; -use crate::core::{Module, Type, Qualified}; -use crate::core::translate::*; -use crate::lambda_lift::*; -use crate::parser::Parser; -use crate::renamer::{Name, rename_expr}; +use crate::{ + compiler::*, + core::{ + translate::*, + Module, + Qualified, + Type, + }, + interner::*, + lambda_lift::*, + parser::Parser, + renamer::{ + rename_expr, + Name, + }, + typecheck::*, + vm::*, +}; ///Returns whether the type in question is an IO action fn is_io(typ: &Type) -> bool { - match *typ { - Type::Application(ref lhs, _) => - match **lhs { - Type::Constructor(ref op) => op.name.as_ref() == "IO", - _ => false - }, - _ => false + if let Type::Application(ref lhs, _) = *typ { + if let Type::Constructor(ref op) = **lhs { + return op.name.as_ref() == "IO"; + } } + false } ///Compiles an expression into an assembly @@ -33,7 +40,7 @@ fn compile_expr(prelude: &Assembly, expr_str: &str) -> Result type_env.typecheck_expr(&mut expr).unwrap(); let temp_module = Module::from_expr(translate_expr(expr)); let m = do_lambda_lift(temp_module); - + let mut compiler = Compiler::new(); compiler.assemblies.push(prelude); Ok(compiler.compile_module(&m)) @@ -41,8 +48,16 @@ fn compile_expr(prelude: &Assembly, expr_str: &str) -> Result ///Finds the main function and if it is an IO function, adds instructions to push the "RealWorld" argument fn find_main(assembly: &Assembly) -> (Vec, Qualified, Name>) { - assembly.super_combinators.iter() - .find(|sc| sc.name == Name { name: intern("main"), uid: 0 }) + assembly + .super_combinators + .iter() + .find(|sc| { + sc.name + == Name { + name: intern("main"), + uid: 0, + } + }) .map(|sc| { if is_io(&sc.typ.value) { //If the expression we compiled is IO we need to add an extra argument @@ -52,10 +67,9 @@ fn find_main(assembly: &Assembly) -> (Vec, Qualified, Na let mut vec: Vec = sc.instructions.iter().map(|x| x.clone()).collect(); let len = vec.len(); vec.insert(len - 3, Instruction::Mkap); - vec.insert(0, Instruction::PushInt(42));//Realworld + vec.insert(0, Instruction::PushInt(42)); //Realworld (vec, sc.typ.clone()) - } - else { + } else { (sc.instructions.clone(), sc.typ.clone()) } }) @@ -63,15 +77,13 @@ fn find_main(assembly: &Assembly) -> (Vec, Qualified, Na } pub fn run_and_print_expr(expr_str: &str) { - let prelude = compile_file("Prelude.hs") - .unwrap(); + let prelude = compile_file("Prelude.hs").unwrap(); let mut vm = VM::new(); vm.add_assembly(prelude); - let assembly = compile_expr(vm.get_assembly(0), expr_str.as_ref()) - .unwrap(); + let assembly = compile_expr(vm.get_assembly(0), expr_str.as_ref()).unwrap(); let (instructions, type_decl) = find_main(&assembly); let assembly_index = vm.add_assembly(assembly); - let result = vm.evaluate(&*instructions, assembly_index);//TODO 0 is not necessarily correct + let result = vm.evaluate(&instructions, assembly_index); //TODO 0 is not necessarily correct println!("{:?} {}", result, type_decl); } @@ -79,26 +91,25 @@ pub fn run_and_print_expr(expr_str: &str) { pub fn start() { let mut vm = VM::new(); match compile_file("Prelude.hs") { - Ok(prelude) => { vm.add_assembly(prelude); } - Err(err) => println!("Failed to compile the prelude\nReason: {}", err) + Ok(prelude) => { + vm.add_assembly(prelude); + } + Err(err) => println!("Failed to compile the prelude\nReason: {}", err), } let stdin = ::std::io::stdin(); for line in stdin.lock().lines() { - let expr_str = match line { - Ok(l) => l, - Err(e) => panic!("Reading line failed with '{:?}'", e) - }; + let expr_str = line.unwrap_or_else(|e| panic!("Reading line failed with '{:?}'", e)); let assembly = match compile_expr(vm.get_assembly(0), expr_str.as_ref()) { Ok(assembly) => assembly, Err(err) => { println!("{}", err); - continue + continue; } }; let (instructions, typ) = find_main(&assembly); let assembly_index = vm.add_assembly(assembly); - let result = vm.evaluate(&*instructions, assembly_index);//TODO 0 is not necessarily correct + let result = vm.evaluate(&instructions, assembly_index); //TODO 0 is not necessarily correct println!("{:?} {}", result, typ); } } diff --git a/src/scoped_map.rs b/src/scoped_map.rs index 5a73667..4d6e38a 100644 --- a/src/scoped_map.rs +++ b/src/scoped_map.rs @@ -1,6 +1,13 @@ -use std::collections::HashMap; -use std::collections::hash_map::{Entry, IterMut}; -use std::hash::Hash; +use std::{ + collections::{ + hash_map::{ + Entry, + IterMut, + }, + HashMap, + }, + hash::Hash, +}; ///A map struct which allows for the isizeroduction of different scopes ///Introducing a new scope will make it possible to isizeroduce additional @@ -12,30 +19,33 @@ pub struct ScopedMap { map: HashMap>, ///A vector of scopes, when entering a scope, None is added as a marker ///when later exiting a scope, values are removed from the map until the marker is found - scopes: Vec> + scopes: Vec>, } #[allow(dead_code)] -impl ScopedMap - where K: Eq + Hash + Clone { - - pub fn new() -> ScopedMap { - ScopedMap { map: HashMap::new(), scopes: Vec::new() } +impl ScopedMap +where + K: Eq + Hash + Clone, +{ + pub fn new() -> Self { + Self { + map: HashMap::new(), + scopes: vec![], + } } ///Introduces a new scope pub fn enter_scope(&mut self) { self.scopes.push(None); } + ///Exits the current scope, removing anything inserted since the ///matching enter_scope call pub fn exit_scope(&mut self) { - loop { - match self.scopes.pop() { - Some(Some(key)) => { self.map.get_mut(&key).map(|x| x.pop()); } - _ => break - } + while let Some(key) = self.scopes.pop().flatten() { + self.map.get_mut(&key).map(|x| x.pop()); } } + ///Removes a previusly inserted value from the map. pub fn remove(&mut self, k: &K) -> bool { match self.map.get_mut(k).map(|x| x.pop()) { @@ -49,7 +59,7 @@ impl ScopedMap } true } - None => false + None => false, } } @@ -59,7 +69,7 @@ impl ScopedMap match *n { Some(ref name) if name == k => return true, None => break, - _ => () + _ => (), } } false @@ -76,7 +86,9 @@ impl ScopedMap ///Returns the number of elements in the container. ///Shadowed elements are not counted - pub fn len(&self) -> usize { self.map.len() } + pub fn len(&self) -> usize { + self.map.len() + } ///Removes all elements pub fn clear(&mut self) { @@ -87,15 +99,13 @@ impl ScopedMap ///Swaps the value stored at key, or inserts it if it is not present pub fn swap(&mut self, k: K, v: V) -> Option { let vec = match self.map.entry(k.clone()) { - Entry::Vacant(entry) => entry.insert(Vec::new()), - Entry::Occupied(entry) => entry.into_mut() + Entry::Vacant(entry) => entry.insert(vec![]), + Entry::Occupied(entry) => entry.into_mut(), }; - if vec.len() != 0 { - let r = vec.pop(); + if let Some(r) = vec.pop() { vec.push(v); - r - } - else { + r.into() + } else { vec.push(v); self.scopes.push(Some(k)); None @@ -113,7 +123,7 @@ impl ScopedMap } Some(v) } - None => None + None => None, } } pub fn find_mut<'a>(&'a mut self, key: &K) -> Option<&'a mut V> { @@ -121,8 +131,8 @@ impl ScopedMap } pub fn insert(&mut self, k: K, v: V) -> bool { let vec = match self.map.entry(k.clone()) { - Entry::Vacant(entry) => entry.insert(Vec::new()), - Entry::Occupied(entry) => entry.into_mut() + Entry::Vacant(entry) => entry.insert(vec![]), + Entry::Occupied(entry) => entry.into_mut(), }; vec.push(v); self.scopes.push(Some(k)); diff --git a/src/typecheck.rs b/src/typecheck.rs index d443681..9246972 100644 --- a/src/typecheck.rs +++ b/src/typecheck.rs @@ -1,34 +1,56 @@ -use std::collections::HashMap; -use std::collections::hash_map::Entry; -use std::fmt; -use std::mem::swap; -use std::error; -use crate::module::*; -use crate::module::Expr::*; -use crate::module::LiteralData::*; -use crate::lexer::Location; -use crate::graph::{Graph, VertexIndex, strongly_connected_components}; -use crate::builtins::builtins; -use crate::renamer::*; -use crate::interner::*; +use { + crate::{ + builtins::builtins, + graph::{ + strongly_connected_components, + Graph, + VertexIndex, + }, + interner::*, + lexer::Location, + module::{ + Expr::*, + LiteralData::*, + *, + }, + renamer::*, + }, + std::{ + collections::{ + hash_map::Entry, + HashMap, + }, + error, + fmt, + mem::swap, + }, +}; pub type TcType = Type; ///Trait which can be implemented by types where types can be looked up by name pub trait Types { fn find_type<'a>(&'a self, name: &Name) -> Option<&'a Qualified>; - fn find_class<'a>(&'a self, name: Name) -> Option<(&'a [Constraint], &'a TypeVariable, &'a [TypeDeclaration])>; + fn find_class<'a>( + &'a self, + name: Name, + ) -> Option<( + &'a [Constraint], + &'a TypeVariable, + &'a [TypeDeclaration], + )>; fn has_instance(&self, classname: Name, typ: &TcType) -> bool { - match self.find_instance(classname, typ) { - Some(_) => true, - None => false - } + self.find_instance(classname, typ).is_some() } - fn find_instance<'a>(&'a self, classname: Name, typ: &TcType) -> Option<(&'a [Constraint], &'a TcType)>; + fn find_instance<'a>( + &'a self, + classname: Name, + typ: &TcType, + ) -> Option<(&'a [Constraint], &'a TcType)>; } ///A trait which also allows for lookup of data types -pub trait DataTypes : Types { +pub trait DataTypes: Types { fn find_data_type<'a>(&'a self, name: Name) -> Option<&'a DataDefinition>; } @@ -54,20 +76,42 @@ impl Types for Module { } } } - self.newtypes.iter() + self.newtypes + .iter() .find(|newtype| newtype.constructor_name == *name) .map(|newtype| &newtype.constructor_type) } - fn find_class<'a>(&'a self, name: Name) -> Option<(&'a [Constraint], &'a TypeVariable, &'a [TypeDeclaration])> { - self.classes.iter() + fn find_class<'a>( + &'a self, + name: Name, + ) -> Option<( + &'a [Constraint], + &'a TypeVariable, + &'a [TypeDeclaration], + )> { + self.classes + .iter() .find(|class| name == class.name) - .map(|class| (class.constraints.as_ref(), &class.variable, class.declarations.as_ref())) + .map(|class| { + ( + class.constraints.as_ref(), + &class.variable, + class.declarations.as_ref(), + ) + }) } - fn find_instance<'a>(&'a self, classname: Name, typ: &TcType) -> Option<(&'a [Constraint], &'a TcType)> { + fn find_instance<'a>( + &'a self, + classname: Name, + typ: &TcType, + ) -> Option<(&'a [Constraint], &'a TcType)> { for instance in self.instances.iter() { - if classname == instance.classname && extract_applied_type(&instance.typ) == extract_applied_type(typ) {//test name + if classname == instance.classname + && extract_applied_type(&instance.typ) == extract_applied_type(typ) + { + //test name return Some((instance.constraints.as_ref(), &instance.typ)); } } @@ -91,11 +135,11 @@ pub struct TypeEnvironment<'a> { ///Stores references to imported modules or assemblies assemblies: Vec<&'a (dyn DataTypes + 'a)>, ///A mapping of names to the type which those names are bound to. - named_types : HashMap>, + named_types: HashMap>, ///A mapping used for any variables declared inside any global binding. ///Used in conjuction to the global 'named_types' map since the local table can ///be cleared once those bindings are no longer in used which gives an overall speed up. - local_types : HashMap>, + local_types: HashMap>, ///Stores the constraints for each typevariable since the typevariables cannot themselves store this. constraints: HashMap>, ///Stores data about the instances which are available. @@ -104,11 +148,11 @@ pub struct TypeEnvironment<'a> { ///3: The Type which the instance is defined for instances: Vec<(Vec>, Name, TcType)>, classes: Vec<(Vec>, Name)>, - data_definitions : Vec>, + data_definitions: Vec>, ///The current age for newly created variables. ///Age is used to determine whether variables need to be quantified or not. - variable_age : isize, - errors: Errors + variable_age: isize, + errors: Errors, } #[derive(Debug)] @@ -121,15 +165,16 @@ impl fmt::Display for TypeError { } impl error::Error for TypeError { - fn description(&self) -> &str { "type error" } + fn description(&self) -> &str { + "type error" + } } - ///A Substitution is a mapping from typevariables to types. #[derive(Clone)] pub struct Substitution { ///A hashmap which contains what a typevariable is unified to. - subs: HashMap + subs: HashMap, } ///Trait which provides access to the bindings in a struct. @@ -143,11 +188,9 @@ impl Bindings for Module { fn get_mut(&mut self, (instance_idx, idx): (usize, usize)) -> &mut [Binding] { let bindings = if instance_idx == 0 { &mut *self.bindings - } - else if instance_idx - 1 < self.instances.len() { + } else if instance_idx - 1 < self.instances.len() { &mut *self.instances[instance_idx - 1].bindings - } - else { + } else { &mut *self.classes[instance_idx - 1 - self.instances.len()].bindings }; mut_bindings_at(bindings, idx) @@ -176,20 +219,23 @@ impl Bindings for Module { } } -fn mut_bindings_at<'a, Ident: Eq>(bindings: &'a mut [Binding], idx: usize) -> &'a mut [Binding] { +fn mut_bindings_at<'a, Ident: Eq>( + bindings: &'a mut [Binding], + idx: usize, +) -> &'a mut [Binding] { let end = bindings[idx..] .iter() .position(|bind| bind.name != bindings[idx].name) .unwrap_or(bindings.len() - idx); - &mut bindings[idx .. idx + end] + &mut bindings[idx..idx + end] } //Woraround since traits around a vector seems problematic struct BindingsWrapper<'a> { - value: &'a mut [Binding] + value: &'a mut [Binding], } -impl <'a> Bindings for BindingsWrapper<'a> { +impl<'a> Bindings for BindingsWrapper<'a> { fn get_mut(&mut self, (_, idx): (usize, usize)) -> &mut [Binding] { mut_bindings_at(self.value, idx) } @@ -204,7 +250,7 @@ impl <'a> Bindings for BindingsWrapper<'a> { } fn insert_to(map: &mut HashMap>, name: &str, typ: TcType) { - map.insert(Name { name: intern(name), uid: 0 }, qualified(vec![], typ)); + map.insert(name.into(), qualified(vec![], typ)); } fn prim(typename: &str, op: &str) -> ::std::string::String { let mut b = "prim".to_string(); @@ -232,38 +278,49 @@ fn add_primitives(globals: &mut HashMap>, typename } } -impl <'a> TypeEnvironment<'a> { - +impl<'a> TypeEnvironment<'a> { ///Creates a new TypeEnvironment and adds all the primitive types - pub fn new() -> TypeEnvironment<'a> { + pub fn new() -> Self { let mut globals = HashMap::new(); add_primitives(&mut globals, "Int"); add_primitives(&mut globals, "Double"); - insert_to(&mut globals,"primIntToDouble", typ::function_type_(typ::int_type(), typ::double_type())); - insert_to(&mut globals, "primDoubleToInt", typ::function_type_(typ::double_type(), typ::int_type())); - let var = Type::Generic(TypeVariable::new_var_kind(intern("a"), Kind::Star.clone())); - + insert_to( + &mut globals, + "primIntToDouble", + typ::function_type_(typ::int_type(), typ::double_type()), + ); + insert_to( + &mut globals, + "primDoubleToInt", + typ::function_type_(typ::double_type(), typ::int_type()), + ); + let var = Type::Generic(TypeVariable::new_var_kind("a".into(), Kind::Star.clone())); + for (name, typ) in builtins().into_iter() { insert_to(&mut globals, name, typ); } let list = typ::list_type(var.clone()); insert_to(&mut globals, "[]", list.clone()); - insert_to(&mut globals, ":", typ::function_type(&var, &typ::function_type(&list, &list))); + insert_to( + &mut globals, + ":", + typ::function_type(&var, &typ::function_type(&list, &list)), + ); insert_to(&mut globals, "()", typ::unit()); for i in (2 as usize)..10 { let (name, typ) = typ::tuple_type(i); insert_to(&mut globals, name.as_ref(), typ); } - TypeEnvironment { - assemblies: Vec::new(), - named_types : globals, - local_types : HashMap::new(), + Self { + assemblies: vec![], + named_types: globals, + local_types: HashMap::new(), constraints: HashMap::new(), - instances: Vec::new(), - classes: Vec::new(), - data_definitions : Vec::new(), - variable_age : 0 , - errors: Errors::new() + instances: vec![], + classes: vec![], + data_definitions: vec![], + variable_age: 0, + errors: Errors::new(), } } @@ -276,8 +333,7 @@ impl <'a> TypeEnvironment<'a> { ///If any errors were found while typechecking panic! is called. pub fn typecheck_module(&mut self, module: &mut Module) -> Result<(), TypeError> { self.typecheck_module2(module); - self.errors.into_result(()) - .map_err(TypeError) + self.errors.into_result(()).map_err(TypeError) } pub fn typecheck_module2(&mut self, module: &mut Module) { let start_var_age = self.variable_age + 1; @@ -292,7 +348,8 @@ impl <'a> TypeEnvironment<'a> { for newtype in module.newtypes.iter() { let mut typ = newtype.constructor_type.clone(); quantify(0, &mut typ); - self.named_types.insert(newtype.constructor_name.clone(), typ); + self.named_types + .insert(newtype.constructor_name.clone(), typ); } for class in module.classes.iter_mut() { //Instantiate a new variable and replace all occurances of the class variable with this @@ -300,19 +357,20 @@ impl <'a> TypeEnvironment<'a> { for type_decl in class.declarations.iter_mut() { var_kind = match find_kind(&class.variable, var_kind, &type_decl.typ.value) { Ok(k) => k, - Err(msg) => panic!("{:?}", msg) + Err(msg) => panic!("{:?}", msg), }; //If we found the variable, update it immediatly since the kind of th variable //matters when looking for constraints, etc - match var_kind { - Some(ref k) => { - class.variable.kind.clone_from(k); - } - None => () - } - - let c = Constraint { class: class.name.clone(), variables: vec![class.variable.clone()] }; - {//Workaround to add the class's constraints directyly to the declaration + if let Some(ref k) = var_kind { + class.variable.kind.clone_from(k); + }; + + let c = Constraint { + class: class.name.clone(), + variables: vec![class.variable.clone()], + }; + { + //Workaround to add the class's constraints directyly to the declaration let mut context = vec![]; swap(&mut context, &mut type_decl.typ.constraints); let mut vec_context: Vec> = context.into_iter().collect(); @@ -325,9 +383,13 @@ impl <'a> TypeEnvironment<'a> { } for binding in class.bindings.iter_mut() { let classname = &class.name; - let decl = class.declarations.iter() + let decl = class + .declarations + .iter() .find(|decl| binding.name.name.as_ref().ends_with(decl.name.as_ref())) - .unwrap_or_else(|| panic!("Could not find {:?} in class {:?}", binding.name, classname)); + .unwrap_or_else( + || panic!("Could not find {:?} in class {:?}", binding.name, classname) + ); binding.typ = decl.typ.clone(); { let mut context = vec![]; @@ -335,21 +397,31 @@ impl <'a> TypeEnvironment<'a> { let mut vec_context: Vec> = context.into_iter().collect(); let c = Constraint { class: class.name.clone(), - variables: vec![class.variable.clone()] + variables: vec![class.variable.clone()], }; vec_context.push(c); binding.typ.constraints = vec_context; } } - self.classes.push((class.constraints.clone(), class.name.clone())); + self.classes + .push((class.constraints.clone(), class.name.clone())); } let data_definitions = module.data_definitions.clone(); for instance in module.instances.iter_mut() { - let (_class_constraints, class_var, class_decls) = module.classes.iter() + let (_, class_var, class_decls) = module + .classes + .iter() .find(|class| class.name == instance.classname) - .map(|class| (class.constraints.as_ref(), &class.variable, class.declarations.as_ref())) + .map(|class| { + ( + class.constraints.as_ref(), + &class.variable, + class.declarations.as_ref(), + ) + }) .or_else(|| { - self.assemblies.iter() + self.assemblies + .iter() .filter_map(|a| a.find_class(instance.classname)) .next() }) @@ -357,19 +429,36 @@ impl <'a> TypeEnvironment<'a> { //Update the kind of the type for the instance to be the same as the class kind (since we have no proper kind inference match instance.typ { Type::Constructor(ref mut op) => { - let maybe_data = self.assemblies.iter().filter_map(|a| a.find_data_type(op.name)) + let maybe_data = self + .assemblies + .iter() + .filter_map(|a| a.find_data_type(op.name)) .next(); op.kind = maybe_data - .or_else(|| data_definitions.iter().find(|data| op.name == extract_applied_type(&data.typ.value).ctor().name)) + .or_else(|| { + data_definitions.iter().find(|data| { + op.name == extract_applied_type(&data.typ.value).ctor().name + }) + }) .map(|data| extract_applied_type(&data.typ.value).kind().clone()) - .unwrap_or_else(|| if intern("[]") == op.name { Kind::Function(Box::new(Kind::Star), Box::new(Kind::Star)) } else { Kind::Star }); + .unwrap_or_else(|| { + if intern("[]") == op.name { + Kind::Function(Kind::Star.into(), Kind::Star.into()) + } else { + Kind::Star + } + }); } - _ => () + _ => (), } for binding in instance.bindings.iter_mut() { let classname = &instance.classname; - let decl = class_decls.iter().find(|decl| binding.name.as_ref().ends_with(decl.name.as_ref())) - .unwrap_or_else(|| panic!("Could not find {:?} in class {:?}", binding.name, classname)); + let decl = class_decls + .iter() + .find(|decl| binding.name.as_ref().ends_with(decl.name.as_ref())) + .unwrap_or_else( + || panic!("Could not find {:?} in class {:?}", binding.name, classname) + ); binding.typ = decl.typ.clone(); replace_var(&mut binding.typ.value, class_var, &instance.typ); self.freshen_qualified_type(&mut binding.typ, HashMap::new()); @@ -384,10 +473,14 @@ impl <'a> TypeEnvironment<'a> { } } { - let mut missing_super_classes = self.find_class_constraints(instance.classname) + let mut missing_super_classes = self + .find_class_constraints(instance.classname) .unwrap_or_else(|| panic!("Error: Missing class {:?}", instance.classname)) - .iter()//Make sure we have an instance for all of the constraints - .filter(|constraint| self.has_instance(constraint.class, &instance.typ, &mut Vec::new()).is_err()) + .iter() //Make sure we have an instance for all of the constraints + .filter(|constraint| { + self.has_instance(constraint.class, &instance.typ, &mut vec![]) + .is_err() + }) .peekable(); if missing_super_classes.peek().is_some() { let mut buffer = ::std::string::String::new(); @@ -400,21 +493,33 @@ impl <'a> TypeEnvironment<'a> { instance.typ, instance.classname, buffer); } } - self.instances.push((instance.constraints.clone(), instance.classname.clone(), instance.typ.clone())); + self.instances.push(( + instance.constraints.clone(), + instance.classname.clone(), + instance.typ.clone(), + )); } - - for type_decl in module.type_declarations.iter_mut() { - match module.bindings.iter_mut().find(|bind| bind.name == type_decl.name) { + for type_decl in module.type_declarations.iter_mut() { + match module + .bindings + .iter_mut() + .find(|bind| bind.name == type_decl.name) + { Some(bind) => { bind.typ = type_decl.typ.clone(); } - None => panic!("Error: Type declaration for '{:?}' has no binding", type_decl.name) + None => panic!( + "Error: Type declaration for '{:?}' has no binding", + type_decl.name + ), } } { - let mut subs = Substitution { subs: HashMap::new() }; + let mut subs = Substitution { + subs: HashMap::new(), + }; self.typecheck_global_bindings(start_var_age, &mut subs, module); } } @@ -423,12 +528,14 @@ impl <'a> TypeEnvironment<'a> { ///The types in the expression are updated with the correct types. ///If the expression has a type error, fail is called. pub fn typecheck_expr(&mut self, expr: &mut TypedExpr) -> Result<(), TypeError> { - let mut subs = Substitution { subs: HashMap::new() }; + let mut subs = + Substitution { + subs: HashMap::new(), + }; let mut typ = self.typecheck(expr, &mut subs); unify_location(self, &mut subs, &expr.location, &mut typ, &mut expr.typ); self.substitute(&mut subs, expr); - self.errors.into_result(()) - .map_err(TypeError) + self.errors.into_result(()).map_err(TypeError) } pub fn typecheck_module_(&mut self, module: &mut Module) { @@ -440,35 +547,52 @@ impl <'a> TypeEnvironment<'a> { ///Finds all the constraints for a type pub fn find_constraints(&self, typ: &TcType) -> Vec> { - let mut result : Vec> = Vec::new(); - each_type(typ, - |var| { - match self.constraints.get(var) { + let mut result: Vec> = vec![]; + each_type( + typ, + |var| match self.constraints.get(var) { Some(constraints) => { for c in constraints.iter() { - if result.iter().find(|x| x.class == *c && x.variables[0] == *var) == None { - result.push(Constraint { class: c.clone(), variables: vec![var.clone()] }); + if result + .iter() + .find(|x| x.class == *c && x.variables[0] == *var) + == None + { + result.push(Constraint { + class: c.clone(), + variables: vec![var.clone()], + }); } } } - None => () - } - }, - |_| ()); + None => (), + }, + |_| (), + ); result } fn find_data_definition(&self, name: Name) -> Option<&DataDefinition> { - self.data_definitions.iter() + self.data_definitions + .iter() .find(|data| extract_applied_type(&data.typ.value).ctor().name == name) - .or_else(|| self.assemblies.iter().filter_map(|a| a.find_data_type(name)).next()) + .or_else(|| { + self.assemblies + .iter() + .filter_map(|a| a.find_data_type(name)) + .next() + }) } - - fn freshen_qualified_type(&mut self, typ: &mut Qualified, mut mapping: HashMap) { + + fn freshen_qualified_type( + &mut self, + typ: &mut Qualified, + mut mapping: HashMap, + ) { for constraint in typ.constraints.iter_mut() { let old = constraint.variables[0].clone(); let new = match mapping.entry(old.clone()) { Entry::Vacant(entry) => entry.insert(self.new_var_kind(old.kind.clone())), - Entry::Occupied(entry) => entry.into_mut() + Entry::Occupied(entry) => entry.into_mut(), }; constraint.variables[0] = new.var().clone(); } @@ -482,103 +606,134 @@ impl <'a> TypeEnvironment<'a> { } ///Walks through an expression and applies the substitution on each of its types - fn substitute(&mut self, subs : &Substitution, expr: &mut TypedExpr) { + fn substitute(&mut self, subs: &Substitution, expr: &mut TypedExpr) { struct SubVisitor<'a: 'b, 'b, 'c> { env: &'b mut TypeEnvironment<'a>, - subs: &'c Substitution + subs: &'c Substitution, } - impl <'a, 'b, 'c> MutVisitor for SubVisitor<'a, 'b, 'c> { + impl<'a, 'b, 'c> MutVisitor for SubVisitor<'a, 'b, 'c> { fn visit_expr(&mut self, expr: &mut TypedExpr) { replace(&mut self.env.constraints, &mut expr.typ, self.subs); walk_expr_mut(self, expr); } } - SubVisitor { env: self, subs: subs }.visit_expr(expr); + SubVisitor { env: self, subs }.visit_expr(expr); } ///Returns whether the type 'searched_type' has an instance for 'class' ///If no instance was found, return the instance which was missing - fn has_instance(&self, class: Name, searched_type: &TcType, new_constraints: &mut Vec>) -> Result<(), InternedStr> { + fn has_instance( + &self, + class: Name, + searched_type: &TcType, + new_constraints: &mut Vec>, + ) -> Result<(), InternedStr> { match extract_applied_type(searched_type) { - &Type::Constructor(ref ctor) => { - match self.find_data_definition(ctor.name) { - Some(data_type) => { - if data_type.deriving.iter().any(|name| *name == class) { - return self.check_instance_constraints(&[], &data_type.typ.value, searched_type, new_constraints); - } + &Type::Constructor(ref ctor) => match self.find_data_definition(ctor.name) { + Some(data_type) => { + if data_type.deriving.iter().any(|name| *name == class) { + return self.check_instance_constraints( + &[], + &data_type.typ.value, + searched_type, + new_constraints, + ); } - None => () } - } - _ => () + None => (), + }, + _ => (), } for &(ref constraints, ref name, ref typ) in self.instances.iter() { if class == *name { - let result = self.check_instance_constraints(&**constraints, typ, searched_type, new_constraints); + let result = self.check_instance_constraints( + constraints, + typ, + searched_type, + new_constraints, + ); if result.is_ok() { return result; } } } - + for types in self.assemblies.iter() { match types.find_instance(class, searched_type) { Some((constraints, unspecialized_type)) => { - return self.check_instance_constraints(constraints, unspecialized_type, searched_type, new_constraints); + return self.check_instance_constraints( + constraints, + unspecialized_type, + searched_type, + new_constraints, + ); } - None => () + None => (), } } Err(class.name) } fn find_class_constraints(&self, class: Name) -> Option<&[Constraint]> { - self.classes.iter() - .find(|& &(_, ref name)| *name == class) + self.classes + .iter() + .find(|&&(_, ref name)| *name == class) .map(|x| x.0.as_ref()) - .or_else(|| self.assemblies.iter() - .filter_map(|types| types.find_class(class))//Find the class - .next()//next will get us the first class (but should only be one) - .map(|(constraints, _, _)| constraints)) + .or_else(|| { + self.assemblies + .iter() + .filter_map(|types| types.find_class(class)) //Find the class + .next() //next will get us the first class (but should only be one) + .map(|(constraints, _, _)| constraints) + }) } ///Checks whether 'actual_type' fulfills all the constraints that the instance has. - fn check_instance_constraints(&self, - constraints: &[Constraint], - instance_type: &TcType, - actual_type: &TcType, - new_constraints: &mut Vec>) -> Result<(), InternedStr> - { + fn check_instance_constraints( + &self, + constraints: &[Constraint], + instance_type: &TcType, + actual_type: &TcType, + new_constraints: &mut Vec>, + ) -> Result<(), InternedStr> { match (instance_type, actual_type) { (&Type::Application(ref lvar, ref r), &Type::Application(ref ltype, ref rtype)) => { if let Type::Variable(ref rvar) = **r { - constraints.iter() + constraints + .iter() .filter(|c| c.variables[0] == *rvar) .map(|constraint| { - let result = self.has_instance(constraint.class, &**rtype, new_constraints); + let result = + self.has_instance(constraint.class, rtype, new_constraints); if result.is_ok() { match **rtype { Type::Variable(ref var) => { new_constraints.push(Constraint { class: constraint.class, - variables: vec![var.clone()] + variables: vec![var.clone()], }); } - _ => () + _ => (), } } result }) .find(|result| result.is_err()) - .unwrap_or_else(|| self.check_instance_constraints(constraints, &**lvar, &**ltype, new_constraints)) - } - else { + .unwrap_or_else(|| { + self.check_instance_constraints( + constraints, + lvar, + ltype, + new_constraints, + ) + }) + } else { Err(intern("Unknown error")) } } (&Type::Constructor(ref l), &Type::Constructor(ref r)) if l.name == r.name => Ok(()), (_, &Type::Variable(_)) => Ok(()), - _ => Err(intern("Unknown error")) + _ => Err(intern("Unknown error")), } } ///Creates a new type variable with a kind @@ -587,7 +742,7 @@ impl <'a> TypeEnvironment<'a> { let mut var = Type::new_var_kind(intern(self.variable_age.to_string().as_ref()), kind); match var { Type::Variable(ref mut var) => var.age = self.variable_age, - _ => () + _ => (), } var } @@ -609,15 +764,32 @@ impl <'a> TypeEnvironment<'a> { let mut typ = None; for guard in gs.iter_mut() { let mut typ2 = self.typecheck(&mut guard.expression, subs); - unify_location(self, subs, &guard.expression.location, &mut typ2, &mut guard.expression.typ); - match typ { - Some(mut typ) => unify_location(self, subs, &guard.expression.location, &mut typ, &mut typ2), - None => () - } + unify_location( + self, + subs, + &guard.expression.location, + &mut typ2, + &mut guard.expression.typ, + ); + if let Some(mut typ) = typ { + unify_location(self, subs, &guard.expression.location, &mut typ, &mut typ2) + }; typ = Some(typ2); let mut predicate = self.typecheck(&mut guard.predicate, subs); - unify_location(self, subs, &guard.predicate.location, &mut predicate, &mut typ::bool_type()); - unify_location(self, subs, &guard.predicate.location, &mut predicate, &mut guard.predicate.typ); + unify_location( + self, + subs, + &guard.predicate.location, + &mut predicate, + &mut typ::bool_type(), + ); + unify_location( + self, + subs, + &guard.predicate.location, + &mut predicate, + &mut guard.predicate.typ, + ); } typ.unwrap() } @@ -625,8 +797,8 @@ impl <'a> TypeEnvironment<'a> { } ///Typechecks an expression - fn typecheck(&mut self, expr : &mut TypedExpr, subs: &mut Substitution) -> TcType { - if expr.typ == Type::::new_var(intern("a")) { + fn typecheck(&mut self, expr: &mut TypedExpr, subs: &mut Substitution) -> TcType { + if expr.typ == Type::::new_var("a".into()) { expr.typ = self.new_var(); } @@ -634,17 +806,19 @@ impl <'a> TypeEnvironment<'a> { Literal(ref lit) => { match *lit { Integral(_) => { - self.constraints.insert(expr.typ.var().clone(), vec![prelude_name("Num")]); + self.constraints + .insert(expr.typ.var().clone(), vec![prelude_name("Num")]); match expr.typ { Type::Variable(ref mut v) => v.kind = Kind::Star.clone(), - _ => () + _ => (), } } Fractional(_) => { - self.constraints.insert(expr.typ.var().clone(), vec![prelude_name("Fractional")]); + self.constraints + .insert(expr.typ.var().clone(), vec![prelude_name("Fractional")]); match expr.typ { Type::Variable(ref mut v) => v.kind = Kind::Star.clone(), - _ => () + _ => (), } } String(_) => { @@ -656,57 +830,69 @@ impl <'a> TypeEnvironment<'a> { } expr.typ.clone() } - Identifier(ref name) => { - match self.fresh(name) { - Some(t) => { - debug!("{:?} as {:?}", name, t); - expr.typ = t.clone(); - t - } - None => panic!("Undefined identifier '{:?}' at {:?}", *name, expr.location) + Identifier(ref name) => match self.fresh(name) { + Some(t) => { + debug!("{:?} as {:?}", name, t); + expr.typ = t.clone(); + t } - } + None => panic!("Undefined identifier '{:?}' at {:?}", *name, expr.location), + }, Apply(ref mut func, ref mut arg) => { - let func_type = self.typecheck(&mut **func, subs); - self.typecheck_apply(&expr.location, subs, func_type, &mut **arg) + let func_type = self.typecheck(func, subs); + self.typecheck_apply(&expr.location, subs, func_type, arg) } OpApply(ref mut lhs, ref op, ref mut rhs) => { let op_type = match self.fresh(op) { Some(typ) => typ, - None => panic!("Undefined identifier '{:?}' at {:?}", *op, expr.location) + None => panic!("Undefined identifier '{:?}' at {:?}", *op, expr.location), }; - let first = self.typecheck_apply(&expr.location, subs, op_type, &mut **lhs); - self.typecheck_apply(&expr.location, subs, first, &mut **rhs) + let first = self.typecheck_apply(&expr.location, subs, op_type, lhs); + self.typecheck_apply(&expr.location, subs, first, rhs) } Lambda(ref arg, ref mut body) => { let mut arg_type = self.new_var(); let mut result = typ::function_type_(arg_type.clone(), self.new_var()); self.typecheck_pattern(&expr.location, subs, arg, &mut arg_type); - let body_type = self.typecheck(&mut **body, subs); + let body_type = self.typecheck(body, subs); with_arg_return(&mut result, |_, return_type| { *return_type = body_type.clone(); }); result } Let(ref mut bindings, ref mut body) => { - self.typecheck_local_bindings(subs, &mut BindingsWrapper { value: &mut **bindings }); + self.typecheck_local_bindings(subs, &mut BindingsWrapper { value: bindings }); self.apply_locals(subs); - self.typecheck(&mut **body, subs) + self.typecheck(body, subs) } Case(ref mut case_expr, ref mut alts) => { - let mut match_type = self.typecheck(&mut **case_expr, subs); - self.typecheck_pattern(&alts[0].pattern.location, subs, &alts[0].pattern.node, &mut match_type); + let mut match_type = self.typecheck(case_expr, subs); + self.typecheck_pattern( + &alts[0].pattern.location, + subs, + &alts[0].pattern.node, + &mut match_type, + ); match *&mut alts[0].where_bindings { - Some(ref mut bindings) => self.typecheck_local_bindings(subs, &mut BindingsWrapper { value: &mut **bindings }), - None => () + Some(ref mut bindings) => self + .typecheck_local_bindings(subs, &mut BindingsWrapper { value: bindings }), + None => (), } let mut alt0_ = self.typecheck_match(&mut alts[0].matches, subs); for alt in alts.iter_mut().skip(1) { - self.typecheck_pattern(&alt.pattern.location, subs, &alt.pattern.node, &mut match_type); + self.typecheck_pattern( + &alt.pattern.location, + subs, + &alt.pattern.node, + &mut match_type, + ); match alt.where_bindings { - Some(ref mut bindings) => self.typecheck_local_bindings(subs, &mut BindingsWrapper { value: &mut **bindings }), - None => () + Some(ref mut bindings) => self.typecheck_local_bindings( + subs, + &mut BindingsWrapper { value: bindings }, + ), + None => (), } let mut alt_type = self.typecheck_match(&mut alt.matches, subs); unify_location(self, subs, &alt.pattern.location, &mut alt0_, &mut alt_type); @@ -714,17 +900,19 @@ impl <'a> TypeEnvironment<'a> { alt0_ } IfElse(ref mut pred, ref mut if_true, ref mut if_false) => { - let mut p = self.typecheck(&mut **pred, subs); + let mut p = self.typecheck(pred, subs); unify_location(self, subs, &expr.location, &mut p, &mut typ::bool_type()); - let mut t = self.typecheck(&mut **if_true, subs); - let mut f = self.typecheck(&mut **if_false, subs); + let mut t = self.typecheck(if_true, subs); + let mut f = self.typecheck(if_false, subs); unify_location(self, subs, &expr.location, &mut t, &mut f); t } Do(ref mut bindings, ref mut last_expr) => { - let mut previous = self.new_var_kind(Kind::Function(Box::new(Kind::Star), Box::new(Kind::Star))); - self.constraints.insert(previous.var().clone(), vec!(Name { name: intern("Monad"), uid: 0 })); - previous = Type::Application(Box::new(previous), Box::new(self.new_var())); + let mut previous = + self.new_var_kind(Kind::Function(Kind::Star.into(), Kind::Star.into())); + self.constraints + .insert(previous.var().clone(), vec!["Monad".into()]); + previous = Type::Application(previous.into(), self.new_var().into()); for bind in bindings.iter_mut() { match *bind { DoBinding::DoExpr(ref mut e) => { @@ -732,7 +920,10 @@ impl <'a> TypeEnvironment<'a> { unify_location(self, subs, &e.location, &mut typ, &mut previous); } DoBinding::DoLet(ref mut bindings) => { - self.typecheck_local_bindings(subs, &mut BindingsWrapper { value: &mut **bindings }); + self.typecheck_local_bindings( + subs, + &mut BindingsWrapper { value: bindings }, + ); self.apply_locals(subs); } DoBinding::DoBind(ref mut pattern, ref mut e) => { @@ -740,71 +931,107 @@ impl <'a> TypeEnvironment<'a> { unify_location(self, subs, &e.location, &mut typ, &mut previous); let inner_type = match typ { Type::Application(_, ref mut t) => t, - _ => panic!("Not a monadic type: {:?}", typ) + _ => panic!("Not a monadic type: {:?}", typ), }; - self.typecheck_pattern(&pattern.location, subs, &pattern.node, &mut **inner_type); + self.typecheck_pattern( + &pattern.location, + subs, + &pattern.node, + inner_type, + ); } } match previous { - Type::Application(ref mut _monad, ref mut typ) => { + Type::Application(_, ref mut typ) => { **typ = self.new_var(); } - _ => panic!() + _ => panic!(), } } - let mut typ = self.typecheck(&mut **last_expr, subs); + let mut typ = self.typecheck(last_expr, subs); unify_location(self, subs, &last_expr.location, &mut typ, &mut previous); typ } TypeSig(ref mut expr, ref mut qualified_type) => { - let mut typ = self.typecheck(&mut **expr, subs); + let mut typ = self.typecheck(expr, subs); self.freshen_qualified_type(qualified_type, HashMap::new()); - match_or_fail(self, subs, &expr.location, &mut typ, &mut qualified_type.value); + match_or_fail( + self, + subs, + &expr.location, + &mut typ, + &mut qualified_type.value, + ); typ } - Paren(ref mut expr) => self.typecheck(&mut **expr, subs) + Paren(ref mut expr) => self.typecheck(expr, subs), }; debug!("{:?}\nas\n{:?}", expr, x); expr.typ = x.clone(); x } - fn typecheck_apply(&mut self, location: &Location, subs: &mut Substitution, mut func_type: TcType, arg: &mut TypedExpr) -> TcType { + fn typecheck_apply( + &mut self, + location: &Location, + subs: &mut Substitution, + mut func_type: TcType, + arg: &mut TypedExpr, + ) -> TcType { let arg_type = self.typecheck(arg, subs); let mut result = typ::function_type_(arg_type, self.new_var()); unify_location(self, subs, location, &mut func_type, &mut result); - result = match result { + match result { Type::Application(_, x) => *x, - _ => panic!("Must be a type application (should be a function type), found {:?}", result) - }; - result + _ => panic!( + "Must be a type application (should be a function type), found {:?}", + result + ), + } } ///Typechecks a pattern. ///Checks that the pattern has the type 'match_type' and adds all variables in the pattern. - fn typecheck_pattern(&mut self, location: &Location, subs: &mut Substitution, pattern: &Pattern, match_type: &mut TcType) { + fn typecheck_pattern( + &mut self, + location: &Location, + subs: &mut Substitution, + pattern: &Pattern, + match_type: &mut TcType, + ) { match pattern { &Pattern::Identifier(ref ident) => { - self.local_types.insert(ident.clone(), qualified(vec![], match_type.clone())); + self.local_types + .insert(ident.clone(), qualified(vec![], match_type.clone())); } &Pattern::Number(_) => { let mut typ = typ::int_type(); unify_location(self, subs, location, &mut typ, match_type); } &Pattern::Constructor(ref ctorname, ref patterns) => { - let mut t = self.fresh(ctorname) - .unwrap_or_else(|| panic!("Undefined constructer '{:?}' when matching pattern", *ctorname)); + let mut t = self.fresh(ctorname).unwrap_or_else(|| { + panic!( + "Undefined constructer '{:?}' when matching pattern", + *ctorname + ) + }); let mut data_type = get_returntype(&t); - + unify_location(self, subs, location, &mut data_type, match_type); replace(&mut self.constraints, &mut t, subs); self.apply_locals(subs); - self.pattern_rec(0, location, subs, &**patterns, &mut t); - } - &Pattern::WildCard => { + self.pattern_rec(0, location, subs, patterns, &mut t); } + &Pattern::WildCard => {} } } ///Walks through the arguments of a pattern and typechecks each of them. - fn pattern_rec(&mut self, i: usize, location: &Location, subs: &mut Substitution, patterns: &[Pattern], func_type: &mut TcType) { + fn pattern_rec( + &mut self, + i: usize, + location: &Location, + subs: &mut Substitution, + patterns: &[Pattern], + func_type: &mut TcType, + ) { if i < patterns.len() { let p = &patterns[i]; with_arg_return(func_type, |arg_type, return_type| { @@ -818,35 +1045,42 @@ impl <'a> TypeEnvironment<'a> { ///map f (x:xs) = ... ///map f [] = ... fn typecheck_binding_group(&mut self, subs: &mut Substitution, bindings: &mut [Binding]) { - debug!("Begin typecheck {:?} :: {:?}", bindings[0].name, bindings[0].typ); + debug!( + "Begin typecheck {:?} :: {:?}", + bindings[0].name, bindings[0].typ + ); let mut argument_types: Vec<_> = (0..bindings[0].arguments.len()) .map(|_| self.new_var()) .collect(); - let type_var = match bindings[0].typ.value { - Type::Variable(ref var) => Some(var.clone()), - _ => None - }; + let type_var = + match bindings[0].typ.value { + Type::Variable(ref var) => Some(var.clone()), + _ => None, + }; let mut previous_type = None; for bind in bindings.iter_mut() { - if argument_types.len() != bind.arguments.len() { - panic!("Binding {:?} do not have the same number of arguments", bind.name);//TODO re add location - } + assert!( + argument_types.len() == bind.arguments.len(), + "Binding {:?} do not have the same number of arguments", + bind.name + ); //TODO re add location for (arg, typ) in bind.arguments.iter_mut().zip(argument_types.iter_mut()) { self.typecheck_pattern(&Location::eof(), subs, arg, typ); } - match bind.where_bindings { - Some(ref mut bindings) => self.typecheck_local_bindings(subs, &mut BindingsWrapper { value: &mut **bindings }), - None => () + if let Some(ref mut bindings) = bind.where_bindings { + self.typecheck_local_bindings(subs, &mut BindingsWrapper { value: bindings }) } let mut typ = self.typecheck_match(&mut bind.matches, subs); fn make_function(arguments: &[TcType], expr: &TcType) -> TcType { - if arguments.len() == 0 { expr.clone() } - else { typ::function_type_(arguments[0].clone(), make_function(&arguments[1..], expr)) } + if arguments.is_empty() { + expr.clone() + } else { + typ::function_type_(arguments[0].clone(), make_function(&arguments[1..], expr)) + } } typ = make_function(argument_types.as_ref(), &typ); - match previous_type { - Some(mut prev) => unify_location(self, subs, bind.matches.location(), &mut typ, &mut prev), - None => () + if let Some(mut prev) = previous_type { + unify_location(self, subs, bind.matches.location(), &mut typ, &mut prev) } replace(&mut self.constraints, &mut typ, subs); previous_type = Some(typ); @@ -856,14 +1090,24 @@ impl <'a> TypeEnvironment<'a> { //In that case we need to unify that variable to 'typ' to make sure that environment becomes updated //Otherwise a type declaration exists and we need to do a match to make sure that the type is not to specialized if type_var.is_none() { - match_or_fail(self, subs, &Location::eof(), &mut final_type, &bindings[0].typ.value); - } - else { - unify_location(self, subs, &Location::eof(), &mut final_type, &mut bindings[0].typ.value); - } - match type_var { - Some(var) => { subs.subs.insert(var, final_type); } - None => () + match_or_fail( + self, + subs, + &Location::eof(), + &mut final_type, + &bindings[0].typ.value, + ); + } else { + unify_location( + self, + subs, + &Location::eof(), + &mut final_type, + &mut bindings[0].typ.value, + ); + } + if let Some(var) = type_var { + subs.subs.insert(var, final_type); } for bind in bindings.iter_mut() { match bind.matches { @@ -876,19 +1120,22 @@ impl <'a> TypeEnvironment<'a> { } } } - debug!("End typecheck {:?} :: {:?}", bindings[0].name, bindings[0].typ); + debug!( + "End typecheck {:?} :: {:?}", + bindings[0].name, bindings[0].typ + ); } - + ///Typechecks a set of bindings which may be mutually recursive ///Takes the minimum age that a variable created for this group can have, the current substitution, a set of bindings, ///and a global indicating wheter the bindings are global (true if at the module level, false otherwise, ex. 'let' binding) - pub fn typecheck_mutually_recursive_bindings - (&mut self - , start_var_age: isize - , subs: &mut Substitution - , bindings: &mut dyn Bindings - , is_global: bool) { - + pub fn typecheck_mutually_recursive_bindings( + &mut self, + start_var_age: isize, + subs: &mut Substitution, + bindings: &mut dyn Bindings, + is_global: bool, + ) { let graph = build_graph(bindings); let groups = strongly_connected_components(&graph); @@ -902,10 +1149,11 @@ impl <'a> TypeEnvironment<'a> { } } if is_global { - self.named_types.insert(binds[0].name.clone(), binds[0].typ.clone()); - } - else { - self.local_types.insert(binds[0].name.clone(), binds[0].typ.clone()); + self.named_types + .insert(binds[0].name.clone(), binds[0].typ.clone()); + } else { + self.local_types + .insert(binds[0].name.clone(), binds[0].typ.clone()); } } for index in group.iter() { @@ -917,12 +1165,15 @@ impl <'a> TypeEnvironment<'a> { if is_global { for index in group.iter() { for bind in bindings.get_mut(graph.get_vertex(*index).value).iter() { - replace(&mut self.constraints, &mut self.named_types.get_mut(&bind.name).unwrap().value, subs); + replace( + &mut self.constraints, + &mut self.named_types.get_mut(&bind.name).unwrap().value, + subs, + ); } } self.local_types.clear(); - } - else { + } else { self.apply_locals(subs); } } @@ -936,8 +1187,7 @@ impl <'a> TypeEnvironment<'a> { { let typ = if is_global { self.named_types.get_mut(&bind.name).unwrap() - } - else { + } else { self.local_types.get_mut(&bind.name).unwrap() }; bind.typ.value = typ.value.clone(); @@ -959,54 +1209,63 @@ impl <'a> TypeEnvironment<'a> { self.typecheck_mutually_recursive_bindings(var, subs, bindings, false); } ///Typechecks a group of global bindings. - fn typecheck_global_bindings(&mut self, start_var_age: isize, subs: &mut Substitution, bindings: &mut dyn Bindings) { + fn typecheck_global_bindings( + &mut self, + start_var_age: isize, + subs: &mut Substitution, + bindings: &mut dyn Bindings, + ) { self.typecheck_mutually_recursive_bindings(start_var_age, subs, bindings, true); } - + ///Workaround to make all imported functions quantified without requiring their type variables to be generic fn find_fresh(&self, name: &Name) -> Option> { - self.local_types.get(name) + self.local_types + .get(name) .or_else(|| self.named_types.get(name)) .map(|x| x.clone()) .or_else(|| { - for types in self.assemblies.iter() { - let v = types.find_type(name).map(|x| x.clone()); - match v { - Some(mut typ) => { - quantify(0, &mut typ); - return Some(typ); + for types in self.assemblies.iter() { + let v = types.find_type(name).map(|x| x.clone()); + match v { + Some(mut typ) => { + quantify(0, &mut typ); + return Some(typ); + } + None => (), } - None => () } - } - None - }) + None + }) } ///Instantiates new typevariables for every typevariable in the type found at 'name' fn fresh(&mut self, name: &Name) -> Option { match self.find_fresh(name) { Some(mut typ) => { - let mut subs = Substitution { subs: HashMap::new() }; + let mut subs = Substitution { + subs: HashMap::new(), + }; freshen(self, &mut subs, &mut typ); for c in typ.constraints.iter() { self.insert_constraint(&c.variables[0], c.class.clone()); } Some(typ.value) } - None => None + None => None, } } - - + fn insert_constraint(&mut self, var: &TypeVariable, classname: Name) { - let mut constraints = self.constraints.remove(var).unwrap_or(Vec::new()); + let mut constraints = self.constraints.remove(var).unwrap_or(vec![]); self.insert_constraint_(&mut constraints, classname); self.constraints.insert(var.clone(), constraints); } fn insert_constraint_(&mut self, constraints: &mut Vec, classname: Name) { let mut ii = 0; while ii < constraints.len() { - if constraints[ii] == classname || self.exists_as_super_class(constraints[ii], classname) { + if constraints[ii] == classname + || self.exists_as_super_class(constraints[ii], classname) + { //'classname' was already in the list, or existed as a sub class to the element return; } @@ -1024,28 +1283,41 @@ impl <'a> TypeEnvironment<'a> { ///Checks if 'classname' exists as a super class to any fn exists_as_super_class(&self, constraint: Name, classname: Name) -> bool { match self.find_class_constraints(constraint) { - Some(constraints) => { - constraints.iter() - .any(|super_class| super_class.class == classname - || self.exists_as_super_class(super_class.class, classname)) - } - None => false + Some(constraints) => constraints.iter().any(|super_class| { + super_class.class == classname + || self.exists_as_super_class(super_class.class, classname) + }), + None => false, } } } - ///Searches through a type, comparing it with the type on the identifier, returning all the specialized constraints -pub fn find_specialized_instances(typ: &TcType, actual_type: &TcType, constraints: &[Constraint]) -> Vec<(Name, TcType)> { - debug!("Finding specialization {:?} => {:?} <-> {:?}", constraints, typ, actual_type); - let mut result = Vec::new(); +pub fn find_specialized_instances( + typ: &TcType, + actual_type: &TcType, + constraints: &[Constraint], +) -> Vec<(Name, TcType)> { + debug!( + "Finding specialization {:?} => {:?} <-> {:?}", + constraints, typ, actual_type + ); + let mut result = vec![]; find_specialized(&mut result, actual_type, typ, constraints); - if constraints.len() == 0 { - panic!("Could not find the specialized instance between {:?} <-> {:?}", typ, actual_type); - } + assert!( + !constraints.is_empty(), + "Could not find the specialized instance between {:?} <-> {:?}", + typ, + actual_type + ); result } -fn find_specialized(result: &mut Vec<(Name, TcType)>, actual_type: &TcType, typ: &TcType, constraints: &[Constraint]) { +fn find_specialized( + result: &mut Vec<(Name, TcType)>, + actual_type: &TcType, + typ: &TcType, + constraints: &[Constraint], +) { match (actual_type, typ) { (_, &Type::Variable(ref var)) => { for c in constraints.iter().filter(|c| c.variables[0] == *var) { @@ -1055,8 +1327,8 @@ fn find_specialized(result: &mut Vec<(Name, TcType)>, actual_type: &TcType, typ: } } (&Type::Application(ref lhs1, ref rhs1), &Type::Application(ref lhs2, ref rhs2)) => { - find_specialized(result, &**lhs1, &**lhs2, constraints); - find_specialized(result, &**rhs1, &**rhs2, constraints); + find_specialized(result, lhs1, lhs2, constraints); + find_specialized(result, rhs1, rhs2, constraints); } (_, &Type::Generic(ref var)) => { for c in constraints.iter().filter(|c| c.variables[0] == *var) { @@ -1065,7 +1337,7 @@ fn find_specialized(result: &mut Vec<(Name, TcType)>, actual_type: &TcType, typ: } } } - _ => () + _ => (), } } @@ -1073,18 +1345,18 @@ fn find_specialized(result: &mut Vec<(Name, TcType)>, actual_type: &TcType, typ: ///A quantified variable will when it is instantiated have new type variables fn quantify(start_var_age: isize, typ: &mut Qualified) { fn quantify_(start_var_age: isize, typ: &mut TcType) { - let x = match *typ { - Type::Variable(ref id) if id.age >= start_var_age => Some(id.clone()), - Type::Application(ref mut lhs, ref mut rhs) => { - quantify_(start_var_age, &mut **lhs); - quantify_(start_var_age, &mut **rhs); - None - } - _ => None - }; - match x { - Some(var) => *typ = Type::Generic(var), - None => () + let x = + match *typ { + Type::Variable(ref id) if id.age >= start_var_age => Some(id.clone()), + Type::Application(ref mut lhs, ref mut rhs) => { + quantify_(start_var_age, lhs); + quantify_(start_var_age, rhs); + None + } + _ => None, + }; + if let Some(var) = x { + *typ = Type::Generic(var); } } for constraint in typ.constraints.iter_mut() { @@ -1101,76 +1373,62 @@ pub fn replace_var(typ: &mut TcType, var: &TypeVariable, replacement: &TcType) { Type::Variable(ref v) => { if v == var { Some(replacement) - } - else { + } else { None } } Type::Constructor(_) => None, Type::Application(ref mut lhs, ref mut rhs) => { - replace_var(&mut **lhs, var, replacement); - replace_var(&mut **rhs, var, replacement); + replace_var(lhs, var, replacement); + replace_var(rhs, var, replacement); None } - Type::Generic(_) => panic!("replace_var called on Generic") + Type::Generic(_) => panic!("replace_var called on Generic"), }; - match new { - Some(x) => { - *typ = x.clone(); - } - None => () + if let Some(x) = new { + *typ = x.clone(); } } ///Returns true if the type is a function fn is_function(typ: &TcType) -> bool { - match *typ { - Type::Application(ref lhs, _) => { - match **lhs { - Type::Application(ref lhs, _) => { - match **lhs { - Type::Constructor(ref op) => op.name == intern("->"), - _ => false - } - } - _ => false + if let Type::Application(ref lhs, _) = typ { + if let Type::Application(ref lhs, _) = **lhs { + if let Type::Constructor(ref op) = **lhs { + return op.name == intern("->"); } } - _ => false } + false } ///Extracts the final return type of a type fn get_returntype(typ: &TcType) -> TcType { - match typ { - &Type::Application(_, ref rhs) => { - if is_function(typ) { - get_returntype(&**rhs) - } - else { - typ.clone() - } - } - _ => typ.clone() + let Type::Application(_, ref rhs) = typ else { + return typ.clone(); + }; + if is_function(typ) { + get_returntype(rhs) + } else { + typ.clone() } } ///Replace all typevariables using the substitution 'subs' -fn replace(constraints: &mut HashMap>, old : &mut TcType, subs : &Substitution) { +fn replace( + constraints: &mut HashMap>, + old: &mut TcType, + subs: &Substitution, +) { let replaced = match *old { - Type::Variable(ref id) => { - subs.subs.get(id).map(|new| { - new.clone() - }) - } + Type::Variable(ref id) => subs.subs.get(id).map(|new| new.clone()), Type::Application(ref mut lhs, ref mut rhs) => { - replace(constraints, &mut **lhs, subs); - replace(constraints, &mut **rhs, subs); + replace(constraints, lhs, subs); + replace(constraints, rhs, subs); None } _ => None, //panic!("replace called on Generic") }; - match replaced { - Some(x) => *old = x, - None => () + if let Some(x) = replaced { + *old = x; } } @@ -1178,34 +1436,37 @@ fn replace(constraints: &mut HashMap>, old : &mut TcType fn occurs(type_var: &TypeVariable, in_type: &TcType) -> bool { match in_type { &Type::Variable(ref var) => type_var.id == var.id, - &Type::Application(ref lhs, ref rhs) => occurs(type_var, &**lhs) || occurs(type_var, &**rhs), - _ => false + &Type::Application(ref lhs, ref rhs) => occurs(type_var, lhs) || occurs(type_var, rhs), + _ => false, } } ///Freshen creates new type variables at every position where Type::Generic(..) appears. fn freshen(env: &mut TypeEnvironment, subs: &mut Substitution, typ: &mut Qualified) { debug!("Freshen {:?}", typ); - fn freshen_(env: &mut TypeEnvironment, subs: &mut Substitution, constraints: &[Constraint], typ: &mut TcType) { + fn freshen_( + env: &mut TypeEnvironment, + subs: &mut Substitution, + constraints: &[Constraint], + typ: &mut TcType, + ) { let result = match *typ { Type::Generic(ref id) => freshen_var(env, subs, constraints, id), Type::Application(ref mut lhs, ref mut rhs) => { - freshen_(env, subs, constraints, &mut **lhs); - freshen_(env, subs, constraints, &mut **rhs); + freshen_(env, subs, constraints, lhs); + freshen_(env, subs, constraints, rhs); None } - _ => None + _ => None, }; - match result { - Some(x) => *typ = x, - None => () + if let Some(x) = result { + *typ = x; } } freshen_(env, subs, &*typ.constraints, &mut typ.value); for constraint in typ.constraints.iter_mut() { - match subs.subs.get(&constraint.variables[0]) { - Some(new) => constraint.variables[0] = new.var().clone(), - None => () + if let Some(new) = subs.subs.get(&constraint.variables[0]) { + constraint.variables[0] = new.var().clone(); } } } @@ -1214,31 +1475,32 @@ fn freshen_all(env: &mut TypeEnvironment, subs: &mut Substitution, typ: &mut TcT let result = match *typ { Type::Variable(ref id) => freshen_var(env, subs, &[], id), Type::Application(ref mut lhs, ref mut rhs) => { - freshen_all(env, subs, &mut **lhs); - freshen_all(env, subs, &mut **rhs); + freshen_all(env, subs, lhs); + freshen_all(env, subs, rhs); None } - _ => None + _ => None, }; - match result { - Some(x) => *typ = x, - None => () + if let Some(x) = result { + *typ = x; } } ///Updates the variable var, also making sure the constraints are updated appropriately -fn freshen_var(env: &mut TypeEnvironment, subs: &mut Substitution, constraints: &[Constraint], id: &TypeVariable) -> Option { - subs.subs.get(id) - .map(|var| var.clone()) - .or_else(|| { +fn freshen_var( + env: &mut TypeEnvironment, + subs: &mut Substitution, + constraints: &[Constraint], + id: &TypeVariable, +) -> Option { + subs.subs.get(id).map(|var| var.clone()).or_else(|| { let mut new = env.new_var_kind(id.kind.clone()); match new { Type::Variable(ref mut v) => v.age = id.age, - _ => () + _ => (), } subs.subs.insert(id.clone(), new.clone()); { - let constraints_for_id = constraints.iter() - .filter(|c| c.variables[0] == *id); + let constraints_for_id = constraints.iter().filter(|c| c.variables[0] == *id); //Add all the constraints to he environment for the 'new' variable for c in constraints_for_id { env.insert_constraint(new.var(), c.class.clone()); @@ -1249,13 +1511,22 @@ fn freshen_var(env: &mut TypeEnvironment, subs: &mut Substitution, constraints: } ///Takes two types and attempts to make them the same type -fn unify_location(env: &mut TypeEnvironment, subs: &mut Substitution, location: &Location, lhs: &mut TcType, rhs: &mut TcType) { +fn unify_location( + env: &mut TypeEnvironment, + subs: &mut Substitution, + location: &Location, + lhs: &mut TcType, + rhs: &mut TcType, +) { debug!("{:?} Unifying {:?} <-> {:?}", location, *lhs, *rhs); match unify(env, subs, lhs, rhs) { Ok(()) => (), - Err(error) => { - env.errors.insert(TypeErrorInfo { location: location.clone(), lhs: lhs.clone(), rhs: rhs.clone(), error: error }) - } + Err(error) => env.errors.insert(TypeErrorInfo { + location: location.clone(), + lhs: lhs.clone(), + rhs: rhs.clone(), + error, + }), } } @@ -1264,7 +1535,7 @@ struct TypeErrorInfo { location: Location, lhs: TcType, rhs: TcType, - error: Error + error: Error, } #[derive(Debug)] @@ -1272,7 +1543,7 @@ enum Error { UnifyFail(TcType, TcType), RecursiveUnification, WrongArity(TcType, TcType), - MissingInstance(InternedStr, TcType, TypeVariable) + MissingInstance(InternedStr, TcType, TypeVariable), } impl fmt::Display for TypeErrorInfo { @@ -1297,7 +1568,12 @@ impl fmt::Display for TypeErrorInfo { ///Tries to bind the type to the variable. ///Returns Ok if the binding was possible. ///Returns Error if the binding was not possible and the reason for the error. -fn bind_variable(env: &mut TypeEnvironment, subs: &mut Substitution, var: &TypeVariable, typ: &TcType) -> Result<(), Error> { +fn bind_variable( + env: &mut TypeEnvironment, + subs: &mut Substitution, + var: &TypeVariable, + typ: &TcType, +) -> Result<(), Error> { match *typ { Type::Variable(ref var2) => { if var != var2 { @@ -1305,13 +1581,10 @@ fn bind_variable(env: &mut TypeEnvironment, subs: &mut Substitution, var: &TypeV for (_, v) in subs.subs.iter_mut() { replace_var(v, var, typ); } - match env.constraints.remove(var) { - Some(constraints) => { - for c in constraints.iter() { - env.insert_constraint(var2, c.clone()); - } + if let Some(constraints) = env.constraints.remove(var) { + for c in constraints.iter() { + env.insert_constraint(var2, c.clone()); } - None => () } } Ok(()) @@ -1319,16 +1592,14 @@ fn bind_variable(env: &mut TypeEnvironment, subs: &mut Substitution, var: &TypeV _ => { if occurs(var, typ) { return Err(Error::RecursiveUnification); - } - else if var.kind != *typ.kind() { + } else if var.kind != *typ.kind() { return Err(Error::WrongArity(Type::Variable(var.clone()), typ.clone())); - } - else { + } else { for (_, replaced) in subs.subs.iter_mut() { replace_var(replaced, var, typ); } subs.subs.insert(var.clone(), typ.clone()); - let mut new_constraints = Vec::new(); + let mut new_constraints = vec![]; match env.constraints.get(var) { Some(constraints) => { for c in constraints.iter() { @@ -1337,22 +1608,32 @@ fn bind_variable(env: &mut TypeEnvironment, subs: &mut Substitution, var: &TypeV Err(missing_instance) => { match *typ { Type::Constructor(ref op) => { - if c.name == intern("Num") && (op.name == intern("Int") || op.name == intern("Double")) && *typ.kind() == Kind::Star { + if c.name == intern("Num") + && (op.name == intern("Int") + || op.name == intern("Double")) + && *typ.kind() == Kind::Star + { continue; - } - else if c.name == intern("Fractional") && intern("Double") == op.name && *typ.kind() == Kind::Star { + } else if c.name == intern("Fractional") + && intern("Double") == op.name + && *typ.kind() == Kind::Star + { continue; } } - _ => () + _ => (), } - return Err(Error::MissingInstance(missing_instance, typ.clone(), var.clone())); + return Err(Error::MissingInstance( + missing_instance, + typ.clone(), + var.clone(), + )); } - Ok(()) => () + Ok(()) => (), } } } - _ => () + _ => (), } for constraint in new_constraints.into_iter() { env.insert_constraint(&constraint.variables[0], constraint.class) @@ -1364,17 +1645,22 @@ fn bind_variable(env: &mut TypeEnvironment, subs: &mut Substitution, var: &TypeV } ///Tries to unify two types, updating the substition as well as the types directly with -///the new type values. -fn unify(env: &mut TypeEnvironment, subs: &mut Substitution, lhs: &mut TcType, rhs: &mut TcType) -> Result<(), Error> { +///the new type values. +fn unify( + env: &mut TypeEnvironment, + subs: &mut Substitution, + lhs: &mut TcType, + rhs: &mut TcType, +) -> Result<(), Error> { match (lhs, rhs) { - (&mut Type::Application(ref mut l1, ref mut r1), &mut Type::Application(ref mut l2, ref mut r2)) => { - unify(env, subs, &mut **l1, &mut**l2) - .and_then(|_| { - replace(&mut env.constraints, &mut **r1, subs); - replace(&mut env.constraints, &mut **r2, subs); - unify(env, subs, &mut **r1, &mut **r2) - }) - } + ( + &mut Type::Application(ref mut l1, ref mut r1), + &mut Type::Application(ref mut l2, ref mut r2), + ) => unify(env, subs, l1, l2).and_then(|_| { + replace(&mut env.constraints, r1, subs); + replace(&mut env.constraints, r2, subs); + unify(env, subs, r1, r2) + }), (&mut Type::Variable(ref mut lhs), &mut Type::Variable(ref mut rhs)) => { //If both are variables we choose that they younger variable is replaced by the oldest //This is because when doing the quantifying, only variables that are created during @@ -1387,8 +1673,7 @@ fn unify(env: &mut TypeEnvironment, subs: &mut Substitution, lhs: &mut TcType, r *lhs = rhs.clone(); } x - } - else { + } else { let x = bind_variable(env, subs, rhs, &Type::Variable(lhs.clone())); if x.is_ok() { *rhs = lhs.clone(); @@ -1397,8 +1682,14 @@ fn unify(env: &mut TypeEnvironment, subs: &mut Substitution, lhs: &mut TcType, r } } (&mut Type::Constructor(ref lhs), &mut Type::Constructor(ref rhs)) => { - if lhs.name == rhs.name { Ok(()) } - else { Err(Error::UnifyFail(Type::Constructor(lhs.clone()), Type::Constructor(rhs.clone()))) } + if lhs.name == rhs.name { + Ok(()) + } else { + Err(Error::UnifyFail( + Type::Constructor(lhs.clone()), + Type::Constructor(rhs.clone()), + )) + } } (lhs, rhs) => { let x = match lhs { @@ -1406,7 +1697,7 @@ fn unify(env: &mut TypeEnvironment, subs: &mut Substitution, lhs: &mut TcType, r lhs => { let y = match rhs { &mut Type::Variable(ref mut var) => bind_variable(env, subs, var, lhs), - _ => return Err(Error::UnifyFail(lhs.clone(), rhs.clone())) + _ => return Err(Error::UnifyFail(lhs.clone(), rhs.clone())), }; if y.is_ok() { *rhs = lhs.clone(); @@ -1422,21 +1713,37 @@ fn unify(env: &mut TypeEnvironment, subs: &mut Substitution, lhs: &mut TcType, r } } -fn match_or_fail(env: &mut TypeEnvironment, subs: &mut Substitution, location: &Location, lhs: &mut TcType, rhs: &TcType) { +fn match_or_fail( + env: &mut TypeEnvironment, + subs: &mut Substitution, + location: &Location, + lhs: &mut TcType, + rhs: &TcType, +) { debug!("Match {:?} --> {:?}", *lhs, *rhs); match match_(env, subs, lhs, rhs) { Ok(()) => (), - Err(error) => env.errors.insert(TypeErrorInfo { location: location.clone(), lhs: lhs.clone(), rhs: rhs.clone(), error: error }) + Err(error) => env.errors.insert(TypeErrorInfo { + location: location.clone(), + lhs: lhs.clone(), + rhs: rhs.clone(), + error, + }), } } ///Match performs matching which is walks through the same process as unify but only allows ///the updates to be one way (such as between a type and the type in a type signature). -fn match_(env: &mut TypeEnvironment, subs: &mut Substitution, lhs: &mut TcType, rhs: &TcType) -> Result<(), Error> { +fn match_( + env: &mut TypeEnvironment, + subs: &mut Substitution, + lhs: &mut TcType, + rhs: &TcType, +) -> Result<(), Error> { match (lhs, rhs) { (&mut Type::Application(ref mut l1, ref mut r1), &Type::Application(ref l2, ref r2)) => { - match_(env, subs, &mut **l1, &**l2).and_then(|_| { - replace(&mut env.constraints, &mut **r1, subs); - match_(env, subs, &mut **r1, &**r2) + match_(env, subs, l1, l2).and_then(|_| { + replace(&mut env.constraints, r1, subs); + match_(env, subs, r1, r2) }) } (&mut Type::Variable(ref mut lhs), &Type::Variable(ref rhs)) => { @@ -1444,12 +1751,20 @@ fn match_(env: &mut TypeEnvironment, subs: &mut Substitution, lhs: &mut TcType, *lhs = rhs.clone(); x } - (&mut Type::Constructor(ref lhs), &Type::Constructor(ref rhs)) => - if lhs.name == rhs.name { Ok(()) } else { Err(Error::UnifyFail(Type::Constructor(lhs.clone()), Type::Constructor(rhs.clone()))) }, + (&mut Type::Constructor(ref lhs), &Type::Constructor(ref rhs)) => { + if lhs.name == rhs.name { + Ok(()) + } else { + Err(Error::UnifyFail( + Type::Constructor(lhs.clone()), + Type::Constructor(rhs.clone()), + )) + } + } (lhs, rhs) => { let x = match lhs { &mut Type::Variable(ref mut var) => bind_variable(env, subs, var, rhs), - _ => return Err(Error::UnifyFail(lhs.clone(), rhs.clone())) + _ => return Err(Error::UnifyFail(lhs.clone(), rhs.clone())), }; *lhs = rhs.clone(); x @@ -1457,7 +1772,6 @@ fn match_(env: &mut TypeEnvironment, subs: &mut Substitution, lhs: &mut TcType, } } - ///Creates a graph containing a vertex for each binding and edges from every binding to every other ///binding that it references fn build_graph(bindings: &dyn Bindings) -> Graph<(usize, usize)> { @@ -1484,130 +1798,141 @@ fn build_graph(bindings: &dyn Bindings) -> Graph<(usize, usize)> { } ///Adds an edge for each identifier which refers to a binding in the graph -fn add_edges(graph: &mut Graph, map: &HashMap, function_index: VertexIndex, expr: &TypedExpr) { +fn add_edges( + graph: &mut Graph, + map: &HashMap, + function_index: VertexIndex, + expr: &TypedExpr, +) { struct EdgeVisitor<'a, T: 'a> { graph: &'a mut Graph, map: &'a HashMap, - function_index: VertexIndex + function_index: VertexIndex, } - impl <'a, T: 'static> Visitor for EdgeVisitor<'a, T> { + impl<'a, T: 'static> Visitor for EdgeVisitor<'a, T> { fn visit_expr(&mut self, expr: &TypedExpr) { - match expr.expr { - Identifier(ref n) => { - match self.map.get(n) { - Some(index) => self.graph.connect(self.function_index, *index), - None => () - } - } - _ => walk_expr(self, expr) - } + let Identifier(ref n) = expr.expr else { + return walk_expr(self, expr); + }; + + self.map + .get(n) + .map(|index| self.graph.connect(self.function_index, *index)); } } - EdgeVisitor { graph: graph, map: map, function_index: function_index }.visit_expr(expr) + EdgeVisitor { + graph, + map, + function_index, + } + .visit_expr(expr) } ///Walks through the type and calls the functions on each variable and type constructor fn each_type(typ: &Type, mut var_fn: F, mut op_fn: G) - where F: FnMut(&TypeVariable), G: FnMut(&TypeConstructor) { +where + F: FnMut(&TypeVariable), + G: FnMut(&TypeConstructor), +{ each_type_(typ, &mut var_fn, &mut op_fn); } -fn each_type_(typ: &Type, var_fn: &mut dyn FnMut(&TypeVariable), op_fn: &mut dyn FnMut(&TypeConstructor)) { +fn each_type_( + typ: &Type, + var_fn: &mut dyn FnMut(&TypeVariable), + op_fn: &mut dyn FnMut(&TypeConstructor), +) { match typ { &Type::Variable(ref var) => (*var_fn)(var), &Type::Constructor(ref op) => (*op_fn)(op), &Type::Application(ref lhs, ref rhs) => { - each_type_(&**lhs, var_fn, op_fn); - each_type_(&**rhs, var_fn, op_fn); + each_type_(lhs, var_fn, op_fn); + each_type_(rhs, var_fn, op_fn); } - _ => () + _ => (), } } ///Finds the kind for the variable test and makes sure that all occurences of the variable ///has the same kind in 'typ' ///'expected' should be None if the kinds is currently unknown, otherwise the expected kind -fn find_kind(test: &TypeVariable, expected: Option, typ: &TcType) -> Result, &'static str> { +fn find_kind( + test: &TypeVariable, + expected: Option, + typ: &TcType, +) -> Result, &'static str> { match *typ { - Type::Variable(ref var) if test.id == var.id => { - match expected { - Some(k) => { - if k != var.kind { - Err("Kinds do not match") - } - else { - Ok(Some(k)) - } + Type::Variable(ref var) if test.id == var.id => match expected { + Some(k) => { + if k != var.kind { + Err("Kinds do not match") + } else { + Ok(Some(k)) } - None => Ok(Some(var.kind.clone())) } - } + None => Ok(Some(var.kind.clone())), + }, Type::Application(ref lhs, ref rhs) => { - find_kind(test, expected, &**lhs) - .and_then(|result| { - find_kind(test, result, &**rhs) - }) + find_kind(test, expected, lhs).and_then(|result| find_kind(test, result, rhs)) } - _ => Ok(expected) + _ => Ok(expected), } } ///Takes a function type and calls the 'func' with the argument to the function and its ///return type. ///Returns true if the function was called. -pub fn with_arg_return(func_type: &mut TcType, func: F) -> bool where F: FnOnce(&mut TcType, &mut TcType) { - match *func_type { - Type::Application(ref mut lhs, ref mut return_type) => { - match **lhs { - Type::Application(_, ref mut arg_type) => { - func(&mut **arg_type, &mut **return_type); - true - } - _ => false - } +pub fn with_arg_return(func_type: &mut TcType, func: F) -> bool +where + F: FnOnce(&mut TcType, &mut TcType), +{ + if let Type::Application(ref mut lhs, ref mut return_type) = func_type { + if let Type::Application(_, ref mut arg_type) = **lhs { + func(arg_type, return_type); + return true; } - _ => false } + false } #[cfg(test)] -pub fn identifier(i : &str) -> TypedExpr { +pub fn identifier(i: &str) -> TypedExpr { TypedExpr::new(Identifier(intern(i))) } #[cfg(test)] -pub fn lambda(arg : &str, body : TypedExpr) -> TypedExpr { - TypedExpr::new(Lambda(Pattern::Identifier(intern(arg)), Box::new(body))) +pub fn lambda(arg: &str, body: TypedExpr) -> TypedExpr { + TypedExpr::new(Lambda(Pattern::Identifier(intern(arg)), body.into())) } #[cfg(test)] -pub fn number(i : isize) -> TypedExpr { +pub fn number(i: isize) -> TypedExpr { TypedExpr::new(Literal(Integral(i))) } #[cfg(test)] -pub fn rational(i : f64) -> TypedExpr { +pub fn rational(i: f64) -> TypedExpr { TypedExpr::new(Literal(Fractional(i))) } #[cfg(test)] -pub fn apply(func : TypedExpr, arg : TypedExpr) -> TypedExpr { - TypedExpr::new(Apply(Box::new(func), Box::new(arg))) +pub fn apply(func: TypedExpr, arg: TypedExpr) -> TypedExpr { + TypedExpr::new(Apply(func.into(), arg.into())) } #[cfg(test)] pub fn op_apply(lhs: TypedExpr, op: InternedStr, rhs: TypedExpr) -> TypedExpr { - TypedExpr::new(OpApply(Box::new(lhs), op, Box::new(rhs))) + TypedExpr::new(OpApply(lhs.into(), op, rhs.into())) } #[cfg(test)] -pub fn let_(bindings : Vec, expr : TypedExpr) -> TypedExpr { - TypedExpr::new(Let(bindings, Box::new(expr))) +pub fn let_(bindings: Vec, expr: TypedExpr) -> TypedExpr { + TypedExpr::new(Let(bindings, expr.into())) } #[cfg(test)] -pub fn case(expr : TypedExpr, alts: Vec) -> TypedExpr { - TypedExpr::new(Case(Box::new(expr), alts)) +pub fn case(expr: TypedExpr, alts: Vec) -> TypedExpr { + TypedExpr::new(Case(expr.into(), alts)) } #[cfg(test)] pub fn if_else(expr: TypedExpr, t: TypedExpr, f: TypedExpr) -> TypedExpr { - TypedExpr::new(IfElse(Box::new(expr), Box::new(t), Box::new(f))) + TypedExpr::new(IfElse(expr.into(), t.into(), f.into())) } #[cfg(test)] -pub fn paren(expr : TypedExpr) -> TypedExpr { - TypedExpr::new(Paren(Box::new(expr))) +pub fn paren(expr: TypedExpr) -> TypedExpr { + TypedExpr::new(Paren(expr.into())) } pub fn typecheck_string(module: &str) -> Result>, ::std::string::String> { @@ -1620,10 +1945,14 @@ pub fn typecheck_string(module: &str) -> Result>, ::std::string ///Parses a module, renames and typechecks it, as well as all of its imported modules pub fn typecheck_module(module: &str) -> Result>, ::std::string::String> { use crate::parser::parse_modules; - parse_modules(module).map_err(|e| format!("{:?}", e)).and_then(typecheck_modules_common) + parse_modules(module) + .map_err(|e| format!("{:?}", e)) + .and_then(typecheck_modules_common) } -fn typecheck_modules_common(modules: Vec) -> Result>, ::std::string::String> { +fn typecheck_modules_common( + modules: Vec, +) -> Result>, ::std::string::String> { use crate::infix::PrecedenceVisitor; let mut modules = rename_modules(modules).map_err(|e| format!("{}", e))?; let mut prec_visitor = PrecedenceVisitor::new(); @@ -1638,192 +1967,224 @@ fn typecheck_modules_common(modules: Vec) -> Result>, : } env.errors.into_result(()) }; - result.map(|()| modules) + result + .map(|()| modules) .map_err(|e| format!("{}", TypeError(e))) } - #[cfg(test)] pub mod test { -use crate::interner::*; -use crate::module::*; -use crate::typecheck::*; -use crate::renamer::Name; -use crate::renamer::tests::{rename_expr, rename_module}; - -use crate::parser::Parser; -use std::io::Read; -use std::path::Path; -use std::fs::File; - -use ::test::Bencher; - -pub fn do_typecheck(input: &str) -> Module { - do_typecheck_with(input, &[]) -} -pub fn do_typecheck_with(input: &str, types: &[&dyn DataTypes]) -> Module { - let mut parser = Parser::new(input.chars()); - let mut module = rename_module(parser.module().unwrap()); - let mut env = TypeEnvironment::new(); - for t in types.iter() { - env.add_types(*t); - } - env.typecheck_module_(&mut module); - module -} - -fn un_name_type(typ: Type) -> Type { - typ.map(|name| name.name) -} + use crate::{ + interner::*, + module::*, + renamer::{ + tests::{ + rename_expr, + rename_module, + }, + Name, + }, + typecheck::*, + }; -fn un_name(typ: Qualified, Name>) -> Qualified, InternedStr> { - let Qualified { constraints, value: typ } = typ; - let constraints2: Vec = constraints.into_iter() - .map(|c| Constraint { class: c.class.name, variables: c.variables }) - .collect(); - qualified(constraints2, un_name_type(typ)) -} + use { + crate::parser::Parser, + std::{ + fs::File, + io::Read, + path::Path, + }, + }; + use ::test::Bencher; -#[test] -fn application() { - let mut env = TypeEnvironment::new(); - let n = identifier("primIntAdd"); - let num = number(1); - let e = apply(n, num); - let mut expr = rename_expr(e); - let unary_func = function_type_(int_type(), int_type()); - env.typecheck_expr_(&mut expr); + pub fn do_typecheck(input: &str) -> Module { + do_typecheck_with(input, &[]) + } + pub fn do_typecheck_with(input: &str, types: &[&dyn DataTypes]) -> Module { + let mut parser = Parser::new(input.chars()); + let mut module = rename_module(parser.module().unwrap()); + let mut env = TypeEnvironment::new(); + for t in types.iter() { + env.add_types(*t); + } + env.typecheck_module_(&mut module); + module + } - assert!(expr.typ == unary_func); -} + fn un_name_type(typ: Type) -> Type { + typ.map(|name| name.name) + } -#[test] -fn typecheck_lambda() { - let mut env = TypeEnvironment::new(); - let unary_func = function_type_(int_type(), int_type()); + fn un_name(typ: Qualified, Name>) -> Qualified, InternedStr> { + let Qualified { + constraints, + value: typ, + } = typ; + let constraints2: Vec = + constraints + .into_iter() + .map(|c| Constraint { + class: c.class.name, + variables: c.variables, + }) + .collect(); + qualified(constraints2, un_name_type(typ)) + } - let e = lambda("x", apply(apply(identifier("primIntAdd"), identifier("x")), number(1))); - let mut expr = rename_expr(e); - env.typecheck_expr_(&mut expr); + #[test] + fn application() { + let mut env = TypeEnvironment::new(); + let n = identifier("primIntAdd"); + let num = number(1); + let e = apply(n, num); + let mut expr = rename_expr(e); + let unary_func = function_type_(int_type(), int_type()); + env.typecheck_expr_(&mut expr); - assert_eq!(expr.typ, unary_func); -} + assert!(expr.typ == unary_func); + } -#[test] -fn typecheck_let() { - let mut env = TypeEnvironment::new(); - let unary_func = function_type_(int_type(), int_type()); + #[test] + fn typecheck_lambda() { + let mut env = TypeEnvironment::new(); + let unary_func = function_type_(int_type(), int_type()); - //let test x = add x in test - let unary_bind = lambda("x", apply(apply(identifier("primIntAdd"), identifier("x")), number(1))); - let e = let_(vec![Binding { arguments: vec![], name: intern("test"), matches: Match::Simple(unary_bind), typ: Default::default() , where_bindings: None }], identifier("test")); - let mut expr = rename_expr(e); - env.typecheck_expr_(&mut expr); + let e = lambda( + "x", + apply(apply(identifier("primIntAdd"), identifier("x")), number(1)), + ); + let mut expr = rename_expr(e); + env.typecheck_expr_(&mut expr); - assert_eq!(expr.typ, unary_func); -} + assert_eq!(expr.typ, unary_func); + } -#[test] -fn typecheck_case() { - let mut env = TypeEnvironment::new(); - let type_int = int_type(); + #[test] + fn typecheck_let() { + let mut env = TypeEnvironment::new(); + let unary_func = function_type_(int_type(), int_type()); + + //let test x = add x in test + let unary_bind = lambda( + "x", + apply(apply(identifier("primIntAdd"), identifier("x")), number(1)), + ); + let e = let_( + vec![Binding { + arguments: vec![], + name: intern("test"), + matches: Match::Simple(unary_bind), + typ: <_>::default(), + where_bindings: None, + }], + identifier("test"), + ); + let mut expr = rename_expr(e); + env.typecheck_expr_(&mut expr); + + assert_eq!(expr.typ, unary_func); + } + + #[test] + fn typecheck_case() { + let mut env = TypeEnvironment::new(); + let type_int = int_type(); - let mut parser = Parser::new(r"case [] of { x:xs -> primIntAdd x 2 ; [] -> 3}".chars()); - let mut expr = rename_expr(parser.expression_().unwrap()); - env.typecheck_expr_(&mut expr); + let mut parser = Parser::new(r"case [] of { x:xs -> primIntAdd x 2 ; [] -> 3}".chars()); + let mut expr = rename_expr(parser.expression_().unwrap()); + env.typecheck_expr_(&mut expr); - assert_eq!(expr.typ, type_int); - match &expr.expr { - &Case(ref case_expr, _) => { - assert_eq!(case_expr.typ, list_type(type_int)); + assert_eq!(expr.typ, type_int); + match &expr.expr { + &Case(ref case_expr, _) => { + assert_eq!(case_expr.typ, list_type(type_int)); + } + _ => panic!("typecheck_case"), } - _ => panic!("typecheck_case") } -} -#[test] -fn typecheck_list() { - let file = -r"mult2 x = primIntMultiply x 2 + #[test] + fn typecheck_list() { + let file = r"mult2 x = primIntMultiply x 2 main = case [mult2 123, 0] of x:xs -> x [] -> 10"; - let module = do_typecheck(file); + let module = do_typecheck(file); - assert_eq!(module.bindings[1].typ.value, int_type()); -} - -#[test] -fn test_typecheck_string() { - let mut env = TypeEnvironment::new(); + assert_eq!(module.bindings[1].typ.value, int_type()); + } - let mut parser = Parser::new("\"hello\"".chars()); - let mut expr = rename_expr(parser.expression_().unwrap()); - env.typecheck_expr_(&mut expr); + #[test] + fn test_typecheck_string() { + let mut env = TypeEnvironment::new(); - assert_eq!(expr.typ, list_type(char_type())); -} + let mut parser = Parser::new("\"hello\"".chars()); + let mut expr = rename_expr(parser.expression_().unwrap()); + env.typecheck_expr_(&mut expr); -#[test] -fn typecheck_tuple() { - let mut env = TypeEnvironment::new(); + assert_eq!(expr.typ, list_type(char_type())); + } - let mut parser = Parser::new("(primIntAdd 0 0, \"a\")".chars()); - let mut expr = rename_expr(parser.expression_().unwrap()); - env.typecheck_expr_(&mut expr); + #[test] + fn typecheck_tuple() { + let mut env = TypeEnvironment::new(); - let list = list_type(char_type()); - assert_eq!(expr.typ, Type::new_op(intern("(,)"), vec![int_type(), list])); -} + let mut parser = Parser::new("(primIntAdd 0 0, \"a\")".chars()); + let mut expr = rename_expr(parser.expression_().unwrap()); + env.typecheck_expr_(&mut expr); -#[test] -fn typecheck_module_() { + let list = list_type(char_type()); + assert_eq!( + expr.typ, + Type::new_op(intern("(,)"), vec![int_type(), list]) + ); + } - let file = -r"data Bool = True | False + #[test] + fn typecheck_module_() { + let file = r"data Bool = True | False test x = True"; - let module = do_typecheck(file); - - let typ = function_type_(Type::new_var(intern("a")), bool_type()); - assert_eq!(module.bindings[0].typ.value, typ); -} + let module = do_typecheck(file); + let typ = function_type_("a".into(), bool_type()); + assert_eq!(module.bindings[0].typ.value, typ); + } -#[test] -fn typecheck_recursive_let() { - let mut env = TypeEnvironment::new(); + #[test] + fn typecheck_recursive_let() { + let mut env = TypeEnvironment::new(); - let mut parser = Parser::new( -r"let + let mut parser = Parser::new( + r"let a = primIntAdd 0 1 test = primIntAdd 1 2 : test2 test2 = 2 : test b = test -in b".chars()); - let mut expr = rename_expr(parser.expression_().unwrap()); - env.typecheck_expr_(&mut expr); - - - let int_type = int_type(); - let list_type = list_type(int_type.clone()); - match &expr.expr { - &Let(ref binds, _) => { - assert_eq!(binds.len(), 4); - assert_eq!(binds[0].name.as_ref(), "a"); - assert_eq!(binds[0].typ.value, int_type); - assert_eq!(binds[1].name.as_ref(), "test"); - assert_eq!(binds[1].typ.value, list_type); - } - _ => panic!("Error") +in b" + .chars(), + ); + let mut expr = rename_expr(parser.expression_().unwrap()); + env.typecheck_expr_(&mut expr); + + let int_type = int_type(); + let list_type = list_type(int_type.clone()); + match &expr.expr { + &Let(ref binds, _) => { + assert_eq!(binds.len(), 4); + assert_eq!(binds[0].name.as_ref(), "a"); + assert_eq!(binds[0].typ.value, int_type); + assert_eq!(binds[1].name.as_ref(), "test"); + assert_eq!(binds[1].typ.value, list_type); + } + _ => panic!("Error"), + } } -} -#[test] -fn typecheck_constraints() { - let file = -r"class Test a where + #[test] + fn typecheck_constraints() { + let file = r"class Test a where test :: a -> Int instance Test Int where @@ -1831,44 +2192,46 @@ instance Test Int where main = test 1"; - let module = do_typecheck(file); + let module = do_typecheck(file); - let typ = &module.bindings[0].typ.value; - assert_eq!(typ, &int_type()); -} + let typ = &module.bindings[0].typ.value; + assert_eq!(typ, &int_type()); + } -//Test that calling a function with constraints will propagate the constraints to -//the type of the caller -#[test] -fn typecheck_constraints2() { - let mut parser = Parser::new( -r"class Test a where + //Test that calling a function with constraints will propagate the constraints to + //the type of the caller + #[test] + fn typecheck_constraints2() { + let mut parser = + Parser::new( + r"class Test a where test :: a -> Int instance Test Int where test x = 10 -main x y = primIntAdd (test x) (test y)".chars()); +main x y = primIntAdd (test x) (test y)" + .chars(), + ); - let mut module = rename_module(parser.module().unwrap()); + let mut module = rename_module(parser.module().unwrap()); - let mut env = TypeEnvironment::new(); - env.typecheck_module_(&mut module); + let mut env = TypeEnvironment::new(); + env.typecheck_module_(&mut module); - let typ = &module.bindings[0].typ; - let a = Type::new_var(intern("a")); - let b = Type::new_var(intern("b")); - let test = function_type_(a.clone(), function_type_(b.clone(), int_type())); - assert_eq!(&typ.value, &test); - assert_eq!(typ.constraints[0].class.as_ref(), "Test"); - assert_eq!(typ.constraints[1].class.as_ref(), "Test"); -} + let typ = &module.bindings[0].typ; + let a: Type<_> = "a".into(); + let b: Type<_> = "b".into(); + let test = function_type_(a.clone(), function_type_(b.clone(), int_type())); + assert_eq!(&typ.value, &test); + assert_eq!(typ.constraints[0].class.as_ref(), "Test"); + assert_eq!(typ.constraints[1].class.as_ref(), "Test"); + } -#[test] -#[should_panic] -fn typecheck_constraints_no_instance() { - let file = -r"class Test a where + #[test] + #[should_panic] + fn typecheck_constraints_no_instance() { + let file = r"class Test a where test :: a -> Int instance Test Int where @@ -1876,13 +2239,13 @@ instance Test Int where main = test [1]"; - do_typecheck(file); -} + do_typecheck(file); + } -#[test] -fn typecheck_super_class() { - let mut parser = Parser::new( -r"data Bool = True | False + #[test] + fn typecheck_super_class() { + let mut parser = Parser::new( + r"data Bool = True | False class Eq a where (==) :: a -> a -> Bool @@ -1903,25 +2266,30 @@ test x y = case x < y of True -> True False -> x == y -".chars()); +" + .chars(), + ); - let mut module = rename_module(parser.module().unwrap()); + let mut module = rename_module(parser.module().unwrap()); - let mut env = TypeEnvironment::new(); - env.typecheck_module_(&mut module); + let mut env = TypeEnvironment::new(); + env.typecheck_module_(&mut module); - let typ = &module.bindings[0].typ; - let a = Type::new_var(intern("a")); - assert_eq!(typ.value, function_type_(a.clone(), function_type_(a.clone(), bool_type()))); - assert_eq!(typ.constraints.len(), 1); - assert_eq!(typ.constraints[0].class.as_ref(), "Ord"); -} + let typ = &module.bindings[0].typ; + let a: Type<_> = "a".into(); + assert_eq!( + typ.value, + function_type_(a.clone(), function_type_(a.clone(), bool_type())) + ); + assert_eq!(typ.constraints.len(), 1); + assert_eq!(typ.constraints[0].class.as_ref(), "Ord"); + } -#[test] -#[should_panic] -fn typecheck_missing_super_class() { - let mut parser = Parser::new( -r"data Bool = True | False + #[test] + #[should_panic] + fn typecheck_missing_super_class() { + let mut parser = Parser::new( + r"data Bool = True | False class Eq a where (==) :: a -> a -> Bool @@ -1935,18 +2303,20 @@ instance Ord Bool where test y = False < y -".chars()); +" + .chars(), + ); - let mut module = rename_module(parser.module().unwrap()); + let mut module = rename_module(parser.module().unwrap()); - let mut env = TypeEnvironment::new(); - env.typecheck_module_(&mut module); -} + let mut env = TypeEnvironment::new(); + env.typecheck_module_(&mut module); + } -#[test] -fn typecheck_instance_super_class() { - let mut parser = Parser::new( -r"data Bool = True | False + #[test] + fn typecheck_instance_super_class() { + let mut parser = Parser::new( + r"data Bool = True | False class Eq a where (==) :: a -> a -> Bool @@ -1964,35 +2334,42 @@ instance Eq a => Eq [a] where (&&) x y = case x of True -> y False -> False -".chars()); - - let mut module = rename_module(parser.module().unwrap()); +" + .chars(), + ); - let mut env = TypeEnvironment::new(); - env.typecheck_module_(&mut module); + let mut module = rename_module(parser.module().unwrap()); - let typ = &module.instances[0].bindings[0].typ; - let var = un_name_type(typ.value.appl().appr().appr().clone()); - let list_type = list_type(var.clone()); - assert_eq!(un_name(typ.clone()), qualified(vec![Constraint { class: intern("Eq"), variables: vec![var.var().clone()] }], - function_type_(list_type.clone(), function_type_(list_type, bool_type())))); -} + let mut env = TypeEnvironment::new(); + env.typecheck_module_(&mut module); -#[test] -fn typecheck_num_double() { + let typ = &module.instances[0].bindings[0].typ; + let var = un_name_type(typ.value.appl().appr().appr().clone()); + let list_type = list_type(var.clone()); + assert_eq!( + un_name(typ.clone()), + qualified( + vec![Constraint { + class: intern("Eq"), + variables: vec![var.var().clone()] + }], + function_type_(list_type.clone(), function_type_(list_type, bool_type())) + ) + ); + } - let file = -r"test x = primDoubleAdd 0 x"; - let module = do_typecheck(file); + #[test] + fn typecheck_num_double() { + let file = r"test x = primDoubleAdd 0 x"; + let module = do_typecheck(file); - let typ = function_type_(double_type(), double_type()); - assert_eq!(module.bindings[0].typ.value, typ); -} + let typ = function_type_(double_type(), double_type()); + assert_eq!(module.bindings[0].typ.value, typ); + } -#[test] -fn typecheck_functor() { - let file = -r"data Maybe a = Just a | Nothing + #[test] + fn typecheck_functor() { + let file = r"data Maybe a = Just a | Nothing class Functor f where fmap :: (a -> b) -> f a -> f b @@ -2004,17 +2381,19 @@ instance Functor Maybe where add2 x = primIntAdd x 2 main = fmap add2 (Just 3)"; - let module = do_typecheck(file); + let module = do_typecheck(file); - let main = &module.bindings[1]; - assert_eq!(main.typ.value, Type::new_op(intern("Maybe"), vec![int_type()])); -} -#[should_panic] -#[test] -fn typecheck_functor_error() { - - do_typecheck( -r"data Maybe a = Just a | Nothing + let main = &module.bindings[1]; + assert_eq!( + main.typ.value, + Type::new_op(intern("Maybe"), vec![int_type()]) + ); + } + #[should_panic] + #[test] + fn typecheck_functor_error() { + do_typecheck( + r"data Maybe a = Just a | Nothing class Functor f where fmap :: (a -> b) -> f a -> f b @@ -2025,49 +2404,53 @@ instance Functor Maybe where Nothing -> Nothing add2 x = primIntAdd x 2 -main = fmap add2 3"); -} - -#[test] -fn typecheck_prelude() { - let path = &Path::new("Prelude.hs"); - let mut contents = ::std::string::String::new(); - File::open(path).and_then(|mut f| f.read_to_string(&mut contents)).unwrap(); - let module = do_typecheck(contents.as_ref()); - - let id = module.bindings.iter().find(|bind| bind.name.as_ref() == "id"); - assert!(id != None); - let id_bind = id.unwrap(); - assert_eq!(id_bind.typ.value, function_type_(Type::new_var(intern("a")), Type::new_var(intern("a")))); -} +main = fmap add2 3", + ); + } -#[test] -fn typecheck_import() { - - let prelude = { + #[test] + fn typecheck_prelude() { let path = &Path::new("Prelude.hs"); let mut contents = ::std::string::String::new(); - File::open(path).and_then(|mut f| f.read_to_string(&mut contents)).unwrap(); - do_typecheck(contents.as_ref()) - }; + File::open(path) + .and_then(|mut f| f.read_to_string(&mut contents)) + .unwrap(); + let module = do_typecheck(contents.as_ref()); + + let id = module + .bindings + .iter() + .find(|bind| bind.name.as_ref() == "id"); + assert!(id != None); + let id_bind = id.unwrap(); + assert_eq!(id_bind.typ.value, function_type_("a".into(), "a".into())); + } + + #[test] + fn typecheck_import() { + let prelude = { + let path = &Path::new("Prelude.hs"); + let mut contents = ::std::string::String::new(); + File::open(path) + .and_then(|mut f| f.read_to_string(&mut contents)) + .unwrap(); + do_typecheck(contents.as_ref()) + }; - let file = -r" + let file = r" test1 = map not [True, False] test2 = id (primIntAdd 2 0)"; - let module = do_typecheck_with(file, &[&prelude as &dyn DataTypes]); + let module = do_typecheck_with(file, &[&prelude as &dyn DataTypes]); - assert_eq!(module.bindings[0].name.as_ref(), "test1"); - assert_eq!(module.bindings[0].typ.value, list_type(bool_type())); - assert_eq!(module.bindings[1].name.as_ref(), "test2"); - assert_eq!(module.bindings[1].typ.value, int_type()); -} + assert_eq!(module.bindings[0].name.as_ref(), "test1"); + assert_eq!(module.bindings[0].typ.value, list_type(bool_type())); + assert_eq!(module.bindings[1].name.as_ref(), "test2"); + assert_eq!(module.bindings[1].typ.value, int_type()); + } -#[test] -fn type_declaration() { - - let input = -r" + #[test] + fn type_declaration() { + let input = r" class Test a where test :: a -> Int @@ -2076,130 +2459,158 @@ instance Test Int where test2 :: Test a => a -> Int -> Int test2 x y = primIntAdd (test x) y"; - let module = do_typecheck(input); + let module = do_typecheck(input); - assert_eq!(module.bindings[0].typ, module.type_declarations[0].typ); -} + assert_eq!(module.bindings[0].typ, module.type_declarations[0].typ); + } -#[test] -fn do_expr_simple() { - - let prelude = { - let path = &Path::new("Prelude.hs"); - let mut contents = ::std::string::String::new(); - File::open(path).and_then(|mut f| f.read_to_string(&mut contents)).unwrap(); - do_typecheck(contents.as_ref()) - }; + #[test] + fn do_expr_simple() { + let prelude = { + let path = &Path::new("Prelude.hs"); + let mut contents = ::std::string::String::new(); + File::open(path) + .and_then(|mut f| f.read_to_string(&mut contents)) + .unwrap(); + do_typecheck(contents.as_ref()) + }; - let file = -r" + let file = r" test x = do let z = [1::Int] y = reverse x t = [2::Int] putStrLn y "; - let module = do_typecheck_with(file, &[&prelude as &dyn DataTypes]); - - assert_eq!(module.bindings[0].typ.value, function_type_(list_type(char_type()), io(unit()))); -} - -#[test] -fn do_expr_pattern() { - - let prelude = { - let path = &Path::new("Prelude.hs"); - let mut contents = ::std::string::String::new(); - File::open(path).and_then(|mut f| f.read_to_string(&mut contents)).unwrap(); - do_typecheck(&contents) - }; + let module = do_typecheck_with(file, &[&prelude as &dyn DataTypes]); + + assert_eq!( + module.bindings[0].typ.value, + function_type_(list_type(char_type()), io(unit())) + ); + } + + #[test] + fn do_expr_pattern() { + let prelude = { + let path = &Path::new("Prelude.hs"); + let mut contents = ::std::string::String::new(); + File::open(path) + .and_then(|mut f| f.read_to_string(&mut contents)) + .unwrap(); + do_typecheck(&contents) + }; - let file = -r" + let file = r" test x = do y:ys <- x return y "; - let module = do_typecheck_with(file, &[&prelude as &dyn DataTypes]); - - let var = Type::new_var(intern("a")); - let t = function_type_(Type::new_var_args(intern("c"), vec![list_type(var.clone())]), Type::new_var_args(intern("c"), vec![var.clone()])); - assert_eq!(module.bindings[0].typ.value, t); - assert_eq!(module.bindings[0].typ.constraints[0].class.as_ref(), "Monad"); -} - -#[test] -fn binding_pattern() { - let module = do_typecheck(r" + let module = do_typecheck_with(file, &[&prelude as &dyn DataTypes]); + + let var: Type<_> = "a".into(); + let t = function_type_( + Type::new_var_args("c".into(), vec![list_type(var.clone())]), + Type::new_var_args("c".into(), vec![var.clone()]), + ); + assert_eq!(module.bindings[0].typ.value, t); + assert_eq!( + module.bindings[0].typ.constraints[0].class.as_ref(), + "Monad" + ); + } + + #[test] + fn binding_pattern() { + let module = do_typecheck( + r" test f (x:xs) = f x : test f xs test _ [] = [] -"); - let a = Type::new_var(intern("a")); - let b = Type::new_var(intern("b")); - let test = function_type_(function_type_(a.clone(), b.clone()), function_type_(list_type(a), list_type(b))); - assert_eq!(module.bindings[0].typ.value, test); -} - -#[test] -fn guards() { - let module = do_typecheck(r" +", + ); + let a: Type<_> = "a".into(); + let b: Type<_> = "b".into(); + let test = function_type_( + function_type_(a.clone(), b.clone()), + function_type_(list_type(a), list_type(b)), + ); + assert_eq!(module.bindings[0].typ.value, test); + } + + #[test] + fn guards() { + let module = do_typecheck( + r" data Bool = True | False if_ p x y | p = x | True = y -"); - let var = Type::new_var(intern("a")); - let test = function_type_(bool_type() - , function_type_(var.clone() - , function_type_(var.clone(), - var.clone()))); - assert_eq!(module.bindings[0].typ.value, test); -} - -#[test] -fn typedeclaration_on_expression() { - let module = do_typecheck(r" +", + ); + let var: Type<_> = "a".into(); + let test = function_type_( + bool_type(), + function_type_(var.clone(), function_type_(var.clone(), var.clone())), + ); + assert_eq!(module.bindings[0].typ.value, test); + } + + #[test] + fn typedeclaration_on_expression() { + let module = + do_typecheck( + r" test = [1,2,3 :: Int] -"); - assert_eq!(module.bindings[0].typ.value, list_type(int_type())); -} +", + ); + assert_eq!(module.bindings[0].typ.value, list_type(int_type())); + } -#[test] -fn deriving() { - typecheck_string( -r"import Prelude + #[test] + fn deriving() { + typecheck_string( + r"import Prelude data Test = Test Int deriving(Eq) data Test2 a = J a | N deriving(Eq) -test x = Test 2 == Test 1 || J x == N") - .unwrap(); -} +test x = Test 2 == Test 1 || J x == N", + ) + .unwrap(); + } -#[test] -fn instance_constraints_propagate() { - let modules = typecheck_string( -r" + #[test] + fn instance_constraints_propagate() { + let modules = typecheck_string( + r" import Prelude test x y = [x] == [y] -") - .unwrap(); - let module = modules.last().unwrap(); - let a = Type::new_var(intern("a")); - let cs = vec![Constraint { class: intern("Eq"), variables: vec![a.var().clone()] } ]; - let typ = qualified(cs, function_type_(a.clone(), function_type_(a.clone(), bool_type()))); - assert_eq!(un_name(module.bindings[0].typ.clone()), typ); -} - -#[test] -fn newtype() { - let modules = typecheck_string( -r" +", + ) + .unwrap(); + let module = modules.last().unwrap(); + let a: Type<_> = "a".into(); + let cs = vec![Constraint { + class: intern("Eq"), + variables: vec![a.var().clone()], + }]; + let typ = qualified( + cs, + function_type_(a.clone(), function_type_(a.clone(), bool_type())), + ); + assert_eq!(un_name(module.bindings[0].typ.clone()), typ); + } + + #[test] + fn newtype() { + let modules = + typecheck_string( + r" import Prelude newtype Even = Even Int @@ -2207,75 +2618,85 @@ makeEven i | i `div` 2 /= (i - 1) `div` 2 = Even i | otherwise = undefined -" -).unwrap(); - let module = modules.last().unwrap(); - assert_eq!(un_name(module.bindings[0].typ.clone()), qualified(Vec::new(), function_type_(int_type(), Type::new_op(intern("Even"), Vec::new())))); -} - - -#[test] -#[should_panic] -fn typedeclaration_to_general() { - do_typecheck(r" +", + ) + .unwrap(); + let module = modules.last().unwrap(); + assert_eq!( + un_name(module.bindings[0].typ.clone()), + qualified( + vec![], + function_type_(int_type(), Type::new_op(intern("Even"), vec![])) + ) + ); + } + + #[test] + #[should_panic] + fn typedeclaration_to_general() { + do_typecheck( + r" test x = primIntAdd 2 x :: Num a => a -"); -} - -#[test] -#[should_panic] -fn do_expr_wrong_monad() { - - let prelude = { - let path = &Path::new("Prelude.hs"); - let mut contents = ::std::string::String::new(); - File::open(path).and_then(|mut f| f.read_to_string(&mut contents)).unwrap(); - do_typecheck(contents.as_ref()) - }; +", + ); + } + + #[test] + #[should_panic] + fn do_expr_wrong_monad() { + let prelude = { + let path = &Path::new("Prelude.hs"); + let mut contents = ::std::string::String::new(); + File::open(path) + .and_then(|mut f| f.read_to_string(&mut contents)) + .unwrap(); + do_typecheck(contents.as_ref()) + }; - let file = -r" + let file = r" test x = do putStrLn x reverse [primIntAdd 0 0, 1, 2]"; - do_typecheck_with(file, &[&prelude as &dyn DataTypes]); -} + do_typecheck_with(file, &[&prelude as &dyn DataTypes]); + } -#[test] -#[should_panic] -fn wrong_type() { - do_typecheck(r"test = primIntAdd 2 []"); -} + #[test] + #[should_panic] + fn wrong_type() { + do_typecheck(r"test = primIntAdd 2 []"); + } -#[test] -#[should_panic] -fn argument_count_error() { - do_typecheck("test = primIntAdd 2 2 3"); -} -#[test] -#[should_panic] -fn case_alternative_error() { - do_typecheck( -r" + #[test] + #[should_panic] + fn argument_count_error() { + do_typecheck("test = primIntAdd 2 2 3"); + } + #[test] + #[should_panic] + fn case_alternative_error() { + do_typecheck( + r" test = case [primIntAdd 1 2] of [] -> primIntAdd 0 1 - 2 -> 1"); -} + 2 -> 1", + ); + } -#[test] -#[should_panic] -fn type_declaration_error() { - do_typecheck( -r" + #[test] + #[should_panic] + fn type_declaration_error() { + do_typecheck( + r" test :: [Int] -> Int -> Int -test x y = primIntAdd x y"); -} +test x y = primIntAdd x y", + ); + } -#[test] -#[should_panic] -fn all_constraints_match() { - typecheck_string( -r" + #[test] + #[should_panic] + fn all_constraints_match() { + typecheck_string( + r" import Prelude class Test a where @@ -2286,51 +2707,55 @@ instance (Eq a, Test a) => Test (Maybe a) where test :: Test a => a -> a test x = test x -test2 = test (Just True)") - .unwrap(); -} +test2 = test (Just True)", + ) + .unwrap(); + } -#[test] -#[should_panic] -fn where_binding() { - typecheck_string( -r" + #[test] + #[should_panic] + fn where_binding() { + typecheck_string( + r" test = case 1 :: Int of 2 -> [] x -> y where y = x 1 -") +", + ) .unwrap(); -} + } -#[test] -#[should_panic] -fn newtype_wrong_arg() { - typecheck_string( -r" + #[test] + #[should_panic] + fn newtype_wrong_arg() { + typecheck_string( + r" import Prelude newtype IntPair a = IntPair (a, Int) test = IntPair (True, False) -" -).unwrap(); -} - -#[bench] -fn bench_prelude(b: &mut Bencher) { - let path = &Path::new("Prelude.hs"); - let mut contents = ::std::string::String::new(); - File::open(path).and_then(|mut f| f.read_to_string(&mut contents)).unwrap(); - let mut parser = Parser::new(contents.chars()); - let module = rename_module(parser.module().unwrap()); - - b.iter(|| { - let mut env = TypeEnvironment::new(); - let mut m = module.clone(); - env.typecheck_module_(&mut m); - }); -} +", + ) + .unwrap(); + } + #[bench] + fn bench_prelude(b: &mut Bencher) { + let path = &Path::new("Prelude.hs"); + let mut contents = ::std::string::String::new(); + File::open(path) + .and_then(|mut f| f.read_to_string(&mut contents)) + .unwrap(); + let mut parser = Parser::new(contents.chars()); + let module = rename_module(parser.module().unwrap()); + + b.iter(|| { + let mut env = TypeEnvironment::new(); + let mut m = module.clone(); + env.typecheck_module_(&mut m); + }); + } } diff --git a/src/types.rs b/src/types.rs index e84eae6..c3588f9 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,17 +1,26 @@ -use std::collections::HashMap; -use std::default::Default; -use std::fmt; -use std::iter; -use crate::interner::{InternedStr, intern}; +use { + crate::interner::{ + intern, + InternedStr, + }, + std::{ + collections::HashMap, + default::Default, + fmt, + iter, + }, +}; #[derive(Clone, Debug, Default, Eq, Hash)] pub struct TypeConstructor { - pub name : Ident, - pub kind : Kind + pub name: Ident, + pub kind: Kind, } -impl PartialEq> for TypeConstructor - where Id: PartialEq { +impl PartialEq> for TypeConstructor +where + Id: PartialEq, +{ fn eq(&self, other: &TypeConstructor) -> bool { self.name == other.name && self.kind == other.kind } @@ -20,66 +29,92 @@ impl PartialEq> for TypeConstructor pub type VarId = InternedStr; #[derive(Clone, Debug, PartialEq, Eq, Default)] pub struct TypeVariable { - pub id : InternedStr, - pub kind : Kind, - pub age: isize + pub id: InternedStr, + pub kind: Kind, + pub age: isize, } #[derive(Clone, Debug, Eq, Hash)] pub enum Type { Variable(TypeVariable), Constructor(TypeConstructor), - Application(Box>, Box>), - Generic(TypeVariable) + Application(Box, Box), + Generic(TypeVariable), } + #[derive(Clone, Debug, Default, Hash)] pub struct Qualified { pub constraints: Vec>, - pub value: T + pub value: T, } -pub fn qualified(constraints: Vec>, typ: Type) -> Qualified, Ident> { - Qualified { constraints: constraints, value: typ } + +pub fn qualified( + constraints: Vec>, + typ: Type, +) -> Qualified, Ident> { + Qualified { + constraints, + value: typ, + } +} + +impl> From<&str> for Type { + fn from(value: &str) -> Self { + Self::new_var(value.into()) + } } impl TypeVariable { - pub fn new(id : VarId) -> TypeVariable { - TypeVariable::new_var_kind(id, Kind::Star) + pub fn new(id: VarId) -> Self { + Self::new_var_kind(id, Kind::Star) } - pub fn new_var_kind(id : VarId, kind: Kind) -> TypeVariable { - TypeVariable { id : id, kind: kind, age: 0 } + pub fn new_var_kind(id: VarId, kind: Kind) -> Self { + Self { id, kind, age: 0 } } } -impl > Type { - +impl> Type { ///Creates a new type variable with the specified id - pub fn new_var(id : VarId) -> Type { - Type::new_var_kind(id, Kind::Star) + pub fn new_var(id: VarId) -> Self { + Self::new_var_kind(id, Kind::Star) } ///Creates a new type which is a type variable which takes a number of types as arguments ///Gives the typevariable the correct kind arity. - pub fn new_var_args(id: VarId, types : Vec>) -> Type { - Type::new_type_kind(Type::Variable(TypeVariable { id : id, kind: Kind::Star, age: 0 }), types) + pub fn new_var_args(id: VarId, types: Vec) -> Self { + Self::new_type_kind( + Self::Variable(TypeVariable { + id, + kind: Kind::Star, + age: 0, + }), + types, + ) } ///Creates a new type variable with the specified kind - pub fn new_var_kind(id : VarId, kind: Kind) -> Type { - Type::Variable(TypeVariable::new_var_kind(id, kind)) + pub fn new_var_kind(id: VarId, kind: Kind) -> Self { + Self::Variable(TypeVariable::new_var_kind(id, kind)) } ///Creates a new type constructor with the specified argument and kind - pub fn new_op(name : Id, types : Vec>) -> Type { - Type::new_type_kind(Type::Constructor(TypeConstructor { name : name, kind: Kind::Star }), types) + pub fn new_op(name: Id, types: Vec) -> Self { + Self::new_type_kind( + Self::Constructor(TypeConstructor { + name, + kind: Kind::Star, + }), + types, + ) } ///Creates a new type constructor applied to the types and with a specific kind - pub fn new_op_kind(name : Id, types : Vec>, kind: Kind) -> Type { - let mut result = Type::Constructor(TypeConstructor { name : name, kind: kind }); + pub fn new_op_kind(name: Id, types: Vec, kind: Kind) -> Self { + let mut result = Type::Constructor(TypeConstructor { name, kind }); for typ in types.into_iter() { - result = Type::Application(Box::new(result), Box::new(typ)); + result = Type::Application(result.into(), typ.into()); } result } - fn new_type_kind(mut result: Type, types: Vec>) -> Type { + fn new_type_kind(mut result: Self, types: Vec) -> Self { *result.mut_kind() = Kind::new(types.len() as isize + 1); for typ in types.into_iter() { - result = Type::Application(Box::new(result), Box::new(typ)); + result = Type::Application(result.into(), typ.into()); } result } @@ -87,8 +122,8 @@ impl > Type { ///Returns a reference to the type variable or fails if it is not a variable pub fn var(&self) -> &TypeVariable { match self { - &Type::Variable(ref var) => var, - _ => panic!("Tried to unwrap {} as a TypeVariable", self) + &Self::Variable(ref var) => var, + _ => panic!("Tried to unwrap {} as a TypeVariable", self), } } @@ -96,25 +131,25 @@ impl > Type { #[allow(dead_code)] pub fn ctor(&self) -> &TypeConstructor { match self { - &Type::Constructor(ref op) => op, - _ => panic!("Tried to unwrap {} as a TypeConstructor", self) + &Self::Constructor(ref op) => op, + _ => panic!("Tried to unwrap {} as a TypeConstructor", self), } } ///Returns a reference to the the type function or fails if it is not an application #[allow(dead_code)] - pub fn appl(&self) -> &Type { + pub fn appl(&self) -> &Self { match self { - &Type::Application(ref lhs, _) => &**lhs, - _ => panic!("Error: Tried to unwrap {} as TypeApplication", self) + &Self::Application(ref lhs, _) => lhs, + _ => panic!("Error: Tried to unwrap {} as TypeApplication", self), } } #[allow(dead_code)] ///Returns a reference to the the type argument or fails if it is not an application - pub fn appr(&self) -> &Type { + pub fn appr(&self) -> &Self { match self { - &Type::Application(_, ref rhs) => &**rhs, - _ => panic!("Error: Tried to unwrap TypeApplication") + &Self::Application(_, ref rhs) => rhs, + _ => panic!("Error: Tried to unwrap TypeApplication"), } } @@ -122,44 +157,56 @@ impl > Type { ///Fails only if the type is a type application with an invalid kind pub fn kind(&self) -> &Kind { match self { - &Type::Variable(ref v) => &v.kind, - &Type::Constructor(ref v) => &v.kind, - &Type::Application(ref lhs, _) => + &Self::Variable(ref v) => &v.kind, + &Self::Constructor(ref v) => &v.kind, + &Self::Application(ref lhs, _) => { match lhs.kind() { - &Kind::Function(_, ref kind) => &**kind, - _ => panic!("Type application must have a kind of Kind::Function, {}", self) - }, - &Type::Generic(ref v) => &v.kind + &Kind::Function(_, ref kind) => kind, + _ => panic!( + "Type application must have a kind of Kind::Function, {}", + self + ), + } + } + &Self::Generic(ref v) => &v.kind, } } ///Returns a mutable reference to the types kind pub fn mut_kind(&mut self) -> &mut Kind { match *self { - Type::Variable(ref mut v) => &mut v.kind, - Type::Constructor(ref mut v) => &mut v.kind, - Type::Application(ref mut lhs, _) => - match *lhs.mut_kind() { - Kind::Function(_, ref mut kind) => &mut **kind, - _ => panic!("Type application must have a kind of Kind::Function") - }, - Type::Generic(ref mut v) => &mut v.kind + Self::Variable(ref mut v) => &mut v.kind, + Self::Constructor(ref mut v) => &mut v.kind, + Self::Application(ref mut lhs, _) => match *lhs.mut_kind() { + Kind::Function(_, ref mut kind) => kind, + _ => panic!("Type application must have a kind of Kind::Function"), + }, + Self::Generic(ref mut v) => &mut v.kind, } } } -impl Type { +impl Type { pub fn map(self, mut f: F) -> Type - where F: FnMut(Id) -> Id2 { + where + F: FnMut(Id) -> Id2, + { self.map_(&mut f) } fn map_(self, f: &mut F) -> Type - where F: FnMut(Id) -> Id2 { + where + F: FnMut(Id) -> Id2, + { match self { - Type::Variable(v) => Type::Variable(v), - Type::Constructor(TypeConstructor { name, kind }) => { - Type::Constructor(TypeConstructor { name: f(name), kind: kind }) + Self::Variable(v) => Type::Variable(v), + Self::Constructor(TypeConstructor { name, kind }) => { + Type::Constructor(TypeConstructor { + name: f(name), + kind, + }) } - Type::Application(lhs, rhs) => Type::Application(Box::new(lhs.map_(f)), Box::new(rhs.map_(f))), - Type::Generic(v) => Type::Generic(v) + Self::Application(lhs, rhs) => { + Type::Application(lhs.map_(f).into(), rhs.map_(f).into()) + } + Self::Generic(v) => Type::Generic(v), } } } @@ -175,7 +222,8 @@ impl ::std::hash::Hash for TypeVariable { ///Constructs a string which holds the name of an n-tuple pub fn tuple_name(n: usize) -> String { let commas = if n == 0 { 0 } else { n - 1 }; - Some('(').into_iter() + Some('(') + .into_iter() .chain(iter::repeat(',').take(commas)) .chain(Some(')').into_iter()) .collect() @@ -183,7 +231,7 @@ pub fn tuple_name(n: usize) -> String { ///Returns the type of an n-tuple constructor as well as the name of the tuple pub fn tuple_type(n: usize) -> (String, Type) { - let mut var_list = Vec::new(); + let mut var_list = vec![]; assert!(n < 26); for i in 0..n { let c = (('a' as u8) + i as u8) as char; @@ -194,7 +242,10 @@ pub fn tuple_type(n: usize) -> (String, Type) { let mut typ = Type::new_op(intern(&ident), var_list); for i in (0..n).rev() { let c = (('a' as u8) + i as u8) as char; - typ = function_type_(Type::Generic(TypeVariable::new(intern(&c.to_string()))), typ); + typ = function_type_( + Type::Generic(TypeVariable::new(intern(&c.to_string()))), + typ, + ); } (ident, typ) } @@ -230,7 +281,7 @@ pub fn function_type(arg: &Type, result: &Type) -> Type { } ///Creates a function type -pub fn function_type_(func : Type, arg : Type) -> Type { +pub fn function_type_(func: Type, arg: Type) -> Type { Type::new_op(intern("->"), vec![func, arg]) } @@ -246,43 +297,38 @@ pub fn unit() -> Type { #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct Constraint { - pub class : Ident, - pub variables : Vec + pub class: Ident, + pub variables: Vec, } -#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Debug, PartialEq, Eq, Hash, Default)] pub enum Kind { - Function(Box, Box), - Star + Function(Box, Box), + #[default] + Star, } impl fmt::Display for Kind { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - &Kind::Star => write!(f, "*"), - &Kind::Function(ref lhs, ref rhs) => write!(f, "({} -> {})", *lhs, *rhs) + &Self::Star => write!(f, "*"), + &Self::Function(ref lhs, ref rhs) => write!(f, "({} -> {})", *lhs, *rhs), } } } impl Kind { - pub fn new(v: isize) -> Kind { - let mut kind = Kind::Star.clone(); + pub fn new(v: isize) -> Self { + let mut kind = Self::Star.clone(); for _ in 1..v { - kind = Kind::Function(Box::new(Kind::Star), Box::new(kind)); + kind = Self::Function(Self::Star.into(), kind.into()); } kind } } -impl Default for Kind { - fn default() -> Kind { - Kind::Star - } -} - -impl Default for Type { - fn default() -> Type { - Type::Variable(TypeVariable::new(intern("a"))) +impl Default for Type { + fn default() -> Self { + Self::Variable(TypeVariable::new("a".into())) } } impl fmt::Display for TypeVariable { @@ -290,25 +336,24 @@ impl fmt::Display for TypeVariable { write!(f, "{}", self.id) } } -impl fmt::Display for TypeConstructor { +impl fmt::Display for TypeConstructor { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.name) } } -impl > fmt::Display for Qualified { +impl> fmt::Display for Qualified { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if self.constraints.len() != 0 { + if !self.constraints.is_empty() { write!(f, "(")?; } for constraint in &self.constraints { write!(f, "{}, ", constraint)?; } - if self.constraints.len() != 0 { - write!(f, ") => {}" , self.value) - } - else { - write!(f, "{}" , self.value) + if !self.constraints.is_empty() { + write!(f, ") => {}", self.value) + } else { + write!(f, "{}", self.value) } } } @@ -324,69 +369,76 @@ struct Prec<'a, Id: 'a>(Prec_, &'a Type); ///If the type is a function it returns the type of the argument and the result type, ///otherwise it returns None -pub fn try_get_function<'a, Id: AsRef>(typ: &'a Type) -> Option<(&'a Type, &'a Type)> { - match *typ { - Type::Application(ref xx, ref result) => { - match **xx { - Type::Application(ref xx, ref arg) => { - match **xx { - Type::Constructor(ref op) if "->" == op.name.as_ref() => { - Some((&**arg, &**result)) - } - _ => None - } - } - _ => None - } - } - _ => None +pub fn try_get_function<'a, Id: AsRef>( + typ: &'a Type, +) -> Option<(&'a Type, &'a Type)> { + let Type::Application(ref xx, ref result) = typ else { + return None; + }; + + let Type::Application(ref xx, ref arg) = **xx else { + return None; + }; + + let Type::Constructor(ref op) = **xx else { + return None; + }; + + if op.name.as_ref() != "->" { + return None; } + + Some((arg, result)) } -impl <'a, Id: fmt::Display + AsRef> fmt::Display for Prec<'a, Id> { +impl<'a, Id: fmt::Display + AsRef> fmt::Display for Prec<'a, Id> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let Prec(p, t) = *self; + let Self(p, t) = *self; match *t { Type::Variable(ref var) => write!(f, "{}", *var), Type::Constructor(ref op) => write!(f, "{}", *op), Type::Generic(ref var) => write!(f, "\\#{}", *var), - Type::Application(ref lhs, ref rhs) => { - match try_get_function(t) { - Some((arg, result)) => { - if p >= Prec_::Function { - write!(f, "({} -> {})", *arg, result) - } - else { - write!(f, "{} -> {}", Prec(Prec_::Function, arg), result) - } + Type::Application(ref lhs, ref rhs) => match try_get_function(t) { + Some((arg, result)) => { + if p >= Prec_::Function { + write!(f, "({} -> {})", *arg, result) + } else { + write!(f, "{} -> {}", Prec(Prec_::Function, arg), result) + } + } + None => match **lhs { + Type::Constructor(ref op) if "[]" == op.name.as_ref() => { + write!(f, "[{}]", rhs) } - None => { - match **lhs { - Type::Constructor(ref op) if "[]" == op.name.as_ref() => { - write!(f, "[{}]", rhs) - } - _ => { - if p >= Prec_::Constructor { - write!(f, "({} {})", Prec(Prec_::Function, &**lhs), Prec(Prec_::Constructor, &**rhs)) - } - else { - write!(f, "{} {}", Prec(Prec_::Function, &**lhs), Prec(Prec_::Constructor, &**rhs)) - } - } + _ => { + if p >= Prec_::Constructor { + write!( + f, + "({} {})", + Prec(Prec_::Function, lhs), + Prec(Prec_::Constructor, rhs) + ) + } else { + write!( + f, + "{} {}", + Prec(Prec_::Function, lhs), + Prec(Prec_::Constructor, rhs) + ) } } - } - } + }, + }, } } } -impl > fmt::Display for Type { +impl> fmt::Display for Type { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", Prec(Prec_::Top, self)) } } -impl fmt::Display for Constraint { +impl fmt::Display for Constraint { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.class)?; for var in self.variables.iter() { @@ -395,40 +447,51 @@ impl fmt::Display for Constraint { Ok(()) } } -fn type_eq<'a, Id, Id2>(mapping: &mut HashMap<&'a TypeVariable, &'a TypeVariable>, lhs: &'a Type, rhs: &'a Type) -> bool - where Id: PartialEq { +fn type_eq<'a, Id, Id2>( + mapping: &mut HashMap<&'a TypeVariable, &'a TypeVariable>, + lhs: &'a Type, + rhs: &'a Type, +) -> bool +where + Id: PartialEq, +{ match (lhs, rhs) { (&Type::Constructor(ref l), &Type::Constructor(ref r)) => l.name == r.name, (&Type::Variable(ref r), &Type::Variable(ref l)) => var_eq(mapping, r, l), (&Type::Application(ref lhs1, ref rhs1), &Type::Application(ref lhs2, ref rhs2)) => { - type_eq(mapping, &**lhs1, &**lhs2) && type_eq(mapping, &**rhs1, &**rhs2) + type_eq(mapping, lhs1, lhs2) && type_eq(mapping, rhs1, rhs2) } - _ => false + _ => false, } } -fn var_eq<'a>(mapping: &mut HashMap<&'a TypeVariable, &'a TypeVariable>, l: &'a TypeVariable, r: &'a TypeVariable) -> bool { +fn var_eq<'a>( + mapping: &mut HashMap<&'a TypeVariable, &'a TypeVariable>, + l: &'a TypeVariable, + r: &'a TypeVariable, +) -> bool { match mapping.get(&l) { Some(x) => return x.id == r.id, - None => () + None => (), } mapping.insert(l, r); true } -impl PartialEq for Qualified, U> { +impl PartialEq for Qualified, U> { fn eq(&self, other: &Qualified, U>) -> bool { let mut mapping = HashMap::new(); - self.constraints.iter() - .zip(other.constraints.iter()) - .all(|(l, r)| l.class == r.class && var_eq(&mut mapping, &l.variables[0], &r.variables[0])) - && type_eq(&mut mapping, &self.value, &other.value) + self.constraints.iter().zip(other.constraints.iter()).all( + |(l, r)| l.class == r.class && var_eq(&mut mapping, &l.variables[0], &r.variables[0]) + ) && type_eq(&mut mapping, &self.value, &other.value) } } -impl Eq for Qualified, U> { } +impl Eq for Qualified, U> {} -impl PartialEq> for Type - where Id: PartialEq { +impl PartialEq> for Type +where + Id: PartialEq, +{ ///Compares two types, treating two type variables as equal as long as they always and only appear at the same place ///a -> b == c -> d ///a -> b != c -> c @@ -440,7 +503,7 @@ impl PartialEq> for Type pub fn extract_applied_type(typ: &Type) -> &Type { match *typ { - Type::Application(ref lhs, _) => extract_applied_type(&**lhs), - _ => typ + Type::Application(ref lhs, _) => extract_applied_type(lhs), + _ => typ, } } diff --git a/src/vm.rs b/src/vm.rs index 403d080..96a591e 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -1,34 +1,50 @@ -use std::fmt; -use std::rc::Rc; -use std::cell::{Ref, RefMut, RefCell}; -use std::path::Path; -use std::io; -use std::io::Read; -use std::fs::File; -use std::error::Error; -use std::num::Wrapping; -use crate::typecheck::TypeEnvironment; -use crate::compiler::*; -use crate::parser::Parser; -use crate::core::translate::translate_module; -use crate::lambda_lift::do_lambda_lift; -use crate::renamer::rename_module; -use crate::vm::primitive::{BuiltinFun, get_builtin}; -use crate::interner::*; +use { + crate::{ + compiler::*, + core::translate::translate_module, + interner::*, + lambda_lift::do_lambda_lift, + parser::Parser, + renamer::rename_module, + typecheck::TypeEnvironment, + vm::primitive::{ + get_builtin, + BuiltinFun, + }, + }, + std::{ + cell::{ + Ref, + RefCell, + RefMut, + }, + error::Error, + fmt, + fs::File, + io::{ + self, + Read, + }, + num::Wrapping, + path::Path, + rc::Rc, + }, +}; use self::Node_::*; #[derive(Clone)] pub struct InstanceDictionary { - entries: Vec> + entries: Vec>, } #[derive(Clone)] enum DictionaryEntry { Function(usize), - App(usize, InstanceDictionary) + App(usize, InstanceDictionary), } +#[derive(Clone)] pub enum Node_<'a> { Application(Node<'a>, Node<'a>), Int(isize), @@ -38,47 +54,34 @@ pub enum Node_<'a> { Indirection(Node<'a>), Constructor(u16, Vec>), Dictionary(InstanceDictionary), - BuiltinFunction(usize, BuiltinFun) -} -impl <'a> Clone for Node_<'a> { - fn clone(&self) -> Node_<'a> { - match self { - &Application(ref func, ref arg) => Application(func.clone(), arg.clone()), - &Int(i) => Int(i), - &Float(i) => Float(i), - &Char(c) => Char(c), - &Combinator(sc) => Combinator(sc), - &Indirection(ref n) => Indirection(n.clone()), - &Constructor(ref tag, ref args) => Constructor(tag.clone(), args.clone()), - &Dictionary(ref dict) => Dictionary(dict.clone()), - &BuiltinFunction(arity, f) => BuiltinFunction(arity, f) - } - } + BuiltinFunction(usize, BuiltinFun), } #[derive(Clone)] pub struct Node<'a> { - node: Rc>> + node: Rc>>, } -impl <'a> Node<'a> { +impl<'a> Node<'a> { ///Creates a new node - fn new(n : Node_<'a>) -> Node<'a> { - Node { node: Rc::new(RefCell::new(n)) } + fn new(n: Node_<'a>) -> Self { + Self { + node: Rc::new(RefCell::new(n)), + } } fn borrow<'b>(&'b self) -> Ref<'b, Node_<'a>> { - (*self.node).borrow() + self.node.borrow() } fn borrow_mut<'b>(&'b self) -> RefMut<'b, Node_<'a>> { - (*self.node).borrow_mut() + self.node.borrow_mut() } } -impl <'a> fmt::Debug for Node<'a> { +impl<'a> fmt::Debug for Node<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{:?}", *self.borrow()) } } -impl <'a> fmt::Debug for Node_<'a> { +impl<'a> fmt::Debug for Node_<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { &Application(ref func, ref arg) => write!(f, "({:?} {:?})", *func, *arg), @@ -89,18 +92,23 @@ impl <'a> fmt::Debug for Node_<'a> { &Indirection(ref n) => write!(f, "(~> {:?})", *n), &Constructor(ref tag, ref args) => { let cons = args; - if cons.len() > 0 { + if !cons.is_empty() { match *cons[0].borrow() { Char(_) => { - fn print_string<'a>(f: &mut fmt::Formatter, cons: &Vec>) -> fmt::Result { + fn print_string<'a>( + f: &mut fmt::Formatter, + cons: &Vec>, + ) -> fmt::Result { if cons.len() >= 2 { match *cons[0].borrow() { - Char(c) => { write!(f, "{:?}", c)?; }, - _ => () + Char(c) => { + write!(f, "{:?}", c)?; + } + _ => (), } match *cons[1].borrow() { Constructor(_, ref args2) => return print_string(f, args2), - _ => () + _ => (), } } Ok(()) @@ -118,8 +126,7 @@ impl <'a> fmt::Debug for Node_<'a> { write!(f, "}}") } } - } - else { + } else { //Print a normal constructor write!(f, "{{{:?}", *tag)?; for arg in args.iter() { @@ -129,14 +136,14 @@ impl <'a> fmt::Debug for Node_<'a> { } } &Dictionary(ref dict) => write!(f, "{:?}", dict), - &BuiltinFunction(..) => write!(f, "") + &BuiltinFunction(..) => write!(f, ""), } } } impl fmt::Debug for InstanceDictionary { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "[")?; - if self.entries.len() > 0 { + if !self.entries.is_empty() { write!(f, "{:?}", *self.entries[0])?; } for entry in self.entries.iter().skip(1) { @@ -148,22 +155,25 @@ impl fmt::Debug for InstanceDictionary { impl fmt::Debug for DictionaryEntry { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - DictionaryEntry::Function(index) => write!(f, "{:?}", index), - DictionaryEntry::App(ref func, ref arg) => write!(f, "({:?} {:?})", *func, *arg) + Self::Function(index) => write!(f, "{:?}", index), + Self::App(ref func, ref arg) => write!(f, "({:?} {:?})", *func, *arg), } } } pub struct VM { ///Vector of all assemblies which are loaded. - assembly : Vec, + assembly: Vec, ///A pair of (assembly_index, function_index). globals: Vec<(usize, usize)>, } -impl <'a> VM { - pub fn new() -> VM { - VM { assembly : Vec::new(), globals: Vec::new() } +impl<'a> VM { + pub fn new() -> Self { + Self { + assembly: vec![], + globals: vec![], + } } ///Adds an assembly to the VM, adding entries to the global table as necessary @@ -182,27 +192,24 @@ impl <'a> VM { ///Evaluates the code into Head Normal Form (HNF) pub fn evaluate(&self, code: &[Instruction], assembly_id: usize) -> Node_ { - let mut stack = Vec::new(); + let mut stack = vec![]; self.execute(&mut stack, code, assembly_id); self.deepseq(stack, assembly_id) } - + ///Evaluates the what is at the top of the stack into HNF fn deepseq(&'a self, mut stack: Vec>, assembly_id: usize) -> Node_<'a> { - static EVALCODE : &'static [Instruction] = &[Instruction::Eval]; + static EVALCODE: &'static [Instruction] = &[Instruction::Eval]; self.execute(&mut stack, EVALCODE, assembly_id); - match *stack[0].borrow() { - Constructor(tag, ref vals) => { - let mut ret = Vec::new(); - for v in vals.iter() { - let s = vec!(v.clone()); - let x = self.deepseq(s, assembly_id); - ret.push(Node::new(x)); - } - Constructor(tag, ret) - } - _ => stack[0].borrow().clone() - } + let Constructor(tag, ref vals) = *stack[0].borrow() else { + return stack[0].borrow().clone(); + }; + Constructor( + tag, + vals.iter() + .map(|v| Node::new(self.deepseq(vec![v.clone()], assembly_id))) + .collect(), + ) } ///Executes a sequence of instructions, leaving the result on the top of the stack @@ -213,48 +220,58 @@ impl <'a> VM { for x in stack.iter() { debug!("{:?}", *x.borrow()); } + + fn constr<'a>(cond: bool) -> Node_<'a> { + Constructor((!cond).into(), vec![]) + } debug!(""); let mut i = Wrapping(0); while i.0 < code.len() { debug!("Executing instruction {:?} : {:?}", i.0, code[i.0]); match code[i.0] { - Add => primitive(stack, |l, r| { l + r }), - Sub => primitive(stack, |l, r| { l - r }), - Multiply => primitive(stack, |l, r| { l * r }), - Divide => primitive(stack, |l, r| { l / r }), - Remainder => primitive(stack, |l, r| { l % r }), - IntEQ => primitive_int(stack, |l, r| { if l == r { Constructor(0, Vec::new()) } else { Constructor(1, Vec::new()) } }), - IntLT => primitive_int(stack, |l, r| { if l < r { Constructor(0, Vec::new()) } else { Constructor(1, Vec::new()) } }), - IntLE => primitive_int(stack, |l, r| { if l <= r { Constructor(0, Vec::new()) } else { Constructor(1, Vec::new()) } }), - IntGT => primitive_int(stack, |l, r| { if l > r { Constructor(0, Vec::new()) } else { Constructor(1, Vec::new()) } }), - IntGE => primitive_int(stack, |l, r| { if l >= r { Constructor(0, Vec::new()) } else { Constructor(1, Vec::new()) } }), - DoubleAdd => primitive_float(stack, |l, r| { Float(l + r) }), - DoubleSub => primitive_float(stack, |l, r| { Float(l - r) }), - DoubleMultiply => primitive_float(stack, |l, r| { Float(l * r) }), - DoubleDivide => primitive_float(stack, |l, r| { Float(l / r) }), - DoubleRemainder => primitive_float(stack, |l, r| { Float(l % r) }), - DoubleEQ => primitive_float(stack, |l, r| { if l == r { Constructor(0, Vec::new()) } else { Constructor(1, Vec::new()) } }), - DoubleLT => primitive_float(stack, |l, r| { if l < r { Constructor(0, Vec::new()) } else { Constructor(1, Vec::new()) } }), - DoubleLE => primitive_float(stack, |l, r| { if l <= r { Constructor(0, Vec::new()) } else { Constructor(1, Vec::new()) } }), - DoubleGT => primitive_float(stack, |l, r| { if l > r { Constructor(0, Vec::new()) } else { Constructor(1, Vec::new()) } }), - DoubleGE => primitive_float(stack, |l, r| { if l >= r { Constructor(0, Vec::new()) } else { Constructor(1, Vec::new()) } }), + Add => primitive(stack, |l, r| l + r), + Sub => primitive(stack, |l, r| l - r), + Multiply => primitive(stack, |l, r| l * r), + Divide => primitive(stack, |l, r| l / r), + Remainder => primitive(stack, |l, r| l % r), + IntEQ => primitive_int(stack, |l, r| constr(l == r)), + IntLT => primitive_int(stack, |l, r| constr(l < r)), + IntLE => primitive_int(stack, |l, r| constr(l <= r)), + IntGT => primitive_int(stack, |l, r| constr(l > r)), + IntGE => primitive_int(stack, |l, r| constr(l >= r)), + DoubleAdd => primitive_float(stack, |l, r| Float(l + r)), + DoubleSub => primitive_float(stack, |l, r| Float(l - r)), + DoubleMultiply => primitive_float(stack, |l, r| Float(l * r)), + DoubleDivide => primitive_float(stack, |l, r| Float(l / r)), + DoubleRemainder => primitive_float(stack, |l, r| Float(l % r)), + DoubleEQ => primitive_float(stack, |l, r| constr(l == r)), + DoubleLT => primitive_float(stack, |l, r| constr(l < r)), + DoubleLE => primitive_float(stack, |l, r| constr(l <= r)), + DoubleGT => primitive_float(stack, |l, r| constr(l > r)), + DoubleGE => primitive_float(stack, |l, r| constr(l >= r)), IntToDouble => { let top = stack.pop().unwrap(); stack.push(match *top.borrow() { Int(i) => Node::new(Float(i as f64)), - _ => panic!("Excpected Int in Int -> Double cast") + _ => panic!("Excpected Int in Int -> Double cast"), }); } DoubleToInt => { let top = stack.pop().unwrap(); stack.push(match *top.borrow() { Float(f) => Node::new(Int(f as isize)), - _ => panic!("Excpected Double in Double -> Int cast") + _ => panic!("Excpected Double in Double -> Int cast"), }); } - PushInt(value) => { stack.push(Node::new(Int(value))); } - PushFloat(value) => { stack.push(Node::new(Float(value))); } - PushChar(value) => { stack.push(Node::new(Char(value))); } + PushInt(value) => { + stack.push(Node::new(Int(value))); + } + PushFloat(value) => { + stack.push(Node::new(Float(value))); + } + PushChar(value) => { + stack.push(Node::new(Char(value))); + } Push(index) => { let x = stack[index].clone(); debug!("Pushed {:?}", *x.borrow()); @@ -280,9 +297,9 @@ impl <'a> VM { stack.push(Node::new(Application(func, arg))); } Eval => { - static UNWINDCODE : &'static [Instruction] = &[Unwind]; + static UNWINDCODE: &'static [Instruction] = &[Unwind]; let old = stack.pop().unwrap(); - let mut new_stack = vec!(old.clone()); + let mut new_stack = vec![old.clone()]; self.execute(&mut new_stack, UNWINDCODE, assembly_id); stack.push(new_stack.pop().unwrap()); debug!("{:?}", stack); @@ -299,23 +316,28 @@ impl <'a> VM { stack[index] = Node::new(Indirection(stack.last().unwrap().clone())); } Unwind => { - fn unwind<'a, F>(i_ptr: &mut Wrapping, arity: usize, stack: &mut Vec>, f: F) - where F: FnOnce(&mut Vec>) -> Node<'a> { + fn unwind<'a, F>( + i_ptr: &mut Wrapping, + arity: usize, + stack: &mut Vec>, + f: F, + ) where + F: FnOnce(&mut Vec>) -> Node<'a>, + { if stack.len() - 1 < arity { while stack.len() > 1 { stack.pop(); } - } - else { + } else { for j in (stack.len() - arity - 1)..(stack.len() - 1) { let temp = match *stack[j].borrow() { Application(_, ref arg) => arg.clone(), - _ => panic!("Expected Application") + _ => panic!("Expected Application"), }; stack[j] = temp; } let value = { - let mut new_stack = Vec::new(); + let mut new_stack = vec![]; for i in 0..arity { let index = stack.len() - i - 2; new_stack.push(stack[index].clone()); @@ -334,7 +356,7 @@ impl <'a> VM { match x { Application(func, _) => { stack.push(func); - i = i - Wrapping(1);//Redo the unwind instruction + i = i - Wrapping(1); //Redo the unwind instruction } Combinator(comb) => { debug!(">>> Call {:?}", comb.name); @@ -344,13 +366,15 @@ impl <'a> VM { }); } BuiltinFunction(arity, func) => { - unwind(&mut i, arity, stack, |new_stack| func(self, new_stack.as_ref())); + unwind(&mut i, arity, stack, |new_stack| { + func(self, new_stack.as_ref()) + }); } Indirection(node) => { *stack.last_mut().unwrap() = node; - i = i - Wrapping(1);//Redo the unwind instruction + i = i - Wrapping(1); //Redo the unwind instruction } - _ => () + _ => (), } } Slide(size) => { @@ -369,11 +393,11 @@ impl <'a> VM { stack.push(field.clone()); } } - _ => panic!("Expected constructor in Split instruction") + _ => panic!("Expected constructor in Split instruction"), } } Pack(tag, arity) => { - let mut args = Vec::new(); + let mut args = vec![]; for _ in 0..arity { args.push(stack.pop().unwrap()); } @@ -383,7 +407,7 @@ impl <'a> VM { match *stack.last().unwrap().borrow() { Constructor(0, _) => (), Constructor(1, _) => i = Wrapping(address - 1), - _ => () + _ => (), } stack.pop(); } @@ -391,14 +415,15 @@ impl <'a> VM { let jumped = match *stack.last().unwrap().borrow() { Constructor(tag, _) => { if jump_tag == tag as usize { - i = i + Wrapping(1);//Skip the jump instruction ie continue to the next test + i = i + Wrapping(1); //Skip the jump instruction ie continue to the next test true - } - else { + } else { false } } - ref x => panic!("Expected constructor when executing CaseJump, got {:?}", *x), + ref x => { + panic!("Expected constructor when executing CaseJump, got {:?}", *x) + } }; if !jumped { stack.pop(); @@ -409,8 +434,13 @@ impl <'a> VM { } PushDictionary(index) => { let assembly = &self.assembly[assembly_id]; - let dict : &[usize] = &*assembly.instance_dictionaries[index]; - let dict = InstanceDictionary { entries: dict.iter().map(|i| Rc::new(DictionaryEntry::Function(*i))).collect() }; + let dict: &[usize] = &*assembly.instance_dictionaries[index]; + let dict = InstanceDictionary { + entries: dict + .iter() + .map(|i| Rc::new(DictionaryEntry::Function(*i))) + .collect(), + }; stack.push(Node::new(Dictionary(dict))); } PushDictionaryMember(index) => { @@ -418,7 +448,7 @@ impl <'a> VM { let x = stack[0].borrow(); let dict = match *x { Dictionary(ref x) => x, - ref x => panic!("Attempted to retrieve {:?} as dictionary", *x) + ref x => panic!("Attempted to retrieve {:?} as dictionary", *x), }; match *dict.entries[index] { DictionaryEntry::Function(gi) => { @@ -428,7 +458,10 @@ impl <'a> VM { DictionaryEntry::App(gi, ref dict) => { let (assembly_index, i) = self.globals[gi]; let sc = &self.assembly[assembly_index].super_combinators[i]; - Application(Node::new(Combinator(sc)), Node::new(Dictionary(dict.clone()))) + Application( + Node::new(Combinator(sc)), + Node::new(Dictionary(dict.clone())), + ) } } }; @@ -438,30 +471,30 @@ impl <'a> VM { let a = stack.pop().unwrap(); let a = a.borrow(); let arg = match *a { - Dictionary(ref d) => { - d - } - _ => panic!() + Dictionary(ref d) => d, + _ => panic!(), }; let func = stack.pop().unwrap(); - let mut new_dict = InstanceDictionary { entries: Vec::new() }; + let mut new_dict = InstanceDictionary { entries: vec![] }; match *func.borrow() { Dictionary(ref d) => { for entry in d.entries.iter() { match **entry { DictionaryEntry::Function(index) => { - new_dict.entries.push(Rc::new(DictionaryEntry::App(index, arg.clone()))); + new_dict.entries.push(Rc::new( + DictionaryEntry::App(index, arg.clone()) + )); } - _ => panic!() + _ => panic!(), } } } - _ => panic!() + _ => panic!(), } stack.push(Node::new(Dictionary(new_dict))); } ConstructDictionary(size) => { - let mut new_dict = InstanceDictionary { entries: Vec::new() }; + let mut new_dict = InstanceDictionary { entries: vec![] }; for _ in 0..size { let temp = stack.pop().unwrap(); let temp = temp.borrow(); @@ -469,18 +502,20 @@ impl <'a> VM { Dictionary(ref d) => { new_dict.entries.extend(d.entries.iter().map(|x| x.clone())); } - ref x => panic!("Unexpected {:?}", x) + ref x => panic!("Unexpected {:?}", x), } } stack.push(Node::new(Dictionary(new_dict))); } PushDictionaryRange(start, size) => { - let mut new_dict = InstanceDictionary { entries: Vec::new() }; + let mut new_dict = InstanceDictionary { entries: vec![] }; match *stack[0].borrow() { Dictionary(ref d) => { - new_dict.entries.extend(d.entries.iter().skip(start).take(size).map(|x| x.clone())); + new_dict + .entries + .extend(d.entries.iter().skip(start).take(size).map(|x| x.clone())); } - _ => panic!() + _ => panic!(), } stack.push(Node::new(Dictionary(new_dict))); } @@ -492,30 +527,44 @@ impl <'a> VM { } } - ///Exucutes a binary primitive instruction taking two integers -fn primitive_int<'a, F>(stack: &mut Vec>, f: F) where F: FnOnce(isize, isize) -> Node_<'a> { +fn primitive_int<'a, F>(stack: &mut Vec>, f: F) +where + F: FnOnce(isize, isize) -> Node_<'a>, +{ let l = stack.pop().unwrap(); let r = stack.pop().unwrap(); let l = l.borrow(); let r = r.borrow(); match (&*l, &*r) { (&Int(lhs), &Int(rhs)) => stack.push(Node::new(f(lhs, rhs))), - (lhs, rhs) => panic!("Expected fully evaluted numbers in primitive instruction\n LHS: {:?}\nRHS: {:?} ", lhs, rhs) + (lhs, rhs) => panic!( + "Expected fully evaluted numbers in primitive instruction\n LHS: {:?}\nRHS: {:?} ", + lhs, rhs + ), } } ///Exucutes a binary primitive instruction taking two doubles -fn primitive_float<'a, F>(stack: &mut Vec>, f: F) where F: FnOnce(f64, f64) -> Node_<'a> { +fn primitive_float<'a, F>(stack: &mut Vec>, f: F) +where + F: FnOnce(f64, f64) -> Node_<'a>, +{ let l = stack.pop().unwrap(); let r = stack.pop().unwrap(); let l = l.borrow(); let r = r.borrow(); match (&*l, &*r) { (&Float(lhs), &Float(rhs)) => stack.push(Node::new(f(lhs, rhs))), - (lhs, rhs) => panic!("Expected fully evaluted numbers in primitive instruction\n LHS: {:?}\nRHS: {:?} ", lhs, rhs) + (lhs, rhs) => panic!( + "Expected fully evaluted numbers in primitive instruction\n LHS: {:?}\nRHS: {:?} ", + lhs, rhs + ), } } -fn primitive(stack: &mut Vec, f: F) where F: FnOnce(isize, isize) -> isize { +fn primitive(stack: &mut Vec, f: F) +where + F: FnOnce(isize, isize) -> isize, +{ primitive_int(stack, move |l, r| Int(f(l, r))) } @@ -524,14 +573,15 @@ pub enum VMResult { Char(char), Int(isize), Double(f64), - Constructor(u16, Vec) + Constructor(u16, Vec), } - // TODO: throw this garbage into the macro below -use crate::parser::ParseError; -use crate::renamer::RenamerError; -use crate::typecheck::TypeError; +use crate::{ + parser::ParseError, + renamer::RenamerError, + typecheck::TypeError, +}; macro_rules! vm_error { ($($pre: ident :: $post: ident),+) => { @@ -545,8 +595,8 @@ macro_rules! vm_error { impl fmt::Display for VMError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - VMError::Io(ref e) => write!(f, "{}", e), - $(VMError::$post(ref e) => write!(f, "{}", e)),+ + Self::Io(ref e) => write!(f, "{}", e), + $(Self::$post(ref e) => write!(f, "{}", e)),+ } } } @@ -573,15 +623,15 @@ macro_rules! vm_error { } vm_error! { parser::ParseError, renamer::RenamerError, typecheck::TypeError } -fn compile_iter>(iterator: T) -> Result { +fn compile_iter>(iterator: T) -> Result { let mut parser = Parser::new(iterator); let module = parser.module().unwrap(); let mut module = rename_module(module).unwrap(); - + let mut typer = TypeEnvironment::new(); typer.typecheck_module(&mut module).unwrap(); let core_module = do_lambda_lift(translate_module(module)); - + let mut compiler = Compiler::new(); Ok(compiler.compile_module(&core_module)) } @@ -598,13 +648,12 @@ pub fn compile_file(filename: &str) -> Result { fn extract_result(node: Node_) -> Option { match node { // TODO: Application result - Constructor(tag, fields) => { - let mut result = Vec::new(); + let mut result = vec![]; for field in fields.iter() { match extract_result((*field.borrow()).clone()) { Some(x) => result.push(x), - None => return None + None => return None, } } @@ -614,7 +663,7 @@ fn extract_result(node: Node_) -> Option { Char(i) => Some(VMResult::Char(i)), Int(i) => Some(VMResult::Int(i)), Float(i) => Some(VMResult::Double(i)), - + x => { println!("Can't extract result {:?}", x); None @@ -639,14 +688,18 @@ fn execute_main_module_(assemblies: Vec) -> Result, S for assembly in assemblies.into_iter() { vm.add_assembly(assembly); } - let x = vm.assembly.iter().flat_map(|a| a.super_combinators.iter()).find(|sc| sc.name.name == intern("main")); + let x = vm + .assembly + .iter() + .flat_map(|a| a.super_combinators.iter()) + .find(|sc| sc.name.name == intern("main")); match x { Some(sc) => { assert!(sc.arity == 0); let result = vm.evaluate(&*sc.instructions, sc.assembly_id); Ok(extract_result(result)) } - None => Ok(None) + None => Ok(None), } } @@ -654,12 +707,29 @@ fn execute_main_module_(assemblies: Vec) -> Result, S #[allow(non_snake_case)] mod primitive { - use std::io::Read; - use std::fs::File; - use crate::vm::{VM, Node, Node_}; - use crate::vm::Node_::{Application, Constructor, BuiltinFunction, Char}; - use crate::compiler::Instruction; - use crate::compiler::Instruction::Eval; + use { + crate::{ + compiler::{ + Instruction, + Instruction::Eval, + }, + vm::{ + Node, + Node_::{ + self, + Application, + BuiltinFunction, + Char, + Constructor, + }, + VM, + }, + }, + std::{ + fs::File, + io::Read, + }, + }; pub fn get_builtin(i: usize) -> (usize, BuiltinFun) { match i { @@ -670,21 +740,21 @@ mod primitive { 4 => (2, io_return), 5 => (2, putStrLn), 6 => (2, compare_tags), - _ => panic!("undefined primitive") + _ => panic!("undefined primitive"), } } - pub type BuiltinFun = for <'a> extern "Rust" fn (&'a VM, &[Node<'a>]) -> Node<'a>; + pub type BuiltinFun = for<'a> extern "Rust" fn(&'a VM, &[Node<'a>]) -> Node<'a>; fn error<'a>(vm: &'a VM, stack: &[Node<'a>]) -> Node<'a> { - let mut vec = Vec::new(); + let mut vec = vec![]; vec.push(stack[0].clone()); let node = vm.deepseq(vec, 123); panic!("error: {:?}", node) } fn eval<'a>(vm: &'a VM, node: Node<'a>) -> Node<'a> { - static EVALCODE : &'static [Instruction] = &[Eval]; - let mut temp = Vec::new(); + static EVALCODE: &'static [Instruction] = &[Eval]; + let mut temp = vec![]; temp.push(node); vm.execute(&mut temp, EVALCODE, 123); temp.pop().unwrap() @@ -693,11 +763,11 @@ mod primitive { eval(vm, stack[0].clone()); stack[1].clone() } - fn io_bind<'a>(_vm: &'a VM, stack: &[Node<'a>]) -> Node<'a> { + fn io_bind<'a>(_: &'a VM, stack: &[Node<'a>]) -> Node<'a> { //IO a -> (a -> IO b) -> IO b //IO a = (RealWorld -> (a, RealWorld) //((RealWorld -> (a, RealWorld)) -> (a -> RealWorld -> (b, RealWorld)) -> RealWorld -> (b, RealWorld) - // 0 1 2 + // 0 1 2 //(a, RealWorld) let aw = Node::new(Application(stack[0].clone(), stack[2].clone())); let p = Node::new(BuiltinFunction(2, pass)); @@ -709,39 +779,42 @@ mod primitive { let aw = stack[0].borrow(); let (a, rw) = match *aw { Constructor(_, ref args) => (&args[0], &args[1]), - _ => panic!("pass exepected constructor") + _ => panic!("pass exepected constructor"), }; - Node::new(Application(Node::new(Application(stack[1].clone(), a.clone())), rw.clone())) + Node::new(Application( + Node::new(Application(stack[1].clone(), a.clone())), + rw.clone(), + )) } - fn io_return<'a>(_vm: &'a VM, stack: &[Node<'a>]) -> Node<'a> { + fn io_return<'a>(_: &'a VM, stack: &[Node<'a>]) -> Node<'a> { //a -> RealWorld -> (a, RealWorld) - Node::new(Constructor(0, vec!(stack[0].clone(), stack[1].clone()))) + Node::new(Constructor(0, vec![stack[0].clone(), stack[1].clone()])) } fn readFile<'a>(vm: &'a VM, stack: &[Node<'a>]) -> Node<'a> { - let mut temp = Vec::new(); + let mut temp = vec![]; temp.push(stack[0].clone()); let node_filename = vm.deepseq(temp, 123); let filename = get_string(&node_filename); let mut file = match File::open(&filename) { Ok(f) => f, - Err(err) => panic!("error: readFile -> {:?}", err) + Err(err) => panic!("error: readFile -> {:?}", err), }; let mut s = ::std::string::String::new(); - let (begin, _end) = match file.read_to_string(&mut s) { + let (begin, _) = match file.read_to_string(&mut s) { Ok(_) => create_string(&s), - Err(err) => panic!("error: readFile -> {:?}", err) + Err(err) => panic!("error: readFile -> {:?}", err), }; //Return (String, RealWorld) - Node::new(Constructor(0, vec!(begin, stack[1].clone()))) + Node::new(Constructor(0, vec![begin, stack[1].clone()])) } fn putStrLn<'a>(vm: &'a VM, stack: &[Node<'a>]) -> Node<'a> { - let mut temp = Vec::new(); + let mut temp = vec![]; temp.push(stack[0].clone()); let msg_node = vm.deepseq(temp, 123); let msg = get_string(&msg_node); println!("{:?}", msg); - Node::new(Constructor(0, vec!(Node::new(Constructor(0, vec!())), stack[1].clone()))) + Node::new(Constructor(0, vec![Node::new(Constructor(0, vec![])), stack[1].clone()])) } fn get_string<'a>(node: &Node_<'a>) -> String { fn get_string_<'a>(buffer: &mut String, node: &Node_<'a>) { @@ -750,12 +823,12 @@ mod primitive { if args.len() == 2 { match *args[0].borrow() { Char(c) => buffer.push(c), - _ => panic!("Unevaluated char") + _ => panic!("Unevaluated char"), } get_string_(buffer, &*args[1].borrow()); } } - _ => panic!("Unevaluated list") + _ => panic!("Unevaluated list"), } } let mut buffer = String::new(); @@ -763,17 +836,17 @@ mod primitive { buffer } fn create_string<'a>(s: &str) -> (Node<'a>, Node<'a>) { - let mut node = Node::new(Constructor(0, vec!())); + let mut node = Node::new(Constructor(0, vec![])); let first = node.clone(); for c in s.chars() { let temp = match *node.borrow_mut() { Constructor(ref mut tag, ref mut args) => { *tag = 1; args.push(Node::new(Char(c))); - args.push(Node::new(Constructor(0, Vec::new()))); + args.push(Node::new(Constructor(0, vec![]))); args[1].clone() } - _ => panic!() + _ => panic!(), }; node = temp; } @@ -789,132 +862,146 @@ mod primitive { (&Constructor(lhs, _), &Constructor(rhs, _)) => match lhs.cmp(&rhs) { Ordering::Less => 0, Ordering::Equal => 1, - Ordering::Greater => 2 + Ordering::Greater => 2, }, - (_, _) => 1//EQ + (_, _) => 1, //EQ }; - Node::new(Constructor(tag, Vec::new())) + Node::new(Constructor(tag, vec![])) } } #[cfg(test)] mod tests { -use crate::typecheck::TypeEnvironment; -use crate::compiler::{compile_with_type_env}; -use crate::vm::{VM, compile_file, compile_iter, execute_main_module, execute_main_string, extract_result, VMResult}; -use crate::interner::*; + use crate::{ + compiler::compile_with_type_env, + interner::*, + typecheck::TypeEnvironment, + vm::{ + compile_file, + compile_iter, + execute_main_module, + execute_main_string, + extract_result, + VMResult, + VM, + }, + }; -fn execute_main>(iterator: T) -> Option { - let mut vm = VM::new(); - vm.add_assembly(compile_iter(iterator).unwrap()); - let x = vm.assembly.iter().flat_map(|a| a.super_combinators.iter()).find(|sc| sc.name.name == intern("main")); - match x { - Some(sc) => { + fn execute_main>(iterator: T) -> Option { + let mut vm = VM::new(); + vm.add_assembly(compile_iter(iterator).unwrap()); + let x = vm + .assembly + .iter() + .flat_map(|a| a.super_combinators.iter()) + .find(|sc| sc.name.name == intern("main")); + if let Some(sc) = x { assert!(sc.arity == 0); let result = vm.evaluate(&*sc.instructions, sc.assembly_id); extract_result(result) + } else { + None } - None => None } -} -#[test] -fn test_primitive() -{ - assert_eq!(execute_main("main = primIntAdd 10 5".chars()), Some(VMResult::Int(15))); - assert_eq!(execute_main("main = primIntSubtract 7 (primIntMultiply 2 3)".chars()), Some(VMResult::Int(1))); - assert_eq!(execute_main("main = primIntDivide 10 (primIntRemainder 6 4)".chars()), Some(VMResult::Int(5))); - assert_eq!(execute_main("main = primDoubleDivide 3. 2.".chars()), Some(VMResult::Double(1.5))); - let s = -r"data Bool = True | False + #[test] + fn test_primitive() { + assert_eq!( + execute_main("main = primIntAdd 10 5".chars()), + Some(VMResult::Int(15)) + ); + assert_eq!( + execute_main("main = primIntSubtract 7 (primIntMultiply 2 3)".chars()), + Some(VMResult::Int(1)) + ); + assert_eq!( + execute_main("main = primIntDivide 10 (primIntRemainder 6 4)".chars()), + Some(VMResult::Int(5)) + ); + assert_eq!( + execute_main("main = primDoubleDivide 3. 2.".chars()), + Some(VMResult::Double(1.5)) + ); + let s = r"data Bool = True | False main = primIntLT 1 2"; - assert_eq!(execute_main(s.chars()), Some(VMResult::Constructor(0, Vec::new()))); -} + assert_eq!( + execute_main(s.chars()), + Some(VMResult::Constructor(0, vec![])) + ); + } -#[test] -fn test_function() -{ - let module = -r"mult2 x = primIntMultiply x 2 + #[test] + fn test_function() { + let module = r"mult2 x = primIntMultiply x 2 main = mult2 10"; - assert_eq!(execute_main(module.chars()), Some(VMResult::Int(20))); + assert_eq!(execute_main(module.chars()), Some(VMResult::Int(20))); - let module2 = -r"mult2 x = primIntMultiply x 2 + let module2 = r"mult2 x = primIntMultiply x 2 add x y = primIntAdd y x main = add 3 (mult2 10)"; - assert_eq!(execute_main(module2.chars()), Some(VMResult::Int(23))); -} -#[test] -fn test_case() -{ - let module = -r"mult2 x = primIntMultiply x 2 + assert_eq!(execute_main(module2.chars()), Some(VMResult::Int(23))); + } + #[test] + fn test_case() { + let module = r"mult2 x = primIntMultiply x 2 main = case [mult2 123, 0] of x:xs -> x [] -> 10"; - assert_eq!(execute_main(module.chars()), Some(VMResult::Int(246))); -} + assert_eq!(execute_main(module.chars()), Some(VMResult::Int(246))); + } -#[test] -fn test_nested_case() { - let module = -r"mult2 x = primIntMultiply x 2 + #[test] + fn test_nested_case() { + let module = r"mult2 x = primIntMultiply x 2 main = case [mult2 123, 0] of 246:xs -> primIntAdd 0 246 [] -> 10"; - assert_eq!(execute_main(module.chars()), Some(VMResult::Int(246))); -} + assert_eq!(execute_main(module.chars()), Some(VMResult::Int(246))); + } -#[test] -fn test_nested_case2() { - let module = -r"mult2 x = primIntMultiply x 2 + #[test] + fn test_nested_case2() { + let module = r"mult2 x = primIntMultiply x 2 main = case [mult2 123, 0] of 246:[] -> primIntAdd 0 246 x:xs -> 20 [] -> 10"; - assert_eq!(execute_main(module.chars()), Some(VMResult::Int(20))); -} -#[test] -fn local_function() { - let module = -r"main = + assert_eq!(execute_main(module.chars()), Some(VMResult::Int(20))); + } + #[test] + fn local_function() { + let module = r"main = let f x y = let g x = primIntAdd x y in g (primIntAdd 1 x) in f (primIntAdd 2 0) (primIntAdd 3 0)"; - assert_eq!(execute_main(module.chars()), Some(VMResult::Int(6))); -} + assert_eq!(execute_main(module.chars()), Some(VMResult::Int(6))); + } -#[test] -fn test_data_types() -{ - let module = -r"data Bool = True | False + #[test] + fn test_data_types() { + let module = r"data Bool = True | False test = False main = case test of False -> primIntAdd 0 0 True -> primIntAdd 1 0"; - assert_eq!(execute_main(module.chars()), Some(VMResult::Int(0))); -} + assert_eq!(execute_main(module.chars()), Some(VMResult::Int(0))); + } -#[test] -fn test_typeclasses_known_types() -{ - let module = -r"data Bool = True | False + #[test] + fn test_typeclasses_known_types() { + let module = r"data Bool = True | False class Test a where test :: a -> Int @@ -929,14 +1016,12 @@ instance Test Bool where main = primIntSubtract (test (primIntAdd 5 0)) (test True)"; - assert_eq!(execute_main(module.chars()), Some(VMResult::Int(4))); -} + assert_eq!(execute_main(module.chars()), Some(VMResult::Int(4))); + } -#[test] -fn test_typeclasses_unknown() -{ - let module = -r"data Bool = True | False + #[test] + fn test_typeclasses_unknown() { + let module = r"data Bool = True | False class Test a where test :: a -> Int @@ -952,101 +1037,133 @@ instance Test Bool where testAdd y = primIntAdd (test (primIntAdd 5 0)) (test y) main = testAdd True"; - assert_eq!(execute_main(module.chars()), Some(VMResult::Int(6))); -} - -#[test] -fn test_run_prelude() { - let prelude = compile_file("Prelude.hs").unwrap(); - let assembly = { - let mut type_env = TypeEnvironment::new(); - - compile_with_type_env(&mut type_env, &[&prelude], -r"add x y = primIntAdd x y -main = foldl add 0 [1,2,3,4]").unwrap() - }; + assert_eq!(execute_main(module.chars()), Some(VMResult::Int(6))); + } - let mut vm = VM::new(); - vm.add_assembly(prelude); - vm.add_assembly(assembly); - let x = vm.assembly.iter().flat_map(|a| a.super_combinators.iter()).find(|sc| sc.name.name == intern("main")); - let result = match x { - Some(sc) => { - assert!(sc.arity == 0); - let result = vm.evaluate(&*sc.instructions, sc.assembly_id); - extract_result(result) - } - None => None - }; - assert_eq!(result, Some(VMResult::Int(10))); -} + #[test] + fn test_run_prelude() { + let prelude = compile_file("Prelude.hs").unwrap(); + let assembly = { + let mut type_env = TypeEnvironment::new(); + + compile_with_type_env( + &mut type_env, + &[&prelude], + r"add x y = primIntAdd x y +main = foldl add 0 [1,2,3,4]", + ) + .unwrap() + }; -#[test] -fn instance_super_class() { - let prelude = compile_file("Prelude.hs").unwrap(); + let mut vm = VM::new(); + vm.add_assembly(prelude); + vm.add_assembly(assembly); + let x = vm + .assembly + .iter() + .flat_map(|a| a.super_combinators.iter()) + .find(|sc| sc.name.name == intern("main")); + let result = + match x { + Some(sc) => { + assert!(sc.arity == 0); + let result = vm.evaluate(&*sc.instructions, sc.assembly_id); + extract_result(result) + } + None => None, + }; + assert_eq!(result, Some(VMResult::Int(10))); + } - let assembly = { - let mut type_env = TypeEnvironment::new(); - compile_with_type_env(&mut type_env, &[&prelude], "main = [primIntAdd 0 1,2,3,4] == [1,2,3]").unwrap() - }; + #[test] + fn instance_super_class() { + let prelude = compile_file("Prelude.hs").unwrap(); + + let assembly = { + let mut type_env = TypeEnvironment::new(); + compile_with_type_env( + &mut type_env, + &[&prelude], + "main = [primIntAdd 0 1,2,3,4] == [1,2,3]", + ) + .unwrap() + }; - let mut vm = VM::new(); - vm.add_assembly(prelude); - vm.add_assembly(assembly); - let x = vm.assembly.iter().flat_map(|a| a.super_combinators.iter()).find(|sc| sc.name.name == intern("main")); - let result = match x { - Some(sc) => { - assert!(sc.arity == 0); - let result = vm.evaluate(&*sc.instructions, sc.assembly_id); - extract_result(result) - } - None => None - }; - assert_eq!(result, Some(VMResult::Constructor(1, Vec::new()))); -} + let mut vm = VM::new(); + vm.add_assembly(prelude); + vm.add_assembly(assembly); + let x = vm + .assembly + .iter() + .flat_map(|a| a.super_combinators.iter()) + .find(|sc| sc.name.name == intern("main")); + let result = + match x { + Some(sc) => { + assert!(sc.arity == 0); + let result = vm.evaluate(&*sc.instructions, sc.assembly_id); + extract_result(result) + } + None => None, + }; + assert_eq!(result, Some(VMResult::Constructor(1, vec![]))); + } -#[test] -fn monad_do() { - let prelude = compile_file("Prelude.hs").unwrap(); + #[test] + fn monad_do() { + let prelude = compile_file("Prelude.hs").unwrap(); - let assembly = { - let mut type_env = TypeEnvironment::new(); - compile_with_type_env(&mut type_env, &[&prelude], -" + let assembly = { + let mut type_env = TypeEnvironment::new(); + compile_with_type_env( + &mut type_env, + &[&prelude], + " test :: Maybe Int -> Maybe Int -> Maybe Int test x y = do x1 <- x y return (x1 + 1) -main = test (Just 4) (Just 6)").unwrap() - }; +main = test (Just 4) (Just 6)", + ) + .unwrap() + }; - let mut vm = VM::new(); - vm.add_assembly(prelude); - vm.add_assembly(assembly); - let x = vm.assembly.iter().flat_map(|a| a.super_combinators.iter()).find(|sc| sc.name.name == intern("main")); - let result = match x { - Some(sc) => { - assert!(sc.arity == 0); - let result = vm.evaluate(&*sc.instructions, sc.assembly_id); - extract_result(result) - } - None => None - }; - assert_eq!(result, Some(VMResult::Constructor(0, vec!(VMResult::Int(5))))); -} + let mut vm = VM::new(); + vm.add_assembly(prelude); + vm.add_assembly(assembly); + let x = vm + .assembly + .iter() + .flat_map(|a| a.super_combinators.iter()) + .find(|sc| sc.name.name == intern("main")); + let result = + match x { + Some(sc) => { + assert!(sc.arity == 0); + let result = vm.evaluate(&*sc.instructions, sc.assembly_id); + extract_result(result) + } + None => None, + }; + assert_eq!( + result, + Some(VMResult::Constructor(0, vec!(VMResult::Int(5)))) + ); + } -#[test] -fn import() { - let result = execute_main_module("Test"); - assert_eq!(result, Ok(Some(VMResult::Int(6)))); -} + #[test] + fn import() { + let result = execute_main_module("Test"); + assert_eq!(result, Ok(Some(VMResult::Int(6)))); + } -#[test] -fn pattern_bind() { - let result = execute_main_string( -r" + #[test] + fn pattern_bind() { + let result = + execute_main_string( + r" import Prelude test :: [Bool] -> Bool @@ -1055,14 +1172,15 @@ test (True:y:ys) = y test [] = False main = test [True, True] -") - .unwrap(); - assert_eq!(result, Some(VMResult::Constructor(0, Vec::new()))); -} -#[test] -fn pattern_guards() { - let result = execute_main_string( -r" +", + ) + .unwrap(); + assert_eq!(result, Some(VMResult::Constructor(0, vec![]))); + } + #[test] + fn pattern_guards() { + let result = execute_main_string( + r" import Prelude test :: Int -> [a] -> Int @@ -1074,15 +1192,22 @@ test x _ = x main = (test 2 [], test 100 [], test 100 ['c']) -") - .unwrap(); - assert_eq!(result, Some(VMResult::Constructor(0, vec!(VMResult::Int(2), VMResult::Int(1), VMResult::Int(100))))); -} +", + ) + .unwrap(); + assert_eq!( + result, + Some(VMResult::Constructor( + 0, + vec!(VMResult::Int(2), VMResult::Int(1), VMResult::Int(100)) + )) + ); + } -#[test] -fn pattern_guards_nested() { - let result = execute_main_string( -r" + #[test] + fn pattern_guards_nested() { + let result = execute_main_string( + r" import Prelude test :: Int -> [Int] -> Int @@ -1094,15 +1219,20 @@ test x _ = x main = (test 2 [], test 100 [0], test 100 [0, 123]) -") - .unwrap(); - assert_eq!(result, Some(VMResult::Constructor(0, vec!(VMResult::Int(2), VMResult::Int(1), VMResult::Int(100))))); -} -#[test] -fn test_class_default_function() -{ - let module = -r"data Bool = True | False +", + ) + .unwrap(); + assert_eq!( + result, + Some(VMResult::Constructor( + 0, + vec!(VMResult::Int(2), VMResult::Int(1), VMResult::Int(100)) + )) + ); + } + #[test] + fn test_class_default_function() { + let module = r"data Bool = True | False class Test a where test :: a -> Int @@ -1117,24 +1247,28 @@ instance Test Bool where test2 = 2 main = (test True, test (1 :: Int))"; - assert_eq!(execute_main(module.chars()), Some(VMResult::Constructor(0, vec![VMResult::Int(42), VMResult::Int(1)]))); -} + assert_eq!( + execute_main(module.chars()), + Some(VMResult::Constructor(0, vec![VMResult::Int(42), VMResult::Int(1)])) + ); + } -#[test] -fn use_super_class() { - let result = execute_main_string( -r" + #[test] + fn use_super_class() { + let result = execute_main_string( + r" import Prelude test x y = (x == y) || (x < y) -main = (test (0 :: Int) 2) && not (test (1 :: Int) 0)") +main = (test (0 :: Int) 2) && not (test (1 :: Int) 0)", + ) .unwrap_or_else(|err| panic!("{:?}", err)); - assert_eq!(result, Some(VMResult::Constructor(0, Vec::new()))); -} -#[test] -fn implement_class() { - let result = execute_main_string( -r" + assert_eq!(result, Some(VMResult::Constructor(0, vec![]))); + } + #[test] + fn implement_class() { + let result = execute_main_string( + r" import Prelude data AB = A | B @@ -1145,63 +1279,74 @@ instance Eq AB where test x y = x == y -main = A == B && test A A") +main = A == B && test A A", + ) .unwrap_or_else(|err| panic!("{:?}", err)); - assert_eq!(result, Some(VMResult::Constructor(1, Vec::new()))); -} + assert_eq!(result, Some(VMResult::Constructor(1, vec![]))); + } -#[test] -fn deriving_eq() { - let result = execute_main_string( -r" + #[test] + fn deriving_eq() { + let result = execute_main_string( + r" import Prelude data Test = A Int | B deriving(Eq) main = A 0 == A 2 || A 0 == B -").unwrap(); - assert_eq!(result, Some(VMResult::Constructor(1, Vec::new()))); -} -#[test] -fn deriving_ord() { - let result = execute_main_string( -r" +", + ) + .unwrap(); + assert_eq!(result, Some(VMResult::Constructor(1, vec![]))); + } + #[test] + fn deriving_ord() { + let result = + execute_main_string( + r" import Prelude data Test = A Int | B deriving(Eq, Ord) main = compare (A 0) (A 2) == LT && compare B (A 123) == GT -").unwrap(); - assert_eq!(result, Some(VMResult::Constructor(0, Vec::new()))); -} +", + ) + .unwrap(); + assert_eq!(result, Some(VMResult::Constructor(0, vec![]))); + } -#[test] -fn instance_eq_list() { - let result = execute_main_string( -r" + #[test] + fn instance_eq_list() { + let result = + execute_main_string( + r" import Prelude test x y = x == y main = test [1 :: Int] [3] -").unwrap(); - assert_eq!(result, Some(VMResult::Constructor(1, Vec::new()))); -} -#[test] -fn build_dictionary() { - //Test that the compiler can generate code to build a dictionary at runtime - let result = execute_main_string( -r" +", + ) + .unwrap(); + assert_eq!(result, Some(VMResult::Constructor(1, vec![]))); + } + #[test] + fn build_dictionary() { + //Test that the compiler can generate code to build a dictionary at runtime + let result = execute_main_string( + r" import Prelude test :: Eq a => a -> a -> Bool test x y = [x] == [y] main = test [1 :: Int] [3] -").unwrap(); - assert_eq!(result, Some(VMResult::Constructor(1, Vec::new()))); -} +", + ) + .unwrap(); + assert_eq!(result, Some(VMResult::Constructor(1, vec![]))); + } -#[test] -fn if_else() { - let result = execute_main_string( -r" + #[test] + fn if_else() { + let result = execute_main_string( + r" import Prelude main = let @@ -1209,14 +1354,17 @@ main = let in if x < 0 then x else 1 -").unwrap(); - assert_eq!(result, Some(VMResult::Int(1))); -} +", + ) + .unwrap(); + assert_eq!(result, Some(VMResult::Int(1))); + } -#[test] -fn newtype() { - let result = execute_main_string( -r" + #[test] + fn newtype() { + let result = + execute_main_string( + r" import Prelude newtype Even = Even Int @@ -1226,15 +1374,20 @@ makeEven i | otherwise = Nothing main = makeEven (100 * 3) -").unwrap(); - - assert_eq!(result, Some(VMResult::Constructor(0, vec![VMResult::Int(300)]))); -} +", + ) + .unwrap(); + + assert_eq!( + result, + Some(VMResult::Constructor(0, vec![VMResult::Int(300)])) + ); + } -#[test] -fn where_bindings() { - let result = execute_main_string( -r" + #[test] + fn where_bindings() { + let result = execute_main_string( + r" import Prelude main = case list of @@ -1246,8 +1399,9 @@ main = case list of y = x + 10 where list = [1::Int] -").unwrap(); - assert_eq!(result, Some(VMResult::Int(11))); -} - +", + ) + .unwrap(); + assert_eq!(result, Some(VMResult::Int(11))); + } }