mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 14:24:45 +00:00
generate signature for foreign symbols
This commit is contained in:
parent
4b8392696e
commit
a6e39e66f1
8 changed files with 75 additions and 31 deletions
|
@ -810,15 +810,29 @@ pub fn build_exp_expr<'a, 'ctx, 'env>(
|
||||||
Literal(literal) => build_exp_literal(env, literal),
|
Literal(literal) => build_exp_literal(env, literal),
|
||||||
RunLowLevel(op, symbols) => run_low_level(env, scope, parent, layout, *op, symbols),
|
RunLowLevel(op, symbols) => run_low_level(env, scope, parent, layout, *op, symbols),
|
||||||
|
|
||||||
ForeignCall(foreign_symbol, symbols) => {
|
ForeignCall {
|
||||||
let function = get_foreign_symbol(env, foreign_symbol.clone());
|
foreign_symbol,
|
||||||
|
arguments,
|
||||||
|
ret_layout,
|
||||||
|
} => {
|
||||||
|
let mut arg_vals: Vec<BasicValueEnum> =
|
||||||
|
Vec::with_capacity_in(arguments.len(), env.arena);
|
||||||
|
|
||||||
let mut arg_vals: Vec<BasicValueEnum> = Vec::with_capacity_in(symbols.len(), env.arena);
|
let mut arg_types = Vec::with_capacity_in(arguments.len(), env.arena);
|
||||||
|
|
||||||
for arg in symbols.iter() {
|
for arg in arguments.iter() {
|
||||||
arg_vals.push(load_symbol(env, scope, arg));
|
let (value, layout) = load_symbol_and_layout(env, scope, arg);
|
||||||
|
arg_vals.push(value);
|
||||||
|
let arg_type =
|
||||||
|
basic_type_from_layout(env.arena, env.context, layout, env.ptr_bytes);
|
||||||
|
arg_types.push(arg_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let ret_type =
|
||||||
|
basic_type_from_layout(env.arena, env.context, ret_layout, env.ptr_bytes);
|
||||||
|
let function_type = get_fn_type(&ret_type, &arg_types);
|
||||||
|
let function = get_foreign_symbol(env, foreign_symbol.clone(), function_type);
|
||||||
|
|
||||||
let call = env.builder.build_call(function, arg_vals.as_slice(), "tmp");
|
let call = env.builder.build_call(function, arg_vals.as_slice(), "tmp");
|
||||||
|
|
||||||
// this is a foreign function, use c calling convention
|
// this is a foreign function, use c calling convention
|
||||||
|
@ -3424,6 +3438,7 @@ fn cxa_rethrow_exception<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>) -> BasicValu
|
||||||
fn get_foreign_symbol<'a, 'ctx, 'env>(
|
fn get_foreign_symbol<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
foreign_symbol: roc_module::ident::ForeignSymbol,
|
foreign_symbol: roc_module::ident::ForeignSymbol,
|
||||||
|
function_type: FunctionType<'ctx>,
|
||||||
) -> FunctionValue<'ctx> {
|
) -> FunctionValue<'ctx> {
|
||||||
let module = env.module;
|
let module = env.module;
|
||||||
let context = env.context;
|
let context = env.context;
|
||||||
|
@ -3433,9 +3448,7 @@ fn get_foreign_symbol<'a, 'ctx, 'env>(
|
||||||
None => {
|
None => {
|
||||||
let foreign_function = module.add_function(
|
let foreign_function = module.add_function(
|
||||||
foreign_symbol.as_str(),
|
foreign_symbol.as_str(),
|
||||||
context
|
function_type,
|
||||||
.struct_type(&[], false)
|
|
||||||
.fn_type(&[context.i64_type().into()], false),
|
|
||||||
Some(Linkage::External),
|
Some(Linkage::External),
|
||||||
);
|
);
|
||||||
foreign_function.set_call_conventions(C_CALL_CONV);
|
foreign_function.set_call_conventions(C_CALL_CONV);
|
||||||
|
|
|
@ -2309,7 +2309,7 @@ fn fabricate_host_exposed_def<'a>(
|
||||||
match annotation.typ.shallow_dealias() {
|
match annotation.typ.shallow_dealias() {
|
||||||
Type::Function(args, _, _) => {
|
Type::Function(args, _, _) => {
|
||||||
for i in 0..args.len() {
|
for i in 0..args.len() {
|
||||||
let name = format!("closure_arg_{}", i);
|
let name = format!("closure_arg_{}_{}", ident, i);
|
||||||
|
|
||||||
let arg_symbol = {
|
let arg_symbol = {
|
||||||
let ident = name.clone().into();
|
let ident = name.clone().into();
|
||||||
|
@ -2343,7 +2343,7 @@ fn fabricate_host_exposed_def<'a>(
|
||||||
};
|
};
|
||||||
|
|
||||||
let effect_closure_symbol = {
|
let effect_closure_symbol = {
|
||||||
let name = "effect_closure";
|
let name = format!("effect_closure_{}", ident);
|
||||||
|
|
||||||
let ident = name.clone().into();
|
let ident = name.clone().into();
|
||||||
scope
|
scope
|
||||||
|
|
|
@ -374,13 +374,13 @@ impl<'a> BorrowInfState<'a> {
|
||||||
self.own_args_using_bools(args, ps);
|
self.own_args_using_bools(args, ps);
|
||||||
}
|
}
|
||||||
|
|
||||||
ForeignCall(_, args) => {
|
ForeignCall { arguments, .. } => {
|
||||||
// very unsure what demand ForeignCall should place upon its arguments
|
// very unsure what demand ForeignCall should place upon its arguments
|
||||||
self.own_var(z);
|
self.own_var(z);
|
||||||
|
|
||||||
let ps = foreign_borrow_signature(self.arena, args.len());
|
let ps = foreign_borrow_signature(self.arena, arguments.len());
|
||||||
|
|
||||||
self.own_args_using_bools(args, ps);
|
self.own_args_using_bools(arguments, ps);
|
||||||
}
|
}
|
||||||
|
|
||||||
Literal(_) | FunctionPointer(_, _) | RuntimeErrorFunction(_) => {}
|
Literal(_) | FunctionPointer(_, _) | RuntimeErrorFunction(_) => {}
|
||||||
|
|
|
@ -125,8 +125,8 @@ pub fn occuring_variables_expr(expr: &Expr<'_>, result: &mut MutSet<Symbol>) {
|
||||||
RunLowLevel(_, args) => {
|
RunLowLevel(_, args) => {
|
||||||
result.extend(args.iter());
|
result.extend(args.iter());
|
||||||
}
|
}
|
||||||
ForeignCall(_, args) => {
|
ForeignCall { arguments, .. } => {
|
||||||
result.extend(args.iter());
|
result.extend(arguments.iter());
|
||||||
}
|
}
|
||||||
|
|
||||||
EmptyArray | RuntimeErrorFunction(_) | Literal(_) => {}
|
EmptyArray | RuntimeErrorFunction(_) | Literal(_) => {}
|
||||||
|
@ -466,9 +466,9 @@ impl<'a> Context<'a> {
|
||||||
self.arena.alloc(Stmt::Let(z, v, l, b))
|
self.arena.alloc(Stmt::Let(z, v, l, b))
|
||||||
}
|
}
|
||||||
|
|
||||||
ForeignCall(_, args) => {
|
ForeignCall { arguments, .. } => {
|
||||||
let ps = crate::borrow::foreign_borrow_signature(self.arena, args.len());
|
let ps = crate::borrow::foreign_borrow_signature(self.arena, arguments.len());
|
||||||
let b = self.add_dec_after_lowlevel(args, ps, b, b_live_vars);
|
let b = self.add_dec_after_lowlevel(arguments, ps, b, b_live_vars);
|
||||||
|
|
||||||
self.arena.alloc(Stmt::Let(z, v, l, b))
|
self.arena.alloc(Stmt::Let(z, v, l, b))
|
||||||
}
|
}
|
||||||
|
|
|
@ -829,7 +829,11 @@ pub enum Expr<'a> {
|
||||||
args: &'a [Symbol],
|
args: &'a [Symbol],
|
||||||
},
|
},
|
||||||
RunLowLevel(LowLevel, &'a [Symbol]),
|
RunLowLevel(LowLevel, &'a [Symbol]),
|
||||||
ForeignCall(ForeignSymbol, &'a [Symbol]),
|
ForeignCall {
|
||||||
|
foreign_symbol: ForeignSymbol,
|
||||||
|
arguments: &'a [Symbol],
|
||||||
|
ret_layout: Layout<'a>,
|
||||||
|
},
|
||||||
|
|
||||||
Tag {
|
Tag {
|
||||||
tag_layout: Layout<'a>,
|
tag_layout: Layout<'a>,
|
||||||
|
@ -944,11 +948,15 @@ impl<'a> Expr<'a> {
|
||||||
.text(format!("lowlevel {:?} ", lowlevel))
|
.text(format!("lowlevel {:?} ", lowlevel))
|
||||||
.append(alloc.intersperse(it, " "))
|
.append(alloc.intersperse(it, " "))
|
||||||
}
|
}
|
||||||
ForeignCall(symbol, args) => {
|
ForeignCall {
|
||||||
let it = args.iter().map(|s| symbol_to_doc(alloc, *s));
|
foreign_symbol,
|
||||||
|
arguments,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
let it = arguments.iter().map(|s| symbol_to_doc(alloc, *s));
|
||||||
|
|
||||||
alloc
|
alloc
|
||||||
.text(format!("foreign {:?} ", symbol.as_str()))
|
.text(format!("foreign {:?} ", foreign_symbol.as_str()))
|
||||||
.append(alloc.intersperse(it, " "))
|
.append(alloc.intersperse(it, " "))
|
||||||
}
|
}
|
||||||
Tag {
|
Tag {
|
||||||
|
@ -3191,7 +3199,11 @@ pub fn with_hole<'a>(
|
||||||
|
|
||||||
let result = Stmt::Let(
|
let result = Stmt::Let(
|
||||||
assigned,
|
assigned,
|
||||||
Expr::ForeignCall(foreign_symbol.clone(), arg_symbols),
|
Expr::ForeignCall {
|
||||||
|
foreign_symbol: foreign_symbol.clone(),
|
||||||
|
arguments: arg_symbols,
|
||||||
|
ret_layout: layout.clone(),
|
||||||
|
},
|
||||||
layout,
|
layout,
|
||||||
hole,
|
hole,
|
||||||
);
|
);
|
||||||
|
@ -4035,10 +4047,14 @@ fn substitute_in_expr<'a>(
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ForeignCall(symbol, args) => {
|
ForeignCall {
|
||||||
|
foreign_symbol,
|
||||||
|
arguments,
|
||||||
|
ret_layout,
|
||||||
|
} => {
|
||||||
let mut did_change = false;
|
let mut did_change = false;
|
||||||
let new_args = Vec::from_iter_in(
|
let new_args = Vec::from_iter_in(
|
||||||
args.iter().map(|s| match substitute(subs, *s) {
|
arguments.iter().map(|s| match substitute(subs, *s) {
|
||||||
None => *s,
|
None => *s,
|
||||||
Some(s) => {
|
Some(s) => {
|
||||||
did_change = true;
|
did_change = true;
|
||||||
|
@ -4051,7 +4067,11 @@ fn substitute_in_expr<'a>(
|
||||||
if did_change {
|
if did_change {
|
||||||
let args = new_args.into_bump_slice();
|
let args = new_args.into_bump_slice();
|
||||||
|
|
||||||
Some(ForeignCall(symbol.clone(), args))
|
Some(ForeignCall {
|
||||||
|
foreign_symbol: foreign_symbol.clone(),
|
||||||
|
arguments: args,
|
||||||
|
ret_layout: ret_layout.clone(),
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,4 +3,4 @@ platform folkertdev/foo
|
||||||
requires [ main ]
|
requires [ main ]
|
||||||
imports []
|
imports []
|
||||||
effects
|
effects
|
||||||
{ putChar Int -> Effect {} }
|
{ putChar Int -> Effect {}, putLine Str -> Effect {} }
|
||||||
|
|
|
@ -2,7 +2,8 @@ app Main provides [ main ] imports [ Effect ]
|
||||||
|
|
||||||
main : Effect.Effect {} as Fx
|
main : Effect.Effect {} as Fx
|
||||||
main =
|
main =
|
||||||
e = Effect.putChar 69
|
|
||||||
d = Effect.putChar 68
|
|
||||||
|
|
||||||
e |> Effect.after \{} -> d
|
Effect.putLine "Hello"
|
||||||
|
|> Effect.after \{} -> Effect.putChar 87
|
||||||
|
# |> Effect.after \{} -> Effect.putLine "orld"
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use roc_std::alloca;
|
use roc_std::alloca;
|
||||||
use roc_std::RocCallResult;
|
use roc_std::RocCallResult;
|
||||||
|
use roc_std::RocStr;
|
||||||
use std::alloc::Layout;
|
use std::alloc::Layout;
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
|
|
||||||
|
@ -25,6 +26,15 @@ pub fn roc_fx_putChar(foo: i64) -> () {
|
||||||
()
|
()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub fn roc_fx_putLine(line: RocStr) -> () {
|
||||||
|
let bytes = line.as_slice();
|
||||||
|
let string = unsafe { std::str::from_utf8_unchecked(bytes) };
|
||||||
|
println!("{}", string);
|
||||||
|
|
||||||
|
()
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn call_the_closure(function_pointer: *const u8, closure_data_ptr: *const u8) -> i64 {
|
unsafe fn call_the_closure(function_pointer: *const u8, closure_data_ptr: *const u8) -> i64 {
|
||||||
let size = size_Fx() as usize;
|
let size = size_Fx() as usize;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue