mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 13:29:12 +00:00
Merge pull request #4354 from roc-lang/var-has-variable
Resolve ability specializations looked up in expects
This commit is contained in:
commit
e90ddcd7d1
15 changed files with 340 additions and 194 deletions
|
@ -247,7 +247,7 @@ fn lowlevel_1(symbol: Symbol, op: LowLevel, var_store: &mut VarStore) -> Def {
|
|||
|
||||
let body = RunLowLevel {
|
||||
op,
|
||||
args: vec![(arg1_var, Var(Symbol::ARG_1))],
|
||||
args: vec![(arg1_var, Var(Symbol::ARG_1, arg1_var))],
|
||||
ret_var,
|
||||
};
|
||||
|
||||
|
@ -268,8 +268,8 @@ fn lowlevel_2(symbol: Symbol, op: LowLevel, var_store: &mut VarStore) -> Def {
|
|||
let body = RunLowLevel {
|
||||
op,
|
||||
args: vec![
|
||||
(arg1_var, Var(Symbol::ARG_1)),
|
||||
(arg2_var, Var(Symbol::ARG_2)),
|
||||
(arg1_var, Var(Symbol::ARG_1, arg1_var)),
|
||||
(arg2_var, Var(Symbol::ARG_2, arg2_var)),
|
||||
],
|
||||
ret_var,
|
||||
};
|
||||
|
@ -292,9 +292,9 @@ fn lowlevel_3(symbol: Symbol, op: LowLevel, var_store: &mut VarStore) -> Def {
|
|||
let body = RunLowLevel {
|
||||
op,
|
||||
args: vec![
|
||||
(arg1_var, Var(Symbol::ARG_1)),
|
||||
(arg2_var, Var(Symbol::ARG_2)),
|
||||
(arg3_var, Var(Symbol::ARG_3)),
|
||||
(arg1_var, Var(Symbol::ARG_1, arg1_var)),
|
||||
(arg2_var, Var(Symbol::ARG_2, arg2_var)),
|
||||
(arg3_var, Var(Symbol::ARG_3, arg3_var)),
|
||||
],
|
||||
ret_var,
|
||||
};
|
||||
|
@ -322,10 +322,10 @@ fn lowlevel_4(symbol: Symbol, op: LowLevel, var_store: &mut VarStore) -> Def {
|
|||
let body = RunLowLevel {
|
||||
op,
|
||||
args: vec![
|
||||
(arg1_var, Var(Symbol::ARG_1)),
|
||||
(arg2_var, Var(Symbol::ARG_2)),
|
||||
(arg3_var, Var(Symbol::ARG_3)),
|
||||
(arg4_var, Var(Symbol::ARG_4)),
|
||||
(arg1_var, Var(Symbol::ARG_1, arg1_var)),
|
||||
(arg2_var, Var(Symbol::ARG_2, arg2_var)),
|
||||
(arg3_var, Var(Symbol::ARG_3, arg3_var)),
|
||||
(arg4_var, Var(Symbol::ARG_4, arg4_var)),
|
||||
],
|
||||
ret_var,
|
||||
};
|
||||
|
@ -355,11 +355,11 @@ fn lowlevel_5(symbol: Symbol, op: LowLevel, var_store: &mut VarStore) -> Def {
|
|||
let body = RunLowLevel {
|
||||
op,
|
||||
args: vec![
|
||||
(arg1_var, Var(Symbol::ARG_1)),
|
||||
(arg2_var, Var(Symbol::ARG_2)),
|
||||
(arg3_var, Var(Symbol::ARG_3)),
|
||||
(arg4_var, Var(Symbol::ARG_4)),
|
||||
(arg5_var, Var(Symbol::ARG_5)),
|
||||
(arg1_var, Var(Symbol::ARG_1, arg1_var)),
|
||||
(arg2_var, Var(Symbol::ARG_2, arg2_var)),
|
||||
(arg3_var, Var(Symbol::ARG_3, arg3_var)),
|
||||
(arg4_var, Var(Symbol::ARG_4, arg4_var)),
|
||||
(arg5_var, Var(Symbol::ARG_5, arg5_var)),
|
||||
],
|
||||
ret_var,
|
||||
};
|
||||
|
@ -486,7 +486,7 @@ fn to_num_checked(symbol: Symbol, var_store: &mut VarStore, lowlevel: LowLevel)
|
|||
ext_var: var_store.fresh(),
|
||||
field: "b".into(),
|
||||
field_var: var_store.fresh(),
|
||||
loc_expr: Box::new(no_region(Var(Symbol::ARG_2))),
|
||||
loc_expr: Box::new(no_region(Var(Symbol::ARG_2, var_store.fresh()))),
|
||||
},
|
||||
),
|
||||
// out of bounds!
|
||||
|
@ -509,7 +509,7 @@ fn to_num_checked(symbol: Symbol, var_store: &mut VarStore, lowlevel: LowLevel)
|
|||
ext_var: var_store.fresh(),
|
||||
field: "a".into(),
|
||||
field_var: num_var_2,
|
||||
loc_expr: Box::new(no_region(Var(Symbol::ARG_2))),
|
||||
loc_expr: Box::new(no_region(Var(Symbol::ARG_2, var_store.fresh()))),
|
||||
},
|
||||
],
|
||||
var_store,
|
||||
|
@ -523,7 +523,7 @@ fn to_num_checked(symbol: Symbol, var_store: &mut VarStore, lowlevel: LowLevel)
|
|||
loc_pattern: no_region(Pattern::Identifier(Symbol::ARG_2)),
|
||||
loc_expr: no_region(RunLowLevel {
|
||||
op: lowlevel,
|
||||
args: vec![(num_var_1, Var(Symbol::ARG_1))],
|
||||
args: vec![(num_var_1, Var(Symbol::ARG_1, var_store.fresh()))],
|
||||
ret_var: record_var,
|
||||
}),
|
||||
expr_var: record_var,
|
||||
|
@ -549,7 +549,7 @@ fn to_num_is_zero(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
let body = Expr::RunLowLevel {
|
||||
op: LowLevel::Eq,
|
||||
args: vec![
|
||||
(num_var, Var(Symbol::ARG_1)),
|
||||
(num_var, Var(Symbol::ARG_1, num_var)),
|
||||
(
|
||||
num_var,
|
||||
Num(
|
||||
|
|
|
@ -255,9 +255,9 @@ fn deep_copy_expr_help<C: CopyEnv>(env: &mut C, copied: &mut Vec<Variable>, expr
|
|||
elem_var: sub!(*elem_var),
|
||||
loc_elems: loc_elems.iter().map(|le| le.map(|e| go_help!(e))).collect(),
|
||||
},
|
||||
Var(sym) => Var(*sym),
|
||||
Var(sym, var) => Var(*sym, sub!(*var)),
|
||||
&AbilityMember(sym, specialization, specialization_var) => {
|
||||
AbilityMember(sym, specialization, specialization_var)
|
||||
AbilityMember(sym, specialization, sub!(specialization_var))
|
||||
}
|
||||
When {
|
||||
loc_cond,
|
||||
|
|
|
@ -124,14 +124,15 @@ fn build_effect_always(
|
|||
Loc::at_zero(empty_record_pattern(var_store)),
|
||||
)];
|
||||
|
||||
let body = Expr::Var(value_symbol);
|
||||
let value_var = var_store.fresh();
|
||||
let body = Expr::Var(value_symbol, value_var);
|
||||
|
||||
Expr::Closure(ClosureData {
|
||||
function_type: var_store.fresh(),
|
||||
closure_type: var_store.fresh(),
|
||||
return_type: var_store.fresh(),
|
||||
name: inner_closure_symbol,
|
||||
captured_symbols: vec![(value_symbol, var_store.fresh())],
|
||||
captured_symbols: vec![(value_symbol, value_var)],
|
||||
recursive: Recursive::NotRecursive,
|
||||
arguments,
|
||||
loc_body: Box::new(Loc::at_zero(body)),
|
||||
|
@ -231,20 +232,22 @@ fn build_effect_map(
|
|||
.introduce("effect_map_thunk".into(), Region::zero())
|
||||
.unwrap()
|
||||
};
|
||||
let thunk_var = var_store.fresh();
|
||||
|
||||
let mapper_symbol = {
|
||||
scope
|
||||
.introduce("effect_map_mapper".into(), Region::zero())
|
||||
.unwrap()
|
||||
};
|
||||
let mapper_var = var_store.fresh();
|
||||
|
||||
let map_symbol = { scope.introduce("map".into(), Region::zero()).unwrap() };
|
||||
|
||||
// `thunk {}`
|
||||
let force_thunk_call = {
|
||||
let boxed = (
|
||||
var_store.fresh(),
|
||||
Loc::at_zero(Expr::Var(thunk_symbol)),
|
||||
thunk_var,
|
||||
Loc::at_zero(Expr::Var(thunk_symbol, thunk_var)),
|
||||
var_store.fresh(),
|
||||
var_store.fresh(),
|
||||
);
|
||||
|
@ -256,8 +259,8 @@ fn build_effect_map(
|
|||
// `toEffect (thunk {})`
|
||||
let mapper_call = {
|
||||
let boxed = (
|
||||
var_store.fresh(),
|
||||
Loc::at_zero(Expr::Var(mapper_symbol)),
|
||||
mapper_var,
|
||||
Loc::at_zero(Expr::Var(mapper_symbol, mapper_var)),
|
||||
var_store.fresh(),
|
||||
var_store.fresh(),
|
||||
);
|
||||
|
@ -411,9 +414,9 @@ fn build_effect_map(
|
|||
(map_symbol, def)
|
||||
}
|
||||
|
||||
fn force_thunk(expr: Expr, var_store: &mut VarStore) -> Expr {
|
||||
fn force_thunk(expr: Expr, thunk_var: Variable, var_store: &mut VarStore) -> Expr {
|
||||
let boxed = (
|
||||
var_store.fresh(),
|
||||
thunk_var,
|
||||
Loc::at_zero(expr),
|
||||
var_store.fresh(),
|
||||
var_store.fresh(),
|
||||
|
@ -441,13 +444,19 @@ fn build_effect_after(
|
|||
let outer_closure_symbol = new_symbol!(scope, "effect_after_inner");
|
||||
|
||||
// `effect {}`
|
||||
let force_effect_call = force_thunk(Expr::Var(effect_symbol), var_store);
|
||||
let force_effect_var = var_store.fresh();
|
||||
let force_effect_call = force_thunk(
|
||||
Expr::Var(effect_symbol, force_effect_var),
|
||||
force_effect_var,
|
||||
var_store,
|
||||
);
|
||||
|
||||
// `toEffect (effect {})`
|
||||
let to_effect_var = var_store.fresh();
|
||||
let to_effect_call = {
|
||||
let boxed = (
|
||||
var_store.fresh(),
|
||||
Loc::at_zero(Expr::Var(to_effect_symbol)),
|
||||
to_effect_var,
|
||||
Loc::at_zero(Expr::Var(to_effect_symbol, to_effect_var)),
|
||||
var_store.fresh(),
|
||||
var_store.fresh(),
|
||||
);
|
||||
|
@ -459,7 +468,12 @@ fn build_effect_after(
|
|||
// let @Effect thunk = toEffect (effect {}) in thunk {}
|
||||
let let_effect_thunk = {
|
||||
// `thunk {}`
|
||||
let force_inner_thunk_call = force_thunk(Expr::Var(thunk_symbol), var_store);
|
||||
let force_inner_thunk_var = var_store.fresh();
|
||||
let force_inner_thunk_call = force_thunk(
|
||||
Expr::Var(thunk_symbol, force_inner_thunk_var),
|
||||
force_inner_thunk_var,
|
||||
var_store,
|
||||
);
|
||||
|
||||
let (specialized_def_type, type_arguments, lambda_set_variables) =
|
||||
build_fresh_opaque_variables(var_store);
|
||||
|
@ -702,9 +716,10 @@ fn force_effect(
|
|||
let ret_var = var_store.fresh();
|
||||
|
||||
let force_thunk_call = {
|
||||
let thunk_var = var_store.fresh();
|
||||
let boxed = (
|
||||
var_store.fresh(),
|
||||
Loc::at_zero(Expr::Var(thunk_symbol)),
|
||||
thunk_var,
|
||||
Loc::at_zero(Expr::Var(thunk_symbol, thunk_var)),
|
||||
var_store.fresh(),
|
||||
ret_var,
|
||||
);
|
||||
|
@ -884,6 +899,7 @@ fn build_effect_forever_inner_body(
|
|||
effect: Symbol,
|
||||
var_store: &mut VarStore,
|
||||
) -> Expr {
|
||||
let thunk1_var = var_store.fresh();
|
||||
let thunk1_symbol = { scope.introduce("thunk1".into(), Region::zero()).unwrap() };
|
||||
|
||||
let thunk2_symbol = { scope.introduce("thunk2".into(), Region::zero()).unwrap() };
|
||||
|
@ -909,7 +925,7 @@ fn build_effect_forever_inner_body(
|
|||
|
||||
Def {
|
||||
loc_pattern: Loc::at_zero(pattern),
|
||||
loc_expr: Loc::at_zero(Expr::Var(effect)),
|
||||
loc_expr: Loc::at_zero(Expr::Var(effect, var_store.fresh())),
|
||||
expr_var: var_store.fresh(),
|
||||
pattern_vars,
|
||||
annotation: None,
|
||||
|
@ -920,8 +936,8 @@ fn build_effect_forever_inner_body(
|
|||
let force_thunk_call = {
|
||||
let ret_var = var_store.fresh();
|
||||
let boxed = (
|
||||
var_store.fresh(),
|
||||
Loc::at_zero(Expr::Var(thunk1_symbol)),
|
||||
thunk1_var,
|
||||
Loc::at_zero(Expr::Var(thunk1_symbol, thunk1_var)),
|
||||
var_store.fresh(),
|
||||
ret_var,
|
||||
);
|
||||
|
@ -945,12 +961,13 @@ fn build_effect_forever_inner_body(
|
|||
let forever_effect = {
|
||||
let boxed = (
|
||||
var_store.fresh(),
|
||||
Loc::at_zero(Expr::Var(forever_symbol)),
|
||||
Loc::at_zero(Expr::Var(forever_symbol, var_store.fresh())),
|
||||
var_store.fresh(),
|
||||
var_store.fresh(),
|
||||
);
|
||||
|
||||
let arguments = vec![(var_store.fresh(), Loc::at_zero(Expr::Var(effect)))];
|
||||
let effect_var = var_store.fresh();
|
||||
let arguments = vec![(effect_var, Loc::at_zero(Expr::Var(effect, effect_var)))];
|
||||
Expr::Call(Box::new(boxed), arguments, CalledVia::Space)
|
||||
};
|
||||
|
||||
|
@ -1198,14 +1215,16 @@ fn build_effect_loop_inner_body(
|
|||
|
||||
// `step state`
|
||||
let rhs = {
|
||||
let step_var = var_store.fresh();
|
||||
let boxed = (
|
||||
var_store.fresh(),
|
||||
Loc::at_zero(Expr::Var(step_symbol)),
|
||||
step_var,
|
||||
Loc::at_zero(Expr::Var(step_symbol, step_var)),
|
||||
var_store.fresh(),
|
||||
var_store.fresh(),
|
||||
);
|
||||
|
||||
let arguments = vec![(var_store.fresh(), Loc::at_zero(Expr::Var(state_symbol)))];
|
||||
let state_var = var_store.fresh();
|
||||
let arguments = vec![(state_var, Loc::at_zero(Expr::Var(state_symbol, state_var)))];
|
||||
Expr::Call(Box::new(boxed), arguments, CalledVia::Space)
|
||||
};
|
||||
|
||||
|
@ -1220,10 +1239,11 @@ fn build_effect_loop_inner_body(
|
|||
|
||||
// thunk1 {}
|
||||
let force_thunk_call = {
|
||||
let thunk1_var = var_store.fresh();
|
||||
let ret_var = var_store.fresh();
|
||||
let boxed = (
|
||||
var_store.fresh(),
|
||||
Loc::at_zero(Expr::Var(thunk1_symbol)),
|
||||
thunk1_var,
|
||||
Loc::at_zero(Expr::Var(thunk1_symbol, thunk1_var)),
|
||||
var_store.fresh(),
|
||||
ret_var,
|
||||
);
|
||||
|
@ -1236,16 +1256,22 @@ fn build_effect_loop_inner_body(
|
|||
|
||||
// recursive call `loop newState step`
|
||||
let loop_new_state_step = {
|
||||
let loop_var = var_store.fresh();
|
||||
let boxed = (
|
||||
var_store.fresh(),
|
||||
Loc::at_zero(Expr::Var(loop_symbol)),
|
||||
loop_var,
|
||||
Loc::at_zero(Expr::Var(loop_symbol, loop_var)),
|
||||
var_store.fresh(),
|
||||
var_store.fresh(),
|
||||
);
|
||||
|
||||
let new_state_var = var_store.fresh();
|
||||
let step_var = var_store.fresh();
|
||||
let arguments = vec![
|
||||
(var_store.fresh(), Loc::at_zero(Expr::Var(new_state_symbol))),
|
||||
(var_store.fresh(), Loc::at_zero(Expr::Var(step_symbol))),
|
||||
(
|
||||
new_state_var,
|
||||
Loc::at_zero(Expr::Var(new_state_symbol, new_state_var)),
|
||||
),
|
||||
(step_var, Loc::at_zero(Expr::Var(step_symbol, step_var))),
|
||||
];
|
||||
Expr::Call(Box::new(boxed), arguments, CalledVia::Space)
|
||||
};
|
||||
|
@ -1283,7 +1309,7 @@ fn build_effect_loop_inner_body(
|
|||
|
||||
crate::expr::WhenBranch {
|
||||
patterns: vec![done_pattern],
|
||||
value: Loc::at_zero(Expr::Var(done_symbol)),
|
||||
value: Loc::at_zero(Expr::Var(done_symbol, var_store.fresh())),
|
||||
guard: None,
|
||||
redundant: RedundantMark::new(var_store),
|
||||
}
|
||||
|
@ -1351,7 +1377,7 @@ pub fn build_host_exposed_def(
|
|||
));
|
||||
|
||||
captured_symbols.push((arg_symbol, arg_var));
|
||||
linked_symbol_arguments.push((arg_var, Expr::Var(arg_symbol)));
|
||||
linked_symbol_arguments.push((arg_var, Expr::Var(arg_symbol, arg_var)));
|
||||
}
|
||||
|
||||
let foreign_symbol_name = format!("roc_fx_{}", ident);
|
||||
|
|
|
@ -100,7 +100,7 @@ pub enum Expr {
|
|||
},
|
||||
|
||||
// Lookups
|
||||
Var(Symbol),
|
||||
Var(Symbol, Variable),
|
||||
AbilityMember(
|
||||
/// Actual member name
|
||||
Symbol,
|
||||
|
@ -230,14 +230,14 @@ pub enum Expr {
|
|||
Expect {
|
||||
loc_condition: Box<Loc<Expr>>,
|
||||
loc_continuation: Box<Loc<Expr>>,
|
||||
lookups_in_cond: Vec<(Symbol, Variable)>,
|
||||
lookups_in_cond: Vec<ExpectLookup>,
|
||||
},
|
||||
|
||||
// not parsed, but is generated when lowering toplevel effectful expects
|
||||
ExpectFx {
|
||||
loc_condition: Box<Loc<Expr>>,
|
||||
loc_continuation: Box<Loc<Expr>>,
|
||||
lookups_in_cond: Vec<(Symbol, Variable)>,
|
||||
lookups_in_cond: Vec<ExpectLookup>,
|
||||
},
|
||||
|
||||
/// Rendered as empty box in editor
|
||||
|
@ -247,6 +247,13 @@ pub enum Expr {
|
|||
RuntimeError(RuntimeError),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct ExpectLookup {
|
||||
pub symbol: Symbol,
|
||||
pub var: Variable,
|
||||
pub ability_info: Option<SpecializationId>,
|
||||
}
|
||||
|
||||
impl Expr {
|
||||
pub fn category(&self) -> Category {
|
||||
match self {
|
||||
|
@ -256,7 +263,7 @@ impl Expr {
|
|||
Self::Str(..) => Category::Str,
|
||||
Self::SingleQuote(..) => Category::Character,
|
||||
Self::List { .. } => Category::List,
|
||||
&Self::Var(sym) => Category::Lookup(sym),
|
||||
&Self::Var(sym, _) => Category::Lookup(sym),
|
||||
&Self::AbilityMember(sym, _, _) => Category::Lookup(sym),
|
||||
Self::When { .. } => Category::When,
|
||||
Self::If { .. } => Category::If,
|
||||
|
@ -372,7 +379,7 @@ impl AccessorData {
|
|||
record_var,
|
||||
ext_var,
|
||||
field_var,
|
||||
loc_expr: Box::new(Loc::at_zero(Expr::Var(record_symbol))),
|
||||
loc_expr: Box::new(Loc::at_zero(Expr::Var(record_symbol, record_var))),
|
||||
field,
|
||||
};
|
||||
|
||||
|
@ -440,7 +447,10 @@ impl OpaqueWrapFunctionData {
|
|||
let body = Expr::OpaqueRef {
|
||||
opaque_var,
|
||||
name: opaque_name,
|
||||
argument: Box::new((argument_var, Loc::at_zero(Expr::Var(argument_symbol)))),
|
||||
argument: Box::new((
|
||||
argument_var,
|
||||
Loc::at_zero(Expr::Var(argument_symbol, argument_var)),
|
||||
)),
|
||||
specialized_def_type: Box::new(specialized_def_type),
|
||||
type_arguments,
|
||||
lambda_set_variables,
|
||||
|
@ -592,7 +602,7 @@ pub fn canonicalize_expr<'a>(
|
|||
} => {
|
||||
let (can_update, update_out) =
|
||||
canonicalize_expr(env, var_store, scope, loc_update.region, &loc_update.value);
|
||||
if let Var(symbol) = &can_update.value {
|
||||
if let Var(symbol, _) = &can_update.value {
|
||||
match canonicalize_fields(env, var_store, scope, region, fields.items) {
|
||||
Ok((can_fields, mut output)) => {
|
||||
output.references.union_mut(&update_out.references);
|
||||
|
@ -765,7 +775,7 @@ pub fn canonicalize_expr<'a>(
|
|||
output.tail_call = None;
|
||||
|
||||
let expr = match fn_expr.value {
|
||||
Var(symbol) => {
|
||||
Var(symbol, _) => {
|
||||
output.references.insert_call(symbol);
|
||||
|
||||
// we're tail-calling a symbol by name, check if it's the tail-callable symbol
|
||||
|
@ -994,7 +1004,7 @@ pub fn canonicalize_expr<'a>(
|
|||
|
||||
// Get all the lookups that were referenced in the condition,
|
||||
// so we can print their values later.
|
||||
let lookups_in_cond = get_lookup_symbols(&loc_condition.value, var_store);
|
||||
let lookups_in_cond = get_lookup_symbols(&loc_condition.value);
|
||||
|
||||
let (loc_continuation, output2) = canonicalize_expr(
|
||||
env,
|
||||
|
@ -1600,7 +1610,7 @@ fn canonicalize_var_lookup(
|
|||
var_store.fresh(),
|
||||
)
|
||||
} else {
|
||||
Var(symbol)
|
||||
Var(symbol, var_store.fresh())
|
||||
}
|
||||
}
|
||||
Err(problem) => {
|
||||
|
@ -1623,7 +1633,7 @@ fn canonicalize_var_lookup(
|
|||
var_store.fresh(),
|
||||
)
|
||||
} else {
|
||||
Var(symbol)
|
||||
Var(symbol, var_store.fresh())
|
||||
}
|
||||
}
|
||||
Err(problem) => {
|
||||
|
@ -1657,7 +1667,7 @@ pub fn inline_calls(var_store: &mut VarStore, scope: &mut Scope, expr: Expr) ->
|
|||
| other @ EmptyRecord
|
||||
| other @ Accessor { .. }
|
||||
| other @ Update { .. }
|
||||
| other @ Var(_)
|
||||
| other @ Var(..)
|
||||
| other @ AbilityMember(..)
|
||||
| other @ RunLowLevel { .. }
|
||||
| other @ TypedHole { .. }
|
||||
|
@ -1960,67 +1970,71 @@ pub fn inline_calls(var_store: &mut VarStore, scope: &mut Scope, expr: Expr) ->
|
|||
let (fn_var, loc_expr, closure_var, expr_var) = *boxed_tuple;
|
||||
|
||||
match loc_expr.value {
|
||||
Var(symbol) if symbol.is_builtin() => match builtin_defs_map(symbol, var_store) {
|
||||
Some(Def {
|
||||
loc_expr:
|
||||
Loc {
|
||||
value:
|
||||
Closure(ClosureData {
|
||||
recursive,
|
||||
arguments: params,
|
||||
loc_body: boxed_body,
|
||||
..
|
||||
}),
|
||||
..
|
||||
},
|
||||
..
|
||||
}) => {
|
||||
debug_assert_eq!(recursive, Recursive::NotRecursive);
|
||||
Var(symbol, _) if symbol.is_builtin() => {
|
||||
match builtin_defs_map(symbol, var_store) {
|
||||
Some(Def {
|
||||
loc_expr:
|
||||
Loc {
|
||||
value:
|
||||
Closure(ClosureData {
|
||||
recursive,
|
||||
arguments: params,
|
||||
loc_body: 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());
|
||||
// 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 = *boxed_body;
|
||||
// Start with the function's body as the answer.
|
||||
let mut loc_answer = *boxed_body;
|
||||
|
||||
// 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, _exhaustive_mark, 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();
|
||||
// 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, _exhaustive_mark, 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();
|
||||
|
||||
let def = Def {
|
||||
loc_pattern,
|
||||
loc_expr,
|
||||
expr_var,
|
||||
pattern_vars,
|
||||
annotation: None,
|
||||
};
|
||||
let def = Def {
|
||||
loc_pattern,
|
||||
loc_expr,
|
||||
expr_var,
|
||||
pattern_vars,
|
||||
annotation: None,
|
||||
};
|
||||
|
||||
loc_answer = Loc {
|
||||
region: Region::zero(),
|
||||
value: LetNonRec(Box::new(def), Box::new(loc_answer)),
|
||||
};
|
||||
loc_answer = Loc {
|
||||
region: Region::zero(),
|
||||
value: LetNonRec(Box::new(def), Box::new(loc_answer)),
|
||||
};
|
||||
}
|
||||
|
||||
loc_answer.value
|
||||
}
|
||||
Some(_) => {
|
||||
unreachable!("Tried to inline a non-function");
|
||||
}
|
||||
None => {
|
||||
unreachable!(
|
||||
"Tried to inline a builtin that wasn't registered: {:?}",
|
||||
symbol
|
||||
);
|
||||
}
|
||||
|
||||
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(
|
||||
|
@ -2172,7 +2186,10 @@ fn desugar_str_segments(var_store: &mut VarStore, segments: Vec<StrSegment>) ->
|
|||
Interpolation(loc_interpolated_expr) => loc_interpolated_expr,
|
||||
};
|
||||
|
||||
let fn_expr = Loc::at(Region::zero(), Expr::Var(Symbol::STR_CONCAT));
|
||||
let fn_expr = Loc::at(
|
||||
Region::zero(),
|
||||
Expr::Var(Symbol::STR_CONCAT, var_store.fresh()),
|
||||
);
|
||||
let expr = Expr::Call(
|
||||
Box::new((
|
||||
var_store.fresh(),
|
||||
|
@ -2531,7 +2548,7 @@ impl Declarations {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn expects(&self) -> VecMap<Region, Vec<(Symbol, Variable)>> {
|
||||
pub fn expects(&self) -> VecMap<Region, Vec<ExpectLookup>> {
|
||||
let mut collector = ExpectCollector {
|
||||
expects: VecMap::default(),
|
||||
};
|
||||
|
@ -2615,16 +2632,34 @@ pub struct DestructureDef {
|
|||
pub pattern_vars: VecMap<Symbol, Variable>,
|
||||
}
|
||||
|
||||
fn get_lookup_symbols(expr: &Expr, var_store: &mut VarStore) -> Vec<(Symbol, Variable)> {
|
||||
fn get_lookup_symbols(expr: &Expr) -> Vec<ExpectLookup> {
|
||||
let mut stack: Vec<&Expr> = vec![expr];
|
||||
let mut symbols = Vec::new();
|
||||
let mut lookups: Vec<ExpectLookup> = Vec::new();
|
||||
|
||||
while let Some(expr) = stack.pop() {
|
||||
match expr {
|
||||
Expr::Var(symbol) | Expr::Update { symbol, .. } | Expr::AbilityMember(symbol, _, _) => {
|
||||
Expr::Var(symbol, var)
|
||||
| Expr::Update {
|
||||
symbol,
|
||||
record_var: var,
|
||||
..
|
||||
} => {
|
||||
// Don't introduce duplicates, or make unused variables
|
||||
if !symbols.iter().any(|(sym, _)| sym == symbol) {
|
||||
symbols.push((*symbol, var_store.fresh()));
|
||||
if !lookups.iter().any(|l| l.symbol == *symbol) {
|
||||
lookups.push(ExpectLookup {
|
||||
symbol: *symbol,
|
||||
var: *var,
|
||||
ability_info: None,
|
||||
});
|
||||
}
|
||||
}
|
||||
Expr::AbilityMember(symbol, spec_id, var) => {
|
||||
if !lookups.iter().any(|l| l.symbol == *symbol) {
|
||||
lookups.push(ExpectLookup {
|
||||
symbol: *symbol,
|
||||
var: *var,
|
||||
ability_info: *spec_id,
|
||||
});
|
||||
}
|
||||
}
|
||||
Expr::List { loc_elems, .. } => {
|
||||
|
@ -2665,7 +2700,7 @@ fn get_lookup_symbols(expr: &Expr, var_store: &mut VarStore) -> Vec<(Symbol, Var
|
|||
stack.reserve(1 + args.len());
|
||||
|
||||
match &boxed_expr.1.value {
|
||||
Expr::Var(_) => {
|
||||
Expr::Var(_, _) => {
|
||||
// do nothing
|
||||
}
|
||||
function_expr => {
|
||||
|
@ -2721,7 +2756,7 @@ fn get_lookup_symbols(expr: &Expr, var_store: &mut VarStore) -> Vec<(Symbol, Var
|
|||
}
|
||||
}
|
||||
|
||||
symbols
|
||||
lookups
|
||||
}
|
||||
|
||||
/// Here we transform
|
||||
|
@ -2768,14 +2803,22 @@ fn toplevel_expect_to_inline_expect_help(mut loc_expr: Loc<Expr>, has_effects: b
|
|||
loop {
|
||||
match loc_expr.value {
|
||||
Expr::LetNonRec(boxed_def, remainder) => {
|
||||
lookups_in_cond.extend(boxed_def.pattern_vars.iter().map(|(a, b)| (*a, *b)));
|
||||
lookups_in_cond.extend(boxed_def.pattern_vars.iter().map(|(a, b)| ExpectLookup {
|
||||
symbol: *a,
|
||||
var: *b,
|
||||
ability_info: None,
|
||||
}));
|
||||
|
||||
stack.push(StoredDef::NonRecursive(loc_expr.region, boxed_def));
|
||||
loc_expr = *remainder;
|
||||
}
|
||||
Expr::LetRec(defs, remainder, mark) => {
|
||||
for def in &defs {
|
||||
lookups_in_cond.extend(def.pattern_vars.iter().map(|(a, b)| (*a, *b)));
|
||||
lookups_in_cond.extend(def.pattern_vars.iter().map(|(a, b)| ExpectLookup {
|
||||
symbol: *a,
|
||||
var: *b,
|
||||
ability_info: None,
|
||||
}));
|
||||
}
|
||||
|
||||
stack.push(StoredDef::Recursive(loc_expr.region, defs, mark));
|
||||
|
@ -2818,7 +2861,7 @@ fn toplevel_expect_to_inline_expect_help(mut loc_expr: Loc<Expr>, has_effects: b
|
|||
}
|
||||
|
||||
struct ExpectCollector {
|
||||
expects: VecMap<Region, Vec<(Symbol, Variable)>>,
|
||||
expects: VecMap<Region, Vec<ExpectLookup>>,
|
||||
}
|
||||
|
||||
impl crate::traverse::Visitor for ExpectCollector {
|
||||
|
|
|
@ -3,7 +3,7 @@ use crate::annotation::canonicalize_annotation;
|
|||
use crate::def::{canonicalize_defs, Def};
|
||||
use crate::effect_module::HostedGeneratedFunctions;
|
||||
use crate::env::Env;
|
||||
use crate::expr::{ClosureData, Declarations, Expr, Output, PendingDerives};
|
||||
use crate::expr::{ClosureData, Declarations, ExpectLookup, Expr, Output, PendingDerives};
|
||||
use crate::pattern::{BindingsFromPattern, Pattern};
|
||||
use crate::scope::Scope;
|
||||
use bumpalo::Bump;
|
||||
|
@ -130,7 +130,7 @@ pub struct Module {
|
|||
pub aliases: MutMap<Symbol, (bool, Alias)>,
|
||||
pub rigid_variables: RigidVariables,
|
||||
pub abilities_store: PendingAbilitiesStore,
|
||||
pub loc_expects: VecMap<Region, Vec<(Symbol, Variable)>>,
|
||||
pub loc_expects: VecMap<Region, Vec<ExpectLookup>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
|
@ -152,7 +152,7 @@ pub struct ModuleOutput {
|
|||
pub symbols_from_requires: Vec<(Loc<Symbol>, Loc<Type>)>,
|
||||
pub pending_derives: PendingDerives,
|
||||
pub scope: Scope,
|
||||
pub loc_expects: VecMap<Region, Vec<(Symbol, Variable)>>,
|
||||
pub loc_expects: VecMap<Region, Vec<ExpectLookup>>,
|
||||
}
|
||||
|
||||
fn validate_generate_with<'a>(
|
||||
|
@ -1040,7 +1040,7 @@ fn fix_values_captured_in_closure_expr(
|
|||
| Float(..)
|
||||
| Str(_)
|
||||
| SingleQuote(..)
|
||||
| Var(_)
|
||||
| Var(..)
|
||||
| AbilityMember(..)
|
||||
| EmptyRecord
|
||||
| TypedHole { .. }
|
||||
|
|
|
@ -13,8 +13,8 @@ use roc_can::expected::Expected::{self, *};
|
|||
use roc_can::expected::PExpected;
|
||||
use roc_can::expr::Expr::{self, *};
|
||||
use roc_can::expr::{
|
||||
AccessorData, AnnotatedMark, ClosureData, DeclarationTag, Declarations, DestructureDef, Field,
|
||||
FunctionDef, OpaqueWrapFunctionData, WhenBranch,
|
||||
AccessorData, AnnotatedMark, ClosureData, DeclarationTag, Declarations, DestructureDef,
|
||||
ExpectLookup, Field, FunctionDef, OpaqueWrapFunctionData, WhenBranch,
|
||||
};
|
||||
use roc_can::pattern::Pattern;
|
||||
use roc_can::traverse::symbols_introduced_from_pattern;
|
||||
|
@ -351,7 +351,7 @@ pub fn constrain_expr(
|
|||
let (fn_var, loc_fn, closure_var, ret_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 {
|
||||
let opt_symbol = if let Var(symbol, _) | AbilityMember(symbol, _, _) = loc_fn.value {
|
||||
Some(symbol)
|
||||
} else {
|
||||
None
|
||||
|
@ -425,9 +425,13 @@ pub fn constrain_expr(
|
|||
let and_constraint = constraints.and_constraint(and_cons);
|
||||
constraints.exists(vars, and_constraint)
|
||||
}
|
||||
Var(symbol) => {
|
||||
// make lookup constraint to lookup this symbol's type in the environment
|
||||
constraints.lookup(*symbol, expected, region)
|
||||
Var(symbol, variable) => {
|
||||
// Save the expectation in the variable, then lookup the symbol's type in the environment
|
||||
let store_expected =
|
||||
constraints.store(expected.get_type_ref().clone(), *variable, file!(), line!());
|
||||
let lookup_constr =
|
||||
constraints.lookup(*symbol, expected.replace(Type::Variable(*variable)), region);
|
||||
constraints.and_constraint([store_expected, lookup_constr])
|
||||
}
|
||||
&AbilityMember(symbol, specialization_id, specialization_var) => {
|
||||
// Save the expectation in the `specialization_var` so we know what to specialize, then
|
||||
|
@ -515,7 +519,12 @@ pub fn constrain_expr(
|
|||
|
||||
let mut vars = Vec::with_capacity(lookups_in_cond.len());
|
||||
|
||||
for (symbol, var) in lookups_in_cond.iter() {
|
||||
for ExpectLookup {
|
||||
symbol,
|
||||
var,
|
||||
ability_info: _,
|
||||
} in lookups_in_cond.iter()
|
||||
{
|
||||
vars.push(*var);
|
||||
|
||||
all_constraints.push(constraints.lookup(
|
||||
|
@ -562,7 +571,12 @@ pub fn constrain_expr(
|
|||
|
||||
let mut vars = Vec::with_capacity(lookups_in_cond.len());
|
||||
|
||||
for (symbol, var) in lookups_in_cond.iter() {
|
||||
for ExpectLookup {
|
||||
symbol,
|
||||
var,
|
||||
ability_info: _,
|
||||
} in lookups_in_cond.iter()
|
||||
{
|
||||
vars.push(*var);
|
||||
|
||||
all_constraints.push(constraints.lookup(
|
||||
|
|
|
@ -357,7 +357,7 @@ fn decoder_record_step_field(
|
|||
name: "Ok".into(),
|
||||
arguments: vec![(
|
||||
field_var,
|
||||
Loc::at_zero(Expr::Var(ok_val_symbol)),
|
||||
Loc::at_zero(Expr::Var(ok_val_symbol, field_var)),
|
||||
)],
|
||||
})),
|
||||
},
|
||||
|
@ -417,7 +417,7 @@ fn decoder_record_step_field(
|
|||
name: "Err".into(),
|
||||
arguments: vec![(
|
||||
decode_err_var,
|
||||
Loc::at_zero(Expr::Var(err_val_symbol)),
|
||||
Loc::at_zero(Expr::Var(err_val_symbol, decode_err_var)),
|
||||
)],
|
||||
}),
|
||||
guard: None,
|
||||
|
@ -433,7 +433,7 @@ fn decoder_record_step_field(
|
|||
record_var: rec_var,
|
||||
ext_var: env.new_ext_var(ExtensionKind::Record),
|
||||
field_var: rec_dot_result,
|
||||
loc_expr: Box::new(Loc::at_zero(Expr::Var(rec_symbol))),
|
||||
loc_expr: Box::new(Loc::at_zero(Expr::Var(rec_symbol, rec_var))),
|
||||
field: "result".into(),
|
||||
})),
|
||||
cond_var: rec_dot_result,
|
||||
|
@ -462,7 +462,7 @@ fn decoder_record_step_field(
|
|||
record_var: rec_var,
|
||||
ext_var: env.new_ext_var(ExtensionKind::Record),
|
||||
field_var: Variable::LIST_U8,
|
||||
loc_expr: Box::new(Loc::at_zero(Expr::Var(rec_symbol))),
|
||||
loc_expr: Box::new(Loc::at_zero(Expr::Var(rec_symbol, rec_var))),
|
||||
field: "rest".into(),
|
||||
})),
|
||||
},
|
||||
|
@ -499,12 +499,15 @@ fn decoder_record_step_field(
|
|||
let condition_expr = Expr::Call(
|
||||
Box::new((
|
||||
this_decode_with_var,
|
||||
Loc::at_zero(Expr::Var(Symbol::DECODE_DECODE_WITH)),
|
||||
Loc::at_zero(Expr::Var(Symbol::DECODE_DECODE_WITH, this_decode_with_var)),
|
||||
lambda_set_var,
|
||||
rec_var,
|
||||
)),
|
||||
vec![
|
||||
(Variable::LIST_U8, Loc::at_zero(Expr::Var(bytes_arg_symbol))),
|
||||
(
|
||||
Variable::LIST_U8,
|
||||
Loc::at_zero(Expr::Var(bytes_arg_symbol, Variable::LIST_U8)),
|
||||
),
|
||||
(
|
||||
decoder_var,
|
||||
Loc::at_zero(Expr::AbilityMember(
|
||||
|
@ -513,7 +516,10 @@ fn decoder_record_step_field(
|
|||
decoder_var,
|
||||
)),
|
||||
),
|
||||
(fmt_arg_var, Loc::at_zero(Expr::Var(fmt_arg_symbol))),
|
||||
(
|
||||
fmt_arg_var,
|
||||
Loc::at_zero(Expr::Var(fmt_arg_symbol, fmt_arg_var)),
|
||||
),
|
||||
],
|
||||
CalledVia::Space,
|
||||
);
|
||||
|
@ -600,7 +606,7 @@ fn decoder_record_step_field(
|
|||
Expr::Call(
|
||||
Box::new((
|
||||
this_decode_custom_var,
|
||||
Loc::at_zero(Expr::Var(Symbol::DECODE_CUSTOM)),
|
||||
Loc::at_zero(Expr::Var(Symbol::DECODE_CUSTOM, this_decode_custom_var)),
|
||||
decode_custom_closure_var,
|
||||
decode_custom_ret_var,
|
||||
)),
|
||||
|
@ -676,7 +682,7 @@ fn decoder_record_step_field(
|
|||
|
||||
// when field is
|
||||
let body = Expr::When {
|
||||
loc_cond: Box::new(Loc::at_zero(Expr::Var(field_arg_symbol))),
|
||||
loc_cond: Box::new(Loc::at_zero(Expr::Var(field_arg_symbol, Variable::STR))),
|
||||
cond_var: Variable::STR,
|
||||
expr_var: keep_or_skip_var,
|
||||
region: Region::zero(),
|
||||
|
@ -764,7 +770,7 @@ fn decoder_record_finalizer(
|
|||
|
||||
pattern_symbols.push(symbol);
|
||||
|
||||
let field_expr = Expr::Var(symbol);
|
||||
let field_expr = Expr::Var(symbol, field_var);
|
||||
let field = Field {
|
||||
var: field_var,
|
||||
region: Region::zero(),
|
||||
|
@ -827,7 +833,7 @@ fn decoder_record_finalizer(
|
|||
record_var: state_record_var,
|
||||
ext_var: env.new_ext_var(ExtensionKind::Record),
|
||||
field_var: result_field_var,
|
||||
loc_expr: Box::new(Loc::at_zero(Expr::Var(state_arg_symbol))),
|
||||
loc_expr: Box::new(Loc::at_zero(Expr::Var(state_arg_symbol, state_record_var))),
|
||||
field: field_name.clone(),
|
||||
};
|
||||
|
||||
|
@ -1126,7 +1132,7 @@ fn wrap_in_decode_custom_decode_with(
|
|||
// ~ bytes, Decoder (List elem) fmt, fmt -> DecoderResult (List val)
|
||||
env.unify(decode_with_type, this_decode_with_fn_var);
|
||||
|
||||
let decode_with_var = Var(Symbol::DECODE_DECODE_WITH);
|
||||
let decode_with_var = Var(Symbol::DECODE_DECODE_WITH, this_decode_with_fn_var);
|
||||
let decode_with_fn = Box::new((
|
||||
this_decode_with_fn_var,
|
||||
Loc::at_zero(decode_with_var),
|
||||
|
@ -1137,9 +1143,9 @@ fn wrap_in_decode_custom_decode_with(
|
|||
decode_with_fn,
|
||||
vec![
|
||||
// bytes inner_decoder fmt
|
||||
(bytes_var, Loc::at_zero(Var(bytes_sym))),
|
||||
(bytes_var, Loc::at_zero(Var(bytes_sym, bytes_var))),
|
||||
(inner_decoder_var, Loc::at_zero(inner_decoder)),
|
||||
(fmt_var, Loc::at_zero(Var(fmt_sym))),
|
||||
(fmt_var, Loc::at_zero(Var(fmt_sym, fmt_var))),
|
||||
],
|
||||
CalledVia::Space,
|
||||
);
|
||||
|
@ -1231,7 +1237,7 @@ fn wrap_in_decode_custom_decode_with(
|
|||
// ~ (List U8, fmt -> DecodeResult (List elem)) -> Decoder (List elem) fmt
|
||||
env.unify(decode_custom_type, this_decode_custom_fn_var);
|
||||
|
||||
let decode_custom_var = Var(Symbol::DECODE_CUSTOM);
|
||||
let decode_custom_var = Var(Symbol::DECODE_CUSTOM, this_decode_custom_fn_var);
|
||||
let decode_custom_fn = Box::new((
|
||||
this_decode_custom_fn_var,
|
||||
Loc::at_zero(decode_custom_var),
|
||||
|
|
|
@ -134,7 +134,7 @@ fn to_encoder_list(env: &mut Env<'_>, fn_name: Symbol) -> (Expr, Variable) {
|
|||
// toEncoder elem
|
||||
let to_encoder_call = Call(
|
||||
to_encoder_fn,
|
||||
vec![(elem_var, Loc::at_zero(Var(elem_sym)))],
|
||||
vec![(elem_var, Loc::at_zero(Var(elem_sym, elem_var)))],
|
||||
CalledVia::Space,
|
||||
);
|
||||
|
||||
|
@ -217,7 +217,7 @@ fn to_encoder_list(env: &mut Env<'_>, fn_name: Symbol) -> (Expr, Variable) {
|
|||
let encode_list_call = Call(
|
||||
encode_list_fn,
|
||||
vec![
|
||||
(list_var, Loc::at_zero(Var(lst_sym))),
|
||||
(list_var, Loc::at_zero(Var(lst_sym, list_var))),
|
||||
(to_elem_encoder_fn_var, Loc::at_zero(to_elem_encoder)),
|
||||
],
|
||||
CalledVia::Space,
|
||||
|
@ -314,7 +314,10 @@ fn to_encoder_record(
|
|||
record_var,
|
||||
ext_var: env.subs.fresh_unnamed_flex_var(),
|
||||
field_var,
|
||||
loc_expr: Box::new(Loc::at_zero(Var(rcd_sym))),
|
||||
loc_expr: Box::new(Loc::at_zero(Var(
|
||||
rcd_sym,
|
||||
env.subs.fresh_unnamed_flex_var(),
|
||||
))),
|
||||
field: field_name,
|
||||
};
|
||||
|
||||
|
@ -572,7 +575,7 @@ fn to_encoder_tag_union(
|
|||
// toEncoder rcd.a
|
||||
let to_encoder_call = Call(
|
||||
to_encoder_fn,
|
||||
vec![(sym_var, Loc::at_zero(Var(sym)))],
|
||||
vec![(sym_var, Loc::at_zero(Var(sym, sym_var)))],
|
||||
CalledVia::Space,
|
||||
);
|
||||
|
||||
|
@ -662,7 +665,7 @@ fn to_encoder_tag_union(
|
|||
// A v1 v2 -> Encode.tag "A" [ Encode.toEncoder v1, Encode.toEncoder v2 ]
|
||||
// B v3 -> Encode.tag "B" [ Encode.toEncoder v3 ]
|
||||
let when_branches = When {
|
||||
loc_cond: Box::new(Loc::at_zero(Var(tag_sym))),
|
||||
loc_cond: Box::new(Loc::at_zero(Var(tag_sym, tag_union_var))),
|
||||
cond_var: tag_union_var,
|
||||
expr_var: whole_tag_encoders_var,
|
||||
region: Region::zero(),
|
||||
|
@ -778,7 +781,7 @@ fn wrap_in_encode_custom(
|
|||
// Encode.appendWith : List U8, encoder_var, fmt -[appendWith]-> List U8 | fmt has EncoderFormatting
|
||||
let append_with_fn = Box::new((
|
||||
this_append_with_fn_var,
|
||||
Loc::at_zero(Var(Symbol::ENCODE_APPEND_WITH)),
|
||||
Loc::at_zero(Var(Symbol::ENCODE_APPEND_WITH, this_append_with_fn_var)),
|
||||
this_append_with_clos_var,
|
||||
Variable::LIST_U8,
|
||||
));
|
||||
|
@ -788,11 +791,11 @@ fn wrap_in_encode_custom(
|
|||
append_with_fn,
|
||||
vec![
|
||||
// (bytes_var, bytes)
|
||||
(bytes_var, Loc::at_zero(Var(bytes_sym))),
|
||||
(bytes_var, Loc::at_zero(Var(bytes_sym, bytes_var))),
|
||||
// (encoder_var, encoder)
|
||||
(encoder_var, Loc::at_zero(encoder)),
|
||||
// (fmt, fmt_var)
|
||||
(fmt_var, Loc::at_zero(Var(fmt_sym))),
|
||||
(fmt_var, Loc::at_zero(Var(fmt_sym, fmt_var))),
|
||||
],
|
||||
CalledVia::Space,
|
||||
);
|
||||
|
@ -869,7 +872,7 @@ fn wrap_in_encode_custom(
|
|||
// Encode.custom : (List U8, fmt -> List U8) -> Encoder fmt | fmt has EncoderFormatting
|
||||
let custom_fn = Box::new((
|
||||
this_custom_fn_var,
|
||||
Loc::at_zero(Var(Symbol::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
|
||||
));
|
||||
|
|
|
@ -90,7 +90,7 @@ fn hash_record(env: &mut Env<'_>, fn_name: Symbol, fields: Vec<Lowercase>) -> (V
|
|||
let hasher_var = synth_var(env.subs, Content::FlexAbleVar(None, Symbol::HASH_HASHER));
|
||||
|
||||
let (body_var, body) = record_fields.iter_all().fold(
|
||||
(hasher_var, Expr::Var(hasher_sym)),
|
||||
(hasher_var, Expr::Var(hasher_sym, hasher_var)),
|
||||
|total_hasher, (field_name, field_var, _)| {
|
||||
let field_name = env.subs[field_name].clone();
|
||||
let field_var = env.subs[field_var];
|
||||
|
@ -99,7 +99,10 @@ fn hash_record(env: &mut Env<'_>, fn_name: Symbol, fields: Vec<Lowercase>) -> (V
|
|||
record_var,
|
||||
field_var,
|
||||
ext_var: env.subs.fresh_unnamed_flex_var(),
|
||||
loc_expr: Box::new(Loc::at_zero(Expr::Var(rcd_sym))),
|
||||
loc_expr: Box::new(Loc::at_zero(Expr::Var(
|
||||
rcd_sym,
|
||||
env.subs.fresh_unnamed_flex_var(),
|
||||
))),
|
||||
field: field_name,
|
||||
};
|
||||
|
||||
|
@ -215,7 +218,7 @@ fn hash_tag_union(
|
|||
let (discr_hasher_var, disc_hasher_expr) = call_hash_ability_member(
|
||||
env,
|
||||
hash_discr_member,
|
||||
(hasher_var, Expr::Var(hasher_sym)),
|
||||
(hasher_var, Expr::Var(hasher_sym, hasher_var)),
|
||||
(
|
||||
discr_num_var,
|
||||
Expr::Int(
|
||||
|
@ -232,7 +235,11 @@ fn hash_tag_union(
|
|||
let (body_var, body_expr) = (payload_vars.into_iter()).zip(payload_syms).fold(
|
||||
(discr_hasher_var, disc_hasher_expr),
|
||||
|total_hasher, (payload_var, payload_sym)| {
|
||||
call_hash_hash(env, total_hasher, (payload_var, Expr::Var(payload_sym)))
|
||||
call_hash_hash(
|
||||
env,
|
||||
total_hasher,
|
||||
(payload_var, Expr::Var(payload_sym, payload_var)),
|
||||
)
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -251,7 +258,7 @@ fn hash_tag_union(
|
|||
// ...
|
||||
let when_var = whole_hasher_var;
|
||||
let when_expr = Expr::When {
|
||||
loc_cond: Box::new(Loc::at_zero(Expr::Var(union_sym))),
|
||||
loc_cond: Box::new(Loc::at_zero(Expr::Var(union_sym, union_var))),
|
||||
cond_var: union_var,
|
||||
expr_var: when_var,
|
||||
region: Region::zero(),
|
||||
|
@ -338,9 +345,13 @@ fn hash_newtype_tag_union(
|
|||
|
||||
// Fold up `Hash.hash (... (Hash.hash discrHasher x11) ...) x1n`
|
||||
let (body_var, body_expr) = (payload_vars.into_iter()).zip(payload_syms).fold(
|
||||
(hasher_var, Expr::Var(hasher_sym)),
|
||||
(hasher_var, Expr::Var(hasher_sym, hasher_var)),
|
||||
|total_hasher, (payload_var, payload_sym)| {
|
||||
call_hash_hash(env, total_hasher, (payload_var, Expr::Var(payload_sym)))
|
||||
call_hash_hash(
|
||||
env,
|
||||
total_hasher,
|
||||
(payload_var, Expr::Var(payload_sym, payload_var)),
|
||||
)
|
||||
},
|
||||
);
|
||||
|
||||
|
|
|
@ -7,8 +7,8 @@ use parking_lot::Mutex;
|
|||
use roc_builtins::roc::module_source;
|
||||
use roc_can::abilities::{AbilitiesStore, PendingAbilitiesStore, ResolvedImpl};
|
||||
use roc_can::constraint::{Constraint as ConstraintSoa, Constraints};
|
||||
use roc_can::expr::Declarations;
|
||||
use roc_can::expr::PendingDerives;
|
||||
use roc_can::expr::{Declarations, ExpectLookup};
|
||||
use roc_can::module::{
|
||||
canonicalize_module_defs, ExposedByModule, ExposedForModule, ExposedModuleTypes, Module,
|
||||
ResolvedImplementations, TypeState,
|
||||
|
@ -719,7 +719,7 @@ pub enum EntryPoint<'a> {
|
|||
pub struct Expectations {
|
||||
pub subs: roc_types::subs::Subs,
|
||||
pub path: PathBuf,
|
||||
pub expectations: VecMap<Region, Vec<(Symbol, Variable)>>,
|
||||
pub expectations: VecMap<Region, Vec<ExpectLookup>>,
|
||||
pub ident_ids: IdentIds,
|
||||
}
|
||||
|
||||
|
@ -763,7 +763,7 @@ struct ParsedModule<'a> {
|
|||
header_for: HeaderFor<'a>,
|
||||
}
|
||||
|
||||
type LocExpects = VecMap<Region, Vec<(Symbol, Variable)>>;
|
||||
type LocExpects = VecMap<Region, Vec<ExpectLookup>>;
|
||||
|
||||
/// A message sent out _from_ a worker thread,
|
||||
/// representing a result of work done, or a request for further work
|
||||
|
|
|
@ -9,7 +9,7 @@ use bumpalo::collections::{CollectIn, Vec};
|
|||
use bumpalo::Bump;
|
||||
use roc_builtins::bitcode::{FloatWidth, IntWidth};
|
||||
use roc_can::abilities::SpecializationId;
|
||||
use roc_can::expr::{AnnotatedMark, ClosureData, IntValue};
|
||||
use roc_can::expr::{AnnotatedMark, ClosureData, ExpectLookup, IntValue};
|
||||
use roc_can::module::ExposedByModule;
|
||||
use roc_collections::all::{default_hasher, BumpMap, BumpMapDefault, MutMap};
|
||||
use roc_collections::VecMap;
|
||||
|
@ -2376,7 +2376,7 @@ fn from_can_let<'a>(
|
|||
|
||||
lower_rest!(variable, cont.value)
|
||||
}
|
||||
Var(original) | AbilityMember(original, _, _) => {
|
||||
Var(original, _) | AbilityMember(original, _, _) => {
|
||||
// a variable is aliased, e.g.
|
||||
//
|
||||
// foo = bar
|
||||
|
@ -2605,7 +2605,7 @@ fn from_can_let<'a>(
|
|||
}
|
||||
|
||||
match def.loc_expr.value {
|
||||
roc_can::expr::Expr::Var(outer_symbol) if !procs.is_module_thunk(outer_symbol) => {
|
||||
roc_can::expr::Expr::Var(outer_symbol, _) if !procs.is_module_thunk(outer_symbol) => {
|
||||
store_pattern(env, procs, layout_cache, &mono_pattern, outer_symbol, stmt)
|
||||
}
|
||||
_ => {
|
||||
|
@ -2747,7 +2747,7 @@ fn pattern_to_when<'a>(
|
|||
cond_var: pattern_var,
|
||||
expr_var: body_var,
|
||||
region: Region::zero(),
|
||||
loc_cond: Box::new(Loc::at_zero(Var(symbol))),
|
||||
loc_cond: Box::new(Loc::at_zero(Var(symbol, pattern_var))),
|
||||
branches: vec![WhenBranch {
|
||||
patterns: vec![WhenBranchPattern {
|
||||
pattern,
|
||||
|
@ -4074,11 +4074,14 @@ pub fn with_hole<'a>(
|
|||
hole,
|
||||
)
|
||||
}
|
||||
Var(mut symbol) => {
|
||||
Var(mut symbol, _) => {
|
||||
// If this symbol is a raw value, find the real name we gave to its specialized usage.
|
||||
if let ReuseSymbol::Value(_symbol) =
|
||||
can_reuse_symbol(env, procs, &roc_can::expr::Expr::Var(symbol), variable)
|
||||
{
|
||||
if let ReuseSymbol::Value(_symbol) = can_reuse_symbol(
|
||||
env,
|
||||
procs,
|
||||
&roc_can::expr::Expr::Var(symbol, variable),
|
||||
variable,
|
||||
) {
|
||||
let real_symbol =
|
||||
procs
|
||||
.symbol_specializations
|
||||
|
@ -5046,7 +5049,7 @@ pub fn with_hole<'a>(
|
|||
};
|
||||
|
||||
match loc_expr.value {
|
||||
roc_can::expr::Expr::Var(proc_name) if is_known(proc_name) => {
|
||||
roc_can::expr::Expr::Var(proc_name, _) if is_known(proc_name) => {
|
||||
// a call by a known name
|
||||
call_by_name(
|
||||
env,
|
||||
|
@ -6010,7 +6013,7 @@ fn tag_union_to_function<'a>(
|
|||
|
||||
let loc_pattern = Loc::at_zero(roc_can::pattern::Pattern::Identifier(arg_symbol));
|
||||
|
||||
let loc_expr = Loc::at_zero(roc_can::expr::Expr::Var(arg_symbol));
|
||||
let loc_expr = Loc::at_zero(roc_can::expr::Expr::Var(arg_symbol, arg_var));
|
||||
|
||||
loc_pattern_args.push((arg_var, AnnotatedMark::known_exhaustive(), loc_pattern));
|
||||
loc_expr_args.push((arg_var, loc_expr));
|
||||
|
@ -6347,11 +6350,25 @@ pub fn from_can<'a>(
|
|||
let rest = from_can(env, variable, loc_continuation.value, procs, layout_cache);
|
||||
let cond_symbol = env.unique_symbol();
|
||||
|
||||
let lookups = Vec::from_iter_in(lookups_in_cond.iter().map(|t| t.0), env.arena);
|
||||
|
||||
let mut lookups = Vec::with_capacity_in(lookups_in_cond.len(), env.arena);
|
||||
let mut layouts = Vec::with_capacity_in(lookups_in_cond.len(), env.arena);
|
||||
|
||||
for (_, var) in lookups_in_cond {
|
||||
for ExpectLookup {
|
||||
symbol,
|
||||
var,
|
||||
ability_info,
|
||||
} in lookups_in_cond
|
||||
{
|
||||
let symbol = match ability_info {
|
||||
Some(specialization_id) => late_resolve_ability_specialization(
|
||||
env,
|
||||
symbol,
|
||||
Some(specialization_id),
|
||||
var,
|
||||
),
|
||||
None => symbol,
|
||||
};
|
||||
lookups.push(symbol);
|
||||
let res_layout = layout_cache.from_var(env.arena, var, env.subs);
|
||||
let layout = return_on_layout_error!(env, res_layout, "Expect");
|
||||
layouts.push(layout);
|
||||
|
@ -6386,11 +6403,25 @@ pub fn from_can<'a>(
|
|||
let rest = from_can(env, variable, loc_continuation.value, procs, layout_cache);
|
||||
let cond_symbol = env.unique_symbol();
|
||||
|
||||
let lookups = Vec::from_iter_in(lookups_in_cond.iter().map(|t| t.0), env.arena);
|
||||
|
||||
let mut lookups = Vec::with_capacity_in(lookups_in_cond.len(), env.arena);
|
||||
let mut layouts = Vec::with_capacity_in(lookups_in_cond.len(), env.arena);
|
||||
|
||||
for (_, var) in lookups_in_cond {
|
||||
for ExpectLookup {
|
||||
symbol,
|
||||
var,
|
||||
ability_info,
|
||||
} in lookups_in_cond
|
||||
{
|
||||
let symbol = match ability_info {
|
||||
Some(specialization_id) => late_resolve_ability_specialization(
|
||||
env,
|
||||
symbol,
|
||||
Some(specialization_id),
|
||||
var,
|
||||
),
|
||||
None => symbol,
|
||||
};
|
||||
lookups.push(symbol);
|
||||
let res_layout = layout_cache.from_var(env.arena, var, env.subs);
|
||||
let layout = return_on_layout_error!(env, res_layout, "Expect");
|
||||
layouts.push(layout);
|
||||
|
@ -7513,7 +7544,7 @@ fn can_reuse_symbol<'a>(
|
|||
AbilityMember(member, specialization_id, _) => {
|
||||
late_resolve_ability_specialization(env, *member, *specialization_id, expr_var)
|
||||
}
|
||||
Var(symbol) => *symbol,
|
||||
Var(symbol, _) => *symbol,
|
||||
_ => return NotASymbol,
|
||||
};
|
||||
|
||||
|
|
|
@ -87,7 +87,7 @@ fn expr<'a>(c: &Ctx, p: EPrec, f: &'a Arena<'a>, e: &'a Expr) -> DocBuilder<'a,
|
|||
.append("]")
|
||||
.group(),
|
||||
),
|
||||
Var(sym) | AbilityMember(sym, _, _) => f.text(format!(
|
||||
Var(sym, _) | AbilityMember(sym, _, _) => f.text(format!(
|
||||
"{}.{}",
|
||||
sym.module_string(c.interns),
|
||||
sym.as_str(c.interns),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue