mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-30 07:14:46 +00:00
Fix inlining and test
This commit is contained in:
parent
3e5627689f
commit
1926adb543
2 changed files with 108 additions and 18 deletions
|
@ -1,4 +1,5 @@
|
|||
use crate::annotation::IntroducedVariables;
|
||||
use crate::builtins::builtin_defs;
|
||||
use crate::def::{can_defs_with_return, Def};
|
||||
use crate::env::Env;
|
||||
use crate::num::{
|
||||
|
@ -1192,9 +1193,62 @@ pub fn inline_calls(var_store: &mut VarStore, scope: &mut Scope, expr: Expr) ->
|
|||
let (fn_var, loc_expr, expr_var) = *boxed_tuple;
|
||||
|
||||
match loc_expr.value {
|
||||
Var(symbol) if symbol.is_builtin() => {
|
||||
todo!("Inline this builtin: {:?}", symbol);
|
||||
}
|
||||
Var(symbol) if symbol.is_builtin() => match builtin_defs(var_store).get(&symbol) {
|
||||
Some(Closure(_var, _, recursive, params, boxed_body)) => {
|
||||
debug_assert_eq!(*recursive, Recursive::NotRecursive);
|
||||
|
||||
// Since this is a canonicalized Expr, we should have
|
||||
// already detected any arity mismatches and replaced this
|
||||
// with a RuntimeError if there was a mismatch.
|
||||
debug_assert_eq!(params.len(), args.len());
|
||||
|
||||
// Start with the function's body as the answer.
|
||||
let (mut loc_answer, _body_var) = *boxed_body.clone();
|
||||
|
||||
// Wrap the body in one LetNonRec for each argument,
|
||||
// such that at the end we have all the arguments in
|
||||
// scope with the values the caller provided.
|
||||
for ((_param_var, loc_pattern), (expr_var, loc_expr)) in
|
||||
params.iter().cloned().zip(args.into_iter()).rev()
|
||||
{
|
||||
// TODO get the correct vars into here.
|
||||
// Not sure if param_var should be involved.
|
||||
let pattern_vars = SendMap::default();
|
||||
|
||||
// TODO get the actual correct aliases
|
||||
let aliases = SendMap::default();
|
||||
|
||||
let def = Def {
|
||||
loc_pattern,
|
||||
loc_expr,
|
||||
expr_var,
|
||||
pattern_vars,
|
||||
annotation: None,
|
||||
};
|
||||
|
||||
loc_answer = Located {
|
||||
region: Region::zero(),
|
||||
value: LetNonRec(
|
||||
Box::new(def),
|
||||
Box::new(loc_answer),
|
||||
var_store.fresh(),
|
||||
aliases,
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
loc_answer.value
|
||||
}
|
||||
Some(_) => {
|
||||
unreachable!("Tried to inline a non-function");
|
||||
}
|
||||
None => {
|
||||
unreachable!(
|
||||
"Tried to inline a builtin that wasn't registered: {:?}",
|
||||
symbol
|
||||
);
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
// For now, we only inline calls to builtins. Leave this alone!
|
||||
Call(Box::new((fn_var, loc_expr, expr_var)), args, called_via)
|
||||
|
|
|
@ -14,13 +14,16 @@ mod helpers;
|
|||
mod can_inline {
|
||||
use crate::helpers::{can_expr_with, test_home};
|
||||
use bumpalo::Bump;
|
||||
use roc_can::def::Def;
|
||||
use roc_can::expr::inline_calls;
|
||||
use roc_can::expr::Expr::{self, *};
|
||||
use roc_can::pattern::Pattern;
|
||||
use roc_can::scope::Scope;
|
||||
use roc_collections::all::SendMap;
|
||||
use roc_module::operator::CalledVia;
|
||||
use roc_module::symbol::Symbol;
|
||||
use roc_region::all::{Located, Region};
|
||||
use roc_types::subs::VarStore;
|
||||
use roc_types::subs::{VarStore, Variable};
|
||||
|
||||
fn assert_inlines_to(input: &str, expected: Expr, var_store: &mut VarStore) {
|
||||
let arena = Bump::new();
|
||||
|
@ -34,6 +37,7 @@ mod can_inline {
|
|||
#[test]
|
||||
fn inline_list_len() {
|
||||
let var_store = &mut VarStore::default();
|
||||
let aliases = SendMap::default();
|
||||
|
||||
assert_inlines_to(
|
||||
indoc!(
|
||||
|
@ -41,23 +45,55 @@ mod can_inline {
|
|||
Int.isZero 5
|
||||
"#
|
||||
),
|
||||
Expr::Call(
|
||||
Box::new((
|
||||
var_store.fresh(),
|
||||
Located {
|
||||
LetNonRec(
|
||||
Box::new(Def {
|
||||
loc_pattern: Located {
|
||||
region: Region::zero(),
|
||||
value: Expr::Var(Symbol::FLOAT_EQ),
|
||||
value: Pattern::Identifier(Symbol::INT_IS_ZERO_ARG),
|
||||
},
|
||||
var_store.fresh(),
|
||||
)),
|
||||
vec![(
|
||||
var_store.fresh(),
|
||||
Located {
|
||||
region: Region::zero(),
|
||||
value: Int(var_store.fresh(), 5),
|
||||
pattern_vars: SendMap::default(),
|
||||
loc_expr: Located {
|
||||
region: Region::new(0, 0, 11, 12),
|
||||
value: Num(unsafe { Variable::unsafe_test_debug_variable(7) }, 5),
|
||||
},
|
||||
)],
|
||||
CalledVia::Space,
|
||||
expr_var: unsafe { Variable::unsafe_test_debug_variable(8) },
|
||||
annotation: None,
|
||||
}),
|
||||
Box::new(Located {
|
||||
region: Region::zero(),
|
||||
value: Expr::Call(
|
||||
Box::new((
|
||||
unsafe { Variable::unsafe_test_debug_variable(138) },
|
||||
Located {
|
||||
region: Region::zero(),
|
||||
value: Expr::Var(Symbol::INT_EQ_I64),
|
||||
},
|
||||
unsafe { Variable::unsafe_test_debug_variable(139) },
|
||||
)),
|
||||
vec![
|
||||
(
|
||||
unsafe { Variable::unsafe_test_debug_variable(140) },
|
||||
Located {
|
||||
region: Region::zero(),
|
||||
value: Var(Symbol::INT_IS_ZERO_ARG),
|
||||
},
|
||||
),
|
||||
(
|
||||
unsafe { Variable::unsafe_test_debug_variable(141) },
|
||||
Located {
|
||||
region: Region::zero(),
|
||||
value: Int(
|
||||
unsafe { Variable::unsafe_test_debug_variable(137) },
|
||||
0,
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
CalledVia::Space,
|
||||
),
|
||||
}),
|
||||
unsafe { Variable::unsafe_test_debug_variable(198) },
|
||||
aliases,
|
||||
),
|
||||
var_store,
|
||||
)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue