From f95c256c0976d520ad87477aca5d73b9d7aefdb0 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 10:24:27 -0800 Subject: [PATCH 01/76] refactoring --- src/builtins.rs | 2 +- src/compiler.rs | 24 +++++++-------- src/core.rs | 38 +++++++++++------------ src/deriving.rs | 28 ++++++++--------- src/graph.rs | 8 ++--- src/infix.rs | 4 +-- src/interner.rs | 2 +- src/lambda_lift.rs | 12 ++++---- src/lexer.rs | 4 +-- src/parser.rs | 60 ++++++++++++++++++------------------ src/renamer.rs | 6 ++-- src/scoped_map.rs | 6 ++-- src/typecheck.rs | 20 ++++++------ src/types.rs | 2 +- src/vm.rs | 76 +++++++++++++++++++++++----------------------- 15 files changed, 146 insertions(+), 146 deletions(-) diff --git a/src/builtins.rs b/src/builtins.rs index a09f45f..fd9caa5 100644 --- a/src/builtins.rs +++ b/src/builtins.rs @@ -15,7 +15,7 @@ pub fn builtins() -> Vec<(&'static str, Type)> { 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())))), + ("#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..feeb4f0 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -374,22 +374,22 @@ impl <'a> Compiler<'a> { for &(name, instruction) in UNARY_PRIMITIVES.iter() { variables.insert(Name { name: intern(name), uid: 0 }, Var::Primitive(1, instruction)); } - Compiler { instance_dictionaries: Vec::new(), - stack_size : 0, assemblies: Vec::new(), + Compiler { instance_dictionaries: vec![], + stack_size : 0, assemblies: vec![], module: None, variables: variables, - context: Vec::new() + context: vec![] } } 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()); } @@ -426,7 +426,7 @@ impl <'a> Compiler<'a> { debug!("Compiling binding {:?} :: {:?}", bind.name, bind.name.typ); let dict_arg = if bind.name.typ.constraints.len() > 0 { 1 } else { 0 }; 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 { @@ -631,13 +631,13 @@ impl <'a> Compiler<'a> { 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 pattern_end = instructions.len() as isize; @@ -924,7 +924,7 @@ impl <'a> Compiler<'a> { if constraints.len() == 0 { panic!("Error: Attempted to compile dictionary with no constraints at "); } - let mut function_indexes = Vec::new(); + let mut function_indexes = vec![]; self.add_class(constraints, &mut function_indexes); self.instance_dictionaries.push((constraints.to_owned(), function_indexes)); dict_len @@ -1067,7 +1067,7 @@ fn compile_module_(modules: Vec>) -> Result { 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![]), @@ -448,7 +448,7 @@ pub mod translate { 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 { @@ -489,7 +489,7 @@ pub mod translate { 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(); instance.bindings = vec; @@ -514,7 +514,7 @@ pub mod translate { 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() .filter(|c| c.variables[0] != *class_var) @@ -678,12 +678,12 @@ impl <'a> Translator<'a> { } fn translate_bindings(&mut self, bindings: Vec>) -> Vec>> { - let mut result = Vec::new(); - let mut vec: Vec> = Vec::new(); + let mut result = vec![]; + let mut vec: Vec> = vec![]; for bind in bindings.into_iter() { if vec.len() > 0 && vec[0].name != bind.name { result.push(self.translate_matching_groups(vec)); - vec = Vec::new(); + vec = vec![]; } vec.push(bind); } @@ -735,7 +735,7 @@ impl <'a> Translator<'a> { ///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(); + let mut result = vec![]; for (p, id) in arguments.iter().zip(arg_ids.iter()) { self.unwrap_pattern(uid, id.clone(), p.clone(), &mut result); } @@ -746,11 +746,11 @@ impl <'a> Translator<'a> { ///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 mut vec = vec![]; 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)); + 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); @@ -789,7 +789,7 @@ impl <'a> Translator<'a> { .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()); + 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 { @@ -798,7 +798,7 @@ impl <'a> Translator<'a> { } } //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 mut arg_ids = vec![]; let name; { let binding0 = &bindings[0]; @@ -823,7 +823,7 @@ impl <'a> Translator<'a> { where_bindings, .. } = bind; - let where_bindings_binds = where_bindings.map_or(Vec::new(), |bs| self.translate_bindings(bs)); + 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); @@ -835,7 +835,7 @@ impl <'a> Translator<'a> { } } fn translate_equations_(&mut self, equations: Vec<(Vec<(Id, Pattern>)>, Vec>>, module::Match)>) -> Expr> { - let mut eqs: Vec = Vec::new(); + 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))); } @@ -878,7 +878,7 @@ impl <'a> Translator<'a> { return make_let(bindings, self.translate_match((*e).clone())); } if ps.len() == 1 { - let mut alts: Vec>> = Vec::new(); + 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 { @@ -916,9 +916,9 @@ impl <'a> Translator<'a> { } let mut last_index = 0; - let mut vec: Vec = Vec::new(); - let mut alts: Vec>> = Vec::new(); - let mut visited = Vec::new(); + 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; @@ -942,7 +942,7 @@ impl <'a> Translator<'a> { match pattern_test { Some(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]) { diff --git a/src/deriving.rs b/src/deriving.rs index 8bdf204..83a1438 100644 --- a/src/deriving.rs +++ b/src/deriving.rs @@ -10,22 +10,22 @@ pub fn generate_deriving(instances: &mut Vec>>, data: &DataDef 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 }); } "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 @@ -73,7 +73,7 @@ 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(); @@ -111,7 +111,7 @@ impl DerivingGen { _ => 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 @@ -119,10 +119,10 @@ impl DerivingGen { } 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()); + let match_id = Id::new(self.name_supply.anonymous(), Type::new_op(name("Ordering"), vec![]), vec![]); Case(Box::new(cmp), vec![ Alternative { - pattern: Pattern::Constructor(id("EQ", Type::new_op(name("Ordering"), Vec::new())), Vec::new()), + 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) } @@ -146,7 +146,7 @@ impl DerivingGen { Alternative { pattern: pattern_r, expression: expr }, Alternative { pattern: Pattern::WildCard, - expression: Identifier(Id::new(Name { uid: 0, name: intern("False") }, bool_type(), Vec::new())) + expression: Identifier(Id::new(Name { uid: 0, name: intern("False") }, bool_type(), vec![])) } ]); Alternative { pattern: Pattern::Constructor(ctor_id, args_l), expression: inner } @@ -157,13 +157,13 @@ impl DerivingGen { fn id(s: &str, typ: Type) -> Id { - Id::new(Name {name: intern(s), uid: 0 }, typ, Vec::new()) + Id::new(Name {name: intern(s), uid: 0 }, 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()); + 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)), Box::new(lhs))), Box::new(rhs)) } @@ -172,12 +172,12 @@ fn bool_binop(op: &str, lhs: Expr>, rhs: Expr>) -> 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())); + let f = Identifier(Id::new(name(op), typ, vec![])); Apply(Box::new(Apply(Box::new(f), Box::new(lhs))), Box::new(rhs)) } fn true_expr() -> Expr> { - Identifier(Id::new(name("True"), bool_type(), Vec::new())) + Identifier(Id::new(name("True"), bool_type(), vec![])) } struct ArgIterator<'a> { diff --git a/src/graph.rs b/src/graph.rs index b528e53..b184603 100644 --- a/src/graph.rs +++ b/src/graph.rs @@ -33,11 +33,11 @@ pub struct Graph { impl Graph { ///Creates a new graph pub fn new() -> Graph { - Graph { edges: Vec::new(), vertices: Vec::new() } + Graph { 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: value }); VertexIndex(self.vertices.len() - 1) } @@ -66,7 +66,7 @@ impl Graph { ///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: graph, index: 1, stack: vec![], connections: vec![], valid: repeat(0).take(graph.len()).collect(), lowlink: repeat(0).take(graph.len()).collect() }; @@ -109,7 +109,7 @@ impl <'a, T> TarjanComponents<'a, T> { } 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(); diff --git a/src/infix.rs b/src/infix.rs index 3f99e94..3d27844 100644 --- a/src/infix.rs +++ b/src/infix.rs @@ -53,8 +53,8 @@ impl PrecedenceVisitor { let loc = lhs.location; 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(); diff --git a/src/interner.rs b/src/interner.rs index 5a7d0b7..c24ea3c 100644 --- a/src/interner.rs +++ b/src/interner.rs @@ -15,7 +15,7 @@ pub struct Interner { impl Interner { pub fn new() -> Interner { - Interner { indexes: HashMap::new(), strings: Vec::new() } + Interner { indexes: HashMap::new(), strings: vec![] } } pub fn intern(&mut self, s: &str) -> InternedStr { diff --git a/src/lambda_lift.rs b/src/lambda_lift.rs index 0dfa33c..f7e326c 100644 --- a/src/lambda_lift.rs +++ b/src/lambda_lift.rs @@ -109,7 +109,7 @@ fn abstract_(&mut self, free_vars: &HashMap, input_expr: &mut rhs = Lambda(var.clone(), Box::new(rhs)); typ = function_type_(var.get_type().clone(), typ); } - let id = Id::new(self.name_supply.from_str("#sc"), typ.clone(), Vec::new()); + let id = Id::new(self.name_supply.from_str("#sc"), typ.clone(), vec![]); let bind = Binding { name: id.clone(), expression: rhs @@ -132,7 +132,7 @@ pub fn lift_lambdas(mut module: Module) -> Module { 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() { @@ -156,9 +156,9 @@ pub fn lift_lambdas(mut module: Module) -> Module { 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() .chain(visitor.out_lambdas.into_iter()) @@ -276,7 +276,7 @@ test2 x = 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 @@ -289,7 +289,7 @@ test2 x = self.count += 1; } else if intern("g") == 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) => { args.push(intern("y")); diff --git a/src/lexer.rs b/src/lexer.rs index 9bda7c0..eaf4331 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -178,9 +178,9 @@ impl > Lexer { Lexer { input : input.peekable(), location : start, - unprocessed_tokens : Vec::new(), + unprocessed_tokens : vec![], tokens : VecDeque::with_capacity(20), - indent_levels : Vec::new(), + indent_levels : vec![], offset : 0, interner: get_local_interner() } diff --git a/src/parser.rs b/src/parser.rs index abcdd2c..2874bc0 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -147,7 +147,7 @@ pub fn module(&mut self) -> ParseResult { _ => unexpected!(self, [LBRACE]) }; - let mut imports = Vec::new(); + let mut imports = vec![]; loop { if self.lexer.peek().token == IMPORT { imports.push(self.import()?); @@ -163,13 +163,13 @@ pub fn module(&mut self) -> ParseResult { } } - 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(); + 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; @@ -229,7 +229,7 @@ fn import(&mut self) -> ParseResult> { self.lexer.next(); let x = if self.lexer.peek().token == RPARENS { self.lexer.next(); - Vec::new() + vec![] } else { let imports = self.sep_by_1(|this| Ok(expect!(this, NAME).value), COMMA)?; @@ -251,8 +251,8 @@ fn class(&mut self) -> ParseResult { 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(); + let mut bindings = vec![]; + let mut declarations = vec![]; for decl_or_binding in x.into_iter() { match decl_or_binding { BindOrTypeDecl::Binding(mut bind) => { @@ -357,7 +357,7 @@ pub fn expression(&mut self) -> ParseResult> { fn list(&mut self) -> ParseResult { - let mut expressions = Vec::new(); + let mut expressions = vec![]; loop { match self.expression()? { Some(expr) => expressions.push(expr), @@ -590,7 +590,7 @@ fn application(&mut self) -> ParseResult> { let e = self.sub_expression()?; match e { Some(mut lhs) => { - let mut expressions = Vec::new(); + let mut expressions = vec![]; loop { let expr = self.sub_expression()?; match expr { @@ -743,7 +743,7 @@ fn make_pattern(&mut self, name: InternedStr, args: F) -> ParseResult ParseResult> { - let mut parameters = Vec::new(); + let mut parameters = vec![]; loop { let token = self.lexer.next().token; match token { @@ -859,13 +859,13 @@ fn constrained_type(&mut self) -> ParseResult<(Vec, Type)> { CONTEXTARROW => self.parse_type(), ARROW => { self.lexer.backtrack(); - let mut args = Vec::new(); + 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::new(); + let mut args = vec![]; swap(&mut args, &mut maybe_constraints); Ok(make_tuple_type(args)) } @@ -882,7 +882,7 @@ fn constructor_type(&mut self, arity : &mut isize, data_def: &DataDefinition) -> Type::new_var(self.lexer.current().value) } else { - Type::new_op(self.lexer.current().value.clone(), Vec::new()) + Type::new_op(self.lexer.current().value.clone(), vec![]) }; function_type_(arg, self.constructor_type(arity, data_def)?) } @@ -903,10 +903,10 @@ fn data_definition(&mut self) -> ParseResult { expect!(self, DATA); let mut definition = DataDefinition { - constructors : Vec::new(), + constructors : vec![], typ : qualified(vec![], Type::new_var(intern("a"))), parameters : HashMap::new(), - deriving: Vec::new() + deriving: vec![] }; definition.typ.value = self.data_lhs()?; expect!(self, EQUALSSIGN); @@ -932,9 +932,9 @@ fn newtype(&mut self) -> ParseResult { }; Ok(Newtype { - typ: qualified(Vec::new(), typ.clone()), + typ: qualified(vec![], typ.clone()), constructor_name: name, - constructor_type: qualified(Vec::new(), function_type_(arg_type, typ)), + constructor_type: qualified(vec![], function_type_(arg_type, typ)), deriving: self.deriving()? }) } @@ -959,7 +959,7 @@ fn deriving(&mut self) -> ParseResult> { } else { self.lexer.backtrack(); - Ok(Vec::new()) + Ok(vec![]) } } @@ -987,7 +987,7 @@ fn sub_type(&mut self) -> ParseResult> { } NAME => { if token.value.chars().next().expect("char at 0").is_uppercase() { - Some(Type::new_op(token.value, Vec::new())) + Some(Type::new_op(token.value, vec![])) } else { Some(Type::new_var(token.value)) @@ -1039,7 +1039,7 @@ fn parse_type(&mut self) -> ParseResult { } } NAME => { - let mut type_arguments = Vec::new(); + let mut type_arguments = vec![]; loop { match self.sub_type()? { Some(typ) => type_arguments.push(typ), @@ -1077,7 +1077,7 @@ fn sep_by_1(&mut self, f : F, sep : TokenEnum) -> ParseResult> 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(); + let mut result = vec![]; loop { result.push(f(self)?); if !sep(self.lexer.next()) { @@ -1134,7 +1134,7 @@ fn make_tuple_type(mut types : Vec) -> Type { } 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 +1143,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())?; @@ -1406,7 +1406,7 @@ import Prelude (id, sum) 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[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")])); } @@ -1467,7 +1467,7 @@ 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.typ, qualified(vec![], Type::new_op(intern("Test"), vec![]))); assert_eq!(data.deriving, [intern("Eq"), intern("Debug")]); } @@ -1535,7 +1535,7 @@ 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].typ, qualified(vec![], typ.clone())); assert_eq!(module.newtypes[0].constructor_type.value, function_type_(Type::new_op(intern("(,)"), vec![a, int_type()]), typ)); } diff --git a/src/renamer.rs b/src/renamer.rs index d76a995..107064f 100644 --- a/src/renamer.rs +++ b/src/renamer.rs @@ -52,7 +52,7 @@ pub struct Errors { } impl Errors { pub fn new() -> Errors { - Errors { errors: Vec::new() } + Errors { errors: vec![] } } pub fn insert(&mut self, e: T) { self.errors.push(e); @@ -543,7 +543,7 @@ pub fn prelude_name(s: &str) -> Name { ///If any errors are encounterd while renaming, an error message is output and fail is called 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); @@ -568,7 +568,7 @@ pub mod typ { } ///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; diff --git a/src/scoped_map.rs b/src/scoped_map.rs index 5a73667..d628058 100644 --- a/src/scoped_map.rs +++ b/src/scoped_map.rs @@ -20,7 +20,7 @@ impl ScopedMap where K: Eq + Hash + Clone { pub fn new() -> ScopedMap { - ScopedMap { map: HashMap::new(), scopes: Vec::new() } + ScopedMap { map: HashMap::new(), scopes: vec![] } } ///Introduces a new scope pub fn enter_scope(&mut self) { @@ -87,7 +87,7 @@ 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::Vacant(entry) => entry.insert(vec![]), Entry::Occupied(entry) => entry.into_mut() }; if vec.len() != 0 { @@ -121,7 +121,7 @@ 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::Vacant(entry) => entry.insert(vec![]), Entry::Occupied(entry) => entry.into_mut() }; vec.push(v); diff --git a/src/typecheck.rs b/src/typecheck.rs index d443681..c5184bb 100644 --- a/src/typecheck.rs +++ b/src/typecheck.rs @@ -255,13 +255,13 @@ impl <'a> TypeEnvironment<'a> { insert_to(&mut globals, name.as_ref(), typ); } TypeEnvironment { - assemblies: Vec::new(), + assemblies: vec![], named_types : globals, local_types : HashMap::new(), constraints: HashMap::new(), - instances: Vec::new(), - classes: Vec::new(), - data_definitions : Vec::new(), + instances: vec![], + classes: vec![], + data_definitions : vec![], variable_age : 0 , errors: Errors::new() } @@ -387,7 +387,7 @@ impl <'a> TypeEnvironment<'a> { 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()) + .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(); @@ -440,7 +440,7 @@ 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(); + let mut result : Vec> = vec![]; each_type(typ, |var| { match self.constraints.get(var) { @@ -999,7 +999,7 @@ impl <'a> TypeEnvironment<'a> { 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); } @@ -1038,7 +1038,7 @@ impl <'a> TypeEnvironment<'a> { ///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(); + 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); @@ -1328,7 +1328,7 @@ fn bind_variable(env: &mut TypeEnvironment, subs: &mut Substitution, var: &TypeV 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() { @@ -2210,7 +2210,7 @@ makeEven i " ).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())))); + assert_eq!(un_name(module.bindings[0].typ.clone()), qualified(vec![], function_type_(int_type(), Type::new_op(intern("Even"), vec![])))); } diff --git a/src/types.rs b/src/types.rs index e84eae6..5840ed4 100644 --- a/src/types.rs +++ b/src/types.rs @@ -183,7 +183,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; diff --git a/src/vm.rs b/src/vm.rs index 403d080..408c8ad 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -63,8 +63,8 @@ pub struct 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() @@ -148,8 +148,8 @@ 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) } } } @@ -163,7 +163,7 @@ pub struct VM { impl <'a> VM { pub fn new() -> VM { - VM { assembly : Vec::new(), globals: Vec::new() } + Self { assembly : vec![], globals: vec![] } } ///Adds an assembly to the VM, adding entries to the global table as necessary @@ -182,7 +182,7 @@ 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) } @@ -193,7 +193,7 @@ impl <'a> VM { self.execute(&mut stack, EVALCODE, assembly_id); match *stack[0].borrow() { Constructor(tag, ref vals) => { - let mut ret = Vec::new(); + let mut ret = vec![]; for v in vals.iter() { let s = vec!(v.clone()); let x = self.deepseq(s, assembly_id); @@ -223,21 +223,21 @@ impl <'a> VM { 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()) } }), + IntEQ => primitive_int(stack, |l, r| { if l == r { Constructor(0, vec![]) } else { Constructor(1, vec![]) } }), + IntLT => primitive_int(stack, |l, r| { if l < r { Constructor(0, vec![]) } else { Constructor(1, vec![]) } }), + IntLE => primitive_int(stack, |l, r| { if l <= r { Constructor(0, vec![]) } else { Constructor(1, vec![]) } }), + IntGT => primitive_int(stack, |l, r| { if l > r { Constructor(0, vec![]) } else { Constructor(1, vec![]) } }), + IntGE => primitive_int(stack, |l, r| { if l >= r { Constructor(0, vec![]) } else { Constructor(1, vec![]) } }), 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()) } }), + DoubleEQ => primitive_float(stack, |l, r| { if l == r { Constructor(0, vec![]) } else { Constructor(1, vec![]) } }), + DoubleLT => primitive_float(stack, |l, r| { if l < r { Constructor(0, vec![]) } else { Constructor(1, vec![]) } }), + DoubleLE => primitive_float(stack, |l, r| { if l <= r { Constructor(0, vec![]) } else { Constructor(1, vec![]) } }), + DoubleGT => primitive_float(stack, |l, r| { if l > r { Constructor(0, vec![]) } else { Constructor(1, vec![]) } }), + DoubleGE => primitive_float(stack, |l, r| { if l >= r { Constructor(0, vec![]) } else { Constructor(1, vec![]) } }), IntToDouble => { let top = stack.pop().unwrap(); stack.push(match *top.borrow() { @@ -315,7 +315,7 @@ impl <'a> VM { 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()); @@ -373,7 +373,7 @@ impl <'a> VM { } } Pack(tag, arity) => { - let mut args = Vec::new(); + let mut args = vec![]; for _ in 0..arity { args.push(stack.pop().unwrap()); } @@ -444,7 +444,7 @@ impl <'a> VM { _ => 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() { @@ -461,7 +461,7 @@ impl <'a> VM { 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(); @@ -475,7 +475,7 @@ impl <'a> VM { 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())); @@ -600,7 +600,7 @@ fn extract_result(node: Node_) -> Option { // 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), @@ -677,14 +677,14 @@ mod primitive { 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(); + let mut temp = vec![]; temp.push(node); vm.execute(&mut temp, EVALCODE, 123); temp.pop().unwrap() @@ -718,7 +718,7 @@ mod primitive { 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); @@ -736,7 +736,7 @@ mod primitive { } 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); @@ -770,7 +770,7 @@ mod primitive { 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!() @@ -793,7 +793,7 @@ mod primitive { }, (_, _) => 1//EQ }; - Node::new(Constructor(tag, Vec::new())) + Node::new(Constructor(tag, vec![])) } } @@ -829,7 +829,7 @@ fn test_primitive() 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] @@ -1002,7 +1002,7 @@ fn instance_super_class() { } None => None }; - assert_eq!(result, Some(VMResult::Constructor(1, Vec::new()))); + assert_eq!(result, Some(VMResult::Constructor(1, vec![]))); } #[test] @@ -1057,7 +1057,7 @@ test [] = False main = test [True, True] ") .unwrap(); - assert_eq!(result, Some(VMResult::Constructor(0, Vec::new()))); + assert_eq!(result, Some(VMResult::Constructor(0, vec![]))); } #[test] fn pattern_guards() { @@ -1129,7 +1129,7 @@ import Prelude test x y = (x == y) || (x < y) 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()))); + assert_eq!(result, Some(VMResult::Constructor(0, vec![]))); } #[test] fn implement_class() { @@ -1147,7 +1147,7 @@ test x y = x == y 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] @@ -1160,7 +1160,7 @@ data Test = A Int | B main = A 0 == A 2 || A 0 == B ").unwrap(); - assert_eq!(result, Some(VMResult::Constructor(1, Vec::new()))); + assert_eq!(result, Some(VMResult::Constructor(1, vec![]))); } #[test] fn deriving_ord() { @@ -1172,7 +1172,7 @@ data Test = A Int | B main = compare (A 0) (A 2) == LT && compare B (A 123) == GT ").unwrap(); - assert_eq!(result, Some(VMResult::Constructor(0, Vec::new()))); + assert_eq!(result, Some(VMResult::Constructor(0, vec![]))); } #[test] @@ -1183,7 +1183,7 @@ import Prelude test x y = x == y main = test [1 :: Int] [3] ").unwrap(); - assert_eq!(result, Some(VMResult::Constructor(1, Vec::new()))); + assert_eq!(result, Some(VMResult::Constructor(1, vec![]))); } #[test] fn build_dictionary() { @@ -1195,7 +1195,7 @@ 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()))); + assert_eq!(result, Some(VMResult::Constructor(1, vec![]))); } #[test] From 0b8c521b58fe093fcba8860f177c69ef1fde8b14 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 10:24:57 -0800 Subject: [PATCH 02/76] cargo fmt --- src/builtins.rs | 58 +- src/compiler.rs | 1172 ++++++++++++------- src/core.rs | 1504 ++++++++++++++---------- src/deriving.rs | 264 +++-- src/graph.rs | 62 +- src/infix.rs | 132 ++- src/interner.rs | 17 +- src/lambda_lift.rs | 292 ++--- src/lexer.rs | 415 ++++--- src/main.rs | 31 +- src/module.rs | 219 ++-- src/parser.rs | 2699 ++++++++++++++++++++++++-------------------- src/renamer.rs | 625 ++++++---- src/repl.rs | 60 +- src/scoped_map.rs | 41 +- src/typecheck.rs | 2136 +++++++++++++++++++++-------------- src/types.rs | 275 +++-- src/vm.rs | 957 +++++++++------- 18 files changed, 6592 insertions(+), 4367 deletions(-) diff --git a/src/builtins.rs b/src/builtins.rs index fd9caa5..e5784d2 100644 --- a/src/builtins.rs +++ b/src/builtins.rs @@ -1,21 +1,51 @@ -use crate::types::{Type, TypeVariable, Kind}; use crate::interner::intern; -use crate::renamer::{name, Name}; use crate::renamer::typ::*; +use crate::renamer::{name, Name}; +use crate::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![])))), + 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![])), + ), + ), ] } - diff --git a/src/compiler.rs b/src/compiler.rs index feeb4f0..bb34c30 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -1,16 +1,16 @@ -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::core::*; +use crate::interner::*; use crate::scoped_map::ScopedMap; +use crate::typecheck::{find_specialized_instances, DataTypes, TypeEnvironment, Types}; +use crate::types::{extract_applied_type, qualified}; use std::borrow::ToOwned; +use crate::builtins::builtins; 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 self::Instruction::*; @@ -59,7 +59,7 @@ pub enum Instruction { PushBuiltin(usize), MkapDictionary, ConstructDictionary(usize), - PushDictionaryRange(usize, usize) + PushDictionaryRange(usize, usize), } #[derive(Debug)] enum Var<'a> { @@ -67,10 +67,10 @@ enum Var<'a> { 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,8 +101,7 @@ static BINARY_PRIMITIVES: &'static [(&'static str, Instruction)] = &[ ("primDoubleGE", DoubleGE), ]; - -impl <'a> Clone for Var<'a> { +impl<'a> Clone for Var<'a> { fn clone(&self) -> Var<'a> { match *self { Var::Stack(x) => Var::Stack(x), @@ -112,17 +111,17 @@ impl <'a> Clone for Var<'a> { 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 + 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 +129,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 +143,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::Constraint(self.offset + index, &sc.typ.value, &*sc.typ.constraints) + ); + } else { return Some(Var::Global(self.offset + index)); } } index += 1; } - 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 +179,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 +188,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 { + } 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 { @@ -246,27 +255,47 @@ 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 z = match extract_applied_type(typ) { - &Type::Constructor(ref x) => x, - _ => panic!() + _ => panic!(), }; + let z = + match extract_applied_type(typ) { + &Type::Constructor(ref x) => x, + _ => panic!(), + }; if classname == instance.classname && y.name == z.name { return Some((instance.constraints.as_ref(), &instance.typ)); } @@ -283,7 +312,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 { @@ -302,32 +331,50 @@ impl Types for Assembly { return 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!() + _ => panic!(), }; let y = match extract_applied_type(&**t) { &Type::Constructor(ref x) => x, - _ => panic!() + _ => panic!(), }; let z = match extract_applied_type(typ) { &Type::Constructor(ref x) => x, - _ => panic!() + _ => panic!(), }; if classname.name == x.name && y.name == z.name { return Some((constraints.as_ref(), &**t)); } } - _ => () + _ => (), } } None @@ -347,42 +394,61 @@ impl DataTypes for Assembly { enum ArgList<'a> { Cons(&'a Expr, &'a ArgList<'a>), - Nil + 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> { +impl<'a> Compiler<'a> { pub fn new() -> Compiler<'a> { 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 { + name: intern(name), + uid: 0, + }, + 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 { + name: intern(name), + uid: 0, + }, + 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 { + name: intern(name), + uid: 0, + }, + Var::Primitive(1, instruction), + ); } - Compiler { instance_dictionaries: vec![], - stack_size : 0, assemblies: vec![], + Compiler { + instance_dictionaries: vec![], + stack_size: 0, + assemblies: vec![], module: None, variables: variables, - context: vec![] + 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![]; let mut instance_dictionaries = vec![]; @@ -395,15 +461,21 @@ impl <'a> Compiler<'a> { } 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()); @@ -412,25 +484,41 @@ impl <'a> Compiler<'a> { Assembly { super_combinators: super_combinators, instance_dictionaries: instance_dictionaries, - offset: self.assemblies.iter().fold(0, |sum, assembly| sum + assembly.super_combinators.len()), + 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: 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 = if bind.name.typ.constraints.len() > 0 { + 1 + } else { + 0 + }; self.context = bind.name.typ.constraints.clone(); 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(Name { + name: intern("$dict"), + uid: 0, + }); } debug!("{:?} {:?}\n {:?}", bind.name, dict_arg, bind.expression); arity = this.compile_lambda_binding(&bind.expression, &mut instructions) + dict_arg; @@ -440,17 +528,24 @@ 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 + instructions: 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()); @@ -462,90 +557,103 @@ 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 => 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 + }) + .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 => () + 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) - }) + None + }) + .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 +666,64 @@ 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: 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); } - &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: 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); } - &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); } @@ -639,24 +754,27 @@ impl <'a> Compiler<'a> { let pattern_start = instructions.len() as isize; 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 +788,27 @@ 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; @@ -689,37 +818,68 @@ impl <'a> Compiler<'a> { //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, - _ => () + _ => (), } 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; } @@ -736,7 +896,7 @@ impl <'a> Compiler<'a> { Var::Global(index) => { instructions.push(PushGlobal(index)); } - _ => panic!() + _ => panic!(), } } } @@ -760,7 +920,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 +934,80 @@ 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) { + 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 }; + 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); + 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) + _ => panic!("Unregistered instance function {:?}", instance_fn_name), } } None => { - self.compile_with_constraints(name, actual_type, function_type, constraints, instructions) + 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(Name { + name: intern("$dict"), + uid: 0, + }) { 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 +1015,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())]); @@ -854,43 +1065,54 @@ 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 { + fn push_dictionary_member( + &self, + constraints: &[Constraint], + name: Name, + ) -> Option { if constraints.len() == 0 { - panic!("Attempted to push dictionary member '{:?}' with no constraints", name) + panic!( + "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 +1122,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)) @@ -926,32 +1154,35 @@ impl <'a> Compiler<'a> { } 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 +1193,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 +1210,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 +1232,23 @@ 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 + &Type::Constructor(ref op) => Some(op.name.as_ref()), + _ => None, } } (&Type::Constructor(ref class_op), &Type::Constructor(ref actual_op)) => { @@ -1020,7 +1259,7 @@ fn try_find_instance_type<'a>(class_var: &TypeVariable, class_type: &Type, try_find_instance_type(class_var, &**lhs1, &**lhs2) .or_else(|| try_find_instance_type(class_var, &**rhs1, &**rhs2)) } - _ => None + _ => None, } } @@ -1030,16 +1269,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,7 +1307,9 @@ 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)) @@ -1084,145 +1331,275 @@ fn compile_module_(modules: Vec>) -> Result Assembly { - super::compile(contents).unwrap() -} + use crate::compiler::Instruction::*; + use crate::compiler::{compile_with_type_env, Assembly, Compiler}; + use crate::interner::*; + use crate::typecheck::TypeEnvironment; + use std::fs::File; + use std::io::Read; + use std::path::Path; + use 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 +1615,55 @@ 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]); -} - -#[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; + let test = &assembly.super_combinators[0]; + assert_eq!( + test.instructions, + vec![Pack(0, 0), PushInt(1), Pack(1, 2), Update(0), Unwind] + ); + } - 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) - }); -} + #[bench] + fn bench_prelude(b: &mut Bencher) { + use crate::core::translate::translate_module; + use crate::lambda_lift::do_lambda_lift; + use crate::parser::Parser; + use crate::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) + }); + } } diff --git a/src/core.rs b/src/core.rs index 9bedfab..e3b0c6c 100644 --- a/src/core.rs +++ b/src/core.rs @@ -1,19 +1,19 @@ -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::*; +use crate::module; +pub use crate::module::LiteralData::{Char, Fractional, Integral, String}; +pub use crate::module::{Constructor, DataDefinition, Newtype, TypeDeclaration}; pub use crate::renamer::Name; +use crate::typecheck::TcType; +pub use crate::types::Type::{Application, Variable}; +pub use crate::types::{Constraint, Qualified, Type, TypeVariable}; +use 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 { @@ -24,9 +24,16 @@ impl Module { 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( + Name { + name: intern("main"), + uid: 0, + }, + expr.get_type().clone(), + vec![], + ), + expression: expr, + }], } } } @@ -34,30 +41,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,13 +72,13 @@ 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: Literal_, } pub type Literal_ = module::LiteralData; @@ -83,7 +90,7 @@ pub enum Expr { Literal(LiteralData), Lambda(Ident, Box>), Let(Vec>, Box>), - Case(Box>, Vec>) + Case(Box>, Vec>), } impl fmt::Display for LiteralData { @@ -92,24 +99,24 @@ 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), @@ -121,7 +128,7 @@ impl fmt::Display for Pattern { } write!(f, ")") } - Pattern::WildCard => write!(f, "_") + Pattern::WildCard => write!(f, "_"), } } } @@ -132,7 +139,7 @@ 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 { @@ -140,24 +147,27 @@ impl > Typed for Expr { &Expr::Literal(ref lit) => &lit.typ, &Expr::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() + &Expr::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!() + Pattern::WildCard => panic!(), } } } @@ -172,7 +182,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 +191,12 @@ impl fmt::Display for Id { } } -impl Id { +impl Id { pub fn new(name: T, typ: TcType, constraints: Vec>) -> Id { - Id { name: name, typ: module::qualified(constraints, typ) } + Id { + name: name, + typ: module::qualified(constraints, typ), + } } } @@ -193,29 +206,27 @@ 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::*; ///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); } @@ -253,7 +264,7 @@ pub mod ref_ { visitor.visit_alternative(alt); } } - _ => () + _ => (), } } @@ -263,9 +274,9 @@ pub mod ref_ { } pub mod mutable { - use super::*; use super::Expr::*; - + use super::*; + pub trait Visitor: Sized { fn visit_expr(&mut self, expr: &mut Expr) { walk_expr(self, expr) @@ -273,8 +284,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); } @@ -312,22 +322,25 @@ pub mod mutable { 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::*; ///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 +358,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) + expression: visitor.visit_expr(expression), } } @@ -371,118 +391,154 @@ pub mod result { } Lambda(x, body) => Lambda(x, Box::new(visitor.visit_expr(*body))), Let(binds, e) => { - let bs: Vec> = binds.into_iter().map(|b| { - visitor.visit_binding(b) - }).collect(); + let bs: Vec> = binds + .into_iter() + .map(|b| visitor.visit_binding(b)) + .collect(); Let(bs, Box::new(visitor.visit_expr(*e))) } 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) } - 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::core::*; use crate::deriving::*; + use crate::module; + use crate::renamer::typ::*; + use crate::renamer::NameSupply; + use crate::typecheck::TcType; use 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![]; - 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: constraints, + name: name, + variable: variable, + declarations: 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 + 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); } @@ -491,7 +547,8 @@ pub mod translate { let defaults = create_default_stubs(class_var, class_decls, instance); 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 { @@ -499,16 +556,30 @@ pub mod translate { data_definitions: data_definitions, newtypes: 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(); @@ -516,542 +587,783 @@ pub mod translate { { 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 = + 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 { 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( + Box::new(Apply( + Box::new(Identifier(Id::new(op, func_type, vec![]))), + l, + )), + 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: 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") + } + }, + 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(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)) + } + }; + } + 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: 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(), + )); - 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.len() > 0 && vec[0].name != bind.name { + //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())), + ) + } + + 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.len() > 0 && vec[0].name != bind.name { + result.push(self.translate_matching_groups(vec)); + vec = vec![]; + } + vec.push(bind); + } + if vec.len() > 0 { result.push(self.translate_matching_groups(vec)); - vec = vec![]; } - 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: 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); + } + 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![]; - 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![]; - 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![], |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(), + Type::new_var(intern("a")), + 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![], |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![]; - 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: 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![], |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![]; - 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 { + 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, + } } - } - 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![]; - 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.len() == 0 { + 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 alt = if ps.len() == 0 { + Alternative { + pattern: Pattern::WildCard, + expression: make_let( + bindings, + self.translate_expr((*e).clone()), + ), + } + } else { + Alternative { + pattern: ps[0].1.clone(), + expression: make_let( + bindings, + self.translate_expr((*e).clone()), + ), + } + }; + alts.push(alt); } - 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![]; - 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 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 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; + } } + _ => (), } - _ => () } + last_index += 1; } - last_index += 1; - } - match pattern_test { - Some(pattern_test) => { - vec.clear(); - 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]) { - 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)) => { - 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()) }); + match pattern_test { + Some(pattern_test) => { + vec.clear(); + 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]) { + 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), + ) => { + 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()), + }); + } } } + _ => (), } - _ => () + } else if patterns.len() == 0 { + vec.push(Equation(patterns, expr)); } } - else if patterns.len() == 0 { - vec.push(Equation(patterns, expr)); - } - } - //For all the pattern that match the pattern we need to generate new case expressions - let e = make_let(variable_bindings, self.translate_equations(vec.as_ref())); + //For all the pattern that match the pattern we need to generate new case expressions + let e = make_let(variable_bindings, self.translate_equations(vec.as_ref())); + let arg_id = &ps[0].0; + let bs = needed_variables(arg_id, equations); + alts.push(Alternative { + pattern: pattern_test.1.clone(), + expression: make_let(bs, e), + }); + } + 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 { 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_test.1.clone(), - expression: make_let(bs, e) + pattern: Pattern::WildCard, + expression: e, }); } - None => break + let &Equation(ps, _) = &equations[0]; + let body = Box::new(Identifier(ps[0].0.clone())); + Case(body, alts) } } - 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 { - 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) - } - } - 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, 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) + } + 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( + Name { + name: intern(s), + uid: 0, + }, + 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 + 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 + _ => None, + }, + _ => None, } } } @@ -1063,23 +1375,21 @@ impl <'a> Translator<'a> { } ///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 - } + binding.arguments.iter().all(|arg| match *arg { + module::Pattern::WildCard | module::Pattern::Identifier(..) => true, + _ => false, }) } ///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)); } @@ -1089,8 +1399,7 @@ impl <'a> Translator<'a> { fn make_let(bindings: Vec>, expr: Expr) -> Expr { if bindings.len() == 0 { expr - } - else { + } else { Let(bindings, Box::new(expr)) } } @@ -1098,26 +1407,53 @@ impl <'a> Translator<'a> { ///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.len() > 0 + && (match ps[0].1 { + Pattern::WildCard | Pattern::Identifier(..) => true, + _ => false, + }) + }) .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(), + }, + Type::new_var(intern("a")), + 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(intern(s)), + }) } ///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![])); + 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"))) } - } diff --git a/src/deriving.rs b/src/deriving.rs index 83a1438..964eb1e 100644 --- a/src/deriving.rs +++ b/src/deriving.rs @@ -1,12 +1,15 @@ -use crate::module::encode_binding_identifier; -use crate::core::*; use crate::core::Expr::*; -use crate::renamer::{name, NameSupply}; -use crate::renamer::typ::*; +use crate::core::*; use crate::interner::{intern, InternedStr}; +use crate::module::encode_binding_identifier; +use crate::renamer::typ::*; +use crate::renamer::{name, 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" => { @@ -15,8 +18,11 @@ pub fn generate_deriving(instances: &mut Vec>>, data: &DataDef instances.push(Instance { constraints: vec![], typ: data.typ.value.clone(), - classname: Name { name: intern("Eq"), uid: 0 }, - bindings: bindings + classname: Name { + name: intern("Eq"), + uid: 0, + }, + bindings: bindings, }); } "Ord" => { @@ -27,35 +33,46 @@ pub fn generate_deriving(instances: &mut Vec>>, data: &DataDef instances.push(Instance { constraints: vec![], typ: data.typ.value.clone(), - classname: Name { name: intern("Ord"), uid: 0 }, - bindings: bindings + classname: Name { + name: intern("Ord"), + uid: 0, + }, + bindings: 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)); + 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) }) } 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 +81,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)); @@ -77,113 +95,219 @@ impl DerivingGen { 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, Box::new(expr)))); //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()] }); + 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![], 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: 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![]), vec![]); - Case(Box::new(cmp), 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) } - ]) + let match_id = Id::new( + self.name_supply.anonymous(), + Type::new_op(name("Ordering"), vec![]), + vec![], + ); + Case( + Box::new(cmp), + 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![])) + 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( + Name { + uid: 0, + name: intern("False"), + }, + 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![]) + Id::new( + Name { + name: intern(s), + uid: 0, + }, + 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![]))); + 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)), Box::new(lhs))), Box::new(rhs)) + Apply( + Box::new(Apply(Box::new(Identifier(id)), Box::new(lhs))), + Box::new(rhs), + ) } 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)); +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(Box::new(Apply(Box::new(f), Box::new(lhs))), Box::new(rhs)) } -fn true_expr() -> Expr> { +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; @@ -192,13 +316,13 @@ impl <'a> Iterator for ArgIterator<'a> { self.typ = rest; Some(arg) } - None => None + None => None, } } } fn extract_applied_type<'a, Id>(typ: &'a Type) -> &'a Type { match typ { &Type::Application(ref lhs, _) => extract_applied_type(&**lhs), - _ => typ + _ => typ, } } diff --git a/src/graph.rs b/src/graph.rs index b184603..d2e377e 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,54 @@ pub struct VertexIndex(usize); pub struct EdgeIndex(usize); impl VertexIndex { - fn get(&self) -> usize { let VertexIndex(v) = *self; v } + fn get(&self) -> usize { + let VertexIndex(v) = *self; + v + } } impl EdgeIndex { - fn get(&self) -> usize { let EdgeIndex(v) = *self; v } + fn get(&self) -> usize { + let EdgeIndex(v) = *self; + v + } } 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![], vertices: vec![] } + Graph { + 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![], value: value }); + self.vertices.push(Vertex { + edges: vec![], + value: 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 +78,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![], connections: vec![], + let mut tarjan = TarjanComponents { + graph: 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 +96,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,9 +116,8 @@ 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()]); } } @@ -111,11 +125,10 @@ impl <'a, T> TarjanComponents<'a, T> { if self.lowlink.get(v.get()) == self.valid.get(v.get()) { 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 +136,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 3d27844..53ff2ff 100644 --- a/src/infix.rs +++ b/src/infix.rs @@ -1,46 +1,58 @@ +use crate::interner::intern; use crate::module::*; use crate::renamer::Name; -use crate::interner::intern; use 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)); ::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)); + map.insert( + Name { + uid: 0, + name: intern(":"), + }, + (5, Assoc::Right), + ); PrecedenceVisitor { precedence: map } } 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,13 +63,20 @@ 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![]; 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); @@ -69,9 +88,8 @@ impl PrecedenceVisitor { 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 { + break; + } else if op_prec == prev_prec { match (op_assoc, prev_assoc) { (Assoc::Left, Assoc::Left) => { reduce(&mut expr_stack, &mut op_stack); @@ -79,29 +97,35 @@ impl PrecedenceVisitor { (Assoc::Right, Assoc::Right) => { debug!("Shift op {:?}", op); op_stack.push(op); - break + break; } - _ => panic!("Syntax error: mismatched associativity") + _ => panic!("Syntax error: mismatched associativity"), } - } - else { + } else { reduce(&mut expr_stack, &mut op_stack); } } None => { op_stack.push(op); - break + break; } } } } rhs => { - let mut result = TypedExpr { typ: typ, location: location, expr: 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 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, Box::new(result)), + location, + ); } return result; } @@ -112,51 +136,71 @@ 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::interner::intern; + use crate::module::*; + use crate::parser::*; use crate::renamer::tests::{rename_expr, rename_modules}; + use crate::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 c24ea3c..35ebf59 100644 --- a/src/interner.rs +++ b/src/interner.rs @@ -1,21 +1,23 @@ -use std::collections::HashMap; -use std::rc::Rc; use std::cell::RefCell; -use std::ops::Deref; +use std::collections::HashMap; use std::fmt; +use std::ops::Deref; +use std::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![] } + Interner { + indexes: HashMap::new(), + strings: vec![], + } } pub fn intern(&mut self, s: &str) -> InternedStr { @@ -33,8 +35,7 @@ impl Interner { pub fn get_str<'a>(&'a self, InternedStr(i): InternedStr) -> &'a str { if i < self.strings.len() { &*self.strings[i] - } - else { + } else { panic!("Invalid InternedStr {:?}", i) } } diff --git a/src/lambda_lift.rs b/src/lambda_lift.rs index f7e326c..a38bc93 100644 --- a/src/lambda_lift.rs +++ b/src/lambda_lift.rs @@ -1,9 +1,9 @@ -use std::collections::HashMap; -use std::collections::hash_map::Entry; -use crate::core::*; use crate::core::Expr::*; -use crate::renamer::NameSupply; +use crate::core::*; use crate::renamer::typ::*; +use crate::renamer::NameSupply; +use std::collections::hash_map::Entry; +use std::collections::HashMap; pub type TypeAndStr = Id; @@ -12,7 +12,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,112 +23,130 @@ 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, &mut **func); + self.free_variables(variables, free_vars, &mut **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, &mut **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, &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, + }); + 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.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(); + for (_, var) in free_vars.iter() { + rhs = Lambda(var.clone(), Box::new(rhs)); + 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], Box::new(Identifier(id))) + }; for (_, var) in free_vars.iter() { - rhs = Lambda(var.clone(), Box::new(rhs)); - typ = function_type_(var.get_type().clone(), typ); + e = Apply(Box::new(e), Box::new(Identifier(var.clone()))); } - let id = Id::new(self.name_supply.from_str("#sc"), typ.clone(), vec![]); - 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) => { @@ -138,29 +156,31 @@ pub fn lift_lambdas(mut module: Module) -> Module { for mut bind in bs.into_iter() { let is_lambda = match bind.expression { Lambda(..) => true, - _ => false + _ => false, }; 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); } - _ => walk_expr(self, expr) + _ => walk_expr(self, expr), } remove_empty_let(expr); } } - let mut visitor = LambdaLifter { out_lambdas: vec![] }; + let mut visitor = LambdaLifter { + out_lambdas: vec![], + }; visitor.visit_module(&mut module); 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; @@ -174,12 +194,11 @@ fn remove_empty_let(expr: &mut Expr) { Let(bindings, e) => { if bindings.len() == 0 { *e - } - else { + } else { Let(bindings, e) } } - temp => temp + temp => temp, }; ::std::mem::swap(&mut temp, expr); ::std::mem::forget(temp); @@ -195,25 +214,28 @@ pub fn abstract_module(mut module: Module) -> Module { self.free_variables(&mut variables, &mut free_vars, &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::core::ref_::*; + use crate::core::translate::translate_module; 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 std::collections::HashSet; + use test::Bencher; struct CheckUniques { - found: HashSet + found: HashSet, } impl Visitor for CheckUniques { @@ -226,7 +248,7 @@ mod tests { &Lambda(ref i, _) => { assert!(self.found.insert(i.clone())); } - _ => () + _ => (), } walk_expr(self, expr) } @@ -234,9 +256,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,32 +269,36 @@ 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.len() == 0, } } 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) } - _ => expr + _ => expr, } } @@ -284,11 +313,10 @@ 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 { + } else if intern("g") == bind.name.name.name { let mut args = vec![]; match get_let(&bind.expression, &mut args) { &Let(ref binds, ref body) => { @@ -296,7 +324,7 @@ test2 x = 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 +336,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 +344,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 +359,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); } @@ -343,13 +373,13 @@ test2 x = fn skip_lambdas(expr: &Expr) -> &Expr { match expr { &Lambda(_, ref body) => skip_lambdas(&**body), - _ => expr + _ => 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 +387,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 +399,17 @@ test2 x = #[bench] fn bench(b: &mut Bencher) { + use crate::typecheck::test::do_typecheck; use std::fs::File; use std::io::Read; use std::path::Path; - use crate::typecheck::test::do_typecheck; 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 eaf4331..b3affdd 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -1,46 +1,46 @@ -use std::fmt; +use crate::interner::*; +use std::cell::RefCell; use std::collections::VecDeque; +use std::fmt; use std::iter::Peekable; use std::rc::Rc; -use std::cell::RefCell; -use crate::interner::*; 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 +51,38 @@ pub enum TokenEnum { DERIVING, IF, THEN, - ELSE + ELSE, } #[derive(Clone, Copy, PartialEq, Debug)] 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 } + Location { + 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 +96,59 @@ 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} } + Token { + token: EOF, + value: intern(""), + location: Location { + column: -1, + row: -1, + absolute: -1, + }, + } } - 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, + ) -> Token { + Token { + token: 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) -> Token { + Token::new( + &get_local_interner(), + token, + value, + Location { + column: -1, + row: -1, + absolute: -1, + }, + ) } } impl PartialEq for Token { - fn eq(&self, rhs : &Token) -> bool { + fn eq(&self, rhs: &Token) -> 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 +170,50 @@ 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 { +fn is_operator(first_char: char) -> bool { match first_char { - '+' | '-' | '*' | '/' | '.' | '$' | - ':' | '=' | '<' | '>' | '|' | '&' | '!' => true, - _ => false + '+' | '-' | '*' | '/' | '.' | '$' | ':' | '=' | '<' | '>' | '|' | '&' | '!' => true, + _ => false, } } -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![], - tokens : VecDeque::with_capacity(20), - indent_levels : vec![], - offset : 0, - interner: get_local_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![], + 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 +226,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,7 +245,7 @@ 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 { @@ -220,15 +253,13 @@ impl > Lexer { self.offset -= 1; match self.tokens.get(self.tokens.len() - 1 - self.offset) { Some(token) => token, - None => panic!("Impossible empty tokens stream") + None => panic!("Impossible empty tokens stream"), } - } - else if self.unprocessed_tokens.len() > 0 { + } else if self.unprocessed_tokens.len() > 0 { //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() } } @@ -237,7 +268,7 @@ impl > Lexer { 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") + None => panic!("Attempted to access Lexer::current() on when tokens is empty"), } } @@ -249,7 +280,11 @@ 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 + || match self.tokens.back() { + None => true, + Some(x) => x.token != EOF, + } } ///Peeks at the next character in the input @@ -274,7 +309,7 @@ impl > Lexer { } Some(c) } - None => None + None => None, } } @@ -290,13 +325,13 @@ impl > Lexer { self.read_char(); result.push(x) } - None => break + None => break, } } 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,7 +342,7 @@ impl > Lexer { number.push('.'); number.push_str(self.scan_digits().as_ref()); } - _ => () + _ => (), } Token::new(&self.interner, token, number.as_ref(), location) } @@ -323,10 +358,15 @@ impl > Lexer { self.read_char(); result.push(ch); } - None => break + None => break, } } - return Token::new(&self.interner, name_or_keyword(result.as_ref()), result.as_ref(), start_location); + return 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 @@ -338,11 +378,16 @@ impl > Lexer { if self.indent_levels.len() != 0 { //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 +396,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 +407,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() @@ -383,7 +430,7 @@ impl > Lexer { ///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 + let tok = self.unprocessed_tokens.last().unwrap().clone(); //TODO dont use clone match tok.token { INDENTLEVEL => { if self.indent_levels.len() > 0 { @@ -392,16 +439,25 @@ impl > Lexer { //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; } } @@ -409,8 +465,7 @@ impl > Lexer { if self.unprocessed_tokens.len() == 0 { self.next_token(); return; - } - else { + } else { return self.layout_independent_token(); } } @@ -423,73 +478,88 @@ impl > Lexer { 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()); + 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 { + } else { if self.indent_levels.len() == 0 { //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 + if self.location.column == 0 { + //newline detected *newline = true; } } - None => { return Token::eof() } + None => return Token::eof(), } } let start_location = self.location; @@ -507,27 +577,26 @@ impl > Lexer { self.read_char(); result.push(ch); } - None => { break; } + None => { + break; + } } } 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); @@ -537,33 +606,32 @@ impl > Lexer { 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 == '\'' { + } 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 { + } else { panic!("Multi char character") } } - None => panic!("Unexpected EOF") + None => panic!("Unexpected EOF"), } } let tok = match c { @@ -575,8 +643,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 +654,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..50093f5 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() { @@ -85,7 +85,6 @@ fn main() { 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..fe0f67d 100644 --- a/src/module.rs +++ b/src/module.rs @@ -1,23 +1,23 @@ -use std::fmt; -use std::collections::HashMap; use crate::interner::{intern, InternedStr}; -use crate::lexer::{Location, Located}; -pub use std::default::Default; +use crate::lexer::{Located, Location}; pub use crate::types::*; +use std::collections::HashMap; +pub use std::default::Default; +use std::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 +25,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 +75,82 @@ 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 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 with_location>( + expr: Expr, + loc: Location, + ) -> TypedExpr { + TypedExpr { + expr: expr, + typ: Type::new_var(intern("a")), + 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 +158,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 + Match::Simple(ref e) => &e.location, } } } @@ -164,14 +178,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 +193,7 @@ pub enum LiteralData { Integral(isize), Fractional(f64), String(InternedStr), - Char(char) + Char(char), } #[derive(Clone, Debug, PartialEq)] pub enum Expr { @@ -190,18 +204,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 +235,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,11 +243,11 @@ 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), @@ -241,17 +259,17 @@ impl > fmt::Display for Pattern { } write!(f, ")") } - &Pattern::WildCard => write!(f, "_") + &Pattern::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), @@ -270,7 +288,7 @@ impl fmt::Display for LiteralData { 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) + LiteralData::Char(c) => write!(f, "'{}'", c), } } } @@ -279,7 +297,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,7 +327,7 @@ 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!(), } } @@ -353,14 +371,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); } &TypeSig(ref expr, _) => visitor.visit_expr(&**expr), &Paren(ref expr) => visitor.visit_expr(&**expr), - &Literal(..) | &Identifier(..) => () + &Literal(..) | &Identifier(..) => (), } } @@ -381,7 +399,7 @@ pub fn walk_alternative>(visitor: &mut V, alt: &Alterna visitor.visit_binding(bind); } } - None => () + None => (), } } @@ -392,13 +410,11 @@ pub fn walk_pattern>(visitor: &mut V, pattern: &Pattern 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 +433,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 +445,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) => { @@ -477,18 +500,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); } TypeSig(ref mut expr, _) => visitor.visit_expr(&mut **expr), Paren(ref mut expr) => visitor.visit_expr(&mut **expr), - Literal(..) | Identifier(..) => () + 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), @@ -505,34 +531,37 @@ pub fn walk_alternative_mut>(visitor: &mut V, alt: & visitor.visit_binding(bind); } } - None => () + None => (), } } -pub fn walk_pattern_mut>(visitor: &mut V, pattern: &mut Pattern) { +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 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() + } else { + let end = self + .vec + .iter() .position(|bind| bind.name != self.vec[0].name) .unwrap_or(self.vec.len()); let head = &self.vec[..end]; @@ -555,11 +584,13 @@ 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 { +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); intern(buffer.as_ref()) } - diff --git a/src/parser.rs b/src/parser.rs index 2874bc0..f365a56 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,17 +1,17 @@ -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::interner::*; use crate::lexer::TokenEnum::*; -use crate::module::*; +use crate::lexer::*; use crate::module::Expr::*; use crate::module::LiteralData::*; -use crate::interner::*; +use crate::module::*; +use std::collections::{HashMap, HashSet}; +use std::error; +use std::fmt; +use std::fs::File; +use std::io; +use std::io::Read; +use std::mem::swap; +use std::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 +20,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 +37,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 +48,59 @@ 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) => ( + ($e: expr, $p: pat) => { match $e { $p => true, - _ => false + _ => false, } - ) + }; } macro_rules! unexpected ( @@ -103,1033 +112,1146 @@ macro_rules! unexpected ( } } ); +impl> Parser { + pub fn new(iterator: Iter) -> Parser { + Parser { + 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![]; + loop { + if self.lexer.peek().token == IMPORT { + imports.push(self.import()?); + if self.lexer.peek().token == SEMICOLON { + self.lexer.next(); + } else { + break; + } + } else { + break; + } + } - let mut imports = vec![]; - loop { - if self.lexer.peek().token == IMPORT { - imports.push(self.import()?); - if self.lexer.peek().token == SEMICOLON { + 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; + if token == NAME || token == LPARENS { + match self.binding_or_type_declaration()? { + BindOrTypeDecl::Binding(bind) => bindings.push(bind), + BindOrTypeDecl::TypeDecl(decl) => type_declarations.push(decl), + } + } 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; } - else { - break + let semicolon = self.lexer.next(); + debug!("More bindings? {:?}", semicolon.token); + if semicolon.token != SEMICOLON { + break; } } - else { - break - } - } - 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; - if token == NAME || token == LPARENS { - match self.binding_or_type_declaration()? { - BindOrTypeDecl::Binding(bind) => bindings.push(bind), - BindOrTypeDecl::TypeDecl(decl) => type_declarations.push(decl) - } - } - 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 : imports, - bindings : bindings, - type_declarations : type_declarations, - classes : classes, - instances : instances, - data_definitions : data_definitions, - newtypes: newtypes, - fixity_declarations : 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![] - } - 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: 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![]; - 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 - 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); + 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 + 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(), + ) + } } - _ => return self.error("The name of the class must start with an uppercase letter".to_string()) + bindings.push(bind) } - bindings.push(bind) + BindOrTypeDecl::TypeDecl(decl) => declarations.push(decl), } - BindOrTypeDecl::TypeDecl(decl) => declarations.push(decl) } - } - - expect!(self, RBRACE); - match typ { - Type::Application(l, r) => { - match (*l, *r) { + 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 + bindings: bindings, }); } - _ => () - } + _ => (), + }, + _ => (), } - _ => () + self.error("Parse error in class declaration header".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); - - 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); + 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: classname, + bindings: bindings, + constraints: constraints, + }) } + _ => return self.error("TypeVariable in instance".to_string()), + } + } - expect!(self, RBRACE); - Ok(Instance { typ : *arg, classname : classname, bindings : bindings, constraints: constraints }) + 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 + )), + })), } - _ => 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 { + self.lexer.backtrack(); + Ok(Some(expr)) + } + } + None => Ok(None), + } } -} -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))) + fn list(&mut self) -> ParseResult { + let mut expressions = vec![]; + loop { + match self.expression()? { + Some(expr) => expressions.push(expr), + None => break, } - else { + 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 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)) + } 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)) + } else { + Some(new_tuple(expressions)) + } + } + } + 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, + } + } + CASE => { + let location = self.lexer.current().location; + let expr = self.expression()?; -fn list(&mut self) -> ParseResult { - let mut expressions = vec![]; - 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()) - })) -} + expect!(self, OF); + expect!(self, LBRACE); -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)) + 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, + } } - 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)) + 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(Box::new(pred), Box::new(if_true), Box::new(if_false)), + 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)))) + 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 + )), + })); } - None => None + 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, + )) } - } - 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 + NAME => { + let token = self.lexer.current(); + Some(TypedExpr::with_location( + Identifier(token.value.clone()), + token.location, + )) } - } - IF => { - let location = self.lexer.current().location; - let pred = 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, THEN); - let if_true = self.expression_()?; - if self.lexer.peek().token == SEMICOLON { - self.lexer.next(); + FLOAT => { + let token = self.lexer.current(); + Some(TypedExpr::with_location( + Literal(Fractional(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)) - })); + STRING => { + let token = self.lexer.current(); + Some(TypedExpr::with_location( + Literal(String(token.value.clone())), + 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); + CHAR => { + let token = self.lexer.current(); + Some(TypedExpr::with_location( + Literal(Char(token.value.chars().next().expect("char at 0"))), + 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)); + _ => { + self.lexer.backtrack(); + None } - EOF => { - return Err(ParseError(Located { - location: self.lexer.current().location, - node: Error::Message("Unexpected EOF".to_string()) - })) + }; + 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); + } + 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()); + } } - _ => { debug!("Lookahead {:?}", self.lexer.current()); } } } -} - -fn let_bindings(&mut self) -> ParseResult> { - 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 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()?) + } else { + None + }; + Ok(Alternative { + pattern: pat, + matches: matches, + where_bindings: 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; - let loc = self.lexer.current().location; - let rhs = self.application()?; - let rhs = self.binary_expression(rhs)?; - let expr = match (lhs, rhs) { - (Some(lhs), Some(rhs)) => { - Some(TypedExpr::with_location(OpApply(Box::new(lhs), op, Box::new(rhs)), loc)) - } - (Some(lhs), None) => { - let name = TypedExpr::with_location(Identifier(op), loc); - Some(TypedExpr::with_location(Apply(Box::new(name), Box::new(lhs)), loc)) - } - (None, Some(rhs)) => { - if op == intern("-") { - let name = TypedExpr::with_location(Identifier(intern("negate")), loc); - let args = vec![rhs]; - Some(make_application(name, args.into_iter())) + 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; + let loc = self.lexer.current().location; + let rhs = self.application()?; + let rhs = self.binary_expression(rhs)?; + let expr = match (lhs, rhs) { + (Some(lhs), Some(rhs)) => Some(TypedExpr::with_location( + OpApply(Box::new(lhs), op, Box::new(rhs)), + loc, + )), + (Some(lhs), None) => { + let name = TypedExpr::with_location(Identifier(op), loc); + Some(TypedExpr::with_location( + Apply(Box::new(name), Box::new(lhs)), + 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)) + (None, Some(rhs)) => { + if op == intern("-") { + 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); + 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, + )) + } } - } - (None, None) => return Ok(None) - }; - Ok(expr) - } - else { - self.lexer.backtrack(); - Ok(lhs) + (None, None) => return Ok(None), + }; + Ok(expr) + } else { + self.lexer.backtrack(); + Ok(lhs) + } } -} -fn application(&mut self) -> ParseResult> { - let e = self.sub_expression()?; - match e { - Some(mut lhs) => { - let mut expressions = vec![]; - loop { - let expr = self.sub_expression()?; - match expr { - Some(e) => expressions.push(e), - None => break + fn application(&mut self) -> ParseResult> { + let e = self.sub_expression()?; + match e { + Some(mut lhs) => { + let mut expressions = vec![]; + loop { + let expr = self.sub_expression()?; + match expr { + Some(e) => expressions.push(e), + None => break, + } } + if expressions.len() > 0 { + let loc = lhs.location; + lhs = make_application(lhs, expressions.into_iter()); //, loc); + lhs.location = loc; + } + Ok(Some(lhs)) } - if expressions.len() > 0 { - let loc = lhs.location; - lhs = make_application(lhs, expressions.into_iter());//, loc); - lhs.location = loc; - } - Ok(Some(lhs)) + None => Ok(None), } - None => Ok(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; + 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(); - 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) + Ok(Constructor { + name: name, + typ: qualified(vec![], typ), + tag: 0, + arity: arity, + }) } -} -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::default(), + arguments: arguments, + where_bindings: where_bindings, + matches: 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![]; - 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: assoc, + precedence: precedence, + operators: 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); } - else { - Pattern::Constructor(intern(tuple_name(tuple_args.len()).as_ref()), tuple_args) + NUMBER => parameters.push(Pattern::Number( + FromStr::from_str(self.lexer.current().value.as_ref()).unwrap(), + )), + LPARENS => { + self.lexer.backtrack(); + parameters.push(self.pattern()?); + } + 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: 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 (context, typ) = self.constrained_type()?; + Ok(TypeDeclaration { + name: name, + typ: Qualified { + constraints: context, + 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![]; - 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 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![]) + 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 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) + } -fn data_definition(&mut self) -> ParseResult { - expect!(self, DATA); + fn data_definition(&mut self) -> ParseResult { + expect!(self, DATA); - let mut definition = DataDefinition { - constructors : vec![], - typ : qualified(vec![], Type::new_var(intern("a"))), - 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 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![], typ.clone()), - constructor_name: name, - constructor_type: qualified(vec![], function_type_(arg_type, typ)), - deriving: self.deriving()? - }) -} + let mut definition = DataDefinition { + constructors: vec![], + typ: qualified(vec![], Type::new_var(intern("a"))), + 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![]) + 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: 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 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![])) - } - 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(&mut **lhs, kind + 1) } - else { + _ => *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(); - 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![])) + LPARENS => { + self.lexer.backtrack(); + Some(self.parse_type()?) } - 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 => { + 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)) } } - } - NAME => { - let mut type_arguments = vec![]; - loop { - match self.sub_type()? { - Some(typ) => type_arguments.push(typ), - None => break - } + _ => { + self.lexer.backtrack(); + None } + }; + Ok(t) + } - 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 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) + } + } + 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![]; + loop { + match self.sub_type()? { + Some(typ) => type_arguments.push(typ), + None => break, + } + } -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![]; - 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(Box::new(func), Box::new(a)), 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, Box::new(body)), 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) } } @@ -1159,7 +1281,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 +1294,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 +1309,372 @@ 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::*; + use crate::lexer::{Located, Location}; + use crate::parser::*; + use crate::typecheck::{apply, case, identifier, if_else, let_, number, op_apply, rational}; + use std::fs::File; + use std::io::Read; + use std::path::Path; + 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")); + } -#[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 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::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 = &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_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![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_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( + 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 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(Type::new_var(intern("a"))) + ); + } + #[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(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 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"), + ), + ], + 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")))) + ); + } -#[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![])); - 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::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 +1682,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![], Type::new_op(intern("Test"), vec![]))); - 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 +1762,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![], 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::new_var(intern("a")); + 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 107064f..6eadd44 100644 --- a/src/renamer.rs +++ b/src/renamer.rs @@ -1,19 +1,22 @@ -use std::fmt; -use std::error; -use crate::module::*; +use crate::interner::*; use crate::lexer::Located; +use crate::module::*; use crate::scoped_map::ScopedMap; -use crate::interner::*; +use std::error; +use std::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) } + Name { + uid: 0, + name: intern(s), + } } impl PartialEq for Name { @@ -32,7 +35,6 @@ impl PartialEq for InternedStr { } } - impl AsRef for Name { fn as_ref(&self) -> &str { self.name.as_ref() @@ -48,9 +50,9 @@ 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 { +impl Errors { pub fn new() -> Errors { Errors { errors: vec![] } } @@ -64,15 +66,19 @@ impl Errors { 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 +96,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)] @@ -103,17 +111,16 @@ 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) + Error::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 } } @@ -127,7 +134,10 @@ impl NameSupply { } ///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; @@ -147,23 +157,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() } + Renamer { + 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 +206,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 => { @@ -198,47 +229,73 @@ impl Renamer { self.declare_global(imported_str, uid); } } - None => {//Import everything - self.import_globals(imported_module, &mut |name| name.name, imported_module.name.uid) + None => { + //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::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))), + OpApply(lhs, op, rhs) => OpApply( + Box::new(self.rename(*lhs)), + self.get_name(op), + Box::new(self.rename(*rhs)), + ), Lambda(arg, body) => { self.uniques.enter_scope(); let l = Lambda(self.rename_pattern(arg), Box::new(self.rename(*body))); @@ -253,46 +310,62 @@ impl Renamer { 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: 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,11 +376,12 @@ 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 @@ -315,37 +389,63 @@ impl Renamer { 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 + None => Name { name: s, uid: 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: 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 +456,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 +477,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,163 +506,202 @@ 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: 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: tag, + arity: 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: parameters, + constructors: c, + deriving: d, + } + }) + .collect(); + + let newtypes2: Vec> = newtypes + .into_iter() + .map(|newtype| { + let Newtype { typ, - tag, - arity - } = ctor; - Constructor { - name : renamer.get_name(name), - typ : renamer.rename_qualified_type(typ), - tag : tag, - arity : arity + 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 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: 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)) - .collect(); - FixityDeclaration { assoc: assoc, precedence: precedence, - operators: ops + 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 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: assoc, + precedence: precedence, + operators: ops, + } + }, + ) + .collect(); let decls2 = renamer.rename_type_declarations(type_declarations); renamer.uniques.exit_scope(); Module { 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![]; 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 crate::types::{Kind, Type, TypeVariable}; + use 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() @@ -572,14 +712,18 @@ pub mod typ { 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 +754,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 +768,38 @@ pub mod typ { } } - #[cfg(test)] pub mod tests { use super::Name; use crate::interner::InternedStr; - use crate::module::{TypedExpr, Module}; + use crate::module::{Module, TypedExpr}; use crate::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 +809,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..62645d9 100644 --- a/src/repl.rs +++ b/src/repl.rs @@ -1,24 +1,23 @@ 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::core::{Module, Qualified, Type}; +use crate::interner::*; use crate::lambda_lift::*; use crate::parser::Parser; -use crate::renamer::{Name, rename_expr}; +use crate::renamer::{rename_expr, Name}; +use crate::typecheck::*; +use crate::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 + Type::Application(ref lhs, _) => match **lhs { + Type::Constructor(ref op) => op.name.as_ref() == "IO", + _ => false, + }, + _ => false, } } @@ -33,7 +32,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 +40,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 +59,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 +69,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 +83,28 @@ 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) + Err(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 d628058..c8bf4ea 100644 --- a/src/scoped_map.rs +++ b/src/scoped_map.rs @@ -1,5 +1,5 @@ -use std::collections::HashMap; use std::collections::hash_map::{Entry, IterMut}; +use std::collections::HashMap; use std::hash::Hash; ///A map struct which allows for the isizeroduction of different scopes @@ -12,15 +12,19 @@ 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 { - +impl ScopedMap +where + K: Eq + Hash + Clone, +{ pub fn new() -> ScopedMap { - ScopedMap { map: HashMap::new(), scopes: vec![] } + ScopedMap { + map: HashMap::new(), + scopes: vec![], + } } ///Introduces a new scope pub fn enter_scope(&mut self) { @@ -31,8 +35,10 @@ impl ScopedMap pub fn exit_scope(&mut self) { loop { match self.scopes.pop() { - Some(Some(key)) => { self.map.get_mut(&key).map(|x| x.pop()); } - _ => break + Some(Some(key)) => { + self.map.get_mut(&key).map(|x| x.pop()); + } + _ => break, } } } @@ -49,7 +55,7 @@ impl ScopedMap } true } - None => false + None => false, } } @@ -59,7 +65,7 @@ impl ScopedMap match *n { Some(ref name) if name == k => return true, None => break, - _ => () + _ => (), } } false @@ -76,7 +82,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) { @@ -88,14 +96,13 @@ impl ScopedMap pub fn swap(&mut self, k: K, v: V) -> Option { let vec = match self.map.entry(k.clone()) { Entry::Vacant(entry) => entry.insert(vec![]), - Entry::Occupied(entry) => entry.into_mut() + Entry::Occupied(entry) => entry.into_mut(), }; if vec.len() != 0 { - let r = vec.pop(); + let r = vec.pop(); vec.push(v); r - } - else { + } else { vec.push(v); self.scopes.push(Some(k)); None @@ -113,7 +120,7 @@ impl ScopedMap } Some(v) } - None => None + None => None, } } pub fn find_mut<'a>(&'a mut self, key: &K) -> Option<&'a mut V> { @@ -122,7 +129,7 @@ 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![]), - Entry::Occupied(entry) => entry.into_mut() + 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 c5184bb..887e6af 100644 --- a/src/typecheck.rs +++ b/src/typecheck.rs @@ -1,34 +1,45 @@ -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::builtins::builtins; +use crate::graph::{strongly_connected_components, Graph, VertexIndex}; +use crate::interner::*; +use crate::lexer::Location; 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::module::*; use crate::renamer::*; -use crate::interner::*; +use std::collections::hash_map::Entry; +use std::collections::HashMap; +use std::error; +use std::fmt; +use std::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 + None => false, } } - 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 +65,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 +124,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 +137,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 +154,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 +177,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 +208,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 +239,13 @@ 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 { + name: intern(name), + uid: 0, + }, + qualified(vec![], typ), + ); } fn prim(typename: &str, op: &str) -> ::std::string::String { let mut b = "prim".to_string(); @@ -232,23 +273,34 @@ 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> { 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())); + 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())); - + 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); @@ -256,14 +308,14 @@ impl <'a> TypeEnvironment<'a> { } TypeEnvironment { assemblies: vec![], - named_types : globals, - local_types : HashMap::new(), + named_types: globals, + local_types: HashMap::new(), constraints: HashMap::new(), instances: vec![], classes: vec![], - data_definitions : vec![], - variable_age : 0 , - errors: Errors::new() + data_definitions: vec![], + variable_age: 0, + errors: Errors::new(), } } @@ -276,8 +328,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 +343,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,7 +352,7 @@ 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 @@ -308,11 +360,15 @@ impl <'a> TypeEnvironment<'a> { Some(ref k) => { class.variable.kind.clone_from(k); } - None => () + None => (), } - - let c = Constraint { class: class.name.clone(), variables: vec![class.variable.clone()] }; - {//Workaround to add the class's constraints directyly to the declaration + + 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 +381,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 +395,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_constraints, 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 +427,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(Box::new(Kind::Star), Box::new(Kind::Star)) + } 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 +471,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![]).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 +491,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 +526,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 +545,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![]; - 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 +604,139 @@ 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: 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 +745,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 +767,39 @@ 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); + 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 => () + Some(mut typ) => unify_location( + self, + subs, + &guard.expression.location, + &mut typ, + &mut typ2, + ), + None => (), } 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,7 +807,7 @@ impl <'a> TypeEnvironment<'a> { } ///Typechecks an expression - fn typecheck(&mut self, expr : &mut TypedExpr, subs: &mut Substitution) -> TcType { + fn typecheck(&mut self, expr: &mut TypedExpr, subs: &mut Substitution) -> TcType { if expr.typ == Type::::new_var(intern("a")) { expr.typ = self.new_var(); } @@ -634,17 +816,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,16 +840,14 @@ 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) @@ -673,7 +855,7 @@ impl <'a> TypeEnvironment<'a> { 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) @@ -690,23 +872,48 @@ impl <'a> TypeEnvironment<'a> { 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: &mut **bindings, + }, + ); self.apply_locals(subs); self.typecheck(&mut **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); + 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: &mut **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: &mut **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); @@ -722,8 +929,15 @@ impl <'a> TypeEnvironment<'a> { 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 })); + 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())); for bind in bindings.iter_mut() { match *bind { @@ -732,7 +946,12 @@ 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: &mut **bindings, + }, + ); self.apply_locals(subs); } DoBinding::DoBind(ref mut pattern, ref mut e) => { @@ -740,16 +959,21 @@ 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, + &mut **inner_type, + ); } } match previous { Type::Application(ref mut _monad, ref mut typ) => { **typ = self.new_var(); } - _ => panic!() + _ => panic!(), } } let mut typ = self.typecheck(&mut **last_expr, subs); @@ -759,52 +983,84 @@ impl <'a> TypeEnvironment<'a> { TypeSig(ref mut expr, ref mut qualified_type) => { let mut typ = self.typecheck(&mut **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(&mut **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 { Type::Application(_, x) => *x, - _ => panic!("Must be a type application (should be a function type), found {:?}", result) + _ => panic!( + "Must be a type application (should be a function type), found {:?}", + result + ), }; 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 => { - } + &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 +1074,54 @@ 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 + panic!( + "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 => () + Some(ref mut bindings) => { + self.typecheck_local_bindings( + subs, + &mut BindingsWrapper { + value: &mut **bindings, + }, + ) + } + None => (), } 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.len() == 0 { + 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 => () + Some(mut prev) => { + unify_location(self, subs, bind.matches.location(), &mut typ, &mut prev) + } + None => (), } replace(&mut self.constraints, &mut typ, subs); previous_type = Some(typ); @@ -856,14 +1131,27 @@ 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_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 => () + Some(var) => { + subs.subs.insert(var, final_type); + } + None => (), } for bind in bindings.iter_mut() { match bind.matches { @@ -876,19 +1164,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 +1193,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 +1209,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 +1231,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,45 +1253,52 @@ 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![]); self.insert_constraint_(&mut constraints, classname); @@ -1006,7 +1307,9 @@ impl <'a> TypeEnvironment<'a> { 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 +1327,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); +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); + panic!( + "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) { @@ -1065,7 +1381,7 @@ fn find_specialized(result: &mut Vec<(Name, TcType)>, actual_type: &TcType, typ: } } } - _ => () + _ => (), } } @@ -1080,11 +1396,11 @@ fn quantify(start_var_age: isize, typ: &mut Qualified) { quantify_(start_var_age, &mut **rhs); None } - _ => None + _ => None, }; match x { Some(var) => *typ = Type::Generic(var), - None => () + None => (), } } for constraint in typ.constraints.iter_mut() { @@ -1101,8 +1417,7 @@ pub fn replace_var(typ: &mut TcType, var: &TypeVariable, replacement: &TcType) { Type::Variable(ref v) => { if v == var { Some(replacement) - } - else { + } else { None } } @@ -1112,30 +1427,28 @@ pub fn replace_var(typ: &mut TcType, var: &TypeVariable, replacement: &TcType) { replace_var(&mut **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 => () + None => (), } } ///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 - } + Type::Application(ref lhs, _) => match **lhs { + Type::Application(ref lhs, _) => { + match **lhs { + Type::Constructor(ref op) => op.name == intern("->"), + _ => false, } - _ => false } - } - _ => false + _ => false, + }, + _ => false, } } ///Extracts the final return type of a type @@ -1144,23 +1457,22 @@ fn get_returntype(typ: &TcType) -> TcType { &Type::Application(_, ref rhs) => { if is_function(typ) { get_returntype(&**rhs) - } - else { + } else { typ.clone() } } - _ => typ.clone() + _ => 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); @@ -1170,7 +1482,7 @@ fn replace(constraints: &mut HashMap>, old : &mut TcType }; match replaced { Some(x) => *old = x, - None => () + None => (), } } @@ -1178,15 +1490,22 @@ 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) => { @@ -1194,18 +1513,18 @@ fn freshen(env: &mut TypeEnvironment, subs: &mut Substitution, typ: &mut Qualifi freshen_(env, subs, constraints, &mut **rhs); None } - _ => None + _ => None, }; match result { Some(x) => *typ = x, - None => () + None => (), } } 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 => () + None => (), } } } @@ -1218,27 +1537,29 @@ fn freshen_all(env: &mut TypeEnvironment, subs: &mut Substitution, typ: &mut TcT freshen_all(env, subs, &mut **rhs); None } - _ => None + _ => None, }; match result { Some(x) => *typ = x, - None => () + None => (), } } ///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 +1570,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: error, + }), } } @@ -1264,7 +1594,7 @@ struct TypeErrorInfo { location: Location, lhs: TcType, rhs: TcType, - error: Error + error: Error, } #[derive(Debug)] @@ -1272,7 +1602,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 +1627,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 { @@ -1311,7 +1646,7 @@ fn bind_variable(env: &mut TypeEnvironment, subs: &mut Substitution, var: &TypeV env.insert_constraint(var2, c.clone()); } } - None => () + None => (), } } Ok(()) @@ -1319,11 +1654,9 @@ 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); } @@ -1337,22 +1670,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 +1707,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, &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::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 +1735,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 +1744,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 +1759,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,16 +1775,32 @@ 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: 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(|_| { @@ -1444,12 +1813,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 +1834,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,34 +1860,49 @@ 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) + Identifier(ref n) => match self.map.get(n) { + Some(index) => self.graph.connect(self.function_index, *index), + None => (), + }, + _ => walk_expr(self, expr), } } } - EdgeVisitor { graph: graph, map: map, function_index: function_index }.visit_expr(expr) + EdgeVisitor { + graph: graph, + map: map, + function_index: 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), @@ -1519,74 +1910,73 @@ fn each_type_(typ: &Type, var_fn: &mut dyn FnMut(&TypeVariable), 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) { +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 + 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 + _ => 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 { +pub fn lambda(arg: &str, body: TypedExpr) -> TypedExpr { TypedExpr::new(Lambda(Pattern::Identifier(intern(arg)), Box::new(body))) } #[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 { +pub fn apply(func: TypedExpr, arg: TypedExpr) -> TypedExpr { TypedExpr::new(Apply(Box::new(func), Box::new(arg))) } #[cfg(test)] @@ -1594,11 +1984,11 @@ pub fn op_apply(lhs: TypedExpr, op: InternedStr, rhs: TypedExpr) -> TypedExpr { TypedExpr::new(OpApply(Box::new(lhs), op, Box::new(rhs))) } #[cfg(test)] -pub fn let_(bindings : Vec, expr : TypedExpr) -> TypedExpr { +pub fn let_(bindings: Vec, expr: TypedExpr) -> TypedExpr { TypedExpr::new(Let(bindings, Box::new(expr))) } #[cfg(test)] -pub fn case(expr : TypedExpr, alts: Vec) -> TypedExpr { +pub fn case(expr: TypedExpr, alts: Vec) -> TypedExpr { TypedExpr::new(Case(Box::new(expr), alts)) } #[cfg(test)] @@ -1606,7 +1996,7 @@ pub fn if_else(expr: TypedExpr, t: TypedExpr, f: TypedExpr) -> TypedExpr { TypedExpr::new(IfElse(Box::new(expr), Box::new(t), Box::new(f))) } #[cfg(test)] -pub fn paren(expr : TypedExpr) -> TypedExpr { +pub fn paren(expr: TypedExpr) -> TypedExpr { TypedExpr::new(Paren(Box::new(expr))) } @@ -1620,10 +2010,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 +2032,213 @@ 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::*; + use crate::module::*; + use crate::renamer::tests::{rename_expr, rename_module}; + use crate::renamer::Name; + use crate::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; + use std::fs::File; + use std::io::Read; + use std::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::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); - - assert_eq!(module.bindings[1].typ.value, int_type()); -} + let module = do_typecheck(file); -#[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_(Type::new_var(intern("a")), 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 +2246,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::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"); + } -#[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 +2293,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 +2320,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::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"); + } -#[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 +2357,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 +2388,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 +2435,19 @@ instance Functor Maybe where add2 x = primIntAdd x 2 main = fmap add2 (Just 3)"; - 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() { + let module = do_typecheck(file); - 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 +2458,56 @@ 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_(Type::new_var(intern("a")), Type::new_var(intern("a"))) + ); + } + + #[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 +2516,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::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" 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::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" 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::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" 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::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" import Prelude newtype Even = Even Int @@ -2207,75 +2675,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![], function_type_(int_type(), Type::new_op(intern("Even"), vec![])))); -} - - -#[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 +2764,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 5840ed4..8793fe2 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,17 +1,19 @@ +use crate::interner::{intern, InternedStr}; use std::collections::HashMap; use std::default::Default; use std::fmt; use std::iter; -use crate::interner::{InternedStr, intern}; #[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,57 +22,82 @@ 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) + 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: constraints, + value: typ, + } } impl TypeVariable { - pub fn new(id : VarId) -> TypeVariable { + pub fn new(id: VarId) -> TypeVariable { TypeVariable::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) -> TypeVariable { + TypeVariable { + id: id, + kind: kind, + age: 0, + } } } -impl > Type { - +impl> Type { ///Creates a new type variable with the specified id - pub fn new_var(id : VarId) -> Type { + pub fn new_var(id: VarId) -> Type { Type::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>) -> Type { + Type::new_type_kind( + Type::Variable(TypeVariable { + id: 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 { + pub fn new_var_kind(id: VarId, kind: Kind) -> Type { Type::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>) -> Type { + Type::new_type_kind( + Type::Constructor(TypeConstructor { + name: 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) -> Type { + let mut result = Type::Constructor(TypeConstructor { + name: name, + kind: kind, + }); for typ in types.into_iter() { result = Type::Application(Box::new(result), Box::new(typ)); } @@ -88,7 +115,7 @@ impl > Type { pub fn var(&self) -> &TypeVariable { match self { &Type::Variable(ref var) => var, - _ => panic!("Tried to unwrap {} as a TypeVariable", self) + _ => panic!("Tried to unwrap {} as a TypeVariable", self), } } @@ -97,7 +124,7 @@ impl > Type { pub fn ctor(&self) -> &TypeConstructor { match self { &Type::Constructor(ref op) => op, - _ => panic!("Tried to unwrap {} as a TypeConstructor", self) + _ => panic!("Tried to unwrap {} as a TypeConstructor", self), } } @@ -106,7 +133,7 @@ impl > Type { pub fn appl(&self) -> &Type { match self { &Type::Application(ref lhs, _) => &**lhs, - _ => panic!("Error: Tried to unwrap {} as TypeApplication", self) + _ => panic!("Error: Tried to unwrap {} as TypeApplication", self), } } #[allow(dead_code)] @@ -114,7 +141,7 @@ impl > Type { pub fn appr(&self) -> &Type { match self { &Type::Application(_, ref rhs) => &**rhs, - _ => panic!("Error: Tried to unwrap TypeApplication") + _ => panic!("Error: Tried to unwrap TypeApplication"), } } @@ -124,12 +151,16 @@ impl > Type { match self { &Type::Variable(ref v) => &v.kind, &Type::Constructor(ref v) => &v.kind, - &Type::Application(ref lhs, _) => + &Type::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 + _ => panic!( + "Type application must have a kind of Kind::Function, {}", + self + ), + } + } + &Type::Generic(ref v) => &v.kind, } } ///Returns a mutable reference to the types kind @@ -137,29 +168,37 @@ impl > Type { 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 + 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, } } } -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 }) + Type::Constructor(TypeConstructor { + name: f(name), + kind: kind, + }) } - Type::Application(lhs, rhs) => Type::Application(Box::new(lhs.map_(f)), Box::new(rhs.map_(f))), - Type::Generic(v) => Type::Generic(v) + Type::Application(lhs, rhs) => { + Type::Application(Box::new(lhs.map_(f)), Box::new(rhs.map_(f))) + } + Type::Generic(v) => Type::Generic(v), } } } @@ -175,7 +214,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() @@ -194,7 +234,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 +273,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,20 +289,20 @@ 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)] pub enum Kind { Function(Box, Box), - Star + 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) + &Kind::Function(ref lhs, ref rhs) => write!(f, "({} -> {})", *lhs, *rhs), } } } @@ -280,7 +323,7 @@ impl Default for Kind { } } -impl Default for Type { +impl Default for Type { fn default() -> Type { Type::Variable(TypeVariable::new(intern("a"))) } @@ -290,13 +333,13 @@ 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 { write!(f, "(")?; @@ -305,10 +348,9 @@ impl > fmt::Display for Qualified< write!(f, "{}, ", constraint)?; } if self.constraints.len() != 0 { - write!(f, ") => {}" , self.value) - } - else { - write!(f, "{}" , self.value) + write!(f, ") => {}", self.value) + } else { + write!(f, "{}", self.value) } } } @@ -324,69 +366,75 @@ 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)> { +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 + Type::Application(ref xx, ref arg) => match **xx { + Type::Constructor(ref op) if "->" == op.name.as_ref() => { + Some((&**arg, &**result)) } - } - _ => None + _ => None, + }, + _ => None, } } - _ => None + _ => None, } } -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; 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) - } - _ => { - 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)) - } + } + 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) + ) } } } } - } + }, } } } -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 +443,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) } - _ => 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 @@ -441,6 +500,6 @@ impl PartialEq> for Type pub fn extract_applied_type(typ: &Type) -> &Type { match *typ { Type::Application(ref lhs, _) => extract_applied_type(&**lhs), - _ => typ + _ => typ, } } diff --git a/src/vm.rs b/src/vm.rs index 408c8ad..732a8fe 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -1,32 +1,32 @@ -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::interner::*; use crate::lambda_lift::do_lambda_lift; +use crate::parser::Parser; use crate::renamer::rename_module; -use crate::vm::primitive::{BuiltinFun, get_builtin}; -use crate::interner::*; +use crate::typecheck::TypeEnvironment; +use crate::vm::primitive::{get_builtin, BuiltinFun}; +use std::cell::{Ref, RefCell, RefMut}; +use std::error::Error; +use std::fmt; +use std::fs::File; +use std::io; +use std::io::Read; +use std::num::Wrapping; +use std::path::Path; +use std::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), } pub enum Node_<'a> { @@ -38,9 +38,9 @@ pub enum Node_<'a> { Indirection(Node<'a>), Constructor(u16, Vec>), Dictionary(InstanceDictionary), - BuiltinFunction(usize, BuiltinFun) + BuiltinFunction(usize, BuiltinFun), } -impl <'a> Clone for Node_<'a> { +impl<'a> Clone for Node_<'a> { fn clone(&self) -> Node_<'a> { match self { &Application(ref func, ref arg) => Application(func.clone(), arg.clone()), @@ -51,20 +51,22 @@ impl <'a> Clone for Node_<'a> { &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(arity, f) => BuiltinFunction(arity, f), } } } #[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>) -> Self { - Self { 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() @@ -73,12 +75,12 @@ impl <'a> Node<'a> { (*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), @@ -92,15 +94,20 @@ impl <'a> fmt::Debug for Node_<'a> { if cons.len() > 0 { 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 +125,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,7 +135,7 @@ impl <'a> fmt::Debug for Node_<'a> { } } &Dictionary(ref dict) => write!(f, "{:?}", dict), - &BuiltinFunction(..) => write!(f, "") + &BuiltinFunction(..) => write!(f, ""), } } } @@ -149,21 +155,24 @@ impl fmt::Debug for DictionaryEntry { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { Self::Function(index) => write!(f, "{:?}", index), - Self::App(ref func, ref arg) => write!(f, "({:?} {:?})", *func, *arg) + 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 { +impl<'a> VM { pub fn new() -> VM { - Self { assembly : vec![], globals: vec![] } + Self { + assembly: vec![], + globals: vec![], + } } ///Adds an assembly to the VM, adding entries to the global table as necessary @@ -186,22 +195,22 @@ impl <'a> VM { 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![]; for v in vals.iter() { - let s = vec!(v.clone()); + let s = vec![v.clone()]; let x = self.deepseq(s, assembly_id); ret.push(Node::new(x)); } Constructor(tag, ret) } - _ => stack[0].borrow().clone() + _ => stack[0].borrow().clone(), } } @@ -218,43 +227,109 @@ impl <'a> VM { 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![]) } else { Constructor(1, vec![]) } }), - IntLT => primitive_int(stack, |l, r| { if l < r { Constructor(0, vec![]) } else { Constructor(1, vec![]) } }), - IntLE => primitive_int(stack, |l, r| { if l <= r { Constructor(0, vec![]) } else { Constructor(1, vec![]) } }), - IntGT => primitive_int(stack, |l, r| { if l > r { Constructor(0, vec![]) } else { Constructor(1, vec![]) } }), - IntGE => primitive_int(stack, |l, r| { if l >= r { Constructor(0, vec![]) } else { Constructor(1, vec![]) } }), - 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![]) } else { Constructor(1, vec![]) } }), - DoubleLT => primitive_float(stack, |l, r| { if l < r { Constructor(0, vec![]) } else { Constructor(1, vec![]) } }), - DoubleLE => primitive_float(stack, |l, r| { if l <= r { Constructor(0, vec![]) } else { Constructor(1, vec![]) } }), - DoubleGT => primitive_float(stack, |l, r| { if l > r { Constructor(0, vec![]) } else { Constructor(1, vec![]) } }), - DoubleGE => primitive_float(stack, |l, r| { if l >= r { Constructor(0, vec![]) } else { Constructor(1, vec![]) } }), + 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![]) + } else { + Constructor(1, vec![]) + } + }), + IntLT => primitive_int(stack, |l, r| { + if l < r { + Constructor(0, vec![]) + } else { + Constructor(1, vec![]) + } + }), + IntLE => primitive_int(stack, |l, r| { + if l <= r { + Constructor(0, vec![]) + } else { + Constructor(1, vec![]) + } + }), + IntGT => primitive_int(stack, |l, r| { + if l > r { + Constructor(0, vec![]) + } else { + Constructor(1, vec![]) + } + }), + IntGE => primitive_int(stack, |l, r| { + if l >= r { + Constructor(0, vec![]) + } else { + Constructor(1, vec![]) + } + }), + 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![]) + } else { + Constructor(1, vec![]) + } + }), + DoubleLT => primitive_float(stack, |l, r| { + if l < r { + Constructor(0, vec![]) + } else { + Constructor(1, vec![]) + } + }), + DoubleLE => primitive_float(stack, |l, r| { + if l <= r { + Constructor(0, vec![]) + } else { + Constructor(1, vec![]) + } + }), + DoubleGT => primitive_float(stack, |l, r| { + if l > r { + Constructor(0, vec![]) + } else { + Constructor(1, vec![]) + } + }), + DoubleGE => primitive_float(stack, |l, r| { + if l >= r { + Constructor(0, vec![]) + } else { + Constructor(1, vec![]) + } + }), 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 +355,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,18 +374,23 @@ 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; } @@ -334,7 +414,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 +424,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,7 +451,7 @@ impl <'a> VM { stack.push(field.clone()); } } - _ => panic!("Expected constructor in Split instruction") + _ => panic!("Expected constructor in Split instruction"), } } Pack(tag, arity) => { @@ -383,7 +465,7 @@ impl <'a> VM { match *stack.last().unwrap().borrow() { Constructor(0, _) => (), Constructor(1, _) => i = Wrapping(address - 1), - _ => () + _ => (), } stack.pop(); } @@ -391,14 +473,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 +492,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 +506,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 +516,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,10 +529,8 @@ 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![] }; @@ -450,13 +539,15 @@ impl <'a> VM { 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))); } @@ -469,7 +560,7 @@ 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))); @@ -478,9 +569,11 @@ impl <'a> VM { 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 +585,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,10 +631,9 @@ 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; @@ -573,15 +679,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 +704,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![]; for field in fields.iter() { match extract_result((*field.borrow()).clone()) { Some(x) => result.push(x), - None => return None + None => return None, } } @@ -614,7 +719,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 +744,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 +763,12 @@ 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::vm::Node_::{Application, BuiltinFunction, Char, Constructor}; + use crate::vm::{Node, Node_, VM}; + use std::fs::File; + use std::io::Read; pub fn get_builtin(i: usize) -> (usize, BuiltinFun) { match i { @@ -670,11 +779,11 @@ 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![]; @@ -683,7 +792,7 @@ mod primitive { panic!("error: {:?}", node) } fn eval<'a>(vm: &'a VM, node: Node<'a>) -> Node<'a> { - static EVALCODE : &'static [Instruction] = &[Eval]; + static EVALCODE: &'static [Instruction] = &[Eval]; let mut temp = vec![]; temp.push(node); vm.execute(&mut temp, EVALCODE, 123); @@ -697,7 +806,7 @@ mod primitive { //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,13 +818,16 @@ 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> { //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![]; @@ -724,15 +836,15 @@ mod primitive { 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) { 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> { @@ -741,7 +853,7 @@ mod primitive { 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 +862,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,7 +875,7 @@ 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() { @@ -773,7 +885,7 @@ mod primitive { args.push(Node::new(Constructor(0, vec![]))); args[1].clone() } - _ => panic!() + _ => panic!(), }; node = temp; } @@ -789,9 +901,9 @@ 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![])) } @@ -800,121 +912,129 @@ mod primitive { #[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; + use crate::interner::*; + use crate::typecheck::TypeEnvironment; + use crate::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) => { - assert!(sc.arity == 0); - let result = vm.evaluate(&*sc.instructions, sc.assembly_id); - extract_result(result) + 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) => { + assert!(sc.arity == 0); + let result = vm.evaluate(&*sc.instructions, sc.assembly_id); + extract_result(result) + } + None => 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![]))); -} + 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 +1049,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 +1070,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![]))); -} + 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 +1205,15 @@ test (True:y:ys) = y test [] = False main = test [True, True] -") - .unwrap(); - assert_eq!(result, Some(VMResult::Constructor(0, vec![]))); -} -#[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 +1225,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 +1252,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 +1280,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![]))); -} -#[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 +1312,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![]))); -} + 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![]))); -} -#[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![]))); -} +", + ) + .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![]))); -} -#[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![]))); -} +", + ) + .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 +1387,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 +1407,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 +1432,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))); + } } From 3e7e2c63ce4a922088536d2e5b1654bc4f262079 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 10:33:04 -0800 Subject: [PATCH 03/76] stuff --- src/vm.rs | 85 ++++++++++--------------------------------------------- 1 file changed, 15 insertions(+), 70 deletions(-) diff --git a/src/vm.rs b/src/vm.rs index 732a8fe..70fdefe 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -1,5 +1,6 @@ use crate::compiler::*; use crate::core::translate::translate_module; +use crate::core::Constructor; use crate::interner::*; use crate::lambda_lift::do_lambda_lift; use crate::parser::Parser; @@ -222,6 +223,10 @@ 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() { @@ -232,81 +237,21 @@ impl<'a> VM { 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![]) - } else { - Constructor(1, vec![]) - } - }), - IntLT => primitive_int(stack, |l, r| { - if l < r { - Constructor(0, vec![]) - } else { - Constructor(1, vec![]) - } - }), - IntLE => primitive_int(stack, |l, r| { - if l <= r { - Constructor(0, vec![]) - } else { - Constructor(1, vec![]) - } - }), - IntGT => primitive_int(stack, |l, r| { - if l > r { - Constructor(0, vec![]) - } else { - Constructor(1, vec![]) - } - }), - IntGE => primitive_int(stack, |l, r| { - if l >= r { - Constructor(0, vec![]) - } else { - Constructor(1, vec![]) - } - }), + 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| { - if l == r { - Constructor(0, vec![]) - } else { - Constructor(1, vec![]) - } - }), - DoubleLT => primitive_float(stack, |l, r| { - if l < r { - Constructor(0, vec![]) - } else { - Constructor(1, vec![]) - } - }), - DoubleLE => primitive_float(stack, |l, r| { - if l <= r { - Constructor(0, vec![]) - } else { - Constructor(1, vec![]) - } - }), - DoubleGT => primitive_float(stack, |l, r| { - if l > r { - Constructor(0, vec![]) - } else { - Constructor(1, vec![]) - } - }), - DoubleGE => primitive_float(stack, |l, r| { - if l >= r { - Constructor(0, vec![]) - } else { - Constructor(1, vec![]) - } - }), + 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() { From 1eede12d408fbc4996747a1cadbe72e229c32b61 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 10:38:06 -0800 Subject: [PATCH 04/76] refactoring --- src/core.rs | 14 +++++++------- src/deriving.rs | 2 +- src/parser.rs | 6 +++--- src/renamer.rs | 40 +++++++++++++++++++--------------------- src/types.rs | 49 +++++++++++++++++++++---------------------------- 5 files changed, 51 insertions(+), 60 deletions(-) diff --git a/src/core.rs b/src/core.rs index e3b0c6c..0dff87f 100644 --- a/src/core.rs +++ b/src/core.rs @@ -194,7 +194,7 @@ impl fmt::Display for Id { impl Id { pub fn new(name: T, typ: TcType, constraints: Vec>) -> Id { Id { - name: name, + name, typ: module::qualified(constraints, typ), } } @@ -377,7 +377,7 @@ pub mod result { ) -> Binding { let Binding { name, expression } = binding; Binding { - name: name, + name, expression: visitor.visit_expr(expression), } } @@ -508,10 +508,10 @@ pub mod translate { bindings, } = class; Class { - constraints: constraints, - name: name, - variable: variable, - declarations: declarations, + constraints, + name, + variable, + declarations, bindings: translator.translate_bindings(bindings), } }) @@ -1083,7 +1083,7 @@ pub mod translate { expr = make_lambda(arg_ids.into_iter(), expr); debug!("Desugared {} :: {}\n {}", name.name, name.typ, expr); Binding { - name: name, + name, expression: expr, } } diff --git a/src/deriving.rs b/src/deriving.rs index 964eb1e..ace7fe2 100644 --- a/src/deriving.rs +++ b/src/deriving.rs @@ -155,7 +155,7 @@ impl DerivingGen { let constraints = make_constraints(vec![], intern(class), &data.typ.value); Binding { name: Id::new( - Name { name: name, uid: 0 }, + Name { name, uid: 0 }, lambda_expr.get_type().clone(), constraints, ), diff --git a/src/parser.rs b/src/parser.rs index f365a56..e00d2e5 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -679,7 +679,7 @@ impl> Parser { let typ = self.constructor_type(&mut arity, data_def)?; self.lexer.backtrack(); Ok(Constructor { - name: name, + name, typ: qualified(vec![], typ), tag: 0, arity: arity, @@ -919,7 +919,7 @@ impl> Parser { expect!(self, TYPEDECL); let (context, typ) = self.constrained_type()?; Ok(TypeDeclaration { - name: name, + name, typ: Qualified { constraints: context, value: typ, @@ -1043,7 +1043,7 @@ impl> Parser { fn data_lhs(&mut self) -> ParseResult { let name = expect!(self, NAME).value.clone(); let mut typ = Type::Constructor(TypeConstructor { - name: name, + name, kind: Kind::Star.clone(), }); while self.lexer.next().token == NAME { diff --git a/src/renamer.rs b/src/renamer.rs index 6eadd44..07992f3 100644 --- a/src/renamer.rs +++ b/src/renamer.rs @@ -627,7 +627,7 @@ fn rename_module_( Class { constraints: constraints2, name: renamer.get_name(name), - variable: variable, + variable, declarations: renamer.rename_type_declarations(declarations), bindings: renamer.rename_bindings(bindings, true), } @@ -636,29 +636,27 @@ fn rename_module_( 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: assoc, - precedence: precedence, - operators: ops, - } - }, - ) - .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)).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, data_definitions: data_definitions2, diff --git a/src/types.rs b/src/types.rs index 8793fe2..7ce136c 100644 --- a/src/types.rs +++ b/src/types.rs @@ -43,35 +43,31 @@ pub fn qualified( typ: Type, ) -> Qualified, Ident> { Qualified { - constraints: constraints, + constraints, value: typ, } } impl TypeVariable { - pub fn new(id: VarId) -> TypeVariable { - TypeVariable::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(id: VarId) -> Self { + Self::new_var_kind(id, Kind::Star) + } + pub fn new_var_kind(id: VarId, kind: Kind) -> Self { + Self { id, kind, age: 0 } } } 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( + pub fn new_var_args(id: VarId, types: Vec) -> Self { + Self::new_type_kind( Type::Variable(TypeVariable { - id: id, + id, kind: Kind::Star, age: 0, }), @@ -79,31 +75,28 @@ impl> Type { ) } ///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( + pub fn new_op(name: Id, types: Vec>) -> Self { + Self::new_type_kind( Type::Constructor(TypeConstructor { - name: name, + 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 } - 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)); @@ -130,7 +123,7 @@ impl> Type { ///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), @@ -138,7 +131,7 @@ impl> Type { } #[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"), From 2c330728363c94ba428226340afd410230f2dad7 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 10:45:07 -0800 Subject: [PATCH 05/76] refactored repeated variable names in construcotrs --- src/compiler.rs | 8 +++--- src/core.rs | 10 +++---- src/module.rs | 4 +-- src/parser.rs | 52 ++++++++++++++++++------------------ src/renamer.rs | 69 +++++++++++++++++++++++------------------------- src/typecheck.rs | 16 +++++------ src/types.rs | 2 +- 7 files changed, 77 insertions(+), 84 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index bb34c30..2fd08c5 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -443,7 +443,7 @@ impl<'a> Compiler<'a> { stack_size: 0, assemblies: vec![], module: None, - variables: variables, + variables, context: vec![], } } @@ -499,7 +499,7 @@ impl<'a> Compiler<'a> { ) }) .collect(), - data_definitions: data_definitions, + data_definitions, } } @@ -536,8 +536,8 @@ impl<'a> Compiler<'a> { assembly_id: self.assemblies.len(), typ: bind.name.typ.clone(), name: bind.name.name, - arity: arity, - instructions: instructions, + arity, + instructions, } } diff --git a/src/core.rs b/src/core.rs index 0dff87f..b54a32d 100644 --- a/src/core.rs +++ b/src/core.rs @@ -529,9 +529,9 @@ pub mod translate { .into_iter() .collect(); new_instances.push(Instance { - constraints: constraints, - typ: typ, - classname: classname, + constraints, + typ, + classname, bindings: bs, }); } @@ -553,8 +553,8 @@ pub mod translate { } Module { classes: classes2, - data_definitions: data_definitions, - newtypes: newtypes, + data_definitions, + newtypes, bindings: bs, instances: new_instances, } diff --git a/src/module.rs b/src/module.rs index fe0f67d..b5f0d0d 100644 --- a/src/module.rs +++ b/src/module.rs @@ -125,7 +125,7 @@ impl> fmt::Display for TypedExpr { impl TypedExpr { pub fn new>(expr: Expr) -> TypedExpr { TypedExpr { - expr: expr, + expr, typ: Type::new_var(intern("a")), location: Location { column: -1, @@ -139,7 +139,7 @@ impl TypedExpr { loc: Location, ) -> TypedExpr { TypedExpr { - expr: expr, + expr, typ: Type::new_var(intern("a")), location: loc, } diff --git a/src/parser.rs b/src/parser.rs index e00d2e5..37b395c 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -211,14 +211,14 @@ impl> Parser { 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, + imports, + bindings, + type_declarations, + classes, + instances, + data_definitions, + newtypes, + fixity_declarations, }) } @@ -241,7 +241,7 @@ impl> Parser { }; Ok(Import { module: module_name, - imports: imports, + imports, }) } @@ -286,11 +286,11 @@ impl> Parser { Type::Application(l, r) => match (*l, *r) { (Type::Constructor(classname), Type::Variable(var)) => { return Ok(Class { - constraints: constraints, + constraints, name: classname.name, variable: var, - declarations: declarations, - bindings: bindings, + declarations, + bindings, }); } _ => (), @@ -326,9 +326,9 @@ impl> Parser { expect!(self, RBRACE); Ok(Instance { typ: *arg, - classname: classname, - bindings: bindings, - constraints: constraints, + classname, + bindings, + constraints, }) } _ => return self.error("TypeVariable in instance".to_string()), @@ -360,7 +360,7 @@ impl> Parser { TypeSig( Box::new(expr), Qualified { - constraints: constraints, + constraints, value: typ, }, ), @@ -599,8 +599,8 @@ impl> Parser { }; Ok(Alternative { pattern: pat, - matches: matches, - where_bindings: where_bindings, + matches, + where_bindings, }) } @@ -682,7 +682,7 @@ impl> Parser { name, typ: qualified(vec![], typ), tag: 0, - arity: arity, + arity, }) } @@ -718,9 +718,9 @@ impl> Parser { Ok(Binding { name: name.clone(), typ: Default::default(), - arguments: arguments, - where_bindings: where_bindings, - matches: matches, + arguments, + where_bindings, + matches, }) } @@ -769,9 +769,9 @@ impl> Parser { }; let operators = self.sep_by_1(|this| Ok(expect!(this, OPERATOR).value), COMMA)?; Ok(FixityDeclaration { - assoc: assoc, - precedence: precedence, - operators: operators, + assoc, + precedence, + operators, }) } @@ -853,7 +853,7 @@ impl> Parser { let location = self.lexer.next().location; self.lexer.backtrack(); self.pattern().map(|pattern| Located { - location: location, + location, node: pattern, }) } diff --git a/src/renamer.rs b/src/renamer.rs index 07992f3..fd70d0b 100644 --- a/src/renamer.rs +++ b/src/renamer.rs @@ -352,7 +352,7 @@ impl Renamer { DoBind(pattern, expr) => { let Located { location, node } = pattern; let loc = Located { - location: location, + location, node: self.rename_pattern(node), }; DoBind(loc, self.rename(expr)) @@ -431,7 +431,7 @@ impl Renamer { .into_iter() .map(|Constraint { class, variables }| Constraint { class: self.get_name(class), - variables: variables, + variables, }) .collect(); qualified(constraints2, self.rename_type(typ)) @@ -509,20 +509,19 @@ fn rename_module_( 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)).collect(); - is - }); - Import { - module: import.module, - imports: imports, - } - }) - .collect(); + 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() @@ -545,8 +544,8 @@ fn rename_module_( Constructor { name: renamer.get_name(name), typ: renamer.rename_qualified_type(typ), - tag: tag, - arity: arity, + tag, + arity, } }) .collect(); @@ -554,7 +553,7 @@ fn rename_module_( DataDefinition { typ: renamer.rename_qualified_type(typ), - parameters: parameters, + parameters, constructors: c, deriving: d, } @@ -572,7 +571,7 @@ fn rename_module_( } = newtype; let deriving2: Vec = deriving.into_iter().map(|s| renamer.get_name(s)).collect(); Newtype { - typ: typ, + typ, constructor_name: renamer.get_name(constructor_name), constructor_type: renamer.rename_qualified_type(constructor_type), deriving: deriving2, @@ -589,14 +588,13 @@ fn rename_module_( typ, classname, } = instance; - let constraints2: Vec> = - constraints - .into_iter() - .map(|Constraint { class, variables }| Constraint { - class: renamer.get_name(class), - variables: variables, - }) - .collect(); + 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, @@ -616,14 +614,13 @@ fn rename_module_( declarations, bindings, } = class; - let constraints2: Vec> = - constraints - .into_iter() - .map(|Constraint { class, variables }| Constraint { - class: renamer.get_name(class), - variables: variables, - }) - .collect(); + let constraints2: Vec> = constraints + .into_iter() + .map(|Constraint { class, variables }| Constraint { + class: renamer.get_name(class), + variables, + }) + .collect(); Class { constraints: constraints2, name: renamer.get_name(name), diff --git a/src/typecheck.rs b/src/typecheck.rs index 887e6af..a63cb59 100644 --- a/src/typecheck.rs +++ b/src/typecheck.rs @@ -615,11 +615,7 @@ impl<'a> TypeEnvironment<'a> { 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' @@ -1584,7 +1580,7 @@ fn unify_location( location: location.clone(), lhs: lhs.clone(), rhs: rhs.clone(), - error: error, + error, }), } } @@ -1789,7 +1785,7 @@ fn match_or_fail( location: location.clone(), lhs: lhs.clone(), rhs: rhs.clone(), - error: error, + error, }), } } @@ -1883,9 +1879,9 @@ fn add_edges( } } EdgeVisitor { - graph: graph, - map: map, - function_index: function_index, + graph, + map, + function_index, } .visit_expr(expr) } diff --git a/src/types.rs b/src/types.rs index 7ce136c..f408898 100644 --- a/src/types.rs +++ b/src/types.rs @@ -185,7 +185,7 @@ impl Type { Type::Constructor(TypeConstructor { name, kind }) => { Type::Constructor(TypeConstructor { name: f(name), - kind: kind, + kind, }) } Type::Application(lhs, rhs) => { From 02c5a83bfc209ca2277e33b7244bf3e816909cf2 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 10:48:07 -0800 Subject: [PATCH 06/76] refactoring --- src/compiler.rs | 4 ++-- src/core.rs | 2 +- src/deriving.rs | 4 ++-- src/graph.rs | 4 ++-- src/infix.rs | 4 ++-- src/interner.rs | 4 ++-- src/lexer.rs | 2 +- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index 2fd08c5..c4b4238 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -482,8 +482,8 @@ impl<'a> Compiler<'a> { } self.module = None; Assembly { - super_combinators: super_combinators, - instance_dictionaries: instance_dictionaries, + super_combinators, + instance_dictionaries, offset: self .assemblies .iter() diff --git a/src/core.rs b/src/core.rs index b54a32d..b44c370 100644 --- a/src/core.rs +++ b/src/core.rs @@ -914,7 +914,7 @@ pub mod translate { let n = Name { name: intern(name.as_ref()), - uid: uid, + uid, }; Some(module::Pattern::Identifier(n)) } diff --git a/src/deriving.rs b/src/deriving.rs index ace7fe2..a9af24e 100644 --- a/src/deriving.rs +++ b/src/deriving.rs @@ -22,7 +22,7 @@ pub fn generate_deriving(instances: &mut Vec>>, data: &DataDef name: intern("Eq"), uid: 0, }, - bindings: bindings, + bindings, }); } "Ord" => { @@ -37,7 +37,7 @@ pub fn generate_deriving(instances: &mut Vec>>, data: &DataDef name: intern("Ord"), uid: 0, }, - bindings: bindings, + bindings, }); } x => panic!("Cannot generate instance for class {:?}", x), diff --git a/src/graph.rs b/src/graph.rs index d2e377e..9f5786b 100644 --- a/src/graph.rs +++ b/src/graph.rs @@ -47,7 +47,7 @@ impl Graph { pub fn new_vertex(&mut self, value: T) -> VertexIndex { self.vertices.push(Vertex { edges: vec![], - value: value, + value, }); VertexIndex(self.vertices.len() - 1) } @@ -79,7 +79,7 @@ impl Graph { ///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, + graph, index: 1, stack: vec![], connections: vec![], diff --git a/src/infix.rs b/src/infix.rs index 53ff2ff..ebf8199 100644 --- a/src/infix.rs +++ b/src/infix.rs @@ -114,8 +114,8 @@ impl PrecedenceVisitor { } rhs => { let mut result = TypedExpr { - typ: typ, - location: location, + typ, + location, expr: rhs, }; while op_stack.len() != 0 { diff --git a/src/interner.rs b/src/interner.rs index 35ebf59..987ebb8 100644 --- a/src/interner.rs +++ b/src/interner.rs @@ -13,8 +13,8 @@ pub struct Interner { } impl Interner { - pub fn new() -> Interner { - Interner { + pub fn new() -> Self { + Self { indexes: HashMap::new(), strings: vec![], } diff --git a/src/lexer.rs b/src/lexer.rs index b3affdd..ae1e1c3 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -120,7 +120,7 @@ impl Token { loc: Location, ) -> Token { Token { - token: token, + token, value: (**interner).borrow_mut().intern(value), location: loc, } From 2dde2236852da5897e8216bbe9054e89bbe2ee49 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 10:52:17 -0800 Subject: [PATCH 07/76] use Self --- src/compiler.rs | 4 ++-- src/graph.rs | 4 ++-- src/infix.rs | 4 ++-- src/lexer.rs | 27 +++++++++++---------------- src/parser.rs | 4 ++-- src/renamer.rs | 8 ++++---- src/scoped_map.rs | 4 ++-- src/types.rs | 19 +++++++------------ 8 files changed, 32 insertions(+), 42 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index c4b4238..7b2b193 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -409,7 +409,7 @@ pub struct Compiler<'a> { } impl<'a> Compiler<'a> { - pub fn new() -> Compiler<'a> { + pub fn new() -> Self { let mut variables = ScopedMap::new(); for (i, &(name, _)) in builtins().iter().enumerate() { variables.insert( @@ -438,7 +438,7 @@ impl<'a> Compiler<'a> { Var::Primitive(1, instruction), ); } - Compiler { + Self { instance_dictionaries: vec![], stack_size: 0, assemblies: vec![], diff --git a/src/graph.rs b/src/graph.rs index 9f5786b..5a4cbcf 100644 --- a/src/graph.rs +++ b/src/graph.rs @@ -37,8 +37,8 @@ pub struct Graph { impl Graph { ///Creates a new graph - pub fn new() -> Graph { - Graph { + pub fn new() -> Self { + Self { edges: vec![], vertices: vec![], } diff --git a/src/infix.rs b/src/infix.rs index ebf8199..dae9cf7 100644 --- a/src/infix.rs +++ b/src/infix.rs @@ -34,7 +34,7 @@ impl MutVisitor for PrecedenceVisitor { } } impl PrecedenceVisitor { - pub fn new() -> PrecedenceVisitor { + pub fn new() -> Self { let mut map = HashMap::new(); map.insert( Name { @@ -43,7 +43,7 @@ impl PrecedenceVisitor { }, (5, Assoc::Right), ); - PrecedenceVisitor { precedence: map } + Self { precedence: map } } fn get_precedence(&self, name: &Name) -> (isize, Assoc) { diff --git a/src/lexer.rs b/src/lexer.rs index ae1e1c3..584241a 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -62,8 +62,8 @@ pub struct Location { } impl Location { - pub fn eof() -> Location { - Location { + pub fn eof() -> Self { + Self { column: -1, row: -1, absolute: -1, @@ -101,8 +101,8 @@ pub struct Token { pub location: Location, } impl Token { - fn eof() -> Token { - Token { + fn eof() -> Self { + Self { token: EOF, value: intern(""), location: Location { @@ -113,13 +113,8 @@ impl Token { } } - fn new( - interner: &Rc>, - token: TokenEnum, - value: &str, - loc: Location, - ) -> Token { - Token { + fn new(interner: &Rc>, token: TokenEnum, value: &str, loc: Location) -> Self { + Self { token, value: (**interner).borrow_mut().intern(value), location: loc, @@ -127,8 +122,8 @@ impl Token { } #[cfg(test)] - fn new_(token: TokenEnum, value: &str) -> Token { - Token::new( + fn new_(token: TokenEnum, value: &str) -> Self { + Self::new( &get_local_interner(), token, value, @@ -142,7 +137,7 @@ impl Token { } impl PartialEq for Token { - fn eq(&self, rhs: &Token) -> bool { + fn eq(&self, rhs: &Self) -> bool { self.token == rhs.token && self.value == rhs.value } } @@ -200,13 +195,13 @@ pub struct Lexer> { impl> Lexer { ///Constructs a new lexer with a default sized token buffer and the local string interner - pub fn new(input: Stream) -> Lexer { + pub fn new(input: Stream) -> Self { let start = Location { column: 0, row: 0, absolute: 0, }; - Lexer { + Self { input: input.peekable(), location: start, unprocessed_tokens: vec![], diff --git a/src/parser.rs b/src/parser.rs index 37b395c..4e8d97e 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -113,8 +113,8 @@ macro_rules! unexpected ( ); impl> Parser { - pub fn new(iterator: Iter) -> Parser { - Parser { + pub fn new(iterator: Iter) -> Self { + Self { lexer: Lexer::new(iterator), } } diff --git a/src/renamer.rs b/src/renamer.rs index fd70d0b..d734f3d 100644 --- a/src/renamer.rs +++ b/src/renamer.rs @@ -53,8 +53,8 @@ pub struct Errors { errors: Vec, } impl Errors { - pub fn new() -> Errors { - Errors { errors: vec![] } + pub fn new() ->Self { + Self { errors: vec![] } } pub fn insert(&mut self, e: T) { self.errors.push(e); @@ -161,8 +161,8 @@ struct Renamer { } impl Renamer { - fn new() -> Renamer { - Renamer { + fn new() -> Self { + Self { uniques: ScopedMap::new(), name_supply: NameSupply::new(), errors: Errors::new(), diff --git a/src/scoped_map.rs b/src/scoped_map.rs index c8bf4ea..5b5db80 100644 --- a/src/scoped_map.rs +++ b/src/scoped_map.rs @@ -20,8 +20,8 @@ impl ScopedMap where K: Eq + Hash + Clone, { - pub fn new() -> ScopedMap { - ScopedMap { + pub fn new() -> Self { + Self { map: HashMap::new(), scopes: vec![], } diff --git a/src/types.rs b/src/types.rs index f408898..1b15ed7 100644 --- a/src/types.rs +++ b/src/types.rs @@ -286,9 +286,10 @@ pub struct Constraint { pub variables: Vec, } -#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Debug, PartialEq, Eq, Hash, Default)] pub enum Kind { Function(Box, Box), + #[default] Star, } impl fmt::Display for Kind { @@ -301,24 +302,18 @@ impl fmt::Display for Kind { } 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(Box::new(Self::Star), Box::new(kind)); } kind } } -impl Default for Kind { - fn default() -> Kind { - Kind::Star - } -} - impl Default for Type { - fn default() -> Type { - Type::Variable(TypeVariable::new(intern("a"))) + fn default() -> Self { + Self::Variable(TypeVariable::new(intern("a"))) } } impl fmt::Display for TypeVariable { From 767aa3efa6d12aea6969f757f8c6ea62961ea02a Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 10:55:57 -0800 Subject: [PATCH 08/76] refactoring --- src/core.rs | 4 ++-- src/renamer.rs | 6 +++--- src/typecheck.rs | 4 ++-- src/vm.rs | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/core.rs b/src/core.rs index b44c370..a7ed141 100644 --- a/src/core.rs +++ b/src/core.rs @@ -192,8 +192,8 @@ impl fmt::Display for Id { } impl Id { - pub fn new(name: T, typ: TcType, constraints: Vec>) -> Id { - Id { + pub fn new(name: T, typ: TcType, constraints: Vec>) -> Self { + Self { name, typ: module::qualified(constraints, typ), } diff --git a/src/renamer.rs b/src/renamer.rs index d734f3d..683c08e 100644 --- a/src/renamer.rs +++ b/src/renamer.rs @@ -53,7 +53,7 @@ pub struct Errors { errors: Vec, } impl Errors { - pub fn new() ->Self { + pub fn new() -> Self { Self { errors: vec![] } } pub fn insert(&mut self, e: T) { @@ -121,8 +121,8 @@ pub struct NameSupply { 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 { diff --git a/src/typecheck.rs b/src/typecheck.rs index a63cb59..07c7ee0 100644 --- a/src/typecheck.rs +++ b/src/typecheck.rs @@ -275,7 +275,7 @@ fn add_primitives(globals: &mut HashMap>, typename 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"); @@ -306,7 +306,7 @@ impl<'a> TypeEnvironment<'a> { let (name, typ) = typ::tuple_type(i); insert_to(&mut globals, name.as_ref(), typ); } - TypeEnvironment { + Self { assemblies: vec![], named_types: globals, local_types: HashMap::new(), diff --git a/src/vm.rs b/src/vm.rs index 70fdefe..e6c83c2 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -169,7 +169,7 @@ pub struct VM { } impl<'a> VM { - pub fn new() -> VM { + pub fn new() -> Self { Self { assembly: vec![], globals: vec![], From 0ad80bd7c90fa96f65cdff3f6348fc1b2a2c211b Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 10:58:31 -0800 Subject: [PATCH 09/76] use Self --- src/core.rs | 20 ++++++++++---------- src/module.rs | 8 ++++---- src/types.rs | 38 +++++++++++++++++++------------------- 3 files changed, 33 insertions(+), 33 deletions(-) diff --git a/src/core.rs b/src/core.rs index a7ed141..c548bbd 100644 --- a/src/core.rs +++ b/src/core.rs @@ -143,9 +143,9 @@ 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!( @@ -154,9 +154,9 @@ impl> Typed for Expr { ), } } - &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(), } } } @@ -164,10 +164,10 @@ 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) => name.get_type(), + Self::Constructor(ref name, _) => name.get_type(), + Self::Number(_) => panic!(), + Self::WildCard => panic!(), } } } diff --git a/src/module.rs b/src/module.rs index b5f0d0d..2b08b58 100644 --- a/src/module.rs +++ b/src/module.rs @@ -250,16 +250,16 @@ impl> fmt::Display for Expr { 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, "_"), } } } diff --git a/src/types.rs b/src/types.rs index 1b15ed7..d99fcdc 100644 --- a/src/types.rs +++ b/src/types.rs @@ -79,7 +79,7 @@ impl> Type { 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>) -> Self { + pub fn new_op(name: Id, types: Vec) -> Self { Self::new_type_kind( Type::Constructor(TypeConstructor { name, @@ -107,7 +107,7 @@ 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, + &Self::Variable(ref var) => var, _ => panic!("Tried to unwrap {} as a TypeVariable", self), } } @@ -116,7 +116,7 @@ impl> Type { #[allow(dead_code)] pub fn ctor(&self) -> &TypeConstructor { match self { - &Type::Constructor(ref op) => op, + &Self::Constructor(ref op) => op, _ => panic!("Tried to unwrap {} as a TypeConstructor", self), } } @@ -125,7 +125,7 @@ impl> Type { #[allow(dead_code)] pub fn appl(&self) -> &Self { match self { - &Type::Application(ref lhs, _) => &**lhs, + &Self::Application(ref lhs, _) => &**lhs, _ => panic!("Error: Tried to unwrap {} as TypeApplication", self), } } @@ -133,7 +133,7 @@ impl> Type { ///Returns a reference to the the type argument or fails if it is not an application pub fn appr(&self) -> &Self { match self { - &Type::Application(_, ref rhs) => &**rhs, + &Self::Application(_, ref rhs) => &**rhs, _ => panic!("Error: Tried to unwrap TypeApplication"), } } @@ -142,9 +142,9 @@ 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!( @@ -153,19 +153,19 @@ impl> Type { ), } } - &Type::Generic(ref v) => &v.kind, + &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() { + 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) => &mut **kind, _ => panic!("Type application must have a kind of Kind::Function"), }, - Type::Generic(ref mut v) => &mut v.kind, + Self::Generic(ref mut v) => &mut v.kind, } } } @@ -181,17 +181,17 @@ impl Type { F: FnMut(Id) -> Id2, { match self { - Type::Variable(v) => Type::Variable(v), - Type::Constructor(TypeConstructor { name, kind }) => { + Self::Variable(v) => Type::Variable(v), + Self::Constructor(TypeConstructor { name, kind }) => { Type::Constructor(TypeConstructor { name: f(name), kind, }) } - Type::Application(lhs, rhs) => { + Self::Application(lhs, rhs) => { Type::Application(Box::new(lhs.map_(f)), Box::new(rhs.map_(f))) } - Type::Generic(v) => Type::Generic(v), + Self::Generic(v) => Type::Generic(v), } } } @@ -295,8 +295,8 @@ pub enum Kind { 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), } } } From 9384ee7f8f1c08e4cf2dee7f79ec8d6a3cfe6be5 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 11:02:43 -0800 Subject: [PATCH 10/76] use self --- src/compiler.rs | 18 +++++++++--------- src/core.rs | 11 +++++------ src/module.rs | 16 ++++++++-------- src/renamer.rs | 4 ++-- src/vm.rs | 4 ++-- 5 files changed, 26 insertions(+), 27 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index 7b2b193..7b93e1b 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -102,16 +102,16 @@ static BINARY_PRIMITIVES: &'static [(&'static str, Instruction)] = &[ ]; impl<'a> Clone for Var<'a> { - fn clone(&self) -> Var<'a> { + fn clone(&self) -> Self { 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, + Self::Stack(x) => Self::Stack(x), + Self::Global(x) => Self::Global(x), + Self::Constructor(x, y) => Self::Constructor(x, y), + Self::Class(x, y, z) => Self::Class(x, y, z), + Self::Constraint(x, y, z) => Self::Constraint(x, y, z), + Self::Builtin(x) => Self::Builtin(x), + Self::Primitive(x, y) => Self::Primitive(x, y), + Self::Newtype => Self::Newtype, } } } diff --git a/src/core.rs b/src/core.rs index c548bbd..ae3655a 100644 --- a/src/core.rs +++ b/src/core.rs @@ -119,16 +119,16 @@ impl fmt::Display for Alternative { 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, "_"), } } } @@ -164,8 +164,7 @@ impl Typed for Pattern { type Id = Ident::Id; fn get_type<'a>(&'a self) -> &'a Type { match *self { - Self::Identifier(ref name) => name.get_type(), - Self::Constructor(ref name, _) => name.get_type(), + Self::Identifier(ref name) | Self::Constructor(ref name, _) => name.get_type(), Self::Number(_) => panic!(), Self::WildCard => panic!(), } diff --git a/src/module.rs b/src/module.rs index 2b08b58..6eb3083 100644 --- a/src/module.rs +++ b/src/module.rs @@ -169,8 +169,8 @@ pub enum 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, } } } @@ -272,8 +272,8 @@ impl> fmt::Display for Alternative { 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)?; } @@ -285,10 +285,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), } } } diff --git a/src/renamer.rs b/src/renamer.rs index 683c08e..35d82bf 100644 --- a/src/renamer.rs +++ b/src/renamer.rs @@ -110,8 +110,8 @@ 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), } } } diff --git a/src/vm.rs b/src/vm.rs index e6c83c2..4041131 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -596,8 +596,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)),+ } } } From f596e1b8652b41b15677fe7b6536b16f115e3a8a Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 11:05:22 -0800 Subject: [PATCH 11/76] rust fmt, group imports --- rustfmt.toml | 4 ++ src/builtins.rs | 17 +++++-- src/compiler.rs | 83 +++++++++++++++++++++++----------- src/core.rs | 84 ++++++++++++++++++++++++---------- src/deriving.rs | 22 ++++++--- src/infix.rs | 29 +++++++----- src/interner.rs | 12 ++--- src/lambda_lift.rs | 58 ++++++++++++++++-------- src/lexer.rs | 16 ++++--- src/module.rs | 26 ++++++++--- src/parser.rs | 77 +++++++++++++++++++++++--------- src/renamer.rs | 58 +++++++++++++++++------- src/repl.rs | 27 +++++++---- src/scoped_map.rs | 13 ++++-- src/typecheck.rs | 71 +++++++++++++++++++---------- src/types.rs | 17 ++++--- src/vm.rs | 109 +++++++++++++++++++++++++++++++-------------- 17 files changed, 508 insertions(+), 215 deletions(-) create mode 100644 rustfmt.toml 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 e5784d2..327fe65 100644 --- a/src/builtins.rs +++ b/src/builtins.rs @@ -1,7 +1,16 @@ -use crate::interner::intern; -use crate::renamer::typ::*; -use crate::renamer::{name, Name}; -use crate::types::{Kind, Type, TypeVariable}; +use crate::{ + interner::intern, + 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)> { diff --git a/src/compiler.rs b/src/compiler.rs index 7b93e1b..3d058a6 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -1,16 +1,37 @@ -use crate::core::Expr::*; -use crate::core::*; -use crate::interner::*; -use crate::scoped_map::ScopedMap; -use crate::typecheck::{find_specialized_instances, DataTypes, TypeEnvironment, Types}; -use crate::types::{extract_applied_type, qualified}; -use std::borrow::ToOwned; - -use crate::builtins::builtins; -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::{ + 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::*; @@ -1331,14 +1352,24 @@ fn compile_module_( #[cfg(test)] mod tests { - use crate::compiler::Instruction::*; - use crate::compiler::{compile_with_type_env, Assembly, Compiler}; - use crate::interner::*; - use crate::typecheck::TypeEnvironment; - use std::fs::File; - use std::io::Read; - use std::path::Path; - use test::Bencher; + 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() @@ -1646,10 +1677,12 @@ test = Test [1::Int]"; #[bench] fn bench_prelude(b: &mut Bencher) { - use crate::core::translate::translate_module; - use crate::lambda_lift::do_lambda_lift; - use crate::parser::Parser; - use crate::renamer::tests::rename_module; + 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(); diff --git a/src/core.rs b/src/core.rs index ae3655a..641b9c6 100644 --- a/src/core.rs +++ b/src/core.rs @@ -1,12 +1,36 @@ -use crate::interner::*; -use crate::module; -pub use crate::module::LiteralData::{Char, Fractional, Integral, String}; -pub use crate::module::{Constructor, DataDefinition, Newtype, TypeDeclaration}; -pub use crate::renamer::Name; -use crate::typecheck::TcType; -pub use crate::types::Type::{Application, Variable}; -pub use crate::types::{Constraint, Qualified, Type, TypeVariable}; -use std::fmt; +pub use crate::{ + module::{ + Constructor, + DataDefinition, + LiteralData::{ + Char, + Fractional, + Integral, + String, + }, + Newtype, + TypeDeclaration, + }, + renamer::Name, + types::{ + Constraint, + Qualified, + Type::{ + self, + Application, + Variable, + }, + TypeVariable, + }, +}; +use { + crate::{ + interner::*, + module, + typecheck::TcType, + }, + std::fmt, +}; pub struct Module { pub classes: Vec>, @@ -213,8 +237,10 @@ impl Typed for Id { } pub mod ref_ { - use super::Expr::*; - use super::*; + 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 @@ -273,8 +299,10 @@ pub mod ref_ { } pub mod mutable { - use super::Expr::*; - use super::*; + use super::{ + Expr::*, + *, + }; pub trait Visitor: Sized { fn visit_expr(&mut self, expr: &mut Expr) { @@ -334,8 +362,10 @@ pub mod mutable { } pub mod result { - use super::Expr::*; - use super::*; + 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 @@ -425,14 +455,22 @@ pub mod result { ///The translate module takes the AST and translates it into the simpler core language. pub mod translate { - use crate::core::Expr::*; - use crate::core::*; - use crate::deriving::*; - use crate::module; - use crate::renamer::typ::*; - use crate::renamer::NameSupply; - use crate::typecheck::TcType; - use std::collections::HashMap; + use { + crate::{ + core::{ + Expr::*, + *, + }, + deriving::*, + module, + renamer::{ + typ::*, + NameSupply, + }, + typecheck::TcType, + }, + std::collections::HashMap, + }; struct Translator<'a> { name_supply: NameSupply, diff --git a/src/deriving.rs b/src/deriving.rs index a9af24e..76a7543 100644 --- a/src/deriving.rs +++ b/src/deriving.rs @@ -1,9 +1,19 @@ -use crate::core::Expr::*; -use crate::core::*; -use crate::interner::{intern, InternedStr}; -use crate::module::encode_binding_identifier; -use crate::renamer::typ::*; -use crate::renamer::{name, NameSupply}; +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 = diff --git a/src/infix.rs b/src/infix.rs index dae9cf7..ceef99c 100644 --- a/src/infix.rs +++ b/src/infix.rs @@ -1,7 +1,11 @@ -use crate::interner::intern; -use crate::module::*; -use crate::renamer::Name; -use std::collections::HashMap; +use { + crate::{ + interner::intern, + module::*, + renamer::Name, + }, + std::collections::HashMap, +}; pub struct PrecedenceVisitor { precedence: HashMap, @@ -136,12 +140,17 @@ impl PrecedenceVisitor { #[cfg(test)] mod tests { - use crate::infix::PrecedenceVisitor; - use crate::interner::intern; - use crate::module::*; - use crate::parser::*; - use crate::renamer::tests::{rename_expr, rename_modules}; - use crate::typecheck::*; + use crate::{ + infix::PrecedenceVisitor, + interner::intern, + module::*, + parser::*, + renamer::tests::{ + rename_expr, + rename_modules, + }, + typecheck::*, + }; #[test] fn operator_precedence() { diff --git a/src/interner.rs b/src/interner.rs index 987ebb8..6f8c163 100644 --- a/src/interner.rs +++ b/src/interner.rs @@ -1,8 +1,10 @@ -use std::cell::RefCell; -use std::collections::HashMap; -use std::fmt; -use std::ops::Deref; -use std::rc::Rc; +use std::{ + cell::RefCell, + collections::HashMap, + fmt, + ops::Deref, + rc::Rc, +}; #[derive(Eq, PartialEq, Clone, Copy, Default, Hash, Debug)] pub struct InternedStr(usize); diff --git a/src/lambda_lift.rs b/src/lambda_lift.rs index a38bc93..caf5481 100644 --- a/src/lambda_lift.rs +++ b/src/lambda_lift.rs @@ -1,9 +1,19 @@ -use crate::core::Expr::*; -use crate::core::*; -use crate::renamer::typ::*; -use crate::renamer::NameSupply; -use std::collections::hash_map::Entry; -use std::collections::HashMap; +use { + crate::{ + core::{ + Expr::*, + *, + }, + renamer::{ + typ::*, + NameSupply, + }, + }, + std::collections::{ + hash_map::Entry, + HashMap, + }, +}; pub type TypeAndStr = Id; @@ -224,15 +234,21 @@ pub fn abstract_module(mut module: Module) -> Module { #[cfg(test)] mod tests { - use crate::core::ref_::*; - use crate::core::translate::translate_module; - use crate::interner::*; - use crate::lambda_lift::*; - use crate::parser::Parser; - use crate::renamer::tests::rename_module; - use crate::typecheck::TypeEnvironment; - use std::collections::HashSet; - use test::Bencher; + 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, @@ -399,10 +415,14 @@ test2 x = #[bench] fn bench(b: &mut Bencher) { - use crate::typecheck::test::do_typecheck; - use std::fs::File; - use std::io::Read; - use std::path::Path; + 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(); diff --git a/src/lexer.rs b/src/lexer.rs index 584241a..5b89959 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -1,9 +1,13 @@ -use crate::interner::*; -use std::cell::RefCell; -use std::collections::VecDeque; -use std::fmt; -use std::iter::Peekable; -use std::rc::Rc; +use { + crate::interner::*, + std::{ + cell::RefCell, + collections::VecDeque, + fmt, + iter::Peekable, + rc::Rc, + }, +}; use self::TokenEnum::*; diff --git a/src/module.rs b/src/module.rs index 6eb3083..71f9f8d 100644 --- a/src/module.rs +++ b/src/module.rs @@ -1,9 +1,23 @@ -use crate::interner::{intern, InternedStr}; -use crate::lexer::{Located, Location}; -pub use crate::types::*; -use std::collections::HashMap; -pub use std::default::Default; -use std::fmt; +pub use { + crate::types::*, + std::default::Default, +}; +use { + crate::{ + interner::{ + intern, + InternedStr, + }, + lexer::{ + Located, + Location, + }, + }, + std::{ + collections::HashMap, + fmt, + }, +}; use self::Expr::*; diff --git a/src/parser.rs b/src/parser.rs index 4e8d97e..25e2fa8 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,17 +1,32 @@ -use crate::interner::*; -use crate::lexer::TokenEnum::*; -use crate::lexer::*; -use crate::module::Expr::*; -use crate::module::LiteralData::*; -use crate::module::*; -use std::collections::{HashMap, HashSet}; -use std::error; -use std::fmt; -use std::fs::File; -use std::io; -use std::io::Read; -use std::mem::swap; -use std::str::FromStr; +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 @@ -1309,14 +1324,32 @@ fn parse_modules_( #[cfg(test)] mod tests { - use crate::interner::*; - use crate::lexer::{Located, Location}; - use crate::parser::*; - use crate::typecheck::{apply, case, identifier, if_else, let_, number, op_apply, rational}; - use std::fs::File; - use std::io::Read; - use std::path::Path; - use test::Bencher; + 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 simple() { diff --git a/src/renamer.rs b/src/renamer.rs index 35d82bf..75e9b4c 100644 --- a/src/renamer.rs +++ b/src/renamer.rs @@ -1,9 +1,15 @@ -use crate::interner::*; -use crate::lexer::Located; -use crate::module::*; -use crate::scoped_map::ScopedMap; -use std::error; -use std::fmt; +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)] @@ -280,8 +286,10 @@ impl Renamer { } fn rename(&mut self, input_expr: TypedExpr) -> TypedExpr { - use crate::module::DoBinding::*; - use crate::module::Expr::*; + use crate::module::{ + DoBinding::*, + Expr::*, + }; let TypedExpr { expr, typ, @@ -687,10 +695,21 @@ pub fn rename_modules( } pub mod typ { - use super::{name, Name}; - use crate::interner::intern; - use crate::types::{Kind, Type, TypeVariable}; - use std::iter::repeat; + 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 { @@ -765,10 +784,17 @@ pub mod typ { #[cfg(test)] pub mod tests { - use super::Name; - use crate::interner::InternedStr; - use crate::module::{Module, TypedExpr}; - 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() diff --git a/src/repl.rs b/src/repl.rs index 62645d9..9b94743 100644 --- a/src/repl.rs +++ b/src/repl.rs @@ -1,14 +1,23 @@ use std::io::BufRead; -use crate::compiler::*; -use crate::core::translate::*; -use crate::core::{Module, Qualified, Type}; -use crate::interner::*; -use crate::lambda_lift::*; -use crate::parser::Parser; -use crate::renamer::{rename_expr, Name}; -use crate::typecheck::*; -use crate::vm::*; +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 { diff --git a/src/scoped_map.rs b/src/scoped_map.rs index 5b5db80..336a90f 100644 --- a/src/scoped_map.rs +++ b/src/scoped_map.rs @@ -1,6 +1,13 @@ -use std::collections::hash_map::{Entry, IterMut}; -use std::collections::HashMap; -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 diff --git a/src/typecheck.rs b/src/typecheck.rs index 07c7ee0..ec5007b 100644 --- a/src/typecheck.rs +++ b/src/typecheck.rs @@ -1,16 +1,30 @@ -use crate::builtins::builtins; -use crate::graph::{strongly_connected_components, Graph, VertexIndex}; -use crate::interner::*; -use crate::lexer::Location; -use crate::module::Expr::*; -use crate::module::LiteralData::*; -use crate::module::*; -use crate::renamer::*; -use std::collections::hash_map::Entry; -use std::collections::HashMap; -use std::error; -use std::fmt; -use std::mem::swap; +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; @@ -2035,16 +2049,27 @@ fn typecheck_modules_common( #[cfg(test)] pub mod test { - use crate::interner::*; - use crate::module::*; - use crate::renamer::tests::{rename_expr, rename_module}; - use crate::renamer::Name; - use crate::typecheck::*; - - use crate::parser::Parser; - use std::fs::File; - use std::io::Read; - use std::path::Path; + use crate::{ + interner::*, + module::*, + renamer::{ + tests::{ + rename_expr, + rename_module, + }, + Name, + }, + typecheck::*, + }; + + use { + crate::parser::Parser, + std::{ + fs::File, + io::Read, + path::Path, + }, + }; use ::test::Bencher; diff --git a/src/types.rs b/src/types.rs index d99fcdc..7c45d3a 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,8 +1,15 @@ -use crate::interner::{intern, InternedStr}; -use std::collections::HashMap; -use std::default::Default; -use std::fmt; -use std::iter; +use { + crate::interner::{ + intern, + InternedStr, + }, + std::{ + collections::HashMap, + default::Default, + fmt, + iter, + }, +}; #[derive(Clone, Debug, Default, Eq, Hash)] pub struct TypeConstructor { diff --git a/src/vm.rs b/src/vm.rs index 4041131..aa5255d 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -1,21 +1,38 @@ -use crate::compiler::*; -use crate::core::translate::translate_module; -use crate::core::Constructor; -use crate::interner::*; -use crate::lambda_lift::do_lambda_lift; -use crate::parser::Parser; -use crate::renamer::rename_module; -use crate::typecheck::TypeEnvironment; -use crate::vm::primitive::{get_builtin, BuiltinFun}; -use std::cell::{Ref, RefCell, RefMut}; -use std::error::Error; -use std::fmt; -use std::fs::File; -use std::io; -use std::io::Read; -use std::num::Wrapping; -use std::path::Path; -use std::rc::Rc; +use { + crate::{ + compiler::*, + core::{ + translate::translate_module, + Constructor, + }, + 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_::*; @@ -580,9 +597,11 @@ pub enum VMResult { } // 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),+) => { @@ -708,12 +727,29 @@ fn execute_main_module_(assemblies: Vec) -> Result, S #[allow(non_snake_case)] mod primitive { - use crate::compiler::Instruction; - use crate::compiler::Instruction::Eval; - use crate::vm::Node_::{Application, BuiltinFunction, Char, Constructor}; - use crate::vm::{Node, Node_, VM}; - use std::fs::File; - use std::io::Read; + 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 { @@ -857,12 +893,19 @@ mod primitive { #[cfg(test)] mod tests { - use crate::compiler::compile_with_type_env; - use crate::interner::*; - use crate::typecheck::TypeEnvironment; - use crate::vm::{ - compile_file, compile_iter, execute_main_module, execute_main_string, extract_result, - VMResult, VM, + 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 { From 4d41415c550cb5894b63feb06ce0a81759467779 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 11:15:11 -0800 Subject: [PATCH 12/76] From<&str> for Name --- src/graph.rs | 6 ++---- src/infix.rs | 12 +++--------- src/renamer.rs | 9 +++++++++ 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/graph.rs b/src/graph.rs index 5a4cbcf..c914c3a 100644 --- a/src/graph.rs +++ b/src/graph.rs @@ -10,14 +10,12 @@ pub struct EdgeIndex(usize); impl VertexIndex { fn get(&self) -> usize { - let VertexIndex(v) = *self; - v + self.0 } } impl EdgeIndex { fn get(&self) -> usize { - let EdgeIndex(v) = *self; - v + self.0 } } diff --git a/src/infix.rs b/src/infix.rs index ceef99c..e3313a4 100644 --- a/src/infix.rs +++ b/src/infix.rs @@ -39,15 +39,9 @@ impl MutVisitor for PrecedenceVisitor { } impl PrecedenceVisitor { pub fn new() -> Self { - let mut map = HashMap::new(); - map.insert( - Name { - uid: 0, - name: intern(":"), - }, - (5, Assoc::Right), - ); - Self { precedence: map } + Self { + precedence: [(":".into(), (5, Assoc::Right))].into_iter().collect(), + } } fn get_precedence(&self, name: &Name) -> (isize, Assoc) { diff --git a/src/renamer.rs b/src/renamer.rs index 75e9b4c..b5b61c9 100644 --- a/src/renamer.rs +++ b/src/renamer.rs @@ -25,6 +25,15 @@ pub fn name(s: &str) -> Name { } } +impl From<&str> for Name { + fn from(s: &str) -> Self { + Self { + uid: 0, + name: intern(s), + } + } +} + impl PartialEq for Name { fn eq(&self, other: &Name) -> bool { self.uid == other.uid && self.name == other.name From 5331b38895855359d83ad0a4daa89561414a90ac Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 11:21:38 -0800 Subject: [PATCH 13/76] From<&str> for Name --- src/compiler.rs | 37 ++++++++----------------------------- src/core.rs | 41 ++++++++--------------------------------- src/deriving.rs | 20 ++++---------------- src/renamer.rs | 5 +---- src/typecheck.rs | 10 ++-------- 5 files changed, 23 insertions(+), 90 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index 3d058a6..5512a77 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -434,28 +434,19 @@ impl<'a> Compiler<'a> { let mut variables = ScopedMap::new(); for (i, &(name, _)) in builtins().iter().enumerate() { variables.insert( - Name { - name: intern(name), - uid: 0, - }, + name.into(), Var::Builtin(i), ); } for &(name, instruction) in BINARY_PRIMITIVES.iter() { variables.insert( - Name { - name: intern(name), - uid: 0, - }, + name.into(), Var::Primitive(2, instruction), ); } for &(name, instruction) in UNARY_PRIMITIVES.iter() { variables.insert( - Name { - name: intern(name), - uid: 0, - }, + name.into(), Var::Primitive(1, instruction), ); } @@ -536,10 +527,7 @@ impl<'a> Compiler<'a> { 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; @@ -700,10 +688,7 @@ impl<'a> Compiler<'a> { instructions.push(PushFloat(i as f64)); } else { let from_integer = Identifier(Id { - name: Name { - name: intern("fromInteger"), - uid: 0, - }, + name: "fromInteger".into(), typ: qualified(vec![], function_type_(int_type(), literal.typ.clone())), }); let number = Literal(LiteralData { @@ -719,10 +704,7 @@ impl<'a> Compiler<'a> { instructions.push(PushFloat(f)); } else { let from_rational = Identifier(Id { - name: Name { - name: intern("fromRational"), - uid: 0, - }, + name: "fromRational".into(), typ: qualified( vec![], function_type_(double_type(), literal.typ.clone()), @@ -911,7 +893,7 @@ 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) => { @@ -1018,10 +1000,7 @@ impl<'a> Compiler<'a> { constraints: &[Constraint], instructions: &mut Vec, ) { - match self.find(Name { - name: intern("$dict"), - uid: 0, - }) { + match self.find("$dict".into()) { Some(Var::Stack(_)) => { //Push dictionary or member of dictionary match self.push_dictionary_member(constraints, name) { diff --git a/src/core.rs b/src/core.rs index 641b9c6..6d7acba 100644 --- a/src/core.rs +++ b/src/core.rs @@ -48,11 +48,7 @@ impl Module { newtypes: vec![], instances: vec![], bindings: vec![Binding { - name: Id::new( - Name { - name: intern("main"), - uid: 0, - }, + name: Id::new("main".into(), expr.get_type().clone(), vec![], ), @@ -804,20 +800,14 @@ pub mod translate { debug!("m_a {}", m_a); let c = match *m_a.appl() { Type::Variable(ref var) => vec![Constraint { - class: Name { - name: intern("Monad"), - uid: 0, - }, + class: "Monad".into(), 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, - }, + ">>".into(), typ, c, )) @@ -839,10 +829,7 @@ pub mod translate { debug!("m_a {}", m_a); let c = match *m_a.appl() { Type::Variable(ref var) => vec![Constraint { - class: Name { - name: intern("Monad"), - uid: 0, - }, + class: "Monad".into(), variables: vec![var.clone()], }], _ => vec![], @@ -850,10 +837,7 @@ pub mod translate { 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, - }, + ">>=".into(), bind_typ, c.clone(), )); @@ -870,10 +854,7 @@ pub mod translate { c.clone(), ); //Constraints for a let fail_ident = Identifier(Id::new( - Name { - name: intern("fail"), - uid: 0, - }, + "fail".into(), function_type_(list_type(char_type()), m_b), c, )); @@ -1369,10 +1350,7 @@ pub mod translate { fn bool_pattern(s: &str) -> Pattern> { Pattern::Constructor( Id::new( - Name { - name: intern(s), - uid: 0, - }, + s.into(), bool_type(), vec![], ), @@ -1484,10 +1462,7 @@ pub mod translate { ///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, - }, + "error".into(), function_type_(list_type(char_type()), Type::new_var(intern("a"))), vec![], )); diff --git a/src/deriving.rs b/src/deriving.rs index 76a7543..fa280a5 100644 --- a/src/deriving.rs +++ b/src/deriving.rs @@ -28,10 +28,7 @@ pub fn generate_deriving(instances: &mut Vec>>, data: &DataDef instances.push(Instance { constraints: vec![], typ: data.typ.value.clone(), - classname: Name { - name: intern("Eq"), - uid: 0, - }, + classname: "Eq".into(), bindings, }); } @@ -43,10 +40,7 @@ pub fn generate_deriving(instances: &mut Vec>>, data: &DataDef instances.push(Instance { constraints: vec![], typ: data.typ.value.clone(), - classname: Name { - name: intern("Ord"), - uid: 0, - }, + classname: "Ord".into(), bindings, }); } @@ -249,10 +243,7 @@ impl DerivingGen { Alternative { pattern: Pattern::WildCard, expression: Identifier(Id::new( - Name { - uid: 0, - name: intern("False"), - }, + "False".into(), bool_type(), vec![], )), @@ -271,10 +262,7 @@ impl DerivingGen { fn id(s: &str, typ: Type) -> Id { Id::new( - Name { - name: intern(s), - uid: 0, - }, + s.into(), typ, vec![], ) diff --git a/src/renamer.rs b/src/renamer.rs index b5b61c9..c1d2fb7 100644 --- a/src/renamer.rs +++ b/src/renamer.rs @@ -19,10 +19,7 @@ pub struct Name { } pub fn name(s: &str) -> Name { - Name { - uid: 0, - name: intern(s), - } + s.into() } impl From<&str> for Name { diff --git a/src/typecheck.rs b/src/typecheck.rs index ec5007b..541cefe 100644 --- a/src/typecheck.rs +++ b/src/typecheck.rs @@ -254,10 +254,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, - }, + name.into(), qualified(vec![], typ), ); } @@ -943,10 +940,7 @@ impl<'a> TypeEnvironment<'a> { 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, - }], + vec!["Monad".into()], ); previous = Type::Application(Box::new(previous), Box::new(self.new_var())); for bind in bindings.iter_mut() { From 5d80935ac2c120749e4537e213a8ab97009ad958 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 11:22:30 -0800 Subject: [PATCH 14/76] cargo fmt --- src/compiler.rs | 15 +++---------- src/core.rs | 56 +++++++++++++++++------------------------------- src/deriving.rs | 37 ++++++++++++-------------------- src/typecheck.rs | 11 +++------- 4 files changed, 40 insertions(+), 79 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index 5512a77..cc40fd1 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -433,22 +433,13 @@ impl<'a> Compiler<'a> { pub fn new() -> Self { let mut variables = ScopedMap::new(); for (i, &(name, _)) in builtins().iter().enumerate() { - variables.insert( - name.into(), - Var::Builtin(i), - ); + variables.insert(name.into(), Var::Builtin(i)); } for &(name, instruction) in BINARY_PRIMITIVES.iter() { - variables.insert( - name.into(), - Var::Primitive(2, instruction), - ); + variables.insert(name.into(), Var::Primitive(2, instruction)); } for &(name, instruction) in UNARY_PRIMITIVES.iter() { - variables.insert( - name.into(), - Var::Primitive(1, instruction), - ); + variables.insert(name.into(), Var::Primitive(1, instruction)); } Self { instance_dictionaries: vec![], diff --git a/src/core.rs b/src/core.rs index 6d7acba..ecae089 100644 --- a/src/core.rs +++ b/src/core.rs @@ -48,10 +48,7 @@ impl Module { newtypes: vec![], instances: vec![], bindings: vec![Binding { - name: Id::new("main".into(), - expr.get_type().clone(), - vec![], - ), + name: Id::new("main".into(), expr.get_type().clone(), vec![]), expression: expr, }], } @@ -798,19 +795,16 @@ pub mod translate { ///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 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, - )) + Identifier(Id::new(">>".into(), typ, c)) } ///Translates ///do {p <- e; stmts} = @@ -827,20 +821,17 @@ pub mod translate { 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 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(), - )); + let bind_ident = Identifier(Id::new(">>=".into(), bind_typ, c.clone())); //Create ok binding let func_ident = Id::new( @@ -1348,14 +1339,7 @@ pub mod translate { } fn bool_pattern(s: &str) -> Pattern> { - Pattern::Constructor( - Id::new( - s.into(), - bool_type(), - vec![], - ), - vec![], - ) + Pattern::Constructor(Id::new(s.into(), bool_type(), vec![]), vec![]) } struct LambdaIterator<'a, Id: 'a> { diff --git a/src/deriving.rs b/src/deriving.rs index fa280a5..1c10b1d 100644 --- a/src/deriving.rs +++ b/src/deriving.rs @@ -232,24 +232,19 @@ impl DerivingGen { ); 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![], - )), - }, - ], - ); + 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, @@ -261,11 +256,7 @@ impl DerivingGen { } fn id(s: &str, typ: Type) -> Id { - Id::new( - s.into(), - typ, - vec![], - ) + Id::new(s.into(), typ, vec![]) } fn compare_tags(lhs: Expr>, rhs: Expr>) -> Expr> { diff --git a/src/typecheck.rs b/src/typecheck.rs index 541cefe..3931998 100644 --- a/src/typecheck.rs +++ b/src/typecheck.rs @@ -253,10 +253,7 @@ impl<'a> Bindings for BindingsWrapper<'a> { } fn insert_to(map: &mut HashMap>, name: &str, typ: TcType) { - map.insert( - name.into(), - 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(); @@ -938,10 +935,8 @@ impl<'a> TypeEnvironment<'a> { 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!["Monad".into()], - ); + self.constraints + .insert(previous.var().clone(), vec!["Monad".into()]); previous = Type::Application(Box::new(previous), Box::new(self.new_var())); for bind in bindings.iter_mut() { match *bind { From 20f8f1d43a8e6ce276ed64e17a0a412ec43c2b64 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 11:29:21 -0800 Subject: [PATCH 15/76] nitpicks --- src/parser.rs | 19 ++++++++++--------- src/renamer.rs | 2 +- src/typecheck.rs | 2 +- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/parser.rs b/src/parser.rs index 25e2fa8..e07e6c1 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -732,7 +732,7 @@ impl> Parser { }; Ok(Binding { name: name.clone(), - typ: Default::default(), + typ: <_>::default(), arguments, where_bindings, matches, @@ -1387,13 +1387,14 @@ 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, - }; + 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_( @@ -1688,7 +1689,7 @@ test x let b2 = Binding { arguments: vec![Pattern::Identifier(intern("x"))], name: intern("test"), - typ: Default::default(), + typ: <_>::default(), matches: Match::Guards(vec![ Guard { predicate: identifier("x"), diff --git a/src/renamer.rs b/src/renamer.rs index c1d2fb7..012ce36 100644 --- a/src/renamer.rs +++ b/src/renamer.rs @@ -402,7 +402,7 @@ impl Renamer { ///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 }, + Some(&Name { uid, .. }) => Name { name: s, uid }, None => Name { name: s, uid: 0 }, //Primitive } } diff --git a/src/typecheck.rs b/src/typecheck.rs index 3931998..f43f956 100644 --- a/src/typecheck.rs +++ b/src/typecheck.rs @@ -2139,7 +2139,7 @@ pub mod test { arguments: vec![], name: intern("test"), matches: Match::Simple(unary_bind), - typ: Default::default(), + typ: <_>::default(), where_bindings: None, }], identifier("test"), From 9452784122e6b8a1dea6427ff168da561b91ecc2 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 11:34:54 -0800 Subject: [PATCH 16/76] refcatoring of module parsing --- src/parser.rs | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/src/parser.rs b/src/parser.rs index e07e6c1..3726fe3 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -194,25 +194,23 @@ impl> Parser { 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()? { + + 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; } - } 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 { From 5302f94f1fa4939608e01525c9ab76fbc8ee377a Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 11:39:21 -0800 Subject: [PATCH 17/76] Location::eof --- src/lexer.rs | 26 ++++---------------------- src/module.rs | 6 +----- src/parser.rs | 4 ++-- 3 files changed, 7 insertions(+), 29 deletions(-) diff --git a/src/lexer.rs b/src/lexer.rs index 5b89959..0d5a1fc 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -58,7 +58,7 @@ pub enum TokenEnum { ELSE, } -#[derive(Clone, Copy, PartialEq, Debug)] +#[derive(Clone, Copy, PartialEq, Debug, Default)] pub struct Location { pub column: isize, pub row: isize, @@ -109,11 +109,7 @@ impl Token { Self { token: EOF, value: intern(""), - location: Location { - column: -1, - row: -1, - absolute: -1, - }, + location: Location::eof(), } } @@ -127,16 +123,7 @@ impl Token { #[cfg(test)] fn new_(token: TokenEnum, value: &str) -> Self { - Self::new( - &get_local_interner(), - token, - value, - Location { - column: -1, - row: -1, - absolute: -1, - }, - ) + Self::new(&get_local_interner(), token, value, Location::eof()) } } @@ -200,14 +187,9 @@ pub struct Lexer> { impl> Lexer { ///Constructs a new lexer with a default sized token buffer and the local string interner pub fn new(input: Stream) -> Self { - let start = Location { - column: 0, - row: 0, - absolute: 0, - }; Self { input: input.peekable(), - location: start, + location: <_>::default(), unprocessed_tokens: vec![], tokens: VecDeque::with_capacity(20), indent_levels: vec![], diff --git a/src/module.rs b/src/module.rs index 71f9f8d..4908561 100644 --- a/src/module.rs +++ b/src/module.rs @@ -141,11 +141,7 @@ impl TypedExpr { TypedExpr { expr, typ: Type::new_var(intern("a")), - location: Location { - column: -1, - row: -1, - absolute: -1, - }, + location: Location::eof(), } } pub fn with_location>( diff --git a/src/parser.rs b/src/parser.rs index 3726fe3..a346292 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -930,11 +930,11 @@ impl> Parser { } } expect!(self, TYPEDECL); - let (context, typ) = self.constrained_type()?; + let (constraints, typ) = self.constrained_type()?; Ok(TypeDeclaration { name, typ: Qualified { - constraints: context, + constraints, value: typ, }, }) From 88bba9af052209f2cf29efe21205b29463f01cac Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 11:47:18 -0800 Subject: [PATCH 18/76] refactoring --- src/core.rs | 43 +++++++++++++++++-------------------------- src/lambda_lift.rs | 5 +---- src/lexer.rs | 14 +++++--------- src/parser.rs | 9 --------- src/typecheck.rs | 5 +---- 5 files changed, 24 insertions(+), 52 deletions(-) diff --git a/src/core.rs b/src/core.rs index ecae089..3638905 100644 --- a/src/core.rs +++ b/src/core.rs @@ -666,11 +666,7 @@ pub mod translate { 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, - }; + let is_lambda = matches!(&input_expr.expr, &module::Expr::Lambda(_, _)); if is_lambda { let module::TypedExpr { typ, expr, .. } = input_expr; match expr { @@ -1142,15 +1138,15 @@ pub mod translate { 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, - } + 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]; @@ -1285,10 +1281,7 @@ pub mod translate { .iter() .filter(|&&Equation(ps, _)| { ps.len() > 0 - && (match ps[0].1 { - Pattern::WildCard | Pattern::Identifier(..) => true, - _ => false, - }) + && matches!(ps[0].1, Pattern::WildCard | Pattern::Identifier(..)) }) .map(|&Equation(ps, e)| Equation(&ps[1..], e)) .collect(); @@ -1374,9 +1367,11 @@ pub mod translate { } ///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, + binding.arguments.iter().all(|arg| { + matches!( + *arg, + module::Pattern::WildCard | module::Pattern::Identifier(..) + ) }) } @@ -1409,11 +1404,7 @@ pub mod translate { equations .iter() .filter(|&&Equation(ps, _)| { - ps.len() > 0 - && (match ps[0].1 { - Pattern::WildCard | Pattern::Identifier(..) => true, - _ => false, - }) + ps.len() > 0 && matches!(ps[0].1, Pattern::WildCard | Pattern::Identifier(..)) }) .map(|eq| { let &Equation(ps, _) = eq; diff --git a/src/lambda_lift.rs b/src/lambda_lift.rs index caf5481..66d15d8 100644 --- a/src/lambda_lift.rs +++ b/src/lambda_lift.rs @@ -164,10 +164,7 @@ pub fn lift_lambdas(mut module: Module) -> Module { 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); diff --git a/src/lexer.rs b/src/lexer.rs index 0d5a1fc..bd8dada 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -161,10 +161,10 @@ fn name_or_keyword(tok: &str) -> TokenEnum { } ///Returns whether the character is a haskell operator fn is_operator(first_char: char) -> bool { - match first_char { - '+' | '-' | '*' | '/' | '.' | '$' | ':' | '=' | '<' | '>' | '|' | '&' | '!' => true, - _ => false, - } + matches!( + first_char, + '+' | '-' | '*' | '/' | '.' | '$' | ':' | '=' | '<' | '>' | '|' | '&' | '!' + ) } pub struct Lexer> { @@ -261,11 +261,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 diff --git a/src/parser.rs b/src/parser.rs index a346292..93c8dc1 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -109,15 +109,6 @@ macro_rules! expect1 { }}; } -macro_rules! matches { - ($e: expr, $p: pat) => { - match $e { - $p => true, - _ => false, - } - }; -} - macro_rules! unexpected ( ($parser: expr, [$($expected: expr),+]) => { unexpected!($parser, $parser.lexer.current().token, $($expected),+) }; ($parser: expr, $token: expr, $($expected: expr),+) => { { diff --git a/src/typecheck.rs b/src/typecheck.rs index f43f956..66b2ff9 100644 --- a/src/typecheck.rs +++ b/src/typecheck.rs @@ -40,10 +40,7 @@ pub trait Types { &'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, From 3e2289e06ad7a4c4a7ddcaaca78c6b25db1a2ada Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 11:49:58 -0800 Subject: [PATCH 19/76] refactoring --- src/core.rs | 3 --- src/vm.rs | 5 +---- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/core.rs b/src/core.rs index 3638905..f14f831 100644 --- a/src/core.rs +++ b/src/core.rs @@ -1,6 +1,5 @@ pub use crate::{ module::{ - Constructor, DataDefinition, LiteralData::{ Char, @@ -17,8 +16,6 @@ pub use crate::{ Qualified, Type::{ self, - Application, - Variable, }, TypeVariable, }, diff --git a/src/vm.rs b/src/vm.rs index aa5255d..e64a2f9 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -1,10 +1,7 @@ use { crate::{ compiler::*, - core::{ - translate::translate_module, - Constructor, - }, + core::translate::translate_module, interner::*, lambda_lift::do_lambda_lift, parser::Parser, From b8358e390e335017e7cc7328e9036e6d841b1ada Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 11:53:52 -0800 Subject: [PATCH 20/76] refactoring --- src/compiler.rs | 2 +- src/core.rs | 8 ++++---- src/types.rs | 2 +- src/vm.rs | 18 ++---------------- 4 files changed, 8 insertions(+), 22 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index cc40fd1..c730ca8 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -414,7 +414,7 @@ impl DataTypes for Assembly { } enum ArgList<'a> { - Cons(&'a Expr, &'a ArgList<'a>), + Cons(&'a Expr, &'a Self), Nil, } diff --git a/src/core.rs b/src/core.rs index f14f831..a134219 100644 --- a/src/core.rs +++ b/src/core.rs @@ -100,11 +100,11 @@ 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 { diff --git a/src/types.rs b/src/types.rs index 7c45d3a..8009617 100644 --- a/src/types.rs +++ b/src/types.rs @@ -295,7 +295,7 @@ pub struct Constraint { #[derive(Clone, Debug, PartialEq, Eq, Hash, Default)] pub enum Kind { - Function(Box, Box), + Function(Box, Box), #[default] Star, } diff --git a/src/vm.rs b/src/vm.rs index e64a2f9..51a4723 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -44,6 +44,7 @@ enum DictionaryEntry { App(usize, InstanceDictionary), } +#[derive(Clone)] pub enum Node_<'a> { Application(Node<'a>, Node<'a>), Int(isize), @@ -55,21 +56,6 @@ pub enum Node_<'a> { 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), - } - } -} #[derive(Clone)] pub struct Node<'a> { @@ -590,7 +576,7 @@ pub enum VMResult { Char(char), Int(isize), Double(f64), - Constructor(u16, Vec), + Constructor(u16, Vec), } // TODO: throw this garbage into the macro below From efa6ae150343e68be72b2ba1c305d93fd464e749 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 11:59:22 -0800 Subject: [PATCH 21/76] refactoring --- src/core.rs | 7 ++----- src/interner.rs | 22 ++++++++-------------- 2 files changed, 10 insertions(+), 19 deletions(-) diff --git a/src/core.rs b/src/core.rs index a134219..d447c22 100644 --- a/src/core.rs +++ b/src/core.rs @@ -92,11 +92,9 @@ pub enum Pattern { #[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), @@ -179,8 +177,7 @@ impl Typed for Pattern { fn get_type<'a>(&'a self) -> &'a Type { match *self { Self::Identifier(ref name) | Self::Constructor(ref name, _) => name.get_type(), - Self::Number(_) => panic!(), - Self::WildCard => panic!(), + Self::Number(_) | Self::WildCard => panic!(), } } } diff --git a/src/interner.rs b/src/interner.rs index 6f8c163..7022a0f 100644 --- a/src/interner.rs +++ b/src/interner.rs @@ -23,23 +23,17 @@ impl Interner { } 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] } } From 8eb9d0dfcb8c18530896b860ca0d2e439e17ac96 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 12:11:07 -0800 Subject: [PATCH 22/76] refactoring --- src/interner.rs | 2 +- src/scoped_map.rs | 2 +- src/types.rs | 7 ++++--- src/vm.rs | 4 ++-- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/interner.rs b/src/interner.rs index 7022a0f..863129e 100644 --- a/src/interner.rs +++ b/src/interner.rs @@ -33,7 +33,7 @@ impl Interner { pub fn get_str<'a>(&'a self, InternedStr(i): InternedStr) -> &'a str { assert!(i < self.strings.len(), "Invalid InternedStr {:?}", i); - &*self.strings[i] + &self.strings[i] } } diff --git a/src/scoped_map.rs b/src/scoped_map.rs index 336a90f..d67a882 100644 --- a/src/scoped_map.rs +++ b/src/scoped_map.rs @@ -105,7 +105,7 @@ where Entry::Vacant(entry) => entry.insert(vec![]), Entry::Occupied(entry) => entry.into_mut(), }; - if vec.len() != 0 { + if !vec.is_empty() { let r = vec.pop(); vec.push(v); r diff --git a/src/types.rs b/src/types.rs index 8009617..8058527 100644 --- a/src/types.rs +++ b/src/types.rs @@ -37,7 +37,7 @@ pub struct TypeVariable { pub enum Type { Variable(TypeVariable), Constructor(TypeConstructor), - Application(Box>, Box>), + Application(Box, Box), Generic(TypeVariable), } #[derive(Clone, Debug, Default, Hash)] @@ -45,6 +45,7 @@ pub struct Qualified { pub constraints: Vec>, pub value: T, } + pub fn qualified( constraints: Vec>, typ: Type, @@ -73,7 +74,7 @@ impl> Type { ///Gives the typevariable the correct kind arity. pub fn new_var_args(id: VarId, types: Vec) -> Self { Self::new_type_kind( - Type::Variable(TypeVariable { + Self::Variable(TypeVariable { id, kind: Kind::Star, age: 0, @@ -88,7 +89,7 @@ impl> Type { ///Creates a new type constructor with the specified argument and kind pub fn new_op(name: Id, types: Vec) -> Self { Self::new_type_kind( - Type::Constructor(TypeConstructor { + Self::Constructor(TypeConstructor { name, kind: Kind::Star, }), diff --git a/src/vm.rs b/src/vm.rs index 51a4723..917fbce 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -70,10 +70,10 @@ impl<'a> Node<'a> { } } 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> { From d6c960ab53c1fd0b4db93ed8f37b75863ae194a7 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 12:13:11 -0800 Subject: [PATCH 23/76] len() == 0 -> is_empty() --- src/compiler.rs | 4 ++-- src/core.rs | 10 +++++----- src/lambda_lift.rs | 4 ++-- src/lexer.rs | 4 ++-- src/module.rs | 2 +- src/parser.rs | 2 +- src/typecheck.rs | 4 ++-- src/vm.rs | 2 +- 8 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index c730ca8..13f6668 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -1086,7 +1086,7 @@ impl<'a> Compiler<'a> { constraints: &[Constraint], name: Name, ) -> Option { - if constraints.len() == 0 { + if constraints.is_empty() { panic!( "Attempted to push dictionary member '{:?}' with no constraints", name @@ -1140,7 +1140,7 @@ impl<'a> Compiler<'a> { } } - if constraints.len() == 0 { + if constraints.is_empty() { panic!("Error: Attempted to compile dictionary with no constraints at "); } let mut function_indexes = vec![]; diff --git a/src/core.rs b/src/core.rs index d447c22..4ccfe4d 100644 --- a/src/core.rs +++ b/src/core.rs @@ -1144,7 +1144,7 @@ pub mod translate { } debug!("In {:?}", equations); let &Equation(ps, (where_bindings_bindings, e)) = &equations[0]; - if ps.len() == 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(); return make_let(bindings, self.translate_match((*e).clone())); @@ -1156,7 +1156,7 @@ pub mod translate { let bindings = where_bindings_bindings.iter().map(|x| x.clone()).collect(); match *m { module::Match::Simple(ref e) => { - let alt = if ps.len() == 0 { + let alt = if ps.is_empty() { Alternative { pattern: Pattern::WildCard, expression: make_let( @@ -1245,7 +1245,7 @@ pub mod translate { } _ => (), } - } else if patterns.len() == 0 { + } else if patterns.is_empty() { vec.push(Equation(patterns, expr)); } } @@ -1262,7 +1262,7 @@ pub mod translate { None => break, } } - if alts.len() == 0 { + if alts.is_empty() { for &Equation(patterns, expr) in equations.iter() { vec.push(Equation(&patterns[1..], expr)); } @@ -1385,7 +1385,7 @@ pub mod translate { } ///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)) diff --git a/src/lambda_lift.rs b/src/lambda_lift.rs index 66d15d8..05bfc7a 100644 --- a/src/lambda_lift.rs +++ b/src/lambda_lift.rs @@ -199,7 +199,7 @@ 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 { Let(bindings, e) @@ -294,7 +294,7 @@ test2 x = &Lambda(ref arg, ref body) => { arg.name.name == args[0] && check_args(&**body, &args[1..]) } - _ => args.len() == 0, + _ => args.is_empty(), } } diff --git a/src/lexer.rs b/src/lexer.rs index bd8dada..7746ad1 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -439,7 +439,7 @@ impl> Lexer { } } self.unprocessed_tokens.pop(); - if self.unprocessed_tokens.len() == 0 { + if self.unprocessed_tokens.is_empty() { self.next_token(); return; } else { @@ -509,7 +509,7 @@ impl> Lexer { .push_back(self.unprocessed_tokens.pop().unwrap()); return; } else { - if self.indent_levels.len() == 0 { + if self.indent_levels.is_empty() { //End of stream return; } else if *self.indent_levels.last().unwrap() != 0 { diff --git a/src/module.rs b/src/module.rs index 4908561..773cf21 100644 --- a/src/module.rs +++ b/src/module.rs @@ -566,7 +566,7 @@ pub struct Binds<'a, Ident: 'a> { 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 { + if self.vec.is_empty() { None } else { let end = self diff --git a/src/parser.rs b/src/parser.rs index 93c8dc1..2b9875c 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -480,7 +480,7 @@ impl> Parser { expect!(self, LBRACE); let mut bindings = self.sep_by_1(|this| this.do_binding(), SEMICOLON)?; expect!(self, RBRACE); - if bindings.len() == 0 { + if bindings.is_empty() { return Err(ParseError(Located { location: self.lexer.current().location, node: Error::Message(format!( diff --git a/src/typecheck.rs b/src/typecheck.rs index 66b2ff9..958cc70 100644 --- a/src/typecheck.rs +++ b/src/typecheck.rs @@ -1106,7 +1106,7 @@ impl<'a> TypeEnvironment<'a> { } let mut typ = self.typecheck_match(&mut bind.matches, subs); fn make_function(arguments: &[TcType], expr: &TcType) -> TcType { - if arguments.len() == 0 { + if arguments.is_empty() { expr.clone() } else { typ::function_type_(arguments[0].clone(), make_function(&arguments[1..], expr)) @@ -1344,7 +1344,7 @@ pub fn find_specialized_instances( ); let mut result = vec![]; find_specialized(&mut result, actual_type, typ, constraints); - if constraints.len() == 0 { + if constraints.is_empty() { panic!( "Could not find the specialized instance between {:?} <-> {:?}", typ, actual_type diff --git a/src/vm.rs b/src/vm.rs index 917fbce..2d769e9 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -92,7 +92,7 @@ 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>( From 309af5ccc98e10c0317b56bc495b8cd212c4d78c Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 12:19:35 -0800 Subject: [PATCH 24/76] cleanup --- src/compiler.rs | 18 +++++++++--------- src/typecheck.rs | 30 ++++++++++++++---------------- 2 files changed, 23 insertions(+), 25 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index 13f6668..9119efa 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -1086,12 +1086,11 @@ impl<'a> Compiler<'a> { constraints: &[Constraint], name: Name, ) -> Option { - if constraints.is_empty() { - panic!( - "Attempted to push dictionary member '{:?}' with no constraints", - name - ) - } + assert!( + !constraints.is_empty(), + "Attempted to push dictionary member '{:?}' with no constraints", + name + ); let mut ii = 0; for c in constraints.iter() { let result = @@ -1140,9 +1139,10 @@ impl<'a> Compiler<'a> { } } - if constraints.is_empty() { - panic!("Error: Attempted to compile dictionary with no constraints at "); - } + 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 diff --git a/src/typecheck.rs b/src/typecheck.rs index 958cc70..b48e288 100644 --- a/src/typecheck.rs +++ b/src/typecheck.rs @@ -966,7 +966,7 @@ impl<'a> TypeEnvironment<'a> { } } match previous { - Type::Application(ref mut _monad, ref mut typ) => { + Type::Application(_, ref mut typ) => { **typ = self.new_var(); } _ => panic!(), @@ -1004,14 +1004,13 @@ impl<'a> TypeEnvironment<'a> { 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 + } } ///Typechecks a pattern. ///Checks that the pattern has the type 'match_type' and adds all variables in the pattern. @@ -1084,12 +1083,11 @@ impl<'a> TypeEnvironment<'a> { }; 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); } @@ -1344,12 +1342,12 @@ pub fn find_specialized_instances( ); let mut result = vec![]; find_specialized(&mut result, actual_type, typ, constraints); - if constraints.is_empty() { - 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( From ceb7a79cf8c7d36ed220f947cc9ba8648d58b987 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 12:28:20 -0800 Subject: [PATCH 25/76] nitpicks --- src/lexer.rs | 19 ++++++++----------- src/typecheck.rs | 2 +- src/vm.rs | 6 +++--- 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/src/lexer.rs b/src/lexer.rs index 7746ad1..5e5e0a0 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -232,10 +232,9 @@ impl> Lexer { 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"), - } + self.tokens + .get(self.tokens.len() - 1 - self.offset) + .expect("Impossible empty tokens stream") } else if self.unprocessed_tokens.len() > 0 { //Some previous call to next produced more than one token so process those first self.layout_independent_token(); @@ -247,10 +246,9 @@ impl> Lexer { ///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 @@ -275,12 +273,11 @@ impl> Lexer { Some(c) => { self.location.absolute += 1; self.location.column += 1; - if c == '\n' || c == '\r' { + 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 - let x = '\n'; - if c == '\r' && self.input.peek() == Some(&x) { + if c == '\r' && self.input.peek() == Some(&'\n') { self.input.next(); } } diff --git a/src/typecheck.rs b/src/typecheck.rs index b48e288..108f0c8 100644 --- a/src/typecheck.rs +++ b/src/typecheck.rs @@ -411,7 +411,7 @@ impl<'a> TypeEnvironment<'a> { } let data_definitions = module.data_definitions.clone(); for instance in module.instances.iter_mut() { - let (_class_constraints, class_var, class_decls) = module + let (_, class_var, class_decls) = module .classes .iter() .find(|class| class.name == instance.classname) diff --git a/src/vm.rs b/src/vm.rs index 2d769e9..ad6274e 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -766,7 +766,7 @@ 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) @@ -789,7 +789,7 @@ mod primitive { 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()])) } @@ -803,7 +803,7 @@ mod primitive { 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), }; From 0382cb5d3d48c119635815fd3b5aa292e5ff1638 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 12:45:23 -0800 Subject: [PATCH 26/76] refactoring --- src/builtins.rs | 4 ++-- src/core.rs | 2 +- src/interner.rs | 12 +++++++++--- src/module.rs | 7 ++----- src/renamer.rs | 16 +++++++++++----- 5 files changed, 25 insertions(+), 16 deletions(-) diff --git a/src/builtins.rs b/src/builtins.rs index 327fe65..e4d2d58 100644 --- a/src/builtins.rs +++ b/src/builtins.rs @@ -15,12 +15,12 @@ use crate::{ ///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"), + id: "a".into(), kind: Kind::Star, age: 0, }); let var2 = Type::Generic(TypeVariable { - id: intern("b"), + id: "b".into(), kind: Kind::Star, age: 0, }); diff --git a/src/core.rs b/src/core.rs index 4ccfe4d..c69f96b 100644 --- a/src/core.rs +++ b/src/core.rs @@ -1425,7 +1425,7 @@ pub mod translate { fn string(s: &str) -> Expr> { Literal(LiteralData { typ: list_type(char_type()), - value: String(intern(s)), + value: String(s.into()), }) } ///Creates an expression which reports an unmatched guard error when executed diff --git a/src/interner.rs b/src/interner.rs index 863129e..4eda6e0 100644 --- a/src/interner.rs +++ b/src/interner.rs @@ -44,9 +44,15 @@ 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 Deref for InternedStr { diff --git a/src/module.rs b/src/module.rs index 773cf21..6451687 100644 --- a/src/module.rs +++ b/src/module.rs @@ -138,12 +138,9 @@ impl> fmt::Display for TypedExpr { impl TypedExpr { pub fn new>(expr: Expr) -> TypedExpr { - TypedExpr { - expr, - typ: Type::new_var(intern("a")), - location: Location::eof(), - } + TypedExpr::with_location(expr, Location::eof()) } + pub fn with_location>( expr: Expr, loc: Location, diff --git a/src/renamer.rs b/src/renamer.rs index 012ce36..8c8a18f 100644 --- a/src/renamer.rs +++ b/src/renamer.rs @@ -68,9 +68,11 @@ 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 } @@ -136,14 +138,17 @@ impl NameSupply { 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 { @@ -151,6 +156,7 @@ impl NameSupply { uid: self.next_id(), } } + pub fn next_id(&mut self) -> usize { self.unique_id += 1; self.unique_id @@ -400,10 +406,10 @@ impl Renamer { } ///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 }, - 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 } } @@ -441,7 +447,7 @@ impl Renamer { constraints, value: typ, } = typ; - let constraints2: Vec> = constraints + let constraints2: Vec<_> = constraints .into_iter() .map(|Constraint { class, variables }| Constraint { class: self.get_name(class), From 6bf60bb5f8866fe6f2e6d2b0bb2aadd85d470e4c Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 12:48:14 -0800 Subject: [PATCH 27/76] intern("a") -> "a".into() --- src/core.rs | 16 ++++++++-------- src/deriving.rs | 2 +- src/module.rs | 2 +- src/parser.rs | 14 +++++++------- src/typecheck.rs | 22 +++++++++++----------- src/types.rs | 2 +- 6 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/core.rs b/src/core.rs index c69f96b..1172a4c 100644 --- a/src/core.rs +++ b/src/core.rs @@ -924,7 +924,7 @@ pub mod translate { ::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![]) + Id::new(n.clone(), Type::new_var("a".into()), vec![]) } _ => panic!(), }; @@ -965,7 +965,7 @@ pub mod translate { let mut vec = vec![]; let dummy_var = &[Id::new( self.name_supply.anonymous(), - Type::new_var(intern("a")), + Type::new_var("a".into()), vec![], )]; let uid = self.name_supply.next_id(); @@ -1297,7 +1297,7 @@ pub mod translate { 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![])) + Pattern::Identifier(Id::new(i, Type::new_var("a".into()), vec![])) } module::Pattern::Number(n) => Pattern::Number(n), module::Pattern::Constructor(name, patterns) => { @@ -1305,20 +1305,20 @@ pub mod translate { .into_iter() .map(|pat| match pat { module::Pattern::Identifier(name) => { - Id::new(name, Type::new_var(intern("a")), vec![]) + Id::new(name, Type::new_var("a".into()), vec![]) } module::Pattern::WildCard => Id::new( Name { name: intern("_"), uid: usize::max_value(), }, - Type::new_var(intern("a")), + Type::new_var("a".into()), vec![], ), _ => panic!("Nested pattern"), }) .collect(); - Pattern::Constructor(Id::new(name, Type::new_var(intern("a")), vec![]), ps) + Pattern::Constructor(Id::new(name, Type::new_var("a".into()), vec![]), ps) } module::Pattern::WildCard => Pattern::WildCard, } @@ -1409,7 +1409,7 @@ pub mod translate { name: intern("_"), uid: usize::max_value(), }, - Type::new_var(intern("a")), + Type::new_var("a".into()), vec![], ), _ => panic!(), @@ -1432,7 +1432,7 @@ pub mod translate { fn unmatched_guard() -> Expr> { let error_ident = Identifier(Id::new( "error".into(), - function_type_(list_type(char_type()), Type::new_var(intern("a"))), + function_type_(list_type(char_type()), Type::new_var("a".into())), vec![], )); Apply(Box::new(error_ident), Box::new(string("Unmatched guard"))) diff --git a/src/deriving.rs b/src/deriving.rs index 1c10b1d..f22b58c 100644 --- a/src/deriving.rs +++ b/src/deriving.rs @@ -260,7 +260,7 @@ fn id(s: &str, typ: Type) -> Id { } fn compare_tags(lhs: Expr>, rhs: Expr>) -> Expr> { - let var = Type::new_var(intern("a")); + let var = Type::new_var("a".into()); let typ = function_type_( var.clone(), function_type_(var.clone(), Type::new_op(name("Ordering"), vec![])), diff --git a/src/module.rs b/src/module.rs index 6451687..15ec5be 100644 --- a/src/module.rs +++ b/src/module.rs @@ -147,7 +147,7 @@ impl TypedExpr { ) -> TypedExpr { TypedExpr { expr, - typ: Type::new_var(intern("a")), + typ: Type::new_var("a".into()), location: loc, } } diff --git a/src/parser.rs b/src/parser.rs index 2b9875c..a0cb3d0 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1006,7 +1006,7 @@ impl> Parser { let mut definition = DataDefinition { constructors: vec![], - typ: qualified(vec![], Type::new_var(intern("a"))), + typ: qualified(vec![], Type::new_var("a".into())), parameters: HashMap::new(), deriving: vec![], }; @@ -1432,7 +1432,7 @@ in test - 2" 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 a = &Type::new_var("a".into()); let b = &Type::new_var(intern("b")); let c = &Type::new_var(intern("c")); let f = function_type( @@ -1472,14 +1472,14 @@ in test - 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 list = Type::new_op(intern("List"), vec![Type::new_var("a".into())]); let cons = Constructor { name: intern("Cons"), tag: 0, arity: 2, typ: qualified( vec![], - function_type(&Type::new_var(intern("a")), &function_type(&list, &list)), + function_type(&Type::new_var("a".into()), &function_type(&list, &list)), ), }; let nil = Constructor { @@ -1570,7 +1570,7 @@ instance Eq a => Eq [a] where assert_eq!(module.instances[0].constraints[0].class, intern("Eq")); assert_eq!( module.instances[0].typ, - list_type(Type::new_var(intern("a"))) + list_type(Type::new_var("a".into())) ); } #[test] @@ -1585,7 +1585,7 @@ instance Eq a => Eq [a] where let module = parser.module().unwrap(); let cls = &module.classes[0]; - let a = TypeVariable::new(intern("a")); + 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")); @@ -1823,7 +1823,7 @@ test = case a of newtype IntPair a = IntPair (a, Int) "; let module = Parser::new(s.chars()).module().unwrap(); - let a = Type::new_var(intern("a")); + let a = Type::new_var("a".into()); let typ = Type::new_op(intern("IntPair"), vec![a.clone()]); assert_eq!(module.newtypes[0].typ, qualified(vec![], typ.clone())); assert_eq!( diff --git a/src/typecheck.rs b/src/typecheck.rs index 108f0c8..5f836c7 100644 --- a/src/typecheck.rs +++ b/src/typecheck.rs @@ -294,7 +294,7 @@ impl<'a> TypeEnvironment<'a> { "primDoubleToInt", typ::function_type_(typ::double_type(), typ::int_type()), ); - let var = Type::Generic(TypeVariable::new_var_kind(intern("a"), Kind::Star.clone())); + 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); @@ -809,7 +809,7 @@ 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")) { + if expr.typ == Type::::new_var("a".into()) { expr.typ = self.new_var(); } @@ -1182,7 +1182,7 @@ impl<'a> TypeEnvironment<'a> { let bind_index = graph.get_vertex(*index).value; let binds = bindings.get_mut(bind_index); for bind in binds.iter_mut() { - if bind.typ.value == Type::::new_var(intern("a")) { + if bind.typ.value == Type::::new_var("a".into()) { bind.typ.value = self.new_var(); } } @@ -2207,7 +2207,7 @@ main = case [mult2 123, 0] of test x = True"; let module = do_typecheck(file); - let typ = function_type_(Type::new_var(intern("a")), bool_type()); + let typ = function_type_(Type::new_var("a".into()), bool_type()); assert_eq!(module.bindings[0].typ.value, typ); } @@ -2279,7 +2279,7 @@ main x y = primIntAdd (test x) (test y)" env.typecheck_module_(&mut module); let typ = &module.bindings[0].typ; - let a = Type::new_var(intern("a")); + let a = Type::new_var("a".into()); let b = Type::new_var(intern("b")); let test = function_type_(a.clone(), function_type_(b.clone(), int_type())); assert_eq!(&typ.value, &test); @@ -2335,7 +2335,7 @@ test x y = case x < y of env.typecheck_module_(&mut module); let typ = &module.bindings[0].typ; - let a = Type::new_var(intern("a")); + let a = Type::new_var("a".into()); assert_eq!( typ.value, function_type_(a.clone(), function_type_(a.clone(), bool_type())) @@ -2484,7 +2484,7 @@ main = fmap add2 3", let id_bind = id.unwrap(); assert_eq!( id_bind.typ.value, - function_type_(Type::new_var(intern("a")), Type::new_var(intern("a"))) + function_type_(Type::new_var("a".into()), Type::new_var("a".into())) ); } @@ -2570,7 +2570,7 @@ test x = do "; let module = do_typecheck_with(file, &[&prelude as &dyn DataTypes]); - let var = Type::new_var(intern("a")); + let var = Type::new_var("a".into()); let t = function_type_( Type::new_var_args(intern("c"), vec![list_type(var.clone())]), Type::new_var_args(intern("c"), vec![var.clone()]), @@ -2590,7 +2590,7 @@ test f (x:xs) = f x : test f xs test _ [] = [] ", ); - let a = Type::new_var(intern("a")); + let a = Type::new_var("a".into()); let b = Type::new_var(intern("b")); let test = function_type_( function_type_(a.clone(), b.clone()), @@ -2611,7 +2611,7 @@ if_ p x y | True = y ", ); - let var = Type::new_var(intern("a")); + let var = Type::new_var("a".into()); let test = function_type_( bool_type(), function_type_(var.clone(), function_type_(var.clone(), var.clone())), @@ -2656,7 +2656,7 @@ test x y = [x] == [y] ) .unwrap(); let module = modules.last().unwrap(); - let a = Type::new_var(intern("a")); + let a = Type::new_var("a".into()); let cs = vec![Constraint { class: intern("Eq"), variables: vec![a.var().clone()], diff --git a/src/types.rs b/src/types.rs index 8058527..5ed78f4 100644 --- a/src/types.rs +++ b/src/types.rs @@ -321,7 +321,7 @@ impl Kind { impl Default for Type { fn default() -> Self { - Self::Variable(TypeVariable::new(intern("a"))) + Self::Variable(TypeVariable::new("a".into())) } } impl fmt::Display for TypeVariable { From 764851e91338e020564168e4884b4377cfbdd2db Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 13:09:14 -0800 Subject: [PATCH 28/76] refactoring --- src/builtins.rs | 1 - src/interner.rs | 6 ++++++ src/parser.rs | 4 ++-- src/typecheck.rs | 10 +++++----- src/types.rs | 6 ++++++ 5 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/builtins.rs b/src/builtins.rs index e4d2d58..7c073c9 100644 --- a/src/builtins.rs +++ b/src/builtins.rs @@ -1,5 +1,4 @@ use crate::{ - interner::intern, renamer::{ name, typ::*, diff --git a/src/interner.rs b/src/interner.rs index 4eda6e0..54e5073 100644 --- a/src/interner.rs +++ b/src/interner.rs @@ -55,6 +55,12 @@ impl From<&str> for InternedStr { } } +impl PartialEq for InternedStr { + fn eq(&self, other: &str) -> bool { + self == &intern(other) + } +} + impl Deref for InternedStr { type Target = str; fn deref(&self) -> &str { diff --git a/src/parser.rs b/src/parser.rs index a0cb3d0..d235336 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1433,8 +1433,8 @@ in test - 2" 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("a".into()); - let b = &Type::new_var(intern("b")); - let c = &Type::new_var(intern("c")); + 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)), diff --git a/src/typecheck.rs b/src/typecheck.rs index 5f836c7..621bc58 100644 --- a/src/typecheck.rs +++ b/src/typecheck.rs @@ -1182,7 +1182,7 @@ impl<'a> TypeEnvironment<'a> { let bind_index = graph.get_vertex(*index).value; let binds = bindings.get_mut(bind_index); for bind in binds.iter_mut() { - if bind.typ.value == Type::::new_var("a".into()) { + if bind.typ.value == Type::::new_var(intern("a")) { bind.typ.value = self.new_var(); } } @@ -2280,7 +2280,7 @@ main x y = primIntAdd (test x) (test y)" let typ = &module.bindings[0].typ; let a = Type::new_var("a".into()); - let b = Type::new_var(intern("b")); + let b = Type::new_var("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"); @@ -2572,8 +2572,8 @@ test x = do let var = Type::new_var("a".into()); let t = function_type_( - Type::new_var_args(intern("c"), vec![list_type(var.clone())]), - Type::new_var_args(intern("c"), vec![var.clone()]), + 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!( @@ -2591,7 +2591,7 @@ test _ [] = [] ", ); let a = Type::new_var("a".into()); - let b = Type::new_var(intern("b")); + let b = Type::new_var("b".into()); let test = function_type_( function_type_(a.clone(), b.clone()), function_type_(list_type(a), list_type(b)), diff --git a/src/types.rs b/src/types.rs index 5ed78f4..4a68d87 100644 --- a/src/types.rs +++ b/src/types.rs @@ -65,6 +65,12 @@ impl TypeVariable { } } +impl> From<&str> for Type { + fn from(value: &str) -> Self { + Self::new_var(value.into()) + } +} + impl> Type { ///Creates a new type variable with the specified id pub fn new_var(id: VarId) -> Self { From 1120197e91d3a6688cf67a0e1ade968faaf3d88c Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 13:17:18 -0800 Subject: [PATCH 29/76] refactoring --- src/core.rs | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/core.rs b/src/core.rs index 1172a4c..4d9fa27 100644 --- a/src/core.rs +++ b/src/core.rs @@ -712,7 +712,7 @@ pub mod translate { r, ) } - module::Expr::Literal(l) => Literal(LiteralData { typ: typ, value: l }), + 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![]), @@ -1335,29 +1335,29 @@ pub mod translate { 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 { From f6643cbb279fdc7a18c213f1f101d027fa352a14 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 13:22:18 -0800 Subject: [PATCH 30/76] refactoring --- src/types.rs | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/types.rs b/src/types.rs index 4a68d87..00f1458 100644 --- a/src/types.rs +++ b/src/types.rs @@ -371,20 +371,23 @@ struct Prec<'a, Id: 'a>(Prec_, &'a Type); 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, + 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> { From d90f54c4034dce62770c3ea5546afd5a1f6545a2 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 13:25:02 -0800 Subject: [PATCH 31/76] refactoring --- src/types.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/types.rs b/src/types.rs index 00f1458..f4f47c2 100644 --- a/src/types.rs +++ b/src/types.rs @@ -371,7 +371,7 @@ struct Prec<'a, Id: 'a>(Prec_, &'a Type); 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 { + let Type::Application(ref xx, ref result) = typ else { return None; }; @@ -387,12 +387,12 @@ pub fn try_get_function<'a, Id: AsRef>( return None; } - Some((&**arg, &**result)) + Some((arg, result)) } 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), From 17cc66609fd7b62041526a3492b73f05a44a6bc8 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 13:28:06 -0800 Subject: [PATCH 32/76] removed unneeded dereferencing --- src/compiler.rs | 26 +++++++++++++------------- src/core.rs | 18 +++++++++--------- src/deriving.rs | 4 ++-- src/lambda_lift.rs | 6 +++--- src/module.rs | 26 +++++++++++++------------- src/typecheck.rs | 28 ++++++++++++++-------------- src/types.rs | 18 +++++++++--------- 7 files changed, 63 insertions(+), 63 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index 9119efa..5b04d45 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -228,7 +228,7 @@ fn find_global<'a>(module: &'a Module, offset: usize, name: Name) -> Option< let typ = bind.expression.get_type(); let constraints = &bind.name.typ.constraints; if constraints.len() > 0 { - Var::Constraint(offset + global_index, typ, &**constraints) + Var::Constraint(offset + global_index, typ, constraints) } else { Var::Global(offset + global_index) } @@ -379,11 +379,11 @@ impl Types for Assembly { for &(ref constraints, ref op) in self.instances.iter() { match op { &Type::Application(ref op, ref t) => { - let x = match extract_applied_type(&**op) { + let x = match extract_applied_type(op) { &Type::Constructor(ref x) => x, _ => panic!(), }; - let y = match extract_applied_type(&**t) { + let y = match extract_applied_type(t) { &Type::Constructor(ref x) => x, _ => panic!(), }; @@ -392,7 +392,7 @@ impl Types for Assembly { _ => panic!(), }; if classname.name == x.name && y.name == z.name { - return Some((constraints.as_ref(), &**t)); + return Some((constraints.as_ref(), t)); } } _ => (), @@ -549,7 +549,7 @@ impl<'a> Compiler<'a> { 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); @@ -731,12 +731,12 @@ 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 @@ -796,8 +796,8 @@ impl<'a> Compiler<'a> { match *expr { Apply(ref func, ref arg) => { return self.compile_apply( - &**func, - ArgList::Cons(&**arg, &args), + func, + ArgList::Cons(arg, &args), instructions, strict, ) @@ -1045,8 +1045,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) => { @@ -1247,8 +1247,8 @@ fn try_find_instance_type<'a>( 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, } diff --git a/src/core.rs b/src/core.rs index 4d9fa27..43a0721 100644 --- a/src/core.rs +++ b/src/core.rs @@ -159,7 +159,7 @@ impl> Typed for Expr { &Self::Literal(ref lit) => &lit.typ, &Self::Apply(ref func, _) => { match func.get_type() { - &Type::Application(_, ref a) => &**a, + &Type::Application(_, ref a) => a, x => panic!( "The function in Apply must be a type application, found {}", x @@ -260,18 +260,18 @@ 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); } @@ -653,7 +653,7 @@ pub mod translate { 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), + module::Match::Guards(ref gs) => self.translate_guards(unmatched_guard(), gs), } } @@ -1051,7 +1051,7 @@ pub mod translate { 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, + 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 }; @@ -1185,7 +1185,7 @@ pub mod translate { pattern: ps[0].1.clone(), expression: make_let( bindings, - self.translate_guards(fallthrough, &**guards), + self.translate_guards(fallthrough, guards), ), }); } diff --git a/src/deriving.rs b/src/deriving.rs index f22b58c..0834a76 100644 --- a/src/deriving.rs +++ b/src/deriving.rs @@ -151,7 +151,7 @@ impl DerivingGen { }, variables: vec![param.var().clone()], }); - make_constraints(result, class, &**f) + make_constraints(result, class, f) } _ => result, } @@ -311,7 +311,7 @@ impl<'a> Iterator for ArgIterator<'a> { } fn extract_applied_type<'a, Id>(typ: &'a Type) -> &'a Type { match typ { - &Type::Application(ref lhs, _) => extract_applied_type(&**lhs), + &Type::Application(ref lhs, _) => extract_applied_type(lhs), _ => typ, } } diff --git a/src/lambda_lift.rs b/src/lambda_lift.rs index 05bfc7a..1c21efc 100644 --- a/src/lambda_lift.rs +++ b/src/lambda_lift.rs @@ -292,7 +292,7 @@ test2 x = 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..]) + arg.name.name == args[0] && check_args(body, &args[1..]) } _ => args.is_empty(), } @@ -309,7 +309,7 @@ test2 x = Identifier(ref i) => args.push(i.name.name), _ => panic!("Expected identifier as argument"), } - get_let(&**f, args) + get_let(f, args) } _ => expr, } @@ -385,7 +385,7 @@ test2 x = fn no_local_lambdas() { fn skip_lambdas(expr: &Expr) -> &Expr { match expr { - &Lambda(_, ref body) => skip_lambdas(&**body), + &Lambda(_, ref body) => skip_lambdas(body), _ => expr, } } diff --git a/src/module.rs b/src/module.rs index 15ec5be..9747e6c 100644 --- a/src/module.rs +++ b/src/module.rs @@ -341,30 +341,30 @@ pub fn walk_binding>(visitor: &mut V, binding: &Binding 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() { @@ -381,10 +381,10 @@ pub fn walk_expr>(visitor: &mut V, expr: &TypedExpr 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), + &TypeSig(ref expr, _) => visitor.visit_expr(expr), + &Paren(ref expr) => visitor.visit_expr(expr), &Literal(..) | &Identifier(..) => (), } } diff --git a/src/typecheck.rs b/src/typecheck.rs index 621bc58..8e330ee 100644 --- a/src/typecheck.rs +++ b/src/typecheck.rs @@ -651,7 +651,7 @@ impl<'a> TypeEnvironment<'a> { if class == *name { let result = self.check_instance_constraints( - &**constraints, + constraints, typ, searched_type, new_constraints, @@ -708,7 +708,7 @@ impl<'a> TypeEnvironment<'a> { .filter(|c| c.variables[0] == *rvar) .map(|constraint| { let result = - self.has_instance(constraint.class, &**rtype, new_constraints); + self.has_instance(constraint.class, rtype, new_constraints); if result.is_ok() { match **rtype { Type::Variable(ref var) => { @@ -726,8 +726,8 @@ impl<'a> TypeEnvironment<'a> { .unwrap_or_else(|| { self.check_instance_constraints( constraints, - &**lvar, - &**ltype, + lvar, + ltype, new_constraints, ) }) @@ -1042,7 +1042,7 @@ impl<'a> TypeEnvironment<'a> { 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); + self.pattern_rec(0, location, subs, patterns, &mut t); } &Pattern::WildCard => {} } @@ -1365,8 +1365,8 @@ fn find_specialized( } } (&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) { @@ -1450,7 +1450,7 @@ fn get_returntype(typ: &TcType) -> TcType { match typ { &Type::Application(_, ref rhs) => { if is_function(typ) { - get_returntype(&**rhs) + get_returntype(rhs) } else { typ.clone() } @@ -1485,7 +1485,7 @@ 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) + occurs(type_var, lhs) || occurs(type_var, rhs) } _ => false, } @@ -1797,9 +1797,9 @@ fn match_( ) -> 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(|_| { + match_(env, subs, &mut **l1, l2).and_then(|_| { replace(&mut env.constraints, &mut **r1, subs); - match_(env, subs, &mut **r1, &**r2) + match_(env, subs, &mut **r1, r2) }) } (&mut Type::Variable(ref mut lhs), &Type::Variable(ref rhs)) => { @@ -1901,8 +1901,8 @@ fn each_type_( &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); } _ => (), } @@ -1928,7 +1928,7 @@ fn find_kind( 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), } diff --git a/src/types.rs b/src/types.rs index f4f47c2..ddbbfc7 100644 --- a/src/types.rs +++ b/src/types.rs @@ -139,7 +139,7 @@ impl> Type { #[allow(dead_code)] pub fn appl(&self) -> &Self { match self { - &Self::Application(ref lhs, _) => &**lhs, + &Self::Application(ref lhs, _) => lhs, _ => panic!("Error: Tried to unwrap {} as TypeApplication", self), } } @@ -147,7 +147,7 @@ impl> Type { ///Returns a reference to the the type argument or fails if it is not an application pub fn appr(&self) -> &Self { match self { - &Self::Application(_, ref rhs) => &**rhs, + &Self::Application(_, ref rhs) => rhs, _ => panic!("Error: Tried to unwrap TypeApplication"), } } @@ -160,7 +160,7 @@ impl> Type { &Self::Constructor(ref v) => &v.kind, &Self::Application(ref lhs, _) => { match lhs.kind() { - &Kind::Function(_, ref kind) => &**kind, + &Kind::Function(_, ref kind) => kind, _ => panic!( "Type application must have a kind of Kind::Function, {}", self @@ -415,15 +415,15 @@ impl<'a, Id: fmt::Display + AsRef> fmt::Display for Prec<'a, Id> { write!( f, "({} {})", - Prec(Prec_::Function, &**lhs), - Prec(Prec_::Constructor, &**rhs) + Prec(Prec_::Function, lhs), + Prec(Prec_::Constructor, rhs) ) } else { write!( f, "{} {}", - Prec(Prec_::Function, &**lhs), - Prec(Prec_::Constructor, &**rhs) + Prec(Prec_::Function, lhs), + Prec(Prec_::Constructor, rhs) ) } } @@ -460,7 +460,7 @@ where (&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, } @@ -504,7 +504,7 @@ where pub fn extract_applied_type(typ: &Type) -> &Type { match *typ { - Type::Application(ref lhs, _) => extract_applied_type(&**lhs), + Type::Application(ref lhs, _) => extract_applied_type(lhs), _ => typ, } } From 21b0944ca0a0856ceb7daf5acda5c15c3ecce250 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 13:28:49 -0800 Subject: [PATCH 33/76] cargo fmt --- src/compiler.rs | 7 +------ src/lambda_lift.rs | 4 +--- src/typecheck.rs | 17 +++++++---------- src/types.rs | 42 ++++++++++++++++++++---------------------- 4 files changed, 29 insertions(+), 41 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index 5b04d45..1922d51 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -795,12 +795,7 @@ impl<'a> Compiler<'a> { //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) } _ => (), } diff --git a/src/lambda_lift.rs b/src/lambda_lift.rs index 1c21efc..47b70d8 100644 --- a/src/lambda_lift.rs +++ b/src/lambda_lift.rs @@ -291,9 +291,7 @@ test2 x = 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..]) - } + &Lambda(ref arg, ref body) => arg.name.name == args[0] && check_args(body, &args[1..]), _ => args.is_empty(), } } diff --git a/src/typecheck.rs b/src/typecheck.rs index 8e330ee..d11861d 100644 --- a/src/typecheck.rs +++ b/src/typecheck.rs @@ -649,13 +649,12 @@ impl<'a> TypeEnvironment<'a> { } 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; } @@ -1484,9 +1483,7 @@ fn replace( 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) - } + &Type::Application(ref lhs, ref rhs) => occurs(type_var, lhs) || occurs(type_var, rhs), _ => false, } } diff --git a/src/types.rs b/src/types.rs index ddbbfc7..b3716d5 100644 --- a/src/types.rs +++ b/src/types.rs @@ -405,30 +405,28 @@ impl<'a, Id: fmt::Display + AsRef> fmt::Display for Prec<'a, Id> { write!(f, "{} -> {}", Prec(Prec_::Function, arg), result) } } - 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) - ) - } + 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) + ) } } - } + }, }, } } From cc787b1e7a941c1d79a617897a9261d0e67f6b39 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 13:30:26 -0800 Subject: [PATCH 34/76] refactoring --- src/compiler.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index 1922d51..3697e05 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -806,14 +806,11 @@ 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) .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) => { From d5c4afc4788933dae7ac7a34dfac14554dd2129e Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 13:41:38 -0800 Subject: [PATCH 35/76] refactoring --- src/core.rs | 25 +++++++------------------ src/scoped_map.rs | 5 ++--- 2 files changed, 9 insertions(+), 21 deletions(-) diff --git a/src/core.rs b/src/core.rs index 43a0721..55d647b 100644 --- a/src/core.rs +++ b/src/core.rs @@ -1156,24 +1156,13 @@ pub mod translate { let bindings = where_bindings_bindings.iter().map(|x| x.clone()).collect(); match *m { module::Match::Simple(ref e) => { - let alt = if ps.is_empty() { - Alternative { - pattern: Pattern::WildCard, - expression: make_let( - bindings, - self.translate_expr((*e).clone()), - ), - } - } else { - Alternative { - pattern: ps[0].1.clone(), - expression: make_let( - bindings, - self.translate_expr((*e).clone()), - ), - } - }; - alts.push(alt); + 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())), + }); } module::Match::Guards(ref guards) => { let fallthrough = if equations.len() == i + 1 { diff --git a/src/scoped_map.rs b/src/scoped_map.rs index d67a882..fb647c3 100644 --- a/src/scoped_map.rs +++ b/src/scoped_map.rs @@ -105,10 +105,9 @@ where Entry::Vacant(entry) => entry.insert(vec![]), Entry::Occupied(entry) => entry.into_mut(), }; - if !vec.is_empty() { - let r = vec.pop(); + if let Some(r) = vec.pop() { vec.push(v); - r + r.into() } else { vec.push(v); self.scopes.push(Some(k)); From 28031c6380591e4b8d94aba77e8636e671fda27e Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 13:44:16 -0800 Subject: [PATCH 36/76] refactoring --- src/core.rs | 69 ++++++++++++++++++++++++++--------------------------- 1 file changed, 34 insertions(+), 35 deletions(-) diff --git a/src/core.rs b/src/core.rs index 55d647b..31602e3 100644 --- a/src/core.rs +++ b/src/core.rs @@ -1208,47 +1208,46 @@ pub mod translate { } last_index += 1; } - match pattern_test { - Some(pattern_test) => { - vec.clear(); - 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]) { - 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), - ) => { - 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()), - }); - } + if let Some(pattern_test) = pattern_test { + vec.clear(); + 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]) { + 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), + ) => { + 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()), + }); } } - _ => (), } - } else if patterns.is_empty() { - vec.push(Equation(patterns, expr)); + _ => (), } + } else if patterns.is_empty() { + vec.push(Equation(patterns, expr)); } - //For all the pattern that match the pattern we need to generate new case expressions - let e = make_let(variable_bindings, self.translate_equations(vec.as_ref())); - - let arg_id = &ps[0].0; - let bs = needed_variables(arg_id, equations); - alts.push(Alternative { - pattern: pattern_test.1.clone(), - expression: make_let(bs, e), - }); } - None => break, + //For all the pattern that match the pattern we need to generate new case expressions + let e = make_let(variable_bindings, self.translate_equations(vec.as_ref())); + + let arg_id = &ps[0].0; + let bs = needed_variables(arg_id, equations); + alts.push(Alternative { + pattern: pattern_test.1.clone(), + expression: make_let(bs, e), + }); + } else { + break; } } if alts.is_empty() { From 3daee49a92945d311199f32c88d81704482966c3 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 13:48:24 -0800 Subject: [PATCH 37/76] refactoring --- src/vm.rs | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/vm.rs b/src/vm.rs index ad6274e..ac47bd4 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -201,18 +201,15 @@ impl<'a> VM { fn deepseq(&'a self, mut stack: Vec>, assembly_id: usize) -> Node_<'a> { 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![]; - 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 From d3994f81fe08ba49dec155d36ffe27c4833b8547 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 13:52:57 -0800 Subject: [PATCH 38/76] nitpicks --- src/core.rs | 24 +++++++++++++++++------- src/types.rs | 6 ------ 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/core.rs b/src/core.rs index 31602e3..a6f7b08 100644 --- a/src/core.rs +++ b/src/core.rs @@ -188,6 +188,18 @@ impl PartialEq for Name { } } +impl From<&str> for TcType { + fn from(value: &str) -> Self { + Self::new_var(value.into()) + } +} + +// impl> From<&str> for Type { +// fn from(value: &str) -> Self { +// Self::new_var(value.into()) +// } +// } + ///Id is a Name combined with a type #[derive(PartialEq, Eq, Hash, Clone, Debug)] pub struct Id { @@ -1285,28 +1297,26 @@ pub mod translate { fn translate_pattern(&mut self, pattern: module::Pattern) -> Pattern> { match pattern { module::Pattern::Identifier(i) => { - Pattern::Identifier(Id::new(i, Type::new_var("a".into()), vec![])) + 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, Type::new_var("a".into()), vec![]) - } + module::Pattern::Identifier(name) => Id::new(name, "a".into(), vec![]), module::Pattern::WildCard => Id::new( Name { - name: intern("_"), + name: "_".into(), uid: usize::max_value(), }, - Type::new_var("a".into()), + "a".into(), vec![], ), _ => panic!("Nested pattern"), }) .collect(); - Pattern::Constructor(Id::new(name, Type::new_var("a".into()), vec![]), ps) + Pattern::Constructor(Id::new(name, "a".into(), vec![]), ps) } module::Pattern::WildCard => Pattern::WildCard, } diff --git a/src/types.rs b/src/types.rs index b3716d5..6a9325a 100644 --- a/src/types.rs +++ b/src/types.rs @@ -65,12 +65,6 @@ impl TypeVariable { } } -impl> From<&str> for Type { - fn from(value: &str) -> Self { - Self::new_var(value.into()) - } -} - impl> Type { ///Creates a new type variable with the specified id pub fn new_var(id: VarId) -> Self { From 9a7368efadffd834f3d31ab4aec9790897e5af45 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 13:54:28 -0800 Subject: [PATCH 39/76] refactoring --- src/core.rs | 12 ------------ src/types.rs | 6 ++++++ 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/src/core.rs b/src/core.rs index a6f7b08..4939dbf 100644 --- a/src/core.rs +++ b/src/core.rs @@ -188,18 +188,6 @@ impl PartialEq for Name { } } -impl From<&str> for TcType { - fn from(value: &str) -> Self { - Self::new_var(value.into()) - } -} - -// impl> From<&str> for Type { -// fn from(value: &str) -> Self { -// Self::new_var(value.into()) -// } -// } - ///Id is a Name combined with a type #[derive(PartialEq, Eq, Hash, Clone, Debug)] pub struct Id { diff --git a/src/types.rs b/src/types.rs index 6a9325a..292c19b 100644 --- a/src/types.rs +++ b/src/types.rs @@ -56,6 +56,12 @@ pub fn qualified( } } +impl> From<&str> for Type { + fn from(value: &str) -> Self { + Self::new_var(value.into()) + } +} + impl TypeVariable { pub fn new(id: VarId) -> Self { Self::new_var_kind(id, Kind::Star) From d23db7ed232cd7010e0232480e79cbdd914fdba0 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 13:59:26 -0800 Subject: [PATCH 40/76] refactoring --- src/core.rs | 12 ++++-------- src/deriving.rs | 2 +- src/module.rs | 2 +- src/parser.rs | 26 ++++++++++++-------------- src/typecheck.rs | 23 ++++++++++------------- 5 files changed, 28 insertions(+), 37 deletions(-) diff --git a/src/core.rs b/src/core.rs index 4939dbf..6b041e5 100644 --- a/src/core.rs +++ b/src/core.rs @@ -924,7 +924,7 @@ pub mod translate { ::std::mem::swap(p, &mut x); let id = match *p { module::Pattern::Identifier(ref n) => { - Id::new(n.clone(), Type::new_var("a".into()), vec![]) + Id::new(n.clone(), "a".into(), vec![]) } _ => panic!(), }; @@ -963,11 +963,7 @@ pub mod translate { alts: Vec>, ) -> Expr> { let mut vec = vec![]; - let dummy_var = &[Id::new( - self.name_supply.anonymous(), - Type::new_var("a".into()), - vec![], - )]; + let dummy_var = &[Id::new(self.name_supply.anonymous(), "a".into(), vec![])]; let uid = self.name_supply.next_id(); for module::Alternative { pattern, @@ -1395,7 +1391,7 @@ pub mod translate { name: intern("_"), uid: usize::max_value(), }, - Type::new_var("a".into()), + "a".into(), vec![], ), _ => panic!(), @@ -1418,7 +1414,7 @@ pub mod translate { fn unmatched_guard() -> Expr> { let error_ident = Identifier(Id::new( "error".into(), - function_type_(list_type(char_type()), Type::new_var("a".into())), + function_type_(list_type(char_type()), "a".into()), vec![], )); Apply(Box::new(error_ident), Box::new(string("Unmatched guard"))) diff --git a/src/deriving.rs b/src/deriving.rs index 0834a76..dd5c17d 100644 --- a/src/deriving.rs +++ b/src/deriving.rs @@ -260,7 +260,7 @@ fn id(s: &str, typ: Type) -> Id { } fn compare_tags(lhs: Expr>, rhs: Expr>) -> Expr> { - let var = Type::new_var("a".into()); + let var: Type<_> = "a".into(); let typ = function_type_( var.clone(), function_type_(var.clone(), Type::new_op(name("Ordering"), vec![])), diff --git a/src/module.rs b/src/module.rs index 9747e6c..9f177fe 100644 --- a/src/module.rs +++ b/src/module.rs @@ -147,7 +147,7 @@ impl TypedExpr { ) -> TypedExpr { TypedExpr { expr, - typ: Type::new_var("a".into()), + typ: "a".into(), location: loc, } } diff --git a/src/parser.rs b/src/parser.rs index d235336..abbf912 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1004,12 +1004,13 @@ impl> Parser { fn data_definition(&mut self) -> ParseResult { expect!(self, DATA); - let mut definition = DataDefinition { - constructors: vec![], - typ: qualified(vec![], Type::new_var("a".into())), - parameters: HashMap::new(), - deriving: vec![], - }; + 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); @@ -1432,7 +1433,7 @@ in test - 2" 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("a".into()); + let a = &"a".into(); let b = &Type::new_var("b".into()); let c = &Type::new_var("c".into()); let f = function_type( @@ -1472,14 +1473,14 @@ in test - 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("a".into())]); + 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(&Type::new_var("a".into()), &function_type(&list, &list)), + function_type(&"a".into(), &function_type(&list, &list)), ), }; let nil = Constructor { @@ -1568,10 +1569,7 @@ instance Eq a => Eq [a] where 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("a".into())) - ); + assert_eq!(module.instances[0].typ, list_type("a".into())); } #[test] fn parse_super_class() { @@ -1823,7 +1821,7 @@ test = case a of newtype IntPair a = IntPair (a, Int) "; let module = Parser::new(s.chars()).module().unwrap(); - let a = Type::new_var("a".into()); + 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!( diff --git a/src/typecheck.rs b/src/typecheck.rs index d11861d..fcee6b4 100644 --- a/src/typecheck.rs +++ b/src/typecheck.rs @@ -2204,7 +2204,7 @@ main = case [mult2 123, 0] of test x = True"; let module = do_typecheck(file); - let typ = function_type_(Type::new_var("a".into()), bool_type()); + let typ = function_type_("a".into(), bool_type()); assert_eq!(module.bindings[0].typ.value, typ); } @@ -2276,8 +2276,8 @@ main x y = primIntAdd (test x) (test y)" env.typecheck_module_(&mut module); let typ = &module.bindings[0].typ; - let a = Type::new_var("a".into()); - let b = Type::new_var("b".into()); + 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"); @@ -2332,7 +2332,7 @@ test x y = case x < y of env.typecheck_module_(&mut module); let typ = &module.bindings[0].typ; - let a = Type::new_var("a".into()); + let a: Type<_> = "a".into(); assert_eq!( typ.value, function_type_(a.clone(), function_type_(a.clone(), bool_type())) @@ -2479,10 +2479,7 @@ main = fmap add2 3", .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("a".into()), Type::new_var("a".into())) - ); + assert_eq!(id_bind.typ.value, function_type_("a".into(), "a".into())); } #[test] @@ -2567,7 +2564,7 @@ test x = do "; let module = do_typecheck_with(file, &[&prelude as &dyn DataTypes]); - let var = Type::new_var("a".into()); + 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()]), @@ -2587,8 +2584,8 @@ test f (x:xs) = f x : test f xs test _ [] = [] ", ); - let a = Type::new_var("a".into()); - let b = Type::new_var("b".into()); + 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)), @@ -2608,7 +2605,7 @@ if_ p x y | True = y ", ); - let var = Type::new_var("a".into()); + let var: Type<_> = "a".into(); let test = function_type_( bool_type(), function_type_(var.clone(), function_type_(var.clone(), var.clone())), @@ -2653,7 +2650,7 @@ test x y = [x] == [y] ) .unwrap(); let module = modules.last().unwrap(); - let a = Type::new_var("a".into()); + let a: Type<_> = "a".into(); let cs = vec![Constraint { class: intern("Eq"), variables: vec![a.var().clone()], From 179c3d7edb16cde71dfc15f85c6f38b9ad3de713 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 14:07:37 -0800 Subject: [PATCH 41/76] refactoring --- src/lexer.rs | 16 ++++++---------- src/scoped_map.rs | 9 ++------- 2 files changed, 8 insertions(+), 17 deletions(-) diff --git a/src/lexer.rs b/src/lexer.rs index 5e5e0a0..673d855 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -290,17 +290,13 @@ impl> Lexer { ///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 } diff --git a/src/scoped_map.rs b/src/scoped_map.rs index fb647c3..3425687 100644 --- a/src/scoped_map.rs +++ b/src/scoped_map.rs @@ -40,13 +40,8 @@ where ///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. From c2c71f3aa828dca11da91fb812c64e5b577e9112 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 14:14:53 -0800 Subject: [PATCH 42/76] using while let --- src/parser.rs | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/src/parser.rs b/src/parser.rs index abbf912..a4e261a 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -659,12 +659,8 @@ impl> Parser { match e { Some(mut lhs) => { let mut expressions = vec![]; - loop { - let expr = self.sub_expression()?; - match expr { - Some(e) => expressions.push(e), - None => break, - } + while let Some(expr) = self.sub_expression()? { + expressions.push(expr); } if expressions.len() > 0 { let loc = lhs.location; @@ -1154,11 +1150,9 @@ impl> Parser { } NAME => { let mut type_arguments = vec![]; - loop { - match self.sub_type()? { - Some(typ) => type_arguments.push(typ), - None => break, - } + + while let Some(typ) = self.sub_type()? { + type_arguments.push(typ); } let this_type = if token From a45d17e82d540a2fda69c794a618b4f52b8d5d7d Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 14:19:13 -0800 Subject: [PATCH 43/76] refactoring --- src/infix.rs | 4 +--- src/lexer.rs | 19 +++++++------------ 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/src/infix.rs b/src/infix.rs index e3313a4..7004257 100644 --- a/src/infix.rs +++ b/src/infix.rs @@ -116,9 +116,7 @@ impl PrecedenceVisitor { location, expr: rhs, }; - while op_stack.len() != 0 { - assert!(expr_stack.len() >= 1); - let lhs = expr_stack.pop().unwrap(); + while let Some(lhs) = expr_stack.pop() { let op = op_stack.pop().unwrap(); result = TypedExpr::with_location( Expr::OpApply(lhs, op, Box::new(result)), diff --git a/src/lexer.rs b/src/lexer.rs index 673d855..42f40af 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -319,24 +319,19 @@ impl> Lexer { ///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( + 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 From 3b02d40c829f156beb0e1f9a877acb886a6e75e4 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 14:26:11 -0800 Subject: [PATCH 44/76] refactoring --- src/infix.rs | 45 +++++++++++++++++++++------------------------ src/lexer.rs | 18 ++++++------------ 2 files changed, 27 insertions(+), 36 deletions(-) diff --git a/src/infix.rs b/src/infix.rs index 7004257..24bc2b2 100644 --- a/src/infix.rs +++ b/src/infix.rs @@ -80,33 +80,30 @@ impl PrecedenceVisitor { 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"), - } - } else { - reduce(&mut expr_stack, &mut op_stack); - } - } - None => { + 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); } + } else { + op_stack.push(op); + break; } } } diff --git a/src/lexer.rs b/src/lexer.rs index 42f40af..08611d6 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -533,19 +533,13 @@ 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, From aaf63faecfb1b473d49c1ca506f5c9569fc3af7d Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 14:32:12 -0800 Subject: [PATCH 45/76] reactoring --- src/parser.rs | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/src/parser.rs b/src/parser.rs index a4e261a..c75085d 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -263,21 +263,17 @@ impl> Parser { 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(), - ) - } - } + + 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) } BindOrTypeDecl::TypeDecl(decl) => declarations.push(decl), From d1c4b05979b5d8163fe8e2fbd87cc6d3c082571d Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 14:37:45 -0800 Subject: [PATCH 46/76] reactoring --- src/parser.rs | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/src/parser.rs b/src/parser.rs index c75085d..6ff0dd8 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -282,22 +282,19 @@ impl> Parser { expect!(self, RBRACE); - match typ { - Type::Application(l, r) => match (*l, *r) { - (Type::Constructor(classname), Type::Variable(var)) => { - return Ok(Class { - constraints, - name: classname.name, - variable: var, - declarations, - bindings, - }); - } - _ => (), - }, - _ => (), - } - self.error("Parse error in class declaration header".to_string()) + 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, + }) } fn instance(&mut self) -> ParseResult { From c376e3cec0feb487326e0950ed06ffd3aadc8718 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 14:39:12 -0800 Subject: [PATCH 47/76] reactoring --- src/parser.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/parser.rs b/src/parser.rs index 6ff0dd8..a610d18 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -374,11 +374,8 @@ impl> Parser { fn list(&mut self) -> ParseResult { let mut expressions = vec![]; - loop { - match self.expression()? { - Some(expr) => expressions.push(expr), - None => break, - } + while let Some(expr) = self.expression()? { + expressions.push(expr); let comma = self.lexer.next().token; if comma != COMMA { self.lexer.backtrack(); From 752d22431c2519574fadad1d63faf505c58c902c Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 14:42:38 -0800 Subject: [PATCH 48/76] reactoring --- src/parser.rs | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/src/parser.rs b/src/parser.rs index a610d18..0f01315 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -409,13 +409,13 @@ impl> Parser { } else { let mut expressions = self.sep_by_1(|this| this.expression_(), COMMA)?; expect!(self, RPARENS); - if expressions.len() == 1 { + Some(if expressions.len() == 1 { let expr = expressions.pop().unwrap(); let loc = expr.location; - Some(TypedExpr::with_location(Paren(Box::new(expr)), loc)) + TypedExpr::with_location(Paren(Box::new(expr)), loc) } else { - Some(new_tuple(expressions)) - } + new_tuple(expressions) + }) } } LBRACKET => Some(self.list()?), @@ -423,10 +423,8 @@ impl> Parser { let binds = self.let_bindings()?; expect!(self, IN); - match self.expression()? { - Some(e) => Some(TypedExpr::new(Let(binds, Box::new(e)))), - None => None, - } + self.expression()? + .map(|e| TypedExpr::new(Let(binds, Box::new(e)))) } CASE => { let location = self.lexer.current().location; @@ -434,13 +432,10 @@ impl> Parser { 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, - } + self.expression()? + .map(|e| TypedExpr::with_location(Case(Box::new(e), alts), location)) } IF => { let location = self.lexer.current().location; From 60bf81ce26e5ba04da650106e5a3ac436a1fd272 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 14:51:09 -0800 Subject: [PATCH 49/76] refactoring --- src/parser.rs | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/parser.rs b/src/parser.rs index 0f01315..d218d34 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -434,8 +434,7 @@ impl> Parser { expect!(self, LBRACE); let alts = self.sep_by_1(|this| this.alternative(), SEMICOLON)?; expect!(self, RBRACE); - self.expression()? - .map(|e| TypedExpr::with_location(Case(Box::new(e), alts), location)) + expr.map(|e| TypedExpr::with_location(Case(Box::new(e), alts), location)) } IF => { let location = self.lexer.current().location; @@ -465,7 +464,8 @@ impl> Parser { expect!(self, LBRACE); let mut bindings = self.sep_by_1(|this| this.do_binding(), SEMICOLON)?; expect!(self, RBRACE); - if bindings.is_empty() { + + let Some(expr) = bindings.pop() else { return Err(ParseError(Located { location: self.lexer.current().location, node: Error::Message(format!( @@ -473,16 +473,14 @@ impl> Parser { self.lexer.current().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(), - ) - } - }; + }; + + 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, Box::new(expr)), location, From 999e64d6938613e1b9bc0c3439b076efe2c3698a Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 14:53:11 -0800 Subject: [PATCH 50/76] refactoring --- src/parser.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/parser.rs b/src/parser.rs index d218d34..ccc3493 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -400,7 +400,7 @@ impl> Parser { fn sub_expression(&mut self) -> ParseResult> { let token = self.lexer.next().token; debug!("Begin SubExpr {:?}", self.lexer.current()); - let expr = match token { + Ok(match token { LPARENS => { let location = self.lexer.current().location; if self.lexer.peek().token == RPARENS { @@ -525,8 +525,7 @@ impl> Parser { self.lexer.backtrack(); None } - }; - Ok(expr) + }) } fn do_binding(&mut self) -> ParseResult { @@ -575,7 +574,7 @@ impl> Parser { } fn alternative(&mut self) -> ParseResult { - let pat = self.located_pattern()?; + 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 { @@ -585,7 +584,7 @@ impl> Parser { None }; Ok(Alternative { - pattern: pat, + pattern, matches, where_bindings, }) From 215a05f73888ec6d3ebe3a9fabe9055c945f1893 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 14:55:09 -0800 Subject: [PATCH 51/76] refactoring --- src/parser.rs | 75 +++++++++++++++++++++++++-------------------------- 1 file changed, 37 insertions(+), 38 deletions(-) diff --git a/src/parser.rs b/src/parser.rs index ccc3493..1277b4e 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -592,48 +592,47 @@ impl> Parser { 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; - let loc = self.lexer.current().location; - let rhs = self.application()?; - let rhs = self.binary_expression(rhs)?; - let expr = match (lhs, rhs) { - (Some(lhs), Some(rhs)) => Some(TypedExpr::with_location( + 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.binary_expression(rhs)?; + Ok(match (lhs, rhs) { + (Some(lhs), Some(rhs)) => { + Some(TypedExpr::with_location( OpApply(Box::new(lhs), op, Box::new(rhs)), loc, - )), - (Some(lhs), None) => { - let name = TypedExpr::with_location(Identifier(op), loc); - Some(TypedExpr::with_location( - Apply(Box::new(name), Box::new(lhs)), - loc, + )) + } + (Some(lhs), None) => { + let name = TypedExpr::with_location(Identifier(op), loc); + Some(TypedExpr::with_location( + Apply(Box::new(name), Box::new(lhs)), + loc, + )) + } + (None, Some(rhs)) => { + if op == intern("-") { + 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); + 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, )) } - (None, Some(rhs)) => { - if op == intern("-") { - 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); - 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, - )) - } - } - (None, None) => return Ok(None), - }; - Ok(expr) - } else { - self.lexer.backtrack(); - Ok(lhs) - } + } + (None, None) => return Ok(None), + }) } fn application(&mut self) -> ParseResult> { From 77bd8e175bf5154f2dc01a6990803eab52e69b98 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 15:06:46 -0800 Subject: [PATCH 52/76] refactoring --- src/module.rs | 51 +++++++++++++++++++-------------------------------- 1 file changed, 19 insertions(+), 32 deletions(-) diff --git a/src/module.rs b/src/module.rs index 9f177fe..a3a3f7e 100644 --- a/src/module.rs +++ b/src/module.rs @@ -411,13 +411,10 @@ pub fn walk_alternative>(visitor: &mut V, alt: &Alterna } 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); } - _ => (), } } @@ -532,13 +529,10 @@ pub fn walk_alternative_mut>( } } } - 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 => (), } } @@ -546,13 +540,10 @@ 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); - } + if let Pattern::Constructor(_, ref mut ps) = pattern { + for p in ps.iter_mut() { + visitor.visit_pattern(p); } - _ => (), } } @@ -564,17 +555,16 @@ impl<'a, Ident: Eq> Iterator for Binds<'a, Ident> { type Item = &'a [Binding]; fn next(&mut self) -> Option<&'a [Binding]> { if self.vec.is_empty() { - 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) + 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) } } @@ -595,9 +585,6 @@ 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); + let buffer = ["#", &instancename, &bindingname].join(""); intern(buffer.as_ref()) } From 27fbe0eebec19f0c5d224cdbaa08bc1a5fe5ceb4 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 15:16:02 -0800 Subject: [PATCH 53/76] refactoring --- src/compiler.rs | 20 ++++++-------------- src/core.rs | 2 +- src/typecheck.rs | 13 +++---------- 3 files changed, 10 insertions(+), 25 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index 3697e05..4a5c009 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -577,13 +577,9 @@ impl<'a> Compiler<'a> { None => None, }) .or_else(|| { - for assembly in self.assemblies.iter() { - match assembly.find_global(identifier) { - Some(var) => return Some(var), - None => (), - } - } - None + self.assemblies + .iter() + .find_map(|assembly| assembly.find_global(identifier)) }) .or_else(|| { Compiler::find_builtin_constructor(identifier.name) @@ -595,13 +591,9 @@ impl<'a> Compiler<'a> { 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 + self.assemblies + .iter() + .find_map(|assembly| assembly.find_constructor(identifier)) }) .or_else(|| Compiler::find_builtin_constructor(identifier.name)) } diff --git a/src/core.rs b/src/core.rs index 6b041e5..946b069 100644 --- a/src/core.rs +++ b/src/core.rs @@ -1380,7 +1380,7 @@ pub mod translate { equations .iter() .filter(|&&Equation(ps, _)| { - ps.len() > 0 && matches!(ps[0].1, Pattern::WildCard | Pattern::Identifier(..)) + !ps.is_empty() && matches!(ps[0].1, Pattern::WildCard | Pattern::Identifier(..)) }) .map(|eq| { let &Equation(ps, _) = eq; diff --git a/src/typecheck.rs b/src/typecheck.rs index fcee6b4..ad1acad 100644 --- a/src/typecheck.rs +++ b/src/typecheck.rs @@ -774,16 +774,9 @@ impl<'a> TypeEnvironment<'a> { &mut typ2, &mut guard.expression.typ, ); - match typ { - Some(mut typ) => unify_location( - self, - subs, - &guard.expression.location, - &mut typ, - &mut typ2, - ), - None => (), - } + 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( From 1e7bdb3c860d334342c1bf751673a6dcbe92f80c Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 15:23:11 -0800 Subject: [PATCH 54/76] nitpicks --- src/typecheck.rs | 40 ++++++++++++++++------------------------ 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/src/typecheck.rs b/src/typecheck.rs index ad1acad..817c98d 100644 --- a/src/typecheck.rs +++ b/src/typecheck.rs @@ -361,12 +361,9 @@ impl<'a> TypeEnvironment<'a> { }; //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 => (), - } + if let Some(ref k) = var_kind { + class.variable.kind.clone_from(k); + }; let c = Constraint { class: class.name.clone(), @@ -1133,11 +1130,8 @@ impl<'a> TypeEnvironment<'a> { &mut bindings[0].typ.value, ); } - match type_var { - Some(var) => { - subs.subs.insert(var, final_type); - } - None => (), + if let Some(var) = type_var { + subs.subs.insert(var, final_type); } for bind in bindings.iter_mut() { match bind.matches { @@ -1506,9 +1500,8 @@ fn freshen(env: &mut TypeEnvironment, subs: &mut Substitution, typ: &mut Qualifi } 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(); } } } @@ -1523,9 +1516,8 @@ fn freshen_all(env: &mut TypeEnvironment, subs: &mut Substitution, typ: &mut TcT } _ => 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 @@ -1857,13 +1849,13 @@ fn add_edges( } 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 { From 98ab3d8573b392ac30d714ee78c673736fb28abf Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 15:25:12 -0800 Subject: [PATCH 55/76] nitpicks --- src/typecheck.rs | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/src/typecheck.rs b/src/typecheck.rs index 817c98d..3f3ae90 100644 --- a/src/typecheck.rs +++ b/src/typecheck.rs @@ -1378,9 +1378,8 @@ fn quantify(start_var_age: isize, typ: &mut Qualified) { } _ => None, }; - match x { - Some(var) => *typ = Type::Generic(var), - None => (), + if let Some(var) = x { + *typ = Type::Generic(var); } } for constraint in typ.constraints.iter_mut() { @@ -1460,9 +1459,8 @@ fn replace( } _ => None, //panic!("replace called on Generic") }; - match replaced { - Some(x) => *old = x, - None => (), + if let Some(x) = replaced { + *old = x; } } @@ -1493,9 +1491,8 @@ fn freshen(env: &mut TypeEnvironment, subs: &mut Substitution, typ: &mut Qualifi } _ => None, }; - match result { - Some(x) => *typ = x, - None => (), + if let Some(x) = result { + *typ = x; } } freshen_(env, subs, &*typ.constraints, &mut typ.value); @@ -1616,13 +1613,10 @@ fn bind_variable( 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(()) From 292d87d241f99e2bb6bca76ca1a8362c84a2c8a2 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 15:27:30 -0800 Subject: [PATCH 56/76] refactoring --- src/typecheck.rs | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/src/typecheck.rs b/src/typecheck.rs index 3f3ae90..bab8944 100644 --- a/src/typecheck.rs +++ b/src/typecheck.rs @@ -1080,16 +1080,13 @@ impl<'a> TypeEnvironment<'a> { 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 { @@ -1100,11 +1097,8 @@ impl<'a> TypeEnvironment<'a> { } } 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); From 8dcc14370d6bf60f5862a3d54cffd29dd7e0f043 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 15:29:20 -0800 Subject: [PATCH 57/76] fixing dereferencing --- src/core.rs | 10 ++-- src/lambda_lift.rs | 12 ++--- src/module.rs | 26 +++++----- src/parser.rs | 4 +- src/typecheck.rs | 121 ++++++++++++++++++++------------------------- src/types.rs | 2 +- 6 files changed, 79 insertions(+), 96 deletions(-) diff --git a/src/core.rs b/src/core.rs index 946b069..0379c1e 100644 --- a/src/core.rs +++ b/src/core.rs @@ -320,18 +320,18 @@ 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); } diff --git a/src/lambda_lift.rs b/src/lambda_lift.rs index 47b70d8..23d2fdc 100644 --- a/src/lambda_lift.rs +++ b/src/lambda_lift.rs @@ -56,8 +56,8 @@ impl FreeVariables { } } Apply(ref mut func, ref mut arg) => { - self.free_variables(variables, free_vars, &mut **func); - self.free_variables(variables, free_vars, &mut **arg); + self.free_variables(variables, free_vars, func); + self.free_variables(variables, free_vars, arg); } Lambda(ref mut arg, ref mut body) => { match variables.entry(arg.name.clone()) { @@ -66,7 +66,7 @@ impl FreeVariables { } Entry::Occupied(mut entry) => *entry.get_mut() += 1, } - self.free_variables(variables, free_vars, &mut **body); + 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 } @@ -89,14 +89,14 @@ impl FreeVariables { } self.abstract_(&free_vars2, &mut bind.expression); } - self.free_variables(variables, free_vars, &mut **expr); + 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, &mut **expr); + 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()) @@ -173,7 +173,7 @@ pub fn lift_lambdas(mut module: Module) -> Module { } } *bindings = new_binds; - self.visit_expr(&mut **body); + self.visit_expr(body); } _ => walk_expr(self, expr), } diff --git a/src/module.rs b/src/module.rs index a3a3f7e..15c3df2 100644 --- a/src/module.rs +++ b/src/module.rs @@ -467,30 +467,30 @@ pub fn walk_binding_mut>( 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() { @@ -507,10 +507,10 @@ pub fn walk_expr_mut>(visitor: &mut V, expr: &mut Ty 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), + TypeSig(ref mut expr, _) => visitor.visit_expr(expr), + Paren(ref mut expr) => visitor.visit_expr(expr), Literal(..) | Identifier(..) => (), } } diff --git a/src/parser.rs b/src/parser.rs index 1277b4e..01c82b4 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1053,9 +1053,7 @@ impl> Parser { fn set_kind(typ: &mut Type, kind: isize) { match typ { - &mut Type::Application(ref mut lhs, _) => { - Parser::::set_kind(&mut **lhs, kind + 1) - } + &mut Type::Application(ref mut lhs, _) => Parser::::set_kind(lhs, kind + 1), _ => *typ.mut_kind() = Kind::new(kind), } } diff --git a/src/typecheck.rs b/src/typecheck.rs index bab8944..5be2f1f 100644 --- a/src/typecheck.rs +++ b/src/typecheck.rs @@ -839,40 +839,35 @@ impl<'a> TypeEnvironment<'a> { 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), }; - 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); + let mut match_type = self.typecheck(case_expr, subs); self.typecheck_pattern( &alts[0].pattern.location, subs, @@ -880,12 +875,8 @@ impl<'a> TypeEnvironment<'a> { &mut match_type, ); match *&mut alts[0].where_bindings { - Some(ref mut bindings) => self.typecheck_local_bindings( - subs, - &mut BindingsWrapper { - value: &mut **bindings, - }, - ), + 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); @@ -899,9 +890,7 @@ impl<'a> TypeEnvironment<'a> { match alt.where_bindings { Some(ref mut bindings) => self.typecheck_local_bindings( subs, - &mut BindingsWrapper { - value: &mut **bindings, - }, + &mut BindingsWrapper { value: bindings }, ), None => (), } @@ -911,10 +900,10 @@ 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 } @@ -933,9 +922,7 @@ impl<'a> TypeEnvironment<'a> { DoBinding::DoLet(ref mut bindings) => { self.typecheck_local_bindings( subs, - &mut BindingsWrapper { - value: &mut **bindings, - }, + &mut BindingsWrapper { value: bindings }, ); self.apply_locals(subs); } @@ -950,7 +937,7 @@ impl<'a> TypeEnvironment<'a> { &pattern.location, subs, &pattern.node, - &mut **inner_type, + inner_type, ); } } @@ -961,12 +948,12 @@ impl<'a> TypeEnvironment<'a> { _ => 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, @@ -977,7 +964,7 @@ impl<'a> TypeEnvironment<'a> { ); 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(); @@ -1081,12 +1068,7 @@ impl<'a> TypeEnvironment<'a> { self.typecheck_pattern(&Location::eof(), subs, arg, typ); } if let Some(ref mut bindings) = bind.where_bindings { - self.typecheck_local_bindings( - subs, - &mut BindingsWrapper { - value: 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 { @@ -1363,15 +1345,16 @@ fn find_specialized( ///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, - }; + 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); } @@ -1396,8 +1379,8 @@ pub fn replace_var(typ: &mut TcType, var: &TypeVariable, replacement: &TcType) { } 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"), @@ -1447,8 +1430,8 @@ fn replace( let replaced = match *old { 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") @@ -1479,8 +1462,8 @@ fn freshen(env: &mut TypeEnvironment, subs: &mut Substitution, typ: &mut Qualifi 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, @@ -1501,8 +1484,8 @@ 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, @@ -1682,10 +1665,10 @@ fn unify( ( &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) + ) => 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 @@ -1767,9 +1750,9 @@ fn match_( ) -> 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)) => { @@ -1912,13 +1895,15 @@ 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 + Type::Application(ref mut lhs, ref mut return_type) => { + match **lhs { + Type::Application(_, ref mut arg_type) => { + func(arg_type, return_type); + true + } + _ => false, } - _ => false, - }, + } _ => false, } } diff --git a/src/types.rs b/src/types.rs index 292c19b..f3c141d 100644 --- a/src/types.rs +++ b/src/types.rs @@ -176,7 +176,7 @@ impl> Type { 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) => &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, From 9bc24515ea88fdb2ad754b9f79e2f6853df3087a Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 15:31:21 -0800 Subject: [PATCH 58/76] refactoring --- src/typecheck.rs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/typecheck.rs b/src/typecheck.rs index 5be2f1f..e6cdb78 100644 --- a/src/typecheck.rs +++ b/src/typecheck.rs @@ -1894,18 +1894,13 @@ 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(arg_type, return_type); - true - } - _ => false, - } + 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)] From 2513a5a99af4814971e1914b0185da15cb77f68c Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 15:37:29 -0800 Subject: [PATCH 59/76] refactoring --- src/deriving.rs | 11 +++++------ src/typecheck.rs | 23 ++++++++--------------- 2 files changed, 13 insertions(+), 21 deletions(-) diff --git a/src/deriving.rs b/src/deriving.rs index dd5c17d..3848e10 100644 --- a/src/deriving.rs +++ b/src/deriving.rs @@ -300,12 +300,11 @@ 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 } } } diff --git a/src/typecheck.rs b/src/typecheck.rs index e6cdb78..e29e009 100644 --- a/src/typecheck.rs +++ b/src/typecheck.rs @@ -1385,27 +1385,20 @@ pub fn replace_var(typ: &mut TcType, var: &TypeVariable, replacement: &TcType) { } 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, - } + 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, + } } + false } ///Extracts the final return type of a type fn get_returntype(typ: &TcType) -> TcType { From 2d072ae069009eee9829712e372607cb629ad2cb Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 15:39:17 -0800 Subject: [PATCH 60/76] refactoring --- src/typecheck.rs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/typecheck.rs b/src/typecheck.rs index e29e009..92d8aab 100644 --- a/src/typecheck.rs +++ b/src/typecheck.rs @@ -1402,15 +1402,13 @@ fn is_function(typ: &TcType) -> bool { } ///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() } } From 885bcf4857b3345f2ae2c168b93d6821bd8c579b Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 15:43:02 -0800 Subject: [PATCH 61/76] refactoring --- src/compiler.rs | 4 ++-- src/core.rs | 19 ++++++++----------- src/deriving.rs | 10 +++++----- src/infix.rs | 4 ++-- src/lambda_lift.rs | 4 ++-- src/parser.rs | 22 +++++++++++----------- src/typecheck.rs | 16 ++++++++-------- src/types.rs | 6 +++--- 8 files changed, 41 insertions(+), 44 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index 4a5c009..b7a41af 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -678,7 +678,7 @@ impl<'a> Compiler<'a> { typ: int_type(), value: Integral(i), }); - let apply = Apply(Box::new(from_integer), Box::new(number)); + let apply = Apply(from_integer.into(), number.into()); self.compile(&apply, instructions, strict); } } @@ -697,7 +697,7 @@ impl<'a> Compiler<'a> { typ: double_type(), value: Fractional(f), }); - let apply = Apply(Box::new(from_rational), Box::new(number)); + let apply = Apply(from_rational.into(), number.into()); self.compile(&apply, instructions, strict); } } diff --git a/src/core.rs b/src/core.rs index 0379c1e..72c3eac 100644 --- a/src/core.rs +++ b/src/core.rs @@ -403,7 +403,7 @@ 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))), Let(binds, e) => { @@ -419,7 +419,7 @@ pub mod result { .into_iter() .map(|alt| visitor.visit_alternative(alt)) .collect(); - Case(Box::new(e2), alts2) + Case(e2.into(), alts2) } expr => expr, } @@ -761,17 +761,14 @@ pub mod translate { core.get_type().clone(), result.get_type().clone(), ); - Apply( - Box::new(Apply(Box::new(x), Box::new(core))), - Box::new(result), - ) + 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), Box::new(result)) + Let(self.translate_bindings(bs), result.into()) } }; } @@ -851,7 +848,7 @@ pub mod translate { Alternative { pattern: Pattern::WildCard, expression: Apply( - Box::new(fail_ident), + fail_ident.into(), Box::new(string("Unmatched pattern in let")), ), }, @@ -1361,7 +1358,7 @@ pub mod translate { ///Creates a function application from a function and its arguments 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 } @@ -1370,7 +1367,7 @@ pub mod translate { if bindings.is_empty() { expr } else { - Let(bindings, Box::new(expr)) + Let(bindings, expr.into()) } } @@ -1417,6 +1414,6 @@ pub mod translate { function_type_(list_type(char_type()), "a".into()), vec![], )); - Apply(Box::new(error_ident), Box::new(string("Unmatched guard"))) + Apply(error_ident.into(), Box::new(string("Unmatched guard"))) } } diff --git a/src/deriving.rs b/src/deriving.rs index 3848e10..09f92ff 100644 --- a/src/deriving.rs +++ b/src/deriving.rs @@ -133,7 +133,7 @@ impl DerivingGen { 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 + 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 @@ -174,7 +174,7 @@ impl DerivingGen { vec![], ); Case( - Box::new(cmp), + cmp.into(), vec![ Alternative { pattern: Pattern::Constructor( @@ -267,8 +267,8 @@ fn compare_tags(lhs: Expr>, rhs: Expr>) -> Expr> { ); let id = Id::new(name("#compare_tags"), typ, vec![]); Apply( - Box::new(Apply(Box::new(Identifier(id)), Box::new(lhs))), - Box::new(rhs), + Box::new(Apply(Box::new(Identifier(id)), lhs.into())), + rhs.into(), ) } @@ -286,7 +286,7 @@ fn binop( function_type_(rhs.get_type().clone(), return_type), ); let f = Identifier(Id::new(name(op), typ, vec![])); - Apply(Box::new(Apply(Box::new(f), Box::new(lhs))), Box::new(rhs)) + Apply(Box::new(Apply(f.into(), lhs.into())), rhs.into()) } fn true_expr() -> Expr> { diff --git a/src/infix.rs b/src/infix.rs index 24bc2b2..ba97cef 100644 --- a/src/infix.rs +++ b/src/infix.rs @@ -21,7 +21,7 @@ impl MutVisitor for PrecedenceVisitor { 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); } _ => (), @@ -116,7 +116,7 @@ impl PrecedenceVisitor { while let Some(lhs) = expr_stack.pop() { let op = op_stack.pop().unwrap(); result = TypedExpr::with_location( - Expr::OpApply(lhs, op, Box::new(result)), + Expr::OpApply(lhs, op, result.into()), location, ); } diff --git a/src/lambda_lift.rs b/src/lambda_lift.rs index 23d2fdc..f7067f7 100644 --- a/src/lambda_lift.rs +++ b/src/lambda_lift.rs @@ -132,7 +132,7 @@ impl FreeVariables { let mut rhs = temp; let mut typ = rhs.get_type().clone(); for (_, var) in free_vars.iter() { - rhs = Lambda(var.clone(), Box::new(rhs)); + 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![]); @@ -143,7 +143,7 @@ impl FreeVariables { Let(vec![bind], Box::new(Identifier(id))) }; for (_, var) in free_vars.iter() { - e = Apply(Box::new(e), Box::new(Identifier(var.clone()))); + e = Apply(e.into(), Box::new(Identifier(var.clone()))); } *input_expr = e } diff --git a/src/parser.rs b/src/parser.rs index 01c82b4..1f6b3f5 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -355,7 +355,7 @@ impl> Parser { let loc = expr.location; Ok(Some(TypedExpr::with_location( TypeSig( - Box::new(expr), + expr.into(), Qualified { constraints, value: typ, @@ -412,7 +412,7 @@ impl> Parser { Some(if expressions.len() == 1 { let expr = expressions.pop().unwrap(); let loc = expr.location; - TypedExpr::with_location(Paren(Box::new(expr)), loc) + TypedExpr::with_location(Paren(expr.into()), loc) } else { new_tuple(expressions) }) @@ -424,7 +424,7 @@ impl> Parser { expect!(self, IN); self.expression()? - .map(|e| TypedExpr::new(Let(binds, Box::new(e)))) + .map(|e| TypedExpr::new(Let(binds, e.into()))) } CASE => { let location = self.lexer.current().location; @@ -434,7 +434,7 @@ impl> Parser { expect!(self, LBRACE); let alts = self.sep_by_1(|this| this.alternative(), SEMICOLON)?; expect!(self, RBRACE); - expr.map(|e| TypedExpr::with_location(Case(Box::new(e), alts), location)) + expr.map(|e| TypedExpr::with_location(Case(e.into(), alts), location)) } IF => { let location = self.lexer.current().location; @@ -450,7 +450,7 @@ impl> Parser { expect!(self, ELSE); let if_false = self.expression_()?; Some(TypedExpr::with_location( - IfElse(Box::new(pred), Box::new(if_true), Box::new(if_false)), + IfElse(pred.into(), if_true.into(), if_false.into()), location, )) } @@ -482,7 +482,7 @@ impl> Parser { }; Some(TypedExpr::with_location( - Do(bindings, Box::new(expr)), + Do(bindings, expr.into()), location, )) } @@ -603,14 +603,14 @@ impl> Parser { Ok(match (lhs, rhs) { (Some(lhs), Some(rhs)) => { Some(TypedExpr::with_location( - OpApply(Box::new(lhs), op, Box::new(rhs)), + 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)), + Apply(name.into(), lhs.into()), loc, )) } @@ -1030,7 +1030,7 @@ impl> Parser { }); while self.lexer.next().token == NAME { typ = Type::Application( - Box::new(typ), + typ.into(), Box::new(Type::new_var(self.lexer.current().value)), ); } @@ -1202,7 +1202,7 @@ fn make_application>(f: TypedExpr, args: I) -> Typ let mut func = f; 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 } @@ -1214,7 +1214,7 @@ fn make_lambda>>( 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 } diff --git a/src/typecheck.rs b/src/typecheck.rs index 92d8aab..0c8f91b 100644 --- a/src/typecheck.rs +++ b/src/typecheck.rs @@ -912,7 +912,7 @@ impl<'a> TypeEnvironment<'a> { self.new_var_kind(Kind::Function(Box::new(Kind::Star), Box::new(Kind::Star))); self.constraints .insert(previous.var().clone(), vec!["Monad".into()]); - previous = Type::Application(Box::new(previous), Box::new(self.new_var())); + previous = Type::Application(previous.into(), Box::new(self.new_var())); for bind in bindings.iter_mut() { match *bind { DoBinding::DoExpr(ref mut e) => { @@ -1900,7 +1900,7 @@ pub fn identifier(i: &str) -> TypedExpr { } #[cfg(test)] pub fn lambda(arg: &str, body: TypedExpr) -> TypedExpr { - TypedExpr::new(Lambda(Pattern::Identifier(intern(arg)), Box::new(body))) + TypedExpr::new(Lambda(Pattern::Identifier(intern(arg)), body.into())) } #[cfg(test)] pub fn number(i: isize) -> TypedExpr { @@ -1912,27 +1912,27 @@ pub fn rational(i: f64) -> TypedExpr { } #[cfg(test)] pub fn apply(func: TypedExpr, arg: TypedExpr) -> TypedExpr { - TypedExpr::new(Apply(Box::new(func), Box::new(arg))) + 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))) + TypedExpr::new(Let(bindings, expr.into())) } #[cfg(test)] pub fn case(expr: TypedExpr, alts: Vec) -> TypedExpr { - TypedExpr::new(Case(Box::new(expr), alts)) + 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))) + TypedExpr::new(Paren(expr.into())) } pub fn typecheck_string(module: &str) -> Result>, ::std::string::String> { diff --git a/src/types.rs b/src/types.rs index f3c141d..be3997f 100644 --- a/src/types.rs +++ b/src/types.rs @@ -106,14 +106,14 @@ impl> Type { 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: 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 } @@ -319,7 +319,7 @@ impl Kind { pub fn new(v: isize) -> Self { let mut kind = Self::Star.clone(); for _ in 1..v { - kind = Self::Function(Box::new(Self::Star), Box::new(kind)); + kind = Self::Function(Box::new(Self::Star), kind.into()); } kind } From 59a6d0b7005f646fd5c244e30fb4f37bb908968a Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 15:47:18 -0800 Subject: [PATCH 62/76] refactoring --- src/parser.rs | 13 +++++-------- src/types.rs | 1 + 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/parser.rs b/src/parser.rs index 1f6b3f5..e5e3b25 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -162,14 +162,11 @@ impl> Parser { }; let mut imports = vec![]; - loop { - if self.lexer.peek().token == IMPORT { - imports.push(self.import()?); - if self.lexer.peek().token == SEMICOLON { - self.lexer.next(); - } else { - break; - } + + while self.lexer.peek().token == IMPORT { + imports.push(self.import()?); + if self.lexer.peek().token == SEMICOLON { + self.lexer.next(); } else { break; } diff --git a/src/types.rs b/src/types.rs index be3997f..27e41d6 100644 --- a/src/types.rs +++ b/src/types.rs @@ -40,6 +40,7 @@ pub enum Type { Application(Box, Box), Generic(TypeVariable), } + #[derive(Clone, Debug, Default, Hash)] pub struct Qualified { pub constraints: Vec>, From 6d39deb51cd7f67c6a1086dafaec42efaa9dc3eb Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 15:53:07 -0800 Subject: [PATCH 63/76] refactoring --- src/lexer.rs | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/src/lexer.rs b/src/lexer.rs index 08611d6..5917351 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -557,9 +557,7 @@ impl> Lexer { return self.scan_identifier(c, start_location); } 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 { @@ -581,17 +579,12 @@ impl> Lexer { } } } 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"), + 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, From 308a0b6ae982a084382653b9c471668b83ed4a36 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 16:10:01 -0800 Subject: [PATCH 64/76] refactoring --- src/compiler.rs | 27 +++++---------------------- src/core.rs | 43 +++++++++++++++++++++---------------------- src/deriving.rs | 2 +- src/lambda_lift.rs | 4 ++-- src/renamer.rs | 10 +++++----- src/repl.rs | 16 ++++++---------- src/typecheck.rs | 2 +- src/types.rs | 2 +- 8 files changed, 42 insertions(+), 64 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index b7a41af..2655c99 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -82,7 +82,7 @@ pub enum Instruction { ConstructDictionary(usize), PushDictionaryRange(usize, usize), } -#[derive(Debug)] +#[derive(Debug, Clone)] enum Var<'a> { Stack(usize), Global(usize), @@ -122,21 +122,6 @@ static BINARY_PRIMITIVES: &'static [(&'static str, Instruction)] = &[ ("primDoubleGE", DoubleGE), ]; -impl<'a> Clone for Var<'a> { - fn clone(&self) -> Self { - match *self { - Self::Stack(x) => Self::Stack(x), - Self::Global(x) => Self::Global(x), - Self::Constructor(x, y) => Self::Constructor(x, y), - Self::Class(x, y, z) => Self::Class(x, y, z), - Self::Constraint(x, y, z) => Self::Constraint(x, y, z), - Self::Builtin(x) => Self::Builtin(x), - Self::Primitive(x, y) => Self::Primitive(x, y), - Self::Newtype => Self::Newtype, - } - } -} - pub struct SuperCombinator { pub arity: usize, pub name: Name, @@ -174,13 +159,11 @@ impl Globals for Assembly { 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) - ); + return Some(if sc.typ.constraints.len() > 0 { + Var::Constraint(self.offset + index, &sc.typ.value, &*sc.typ.constraints) } else { - return Some(Var::Global(self.offset + index)); - } + Var::Global(self.offset + index) + }); } index += 1; } diff --git a/src/core.rs b/src/core.rs index 72c3eac..dcad7b6 100644 --- a/src/core.rs +++ b/src/core.rs @@ -705,34 +705,33 @@ pub mod translate { function_type_(r.get_type().clone(), typ), ); Apply( - Box::new(Apply( - Box::new(Identifier(Id::new(op, func_type, vec![]))), - l, - )), + Apply(Identifier(Id::new(op, func_type, vec![])).into(), l).into(), r, ) } 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![]), - Box::new(self.translate_expr_rest(*body)), - ), - module::Pattern::WildCard => Lambda( - Id::new( - Name { - name: intern("_"), - uid: usize::max_value(), - }, - typ, - vec![], + module::Expr::Lambda(arg, body) => { + match arg { + module::Pattern::Identifier(arg) => Lambda( + Id::new(arg, typ, vec![]), + self.translate_expr_rest(*body).into(), ), - Box::new(self.translate_expr_rest(*body)), - ), - _ => { - panic!("Core translation of pattern matches in lambdas are not implemented") + 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))) diff --git a/src/deriving.rs b/src/deriving.rs index 09f92ff..afbfd95 100644 --- a/src/deriving.rs +++ b/src/deriving.rs @@ -57,7 +57,7 @@ impl DerivingGen { 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) + Case(Identifier(id_l.clone()).into(), alts) }) } diff --git a/src/lambda_lift.rs b/src/lambda_lift.rs index f7067f7..425ebb4 100644 --- a/src/lambda_lift.rs +++ b/src/lambda_lift.rs @@ -140,10 +140,10 @@ impl FreeVariables { name: id.clone(), expression: rhs, }; - Let(vec![bind], Box::new(Identifier(id))) + Let(vec![bind], Identifier(id).into()) }; for (_, var) in free_vars.iter() { - e = Apply(e.into(), Box::new(Identifier(var.clone()))); + e = Apply(e.into(), Identifier(var.clone()).into()); } *input_expr = e } diff --git a/src/renamer.rs b/src/renamer.rs index 8c8a18f..7d653df 100644 --- a/src/renamer.rs +++ b/src/renamer.rs @@ -310,22 +310,22 @@ impl Renamer { 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))), + Apply(func, arg) => Apply(self.rename(*func).into(), self.rename(*arg).into()), OpApply(lhs, op, rhs) => OpApply( - Box::new(self.rename(*lhs)), + self.rename(*lhs).into(), self.get_name(op), - Box::new(self.rename(*rhs)), + 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 } diff --git a/src/repl.rs b/src/repl.rs index 9b94743..76754eb 100644 --- a/src/repl.rs +++ b/src/repl.rs @@ -21,13 +21,12 @@ use crate::{ ///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 @@ -100,10 +99,7 @@ pub fn start() { 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) => { diff --git a/src/typecheck.rs b/src/typecheck.rs index 0c8f91b..06cb108 100644 --- a/src/typecheck.rs +++ b/src/typecheck.rs @@ -443,7 +443,7 @@ impl<'a> TypeEnvironment<'a> { .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)) + Kind::Function(Kind::Star.into(), Kind::Star.into()) } else { Kind::Star } diff --git a/src/types.rs b/src/types.rs index 27e41d6..b14eae4 100644 --- a/src/types.rs +++ b/src/types.rs @@ -204,7 +204,7 @@ impl Type { }) } Self::Application(lhs, rhs) => { - Type::Application(Box::new(lhs.map_(f)), Box::new(rhs.map_(f))) + Type::Application(lhs.map_(f).into(), rhs.map_(f).into()) } Self::Generic(v) => Type::Generic(v), } From a1136e4338a3f4d7126b96dce49f6626ca723a58 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 16:16:58 -0800 Subject: [PATCH 65/76] refactoring --- src/compiler.rs | 54 ++++++++++++++++++++----------------------------- 1 file changed, 22 insertions(+), 32 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index 2655c99..5b781f9 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -239,10 +239,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() { @@ -291,15 +289,12 @@ impl Types for Module { 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 Type::Constructor(ref z) = extract_applied_type(typ) else { + panic!(); }; - let z = - match extract_applied_type(typ) { - &Type::Constructor(ref x) => x, - _ => panic!(), - }; if classname == instance.classname && y.name == z.name { return Some((instance.constraints.as_ref(), &instance.typ)); } @@ -332,7 +327,7 @@ impl Types for Assembly { } } } - return None; + None } fn find_class<'a>( @@ -360,25 +355,20 @@ impl Types for Assembly { 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 From 4528843d7940d05ce3be2a3aa790c5f3a07fd271 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 16:23:07 -0800 Subject: [PATCH 66/76] refactoring --- src/compiler.rs | 7 ++++--- src/lexer.rs | 27 ++++++++++++--------------- src/scoped_map.rs | 2 ++ 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index 5b781f9..167d4cd 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -1194,9 +1194,10 @@ fn try_find_instance_type<'a>( 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)) => { diff --git a/src/lexer.rs b/src/lexer.rs index 5917351..d90a194 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -116,7 +116,7 @@ impl Token { fn new(interner: &Rc>, token: TokenEnum, value: &str, loc: Location) -> Self { Self { token, - value: (**interner).borrow_mut().intern(value), + value: interner.borrow_mut().intern(value), location: loc, } } @@ -269,22 +269,19 @@ 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 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(); - } + 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 diff --git a/src/scoped_map.rs b/src/scoped_map.rs index 3425687..4d6e38a 100644 --- a/src/scoped_map.rs +++ b/src/scoped_map.rs @@ -37,6 +37,7 @@ where 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) { @@ -44,6 +45,7 @@ where 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()) { From 21f6c249fb953bfdd05c876098df78e74cbb1f87 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 19:23:38 -0800 Subject: [PATCH 67/76] refactoring --- src/lambda_lift.rs | 8 +++++--- src/parser.rs | 11 ++++------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/lambda_lift.rs b/src/lambda_lift.rs index 425ebb4..d38f0a9 100644 --- a/src/lambda_lift.rs +++ b/src/lambda_lift.rs @@ -216,9 +216,11 @@ 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 = diff --git a/src/parser.rs b/src/parser.rs index e5e3b25..d0e041e 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1026,10 +1026,7 @@ impl> Parser { kind: Kind::Star.clone(), }); while self.lexer.next().token == NAME { - typ = Type::Application( - typ.into(), - Box::new(Type::new_var(self.lexer.current().value)), - ); + typ = Type::Application(typ.into(), Type::new_var(self.lexer.current().value).into()); } self.lexer.backtrack(); Parser::::set_kind(&mut typ, 1); @@ -1488,7 +1485,7 @@ in test - 2" expr, case( TypedExpr::new(TypeSig( - Box::new(identifier("()")), + identifier("()").into(), qualified(vec![], Type::new_op(intern("()"), vec![])) )), vec![Alternative { @@ -1583,7 +1580,7 @@ instance Eq a => Eq [a] where identifier("getContents"), ), ], - Box::new(apply(identifier("return"), identifier("s"))), + apply(identifier("return".into(), identifier("s"))), )); assert_eq!(module.bindings[0].matches, Match::Simple(b)); } @@ -1597,7 +1594,7 @@ instance Eq a => Eq [a] where ); assert_eq!( expr, - TypedExpr::new(Lambda(pattern, Box::new(identifier("x")))) + TypedExpr::new(Lambda(pattern, identifier("x"))).into() ); } From 3a4fd3d62f8677644795f791834d75ed2dc86c51 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 19:37:51 -0800 Subject: [PATCH 68/76] refactoring --- src/compiler.rs | 10 +++++----- src/core.rs | 4 ++-- src/deriving.rs | 2 +- src/lexer.rs | 2 +- src/main.rs | 2 +- src/parser.rs | 2 +- src/renamer.rs | 2 +- src/repl.rs | 4 ++-- src/typecheck.rs | 2 +- 9 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index 167d4cd..6b4b704 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -150,7 +150,7 @@ impl Globals for Assembly { for decl in class.declarations.iter() { if decl.name == name { return Some( - Var::Class(&decl.typ.value, &*decl.typ.constraints, &class.variable) + Var::Class(&decl.typ.value, &decl.typ.constraints, &class.variable) ); } } @@ -160,7 +160,7 @@ impl Globals for Assembly { for sc in self.super_combinators.iter() { if name == sc.name { return Some(if sc.typ.constraints.len() > 0 { - Var::Constraint(self.offset + index, &sc.typ.value, &*sc.typ.constraints) + Var::Constraint(self.offset + index, &sc.typ.value, &sc.typ.constraints) } else { Var::Global(self.offset + index) }); @@ -186,7 +186,7 @@ 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 { - return Some(Var::Class(&decl.typ.value, &*decl.typ.constraints, &class.variable)); + return Some(Var::Class(&decl.typ.value, &decl.typ.constraints, &class.variable)); } } } @@ -956,7 +956,7 @@ impl<'a> Compiler<'a> { None => { let dictionary_key = find_specialized_instances(function_type, actual_type, constraints); - self.push_dictionary(constraints, &*dictionary_key, instructions); + self.push_dictionary(constraints, &dictionary_key, instructions); } } } @@ -965,7 +965,7 @@ impl<'a> Compiler<'a> { //push dictionary let dictionary_key = find_specialized_instances(function_type, actual_type, constraints); - self.push_dictionary(constraints, &*dictionary_key, instructions); + self.push_dictionary(constraints, &dictionary_key, instructions); } } } diff --git a/src/core.rs b/src/core.rs index dcad7b6..24bbe42 100644 --- a/src/core.rs +++ b/src/core.rs @@ -905,7 +905,7 @@ pub mod translate { //as the same since their binding variable are the same name.truncate(base_length); name.push('_'); - name.push_str(&*i.to_string()); + name.push_str(&i.to_string()); let n = Name { name: intern(name.as_ref()), @@ -1064,7 +1064,7 @@ pub mod translate { let where_bindings_binds = where_bindings.map_or(vec![], |bs| self.translate_bindings(bs)); ( - self.unwrap_patterns(uid, arg_ids.as_ref(), &*arguments), + self.unwrap_patterns(uid, arg_ids.as_ref(), &arguments), where_bindings_binds, matches, ) diff --git a/src/deriving.rs b/src/deriving.rs index afbfd95..b5ad8e9 100644 --- a/src/deriving.rs +++ b/src/deriving.rs @@ -230,7 +230,7 @@ impl DerivingGen { iter.typ.clone(), constructor.typ.constraints.clone(), ); - let expr = f(self, &*args_l, &*args_r); + 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())), diff --git a/src/lexer.rs b/src/lexer.rs index d90a194..4cd3775 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -581,7 +581,7 @@ impl> Lexer { panic!("Multi char character") } //FIXME: Slow - return Token::new(&self.interner, CHAR, &*x.to_string(), start_location); + return Token::new(&self.interner, CHAR, &x.to_string(), start_location); } let tok = match c { ';' => SEMICOLON, diff --git a/src/main.rs b/src/main.rs index 50093f5..ea7de50 100644 --- a/src/main.rs +++ b/src/main.rs @@ -82,7 +82,7 @@ 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), diff --git a/src/parser.rs b/src/parser.rs index d0e041e..b8e6041 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -311,7 +311,7 @@ impl> Parser { let mut bindings = self.sep_by_1(|this| this.binding(), SEMICOLON)?; { - let inner_type = extract_applied_type(&*arg); + let inner_type = extract_applied_type(&arg); for bind in bindings.iter_mut() { bind.name = encode_binding_identifier(inner_type.ctor().name, bind.name); } diff --git a/src/renamer.rs b/src/renamer.rs index 7d653df..c93490b 100644 --- a/src/renamer.rs +++ b/src/renamer.rs @@ -207,7 +207,7 @@ impl Renamer { 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(&class.bindings).map(|binds| binds[0].name)) })) .chain(binding_groups(module.bindings.as_ref()).map(|binds| binds[0].name)); for name in names { diff --git a/src/repl.rs b/src/repl.rs index 76754eb..67eeb34 100644 --- a/src/repl.rs +++ b/src/repl.rs @@ -83,7 +83,7 @@ pub fn run_and_print_expr(expr_str: &str) { 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); } @@ -109,7 +109,7 @@ pub fn start() { }; 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/typecheck.rs b/src/typecheck.rs index 06cb108..1223cc0 100644 --- a/src/typecheck.rs +++ b/src/typecheck.rs @@ -1463,7 +1463,7 @@ fn freshen(env: &mut TypeEnvironment, subs: &mut Substitution, typ: &mut Qualifi *typ = x; } } - freshen_(env, subs, &*typ.constraints, &mut typ.value); + freshen_(env, subs, &typ.constraints, &mut typ.value); for constraint in typ.constraints.iter_mut() { if let Some(new) = subs.subs.get(&constraint.variables[0]) { constraint.variables[0] = new.var().clone(); From e995b6a9b548bc5b9eea72689b69dcfde8617cf5 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 19:43:16 -0800 Subject: [PATCH 69/76] nitpicks --- src/core.rs | 8 ++++---- src/deriving.rs | 4 ++-- src/typecheck.rs | 6 +++--- src/types.rs | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/core.rs b/src/core.rs index 24bbe42..aa0bf24 100644 --- a/src/core.rs +++ b/src/core.rs @@ -405,13 +405,13 @@ pub mod result { let a = visitor.visit_expr(*arg); 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, visitor.visit_expr(*e).into()) } Case(e, alts) => { let e2 = visitor.visit_expr(*e); @@ -905,7 +905,7 @@ pub mod translate { //as the same since their binding variable are the same name.truncate(base_length); name.push('_'); - name.push_str(&i.to_string()); + name.push_str(&*i.to_string()); let n = Name { name: intern(name.as_ref()), @@ -1064,7 +1064,7 @@ pub mod translate { let where_bindings_binds = where_bindings.map_or(vec![], |bs| self.translate_bindings(bs)); ( - self.unwrap_patterns(uid, arg_ids.as_ref(), &arguments), + self.unwrap_patterns(uid, arg_ids.as_ref(), &*arguments), where_bindings_binds, matches, ) diff --git a/src/deriving.rs b/src/deriving.rs index b5ad8e9..6768023 100644 --- a/src/deriving.rs +++ b/src/deriving.rs @@ -230,7 +230,7 @@ impl DerivingGen { iter.typ.clone(), constructor.typ.constraints.clone(), ); - let expr = f(self, &args_l, &args_r); + 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())), @@ -286,7 +286,7 @@ fn binop( function_type_(rhs.get_type().clone(), return_type), ); let f = Identifier(Id::new(name(op), typ, vec![])); - Apply(Box::new(Apply(f.into(), lhs.into())), rhs.into()) + Apply(Apply(f.into(), lhs.into()).into(), rhs.into()) } fn true_expr() -> Expr> { diff --git a/src/typecheck.rs b/src/typecheck.rs index 1223cc0..9246972 100644 --- a/src/typecheck.rs +++ b/src/typecheck.rs @@ -909,10 +909,10 @@ impl<'a> TypeEnvironment<'a> { } 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.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(), Box::new(self.new_var())); + previous = Type::Application(previous.into(), self.new_var().into()); for bind in bindings.iter_mut() { match *bind { DoBinding::DoExpr(ref mut e) => { @@ -1463,7 +1463,7 @@ fn freshen(env: &mut TypeEnvironment, subs: &mut Substitution, typ: &mut Qualifi *typ = x; } } - freshen_(env, subs, &typ.constraints, &mut typ.value); + freshen_(env, subs, &*typ.constraints, &mut typ.value); for constraint in typ.constraints.iter_mut() { if let Some(new) = subs.subs.get(&constraint.variables[0]) { constraint.variables[0] = new.var().clone(); diff --git a/src/types.rs b/src/types.rs index b14eae4..3658813 100644 --- a/src/types.rs +++ b/src/types.rs @@ -320,7 +320,7 @@ impl Kind { pub fn new(v: isize) -> Self { let mut kind = Self::Star.clone(); for _ in 1..v { - kind = Self::Function(Box::new(Self::Star), kind.into()); + kind = Self::Function(Self::Star.into(), kind.into()); } kind } From 748590c770d5f775aa85f08ab8e56333267de1fb Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 19:49:22 -0800 Subject: [PATCH 70/76] find --- src/compiler.rs | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index 6b4b704..eb35b11 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -156,17 +156,19 @@ impl Globals for Assembly { } } - let mut index = 0; - for sc in self.super_combinators.iter() { - if name == sc.name { - return Some(if sc.typ.constraints.len() > 0 { - Var::Constraint(self.offset + index, &sc.typ.value, &sc.typ.constraints) - } else { - 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)) } @@ -186,7 +188,7 @@ 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 { - return Some(Var::Class(&decl.typ.value, &decl.typ.constraints, &class.variable)); + return Some(Var::Class(&decl.typ.value, &*decl.typ.constraints, &class.variable)); } } } @@ -956,7 +958,7 @@ impl<'a> Compiler<'a> { None => { let dictionary_key = find_specialized_instances(function_type, actual_type, constraints); - self.push_dictionary(constraints, &dictionary_key, instructions); + self.push_dictionary(constraints, &*dictionary_key, instructions); } } } @@ -965,7 +967,7 @@ impl<'a> Compiler<'a> { //push dictionary let dictionary_key = find_specialized_instances(function_type, actual_type, constraints); - self.push_dictionary(constraints, &dictionary_key, instructions); + self.push_dictionary(constraints, &*dictionary_key, instructions); } } } From 512e06acf3940e4f5a6e24cbed9adcd3bcb53040 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 19:55:31 -0800 Subject: [PATCH 71/76] nitpicks --- src/parser.rs | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/src/parser.rs b/src/parser.rs index b8e6041..183953e 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -633,22 +633,20 @@ impl> Parser { } fn application(&mut self) -> ParseResult> { - let e = self.sub_expression()?; - match e { - Some(mut lhs) => { - let mut expressions = vec![]; - while let Some(expr) = self.sub_expression()? { - expressions.push(expr); - } - if expressions.len() > 0 { - let loc = lhs.location; - lhs = make_application(lhs, expressions.into_iter()); //, loc); - lhs.location = loc; - } - Ok(Some(lhs)) + Ok(if let Some(mut lhs) = self.sub_expression()? { + let mut expressions = vec![]; + while let Some(expr) = self.sub_expression()? { + expressions.push(expr); } - None => Ok(None), - } + if !expressions.is_empty() { + let loc = lhs.location; + lhs = make_application(lhs, expressions.into_iter()); //, loc); + lhs.location = loc; + } + Some(lhs) + } else { + None + }) } fn constructor(&mut self, data_def: &DataDefinition) -> ParseResult { @@ -1580,7 +1578,7 @@ instance Eq a => Eq [a] where identifier("getContents"), ), ], - apply(identifier("return".into(), identifier("s"))), + apply(identifier("return"), identifier("s")).into(), )); assert_eq!(module.bindings[0].matches, Match::Simple(b)); } @@ -1594,7 +1592,7 @@ instance Eq a => Eq [a] where ); assert_eq!( expr, - TypedExpr::new(Lambda(pattern, identifier("x"))).into() + TypedExpr::new(Lambda(pattern, identifier("x").into())).into() ); } From d003fbf8e731319175e47d9fa3e379f946d91056 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 20:03:38 -0800 Subject: [PATCH 72/76] refactoring --- src/compiler.rs | 6 +----- src/core.rs | 12 ++++++------ src/lexer.rs | 7 +++---- 3 files changed, 10 insertions(+), 15 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index eb35b11..597804d 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -483,11 +483,7 @@ impl<'a> Compiler<'a> { 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![]; let mut arity = 0; diff --git a/src/core.rs b/src/core.rs index aa0bf24..3d324e2 100644 --- a/src/core.rs +++ b/src/core.rs @@ -1185,12 +1185,12 @@ pub mod translate { let mut pattern_test = None; while last_index < equations.len() { let &Equation(ps, _) = &equations[last_index]; - if ps.len() > 0 { - match ps[0].1 { + if let Some(head) = ps.first() { + match head.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]); + if visited.iter().find(|x| matching(**x, &head)).is_none() { + pattern_test = Some(head); + visited.push(&head); last_index += 1; break; } @@ -1205,7 +1205,7 @@ pub mod translate { 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 diff --git a/src/lexer.rs b/src/lexer.rs index 4cd3775..dbc19d9 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -391,13 +391,12 @@ 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"); From 20d8fc1e3d97853158d88c5421006133690f6705 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 20:08:24 -0800 Subject: [PATCH 73/76] nitpicks --- src/compiler.rs | 2 +- src/core.rs | 8 ++++---- src/lambda_lift.rs | 2 +- src/lexer.rs | 8 ++++---- src/renamer.rs | 2 +- src/types.rs | 4 ++-- src/vm.rs | 2 +- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index 597804d..d7b862e 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -212,7 +212,7 @@ fn find_global<'a>(module: &'a Module, offset: usize, name: Name) -> Option< global_index -= 1; let typ = bind.expression.get_type(); let constraints = &bind.name.typ.constraints; - if constraints.len() > 0 { + if !constraints.is_empty() { Var::Constraint(offset + global_index, typ, constraints) } else { Var::Global(offset + global_index) diff --git a/src/core.rs b/src/core.rs index 3d324e2..e61196b 100644 --- a/src/core.rs +++ b/src/core.rs @@ -872,13 +872,13 @@ pub mod translate { let mut result = vec![]; let mut vec: Vec> = vec![]; for bind in bindings.into_iter() { - if vec.len() > 0 && vec[0].name != bind.name { + if !vec.is_empty() && vec[0].name != bind.name { result.push(self.translate_matching_groups(vec)); vec = vec![]; } vec.push(bind); } - if vec.len() > 0 { + if !vec.is_empty() { result.push(self.translate_matching_groups(vec)); } result @@ -1254,12 +1254,12 @@ pub mod translate { let defaults: Vec = equations .iter() .filter(|&&Equation(ps, _)| { - ps.len() > 0 + !ps.is_empty() && matches!(ps[0].1, Pattern::WildCard | Pattern::Identifier(..)) }) .map(|&Equation(ps, e)| Equation(&ps[1..], e)) .collect(); - if defaults.len() != 0 { + 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())); diff --git a/src/lambda_lift.rs b/src/lambda_lift.rs index d38f0a9..8a10619 100644 --- a/src/lambda_lift.rs +++ b/src/lambda_lift.rs @@ -122,7 +122,7 @@ impl FreeVariables { free_vars: &HashMap, input_expr: &mut Expr, ) { - if free_vars.len() != 0 { + if !free_vars.is_empty() { let mut temp = Literal(LiteralData { typ: Type::new_var(self.name_supply.from_str("a").name), value: Integral(0), diff --git a/src/lexer.rs b/src/lexer.rs index dbc19d9..753cc9a 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -235,7 +235,7 @@ impl> Lexer { self.tokens .get(self.tokens.len() - 1 - self.offset) .expect("Impossible empty tokens stream") - } else if self.unprocessed_tokens.len() > 0 { + } 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() @@ -337,7 +337,7 @@ 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 { @@ -433,7 +433,7 @@ impl> Lexer { 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 { @@ -471,7 +471,7 @@ impl> Lexer { return; } RBRACE => { - if self.indent_levels.len() > 0 && *self.indent_levels.last().unwrap() == 0 { + 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(); diff --git a/src/renamer.rs b/src/renamer.rs index c93490b..76612a0 100644 --- a/src/renamer.rs +++ b/src/renamer.rs @@ -74,7 +74,7 @@ impl Errors { } pub fn has_errors(&self) -> bool { - self.errors.len() != 0 + !self.errors.is_empty() } pub fn into_result(&mut self, value: V) -> Result> { diff --git a/src/types.rs b/src/types.rs index 3658813..c3588f9 100644 --- a/src/types.rs +++ b/src/types.rs @@ -344,13 +344,13 @@ impl fmt::Display for TypeConstructor { 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 { + if !self.constraints.is_empty() { write!(f, ") => {}", self.value) } else { write!(f, "{}", self.value) diff --git a/src/vm.rs b/src/vm.rs index ac47bd4..7223172 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -143,7 +143,7 @@ impl<'a> fmt::Debug for Node_<'a> { 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) { From 75f2f1fff4d93d32a74b2fee9e947cd77e2d9071 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 20:13:32 -0800 Subject: [PATCH 74/76] refactoring --- src/renamer.rs | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/src/renamer.rs b/src/renamer.rs index 76612a0..af34598 100644 --- a/src/renamer.rs +++ b/src/renamer.rs @@ -241,20 +241,17 @@ 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, + ) } } } From 4983abe40dbb9b84008f485e437098bb5edd34ae Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 20:15:20 -0800 Subject: [PATCH 75/76] refactoring --- src/compiler.rs | 67 +++++++++++++++++++++++-------------------------- 1 file changed, 32 insertions(+), 35 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index d7b862e..a0dafef 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -897,43 +897,40 @@ impl<'a> Compiler<'a> { 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), + 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, + ) } } From b153a7f09de6c2b7469447534255f7469008fe69 Mon Sep 17 00:00:00 2001 From: Adam Nemecek Date: Fri, 22 Dec 2023 20:26:12 -0800 Subject: [PATCH 76/76] refactoring --- src/lexer.rs | 15 +++++++-------- src/vm.rs | 13 ++++++------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/lexer.rs b/src/lexer.rs index 753cc9a..86b914c 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -512,15 +512,14 @@ impl> Lexer { 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; diff --git a/src/vm.rs b/src/vm.rs index 7223172..96a591e 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -896,13 +896,12 @@ mod tests { .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); - extract_result(result) - } - None => None, + if let Some(sc) = x { + assert!(sc.arity == 0); + let result = vm.evaluate(&*sc.instructions, sc.assembly_id); + extract_result(result) + } else { + None } }