Fix inlining and test

This commit is contained in:
Richard Feldman 2020-07-03 23:16:32 -04:00
parent 3e5627689f
commit 1926adb543
2 changed files with 108 additions and 18 deletions

View file

@ -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)

View file

@ -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,
)