diff --git a/compiler/mono/src/expr.rs b/compiler/mono/src/expr.rs index 558c60b893..1197e9344d 100644 --- a/compiler/mono/src/expr.rs +++ b/compiler/mono/src/expr.rs @@ -104,6 +104,20 @@ struct Env<'a, 'i> { pub home: ModuleId, pub ident_ids: &'i mut IdentIds, pub pointer_size: u32, + symbol_counter: usize, +} + +impl<'a, 'i> Env<'a, 'i> { + pub fn fresh_symbol(&mut self) -> Symbol { + let ident_id = self + .ident_ids + .add(format!("_{}", self.symbol_counter).into()); + self.symbol_counter += 1; + + self.home.register_debug_idents(&self.ident_ids); + + Symbol::new(self.home, ident_id) + } } #[derive(Clone, Debug, PartialEq)] @@ -206,6 +220,7 @@ impl<'a> Expr<'a> { home, ident_ids, pointer_size, + symbol_counter: 0, }; from_can(&mut env, can_expr, procs, None) @@ -357,7 +372,7 @@ fn from_can<'a>( None => { // an anonymous closure. These will always be specialized already // by the surrounding context - let symbol = gen_closure_name(procs, &mut env.ident_ids, env.home); + let symbol = env.fresh_symbol(); let opt_proc = specialize_proc_body( env, procs, @@ -637,14 +652,6 @@ fn store_pattern<'a>( } } -fn gen_closure_name(procs: &Procs<'_>, ident_ids: &mut IdentIds, home: ModuleId) -> Symbol { - let ident_id = ident_ids.add(format!("_{}", procs.len()).into()); - - home.register_debug_idents(&ident_ids); - - Symbol::new(home, ident_id) -} - fn from_can_when<'a>( env: &mut Env<'a, '_>, cond_var: Variable, @@ -935,7 +942,7 @@ fn call_by_name<'a>( )); // generate a symbol for this specialization - gen_closure_name(procs, &mut env.ident_ids, env.home) + env.fresh_symbol() } } else { opt_specialize_body = None; diff --git a/compiler/mono/tests/test_mono.rs b/compiler/mono/tests/test_mono.rs index 65ae5ea18e..4e29588d34 100644 --- a/compiler/mono/tests/test_mono.rs +++ b/compiler/mono/tests/test_mono.rs @@ -160,6 +160,92 @@ mod test_mono { ) } + #[test] + fn polymorphic_identity() { + compiles_to( + r#" + id = \x -> x + + id { x: id 0x4 } + "#, + { + use self::Builtin::*; + use Layout::Builtin; + let home = test_home(); + + let gen_symbol_3 = Interns::from_index(home, 3); + let gen_symbol_4 = Interns::from_index(home, 4); + + CallByName( + gen_symbol_3, + &[( + Struct { + fields: &[( + "x".into(), + CallByName(gen_symbol_4, &[(Int(4), Builtin(Int64))]), + )], + layout: Layout::Struct(&[("x".into(), Builtin(Int64))]), + }, + Layout::Struct(&[("x".into(), Builtin(Int64))]), + )], + ) + }, + ) + } + + // needs LetRec to be converted to mono + // #[test] + // fn polymorphic_recursive() { + // compiles_to( + // r#" + // f = \x -> + // when x < 10 is + // True -> f (x + 1) + // False -> x + // + // { x: f 0x4, y: f 3.14 } + // "#, + // { + // use self::Builtin::*; + // use Layout::Builtin; + // let home = test_home(); + // + // let gen_symbol_3 = Interns::from_index(home, 3); + // let gen_symbol_4 = Interns::from_index(home, 4); + // + // Float(3.4) + // + // }, + // ) + // } + + // needs layout for non-empty tag union + // #[test] + // fn is_nil() { + // let arena = Bump::new(); + // + // compiles_to_with_interns( + // r#" + // LinkedList a : [ Cons a (LinkedList a), Nil ] + // + // isNil : LinkedList a -> Bool + // isNil = \list -> + // when list is + // Nil -> True + // Cons _ _ -> False + // + // listInt : LinkedList Int + // listInt = Nil + // + // isNil listInt + // "#, + // |interns| { + // let home = test_home(); + // let var_is_nil = interns.symbol(home, "isNil".into()); + // }, + // ); + // } + #[test] fn bool_literal() { let arena = Bump::new();