mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-27 05:49:08 +00:00
Merge branch 'main' into Frame-Limited
This commit is contained in:
commit
b0c1877a04
26 changed files with 448 additions and 193 deletions
|
@ -305,8 +305,8 @@ where
|
||||||
debug_assert_eq!(variant_types.len(), 1);
|
debug_assert_eq!(variant_types.len(), 1);
|
||||||
variant_types[0]
|
variant_types[0]
|
||||||
} else {
|
} else {
|
||||||
let data_type = builder.add_union_type(&variant_types)?;
|
|
||||||
let cell_type = builder.add_heap_cell_type();
|
let cell_type = builder.add_heap_cell_type();
|
||||||
|
let data_type = builder.add_union_type(&variant_types)?;
|
||||||
|
|
||||||
builder.add_tuple_type(&[cell_type, data_type])?
|
builder.add_tuple_type(&[cell_type, data_type])?
|
||||||
};
|
};
|
||||||
|
@ -1476,7 +1476,8 @@ fn expr_spec<'a>(
|
||||||
|
|
||||||
let _unit = builder.add_update(block, update_mode_var, heap_cell)?;
|
let _unit = builder.add_update(block, update_mode_var, heap_cell)?;
|
||||||
|
|
||||||
with_new_heap_cell(builder, block, union_data)
|
let value = with_new_heap_cell(builder, block, union_data)?;
|
||||||
|
builder.add_make_named(block, MOD_APP, type_name, value)
|
||||||
}
|
}
|
||||||
RuntimeErrorFunction(_) => {
|
RuntimeErrorFunction(_) => {
|
||||||
let type_id = layout_spec(env, builder, interner, layout)?;
|
let type_id = layout_spec(env, builder, interner, layout)?;
|
||||||
|
|
|
@ -4421,3 +4421,42 @@ fn layout_cache_structure_with_multiple_recursive_structures() {
|
||||||
u8
|
u8
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(any(feature = "gen-llvm"))]
|
||||||
|
fn reset_recursive_type_wraps_in_named_type() {
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r###"
|
||||||
|
app "test" provides [main] to "./platform"
|
||||||
|
|
||||||
|
main : Str
|
||||||
|
main =
|
||||||
|
newList = mapLinkedList (Cons 1 (Cons 2 (Cons 3 Nil))) (\x -> x + 1)
|
||||||
|
printLinkedList newList Num.toStr
|
||||||
|
|
||||||
|
LinkedList a : [Cons a (LinkedList a), Nil]
|
||||||
|
|
||||||
|
mapLinkedList : LinkedList a, (a -> b) -> LinkedList b
|
||||||
|
mapLinkedList = \linkedList, f -> when linkedList is
|
||||||
|
Nil -> Nil
|
||||||
|
Cons x xs ->
|
||||||
|
s = if Bool.true then "true" else "false"
|
||||||
|
expect s == "true"
|
||||||
|
|
||||||
|
Cons (f x) (mapLinkedList xs f)
|
||||||
|
|
||||||
|
printLinkedList : LinkedList a, (a -> Str) -> Str
|
||||||
|
printLinkedList = \linkedList, f ->
|
||||||
|
when linkedList is
|
||||||
|
Nil -> "Nil"
|
||||||
|
Cons x xs ->
|
||||||
|
strX = f x
|
||||||
|
strXs = printLinkedList xs f
|
||||||
|
"Cons \(strX) (\(strXs))"
|
||||||
|
"###
|
||||||
|
),
|
||||||
|
RocStr::from("Cons 2 (Cons 3 (Cons 4 (Nil)))"),
|
||||||
|
RocStr
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -132,4 +132,5 @@ RocFn : {
|
||||||
args : List TypeId,
|
args : List TypeId,
|
||||||
lambdaSet : TypeId,
|
lambdaSet : TypeId,
|
||||||
ret : TypeId,
|
ret : TypeId,
|
||||||
|
isToplevel : Bool,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
interface Types
|
interface Types
|
||||||
exposes [Types, shape, size, alignment, target, walkShapes]
|
exposes [Types, shape, size, alignment, target, walkShapes, entryPoints]
|
||||||
imports [Shape.{ Shape }, TypeId.{ TypeId }, Target.{ Target }, InternalTypeId]
|
imports [Shape.{ Shape }, TypeId.{ TypeId }, Target.{ Target }, InternalTypeId]
|
||||||
|
|
||||||
# TODO: switch AssocList uses to Dict once roc_std is updated.
|
# TODO: switch AssocList uses to Dict once roc_std is updated.
|
||||||
|
@ -19,12 +19,18 @@ Types := {
|
||||||
## This is important for declaration order in C; we need to output a
|
## This is important for declaration order in C; we need to output a
|
||||||
## type declaration earlier in the file than where it gets referenced by another type.
|
## type declaration earlier in the file than where it gets referenced by another type.
|
||||||
deps : List Tuple2,
|
deps : List Tuple2,
|
||||||
|
|
||||||
|
## Names and types of the entry points of the program (e.g. mainForHost)
|
||||||
|
entrypoints : List Tuple1,
|
||||||
target : Target,
|
target : Target,
|
||||||
}
|
}
|
||||||
|
|
||||||
target : Types -> Target
|
target : Types -> Target
|
||||||
target = \@Types types -> types.target
|
target = \@Types types -> types.target
|
||||||
|
|
||||||
|
entryPoints : Types -> List Tuple1
|
||||||
|
entryPoints = \@Types { entrypoints } -> entrypoints
|
||||||
|
|
||||||
walkShapes : Types, state, (state, Shape, TypeId -> state) -> state
|
walkShapes : Types, state, (state, Shape, TypeId -> state) -> state
|
||||||
walkShapes = \@Types { types: shapes }, originalState, update ->
|
walkShapes = \@Types { types: shapes }, originalState, update ->
|
||||||
List.walk shapes { index: 0, state: originalState } \{ index, state }, elem ->
|
List.walk shapes { index: 0, state: originalState } \{ index, state }, elem ->
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
app "rust-glue"
|
app "rust-glue"
|
||||||
packages { pf: "../platform/main.roc" }
|
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
|
provides [makeGlue] to pf
|
||||||
|
|
||||||
makeGlue : List Types -> Result (List File) Str
|
makeGlue : List Types -> Result (List File) Str
|
||||||
|
@ -63,9 +63,11 @@ convertTypesToFile = \types ->
|
||||||
TagUnion (NonNullableUnwrapped { name, tagName, payload }) ->
|
TagUnion (NonNullableUnwrapped { name, tagName, payload }) ->
|
||||||
generateRecursiveTagUnion buf types id name [{ name: tagName, payload: Some payload }] 0 0 None
|
generateRecursiveTagUnion buf types id name [{ name: tagName, payload: Some payload }] 0 0 None
|
||||||
|
|
||||||
Function _ ->
|
Function rocFn ->
|
||||||
# TODO: actually generate glue functions.
|
if rocFn.isToplevel then
|
||||||
buf
|
buf
|
||||||
|
else
|
||||||
|
generateFunction buf types rocFn
|
||||||
|
|
||||||
RecursivePointer _ ->
|
RecursivePointer _ ->
|
||||||
# This is recursively pointing to a type that should already have been added,
|
# This is recursively pointing to a type that should already have been added,
|
||||||
|
@ -92,9 +94,129 @@ convertTypesToFile = \types ->
|
||||||
|
|
||||||
{
|
{
|
||||||
name: "\(archStr).rs",
|
name: "\(archStr).rs",
|
||||||
content,
|
content: content |> generateEntryPoints types,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 = \buf, types, name, id ->
|
||||||
|
publicSignature =
|
||||||
|
when Types.shape types id is
|
||||||
|
Function rocFn ->
|
||||||
|
arguments =
|
||||||
|
rocFn.args
|
||||||
|
|> List.mapWithIndex \argId, i ->
|
||||||
|
type = typeName types argId
|
||||||
|
c = Num.toStr i
|
||||||
|
"arg\(c): \(type)"
|
||||||
|
|> Str.joinWith ", "
|
||||||
|
|
||||||
|
ret = typeName types rocFn.ret
|
||||||
|
|
||||||
|
"(\(arguments)) -> \(ret)"
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
ret = typeName types id
|
||||||
|
"() -> \(ret)"
|
||||||
|
|
||||||
|
externSignature =
|
||||||
|
when Types.shape types id is
|
||||||
|
Function rocFn ->
|
||||||
|
arguments =
|
||||||
|
rocFn.args
|
||||||
|
|> List.map \argId ->
|
||||||
|
type = typeName types argId
|
||||||
|
"_: \(type)"
|
||||||
|
|> Str.joinWith ", "
|
||||||
|
|
||||||
|
ret = typeName types rocFn.ret
|
||||||
|
"(_: *mut \(ret), \(arguments))"
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
ret = typeName types id
|
||||||
|
"(_: *mut \(ret))"
|
||||||
|
|
||||||
|
externArguments =
|
||||||
|
when Types.shape types id is
|
||||||
|
Function rocFn ->
|
||||||
|
rocFn.args
|
||||||
|
|> List.mapWithIndex \_, i ->
|
||||||
|
c = Num.toStr i
|
||||||
|
"arg\(c)"
|
||||||
|
|> Str.joinWith ", "
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
""
|
||||||
|
|
||||||
|
"""
|
||||||
|
\(buf)
|
||||||
|
|
||||||
|
pub fn \(name)\(publicSignature) {
|
||||||
|
extern "C" {
|
||||||
|
fn roc__\(name)_1_exposed_generic\(externSignature);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut ret = std::mem::MaybeUninit::uninit();
|
||||||
|
|
||||||
|
unsafe { roc__\(name)_1_exposed_generic(ret.as_mut_ptr(), \(externArguments)) };
|
||||||
|
|
||||||
|
unsafe { ret.assume_init() }
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
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 : Str, Types, TypeId, _, _, _ -> Str
|
||||||
generateStruct = \buf, types, id, name, structFields, visibility ->
|
generateStruct = \buf, types, id, name, structFields, visibility ->
|
||||||
escapedName = escapeKW name
|
escapedName = escapeKW name
|
||||||
|
@ -125,6 +247,7 @@ generateStructFields = \buf, types, visibility, structFields ->
|
||||||
when structFields is
|
when structFields is
|
||||||
HasNoClosure fields ->
|
HasNoClosure fields ->
|
||||||
List.walk fields buf (generateStructFieldWithoutClosure types visibility)
|
List.walk fields buf (generateStructFieldWithoutClosure types visibility)
|
||||||
|
|
||||||
HasClosure _ ->
|
HasClosure _ ->
|
||||||
Str.concat buf "// TODO: Struct fields with closures"
|
Str.concat buf "// TODO: Struct fields with closures"
|
||||||
|
|
||||||
|
@ -147,6 +270,7 @@ nameTagUnionPayloadFields = \payloadFields ->
|
||||||
HasNoClosure fields ->
|
HasNoClosure fields ->
|
||||||
renamedFields = List.map fields \{ name, id } -> { name: "f\(name)", id }
|
renamedFields = List.map fields \{ name, id } -> { name: "f\(name)", id }
|
||||||
HasNoClosure renamedFields
|
HasNoClosure renamedFields
|
||||||
|
|
||||||
HasClosure fields ->
|
HasClosure fields ->
|
||||||
renamedFields = List.map fields \{ name, id, accessors } -> { name: "f\(name)", id, accessors }
|
renamedFields = List.map fields \{ name, id, accessors } -> { name: "f\(name)", id, accessors }
|
||||||
HasClosure renamedFields
|
HasClosure renamedFields
|
||||||
|
@ -371,7 +495,7 @@ generateUnionField = \types ->
|
||||||
else
|
else
|
||||||
typeStr
|
typeStr
|
||||||
|
|
||||||
Str.concat accum "\(indent)\(escapedFieldName): \(fullTypeStr),\n"
|
Str.concat accum "\(indent)\(escapedFieldName): std::mem::ManuallyDrop<\(fullTypeStr)>,\n"
|
||||||
|
|
||||||
None ->
|
None ->
|
||||||
# If there's no payload, we don't need a discriminant for it.
|
# If there's no payload, we don't need a discriminant for it.
|
||||||
|
@ -417,6 +541,7 @@ generateSingleTagStruct = \buf, types, name, tagName, payload ->
|
||||||
generateZeroElementSingleTagStruct b escapedName tagName
|
generateZeroElementSingleTagStruct b escapedName tagName
|
||||||
else
|
else
|
||||||
generateMultiElementSingleTagStruct b types escapedName tagName fields asStructFields
|
generateMultiElementSingleTagStruct b types escapedName tagName fields asStructFields
|
||||||
|
|
||||||
HasClosure _ ->
|
HasClosure _ ->
|
||||||
Str.concat buf "\\TODO: SingleTagStruct with closures"
|
Str.concat buf "\\TODO: SingleTagStruct with closures"
|
||||||
|
|
||||||
|
|
|
@ -380,11 +380,8 @@ pub fn load_types(
|
||||||
|
|
||||||
// Get the variables for all the exposed_to_host symbols
|
// Get the variables for all the exposed_to_host symbols
|
||||||
let variables = (0..decls.len()).filter_map(|index| {
|
let variables = (0..decls.len()).filter_map(|index| {
|
||||||
if exposed_to_host.contains_key(&decls.symbols[index].value) {
|
let symbol = decls.symbols[index].value;
|
||||||
Some(decls.variables[index])
|
exposed_to_host.get(&symbol).copied()
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let operating_system = target_info.operating_system;
|
let operating_system = target_info.operating_system;
|
||||||
|
@ -453,14 +450,14 @@ pub fn load_types(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let types = Types::new(
|
let types = Types::new_with_entry_points(
|
||||||
arena,
|
arena,
|
||||||
subs,
|
subs,
|
||||||
variables.clone(),
|
|
||||||
arena.alloc(interns),
|
arena.alloc(interns),
|
||||||
glue_procs_by_layout,
|
glue_procs_by_layout,
|
||||||
layout_cache,
|
layout_cache,
|
||||||
target_info,
|
target_info,
|
||||||
|
exposed_to_host.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
arch_types.push(types);
|
arch_types.push(types);
|
||||||
|
|
|
@ -42,6 +42,7 @@ pub struct File {
|
||||||
pub struct Types {
|
pub struct Types {
|
||||||
pub aligns: roc_std::RocList<u32>,
|
pub aligns: roc_std::RocList<u32>,
|
||||||
pub deps: roc_std::RocList<Tuple2>,
|
pub deps: roc_std::RocList<Tuple2>,
|
||||||
|
pub entrypoints: roc_std::RocList<Tuple1>,
|
||||||
pub sizes: roc_std::RocList<u32>,
|
pub sizes: roc_std::RocList<u32>,
|
||||||
pub types: roc_std::RocList<RocType>,
|
pub types: roc_std::RocList<RocType>,
|
||||||
pub typesByName: roc_std::RocList<Tuple1>,
|
pub typesByName: roc_std::RocList<Tuple1>,
|
||||||
|
@ -567,6 +568,7 @@ pub struct RocFn {
|
||||||
pub functionName: roc_std::RocStr,
|
pub functionName: roc_std::RocStr,
|
||||||
pub lambdaSet: u32,
|
pub lambdaSet: u32,
|
||||||
pub ret: u32,
|
pub ret: u32,
|
||||||
|
pub is_toplevel: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
|
#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
|
||||||
|
@ -713,6 +715,7 @@ pub struct RocFn {
|
||||||
pub functionName: roc_std::RocStr,
|
pub functionName: roc_std::RocStr,
|
||||||
pub lambdaSet: u64,
|
pub lambdaSet: u64,
|
||||||
pub ret: u64,
|
pub ret: u64,
|
||||||
|
pub isToplevel: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Tuple1 {
|
impl Tuple1 {
|
||||||
|
|
|
@ -21,7 +21,7 @@ use roc_mono::{
|
||||||
};
|
};
|
||||||
use roc_target::{Architecture, OperatingSystem, TargetInfo};
|
use roc_target::{Architecture, OperatingSystem, TargetInfo};
|
||||||
use roc_types::{
|
use roc_types::{
|
||||||
subs::{Content, FlatType, GetSubsSlice, Label, Subs, UnionLabels, Variable},
|
subs::{Content, FlatType, GetSubsSlice, Label, Subs, SubsSlice, UnionLabels, Variable},
|
||||||
types::{AliasKind, RecordField},
|
types::{AliasKind, RecordField},
|
||||||
};
|
};
|
||||||
use std::convert::From;
|
use std::convert::From;
|
||||||
|
@ -68,10 +68,16 @@ pub struct Types {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Types {
|
impl Types {
|
||||||
|
const UNIT: TypeId = TypeId(0);
|
||||||
|
|
||||||
pub fn with_capacity(cap: usize, target_info: TargetInfo) -> Self {
|
pub fn with_capacity(cap: usize, target_info: TargetInfo) -> Self {
|
||||||
|
let mut types = Vec::with_capacity(cap);
|
||||||
|
|
||||||
|
types.push(RocType::Unit);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
target: target_info,
|
target: target_info,
|
||||||
types: Vec::with_capacity(cap),
|
types,
|
||||||
types_by_name: FnvHashMap::with_capacity_and_hasher(10, Default::default()),
|
types_by_name: FnvHashMap::with_capacity_and_hasher(10, Default::default()),
|
||||||
entry_points: Vec::new(),
|
entry_points: Vec::new(),
|
||||||
sizes: Vec::new(),
|
sizes: Vec::new(),
|
||||||
|
@ -81,16 +87,16 @@ impl Types {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub(crate) fn new<'a, I: Iterator<Item = Variable>>(
|
pub(crate) fn new_with_entry_points<'a>(
|
||||||
arena: &'a Bump,
|
arena: &'a Bump,
|
||||||
subs: &'a Subs,
|
subs: &'a Subs,
|
||||||
variables: I,
|
|
||||||
interns: &'a Interns,
|
interns: &'a Interns,
|
||||||
glue_procs_by_layout: MutMap<Layout<'a>, &'a [String]>,
|
glue_procs_by_layout: MutMap<Layout<'a>, &'a [String]>,
|
||||||
layout_cache: LayoutCache<'a>,
|
layout_cache: LayoutCache<'a>,
|
||||||
target: TargetInfo,
|
target: TargetInfo,
|
||||||
|
mut entry_points: MutMap<Symbol, Variable>,
|
||||||
) -> Self {
|
) -> 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(
|
let mut env = Env::new(
|
||||||
arena,
|
arena,
|
||||||
subs,
|
subs,
|
||||||
|
@ -100,10 +106,23 @@ impl Types {
|
||||||
target,
|
target,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let variables: Vec<_> = entry_points.values().copied().collect();
|
||||||
for var in variables {
|
for var in variables {
|
||||||
env.lambda_set_ids = env.find_lambda_sets(var);
|
env.lambda_set_ids = env.find_lambda_sets(var);
|
||||||
env.add_type(var, &mut types);
|
let id = env.add_toplevel_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);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_assert!(entry_points.is_empty());
|
||||||
|
|
||||||
env.resolve_pending_recursive_types(&mut types);
|
env.resolve_pending_recursive_types(&mut types);
|
||||||
|
|
||||||
|
@ -412,6 +431,7 @@ impl Types {
|
||||||
args: args_a,
|
args: args_a,
|
||||||
lambda_set: lambda_a,
|
lambda_set: lambda_a,
|
||||||
ret: ret_a,
|
ret: ret_a,
|
||||||
|
is_toplevel: is_toplevel_a,
|
||||||
}),
|
}),
|
||||||
Function(RocFn {
|
Function(RocFn {
|
||||||
function_name: name_b,
|
function_name: name_b,
|
||||||
|
@ -419,12 +439,14 @@ impl Types {
|
||||||
args: args_b,
|
args: args_b,
|
||||||
lambda_set: lambda_b,
|
lambda_set: lambda_b,
|
||||||
ret: ret_b,
|
ret: ret_b,
|
||||||
|
is_toplevel: is_toplevel_b,
|
||||||
}),
|
}),
|
||||||
) => {
|
) => {
|
||||||
// for functions, the name is actually important because two functions
|
// for functions, the name is actually important because two functions
|
||||||
// with the same type could have completely different implementations!
|
// with the same type could have completely different implementations!
|
||||||
if name_a == name_b
|
if name_a == name_b
|
||||||
&& extern_a == extern_b
|
&& extern_a == extern_b
|
||||||
|
&& is_toplevel_a == is_toplevel_b
|
||||||
&& args_a.len() == args_b.len()
|
&& args_a.len() == args_b.len()
|
||||||
&& self.is_equivalent_help(
|
&& self.is_equivalent_help(
|
||||||
self.get_type_or_pending(*lambda_a),
|
self.get_type_or_pending(*lambda_a),
|
||||||
|
@ -626,9 +648,17 @@ impl From<&Types> for roc_type::Types {
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(k, v)| roc_type::Tuple1::T(k.as_str().into(), v.0 as _))
|
.map(|(k, v)| roc_type::Tuple1::T(k.as_str().into(), v.0 as _))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
let entrypoints = types
|
||||||
|
.entry_points()
|
||||||
|
.iter()
|
||||||
|
.map(|(k, v)| roc_type::Tuple1::T(k.as_str().into(), v.0 as _))
|
||||||
|
.collect();
|
||||||
|
|
||||||
roc_type::Types {
|
roc_type::Types {
|
||||||
aligns: types.aligns.as_slice().into(),
|
aligns: types.aligns.as_slice().into(),
|
||||||
deps,
|
deps,
|
||||||
|
entrypoints,
|
||||||
sizes: types.sizes.as_slice().into(),
|
sizes: types.sizes.as_slice().into(),
|
||||||
types: types.types.iter().map(|t| t.into()).collect(),
|
types: types.types.iter().map(|t| t.into()).collect(),
|
||||||
typesByName: types_by_name,
|
typesByName: types_by_name,
|
||||||
|
@ -667,12 +697,14 @@ impl From<&RocType> for roc_type::RocType {
|
||||||
args,
|
args,
|
||||||
lambda_set,
|
lambda_set,
|
||||||
ret,
|
ret,
|
||||||
|
is_toplevel,
|
||||||
}) => roc_type::RocType::Function(roc_type::RocFn {
|
}) => roc_type::RocType::Function(roc_type::RocFn {
|
||||||
args: args.iter().map(|arg| arg.0 as _).collect(),
|
args: args.iter().map(|arg| arg.0 as _).collect(),
|
||||||
functionName: function_name.as_str().into(),
|
functionName: function_name.as_str().into(),
|
||||||
externName: extern_name.as_str().into(),
|
externName: extern_name.as_str().into(),
|
||||||
ret: ret.0 as _,
|
ret: ret.0 as _,
|
||||||
lambdaSet: lambda_set.0 as _,
|
lambdaSet: lambda_set.0 as _,
|
||||||
|
isToplevel: *is_toplevel,
|
||||||
}),
|
}),
|
||||||
RocType::Unit => roc_type::RocType::Unit,
|
RocType::Unit => roc_type::RocType::Unit,
|
||||||
RocType::Unsized => roc_type::RocType::Unsized,
|
RocType::Unsized => roc_type::RocType::Unsized,
|
||||||
|
@ -937,6 +969,7 @@ impl RocStructFields {
|
||||||
pub struct RocFn {
|
pub struct RocFn {
|
||||||
pub function_name: String,
|
pub function_name: String,
|
||||||
pub extern_name: String,
|
pub extern_name: String,
|
||||||
|
pub is_toplevel: bool,
|
||||||
pub args: Vec<TypeId>,
|
pub args: Vec<TypeId>,
|
||||||
pub lambda_set: TypeId,
|
pub lambda_set: TypeId,
|
||||||
pub ret: TypeId,
|
pub ret: TypeId,
|
||||||
|
@ -1261,16 +1294,97 @@ impl<'a> Env<'a> {
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_type(&mut self, var: Variable, types: &mut Types) -> TypeId {
|
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 type");
|
roc_tracing::debug!(content=?roc_types::subs::SubsFmtContent(self.subs.get_content_without_compacting(var), self.subs), "adding toplevel type");
|
||||||
|
|
||||||
let layout = self
|
let layout = self
|
||||||
.layout_cache
|
.layout_cache
|
||||||
.from_var(self.arena, var, self.subs)
|
.from_var(self.arena, var, self.subs)
|
||||||
.expect("Something weird ended up in the content");
|
.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<Variable>,
|
||||||
|
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>(
|
fn add_type_help<'a>(
|
||||||
|
@ -1352,62 +1466,17 @@ fn add_type_help<'a>(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Content::Structure(FlatType::Func(args, closure_var, ret_var)) => {
|
Content::Structure(FlatType::Func(args, closure_var, ret_var)) => {
|
||||||
let args = env.subs.get_subs_slice(*args);
|
let is_toplevel = false; // or in any case, we cannot assume that we are
|
||||||
let mut arg_type_ids = Vec::with_capacity(args.len());
|
|
||||||
|
|
||||||
let name = format!("RocFunction_{:?}", closure_var);
|
add_function_type(
|
||||||
|
env,
|
||||||
let lambda_set_layout = env
|
layout,
|
||||||
.layout_cache
|
types,
|
||||||
.from_var(env.arena, *closure_var, env.subs)
|
args,
|
||||||
.expect("Something weird ended up in the content");
|
*closure_var,
|
||||||
|
*ret_var,
|
||||||
let _lambda_set = match env.layout_cache.interner.get(lambda_set_layout) {
|
is_toplevel,
|
||||||
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
|
|
||||||
}
|
}
|
||||||
Content::Structure(FlatType::FunctionOrTagUnion(_, _, _)) => {
|
Content::Structure(FlatType::FunctionOrTagUnion(_, _, _)) => {
|
||||||
todo!()
|
todo!()
|
||||||
|
|
|
@ -6,9 +6,9 @@ app "app"
|
||||||
main = {
|
main = {
|
||||||
default: Job {
|
default: Job {
|
||||||
command: Command {
|
command: Command {
|
||||||
tool: SystemTool { name: "test", num: 42 }
|
tool: SystemTool { name: "test", num: 42 },
|
||||||
|
},
|
||||||
|
inputFiles: ["foo"],
|
||||||
},
|
},
|
||||||
inputFiles : ["foo"]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ platform "test-platform"
|
||||||
|
|
||||||
Tool : [
|
Tool : [
|
||||||
SystemTool { name : Str, num : U32 },
|
SystemTool { name : Str, num : U32 },
|
||||||
FromJob { job : Job, num : U32 }
|
FromJob { job : Job, num : U32 },
|
||||||
]
|
]
|
||||||
|
|
||||||
Command : [Command { tool : Tool }]
|
Command : [Command { tool : Tool }]
|
||||||
|
|
7
crates/glue/tests/fixtures/arguments/app.roc
vendored
Normal file
7
crates/glue/tests/fixtures/arguments/app.roc
vendored
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
app "app"
|
||||||
|
packages { pf: "platform.roc" }
|
||||||
|
imports []
|
||||||
|
provides [main] to pf
|
||||||
|
|
||||||
|
main : I64 -> I64
|
||||||
|
main = \x -> 2 * x
|
9
crates/glue/tests/fixtures/arguments/platform.roc
vendored
Normal file
9
crates/glue/tests/fixtures/arguments/platform.roc
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
platform "test-platform"
|
||||||
|
requires {} { main : I64 -> I64 }
|
||||||
|
exposes []
|
||||||
|
packages {}
|
||||||
|
imports []
|
||||||
|
provides [mainForHost]
|
||||||
|
|
||||||
|
mainForHost : I64 -> I64
|
||||||
|
mainForHost = \x -> main x
|
60
crates/glue/tests/fixtures/arguments/src/lib.rs
vendored
Normal file
60
crates/glue/tests/fixtures/arguments/src/lib.rs
vendored
Normal file
|
@ -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)
|
||||||
|
}
|
|
@ -1,22 +1,11 @@
|
||||||
mod test_glue;
|
mod test_glue;
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#[link_name = "roc__mainForHost_1_exposed_generic"]
|
|
||||||
fn roc_main(_: *mut test_glue::MyRcd);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn rust_main() -> i32 {
|
pub extern "C" fn rust_main() -> i32 {
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::collections::hash_set::HashSet;
|
use std::collections::hash_set::HashSet;
|
||||||
|
|
||||||
let record = unsafe {
|
let record = test_glue::mainForHost();
|
||||||
let mut ret: core::mem::MaybeUninit<test_glue::MyRcd> = core::mem::MaybeUninit::uninit();
|
|
||||||
|
|
||||||
roc_main(ret.as_mut_ptr());
|
|
||||||
|
|
||||||
ret.assume_init()
|
|
||||||
};
|
|
||||||
|
|
||||||
// Verify that the record has all the expected traits.
|
// Verify that the record has all the expected traits.
|
||||||
|
|
||||||
|
|
|
@ -1,22 +1,11 @@
|
||||||
mod test_glue;
|
mod test_glue;
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#[link_name = "roc__mainForHost_1_exposed_generic"]
|
|
||||||
fn roc_main(_: *mut test_glue::MyEnum);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn rust_main() -> i32 {
|
pub extern "C" fn rust_main() -> i32 {
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::collections::hash_set::HashSet;
|
use std::collections::hash_set::HashSet;
|
||||||
|
|
||||||
let tag_union = unsafe {
|
let tag_union = test_glue::mainForHost();
|
||||||
let mut ret: core::mem::MaybeUninit<test_glue::MyEnum> = core::mem::MaybeUninit::uninit();
|
|
||||||
|
|
||||||
roc_main(ret.as_mut_ptr());
|
|
||||||
|
|
||||||
ret.assume_init()
|
|
||||||
};
|
|
||||||
|
|
||||||
// Verify that it has all the expected traits.
|
// Verify that it has all the expected traits.
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,6 @@ main = {
|
||||||
},
|
},
|
||||||
job: [],
|
job: [],
|
||||||
inputFiles: ["foo"],
|
inputFiles: ["foo"],
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,25 +1,13 @@
|
||||||
mod test_glue;
|
mod test_glue;
|
||||||
|
|
||||||
use indoc::indoc;
|
use indoc::indoc;
|
||||||
use test_glue::Combined;
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#[link_name = "roc__mainForHost_1_exposed_generic"]
|
|
||||||
fn roc_main(_: *mut Combined);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn rust_main() -> i32 {
|
pub extern "C" fn rust_main() -> i32 {
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::collections::hash_set::HashSet;
|
use std::collections::hash_set::HashSet;
|
||||||
|
|
||||||
let tag_union = unsafe {
|
let tag_union = test_glue::mainForHost();
|
||||||
let mut ret: core::mem::MaybeUninit<Combined> = core::mem::MaybeUninit::uninit();
|
|
||||||
|
|
||||||
roc_main(ret.as_mut_ptr());
|
|
||||||
|
|
||||||
ret.assume_init()
|
|
||||||
};
|
|
||||||
|
|
||||||
// Verify that it has all the expected traits.
|
// Verify that it has all the expected traits.
|
||||||
|
|
||||||
|
|
|
@ -1,21 +1,10 @@
|
||||||
mod test_glue;
|
mod test_glue;
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#[link_name = "roc__mainForHost_1_exposed_generic"]
|
|
||||||
fn roc_main(_: *mut test_glue::Outer);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn rust_main() -> i32 {
|
pub extern "C" fn rust_main() -> i32 {
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
let outer = unsafe {
|
let outer = test_glue::mainForHost();
|
||||||
let mut ret: core::mem::MaybeUninit<test_glue::Outer> = core::mem::MaybeUninit::uninit();
|
|
||||||
|
|
||||||
roc_main(ret.as_mut_ptr());
|
|
||||||
|
|
||||||
ret.assume_init()
|
|
||||||
};
|
|
||||||
|
|
||||||
// Verify that `inner` has all the expected traits.
|
// Verify that `inner` has all the expected traits.
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,23 +3,12 @@ mod test_glue;
|
||||||
use indoc::indoc;
|
use indoc::indoc;
|
||||||
use test_glue::SingleTagUnion;
|
use test_glue::SingleTagUnion;
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#[link_name = "roc__mainForHost_1_exposed_generic"]
|
|
||||||
fn roc_main(_: *mut SingleTagUnion);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn rust_main() -> i32 {
|
pub extern "C" fn rust_main() -> i32 {
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::collections::hash_set::HashSet;
|
use std::collections::hash_set::HashSet;
|
||||||
|
|
||||||
let tag_union = unsafe {
|
let tag_union = test_glue::mainForHost();
|
||||||
let mut ret: core::mem::MaybeUninit<SingleTagUnion> = core::mem::MaybeUninit::uninit();
|
|
||||||
|
|
||||||
roc_main(ret.as_mut_ptr());
|
|
||||||
|
|
||||||
ret.assume_init()
|
|
||||||
};
|
|
||||||
|
|
||||||
// Verify that it has all the expected traits.
|
// Verify that it has all the expected traits.
|
||||||
|
|
||||||
|
|
|
@ -122,6 +122,9 @@ mod glue_cli_run {
|
||||||
multiple_modules:"multiple-modules" => indoc!(r#"
|
multiple_modules:"multiple-modules" => indoc!(r#"
|
||||||
combined was: Combined { s1: DepStr1::S("hello"), s2: DepStr2::R("world") }
|
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<String>) {
|
fn check_for_tests(all_fixtures: &mut roc_collections::VecSet<String>) {
|
||||||
|
|
|
@ -10,10 +10,7 @@ use std::io::Write;
|
||||||
use std::mem::MaybeUninit;
|
use std::mem::MaybeUninit;
|
||||||
use std::os::raw::c_char;
|
use std::os::raw::c_char;
|
||||||
|
|
||||||
extern "C" {
|
use glue::mainForHost as roc_main;
|
||||||
#[link_name = "roc__mainForHost_1_exposed_generic"]
|
|
||||||
fn roc_main(_: *mut Op);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn roc_alloc(size: usize, _alignment: u32) -> *mut c_void {
|
pub unsafe extern "C" fn roc_alloc(size: usize, _alignment: u32) -> *mut c_void {
|
||||||
|
@ -93,13 +90,7 @@ pub extern "C" fn rust_main() -> i32 {
|
||||||
|
|
||||||
println!("Let's do things!");
|
println!("Let's do things!");
|
||||||
|
|
||||||
let mut op: Op = unsafe {
|
let mut op: Op = roc_main();
|
||||||
let mut mem = MaybeUninit::uninit();
|
|
||||||
|
|
||||||
roc_main(mem.as_mut_ptr());
|
|
||||||
|
|
||||||
mem.assume_init()
|
|
||||||
};
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
match dbg!(op.discriminant()) {
|
match dbg!(op.discriminant()) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue