mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-03 16:44:33 +00:00
call changes in mono
This commit is contained in:
parent
6bc0cf33a5
commit
0893aa7369
5 changed files with 346 additions and 295 deletions
|
@ -334,14 +334,21 @@ impl<'a> BorrowInfState<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FunctionCall {
|
Call(crate::ir::Call {
|
||||||
call_type,
|
call_type,
|
||||||
args,
|
arguments,
|
||||||
arg_layouts,
|
}) => {
|
||||||
..
|
use crate::ir::CallType::*;
|
||||||
|
|
||||||
|
match call_type {
|
||||||
|
ByName {
|
||||||
|
name, arg_layouts, ..
|
||||||
|
}
|
||||||
|
| ByPointer {
|
||||||
|
name, arg_layouts, ..
|
||||||
} => {
|
} => {
|
||||||
// get the borrow signature of the applied function
|
// get the borrow signature of the applied function
|
||||||
let ps = match self.param_map.get_symbol(call_type.get_inner()) {
|
let ps = match self.param_map.get_symbol(*name) {
|
||||||
Some(slice) => slice,
|
Some(slice) => slice,
|
||||||
None => Vec::from_iter_in(
|
None => Vec::from_iter_in(
|
||||||
arg_layouts.iter().cloned().map(|layout| Param {
|
arg_layouts.iter().cloned().map(|layout| Param {
|
||||||
|
@ -358,19 +365,19 @@ impl<'a> BorrowInfState<'a> {
|
||||||
self.own_var(z);
|
self.own_var(z);
|
||||||
|
|
||||||
// if the function exects an owned argument (ps), the argument must be owned (args)
|
// if the function exects an owned argument (ps), the argument must be owned (args)
|
||||||
self.own_args_using_params(args, ps);
|
self.own_args_using_params(arguments, ps);
|
||||||
}
|
}
|
||||||
|
|
||||||
RunLowLevel(op, args) => {
|
LowLevel { op } => {
|
||||||
// very unsure what demand RunLowLevel should place upon its arguments
|
// very unsure what demand RunLowLevel should place upon its arguments
|
||||||
self.own_var(z);
|
self.own_var(z);
|
||||||
|
|
||||||
let ps = lowlevel_borrow_signature(self.arena, *op);
|
let ps = lowlevel_borrow_signature(self.arena, *op);
|
||||||
|
|
||||||
self.own_args_using_bools(args, ps);
|
self.own_args_using_bools(arguments, ps);
|
||||||
}
|
}
|
||||||
|
|
||||||
ForeignCall { arguments, .. } => {
|
Foreign { .. } => {
|
||||||
// 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);
|
||||||
|
|
||||||
|
@ -378,30 +385,41 @@ impl<'a> BorrowInfState<'a> {
|
||||||
|
|
||||||
self.own_args_using_bools(arguments, ps);
|
self.own_args_using_bools(arguments, ps);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Literal(_) | FunctionPointer(_, _) | RuntimeErrorFunction(_) => {}
|
Literal(_) | FunctionPointer(_, _) | RuntimeErrorFunction(_) => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn preserve_tail_call(&mut self, x: Symbol, v: &Expr<'a>, b: &Stmt<'a>) {
|
fn preserve_tail_call(&mut self, x: Symbol, v: &Expr<'a>, b: &Stmt<'a>) {
|
||||||
if let (
|
match (v, b) {
|
||||||
Expr::FunctionCall {
|
(
|
||||||
call_type,
|
Expr::Call(crate::ir::Call {
|
||||||
args: ys,
|
call_type: crate::ir::CallType::ByName { name: g, .. },
|
||||||
|
arguments: ys,
|
||||||
..
|
..
|
||||||
},
|
}),
|
||||||
Stmt::Ret(z),
|
Stmt::Ret(z),
|
||||||
) = (v, b)
|
)
|
||||||
{
|
| (
|
||||||
let g = call_type.get_inner();
|
Expr::Call(crate::ir::Call {
|
||||||
if self.current_proc == g && x == *z {
|
call_type: crate::ir::CallType::ByPointer { name: g, .. },
|
||||||
|
arguments: ys,
|
||||||
|
..
|
||||||
|
}),
|
||||||
|
Stmt::Ret(z),
|
||||||
|
) => {
|
||||||
|
if self.current_proc == *g && x == *z {
|
||||||
// anonymous functions (for which the ps may not be known)
|
// anonymous functions (for which the ps may not be known)
|
||||||
// can never be tail-recursive, so this is fine
|
// can never be tail-recursive, so this is fine
|
||||||
if let Some(ps) = self.param_map.get_symbol(g) {
|
if let Some(ps) = self.param_map.get_symbol(*g) {
|
||||||
self.own_params_using_args(ys, ps)
|
self.own_params_using_args(ys, ps)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_param_set(&mut self, ps: &[Param<'a>]) {
|
fn update_param_set(&mut self, ps: &[Param<'a>]) {
|
||||||
|
|
|
@ -1277,7 +1277,10 @@ fn compile_test<'a>(
|
||||||
ret_layout,
|
ret_layout,
|
||||||
);
|
);
|
||||||
|
|
||||||
let test = Expr::RunLowLevel(LowLevel::Eq, arena.alloc([lhs, rhs]));
|
let test = Expr::Call(crate::ir::Call {
|
||||||
|
call_type: crate::ir::CallType::LowLevel { op: LowLevel::Eq },
|
||||||
|
arguments: arena.alloc([lhs, rhs]),
|
||||||
|
});
|
||||||
|
|
||||||
// write to the test symbol
|
// write to the test symbol
|
||||||
cond = Stmt::Let(
|
cond = Stmt::Let(
|
||||||
|
|
|
@ -88,10 +88,10 @@ pub fn occuring_variables_expr(expr: &Expr<'_>, result: &mut MutSet<Symbol>) {
|
||||||
result.insert(*symbol);
|
result.insert(*symbol);
|
||||||
}
|
}
|
||||||
|
|
||||||
FunctionCall { args, .. } => {
|
Call(crate::ir::Call { arguments, .. }) => {
|
||||||
// NOTE thouth the function name does occur, it is a static constant in the program
|
// NOTE thouth the function name does occur, it is a static constant in the program
|
||||||
// for liveness, it should not be included here.
|
// for liveness, it should not be included here.
|
||||||
result.extend(args.iter().copied());
|
result.extend(arguments.iter().copied());
|
||||||
}
|
}
|
||||||
|
|
||||||
Tag { arguments, .. }
|
Tag { arguments, .. }
|
||||||
|
@ -110,12 +110,6 @@ pub fn occuring_variables_expr(expr: &Expr<'_>, result: &mut MutSet<Symbol>) {
|
||||||
Reset(x) => {
|
Reset(x) => {
|
||||||
result.insert(*x);
|
result.insert(*x);
|
||||||
}
|
}
|
||||||
RunLowLevel(_, args) => {
|
|
||||||
result.extend(args.iter());
|
|
||||||
}
|
|
||||||
ForeignCall { arguments, .. } => {
|
|
||||||
result.extend(arguments.iter());
|
|
||||||
}
|
|
||||||
|
|
||||||
EmptyArray | RuntimeErrorFunction(_) | Literal(_) => {}
|
EmptyArray | RuntimeErrorFunction(_) | Literal(_) => {}
|
||||||
}
|
}
|
||||||
|
@ -447,28 +441,36 @@ impl<'a> Context<'a> {
|
||||||
self.arena.alloc(Stmt::Let(z, v, l, b))
|
self.arena.alloc(Stmt::Let(z, v, l, b))
|
||||||
}
|
}
|
||||||
|
|
||||||
RunLowLevel(op, args) => {
|
Call(crate::ir::Call {
|
||||||
let ps = crate::borrow::lowlevel_borrow_signature(self.arena, op);
|
ref call_type,
|
||||||
let b = self.add_dec_after_lowlevel(args, ps, b, b_live_vars);
|
arguments,
|
||||||
|
}) => {
|
||||||
|
use crate::ir::CallType::*;
|
||||||
|
|
||||||
self.arena.alloc(Stmt::Let(z, v, l, b))
|
match &call_type {
|
||||||
}
|
LowLevel { op } => {
|
||||||
|
let ps = crate::borrow::lowlevel_borrow_signature(self.arena, *op);
|
||||||
ForeignCall { arguments, .. } => {
|
|
||||||
let ps = crate::borrow::foreign_borrow_signature(self.arena, arguments.len());
|
|
||||||
let b = self.add_dec_after_lowlevel(arguments, 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))
|
||||||
}
|
}
|
||||||
|
|
||||||
FunctionCall {
|
Foreign { .. } => {
|
||||||
args: ys,
|
let ps =
|
||||||
arg_layouts,
|
crate::borrow::foreign_borrow_signature(self.arena, arguments.len());
|
||||||
call_type,
|
let b = self.add_dec_after_lowlevel(arguments, ps, b, b_live_vars);
|
||||||
..
|
|
||||||
|
&*self.arena.alloc(Stmt::Let(z, v, l, b))
|
||||||
|
}
|
||||||
|
|
||||||
|
ByName {
|
||||||
|
name, arg_layouts, ..
|
||||||
|
}
|
||||||
|
| ByPointer {
|
||||||
|
name, arg_layouts, ..
|
||||||
} => {
|
} => {
|
||||||
// get the borrow signature
|
// get the borrow signature
|
||||||
let ps = match self.param_map.get_symbol(call_type.get_inner()) {
|
let ps = match self.param_map.get_symbol(*name) {
|
||||||
Some(slice) => slice,
|
Some(slice) => slice,
|
||||||
None => Vec::from_iter_in(
|
None => Vec::from_iter_in(
|
||||||
arg_layouts.iter().cloned().map(|layout| Param {
|
arg_layouts.iter().cloned().map(|layout| Param {
|
||||||
|
@ -481,10 +483,12 @@ impl<'a> Context<'a> {
|
||||||
.into_bump_slice(),
|
.into_bump_slice(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let b = self.add_dec_after_application(ys, ps, b, b_live_vars);
|
let b = self.add_dec_after_application(arguments, ps, b, b_live_vars);
|
||||||
let b = self.arena.alloc(Stmt::Let(z, v, l, b));
|
let b = self.arena.alloc(Stmt::Let(z, v, l, b));
|
||||||
|
|
||||||
self.add_inc_before(ys, ps, b, b_live_vars)
|
self.add_inc_before(arguments, ps, b, b_live_vars)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EmptyArray
|
EmptyArray
|
||||||
|
@ -510,7 +514,7 @@ impl<'a> Context<'a> {
|
||||||
// is this value a constant?
|
// is this value a constant?
|
||||||
// TODO do function pointers also fall into this category?
|
// TODO do function pointers also fall into this category?
|
||||||
let persistent = match expr {
|
let persistent = match expr {
|
||||||
Expr::FunctionCall { args, .. } => args.is_empty(),
|
Expr::Call(crate::ir::Call { arguments, .. }) => arguments.is_empty(),
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -785,20 +785,6 @@ pub enum Literal<'a> {
|
||||||
/// compile to bytes, e.g. [ Blue, Black, Red, Green, White ]
|
/// compile to bytes, e.g. [ Blue, Black, Red, Green, White ]
|
||||||
Byte(u8),
|
Byte(u8),
|
||||||
}
|
}
|
||||||
#[derive(Clone, Debug, PartialEq, Copy)]
|
|
||||||
pub enum CallType {
|
|
||||||
ByName(Symbol),
|
|
||||||
ByPointer(Symbol),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CallType {
|
|
||||||
pub fn get_inner(&self) -> Symbol {
|
|
||||||
match self {
|
|
||||||
CallType::ByName(s) => *s,
|
|
||||||
CallType::ByPointer(s) => *s,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
pub enum Wrapped {
|
pub enum Wrapped {
|
||||||
|
@ -838,25 +824,98 @@ impl Wrapped {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
pub struct Call<'a> {
|
||||||
|
pub call_type: CallType<'a>,
|
||||||
|
pub arguments: &'a [Symbol],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Call<'a> {
|
||||||
|
pub fn to_doc<'b, D, A>(&'b self, alloc: &'b D) -> DocBuilder<'b, D, A>
|
||||||
|
where
|
||||||
|
D: DocAllocator<'b, A>,
|
||||||
|
D::Doc: Clone,
|
||||||
|
A: Clone,
|
||||||
|
{
|
||||||
|
use CallType::*;
|
||||||
|
|
||||||
|
let arguments = self.arguments;
|
||||||
|
|
||||||
|
match self.call_type {
|
||||||
|
CallType::ByName { name, .. } => {
|
||||||
|
let it = std::iter::once(name)
|
||||||
|
.chain(arguments.iter().copied())
|
||||||
|
.map(|s| symbol_to_doc(alloc, s));
|
||||||
|
|
||||||
|
alloc.text("CallByName ").append(alloc.intersperse(it, " "))
|
||||||
|
}
|
||||||
|
CallType::ByPointer { name, .. } => {
|
||||||
|
let it = std::iter::once(name)
|
||||||
|
.chain(arguments.iter().copied())
|
||||||
|
.map(|s| symbol_to_doc(alloc, s));
|
||||||
|
|
||||||
|
alloc
|
||||||
|
.text("CallByPointer ")
|
||||||
|
.append(alloc.intersperse(it, " "))
|
||||||
|
}
|
||||||
|
LowLevel { op: lowlevel } => {
|
||||||
|
let it = arguments.iter().map(|s| symbol_to_doc(alloc, *s));
|
||||||
|
|
||||||
|
alloc
|
||||||
|
.text(format!("lowlevel {:?} ", lowlevel))
|
||||||
|
.append(alloc.intersperse(it, " "))
|
||||||
|
}
|
||||||
|
Foreign {
|
||||||
|
foreign_symbol: ref foreign_symbol,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
let it = arguments.iter().map(|s| symbol_to_doc(alloc, *s));
|
||||||
|
|
||||||
|
alloc
|
||||||
|
.text(format!("foreign {:?} ", foreign_symbol.as_str()))
|
||||||
|
.append(alloc.intersperse(it, " "))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
pub enum CallType<'a> {
|
||||||
|
ByName {
|
||||||
|
name: Symbol,
|
||||||
|
|
||||||
|
full_layout: Layout<'a>,
|
||||||
|
ret_layout: Layout<'a>,
|
||||||
|
arg_layouts: &'a [Layout<'a>],
|
||||||
|
},
|
||||||
|
ByPointer {
|
||||||
|
name: Symbol,
|
||||||
|
|
||||||
|
full_layout: Layout<'a>,
|
||||||
|
ret_layout: Layout<'a>,
|
||||||
|
arg_layouts: &'a [Layout<'a>],
|
||||||
|
},
|
||||||
|
Foreign {
|
||||||
|
foreign_symbol: ForeignSymbol,
|
||||||
|
ret_layout: Layout<'a>,
|
||||||
|
},
|
||||||
|
LowLevel {
|
||||||
|
op: LowLevel,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// x = f a b c; S
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// invoke x = f a b c in S else Unreachable
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub enum Expr<'a> {
|
pub enum Expr<'a> {
|
||||||
Literal(Literal<'a>),
|
Literal(Literal<'a>),
|
||||||
|
|
||||||
// Functions
|
// Functions
|
||||||
FunctionPointer(Symbol, Layout<'a>),
|
FunctionPointer(Symbol, Layout<'a>),
|
||||||
FunctionCall {
|
Call(Call<'a>),
|
||||||
call_type: CallType,
|
|
||||||
full_layout: Layout<'a>,
|
|
||||||
ret_layout: Layout<'a>,
|
|
||||||
arg_layouts: &'a [Layout<'a>],
|
|
||||||
args: &'a [Symbol],
|
|
||||||
},
|
|
||||||
RunLowLevel(LowLevel, &'a [Symbol]),
|
|
||||||
ForeignCall {
|
|
||||||
foreign_symbol: ForeignSymbol,
|
|
||||||
arguments: &'a [Symbol],
|
|
||||||
ret_layout: Layout<'a>,
|
|
||||||
},
|
|
||||||
|
|
||||||
Tag {
|
Tag {
|
||||||
tag_layout: Layout<'a>,
|
tag_layout: Layout<'a>,
|
||||||
|
@ -957,44 +1016,8 @@ impl<'a> Expr<'a> {
|
||||||
.text("FunctionPointer ")
|
.text("FunctionPointer ")
|
||||||
.append(symbol_to_doc(alloc, *symbol)),
|
.append(symbol_to_doc(alloc, *symbol)),
|
||||||
|
|
||||||
FunctionCall {
|
Call(call) => call.to_doc(alloc),
|
||||||
call_type, args, ..
|
|
||||||
} => match call_type {
|
|
||||||
CallType::ByName(name) => {
|
|
||||||
let it = std::iter::once(name)
|
|
||||||
.chain(args.iter())
|
|
||||||
.map(|s| symbol_to_doc(alloc, *s));
|
|
||||||
|
|
||||||
alloc.text("CallByName ").append(alloc.intersperse(it, " "))
|
|
||||||
}
|
|
||||||
CallType::ByPointer(name) => {
|
|
||||||
let it = std::iter::once(name)
|
|
||||||
.chain(args.iter())
|
|
||||||
.map(|s| symbol_to_doc(alloc, *s));
|
|
||||||
|
|
||||||
alloc
|
|
||||||
.text("CallByPointer ")
|
|
||||||
.append(alloc.intersperse(it, " "))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
RunLowLevel(lowlevel, args) => {
|
|
||||||
let it = args.iter().map(|s| symbol_to_doc(alloc, *s));
|
|
||||||
|
|
||||||
alloc
|
|
||||||
.text(format!("lowlevel {:?} ", lowlevel))
|
|
||||||
.append(alloc.intersperse(it, " "))
|
|
||||||
}
|
|
||||||
ForeignCall {
|
|
||||||
foreign_symbol,
|
|
||||||
arguments,
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
let it = arguments.iter().map(|s| symbol_to_doc(alloc, *s));
|
|
||||||
|
|
||||||
alloc
|
|
||||||
.text(format!("foreign {:?} ", foreign_symbol.as_str()))
|
|
||||||
.append(alloc.intersperse(it, " "))
|
|
||||||
}
|
|
||||||
Tag {
|
Tag {
|
||||||
tag_name,
|
tag_name,
|
||||||
arguments,
|
arguments,
|
||||||
|
@ -3509,13 +3532,15 @@ pub fn with_hole<'a>(
|
||||||
// build the call
|
// build the call
|
||||||
result = Stmt::Let(
|
result = Stmt::Let(
|
||||||
assigned,
|
assigned,
|
||||||
Expr::FunctionCall {
|
Expr::Call(self::Call {
|
||||||
call_type: CallType::ByPointer(closure_function_symbol),
|
call_type: CallType::ByPointer {
|
||||||
|
name: closure_function_symbol,
|
||||||
full_layout: function_ptr_layout.clone(),
|
full_layout: function_ptr_layout.clone(),
|
||||||
ret_layout: ret_layout.clone(),
|
ret_layout: ret_layout.clone(),
|
||||||
args: arg_symbols,
|
|
||||||
arg_layouts,
|
arg_layouts,
|
||||||
},
|
},
|
||||||
|
arguments: arg_symbols,
|
||||||
|
}),
|
||||||
ret_layout,
|
ret_layout,
|
||||||
arena.alloc(hole),
|
arena.alloc(hole),
|
||||||
);
|
);
|
||||||
|
@ -3556,13 +3581,15 @@ pub fn with_hole<'a>(
|
||||||
} else {
|
} else {
|
||||||
result = Stmt::Let(
|
result = Stmt::Let(
|
||||||
assigned,
|
assigned,
|
||||||
Expr::FunctionCall {
|
Expr::Call(self::Call {
|
||||||
call_type: CallType::ByPointer(function_symbol),
|
call_type: CallType::ByPointer {
|
||||||
|
name: function_symbol,
|
||||||
full_layout,
|
full_layout,
|
||||||
ret_layout: ret_layout.clone(),
|
ret_layout: ret_layout.clone(),
|
||||||
args: arg_symbols,
|
|
||||||
arg_layouts,
|
arg_layouts,
|
||||||
},
|
},
|
||||||
|
arguments: arg_symbols,
|
||||||
|
}),
|
||||||
ret_layout,
|
ret_layout,
|
||||||
arena.alloc(hole),
|
arena.alloc(hole),
|
||||||
);
|
);
|
||||||
|
@ -3573,13 +3600,15 @@ pub fn with_hole<'a>(
|
||||||
|
|
||||||
result = Stmt::Let(
|
result = Stmt::Let(
|
||||||
assigned,
|
assigned,
|
||||||
Expr::FunctionCall {
|
Expr::Call(self::Call {
|
||||||
call_type: CallType::ByPointer(function_symbol),
|
call_type: CallType::ByPointer {
|
||||||
|
name: function_symbol,
|
||||||
full_layout,
|
full_layout,
|
||||||
ret_layout: ret_layout.clone(),
|
ret_layout: ret_layout.clone(),
|
||||||
args: arg_symbols,
|
|
||||||
arg_layouts,
|
arg_layouts,
|
||||||
},
|
},
|
||||||
|
arguments: arg_symbols,
|
||||||
|
}),
|
||||||
ret_layout,
|
ret_layout,
|
||||||
arena.alloc(hole),
|
arena.alloc(hole),
|
||||||
);
|
);
|
||||||
|
@ -3620,11 +3649,13 @@ pub fn with_hole<'a>(
|
||||||
|
|
||||||
let result = Stmt::Let(
|
let result = Stmt::Let(
|
||||||
assigned,
|
assigned,
|
||||||
Expr::ForeignCall {
|
Expr::Call(self::Call {
|
||||||
|
call_type: CallType::Foreign {
|
||||||
foreign_symbol,
|
foreign_symbol,
|
||||||
arguments: arg_symbols,
|
|
||||||
ret_layout: layout.clone(),
|
ret_layout: layout.clone(),
|
||||||
},
|
},
|
||||||
|
arguments: arg_symbols,
|
||||||
|
}),
|
||||||
layout,
|
layout,
|
||||||
hole,
|
hole,
|
||||||
);
|
);
|
||||||
|
@ -3666,7 +3697,15 @@ pub fn with_hole<'a>(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let result = Stmt::Let(assigned, Expr::RunLowLevel(op, arg_symbols), layout, hole);
|
let result = Stmt::Let(
|
||||||
|
assigned,
|
||||||
|
Expr::Call(self::Call {
|
||||||
|
call_type: CallType::LowLevel { op },
|
||||||
|
arguments: arg_symbols,
|
||||||
|
}),
|
||||||
|
layout,
|
||||||
|
hole,
|
||||||
|
);
|
||||||
|
|
||||||
let iter = args
|
let iter = args
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
@ -4455,72 +4494,37 @@ fn substitute_in_expr<'a>(
|
||||||
match expr {
|
match expr {
|
||||||
Literal(_) | FunctionPointer(_, _) | EmptyArray | RuntimeErrorFunction(_) => None,
|
Literal(_) | FunctionPointer(_, _) | EmptyArray | RuntimeErrorFunction(_) => None,
|
||||||
|
|
||||||
FunctionCall {
|
Call(self::Call {
|
||||||
call_type,
|
call_type,
|
||||||
args,
|
arguments,
|
||||||
|
}) => {
|
||||||
|
let opt_call_type = match call_type {
|
||||||
|
CallType::ByName {
|
||||||
|
name,
|
||||||
arg_layouts,
|
arg_layouts,
|
||||||
ret_layout,
|
ret_layout,
|
||||||
full_layout,
|
full_layout,
|
||||||
} => {
|
} => substitute(subs, *name).map(|new| CallType::ByName {
|
||||||
let opt_call_type = match call_type {
|
name: new,
|
||||||
CallType::ByName(s) => substitute(subs, *s).map(CallType::ByName),
|
arg_layouts,
|
||||||
CallType::ByPointer(s) => substitute(subs, *s).map(CallType::ByPointer),
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut did_change = false;
|
|
||||||
let new_args = Vec::from_iter_in(
|
|
||||||
args.iter().map(|s| match substitute(subs, *s) {
|
|
||||||
None => *s,
|
|
||||||
Some(s) => {
|
|
||||||
did_change = true;
|
|
||||||
s
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
arena,
|
|
||||||
);
|
|
||||||
|
|
||||||
if did_change || opt_call_type.is_some() {
|
|
||||||
let call_type = opt_call_type.unwrap_or(*call_type);
|
|
||||||
|
|
||||||
let args = new_args.into_bump_slice();
|
|
||||||
|
|
||||||
Some(FunctionCall {
|
|
||||||
call_type,
|
|
||||||
args,
|
|
||||||
arg_layouts: *arg_layouts,
|
|
||||||
ret_layout: ret_layout.clone(),
|
ret_layout: ret_layout.clone(),
|
||||||
full_layout: full_layout.clone(),
|
full_layout: full_layout.clone(),
|
||||||
})
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RunLowLevel(op, args) => {
|
|
||||||
let mut did_change = false;
|
|
||||||
let new_args = Vec::from_iter_in(
|
|
||||||
args.iter().map(|s| match substitute(subs, *s) {
|
|
||||||
None => *s,
|
|
||||||
Some(s) => {
|
|
||||||
did_change = true;
|
|
||||||
s
|
|
||||||
}
|
|
||||||
}),
|
}),
|
||||||
arena,
|
CallType::ByPointer {
|
||||||
);
|
name,
|
||||||
|
arg_layouts,
|
||||||
if did_change {
|
|
||||||
let args = new_args.into_bump_slice();
|
|
||||||
|
|
||||||
Some(RunLowLevel(*op, args))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ForeignCall {
|
|
||||||
foreign_symbol,
|
|
||||||
arguments,
|
|
||||||
ret_layout,
|
ret_layout,
|
||||||
} => {
|
full_layout,
|
||||||
|
} => substitute(subs, *name).map(|new| CallType::ByPointer {
|
||||||
|
name: new,
|
||||||
|
arg_layouts,
|
||||||
|
ret_layout: ret_layout.clone(),
|
||||||
|
full_layout: full_layout.clone(),
|
||||||
|
}),
|
||||||
|
CallType::Foreign { .. } => None,
|
||||||
|
CallType::LowLevel { .. } => None,
|
||||||
|
};
|
||||||
|
|
||||||
let mut did_change = false;
|
let mut did_change = false;
|
||||||
let new_args = Vec::from_iter_in(
|
let new_args = Vec::from_iter_in(
|
||||||
arguments.iter().map(|s| match substitute(subs, *s) {
|
arguments.iter().map(|s| match substitute(subs, *s) {
|
||||||
|
@ -4533,14 +4537,15 @@ fn substitute_in_expr<'a>(
|
||||||
arena,
|
arena,
|
||||||
);
|
);
|
||||||
|
|
||||||
if did_change {
|
if did_change || opt_call_type.is_some() {
|
||||||
let args = new_args.into_bump_slice();
|
let call_type = opt_call_type.unwrap_or_else(|| call_type.clone());
|
||||||
|
|
||||||
Some(ForeignCall {
|
let arguments = new_args.into_bump_slice();
|
||||||
foreign_symbol: foreign_symbol.clone(),
|
|
||||||
arguments: args,
|
Some(Expr::Call(self::Call {
|
||||||
ret_layout: ret_layout.clone(),
|
call_type,
|
||||||
})
|
arguments,
|
||||||
|
}))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -5211,13 +5216,15 @@ fn call_by_name<'a>(
|
||||||
"see call_by_name for background (scroll down a bit)"
|
"see call_by_name for background (scroll down a bit)"
|
||||||
);
|
);
|
||||||
|
|
||||||
let call = Expr::FunctionCall {
|
let call = Expr::Call(self::Call {
|
||||||
call_type: CallType::ByName(proc_name),
|
call_type: CallType::ByName {
|
||||||
|
name: proc_name,
|
||||||
ret_layout: ret_layout.clone(),
|
ret_layout: ret_layout.clone(),
|
||||||
full_layout: full_layout.clone(),
|
full_layout: full_layout.clone(),
|
||||||
arg_layouts,
|
arg_layouts,
|
||||||
args: field_symbols,
|
},
|
||||||
};
|
arguments: field_symbols,
|
||||||
|
});
|
||||||
|
|
||||||
let result = Stmt::Let(assigned, call, ret_layout.clone(), hole);
|
let result = Stmt::Let(assigned, call, ret_layout.clone(), hole);
|
||||||
|
|
||||||
|
@ -5259,13 +5266,16 @@ fn call_by_name<'a>(
|
||||||
field_symbols.len(),
|
field_symbols.len(),
|
||||||
"see call_by_name for background (scroll down a bit)"
|
"see call_by_name for background (scroll down a bit)"
|
||||||
);
|
);
|
||||||
let call = Expr::FunctionCall {
|
|
||||||
call_type: CallType::ByName(proc_name),
|
let call = Expr::Call(self::Call {
|
||||||
|
call_type: CallType::ByName {
|
||||||
|
name: proc_name,
|
||||||
ret_layout: ret_layout.clone(),
|
ret_layout: ret_layout.clone(),
|
||||||
full_layout: full_layout.clone(),
|
full_layout: full_layout.clone(),
|
||||||
arg_layouts,
|
arg_layouts,
|
||||||
args: field_symbols,
|
},
|
||||||
};
|
arguments: field_symbols,
|
||||||
|
});
|
||||||
|
|
||||||
let iter = loc_args.into_iter().rev().zip(field_symbols.iter().rev());
|
let iter = loc_args.into_iter().rev().zip(field_symbols.iter().rev());
|
||||||
|
|
||||||
|
@ -5319,13 +5329,19 @@ fn call_by_name<'a>(
|
||||||
// and we have to fix it here.
|
// and we have to fix it here.
|
||||||
match full_layout {
|
match full_layout {
|
||||||
Layout::Closure(_, closure_layout, _) => {
|
Layout::Closure(_, closure_layout, _) => {
|
||||||
let call = Expr::FunctionCall {
|
let call = Expr::Call(self::Call {
|
||||||
call_type: CallType::ByName(proc_name),
|
call_type: CallType::ByName {
|
||||||
ret_layout: function_layout.result.clone(),
|
name: proc_name,
|
||||||
full_layout: function_layout.full.clone(),
|
ret_layout: function_layout
|
||||||
|
.result
|
||||||
|
.clone(),
|
||||||
|
full_layout: function_layout
|
||||||
|
.full
|
||||||
|
.clone(),
|
||||||
arg_layouts: function_layout.arguments,
|
arg_layouts: function_layout.arguments,
|
||||||
args: field_symbols,
|
},
|
||||||
};
|
arguments: field_symbols,
|
||||||
|
});
|
||||||
|
|
||||||
// in the case of a closure specifically, we
|
// in the case of a closure specifically, we
|
||||||
// have to create a custom layout, to make sure
|
// have to create a custom layout, to make sure
|
||||||
|
@ -5346,13 +5362,19 @@ fn call_by_name<'a>(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let call = Expr::FunctionCall {
|
let call = Expr::Call(self::Call {
|
||||||
call_type: CallType::ByName(proc_name),
|
call_type: CallType::ByName {
|
||||||
ret_layout: function_layout.result.clone(),
|
name: proc_name,
|
||||||
full_layout: function_layout.full.clone(),
|
ret_layout: function_layout
|
||||||
|
.result
|
||||||
|
.clone(),
|
||||||
|
full_layout: function_layout
|
||||||
|
.full
|
||||||
|
.clone(),
|
||||||
arg_layouts: function_layout.arguments,
|
arg_layouts: function_layout.arguments,
|
||||||
args: field_symbols,
|
},
|
||||||
};
|
arguments: field_symbols,
|
||||||
|
});
|
||||||
|
|
||||||
Stmt::Let(
|
Stmt::Let(
|
||||||
assigned,
|
assigned,
|
||||||
|
@ -5368,13 +5390,15 @@ fn call_by_name<'a>(
|
||||||
field_symbols.len(),
|
field_symbols.len(),
|
||||||
"scroll up a bit for background"
|
"scroll up a bit for background"
|
||||||
);
|
);
|
||||||
let call = Expr::FunctionCall {
|
let call = Expr::Call(self::Call {
|
||||||
call_type: CallType::ByName(proc_name),
|
call_type: CallType::ByName {
|
||||||
|
name: proc_name,
|
||||||
ret_layout: function_layout.result.clone(),
|
ret_layout: function_layout.result.clone(),
|
||||||
full_layout: function_layout.full,
|
full_layout: function_layout.full.clone(),
|
||||||
arg_layouts: function_layout.arguments,
|
arg_layouts: function_layout.arguments,
|
||||||
args: field_symbols,
|
},
|
||||||
};
|
arguments: field_symbols,
|
||||||
|
});
|
||||||
|
|
||||||
let iter = loc_args
|
let iter = loc_args
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
@ -5420,13 +5444,15 @@ fn call_by_name<'a>(
|
||||||
"scroll up a bit for background"
|
"scroll up a bit for background"
|
||||||
);
|
);
|
||||||
|
|
||||||
let call = Expr::FunctionCall {
|
let call = Expr::Call(self::Call {
|
||||||
call_type: CallType::ByName(proc_name),
|
call_type: CallType::ByName {
|
||||||
|
name: proc_name,
|
||||||
ret_layout: ret_layout.clone(),
|
ret_layout: ret_layout.clone(),
|
||||||
full_layout: full_layout.clone(),
|
full_layout: full_layout.clone(),
|
||||||
arg_layouts,
|
arg_layouts,
|
||||||
args: field_symbols,
|
},
|
||||||
};
|
arguments: field_symbols,
|
||||||
|
});
|
||||||
|
|
||||||
let iter =
|
let iter =
|
||||||
loc_args.into_iter().rev().zip(field_symbols.iter().rev());
|
loc_args.into_iter().rev().zip(field_symbols.iter().rev());
|
||||||
|
|
|
@ -75,17 +75,17 @@ fn insert_jumps<'a>(
|
||||||
match stmt {
|
match stmt {
|
||||||
Let(
|
Let(
|
||||||
symbol,
|
symbol,
|
||||||
Expr::FunctionCall {
|
Expr::Call(crate::ir::Call {
|
||||||
call_type: CallType::ByName(fsym),
|
call_type: CallType::ByName { name: fsym, .. },
|
||||||
args,
|
arguments,
|
||||||
..
|
..
|
||||||
},
|
}),
|
||||||
_,
|
_,
|
||||||
Stmt::Ret(rsym),
|
Stmt::Ret(rsym),
|
||||||
) if needle == *fsym && symbol == rsym => {
|
) if needle == *fsym && symbol == rsym => {
|
||||||
// replace the call and return with a jump
|
// replace the call and return with a jump
|
||||||
|
|
||||||
let jump = Stmt::Jump(goal_id, args);
|
let jump = Stmt::Jump(goal_id, arguments);
|
||||||
|
|
||||||
Some(arena.alloc(jump))
|
Some(arena.alloc(jump))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue