This commit is contained in:
Folkert 2021-11-03 14:09:04 +01:00
parent 74df66a472
commit a15183a7d1
8 changed files with 83 additions and 78 deletions

View file

@ -1,5 +1,5 @@
use crate::def::Def;
use crate::expr::Expr::*;
use crate::expr::{ClosureData, Expr::*};
use crate::expr::{Expr, Recursive, WhenBranch};
use crate::pattern::Pattern;
use roc_collections::all::SendMap;
@ -2889,7 +2889,7 @@ fn set_walk(symbol: Symbol, var_store: &mut VarStore) -> Def {
CalledVia::Space,
);
let wrapper = Closure {
let wrapper = Closure(ClosureData {
function_type: wrapper_var,
closure_type: var_store.fresh(),
closure_ext_var: var_store.fresh(),
@ -2903,7 +2903,7 @@ fn set_walk(symbol: Symbol, var_store: &mut VarStore) -> Def {
(Variable::EMPTY_RECORD, no_region(Pattern::Underscore)),
],
loc_body: Box::new(no_region(call_func)),
};
});
let body = RunLowLevel {
op: LowLevel::DictWalk,
@ -3918,7 +3918,7 @@ fn defn_help(
.map(|(var, symbol)| (var, no_region(Identifier(symbol))))
.collect();
Closure {
Closure(ClosureData {
function_type: var_store.fresh(),
closure_type: var_store.fresh(),
closure_ext_var: var_store.fresh(),
@ -3928,7 +3928,7 @@ fn defn_help(
recursive: Recursive::NotRecursive,
arguments: closure_args,
loc_body: Box::new(no_region(body)),
}
})
}
#[inline(always)]

View file

@ -1,6 +1,7 @@
use crate::annotation::canonicalize_annotation;
use crate::annotation::IntroducedVariables;
use crate::env::Env;
use crate::expr::ClosureData;
use crate::expr::Expr::{self, *};
use crate::expr::{
canonicalize_expr, local_successors, references_from_call, references_from_local, Output,
@ -670,10 +671,10 @@ fn group_to_declaration(
let mut new_def = can_def.clone();
// Determine recursivity of closures that are not tail-recursive
if let Closure {
if let Closure(ClosureData {
recursive: recursive @ Recursive::NotRecursive,
..
} = &mut new_def.loc_expr.value
}) = &mut new_def.loc_expr.value
{
*recursive = closure_recursivity(*symbol, closures);
}
@ -698,10 +699,10 @@ fn group_to_declaration(
let mut new_def = can_def.clone();
// Determine recursivity of closures that are not tail-recursive
if let Closure {
if let Closure(ClosureData {
recursive: recursive @ Recursive::NotRecursive,
..
} = &mut new_def.loc_expr.value
}) = &mut new_def.loc_expr.value
{
*recursive = closure_recursivity(symbol, closures);
}
@ -838,7 +839,7 @@ fn canonicalize_pending_def<'a>(
};
Located {
value: Closure {
value: Closure(ClosureData {
function_type: var_store.fresh(),
closure_type: var_store.fresh(),
closure_ext_var: var_store.fresh(),
@ -848,7 +849,7 @@ fn canonicalize_pending_def<'a>(
recursive: Recursive::NotRecursive,
arguments: underscores,
loc_body: Box::new(body_expr),
},
}),
region: loc_ann.region,
}
};
@ -1001,7 +1002,7 @@ fn canonicalize_pending_def<'a>(
if let (
&ast::Pattern::Identifier(_name),
&Pattern::Identifier(ref defined_symbol),
&Closure {
&Closure(ClosureData {
function_type,
closure_type,
closure_ext_var,
@ -1011,7 +1012,7 @@ fn canonicalize_pending_def<'a>(
loc_body: ref body,
ref captured_symbols,
..
},
}),
) = (
&loc_pattern.value,
&loc_can_pattern.value,
@ -1049,7 +1050,7 @@ fn canonicalize_pending_def<'a>(
});
// renamed_closure_def = Some(&defined_symbol);
loc_can_expr.value = Closure {
loc_can_expr.value = Closure(ClosureData {
function_type,
closure_type,
closure_ext_var,
@ -1059,7 +1060,7 @@ fn canonicalize_pending_def<'a>(
recursive: is_recursive,
arguments: arguments.clone(),
loc_body: body.clone(),
};
});
}
// Store the referenced locals in the refs_by_symbol map, so we can later figure out
@ -1144,7 +1145,7 @@ fn canonicalize_pending_def<'a>(
if let (
&ast::Pattern::Identifier(_name),
&Pattern::Identifier(ref defined_symbol),
&Closure {
&Closure(ClosureData {
function_type,
closure_type,
closure_ext_var,
@ -1154,7 +1155,7 @@ fn canonicalize_pending_def<'a>(
loc_body: ref body,
ref captured_symbols,
..
},
}),
) = (
&loc_pattern.value,
&loc_can_pattern.value,
@ -1191,7 +1192,7 @@ fn canonicalize_pending_def<'a>(
refs.lookups = refs.lookups.without(defined_symbol);
});
loc_can_expr.value = Closure {
loc_can_expr.value = Closure(ClosureData {
function_type,
closure_type,
closure_ext_var,
@ -1201,7 +1202,7 @@ fn canonicalize_pending_def<'a>(
recursive: is_recursive,
arguments: arguments.clone(),
loc_body: body.clone(),
};
});
}
// Store the referenced locals in the refs_by_symbol map, so we can later figure out

View file

@ -102,17 +102,7 @@ pub enum Expr {
ret_var: Variable,
},
Closure {
function_type: Variable,
closure_type: Variable,
closure_ext_var: Variable,
return_type: Variable,
name: Symbol,
captured_symbols: Vec<(Symbol, Variable)>,
recursive: Recursive,
arguments: Vec<(Variable, Located<Pattern>)>,
loc_body: Box<Located<Expr>>,
},
Closure(ClosureData),
// Product Types
Record {
@ -173,6 +163,18 @@ pub enum Expr {
// Compiles, but will crash if reached
RuntimeError(RuntimeError),
}
#[derive(Clone, Debug, PartialEq)]
pub struct ClosureData {
pub function_type: Variable,
pub closure_type: Variable,
pub closure_ext_var: Variable,
pub return_type: Variable,
pub name: Symbol,
pub captured_symbols: Vec<(Symbol, Variable)>,
pub recursive: Recursive,
pub arguments: Vec<(Variable, Located<Pattern>)>,
pub loc_body: Box<Located<Expr>>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct Field {
@ -572,7 +574,7 @@ pub fn canonicalize_expr<'a>(
}
(
Closure {
Closure(ClosureData {
function_type: var_store.fresh(),
closure_type: var_store.fresh(),
closure_ext_var: var_store.fresh(),
@ -582,7 +584,7 @@ pub fn canonicalize_expr<'a>(
recursive: Recursive::NotRecursive,
arguments: can_args,
loc_body: Box::new(loc_body_expr),
},
}),
output,
)
}
@ -1403,7 +1405,7 @@ pub fn inline_calls(var_store: &mut VarStore, scope: &mut Scope, expr: Expr) ->
LetNonRec(Box::new(def), Box::new(loc_expr), var)
}
Closure {
Closure(ClosureData {
function_type,
closure_type,
closure_ext_var,
@ -1413,14 +1415,14 @@ pub fn inline_calls(var_store: &mut VarStore, scope: &mut Scope, expr: Expr) ->
captured_symbols,
arguments,
loc_body,
} => {
}) => {
let loc_expr = *loc_body;
let loc_expr = Located {
value: inline_calls(var_store, scope, loc_expr.value),
region: loc_expr.region,
};
Closure {
Closure(ClosureData {
function_type,
closure_type,
closure_ext_var,
@ -1430,7 +1432,7 @@ pub fn inline_calls(var_store: &mut VarStore, scope: &mut Scope, expr: Expr) ->
captured_symbols,
arguments,
loc_body: Box::new(loc_expr),
}
})
}
Record { record_var, fields } => {
@ -1492,12 +1494,12 @@ pub fn inline_calls(var_store: &mut VarStore, scope: &mut Scope, expr: Expr) ->
loc_expr:
Located {
value:
Closure {
Closure(ClosureData {
recursive,
arguments: params,
loc_body: boxed_body,
..
},
}),
..
},
..

View file

@ -1,6 +1,6 @@
use crate::def::{canonicalize_defs, sort_can_defs, Declaration, Def};
use crate::env::Env;
use crate::expr::{Expr, Output};
use crate::expr::{ClosureData, Expr, Output};
use crate::operator::desugar_def;
use crate::pattern::Pattern;
use crate::scope::Scope;
@ -416,13 +416,13 @@ fn fix_values_captured_in_closure_expr(
fix_values_captured_in_closure_expr(&mut loc_expr.value, no_capture_symbols);
}
Closure {
Closure(ClosureData {
captured_symbols,
name,
arguments,
loc_body,
..
} => {
}) => {
captured_symbols.retain(|(s, _)| !no_capture_symbols.contains(s));
captured_symbols.retain(|(s, _)| s != name);

View file

@ -7,7 +7,7 @@ use roc_can::def::{Declaration, Def};
use roc_can::expected::Expected::{self, *};
use roc_can::expected::PExpected;
use roc_can::expr::Expr::{self, *};
use roc_can::expr::{Field, WhenBranch};
use roc_can::expr::{ClosureData, Field, WhenBranch};
use roc_can::pattern::Pattern;
use roc_collections::all::{ImMap, Index, MutSet, SendMap};
use roc_module::ident::{Lowercase, TagName};
@ -333,7 +333,7 @@ pub fn constrain_expr(
// make lookup constraint to lookup this symbol's type in the environment
Lookup(*symbol, expected, region)
}
Closure {
Closure(ClosureData {
function_type: fn_var,
closure_type: closure_var,
closure_ext_var,
@ -343,7 +343,7 @@ pub fn constrain_expr(
captured_symbols,
name,
..
} => {
}) => {
// NOTE defs are treated somewhere else!
let loc_body_expr = &**boxed;
@ -1203,7 +1203,7 @@ fn constrain_def(env: &Env, def: &Def, body_con: Constraint) -> Constraint {
// instead of the more generic "something is wrong with the body of `f`"
match (&def.loc_expr.value, &signature) {
(
Closure {
Closure(ClosureData {
function_type: fn_var,
closure_type: closure_var,
closure_ext_var,
@ -1213,7 +1213,7 @@ fn constrain_def(env: &Env, def: &Def, body_con: Constraint) -> Constraint {
loc_body,
name,
..
},
}),
Type::Function(arg_types, signature_closure_type, ret_type),
) => {
// NOTE if we ever have problems with the closure, the ignored `_closure_type`
@ -1561,7 +1561,7 @@ pub fn rec_defs_help(
// instead of the more generic "something is wrong with the body of `f`"
match (&def.loc_expr.value, &signature) {
(
Closure {
Closure(ClosureData {
function_type: fn_var,
closure_type: closure_var,
closure_ext_var,
@ -1571,7 +1571,7 @@ pub fn rec_defs_help(
loc_body,
name,
..
},
}),
Type::Function(arg_types, _closure_type, ret_type),
) => {
// NOTE if we ever have trouble with closure type unification, the ignored

View file

@ -1,7 +1,7 @@
use roc_can::annotation::IntroducedVariables;
use roc_can::def::{Declaration, Def};
use roc_can::env::Env;
use roc_can::expr::{Expr, Recursive};
use roc_can::expr::{ClosureData, Expr, Recursive};
use roc_can::pattern::Pattern;
use roc_can::scope::Scope;
use roc_collections::all::{MutSet, SendMap};
@ -117,7 +117,7 @@ fn build_effect_always(
let body = Expr::Var(value_symbol);
Expr::Closure {
Expr::Closure(ClosureData {
function_type: var_store.fresh(),
closure_type: var_store.fresh(),
closure_ext_var: var_store.fresh(),
@ -127,7 +127,7 @@ fn build_effect_always(
recursive: Recursive::NotRecursive,
arguments,
loc_body: Box::new(Located::at_zero(body)),
}
})
};
// \value -> @Effect \{} -> value
@ -146,7 +146,7 @@ fn build_effect_always(
)];
let function_var = var_store.fresh();
let closure = Expr::Closure {
let closure = Expr::Closure(ClosureData {
function_type: function_var,
closure_type: var_store.fresh(),
closure_ext_var: var_store.fresh(),
@ -156,7 +156,7 @@ fn build_effect_always(
recursive: Recursive::NotRecursive,
arguments,
loc_body: Box::new(Located::at_zero(body)),
};
});
(function_var, closure)
};
@ -295,7 +295,7 @@ fn build_effect_map(
Located::at_zero(empty_record_pattern(var_store)),
)];
Expr::Closure {
Expr::Closure(ClosureData {
function_type: var_store.fresh(),
closure_type: var_store.fresh(),
closure_ext_var: var_store.fresh(),
@ -308,7 +308,7 @@ fn build_effect_map(
recursive: Recursive::NotRecursive,
arguments,
loc_body: Box::new(Located::at_zero(mapper_call)),
}
})
};
let arguments = vec![
@ -339,7 +339,7 @@ fn build_effect_map(
};
let function_var = var_store.fresh();
let map_closure = Expr::Closure {
let map_closure = Expr::Closure(ClosureData {
function_type: function_var,
closure_type: var_store.fresh(),
closure_ext_var: var_store.fresh(),
@ -349,7 +349,7 @@ fn build_effect_map(
recursive: Recursive::NotRecursive,
arguments,
loc_body: Box::new(Located::at_zero(body)),
};
});
let mut introduced_variables = IntroducedVariables::default();
@ -509,7 +509,7 @@ fn build_effect_after(
];
let function_var = var_store.fresh();
let after_closure = Expr::Closure {
let after_closure = Expr::Closure(ClosureData {
function_type: function_var,
closure_type: var_store.fresh(),
closure_ext_var: var_store.fresh(),
@ -519,7 +519,7 @@ fn build_effect_after(
recursive: Recursive::NotRecursive,
arguments,
loc_body: Box::new(Located::at_zero(to_effect_call)),
};
});
let mut introduced_variables = IntroducedVariables::default();
@ -653,7 +653,7 @@ pub fn build_host_exposed_def(
.unwrap()
};
let effect_closure = Expr::Closure {
let effect_closure = Expr::Closure(ClosureData {
function_type: var_store.fresh(),
closure_type: var_store.fresh(),
closure_ext_var: var_store.fresh(),
@ -666,7 +666,7 @@ pub fn build_host_exposed_def(
Located::at_zero(empty_record_pattern(var_store)),
)],
loc_body: Box::new(Located::at_zero(low_level_call)),
};
});
let body = Expr::Tag {
variant_var: var_store.fresh(),
@ -675,7 +675,7 @@ pub fn build_host_exposed_def(
arguments: vec![(var_store.fresh(), Located::at_zero(effect_closure))],
};
Expr::Closure {
Expr::Closure(ClosureData {
function_type: var_store.fresh(),
closure_type: var_store.fresh(),
closure_ext_var: var_store.fresh(),
@ -685,7 +685,7 @@ pub fn build_host_exposed_def(
recursive: Recursive::NotRecursive,
arguments,
loc_body: Box::new(Located::at_zero(body)),
}
})
}
_ => {
// not a function
@ -717,7 +717,7 @@ pub fn build_host_exposed_def(
destructs: vec![],
};
let effect_closure = Expr::Closure {
let effect_closure = Expr::Closure(ClosureData {
function_type: var_store.fresh(),
closure_type: var_store.fresh(),
closure_ext_var: var_store.fresh(),
@ -727,7 +727,7 @@ pub fn build_host_exposed_def(
recursive: Recursive::NotRecursive,
arguments: vec![(var_store.fresh(), Located::at_zero(empty_record_pattern))],
loc_body: Box::new(Located::at_zero(low_level_call)),
};
});
Expr::Tag {
variant_var: var_store.fresh(),

View file

@ -4129,6 +4129,7 @@ fn add_def_to_module<'a>(
exposed_to_host: &MutMap<Symbol, Variable>,
is_recursive: bool,
) {
use roc_can::expr::ClosureData;
use roc_can::expr::Expr::*;
use roc_can::pattern::Pattern::*;
@ -4137,14 +4138,14 @@ fn add_def_to_module<'a>(
let is_exposed = exposed_to_host.contains_key(&symbol);
match def.loc_expr.value {
Closure {
Closure(ClosureData {
function_type: annotation,
return_type: ret_var,
arguments: loc_args,
loc_body,
captured_symbols,
..
} => {
}) => {
// this is a top-level definition, it should not capture anything
debug_assert!(captured_symbols.is_empty());

View file

@ -9,6 +9,7 @@ use crate::layout::{
use bumpalo::collections::Vec;
use bumpalo::Bump;
use hashbrown::hash_map::Entry;
use roc_can::expr::ClosureData;
use roc_collections::all::{default_hasher, BumpMap, BumpMapDefault, MutMap};
use roc_module::ident::{ForeignSymbol, Lowercase, TagName};
use roc_module::low_level::LowLevel;
@ -2910,7 +2911,7 @@ pub fn with_hole<'a>(
}
LetNonRec(def, cont, _) => {
if let roc_can::pattern::Pattern::Identifier(symbol) = &def.loc_pattern.value {
if let Closure {
if let Closure(ClosureData {
function_type,
return_type,
recursive,
@ -2918,7 +2919,7 @@ pub fn with_hole<'a>(
loc_body: boxed_body,
captured_symbols,
..
} = def.loc_expr.value
}) = def.loc_expr.value
{
// Extract Procs, but discard the resulting Expr::Load.
// That Load looks up the pointer, which we won't use here!
@ -3086,14 +3087,14 @@ pub fn with_hole<'a>(
// because Roc is strict, only functions can be recursive!
for def in defs.into_iter() {
if let roc_can::pattern::Pattern::Identifier(symbol) = &def.loc_pattern.value {
if let Closure {
if let Closure(ClosureData {
function_type,
return_type,
recursive,
arguments,
loc_body: boxed_body,
..
} = def.loc_expr.value
}) = def.loc_expr.value
{
// Extract Procs, but discard the resulting Expr::Load.
// That Load looks up the pointer, which we won't use here!
@ -3811,7 +3812,7 @@ pub fn with_hole<'a>(
}
}
Closure {
Closure(ClosureData {
function_type,
return_type,
name,
@ -3819,7 +3820,7 @@ pub fn with_hole<'a>(
captured_symbols,
loc_body: boxed_body,
..
} => {
}) => {
let loc_body = *boxed_body;
let raw = layout_cache.raw_from_var(env.arena, function_type, env.subs);
@ -4803,14 +4804,14 @@ pub fn from_can<'a>(
// Now that we know for sure it's a closure, get an owned
// version of these variant args so we can use them properly.
match def.loc_expr.value {
Closure {
Closure(ClosureData {
function_type,
return_type,
recursive,
arguments,
loc_body: boxed_body,
..
} => {
}) => {
// Extract Procs, but discard the resulting Expr::Load.
// That Load looks up the pointer, which we won't use here!
@ -4844,11 +4845,11 @@ pub fn from_can<'a>(
}
LetNonRec(def, cont, outer_annotation) => {
if let roc_can::pattern::Pattern::Identifier(symbol) = &def.loc_pattern.value {
if let Closure { .. } = &def.loc_expr.value {
if let Closure(_) = &def.loc_expr.value {
// Now that we know for sure it's a closure, get an owned
// version of these variant args so we can use them properly.
match def.loc_expr.value {
Closure {
Closure(ClosureData {
function_type,
return_type,
closure_type,
@ -4858,7 +4859,7 @@ pub fn from_can<'a>(
loc_body: boxed_body,
captured_symbols,
..
} => {
}) => {
if true || !procs.partial_procs.contains_key(*symbol) {
let loc_body = *boxed_body;