mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-03 19:58:18 +00:00
generate signature for the entry points
This commit is contained in:
parent
d42e831e47
commit
3ff17aa0ea
11 changed files with 150 additions and 92 deletions
|
@ -1,5 +1,5 @@
|
|||
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]
|
||||
|
||||
# TODO: switch AssocList uses to Dict once roc_std is updated.
|
||||
|
@ -19,12 +19,19 @@ Types := {
|
|||
## 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.
|
||||
deps : List Tuple2,
|
||||
|
||||
## Names and types of the entry points of the program (e.g. mainForHost)
|
||||
entrypoints : List Tuple1,
|
||||
|
||||
target : Target,
|
||||
}
|
||||
|
||||
target : 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 { types: shapes }, originalState, update ->
|
||||
List.walk shapes { index: 0, state: originalState } \{ index, state }, elem ->
|
||||
|
|
|
@ -8,7 +8,7 @@ makeGlue = \typesByArch ->
|
|||
modFileContent =
|
||||
List.walk typesByArch "" \content, types ->
|
||||
arch = (Types.target types).architecture
|
||||
archStr = archName arch
|
||||
archStr = archName arch
|
||||
|
||||
Str.concat
|
||||
content
|
||||
|
@ -17,7 +17,7 @@ makeGlue = \typesByArch ->
|
|||
mod \(archStr);
|
||||
#[cfg(target_arch = "\(archStr)")]
|
||||
pub use \(archStr)::*;
|
||||
|
||||
|
||||
"""
|
||||
|
||||
typesByArch
|
||||
|
@ -88,13 +88,90 @@ convertTypesToFile = \types ->
|
|||
buf
|
||||
|
||||
arch = (Types.target types).architecture
|
||||
archStr = archName arch
|
||||
archStr = archName arch
|
||||
|
||||
{
|
||||
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 ->
|
||||
# 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 ->
|
||||
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() }
|
||||
}
|
||||
"""
|
||||
|
||||
generateStruct : Str, Types, TypeId, _, _, _ -> Str
|
||||
generateStruct = \buf, types, id, name, structFields, visibility ->
|
||||
escapedName = escapeKW name
|
||||
|
@ -169,7 +246,7 @@ generateEnumeration = \buf, types, enumType, name, tags, tagBytes ->
|
|||
impl core::fmt::Debug for \(escapedName) {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
match self {
|
||||
|
||||
|
||||
"""
|
||||
|> \b -> List.walk tags b (generateEnumTagsDebug name)
|
||||
|> Str.concat "\(indent)\(indent)}\n\(indent)}\n}\n\n"
|
||||
|
@ -222,7 +299,7 @@ generateNonRecursiveTagUnion = \buf, types, id, name, tags, discriminantSize, di
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
"""
|
||||
|> Str.concat "// TODO: NonRecursive TagUnion constructor impls\n\n"
|
||||
|> \b ->
|
||||
|
@ -235,7 +312,7 @@ generateNonRecursiveTagUnion = \buf, types, id, name, tags, discriminantSize, di
|
|||
impl Drop for \(escapedName) {
|
||||
fn drop(&mut self) {
|
||||
// Drop the payloads
|
||||
|
||||
|
||||
"""
|
||||
|> generateTagUnionDropPayload types selfMut tags discriminantName discriminantSize 2
|
||||
|> Str.concat
|
||||
|
@ -243,7 +320,7 @@ generateNonRecursiveTagUnion = \buf, types, id, name, tags, discriminantSize, di
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
"""
|
||||
else
|
||||
b
|
||||
|
@ -428,7 +505,7 @@ generateMultiElementSingleTagStruct = \buf, types, name, tagName, payloadFields,
|
|||
|> Str.concat
|
||||
"""
|
||||
impl \(name) {
|
||||
|
||||
|
||||
"""
|
||||
|> \b ->
|
||||
fieldTypes =
|
||||
|
@ -475,7 +552,7 @@ generateMultiElementSingleTagStruct = \buf, types, name, tagName, payloadFields,
|
|||
\(indent) }
|
||||
\(indent)}
|
||||
|
||||
|
||||
|
||||
""",
|
||||
fieldTypes,
|
||||
fieldAccesses,
|
||||
|
@ -494,7 +571,7 @@ generateMultiElementSingleTagStruct = \buf, types, name, tagName, payloadFields,
|
|||
\(indent) \(retExpr)
|
||||
\(indent)}
|
||||
|
||||
|
||||
|
||||
""",
|
||||
fieldTypes,
|
||||
fieldAccesses,
|
||||
|
@ -517,7 +594,7 @@ generateMultiElementSingleTagStruct = \buf, types, name, tagName, payloadFields,
|
|||
\(indent)pub fn as_\(tagName)(&self) -> \(retType) {
|
||||
\(indent) \(retExpr)
|
||||
\(indent)}
|
||||
|
||||
|
||||
"""
|
||||
|> Str.concat
|
||||
"""
|
||||
|
@ -527,7 +604,7 @@ generateMultiElementSingleTagStruct = \buf, types, name, tagName, payloadFields,
|
|||
impl core::fmt::Debug for \(name) {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
f.debug_tuple("\(name)::\(tagName)")
|
||||
|
||||
|
||||
"""
|
||||
|> \b ->
|
||||
payloadFields
|
||||
|
@ -542,7 +619,7 @@ generateMultiElementSingleTagStruct = \buf, types, name, tagName, payloadFields,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
"""
|
||||
|
||||
asRustTuple = \list ->
|
||||
|
@ -585,7 +662,7 @@ generateZeroElementSingleTagStruct = \buf, name, tagName ->
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
"""
|
||||
|
||||
generateDeriveStr = \buf, types, type, includeDebug ->
|
||||
|
@ -854,7 +931,7 @@ fileHeader =
|
|||
#![allow(clippy::clone_on_copy)]
|
||||
|
||||
|
||||
|
||||
|
||||
"""
|
||||
|
||||
indent = " "
|
||||
|
|
|
@ -453,7 +453,7 @@ pub fn load_types(
|
|||
}
|
||||
}
|
||||
|
||||
let types = Types::new(
|
||||
let types = Types::new_with_entry_points(
|
||||
arena,
|
||||
subs,
|
||||
variables.clone(),
|
||||
|
@ -461,6 +461,7 @@ pub fn load_types(
|
|||
glue_procs_by_layout,
|
||||
layout_cache,
|
||||
target_info,
|
||||
exposed_to_host.clone(),
|
||||
);
|
||||
|
||||
arch_types.push(types);
|
||||
|
|
|
@ -42,6 +42,7 @@ pub struct File {
|
|||
pub struct Types {
|
||||
pub aligns: roc_std::RocList<u32>,
|
||||
pub deps: roc_std::RocList<Tuple2>,
|
||||
pub entrypoints: roc_std::RocList<Tuple1>,
|
||||
pub sizes: roc_std::RocList<u32>,
|
||||
pub types: roc_std::RocList<RocType>,
|
||||
pub typesByName: roc_std::RocList<Tuple1>,
|
||||
|
|
|
@ -81,7 +81,7 @@ impl Types {
|
|||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) fn new<'a, I: Iterator<Item = Variable>>(
|
||||
pub(crate) fn new_with_entry_points<'a, I: Iterator<Item = Variable>>(
|
||||
arena: &'a Bump,
|
||||
subs: &'a Subs,
|
||||
variables: I,
|
||||
|
@ -89,6 +89,7 @@ impl Types {
|
|||
glue_procs_by_layout: MutMap<Layout<'a>, &'a [String]>,
|
||||
layout_cache: LayoutCache<'a>,
|
||||
target: TargetInfo,
|
||||
mut entry_points: MutMap<Symbol, Variable>,
|
||||
) -> Self {
|
||||
let mut types = Self::with_capacity(variables.size_hint().0, target);
|
||||
let mut env = Env::new(
|
||||
|
@ -102,9 +103,37 @@ impl Types {
|
|||
|
||||
for var in variables {
|
||||
env.lambda_set_ids = env.find_lambda_sets(var);
|
||||
env.add_type(var, &mut types);
|
||||
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 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);
|
||||
|
||||
types
|
||||
|
@ -626,9 +655,17 @@ impl From<&Types> for roc_type::Types {
|
|||
.iter()
|
||||
.map(|(k, v)| roc_type::Tuple1::T(k.as_str().into(), v.0 as _))
|
||||
.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 {
|
||||
aligns: types.aligns.as_slice().into(),
|
||||
deps,
|
||||
entrypoints,
|
||||
sizes: types.sizes.as_slice().into(),
|
||||
types: types.types.iter().map(|t| t.into()).collect(),
|
||||
typesByName: types_by_name,
|
||||
|
|
|
@ -1,22 +1,11 @@
|
|||
mod test_glue;
|
||||
|
||||
extern "C" {
|
||||
#[link_name = "roc__mainForHost_1_exposed_generic"]
|
||||
fn roc_main(_: *mut test_glue::MyRcd);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn rust_main() -> i32 {
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::hash_set::HashSet;
|
||||
|
||||
let record = unsafe {
|
||||
let mut ret: core::mem::MaybeUninit<test_glue::MyRcd> = core::mem::MaybeUninit::uninit();
|
||||
|
||||
roc_main(ret.as_mut_ptr());
|
||||
|
||||
ret.assume_init()
|
||||
};
|
||||
let record = test_glue::mainForHost();
|
||||
|
||||
// Verify that the record has all the expected traits.
|
||||
|
||||
|
|
|
@ -1,22 +1,11 @@
|
|||
mod test_glue;
|
||||
|
||||
extern "C" {
|
||||
#[link_name = "roc__mainForHost_1_exposed_generic"]
|
||||
fn roc_main(_: *mut test_glue::MyEnum);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn rust_main() -> i32 {
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::hash_set::HashSet;
|
||||
|
||||
let tag_union = unsafe {
|
||||
let mut ret: core::mem::MaybeUninit<test_glue::MyEnum> = core::mem::MaybeUninit::uninit();
|
||||
|
||||
roc_main(ret.as_mut_ptr());
|
||||
|
||||
ret.assume_init()
|
||||
};
|
||||
let tag_union = test_glue::mainForHost();
|
||||
|
||||
// Verify that it has all the expected traits.
|
||||
|
||||
|
|
|
@ -1,25 +1,13 @@
|
|||
mod test_glue;
|
||||
|
||||
use indoc::indoc;
|
||||
use test_glue::Combined;
|
||||
|
||||
extern "C" {
|
||||
#[link_name = "roc__mainForHost_1_exposed_generic"]
|
||||
fn roc_main(_: *mut Combined);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn rust_main() -> i32 {
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::hash_set::HashSet;
|
||||
|
||||
let tag_union = unsafe {
|
||||
let mut ret: core::mem::MaybeUninit<Combined> = core::mem::MaybeUninit::uninit();
|
||||
|
||||
roc_main(ret.as_mut_ptr());
|
||||
|
||||
ret.assume_init()
|
||||
};
|
||||
let tag_union = test_glue::mainForHost();
|
||||
|
||||
// Verify that it has all the expected traits.
|
||||
|
||||
|
|
|
@ -1,21 +1,10 @@
|
|||
mod test_glue;
|
||||
|
||||
extern "C" {
|
||||
#[link_name = "roc__mainForHost_1_exposed_generic"]
|
||||
fn roc_main(_: *mut test_glue::Outer);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn rust_main() -> i32 {
|
||||
use std::cmp::Ordering;
|
||||
|
||||
let outer = unsafe {
|
||||
let mut ret: core::mem::MaybeUninit<test_glue::Outer> = core::mem::MaybeUninit::uninit();
|
||||
|
||||
roc_main(ret.as_mut_ptr());
|
||||
|
||||
ret.assume_init()
|
||||
};
|
||||
let outer = test_glue::mainForHost();
|
||||
|
||||
// Verify that `inner` has all the expected traits.
|
||||
{
|
||||
|
|
|
@ -3,23 +3,12 @@ mod test_glue;
|
|||
use indoc::indoc;
|
||||
use test_glue::SingleTagUnion;
|
||||
|
||||
extern "C" {
|
||||
#[link_name = "roc__mainForHost_1_exposed_generic"]
|
||||
fn roc_main(_: *mut SingleTagUnion);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn rust_main() -> i32 {
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::hash_set::HashSet;
|
||||
|
||||
let tag_union = unsafe {
|
||||
let mut ret: core::mem::MaybeUninit<SingleTagUnion> = core::mem::MaybeUninit::uninit();
|
||||
|
||||
roc_main(ret.as_mut_ptr());
|
||||
|
||||
ret.assume_init()
|
||||
};
|
||||
let tag_union = test_glue::mainForHost();
|
||||
|
||||
// Verify that it has all the expected traits.
|
||||
|
||||
|
|
|
@ -10,10 +10,7 @@ use std::io::Write;
|
|||
use std::mem::MaybeUninit;
|
||||
use std::os::raw::c_char;
|
||||
|
||||
extern "C" {
|
||||
#[link_name = "roc__mainForHost_1_exposed_generic"]
|
||||
fn roc_main(_: *mut Op);
|
||||
}
|
||||
use glue::mainForHost as roc_main;
|
||||
|
||||
#[no_mangle]
|
||||
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!");
|
||||
|
||||
let mut op: Op = unsafe {
|
||||
let mut mem = MaybeUninit::uninit();
|
||||
|
||||
roc_main(mem.as_mut_ptr());
|
||||
|
||||
mem.assume_init()
|
||||
};
|
||||
let mut op: Op = roc_main();
|
||||
|
||||
loop {
|
||||
match dbg!(op.discriminant()) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue