diff --git a/crates/glue/platform/Shape.roc b/crates/glue/platform/Shape.roc index da5767c3be..14d805fed4 100644 --- a/crates/glue/platform/Shape.roc +++ b/crates/glue/platform/Shape.roc @@ -101,7 +101,7 @@ RocTagUnion : [ { name : Str, tagName : Str, - payload: RocSingleTagPayload, + payload : RocSingleTagPayload, }, ## A recursive tag union with only two variants, where one is empty. ## Optimizations: Use null for the empty variant AND don't store a tag ID for the other variant. @@ -117,19 +117,20 @@ RocTagUnion : [ ] RocStructFields : [ - HasNoClosure (List { name: Str, id: TypeId }), - HasClosure (List { name: Str, id: TypeId, accessors: { getter: Str } }), + HasNoClosure (List { name : Str, id : TypeId }), + HasClosure (List { name : Str, id : TypeId, accessors : { getter : Str } }), ] -RocSingleTagPayload: [ - HasClosure (List { name: Str, id: TypeId }), - HasNoClosure (List { id: TypeId }), +RocSingleTagPayload : [ + HasClosure (List { name : Str, id : TypeId }), + HasNoClosure (List { id : TypeId }), ] RocFn : { - functionName: Str, - externName: Str, - args: List TypeId, - lambdaSet: TypeId, - ret: TypeId, + functionName : Str, + externName : Str, + args : List TypeId, + lambdaSet : TypeId, + ret : TypeId, + isToplevel : Bool, } diff --git a/crates/glue/platform/Types.roc b/crates/glue/platform/Types.roc index acedfe5bfc..9d2f4d3819 100644 --- a/crates/glue/platform/Types.roc +++ b/crates/glue/platform/Types.roc @@ -22,7 +22,6 @@ Types := { ## Names and types of the entry points of the program (e.g. mainForHost) entrypoints : List Tuple1, - target : Target, } @@ -30,7 +29,7 @@ target : Types -> Target target = \@Types types -> types.target entryPoints : Types -> List Tuple1 -entryPoints = \@Types { entrypoints} -> entrypoints +entryPoints = \@Types { entrypoints } -> entrypoints walkShapes : Types, state, (state, Shape, TypeId -> state) -> state walkShapes = \@Types { types: shapes }, originalState, update -> diff --git a/crates/glue/src/RustGlue.roc b/crates/glue/src/RustGlue.roc index a7fe87b263..5e26ebfb39 100644 --- a/crates/glue/src/RustGlue.roc +++ b/crates/glue/src/RustGlue.roc @@ -1,6 +1,6 @@ app "rust-glue" packages { pf: "../platform/main.roc" } - imports [pf.Types.{ Types }, pf.File.{ File }, pf.TypeId.{ TypeId }] + imports [pf.Types.{ Types }, pf.Shape.{ RocFn }, pf.File.{ File }, pf.TypeId.{ TypeId }] provides [makeGlue] to pf makeGlue : List Types -> Result (List File) Str @@ -63,9 +63,11 @@ convertTypesToFile = \types -> TagUnion (NonNullableUnwrapped { name, tagName, payload }) -> generateRecursiveTagUnion buf types id name [{ name: tagName, payload: Some payload }] 0 0 None - Function _ -> - # TODO: actually generate glue functions. - buf + Function rocFn -> + if rocFn.isToplevel then + buf + else + generateFunction buf types rocFn RecursivePointer _ -> # This is recursively pointing to a type that should already have been added, @@ -95,25 +97,18 @@ convertTypesToFile = \types -> content: content |> generateEntryPoints types, } -generateEntryPoints: Str, Types -> Str +generateEntryPoints : Str, Types -> Str generateEntryPoints = \buf, types -> List.walk (Types.entryPoints types) buf \accum, T name id -> generateEntryPoint accum types name id -generateEntryPoint: Str, Types, Str, TypeId -> Str +generateEntryPoint : Str, Types, Str, TypeId -> Str generateEntryPoint = \buf, types, name, id -> - # functionName: Str, - # externName: Str, - # args: List TypeId, - # lambdaSet: TypeId, - # ret: TypeId, - - publicSignature = when Types.shape types id is Function rocFn -> arguments = rocFn.args - |> List.mapWithIndex \i, argId -> + |> List.mapWithIndex \argId, i -> type = typeName types argId c = Num.toStr i "arg\(c): \(type)" @@ -148,7 +143,7 @@ generateEntryPoint = \buf, types, name, id -> when Types.shape types id is Function rocFn -> rocFn.args - |> List.mapWithIndex \i, _ -> + |> List.mapWithIndex \_, i -> c = Num.toStr i "arg\(c)" |> Str.joinWith ", " @@ -172,6 +167,56 @@ generateEntryPoint = \buf, types, name, id -> } """ +generateFunction : Str, Types, RocFn -> Str +generateFunction = \buf, types, rocFn -> + name = rocFn.functionName + externName = rocFn.externName + + lambdaSet = typeName types rocFn.lambdaSet + + publicArguments = + rocFn.args + |> List.mapWithIndex \argId, i -> + type = typeName types argId + c = Num.toStr i + "arg\(c): \(type)" + |> Str.joinWith ", " + + externArguments = + rocFn.args + |> List.mapWithIndex \_, i -> + c = Num.toStr i + "arg\(c)" + |> Str.joinWith ", " + + externComma = if Str.isEmpty publicArguments then "" else ", " + + ret = typeName types rocFn.ret + + """ + \(buf) + + #[repr(C)] + pub struct \(name) { + closure_data: \(lambdaSet), + } + + impl \(name) { + pub fn force_thunk(mut self, \(publicArguments)) -> \(ret) { + extern "C" { + fn \(externName)(\(publicArguments)\(externComma) closure_data: *mut u8, output: *mut \(ret)); + } + + let mut output = std::mem::MaybeUninit::uninit(); + let ptr = &mut self.closure_data as *mut _ as *mut u8; + + unsafe { \(externName)(\(externArguments)\(externComma) ptr, output.as_mut_ptr(), ) }; + + unsafe { output.assume_init() } + } + } + """ + generateStruct : Str, Types, TypeId, _, _, _ -> Str generateStruct = \buf, types, id, name, structFields, visibility -> escapedName = escapeKW name @@ -202,6 +247,7 @@ generateStructFields = \buf, types, visibility, structFields -> when structFields is HasNoClosure fields -> List.walk fields buf (generateStructFieldWithoutClosure types visibility) + HasClosure _ -> Str.concat buf "// TODO: Struct fields with closures" @@ -224,6 +270,7 @@ nameTagUnionPayloadFields = \payloadFields -> HasNoClosure fields -> renamedFields = List.map fields \{ name, id } -> { name: "f\(name)", id } HasNoClosure renamedFields + HasClosure fields -> renamedFields = List.map fields \{ name, id, accessors } -> { name: "f\(name)", id, accessors } HasClosure renamedFields @@ -448,7 +495,7 @@ generateUnionField = \types -> else typeStr - Str.concat accum "\(indent)\(escapedFieldName): \(fullTypeStr),\n" + Str.concat accum "\(indent)\(escapedFieldName): std::mem::ManuallyDrop<\(fullTypeStr)>,\n" None -> # If there's no payload, we don't need a discriminant for it. @@ -494,6 +541,7 @@ generateSingleTagStruct = \buf, types, name, tagName, payload -> generateZeroElementSingleTagStruct b escapedName tagName else generateMultiElementSingleTagStruct b types escapedName tagName fields asStructFields + HasClosure _ -> Str.concat buf "\\TODO: SingleTagStruct with closures" diff --git a/crates/glue/src/load.rs b/crates/glue/src/load.rs index d374242112..17fed2ed10 100644 --- a/crates/glue/src/load.rs +++ b/crates/glue/src/load.rs @@ -380,11 +380,8 @@ pub fn load_types( // Get the variables for all the exposed_to_host symbols let variables = (0..decls.len()).filter_map(|index| { - if exposed_to_host.contains_key(&decls.symbols[index].value) { - Some(decls.variables[index]) - } else { - None - } + let symbol = decls.symbols[index].value; + exposed_to_host.get(&symbol).copied() }); let operating_system = target_info.operating_system; @@ -456,7 +453,6 @@ pub fn load_types( let types = Types::new_with_entry_points( arena, subs, - variables.clone(), arena.alloc(interns), glue_procs_by_layout, layout_cache, diff --git a/crates/glue/src/roc_type/mod.rs b/crates/glue/src/roc_type/mod.rs index fd5952d82e..e053f8b0cc 100644 --- a/crates/glue/src/roc_type/mod.rs +++ b/crates/glue/src/roc_type/mod.rs @@ -568,6 +568,7 @@ pub struct RocFn { pub functionName: roc_std::RocStr, pub lambdaSet: u32, pub ret: u32, + pub is_toplevel: bool, } #[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))] @@ -714,6 +715,7 @@ pub struct RocFn { pub functionName: roc_std::RocStr, pub lambdaSet: u64, pub ret: u64, + pub isToplevel: bool, } impl Tuple1 { diff --git a/crates/glue/src/types.rs b/crates/glue/src/types.rs index 514a9475f2..88f8671d6f 100644 --- a/crates/glue/src/types.rs +++ b/crates/glue/src/types.rs @@ -21,7 +21,7 @@ use roc_mono::{ }; use roc_target::{Architecture, OperatingSystem, TargetInfo}; use roc_types::{ - subs::{Content, FlatType, GetSubsSlice, Label, Subs, UnionLabels, Variable}, + subs::{Content, FlatType, GetSubsSlice, Label, Subs, SubsSlice, UnionLabels, Variable}, types::{AliasKind, RecordField}, }; use std::convert::From; @@ -68,10 +68,16 @@ pub struct Types { } impl Types { + const UNIT: TypeId = TypeId(0); + pub fn with_capacity(cap: usize, target_info: TargetInfo) -> Self { + let mut types = Vec::with_capacity(cap); + + types.push(RocType::Unit); + Self { target: target_info, - types: Vec::with_capacity(cap), + types, types_by_name: FnvHashMap::with_capacity_and_hasher(10, Default::default()), entry_points: Vec::new(), sizes: Vec::new(), @@ -81,17 +87,16 @@ impl Types { } #[allow(clippy::too_many_arguments)] - pub(crate) fn new_with_entry_points<'a, I: Iterator>( + pub(crate) fn new_with_entry_points<'a>( arena: &'a Bump, subs: &'a Subs, - variables: I, interns: &'a Interns, glue_procs_by_layout: MutMap, &'a [String]>, layout_cache: LayoutCache<'a>, target: TargetInfo, mut entry_points: MutMap, ) -> Self { - let mut types = Self::with_capacity(variables.size_hint().0, target); + let mut types = Self::with_capacity(entry_points.len(), target); let mut env = Env::new( arena, subs, @@ -101,25 +106,10 @@ impl Types { target, ); - for var in variables { - env.lambda_set_ids = env.find_lambda_sets(var); - let id = env.add_type(var, &mut types); - - let key = entry_points - .iter() - .find_map(|(k, v)| (*v == var).then_some((*k, id))); - - if let Some((k, id)) = key { - let name = k.as_str(env.interns).to_string(); - types.entry_points.push((name, id)); - entry_points.remove(&k); - } - } - let variables: Vec<_> = entry_points.values().copied().collect(); for var in variables { env.lambda_set_ids = env.find_lambda_sets(var); - let id = env.add_type(var, &mut types); + let id = env.add_toplevel_type(var, &mut types); let key = entry_points .iter() @@ -441,6 +431,7 @@ impl Types { args: args_a, lambda_set: lambda_a, ret: ret_a, + is_toplevel: is_toplevel_a, }), Function(RocFn { function_name: name_b, @@ -448,12 +439,14 @@ impl Types { args: args_b, lambda_set: lambda_b, ret: ret_b, + is_toplevel: is_toplevel_b, }), ) => { // for functions, the name is actually important because two functions // with the same type could have completely different implementations! if name_a == name_b && extern_a == extern_b + && is_toplevel_a == is_toplevel_b && args_a.len() == args_b.len() && self.is_equivalent_help( self.get_type_or_pending(*lambda_a), @@ -704,12 +697,14 @@ impl From<&RocType> for roc_type::RocType { args, lambda_set, ret, + is_toplevel, }) => roc_type::RocType::Function(roc_type::RocFn { args: args.iter().map(|arg| arg.0 as _).collect(), functionName: function_name.as_str().into(), externName: extern_name.as_str().into(), ret: ret.0 as _, lambdaSet: lambda_set.0 as _, + isToplevel: *is_toplevel, }), RocType::Unit => roc_type::RocType::Unit, RocType::Unsized => roc_type::RocType::Unsized, @@ -974,6 +969,7 @@ impl RocStructFields { pub struct RocFn { pub function_name: String, pub extern_name: String, + pub is_toplevel: bool, pub args: Vec, pub lambda_set: TypeId, pub ret: TypeId, @@ -1298,18 +1294,99 @@ impl<'a> Env<'a> { result } - fn add_type(&mut self, var: Variable, types: &mut Types) -> TypeId { - roc_tracing::debug!(content=?roc_types::subs::SubsFmtContent(self.subs.get_content_without_compacting(var), self.subs), "adding type"); + fn add_toplevel_type(&mut self, var: Variable, types: &mut Types) -> TypeId { + roc_tracing::debug!(content=?roc_types::subs::SubsFmtContent(self.subs.get_content_without_compacting(var), self.subs), "adding toplevel type"); let layout = self .layout_cache .from_var(self.arena, var, self.subs) .expect("Something weird ended up in the content"); - add_type_help(self, layout, var, None, types) + match self.subs.get_content_without_compacting(var) { + Content::Structure(FlatType::Func(args, closure_var, ret_var)) => { + // this is a toplevel type, so the closure must be empty + let is_toplevel = true; + add_function_type( + self, + layout, + types, + args, + *closure_var, + *ret_var, + is_toplevel, + ) + } + _ => add_type_help(self, layout, var, None, types), + } } } +fn add_function_type<'a>( + env: &mut Env<'a>, + layout: InLayout<'a>, + types: &mut Types, + args: &SubsSlice, + closure_var: Variable, + ret_var: Variable, + is_toplevel: bool, +) -> TypeId { + let args = env.subs.get_subs_slice(*args); + let mut arg_type_ids = Vec::with_capacity(args.len()); + + let name = format!("RocFunction_{:?}", closure_var); + + let id = env.lambda_set_ids.get(&closure_var).unwrap(); + let extern_name = format!("roc__mainForHost_{}_caller", id.0); + + for arg_var in args { + let arg_layout = env + .layout_cache + .from_var(env.arena, *arg_var, env.subs) + .expect("Something weird ended up in the content"); + + arg_type_ids.push(add_type_help(env, arg_layout, *arg_var, None, types)); + } + + let lambda_set_type_id = if is_toplevel { + Types::UNIT + } else { + let lambda_set_layout = env + .layout_cache + .from_var(env.arena, closure_var, env.subs) + .expect("Something weird ended up in the content"); + + add_type_help(env, lambda_set_layout, closure_var, None, types) + }; + + let ret_type_id = { + let ret_layout = env + .layout_cache + .from_var(env.arena, ret_var, env.subs) + .expect("Something weird ended up in the content"); + + add_type_help(env, ret_layout, ret_var, None, types) + }; + + let fn_type_id = add_function(env, name, types, layout, |name| { + RocType::Function(RocFn { + function_name: name, + extern_name, + args: arg_type_ids.clone(), + lambda_set: lambda_set_type_id, + ret: ret_type_id, + is_toplevel, + }) + }); + + types.depends(fn_type_id, ret_type_id); + + for arg_type_id in arg_type_ids { + types.depends(fn_type_id, arg_type_id); + } + + fn_type_id +} + fn add_type_help<'a>( env: &mut Env<'a>, layout: InLayout<'a>, @@ -1389,62 +1466,17 @@ fn add_type_help<'a>( } }, Content::Structure(FlatType::Func(args, closure_var, ret_var)) => { - let args = env.subs.get_subs_slice(*args); - let mut arg_type_ids = Vec::with_capacity(args.len()); + let is_toplevel = false; // or in any case, we cannot assume that we are - let name = format!("RocFunction_{:?}", closure_var); - - let lambda_set_layout = env - .layout_cache - .from_var(env.arena, *closure_var, env.subs) - .expect("Something weird ended up in the content"); - - let _lambda_set = match env.layout_cache.interner.get(lambda_set_layout) { - Layout::LambdaSet(lambda_set) => lambda_set, - _ => unreachable!(), - }; - - let id = env.lambda_set_ids.get(closure_var).unwrap(); - let extern_name = format!("roc__mainForHost_{}_caller", id.0); - - for arg_var in args { - let arg_layout = env - .layout_cache - .from_var(env.arena, *arg_var, env.subs) - .expect("Something weird ended up in the content"); - - arg_type_ids.push(add_type_help(env, arg_layout, *arg_var, None, types)); - } - - let lambda_set_type_id = - add_type_help(env, lambda_set_layout, *closure_var, None, types); - - let ret_type_id = { - let ret_layout = env - .layout_cache - .from_var(env.arena, *ret_var, env.subs) - .expect("Something weird ended up in the content"); - - add_type_help(env, ret_layout, *ret_var, None, types) - }; - - let fn_type_id = add_function(env, name, types, layout, |name| { - RocType::Function(RocFn { - function_name: name, - extern_name, - args: arg_type_ids.clone(), - lambda_set: lambda_set_type_id, - ret: ret_type_id, - }) - }); - - types.depends(fn_type_id, ret_type_id); - - for arg_type_id in arg_type_ids { - types.depends(fn_type_id, arg_type_id); - } - - fn_type_id + add_function_type( + env, + layout, + types, + args, + *closure_var, + *ret_var, + is_toplevel, + ) } Content::Structure(FlatType::FunctionOrTagUnion(_, _, _)) => { todo!() diff --git a/crates/glue/tests/fixtures/advanced-recursive-union/app.roc b/crates/glue/tests/fixtures/advanced-recursive-union/app.roc index 83bfe96a8f..0c24291ff9 100644 --- a/crates/glue/tests/fixtures/advanced-recursive-union/app.roc +++ b/crates/glue/tests/fixtures/advanced-recursive-union/app.roc @@ -6,9 +6,9 @@ app "app" main = { default: Job { command: Command { - tool: SystemTool { name: "test", num: 42 } + tool: SystemTool { name: "test", num: 42 }, }, - inputFiles : ["foo"] - } + inputFiles: ["foo"], + }, } diff --git a/crates/glue/tests/fixtures/advanced-recursive-union/platform.roc b/crates/glue/tests/fixtures/advanced-recursive-union/platform.roc index 8a637a638b..6f23d2eda9 100644 --- a/crates/glue/tests/fixtures/advanced-recursive-union/platform.roc +++ b/crates/glue/tests/fixtures/advanced-recursive-union/platform.roc @@ -7,7 +7,7 @@ platform "test-platform" Tool : [ SystemTool { name : Str, num : U32 }, - FromJob { job : Job, num : U32 } + FromJob { job : Job, num : U32 }, ] Command : [Command { tool : Tool }] @@ -20,7 +20,7 @@ Job : [ # WithTool Tool # Mutual recursion; Tool also references Job ] -Rbt : { default: Job } +Rbt : { default : Job } mainForHost : Rbt mainForHost = main diff --git a/crates/glue/tests/fixtures/arguments/app.roc b/crates/glue/tests/fixtures/arguments/app.roc new file mode 100644 index 0000000000..a6fb727c6c --- /dev/null +++ b/crates/glue/tests/fixtures/arguments/app.roc @@ -0,0 +1,7 @@ +app "app" + packages { pf: "platform.roc" } + imports [] + provides [main] to pf + +main : I64 -> I64 +main = \x -> 2 * x diff --git a/crates/glue/tests/fixtures/arguments/platform.roc b/crates/glue/tests/fixtures/arguments/platform.roc new file mode 100644 index 0000000000..b4cfc05570 --- /dev/null +++ b/crates/glue/tests/fixtures/arguments/platform.roc @@ -0,0 +1,9 @@ +platform "test-platform" + requires {} { main : I64 -> I64 } + exposes [] + packages {} + imports [] + provides [mainForHost] + +mainForHost : I64 -> I64 +mainForHost = \x -> main x diff --git a/crates/glue/tests/fixtures/arguments/src/lib.rs b/crates/glue/tests/fixtures/arguments/src/lib.rs new file mode 100644 index 0000000000..19426b0b3e --- /dev/null +++ b/crates/glue/tests/fixtures/arguments/src/lib.rs @@ -0,0 +1,60 @@ +mod test_glue; + +#[no_mangle] +pub extern "C" fn rust_main() -> i32 { + let answer = test_glue::mainForHost(42i64); + + println!("Answer was: {:?}", answer); // Debug + + // Exit code + 0 +} + +// Externs required by roc_std and by the Roc app + +use core::ffi::c_void; +use std::ffi::CStr; +use std::os::raw::c_char; + +#[no_mangle] +pub unsafe extern "C" fn roc_alloc(size: usize, _alignment: u32) -> *mut c_void { + return libc::malloc(size); +} + +#[no_mangle] +pub unsafe extern "C" fn roc_realloc( + c_ptr: *mut c_void, + new_size: usize, + _old_size: usize, + _alignment: u32, +) -> *mut c_void { + return libc::realloc(c_ptr, new_size); +} + +#[no_mangle] +pub unsafe extern "C" fn roc_dealloc(c_ptr: *mut c_void, _alignment: u32) { + return libc::free(c_ptr); +} + +#[no_mangle] +pub unsafe extern "C" fn roc_panic(c_ptr: *mut c_void, tag_id: u32) { + match tag_id { + 0 => { + let slice = CStr::from_ptr(c_ptr as *const c_char); + let string = slice.to_str().unwrap(); + eprintln!("Roc hit a panic: {}", string); + std::process::exit(1); + } + _ => todo!(), + } +} + +#[no_mangle] +pub unsafe extern "C" fn roc_memcpy(dst: *mut c_void, src: *mut c_void, n: usize) -> *mut c_void { + libc::memcpy(dst, src, n) +} + +#[no_mangle] +pub unsafe extern "C" fn roc_memset(dst: *mut c_void, c: i32, n: usize) -> *mut c_void { + libc::memset(dst, c, n) +} diff --git a/crates/glue/tests/fixtures/list-recursive-union/app.roc b/crates/glue/tests/fixtures/list-recursive-union/app.roc index fe5462027f..eb1b704e37 100644 --- a/crates/glue/tests/fixtures/list-recursive-union/app.roc +++ b/crates/glue/tests/fixtures/list-recursive-union/app.roc @@ -10,7 +10,7 @@ main = { args: [], }, job: [], - inputFiles : ["foo"], - } + inputFiles: ["foo"], + }, } diff --git a/crates/glue/tests/fixtures/list-recursive-union/platform.roc b/crates/glue/tests/fixtures/list-recursive-union/platform.roc index 7f3967b2af..b248ccc6f1 100644 --- a/crates/glue/tests/fixtures/list-recursive-union/platform.roc +++ b/crates/glue/tests/fixtures/list-recursive-union/platform.roc @@ -5,13 +5,13 @@ platform "test-platform" imports [] provides [mainForHost] -Tool : [SystemTool { name: Str }] +Tool : [SystemTool { name : Str }] -Command : [Command { tool : Tool, args: List Str }] +Command : [Command { tool : Tool, args : List Str }] -Job : [Job { command : Command, job: List Job, inputFiles : List Str }, Blah Str] +Job : [Job { command : Command, job : List Job, inputFiles : List Str }, Blah Str] -Rbt : { default: Job } +Rbt : { default : Job } mainForHost : Rbt mainForHost = main diff --git a/crates/glue/tests/fixtures/multiple-modules/Dep1.roc b/crates/glue/tests/fixtures/multiple-modules/Dep1.roc index c698bb66f2..291dfd66ac 100644 --- a/crates/glue/tests/fixtures/multiple-modules/Dep1.roc +++ b/crates/glue/tests/fixtures/multiple-modules/Dep1.roc @@ -1,5 +1,5 @@ interface Dep1 exposes [DepStr1, string] imports [] -DepStr1 := [ S Str ] +DepStr1 := [S Str] string = \s -> @DepStr1 (S s) diff --git a/crates/glue/tests/fixtures/multiple-modules/Dep2.roc b/crates/glue/tests/fixtures/multiple-modules/Dep2.roc index 830a8d8a96..99f00e08c1 100644 --- a/crates/glue/tests/fixtures/multiple-modules/Dep2.roc +++ b/crates/glue/tests/fixtures/multiple-modules/Dep2.roc @@ -1,5 +1,5 @@ interface Dep2 exposes [DepStr2, string] imports [] -DepStr2 := [ R Str ] +DepStr2 := [R Str] string = \s -> @DepStr2 (R s) diff --git a/crates/glue/tests/fixtures/multiple-modules/app.roc b/crates/glue/tests/fixtures/multiple-modules/app.roc index 5ff6397dc0..da8a540581 100644 --- a/crates/glue/tests/fixtures/multiple-modules/app.roc +++ b/crates/glue/tests/fixtures/multiple-modules/app.roc @@ -3,4 +3,4 @@ app "app" imports [pf.Dep1, pf.Dep2] provides [main] to pf -main = {s1: Dep1.string "hello", s2: Dep2.string "world"} +main = { s1: Dep1.string "hello", s2: Dep2.string "world" } diff --git a/crates/glue/tests/fixtures/multiple-modules/platform.roc b/crates/glue/tests/fixtures/multiple-modules/platform.roc index e7dcc2c38a..016bb3fc13 100644 --- a/crates/glue/tests/fixtures/multiple-modules/platform.roc +++ b/crates/glue/tests/fixtures/multiple-modules/platform.roc @@ -5,7 +5,7 @@ platform "test-platform" imports [Dep1, Dep2] provides [mainForHost] -Combined : {s1: Dep1.DepStr1, s2: Dep2.DepStr2} +Combined : { s1 : Dep1.DepStr1, s2 : Dep2.DepStr2 } mainForHost : Combined mainForHost = main diff --git a/crates/glue/tests/test_glue_cli.rs b/crates/glue/tests/test_glue_cli.rs index ba36f86d97..ed75182b6c 100644 --- a/crates/glue/tests/test_glue_cli.rs +++ b/crates/glue/tests/test_glue_cli.rs @@ -122,6 +122,9 @@ mod glue_cli_run { multiple_modules:"multiple-modules" => indoc!(r#" combined was: Combined { s1: DepStr1::S("hello"), s2: DepStr2::R("world") } "#), + arguments:"arguments" => indoc!(r#" + Answer was: 84 + "#), } fn check_for_tests(all_fixtures: &mut roc_collections::VecSet) {