diff --git a/crates/compiler/module/src/symbol.rs b/crates/compiler/module/src/symbol.rs index 9b52dd7679..e573f2f9fb 100644 --- a/crates/compiler/module/src/symbol.rs +++ b/crates/compiler/module/src/symbol.rs @@ -249,7 +249,7 @@ lazy_static! { std::sync::Mutex::new(roc_collections::SmallStringInterner::with_capacity(10)); } -#[derive(Debug, Default)] +#[derive(Debug, Default, Clone)] pub struct Interns { pub module_ids: ModuleIds, pub all_ident_ids: IdentIdsByModule, @@ -663,7 +663,7 @@ impl IdentIds { } } -#[derive(Debug, Default)] +#[derive(Debug, Default, Clone)] pub struct IdentIdsByModule(VecMap); impl IdentIdsByModule { diff --git a/crates/repl_cli/src/lib.rs b/crates/repl_cli/src/lib.rs index b52306de6b..0650650ae0 100644 --- a/crates/repl_cli/src/lib.rs +++ b/crates/repl_cli/src/lib.rs @@ -395,6 +395,8 @@ fn gen_and_eval_llvm<'a>( } }; + let interns = loaded.interns.clone(); + let (lib, main_fn_name, subs) = mono_module_to_dylib(&arena, target, loaded, opt_level).expect("we produce a valid Dylib"); @@ -407,6 +409,7 @@ fn gen_and_eval_llvm<'a>( main_fn_layout, &content, &subs, + &interns, target_info, ); diff --git a/crates/repl_eval/src/eval.rs b/crates/repl_eval/src/eval.rs index df2ca2562a..ed88981d13 100644 --- a/crates/repl_eval/src/eval.rs +++ b/crates/repl_eval/src/eval.rs @@ -1,12 +1,13 @@ use bumpalo::collections::Vec; use bumpalo::Bump; +use roc_types::types::AliasKind; use std::cmp::{max_by_key, min_by_key}; use roc_builtins::bitcode::{FloatWidth, IntWidth}; use roc_collections::all::MutMap; use roc_module::called_via::CalledVia; use roc_module::ident::TagName; -use roc_module::symbol::Symbol; +use roc_module::symbol::{Interns, ModuleId, Symbol}; use roc_mono::ir::ProcLayout; use roc_mono::layout::{ union_sorted_tags_help, Builtin, Layout, LayoutCache, UnionLayout, UnionVariant, WrappedVariant, @@ -23,6 +24,7 @@ struct Env<'a, 'env> { arena: &'a Bump, subs: &'env Subs, target_info: TargetInfo, + interns: &'a Interns, } pub enum ToAstProblem { @@ -45,12 +47,14 @@ pub fn jit_to_ast<'a, A: ReplApp<'a>>( layout: ProcLayout<'a>, content: &'a Content, subs: &'a Subs, + interns: &'a Interns, target_info: TargetInfo, ) -> Result, ToAstProblem> { let env = Env { arena, subs, target_info, + interns, }; match layout { @@ -70,6 +74,7 @@ pub fn jit_to_ast<'a, A: ReplApp<'a>>( enum NewtypeKind<'a> { Tag(&'a TagName), RecordField(&'a str), + Opaque(Symbol), } /// Unrolls types that are newtypes. These include @@ -115,7 +120,7 @@ fn unroll_newtypes_and_aliases<'a>( )); content = env.subs.get_content_without_compacting(field.into_inner()); } - Content::Alias(_, _, real_var, _) => { + Content::Alias(name, _, real_var, kind) => { // We need to pass through aliases too, because their underlying types may have // unrolled newtypes. For example, // T : { a : Str } @@ -126,6 +131,9 @@ fn unroll_newtypes_and_aliases<'a>( // // At the end of the day what we should show to the user is the alias content, not // what's inside, so keep that around too. + if *kind == AliasKind::Opaque && name.module_id() != ModuleId::NUM { + newtype_containers.push(NewtypeKind::Opaque(*name)); + } alias_content = Some(content); content = env.subs.get_content_without_compacting(*real_var); } @@ -157,6 +165,13 @@ fn apply_newtypes<'a>( let field = Loc::at_zero(AssignedField::RequiredValue(label, &[], field_val)); expr = Expr::Record(Collection::with_items(&*arena.alloc([field]))) } + NewtypeKind::Opaque(name) => { + let opaque_name = arena.alloc(format!("@{}", name.as_str(&env.interns))); + let opaque_ref = &*arena.alloc(Loc::at_zero(Expr::OpaqueRef(opaque_name))); + let loc_arg_expr = &*arena.alloc(Loc::at_zero(expr)); + let loc_arg_exprs = arena.alloc_slice_copy(&[loc_arg_expr]); + expr = Expr::Apply(opaque_ref, loc_arg_exprs, CalledVia::Space); + } } } expr diff --git a/crates/repl_expect/src/lib.rs b/crates/repl_expect/src/lib.rs index e7119bff96..1532be7e83 100644 --- a/crates/repl_expect/src/lib.rs +++ b/crates/repl_expect/src/lib.rs @@ -1,3 +1,4 @@ +use roc_module::symbol::Interns; use roc_mono::{ ir::ProcLayout, layout::{CapturesNiche, LayoutCache}, @@ -16,6 +17,7 @@ pub fn get_values<'a>( target_info: TargetInfo, arena: &'a bumpalo::Bump, subs: &'a Subs, + interns: &'a Interns, start: *const u8, mut start_offset: usize, variables: &[Variable], @@ -52,6 +54,7 @@ pub fn get_values<'a>( proc_layout, content, subs, + interns, target_info, ) }?; diff --git a/crates/repl_test/src/tests.rs b/crates/repl_test/src/tests.rs index 7302cb7c9a..ab802472e8 100644 --- a/crates/repl_test/src/tests.rs +++ b/crates/repl_test/src/tests.rs @@ -1024,7 +1024,7 @@ fn opaque_apply() { @Age 23 "# ), - "23 : Age", + "@Age 23 : Age", ) } @@ -1038,7 +1038,7 @@ fn opaque_apply_polymorphic() { @F (Package "" { a: "" }) "# ), - r#"Package "" { a: "" } : F Str { a : Str }"#, + r#"@F (Package "" { a: "" }) : F Str { a : Str }"#, ) } @@ -1054,7 +1054,7 @@ fn opaque_pattern_and_call() { f (@F (Package A {})) "# ), - r#"Package {} A : F {} [A]*"#, + r#"@F (Package {} A) : F {} [A]*"#, ) } @@ -1189,6 +1189,6 @@ fn opaque_wrap_function() { List.map [1u8, 2u8, 3u8] @A "# ), - "[1, 2, 3] : List (A U8)", + "[@A 1, @A 2, @A 3] : List (A U8)", ); } diff --git a/crates/repl_wasm/src/repl.rs b/crates/repl_wasm/src/repl.rs index 52164d496b..f449589750 100644 --- a/crates/repl_wasm/src/repl.rs +++ b/crates/repl_wasm/src/repl.rs @@ -251,6 +251,7 @@ pub async fn entrypoint_from_js(src: String) -> Result { main_fn_layout, content, &subs, + &interns, target_info, );