Add fx var to can's Call

This commit is contained in:
Agus Zubiaga 2024-10-05 21:52:35 -03:00
parent 3cef756559
commit e8d7820f34
No known key found for this signature in database
14 changed files with 52 additions and 10 deletions

View file

@ -413,13 +413,14 @@ fn deep_copy_expr_help<C: CopyEnv>(env: &mut C, copied: &mut Vec<Variable>, expr
}
Call(f, args, called_via) => {
let (fn_var, fn_expr, clos_var, ret_var) = &**f;
let (fn_var, fn_expr, clos_var, ret_var, fx_var) = &**f;
Call(
Box::new((
sub!(*fn_var),
fn_expr.map(|e| go_help!(e)),
sub!(*clos_var),
sub!(*ret_var),
sub!(*fx_var),
)),
args.iter()
.map(|(var, expr)| (sub!(*var), expr.map(|e| go_help!(e))))

View file

@ -267,7 +267,7 @@ fn expr<'a>(c: &Ctx, p: EPrec, f: &'a Arena<'a>, e: &'a Expr) -> DocBuilder<'a,
.append(expr(c, Free, f, &body.value))
.group(),
Call(fun, args, _) => {
let (_, fun, _, _) = &**fun;
let (_, fun, _, _, _) = &**fun;
maybe_paren!(
Free,
p,

View file

@ -155,7 +155,7 @@ pub enum Expr {
/// This is *only* for calling functions, not for tag application.
/// The Tag variant contains any applied values inside it.
Call(
Box<(Variable, Loc<Expr>, Variable, Variable)>,
Box<(Variable, Loc<Expr>, Variable, Variable, Variable)>,
Vec<(Variable, Loc<Expr>)>,
CalledVia,
),
@ -930,6 +930,7 @@ pub fn canonicalize_expr<'a>(
fn_expr,
var_store.fresh(),
var_store.fresh(),
var_store.fresh(),
)),
args,
*application_style,
@ -969,6 +970,7 @@ pub fn canonicalize_expr<'a>(
fn_expr,
var_store.fresh(),
var_store.fresh(),
var_store.fresh(),
)),
args,
*application_style,
@ -2448,10 +2450,11 @@ pub fn inline_calls(var_store: &mut VarStore, expr: Expr) -> Expr {
}
Call(boxed_tuple, args, called_via) => {
let (fn_var, loc_expr, closure_var, expr_var) = *boxed_tuple;
let (fn_var, loc_expr, closure_var, expr_var, fx_var) = *boxed_tuple;
match loc_expr.value {
Var(symbol, _) if symbol.is_builtin() => {
// NOTE: This assumes builtins are not effectful!
match builtin_defs_map(symbol, var_store) {
Some(Def {
loc_expr:
@ -2519,7 +2522,7 @@ pub fn inline_calls(var_store: &mut VarStore, expr: Expr) -> Expr {
_ => {
// For now, we only inline calls to builtins. Leave this alone!
Call(
Box::new((fn_var, loc_expr, closure_var, expr_var)),
Box::new((fn_var, loc_expr, closure_var, expr_var, fx_var)),
args,
called_via,
)
@ -2787,6 +2790,7 @@ fn desugar_str_segments(var_store: &mut VarStore, segments: Vec<StrSegment>) ->
fn_expr,
var_store.fresh(),
var_store.fresh(),
var_store.fresh(),
)),
vec![
(var_store.fresh(), empty_string),
@ -2823,6 +2827,7 @@ fn desugar_str_segments(var_store: &mut VarStore, segments: Vec<StrSegment>) ->
fn_expr,
var_store.fresh(),
var_store.fresh(),
var_store.fresh(),
)),
vec![
(var_store.fresh(), loc_new_expr),

View file

@ -292,7 +292,7 @@ pub fn walk_expr<V: Visitor>(visitor: &mut V, expr: &Expr, var: Variable) {
visitor.visit_expr(&body.value, body.region, var);
}
Expr::Call(f, args, _called_via) => {
let (fn_var, loc_fn, _closure_var, _ret_var) = &**f;
let (fn_var, loc_fn, _closure_var, _ret_var, _fx_var) = &**f;
walk_call(visitor, *fn_var, loc_fn, args);
}
Expr::Crash { msg, .. } => {

View file

@ -481,7 +481,7 @@ pub fn constrain_expr(
}
}
Call(boxed, loc_args, called_via) => {
let (fn_var, loc_fn, closure_var, ret_var) = &**boxed;
let (fn_var, loc_fn, closure_var, ret_var, fx_var) = &**boxed;
// The expression that evaluates to the function being called, e.g. `foo` in
// (foo) bar baz
let opt_symbol = if let Var(symbol, _) | AbilityMember(symbol, _, _) = loc_fn.value {
@ -512,6 +512,9 @@ pub fn constrain_expr(
// The function's return type
let ret_type = Variable(*ret_var);
// The function's effect type
let fx_type = Variable(*fx_var);
// type of values captured in the closure
let closure_type = Variable(*closure_var);
@ -521,6 +524,7 @@ pub fn constrain_expr(
vars.push(*fn_var);
vars.push(*ret_var);
vars.push(*closure_var);
vars.push(*fx_var);
let mut arg_types = Vec::with_capacity(loc_args.len());
let mut arg_cons = Vec::with_capacity(loc_args.len());
@ -555,8 +559,7 @@ pub fn constrain_expr(
let arguments = types.from_old_type_slice(arg_types.iter());
let lambda_set = types.from_old_type(&closure_type);
let ret = types.from_old_type(&ret_type);
// [purity-inference] TODO: Add fx var to call
let fx = types.from_old_type(&Type::Variable(Variable::PURE));
let fx = types.from_old_type(&fx_type);
let typ = types.function(arguments, lambda_set, ret, fx);
constraints.push_type(types, typ)
};
@ -572,6 +575,7 @@ pub fn constrain_expr(
constraints.equal_types_var(*fn_var, expected_fn_type, category.clone(), fn_region),
constraints.and_constraint(arg_cons),
constraints.equal_types_var(*ret_var, expected_final_type, category, region),
// [purity-inference] TODO: union with current function's fx var
];
let and_constraint = constraints.and_constraint(and_cons);

View file

@ -91,6 +91,7 @@ fn wrap_in_decode_custom_decode_with(
Loc::at_zero(decode_with_var),
this_decode_with_clos_var,
this_decode_with_ret_var,
Variable::PURE,
));
let decode_with_call = Call(
decode_with_fn,
@ -198,6 +199,7 @@ fn wrap_in_decode_custom_decode_with(
Loc::at_zero(decode_custom_var),
this_decode_custom_clos_var,
this_decode_custom_ret_var,
Variable::PURE,
));
let decode_custom_call = Call(
decode_custom_fn,

View file

@ -78,6 +78,7 @@ pub(crate) fn decoder(env: &mut Env<'_>, _def_symbol: Symbol) -> (Expr, Variable
Loc::at_zero(decode_list_member),
this_decode_list_clos_var,
this_decode_list_ret_var,
Variable::PURE,
));
let decode_list_call = Call(

View file

@ -130,6 +130,7 @@ pub(crate) fn decoder(
)),
decode_record_lambda_set,
record_decoder_var,
Variable::PURE,
)),
vec![
(initial_state_var, Loc::at_zero(initial_state)),
@ -422,6 +423,7 @@ fn custom_decoder(env: &mut Env<'_>, args: DecodingFieldArgs) -> (Variable, Expr
Loc::at_zero(Expr::Var(Symbol::DECODE_CUSTOM, this_decode_custom_var)),
decode_custom_closure_var,
decode_custom_ret_var,
Variable::PURE,
)),
vec![(this_custom_callback_var, Loc::at_zero(custom_callback))],
CalledVia::Space,
@ -1328,6 +1330,7 @@ pub(super) fn decode_with(
Loc::at_zero(Expr::Var(Symbol::DECODE_DECODE_WITH, this_decode_with_var)),
lambda_set_var,
rec_var,
Variable::PURE,
)),
vec![
(Variable::LIST_U8, Loc::at_zero(bytes_arg_expr)),

View file

@ -120,6 +120,7 @@ pub(crate) fn decoder(env: &mut Env, _def_symbol: Symbol, arity: u32) -> (Expr,
)),
decode_record_lambda_set,
tuple_decoder_var,
Variable::PURE,
)),
vec![
(state_var, Loc::at_zero(initial_state)),
@ -490,6 +491,7 @@ fn step_elem(
Loc::at_zero(Expr::Var(Symbol::DECODE_DECODE_WITH, this_decode_with_var)),
lambda_set_var,
rec_var,
Variable::PURE,
)),
vec![
(
@ -598,6 +600,7 @@ fn step_elem(
Loc::at_zero(Expr::Var(Symbol::DECODE_CUSTOM, this_decode_custom_var)),
decode_custom_closure_var,
decode_custom_ret_var,
Variable::PURE,
)),
vec![(this_custom_callback_var, Loc::at_zero(custom_callback))],
CalledVia::Space,

View file

@ -146,6 +146,7 @@ fn to_encoder_list(env: &mut Env<'_>, fn_name: Symbol) -> (Expr, Variable) {
Loc::at_zero(to_encoder_var),
to_encoder_clos_var,
elem_encoder_var,
Variable::PURE,
));
// toEncoder elem
@ -231,6 +232,7 @@ fn to_encoder_list(env: &mut Env<'_>, fn_name: Symbol) -> (Expr, Variable) {
Loc::at_zero(encode_list),
this_encode_list_clos_var,
this_list_encoder_var,
Variable::PURE,
));
// Encode.list lst to_elem_encoder
@ -370,6 +372,7 @@ fn to_encoder_record(
Loc::at_zero(to_encoder_var),
to_encoder_clos_var,
encoder_var,
Variable::PURE,
));
// toEncoder rcd.a
@ -451,6 +454,7 @@ fn to_encoder_record(
Loc::at_zero(encode_record_var),
encode_record_clos_var,
encoder_var,
Variable::PURE,
));
// Encode.record [ { key: .., value: .. }, .. ]
@ -574,6 +578,7 @@ fn to_encoder_tuple(
Loc::at_zero(to_encoder_var),
to_encoder_clos_var,
encoder_var,
Variable::PURE,
));
// toEncoder tup.0
@ -635,6 +640,7 @@ fn to_encoder_tuple(
Loc::at_zero(encode_tuple_var),
encode_tuple_clos_var,
encoder_var,
Variable::PURE,
));
// Encode.tuple [ { key: .., value: .. }, .. ]
@ -776,6 +782,7 @@ fn to_encoder_tag_union(
Loc::at_zero(to_encoder_var),
to_encoder_clos_var,
encoder_var,
Variable::PURE,
));
// toEncoder rcd.a
@ -835,6 +842,7 @@ fn to_encoder_tag_union(
Loc::at_zero(encode_tag_var),
this_encode_tag_clos_var,
this_encoder_var,
Variable::PURE,
));
// Encode.tag "A" [ Encode.toEncoder v1, Encode.toEncoder v2 ]
@ -991,6 +999,7 @@ fn wrap_in_encode_custom(
Loc::at_zero(Var(Symbol::ENCODE_APPEND_WITH, this_append_with_fn_var)),
this_append_with_clos_var,
Variable::LIST_U8,
Variable::PURE,
));
// Encode.appendWith bytes encoder fmt
@ -1084,6 +1093,7 @@ fn wrap_in_encode_custom(
Loc::at_zero(Var(Symbol::ENCODE_CUSTOM, this_custom_fn_var)),
this_custom_clos_var, // -[clos]->
this_custom_encoder_var, // t' ~ Encoder fmt
Variable::PURE,
));
// Encode.custom \bytes, fmt -> Encode.appendWith bytes encoder fmt

View file

@ -489,6 +489,7 @@ fn call_hash_ability_member(
Loc::at_zero(hash_fn_head),
this_hash_clos_var,
this_out_hasher_var,
Variable::PURE,
));
let hash_arguments = vec![

View file

@ -152,6 +152,7 @@ fn to_inspector_list(env: &mut Env<'_>, fn_name: Symbol) -> (Expr, Variable) {
Loc::at_zero(to_inspector_var),
to_inspector_clos_var,
elem_inspector_var,
Variable::PURE,
));
// toInspector elem
@ -238,6 +239,7 @@ fn to_inspector_list(env: &mut Env<'_>, fn_name: Symbol) -> (Expr, Variable) {
Loc::at_zero(inspect_list),
this_inspect_list_clos_var,
this_list_inspector_var,
Variable::PURE,
));
// Inspect.list lst to_elem_inspector
@ -382,6 +384,7 @@ fn to_inspector_record(
Loc::at_zero(to_inspector_var),
to_inspector_clos_var,
inspector_var,
Variable::PURE,
));
// toInspector rcd.a
@ -463,6 +466,7 @@ fn to_inspector_record(
Loc::at_zero(inspect_record_var),
inspect_record_clos_var,
inspector_var,
Variable::PURE,
));
// Inspect.record [ { key: .., value: .. }, .. ]
@ -587,6 +591,7 @@ fn to_inspector_tuple(
Loc::at_zero(to_inspector_var),
to_inspector_clos_var,
inspector_var,
Variable::PURE,
));
// toInspector tup.0
@ -648,6 +653,7 @@ fn to_inspector_tuple(
Loc::at_zero(inspect_tuple_var),
inspect_tuple_clos_var,
inspector_var,
Variable::PURE,
));
// Inspect.tuple [ { key: .., value: .. }, .. ]
@ -789,6 +795,7 @@ fn to_inspector_tag_union(
Loc::at_zero(to_inspector_var),
to_inspector_clos_var,
inspector_var,
Variable::PURE,
));
// toInspector rcd.a
@ -852,6 +859,7 @@ fn to_inspector_tag_union(
Loc::at_zero(inspect_tag_var),
this_inspect_tag_clos_var,
this_inspector_var,
Variable::PURE,
));
// Inspect.tag "A" [ Inspect.toInspector v1, Inspect.toInspector v2 ]
@ -997,6 +1005,7 @@ fn wrap_in_inspect_custom(
Loc::at_zero(Var(Symbol::INSPECT_APPLY, this_apply_fn_var)),
this_apply_clos_var,
fmt_var,
Variable::PURE,
));
// Inspect.apply inspector fmt
@ -1081,6 +1090,7 @@ fn wrap_in_inspect_custom(
Loc::at_zero(Var(Symbol::INSPECT_CUSTOM, this_custom_fn_var)),
this_custom_clos_var, // -[clos]->
this_custom_inspector_var, // t' ~ Inspector fmt
Variable::PURE,
));
// Inspect.custom \fmt -> Inspect.apply inspector fmt

View file

@ -520,6 +520,7 @@ impl<'a> LowerParams<'a> {
Loc::at_zero(Var(symbol, var)),
self.var_store.fresh(),
self.var_store.fresh(),
self.var_store.fresh(),
));
let body = Call(
@ -565,6 +566,7 @@ impl<'a> LowerParams<'a> {
Loc::at_zero(Var(symbol, var)),
self.var_store.fresh(),
self.var_store.fresh(),
self.var_store.fresh(),
));
Call(

View file

@ -5455,7 +5455,7 @@ pub fn with_hole<'a>(
}
Call(boxed, loc_args, _) => {
let (fn_var, loc_expr, _lambda_set_var, _ret_var) = *boxed;
let (fn_var, loc_expr, _lambda_set_var, _ret_var, _fx_var) = *boxed;
// even if a call looks like it's by name, it may in fact be by-pointer.
// E.g. in `(\f, x -> f x)` the call is in fact by pointer.