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
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -3959,6 +3959,7 @@ dependencies = [
|
||||||
"pretty_assertions",
|
"pretty_assertions",
|
||||||
"roc_build",
|
"roc_build",
|
||||||
"roc_builtins",
|
"roc_builtins",
|
||||||
|
"roc_can",
|
||||||
"roc_collections",
|
"roc_collections",
|
||||||
"roc_gen_llvm",
|
"roc_gen_llvm",
|
||||||
"roc_intern",
|
"roc_intern",
|
||||||
|
|
|
@ -247,7 +247,7 @@ fn lowlevel_1(symbol: Symbol, op: LowLevel, var_store: &mut VarStore) -> Def {
|
||||||
|
|
||||||
let body = RunLowLevel {
|
let body = RunLowLevel {
|
||||||
op,
|
op,
|
||||||
args: vec![(arg1_var, Var(Symbol::ARG_1))],
|
args: vec![(arg1_var, Var(Symbol::ARG_1, arg1_var))],
|
||||||
ret_var,
|
ret_var,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -268,8 +268,8 @@ fn lowlevel_2(symbol: Symbol, op: LowLevel, var_store: &mut VarStore) -> Def {
|
||||||
let body = RunLowLevel {
|
let body = RunLowLevel {
|
||||||
op,
|
op,
|
||||||
args: vec![
|
args: vec![
|
||||||
(arg1_var, Var(Symbol::ARG_1)),
|
(arg1_var, Var(Symbol::ARG_1, arg1_var)),
|
||||||
(arg2_var, Var(Symbol::ARG_2)),
|
(arg2_var, Var(Symbol::ARG_2, arg2_var)),
|
||||||
],
|
],
|
||||||
ret_var,
|
ret_var,
|
||||||
};
|
};
|
||||||
|
@ -292,9 +292,9 @@ fn lowlevel_3(symbol: Symbol, op: LowLevel, var_store: &mut VarStore) -> Def {
|
||||||
let body = RunLowLevel {
|
let body = RunLowLevel {
|
||||||
op,
|
op,
|
||||||
args: vec![
|
args: vec![
|
||||||
(arg1_var, Var(Symbol::ARG_1)),
|
(arg1_var, Var(Symbol::ARG_1, arg1_var)),
|
||||||
(arg2_var, Var(Symbol::ARG_2)),
|
(arg2_var, Var(Symbol::ARG_2, arg2_var)),
|
||||||
(arg3_var, Var(Symbol::ARG_3)),
|
(arg3_var, Var(Symbol::ARG_3, arg3_var)),
|
||||||
],
|
],
|
||||||
ret_var,
|
ret_var,
|
||||||
};
|
};
|
||||||
|
@ -322,10 +322,10 @@ fn lowlevel_4(symbol: Symbol, op: LowLevel, var_store: &mut VarStore) -> Def {
|
||||||
let body = RunLowLevel {
|
let body = RunLowLevel {
|
||||||
op,
|
op,
|
||||||
args: vec![
|
args: vec![
|
||||||
(arg1_var, Var(Symbol::ARG_1)),
|
(arg1_var, Var(Symbol::ARG_1, arg1_var)),
|
||||||
(arg2_var, Var(Symbol::ARG_2)),
|
(arg2_var, Var(Symbol::ARG_2, arg2_var)),
|
||||||
(arg3_var, Var(Symbol::ARG_3)),
|
(arg3_var, Var(Symbol::ARG_3, arg3_var)),
|
||||||
(arg4_var, Var(Symbol::ARG_4)),
|
(arg4_var, Var(Symbol::ARG_4, arg4_var)),
|
||||||
],
|
],
|
||||||
ret_var,
|
ret_var,
|
||||||
};
|
};
|
||||||
|
@ -355,11 +355,11 @@ fn lowlevel_5(symbol: Symbol, op: LowLevel, var_store: &mut VarStore) -> Def {
|
||||||
let body = RunLowLevel {
|
let body = RunLowLevel {
|
||||||
op,
|
op,
|
||||||
args: vec![
|
args: vec![
|
||||||
(arg1_var, Var(Symbol::ARG_1)),
|
(arg1_var, Var(Symbol::ARG_1, arg1_var)),
|
||||||
(arg2_var, Var(Symbol::ARG_2)),
|
(arg2_var, Var(Symbol::ARG_2, arg2_var)),
|
||||||
(arg3_var, Var(Symbol::ARG_3)),
|
(arg3_var, Var(Symbol::ARG_3, arg3_var)),
|
||||||
(arg4_var, Var(Symbol::ARG_4)),
|
(arg4_var, Var(Symbol::ARG_4, arg4_var)),
|
||||||
(arg5_var, Var(Symbol::ARG_5)),
|
(arg5_var, Var(Symbol::ARG_5, arg5_var)),
|
||||||
],
|
],
|
||||||
ret_var,
|
ret_var,
|
||||||
};
|
};
|
||||||
|
@ -486,7 +486,7 @@ fn to_num_checked(symbol: Symbol, var_store: &mut VarStore, lowlevel: LowLevel)
|
||||||
ext_var: var_store.fresh(),
|
ext_var: var_store.fresh(),
|
||||||
field: "b".into(),
|
field: "b".into(),
|
||||||
field_var: var_store.fresh(),
|
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!
|
// out of bounds!
|
||||||
|
@ -509,7 +509,7 @@ fn to_num_checked(symbol: Symbol, var_store: &mut VarStore, lowlevel: LowLevel)
|
||||||
ext_var: var_store.fresh(),
|
ext_var: var_store.fresh(),
|
||||||
field: "a".into(),
|
field: "a".into(),
|
||||||
field_var: num_var_2,
|
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,
|
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_pattern: no_region(Pattern::Identifier(Symbol::ARG_2)),
|
||||||
loc_expr: no_region(RunLowLevel {
|
loc_expr: no_region(RunLowLevel {
|
||||||
op: lowlevel,
|
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,
|
ret_var: record_var,
|
||||||
}),
|
}),
|
||||||
expr_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 {
|
let body = Expr::RunLowLevel {
|
||||||
op: LowLevel::Eq,
|
op: LowLevel::Eq,
|
||||||
args: vec![
|
args: vec![
|
||||||
(num_var, Var(Symbol::ARG_1)),
|
(num_var, Var(Symbol::ARG_1, num_var)),
|
||||||
(
|
(
|
||||||
num_var,
|
num_var,
|
||||||
Num(
|
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),
|
elem_var: sub!(*elem_var),
|
||||||
loc_elems: loc_elems.iter().map(|le| le.map(|e| go_help!(e))).collect(),
|
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, specialization_var)
|
AbilityMember(sym, specialization, sub!(specialization_var))
|
||||||
}
|
}
|
||||||
When {
|
When {
|
||||||
loc_cond,
|
loc_cond,
|
||||||
|
|
|
@ -124,14 +124,15 @@ fn build_effect_always(
|
||||||
Loc::at_zero(empty_record_pattern(var_store)),
|
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 {
|
Expr::Closure(ClosureData {
|
||||||
function_type: var_store.fresh(),
|
function_type: var_store.fresh(),
|
||||||
closure_type: var_store.fresh(),
|
closure_type: var_store.fresh(),
|
||||||
return_type: var_store.fresh(),
|
return_type: var_store.fresh(),
|
||||||
name: inner_closure_symbol,
|
name: inner_closure_symbol,
|
||||||
captured_symbols: vec![(value_symbol, var_store.fresh())],
|
captured_symbols: vec![(value_symbol, value_var)],
|
||||||
recursive: Recursive::NotRecursive,
|
recursive: Recursive::NotRecursive,
|
||||||
arguments,
|
arguments,
|
||||||
loc_body: Box::new(Loc::at_zero(body)),
|
loc_body: Box::new(Loc::at_zero(body)),
|
||||||
|
@ -231,20 +232,22 @@ fn build_effect_map(
|
||||||
.introduce("effect_map_thunk".into(), Region::zero())
|
.introduce("effect_map_thunk".into(), Region::zero())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
};
|
};
|
||||||
|
let thunk_var = var_store.fresh();
|
||||||
|
|
||||||
let mapper_symbol = {
|
let mapper_symbol = {
|
||||||
scope
|
scope
|
||||||
.introduce("effect_map_mapper".into(), Region::zero())
|
.introduce("effect_map_mapper".into(), Region::zero())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
};
|
};
|
||||||
|
let mapper_var = var_store.fresh();
|
||||||
|
|
||||||
let map_symbol = { scope.introduce("map".into(), Region::zero()).unwrap() };
|
let map_symbol = { scope.introduce("map".into(), Region::zero()).unwrap() };
|
||||||
|
|
||||||
// `thunk {}`
|
// `thunk {}`
|
||||||
let force_thunk_call = {
|
let force_thunk_call = {
|
||||||
let boxed = (
|
let boxed = (
|
||||||
var_store.fresh(),
|
thunk_var,
|
||||||
Loc::at_zero(Expr::Var(thunk_symbol)),
|
Loc::at_zero(Expr::Var(thunk_symbol, thunk_var)),
|
||||||
var_store.fresh(),
|
var_store.fresh(),
|
||||||
var_store.fresh(),
|
var_store.fresh(),
|
||||||
);
|
);
|
||||||
|
@ -256,8 +259,8 @@ fn build_effect_map(
|
||||||
// `toEffect (thunk {})`
|
// `toEffect (thunk {})`
|
||||||
let mapper_call = {
|
let mapper_call = {
|
||||||
let boxed = (
|
let boxed = (
|
||||||
var_store.fresh(),
|
mapper_var,
|
||||||
Loc::at_zero(Expr::Var(mapper_symbol)),
|
Loc::at_zero(Expr::Var(mapper_symbol, mapper_var)),
|
||||||
var_store.fresh(),
|
var_store.fresh(),
|
||||||
var_store.fresh(),
|
var_store.fresh(),
|
||||||
);
|
);
|
||||||
|
@ -411,9 +414,9 @@ fn build_effect_map(
|
||||||
(map_symbol, def)
|
(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 = (
|
let boxed = (
|
||||||
var_store.fresh(),
|
thunk_var,
|
||||||
Loc::at_zero(expr),
|
Loc::at_zero(expr),
|
||||||
var_store.fresh(),
|
var_store.fresh(),
|
||||||
var_store.fresh(),
|
var_store.fresh(),
|
||||||
|
@ -441,13 +444,19 @@ fn build_effect_after(
|
||||||
let outer_closure_symbol = new_symbol!(scope, "effect_after_inner");
|
let outer_closure_symbol = new_symbol!(scope, "effect_after_inner");
|
||||||
|
|
||||||
// `effect {}`
|
// `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 {})`
|
// `toEffect (effect {})`
|
||||||
|
let to_effect_var = var_store.fresh();
|
||||||
let to_effect_call = {
|
let to_effect_call = {
|
||||||
let boxed = (
|
let boxed = (
|
||||||
var_store.fresh(),
|
to_effect_var,
|
||||||
Loc::at_zero(Expr::Var(to_effect_symbol)),
|
Loc::at_zero(Expr::Var(to_effect_symbol, to_effect_var)),
|
||||||
var_store.fresh(),
|
var_store.fresh(),
|
||||||
var_store.fresh(),
|
var_store.fresh(),
|
||||||
);
|
);
|
||||||
|
@ -459,7 +468,12 @@ fn build_effect_after(
|
||||||
// let @Effect thunk = toEffect (effect {}) in thunk {}
|
// let @Effect thunk = toEffect (effect {}) in thunk {}
|
||||||
let let_effect_thunk = {
|
let let_effect_thunk = {
|
||||||
// `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) =
|
let (specialized_def_type, type_arguments, lambda_set_variables) =
|
||||||
build_fresh_opaque_variables(var_store);
|
build_fresh_opaque_variables(var_store);
|
||||||
|
@ -702,9 +716,10 @@ fn force_effect(
|
||||||
let ret_var = var_store.fresh();
|
let ret_var = var_store.fresh();
|
||||||
|
|
||||||
let force_thunk_call = {
|
let force_thunk_call = {
|
||||||
|
let thunk_var = var_store.fresh();
|
||||||
let boxed = (
|
let boxed = (
|
||||||
var_store.fresh(),
|
thunk_var,
|
||||||
Loc::at_zero(Expr::Var(thunk_symbol)),
|
Loc::at_zero(Expr::Var(thunk_symbol, thunk_var)),
|
||||||
var_store.fresh(),
|
var_store.fresh(),
|
||||||
ret_var,
|
ret_var,
|
||||||
);
|
);
|
||||||
|
@ -884,6 +899,7 @@ fn build_effect_forever_inner_body(
|
||||||
effect: Symbol,
|
effect: Symbol,
|
||||||
var_store: &mut VarStore,
|
var_store: &mut VarStore,
|
||||||
) -> Expr {
|
) -> Expr {
|
||||||
|
let thunk1_var = var_store.fresh();
|
||||||
let thunk1_symbol = { scope.introduce("thunk1".into(), Region::zero()).unwrap() };
|
let thunk1_symbol = { scope.introduce("thunk1".into(), Region::zero()).unwrap() };
|
||||||
|
|
||||||
let thunk2_symbol = { scope.introduce("thunk2".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 {
|
Def {
|
||||||
loc_pattern: Loc::at_zero(pattern),
|
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(),
|
expr_var: var_store.fresh(),
|
||||||
pattern_vars,
|
pattern_vars,
|
||||||
annotation: None,
|
annotation: None,
|
||||||
|
@ -920,8 +936,8 @@ fn build_effect_forever_inner_body(
|
||||||
let force_thunk_call = {
|
let force_thunk_call = {
|
||||||
let ret_var = var_store.fresh();
|
let ret_var = var_store.fresh();
|
||||||
let boxed = (
|
let boxed = (
|
||||||
var_store.fresh(),
|
thunk1_var,
|
||||||
Loc::at_zero(Expr::Var(thunk1_symbol)),
|
Loc::at_zero(Expr::Var(thunk1_symbol, thunk1_var)),
|
||||||
var_store.fresh(),
|
var_store.fresh(),
|
||||||
ret_var,
|
ret_var,
|
||||||
);
|
);
|
||||||
|
@ -945,12 +961,13 @@ fn build_effect_forever_inner_body(
|
||||||
let forever_effect = {
|
let forever_effect = {
|
||||||
let boxed = (
|
let boxed = (
|
||||||
var_store.fresh(),
|
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(),
|
||||||
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)
|
Expr::Call(Box::new(boxed), arguments, CalledVia::Space)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1198,14 +1215,16 @@ fn build_effect_loop_inner_body(
|
||||||
|
|
||||||
// `step state`
|
// `step state`
|
||||||
let rhs = {
|
let rhs = {
|
||||||
|
let step_var = var_store.fresh();
|
||||||
let boxed = (
|
let boxed = (
|
||||||
var_store.fresh(),
|
step_var,
|
||||||
Loc::at_zero(Expr::Var(step_symbol)),
|
Loc::at_zero(Expr::Var(step_symbol, step_var)),
|
||||||
var_store.fresh(),
|
var_store.fresh(),
|
||||||
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)
|
Expr::Call(Box::new(boxed), arguments, CalledVia::Space)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1220,10 +1239,11 @@ fn build_effect_loop_inner_body(
|
||||||
|
|
||||||
// thunk1 {}
|
// thunk1 {}
|
||||||
let force_thunk_call = {
|
let force_thunk_call = {
|
||||||
|
let thunk1_var = var_store.fresh();
|
||||||
let ret_var = var_store.fresh();
|
let ret_var = var_store.fresh();
|
||||||
let boxed = (
|
let boxed = (
|
||||||
var_store.fresh(),
|
thunk1_var,
|
||||||
Loc::at_zero(Expr::Var(thunk1_symbol)),
|
Loc::at_zero(Expr::Var(thunk1_symbol, thunk1_var)),
|
||||||
var_store.fresh(),
|
var_store.fresh(),
|
||||||
ret_var,
|
ret_var,
|
||||||
);
|
);
|
||||||
|
@ -1236,16 +1256,22 @@ fn build_effect_loop_inner_body(
|
||||||
|
|
||||||
// recursive call `loop newState step`
|
// recursive call `loop newState step`
|
||||||
let loop_new_state_step = {
|
let loop_new_state_step = {
|
||||||
|
let loop_var = var_store.fresh();
|
||||||
let boxed = (
|
let boxed = (
|
||||||
var_store.fresh(),
|
loop_var,
|
||||||
Loc::at_zero(Expr::Var(loop_symbol)),
|
Loc::at_zero(Expr::Var(loop_symbol, loop_var)),
|
||||||
var_store.fresh(),
|
var_store.fresh(),
|
||||||
var_store.fresh(),
|
var_store.fresh(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let new_state_var = var_store.fresh();
|
||||||
|
let step_var = var_store.fresh();
|
||||||
let arguments = vec![
|
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)
|
Expr::Call(Box::new(boxed), arguments, CalledVia::Space)
|
||||||
};
|
};
|
||||||
|
@ -1283,7 +1309,7 @@ fn build_effect_loop_inner_body(
|
||||||
|
|
||||||
crate::expr::WhenBranch {
|
crate::expr::WhenBranch {
|
||||||
patterns: vec![done_pattern],
|
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,
|
guard: None,
|
||||||
redundant: RedundantMark::new(var_store),
|
redundant: RedundantMark::new(var_store),
|
||||||
}
|
}
|
||||||
|
@ -1351,7 +1377,7 @@ pub fn build_host_exposed_def(
|
||||||
));
|
));
|
||||||
|
|
||||||
captured_symbols.push((arg_symbol, arg_var));
|
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);
|
let foreign_symbol_name = format!("roc_fx_{}", ident);
|
||||||
|
|
|
@ -100,7 +100,7 @@ pub enum Expr {
|
||||||
},
|
},
|
||||||
|
|
||||||
// Lookups
|
// Lookups
|
||||||
Var(Symbol),
|
Var(Symbol, Variable),
|
||||||
AbilityMember(
|
AbilityMember(
|
||||||
/// Actual member name
|
/// Actual member name
|
||||||
Symbol,
|
Symbol,
|
||||||
|
@ -230,14 +230,14 @@ pub enum Expr {
|
||||||
Expect {
|
Expect {
|
||||||
loc_condition: Box<Loc<Expr>>,
|
loc_condition: Box<Loc<Expr>>,
|
||||||
loc_continuation: 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
|
// not parsed, but is generated when lowering toplevel effectful expects
|
||||||
ExpectFx {
|
ExpectFx {
|
||||||
loc_condition: Box<Loc<Expr>>,
|
loc_condition: Box<Loc<Expr>>,
|
||||||
loc_continuation: 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
|
/// Rendered as empty box in editor
|
||||||
|
@ -247,6 +247,13 @@ pub enum Expr {
|
||||||
RuntimeError(RuntimeError),
|
RuntimeError(RuntimeError),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub struct ExpectLookup {
|
||||||
|
pub symbol: Symbol,
|
||||||
|
pub var: Variable,
|
||||||
|
pub ability_info: Option<SpecializationId>,
|
||||||
|
}
|
||||||
|
|
||||||
impl Expr {
|
impl Expr {
|
||||||
pub fn category(&self) -> Category {
|
pub fn category(&self) -> Category {
|
||||||
match self {
|
match self {
|
||||||
|
@ -256,7 +263,7 @@ impl Expr {
|
||||||
Self::Str(..) => Category::Str,
|
Self::Str(..) => Category::Str,
|
||||||
Self::SingleQuote(..) => Category::Character,
|
Self::SingleQuote(..) => Category::Character,
|
||||||
Self::List { .. } => Category::List,
|
Self::List { .. } => Category::List,
|
||||||
&Self::Var(sym) => Category::Lookup(sym),
|
&Self::Var(sym, _) => Category::Lookup(sym),
|
||||||
&Self::AbilityMember(sym, _, _) => Category::Lookup(sym),
|
&Self::AbilityMember(sym, _, _) => Category::Lookup(sym),
|
||||||
Self::When { .. } => Category::When,
|
Self::When { .. } => Category::When,
|
||||||
Self::If { .. } => Category::If,
|
Self::If { .. } => Category::If,
|
||||||
|
@ -372,7 +379,7 @@ impl AccessorData {
|
||||||
record_var,
|
record_var,
|
||||||
ext_var,
|
ext_var,
|
||||||
field_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,
|
field,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -440,7 +447,10 @@ impl OpaqueWrapFunctionData {
|
||||||
let body = Expr::OpaqueRef {
|
let body = Expr::OpaqueRef {
|
||||||
opaque_var,
|
opaque_var,
|
||||||
name: opaque_name,
|
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),
|
specialized_def_type: Box::new(specialized_def_type),
|
||||||
type_arguments,
|
type_arguments,
|
||||||
lambda_set_variables,
|
lambda_set_variables,
|
||||||
|
@ -592,7 +602,7 @@ pub fn canonicalize_expr<'a>(
|
||||||
} => {
|
} => {
|
||||||
let (can_update, update_out) =
|
let (can_update, update_out) =
|
||||||
canonicalize_expr(env, var_store, scope, loc_update.region, &loc_update.value);
|
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) {
|
match canonicalize_fields(env, var_store, scope, region, fields.items) {
|
||||||
Ok((can_fields, mut output)) => {
|
Ok((can_fields, mut output)) => {
|
||||||
output.references.union_mut(&update_out.references);
|
output.references.union_mut(&update_out.references);
|
||||||
|
@ -765,7 +775,7 @@ pub fn canonicalize_expr<'a>(
|
||||||
output.tail_call = None;
|
output.tail_call = None;
|
||||||
|
|
||||||
let expr = match fn_expr.value {
|
let expr = match fn_expr.value {
|
||||||
Var(symbol) => {
|
Var(symbol, _) => {
|
||||||
output.references.insert_call(symbol);
|
output.references.insert_call(symbol);
|
||||||
|
|
||||||
// we're tail-calling a symbol by name, check if it's the tail-callable 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,
|
// Get all the lookups that were referenced in the condition,
|
||||||
// so we can print their values later.
|
// 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(
|
let (loc_continuation, output2) = canonicalize_expr(
|
||||||
env,
|
env,
|
||||||
|
@ -1600,7 +1610,7 @@ fn canonicalize_var_lookup(
|
||||||
var_store.fresh(),
|
var_store.fresh(),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
Var(symbol)
|
Var(symbol, var_store.fresh())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(problem) => {
|
Err(problem) => {
|
||||||
|
@ -1623,7 +1633,7 @@ fn canonicalize_var_lookup(
|
||||||
var_store.fresh(),
|
var_store.fresh(),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
Var(symbol)
|
Var(symbol, var_store.fresh())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(problem) => {
|
Err(problem) => {
|
||||||
|
@ -1657,7 +1667,7 @@ pub fn inline_calls(var_store: &mut VarStore, scope: &mut Scope, expr: Expr) ->
|
||||||
| other @ EmptyRecord
|
| other @ EmptyRecord
|
||||||
| other @ Accessor { .. }
|
| other @ Accessor { .. }
|
||||||
| other @ Update { .. }
|
| other @ Update { .. }
|
||||||
| other @ Var(_)
|
| other @ Var(..)
|
||||||
| other @ AbilityMember(..)
|
| other @ AbilityMember(..)
|
||||||
| other @ RunLowLevel { .. }
|
| other @ RunLowLevel { .. }
|
||||||
| other @ TypedHole { .. }
|
| other @ TypedHole { .. }
|
||||||
|
@ -1960,7 +1970,8 @@ pub fn inline_calls(var_store: &mut VarStore, scope: &mut Scope, expr: Expr) ->
|
||||||
let (fn_var, loc_expr, closure_var, expr_var) = *boxed_tuple;
|
let (fn_var, loc_expr, closure_var, expr_var) = *boxed_tuple;
|
||||||
|
|
||||||
match loc_expr.value {
|
match loc_expr.value {
|
||||||
Var(symbol) if symbol.is_builtin() => match builtin_defs_map(symbol, var_store) {
|
Var(symbol, _) if symbol.is_builtin() => {
|
||||||
|
match builtin_defs_map(symbol, var_store) {
|
||||||
Some(Def {
|
Some(Def {
|
||||||
loc_expr:
|
loc_expr:
|
||||||
Loc {
|
Loc {
|
||||||
|
@ -1988,8 +1999,10 @@ pub fn inline_calls(var_store: &mut VarStore, scope: &mut Scope, expr: Expr) ->
|
||||||
// Wrap the body in one LetNonRec for each argument,
|
// Wrap the body in one LetNonRec for each argument,
|
||||||
// such that at the end we have all the arguments in
|
// such that at the end we have all the arguments in
|
||||||
// scope with the values the caller provided.
|
// scope with the values the caller provided.
|
||||||
for ((_param_var, _exhaustive_mark, loc_pattern), (expr_var, loc_expr)) in
|
for (
|
||||||
params.iter().cloned().zip(args.into_iter()).rev()
|
(_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.
|
// TODO get the correct vars into here.
|
||||||
// Not sure if param_var should be involved.
|
// Not sure if param_var should be involved.
|
||||||
|
@ -2020,7 +2033,8 @@ pub fn inline_calls(var_store: &mut VarStore, scope: &mut Scope, expr: Expr) ->
|
||||||
symbol
|
symbol
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
// For now, we only inline calls to builtins. Leave this alone!
|
// For now, we only inline calls to builtins. Leave this alone!
|
||||||
Call(
|
Call(
|
||||||
|
@ -2172,7 +2186,10 @@ fn desugar_str_segments(var_store: &mut VarStore, segments: Vec<StrSegment>) ->
|
||||||
Interpolation(loc_interpolated_expr) => loc_interpolated_expr,
|
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(
|
let expr = Expr::Call(
|
||||||
Box::new((
|
Box::new((
|
||||||
var_store.fresh(),
|
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 {
|
let mut collector = ExpectCollector {
|
||||||
expects: VecMap::default(),
|
expects: VecMap::default(),
|
||||||
};
|
};
|
||||||
|
@ -2615,16 +2632,34 @@ pub struct DestructureDef {
|
||||||
pub pattern_vars: VecMap<Symbol, Variable>,
|
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 stack: Vec<&Expr> = vec![expr];
|
||||||
let mut symbols = Vec::new();
|
let mut lookups: Vec<ExpectLookup> = Vec::new();
|
||||||
|
|
||||||
while let Some(expr) = stack.pop() {
|
while let Some(expr) = stack.pop() {
|
||||||
match expr {
|
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
|
// Don't introduce duplicates, or make unused variables
|
||||||
if !symbols.iter().any(|(sym, _)| sym == symbol) {
|
if !lookups.iter().any(|l| l.symbol == *symbol) {
|
||||||
symbols.push((*symbol, var_store.fresh()));
|
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, .. } => {
|
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());
|
stack.reserve(1 + args.len());
|
||||||
|
|
||||||
match &boxed_expr.1.value {
|
match &boxed_expr.1.value {
|
||||||
Expr::Var(_) => {
|
Expr::Var(_, _) => {
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
function_expr => {
|
function_expr => {
|
||||||
|
@ -2721,7 +2756,7 @@ fn get_lookup_symbols(expr: &Expr, var_store: &mut VarStore) -> Vec<(Symbol, Var
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
symbols
|
lookups
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Here we transform
|
/// Here we transform
|
||||||
|
@ -2768,14 +2803,22 @@ fn toplevel_expect_to_inline_expect_help(mut loc_expr: Loc<Expr>, has_effects: b
|
||||||
loop {
|
loop {
|
||||||
match loc_expr.value {
|
match loc_expr.value {
|
||||||
Expr::LetNonRec(boxed_def, remainder) => {
|
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));
|
stack.push(StoredDef::NonRecursive(loc_expr.region, boxed_def));
|
||||||
loc_expr = *remainder;
|
loc_expr = *remainder;
|
||||||
}
|
}
|
||||||
Expr::LetRec(defs, remainder, mark) => {
|
Expr::LetRec(defs, remainder, mark) => {
|
||||||
for def in &defs {
|
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));
|
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 {
|
struct ExpectCollector {
|
||||||
expects: VecMap<Region, Vec<(Symbol, Variable)>>,
|
expects: VecMap<Region, Vec<ExpectLookup>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl crate::traverse::Visitor for ExpectCollector {
|
impl crate::traverse::Visitor for ExpectCollector {
|
||||||
|
|
|
@ -3,7 +3,7 @@ use crate::annotation::canonicalize_annotation;
|
||||||
use crate::def::{canonicalize_defs, Def};
|
use crate::def::{canonicalize_defs, Def};
|
||||||
use crate::effect_module::HostedGeneratedFunctions;
|
use crate::effect_module::HostedGeneratedFunctions;
|
||||||
use crate::env::Env;
|
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::pattern::{BindingsFromPattern, Pattern};
|
||||||
use crate::scope::Scope;
|
use crate::scope::Scope;
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
|
@ -130,7 +130,7 @@ pub struct Module {
|
||||||
pub aliases: MutMap<Symbol, (bool, Alias)>,
|
pub aliases: MutMap<Symbol, (bool, Alias)>,
|
||||||
pub rigid_variables: RigidVariables,
|
pub rigid_variables: RigidVariables,
|
||||||
pub abilities_store: PendingAbilitiesStore,
|
pub abilities_store: PendingAbilitiesStore,
|
||||||
pub loc_expects: VecMap<Region, Vec<(Symbol, Variable)>>,
|
pub loc_expects: VecMap<Region, Vec<ExpectLookup>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
|
@ -152,7 +152,7 @@ pub struct ModuleOutput {
|
||||||
pub symbols_from_requires: Vec<(Loc<Symbol>, Loc<Type>)>,
|
pub symbols_from_requires: Vec<(Loc<Symbol>, Loc<Type>)>,
|
||||||
pub pending_derives: PendingDerives,
|
pub pending_derives: PendingDerives,
|
||||||
pub scope: Scope,
|
pub scope: Scope,
|
||||||
pub loc_expects: VecMap<Region, Vec<(Symbol, Variable)>>,
|
pub loc_expects: VecMap<Region, Vec<ExpectLookup>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate_generate_with<'a>(
|
fn validate_generate_with<'a>(
|
||||||
|
@ -1040,7 +1040,7 @@ fn fix_values_captured_in_closure_expr(
|
||||||
| Float(..)
|
| Float(..)
|
||||||
| Str(_)
|
| Str(_)
|
||||||
| SingleQuote(..)
|
| SingleQuote(..)
|
||||||
| Var(_)
|
| Var(..)
|
||||||
| AbilityMember(..)
|
| AbilityMember(..)
|
||||||
| EmptyRecord
|
| EmptyRecord
|
||||||
| TypedHole { .. }
|
| TypedHole { .. }
|
||||||
|
|
|
@ -13,8 +13,8 @@ use roc_can::expected::Expected::{self, *};
|
||||||
use roc_can::expected::PExpected;
|
use roc_can::expected::PExpected;
|
||||||
use roc_can::expr::Expr::{self, *};
|
use roc_can::expr::Expr::{self, *};
|
||||||
use roc_can::expr::{
|
use roc_can::expr::{
|
||||||
AccessorData, AnnotatedMark, ClosureData, DeclarationTag, Declarations, DestructureDef, Field,
|
AccessorData, AnnotatedMark, ClosureData, DeclarationTag, Declarations, DestructureDef,
|
||||||
FunctionDef, OpaqueWrapFunctionData, WhenBranch,
|
ExpectLookup, Field, FunctionDef, OpaqueWrapFunctionData, WhenBranch,
|
||||||
};
|
};
|
||||||
use roc_can::pattern::Pattern;
|
use roc_can::pattern::Pattern;
|
||||||
use roc_can::traverse::symbols_introduced_from_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;
|
let (fn_var, loc_fn, closure_var, ret_var) = &**boxed;
|
||||||
// The expression that evaluates to the function being called, e.g. `foo` in
|
// The expression that evaluates to the function being called, e.g. `foo` in
|
||||||
// (foo) bar baz
|
// (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)
|
Some(symbol)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -425,9 +425,13 @@ pub fn constrain_expr(
|
||||||
let and_constraint = constraints.and_constraint(and_cons);
|
let and_constraint = constraints.and_constraint(and_cons);
|
||||||
constraints.exists(vars, and_constraint)
|
constraints.exists(vars, and_constraint)
|
||||||
}
|
}
|
||||||
Var(symbol) => {
|
Var(symbol, variable) => {
|
||||||
// make lookup constraint to lookup this symbol's type in the environment
|
// Save the expectation in the variable, then lookup the symbol's type in the environment
|
||||||
constraints.lookup(*symbol, expected, region)
|
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) => {
|
&AbilityMember(symbol, specialization_id, specialization_var) => {
|
||||||
// Save the expectation in the `specialization_var` so we know what to specialize, then
|
// 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());
|
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);
|
vars.push(*var);
|
||||||
|
|
||||||
all_constraints.push(constraints.lookup(
|
all_constraints.push(constraints.lookup(
|
||||||
|
@ -562,7 +571,12 @@ pub fn constrain_expr(
|
||||||
|
|
||||||
let mut vars = Vec::with_capacity(lookups_in_cond.len());
|
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);
|
vars.push(*var);
|
||||||
|
|
||||||
all_constraints.push(constraints.lookup(
|
all_constraints.push(constraints.lookup(
|
||||||
|
|
|
@ -357,7 +357,7 @@ fn decoder_record_step_field(
|
||||||
name: "Ok".into(),
|
name: "Ok".into(),
|
||||||
arguments: vec![(
|
arguments: vec![(
|
||||||
field_var,
|
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(),
|
name: "Err".into(),
|
||||||
arguments: vec![(
|
arguments: vec![(
|
||||||
decode_err_var,
|
decode_err_var,
|
||||||
Loc::at_zero(Expr::Var(err_val_symbol)),
|
Loc::at_zero(Expr::Var(err_val_symbol, decode_err_var)),
|
||||||
)],
|
)],
|
||||||
}),
|
}),
|
||||||
guard: None,
|
guard: None,
|
||||||
|
@ -433,7 +433,7 @@ fn decoder_record_step_field(
|
||||||
record_var: rec_var,
|
record_var: rec_var,
|
||||||
ext_var: env.new_ext_var(ExtensionKind::Record),
|
ext_var: env.new_ext_var(ExtensionKind::Record),
|
||||||
field_var: rec_dot_result,
|
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(),
|
field: "result".into(),
|
||||||
})),
|
})),
|
||||||
cond_var: rec_dot_result,
|
cond_var: rec_dot_result,
|
||||||
|
@ -462,7 +462,7 @@ fn decoder_record_step_field(
|
||||||
record_var: rec_var,
|
record_var: rec_var,
|
||||||
ext_var: env.new_ext_var(ExtensionKind::Record),
|
ext_var: env.new_ext_var(ExtensionKind::Record),
|
||||||
field_var: Variable::LIST_U8,
|
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(),
|
field: "rest".into(),
|
||||||
})),
|
})),
|
||||||
},
|
},
|
||||||
|
@ -499,12 +499,15 @@ fn decoder_record_step_field(
|
||||||
let condition_expr = Expr::Call(
|
let condition_expr = Expr::Call(
|
||||||
Box::new((
|
Box::new((
|
||||||
this_decode_with_var,
|
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,
|
lambda_set_var,
|
||||||
rec_var,
|
rec_var,
|
||||||
)),
|
)),
|
||||||
vec![
|
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,
|
decoder_var,
|
||||||
Loc::at_zero(Expr::AbilityMember(
|
Loc::at_zero(Expr::AbilityMember(
|
||||||
|
@ -513,7 +516,10 @@ fn decoder_record_step_field(
|
||||||
decoder_var,
|
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,
|
CalledVia::Space,
|
||||||
);
|
);
|
||||||
|
@ -600,7 +606,7 @@ fn decoder_record_step_field(
|
||||||
Expr::Call(
|
Expr::Call(
|
||||||
Box::new((
|
Box::new((
|
||||||
this_decode_custom_var,
|
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_closure_var,
|
||||||
decode_custom_ret_var,
|
decode_custom_ret_var,
|
||||||
)),
|
)),
|
||||||
|
@ -676,7 +682,7 @@ fn decoder_record_step_field(
|
||||||
|
|
||||||
// when field is
|
// when field is
|
||||||
let body = Expr::When {
|
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,
|
cond_var: Variable::STR,
|
||||||
expr_var: keep_or_skip_var,
|
expr_var: keep_or_skip_var,
|
||||||
region: Region::zero(),
|
region: Region::zero(),
|
||||||
|
@ -764,7 +770,7 @@ fn decoder_record_finalizer(
|
||||||
|
|
||||||
pattern_symbols.push(symbol);
|
pattern_symbols.push(symbol);
|
||||||
|
|
||||||
let field_expr = Expr::Var(symbol);
|
let field_expr = Expr::Var(symbol, field_var);
|
||||||
let field = Field {
|
let field = Field {
|
||||||
var: field_var,
|
var: field_var,
|
||||||
region: Region::zero(),
|
region: Region::zero(),
|
||||||
|
@ -827,7 +833,7 @@ fn decoder_record_finalizer(
|
||||||
record_var: state_record_var,
|
record_var: state_record_var,
|
||||||
ext_var: env.new_ext_var(ExtensionKind::Record),
|
ext_var: env.new_ext_var(ExtensionKind::Record),
|
||||||
field_var: result_field_var,
|
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(),
|
field: field_name.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1126,7 +1132,7 @@ fn wrap_in_decode_custom_decode_with(
|
||||||
// ~ bytes, Decoder (List elem) fmt, fmt -> DecoderResult (List val)
|
// ~ bytes, Decoder (List elem) fmt, fmt -> DecoderResult (List val)
|
||||||
env.unify(decode_with_type, this_decode_with_fn_var);
|
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((
|
let decode_with_fn = Box::new((
|
||||||
this_decode_with_fn_var,
|
this_decode_with_fn_var,
|
||||||
Loc::at_zero(decode_with_var),
|
Loc::at_zero(decode_with_var),
|
||||||
|
@ -1137,9 +1143,9 @@ fn wrap_in_decode_custom_decode_with(
|
||||||
decode_with_fn,
|
decode_with_fn,
|
||||||
vec![
|
vec![
|
||||||
// bytes inner_decoder fmt
|
// 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)),
|
(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,
|
CalledVia::Space,
|
||||||
);
|
);
|
||||||
|
@ -1231,7 +1237,7 @@ fn wrap_in_decode_custom_decode_with(
|
||||||
// ~ (List U8, fmt -> DecodeResult (List elem)) -> Decoder (List elem) fmt
|
// ~ (List U8, fmt -> DecodeResult (List elem)) -> Decoder (List elem) fmt
|
||||||
env.unify(decode_custom_type, this_decode_custom_fn_var);
|
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((
|
let decode_custom_fn = Box::new((
|
||||||
this_decode_custom_fn_var,
|
this_decode_custom_fn_var,
|
||||||
Loc::at_zero(decode_custom_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
|
// toEncoder elem
|
||||||
let to_encoder_call = Call(
|
let to_encoder_call = Call(
|
||||||
to_encoder_fn,
|
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,
|
CalledVia::Space,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -217,7 +217,7 @@ fn to_encoder_list(env: &mut Env<'_>, fn_name: Symbol) -> (Expr, Variable) {
|
||||||
let encode_list_call = Call(
|
let encode_list_call = Call(
|
||||||
encode_list_fn,
|
encode_list_fn,
|
||||||
vec![
|
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)),
|
(to_elem_encoder_fn_var, Loc::at_zero(to_elem_encoder)),
|
||||||
],
|
],
|
||||||
CalledVia::Space,
|
CalledVia::Space,
|
||||||
|
@ -314,7 +314,10 @@ fn to_encoder_record(
|
||||||
record_var,
|
record_var,
|
||||||
ext_var: env.subs.fresh_unnamed_flex_var(),
|
ext_var: env.subs.fresh_unnamed_flex_var(),
|
||||||
field_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,
|
field: field_name,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -572,7 +575,7 @@ fn to_encoder_tag_union(
|
||||||
// toEncoder rcd.a
|
// toEncoder rcd.a
|
||||||
let to_encoder_call = Call(
|
let to_encoder_call = Call(
|
||||||
to_encoder_fn,
|
to_encoder_fn,
|
||||||
vec![(sym_var, Loc::at_zero(Var(sym)))],
|
vec![(sym_var, Loc::at_zero(Var(sym, sym_var)))],
|
||||||
CalledVia::Space,
|
CalledVia::Space,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -662,7 +665,7 @@ fn to_encoder_tag_union(
|
||||||
// A v1 v2 -> Encode.tag "A" [ Encode.toEncoder v1, Encode.toEncoder v2 ]
|
// A v1 v2 -> Encode.tag "A" [ Encode.toEncoder v1, Encode.toEncoder v2 ]
|
||||||
// B v3 -> Encode.tag "B" [ Encode.toEncoder v3 ]
|
// B v3 -> Encode.tag "B" [ Encode.toEncoder v3 ]
|
||||||
let when_branches = When {
|
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,
|
cond_var: tag_union_var,
|
||||||
expr_var: whole_tag_encoders_var,
|
expr_var: whole_tag_encoders_var,
|
||||||
region: Region::zero(),
|
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
|
// Encode.appendWith : List U8, encoder_var, fmt -[appendWith]-> List U8 | fmt has EncoderFormatting
|
||||||
let append_with_fn = Box::new((
|
let append_with_fn = Box::new((
|
||||||
this_append_with_fn_var,
|
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,
|
this_append_with_clos_var,
|
||||||
Variable::LIST_U8,
|
Variable::LIST_U8,
|
||||||
));
|
));
|
||||||
|
@ -788,11 +791,11 @@ fn wrap_in_encode_custom(
|
||||||
append_with_fn,
|
append_with_fn,
|
||||||
vec![
|
vec![
|
||||||
// (bytes_var, bytes)
|
// (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, encoder)
|
||||||
(encoder_var, Loc::at_zero(encoder)),
|
(encoder_var, Loc::at_zero(encoder)),
|
||||||
// (fmt, fmt_var)
|
// (fmt, fmt_var)
|
||||||
(fmt_var, Loc::at_zero(Var(fmt_sym))),
|
(fmt_var, Loc::at_zero(Var(fmt_sym, fmt_var))),
|
||||||
],
|
],
|
||||||
CalledVia::Space,
|
CalledVia::Space,
|
||||||
);
|
);
|
||||||
|
@ -869,7 +872,7 @@ fn wrap_in_encode_custom(
|
||||||
// Encode.custom : (List U8, fmt -> List U8) -> Encoder fmt | fmt has EncoderFormatting
|
// Encode.custom : (List U8, fmt -> List U8) -> Encoder fmt | fmt has EncoderFormatting
|
||||||
let custom_fn = Box::new((
|
let custom_fn = Box::new((
|
||||||
this_custom_fn_var,
|
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_clos_var, // -[clos]->
|
||||||
this_custom_encoder_var, // t' ~ Encoder fmt
|
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 hasher_var = synth_var(env.subs, Content::FlexAbleVar(None, Symbol::HASH_HASHER));
|
||||||
|
|
||||||
let (body_var, body) = record_fields.iter_all().fold(
|
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, _)| {
|
|total_hasher, (field_name, field_var, _)| {
|
||||||
let field_name = env.subs[field_name].clone();
|
let field_name = env.subs[field_name].clone();
|
||||||
let field_var = env.subs[field_var];
|
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,
|
record_var,
|
||||||
field_var,
|
field_var,
|
||||||
ext_var: env.subs.fresh_unnamed_flex_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,
|
field: field_name,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -215,7 +218,7 @@ fn hash_tag_union(
|
||||||
let (discr_hasher_var, disc_hasher_expr) = call_hash_ability_member(
|
let (discr_hasher_var, disc_hasher_expr) = call_hash_ability_member(
|
||||||
env,
|
env,
|
||||||
hash_discr_member,
|
hash_discr_member,
|
||||||
(hasher_var, Expr::Var(hasher_sym)),
|
(hasher_var, Expr::Var(hasher_sym, hasher_var)),
|
||||||
(
|
(
|
||||||
discr_num_var,
|
discr_num_var,
|
||||||
Expr::Int(
|
Expr::Int(
|
||||||
|
@ -232,7 +235,11 @@ fn hash_tag_union(
|
||||||
let (body_var, body_expr) = (payload_vars.into_iter()).zip(payload_syms).fold(
|
let (body_var, body_expr) = (payload_vars.into_iter()).zip(payload_syms).fold(
|
||||||
(discr_hasher_var, disc_hasher_expr),
|
(discr_hasher_var, disc_hasher_expr),
|
||||||
|total_hasher, (payload_var, payload_sym)| {
|
|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_var = whole_hasher_var;
|
||||||
let when_expr = Expr::When {
|
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,
|
cond_var: union_var,
|
||||||
expr_var: when_var,
|
expr_var: when_var,
|
||||||
region: Region::zero(),
|
region: Region::zero(),
|
||||||
|
@ -338,9 +345,13 @@ fn hash_newtype_tag_union(
|
||||||
|
|
||||||
// Fold up `Hash.hash (... (Hash.hash discrHasher x11) ...) x1n`
|
// Fold up `Hash.hash (... (Hash.hash discrHasher x11) ...) x1n`
|
||||||
let (body_var, body_expr) = (payload_vars.into_iter()).zip(payload_syms).fold(
|
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)| {
|
|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_builtins::roc::module_source;
|
||||||
use roc_can::abilities::{AbilitiesStore, PendingAbilitiesStore, ResolvedImpl};
|
use roc_can::abilities::{AbilitiesStore, PendingAbilitiesStore, ResolvedImpl};
|
||||||
use roc_can::constraint::{Constraint as ConstraintSoa, Constraints};
|
use roc_can::constraint::{Constraint as ConstraintSoa, Constraints};
|
||||||
use roc_can::expr::Declarations;
|
|
||||||
use roc_can::expr::PendingDerives;
|
use roc_can::expr::PendingDerives;
|
||||||
|
use roc_can::expr::{Declarations, ExpectLookup};
|
||||||
use roc_can::module::{
|
use roc_can::module::{
|
||||||
canonicalize_module_defs, ExposedByModule, ExposedForModule, ExposedModuleTypes, Module,
|
canonicalize_module_defs, ExposedByModule, ExposedForModule, ExposedModuleTypes, Module,
|
||||||
ResolvedImplementations, TypeState,
|
ResolvedImplementations, TypeState,
|
||||||
|
@ -719,7 +719,7 @@ pub enum EntryPoint<'a> {
|
||||||
pub struct Expectations {
|
pub struct Expectations {
|
||||||
pub subs: roc_types::subs::Subs,
|
pub subs: roc_types::subs::Subs,
|
||||||
pub path: PathBuf,
|
pub path: PathBuf,
|
||||||
pub expectations: VecMap<Region, Vec<(Symbol, Variable)>>,
|
pub expectations: VecMap<Region, Vec<ExpectLookup>>,
|
||||||
pub ident_ids: IdentIds,
|
pub ident_ids: IdentIds,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -763,7 +763,7 @@ struct ParsedModule<'a> {
|
||||||
header_for: HeaderFor<'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,
|
/// A message sent out _from_ a worker thread,
|
||||||
/// representing a result of work done, or a request for further work
|
/// 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 bumpalo::Bump;
|
||||||
use roc_builtins::bitcode::{FloatWidth, IntWidth};
|
use roc_builtins::bitcode::{FloatWidth, IntWidth};
|
||||||
use roc_can::abilities::SpecializationId;
|
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_can::module::ExposedByModule;
|
||||||
use roc_collections::all::{default_hasher, BumpMap, BumpMapDefault, MutMap};
|
use roc_collections::all::{default_hasher, BumpMap, BumpMapDefault, MutMap};
|
||||||
use roc_collections::VecMap;
|
use roc_collections::VecMap;
|
||||||
|
@ -2376,7 +2376,7 @@ fn from_can_let<'a>(
|
||||||
|
|
||||||
lower_rest!(variable, cont.value)
|
lower_rest!(variable, cont.value)
|
||||||
}
|
}
|
||||||
Var(original) | AbilityMember(original, _, _) => {
|
Var(original, _) | AbilityMember(original, _, _) => {
|
||||||
// a variable is aliased, e.g.
|
// a variable is aliased, e.g.
|
||||||
//
|
//
|
||||||
// foo = bar
|
// foo = bar
|
||||||
|
@ -2605,7 +2605,7 @@ fn from_can_let<'a>(
|
||||||
}
|
}
|
||||||
|
|
||||||
match def.loc_expr.value {
|
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)
|
store_pattern(env, procs, layout_cache, &mono_pattern, outer_symbol, stmt)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -2747,7 +2747,7 @@ fn pattern_to_when<'a>(
|
||||||
cond_var: pattern_var,
|
cond_var: pattern_var,
|
||||||
expr_var: body_var,
|
expr_var: body_var,
|
||||||
region: Region::zero(),
|
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 {
|
branches: vec![WhenBranch {
|
||||||
patterns: vec![WhenBranchPattern {
|
patterns: vec![WhenBranchPattern {
|
||||||
pattern,
|
pattern,
|
||||||
|
@ -4074,11 +4074,14 @@ pub fn with_hole<'a>(
|
||||||
hole,
|
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 this symbol is a raw value, find the real name we gave to its specialized usage.
|
||||||
if let ReuseSymbol::Value(_symbol) =
|
if let ReuseSymbol::Value(_symbol) = can_reuse_symbol(
|
||||||
can_reuse_symbol(env, procs, &roc_can::expr::Expr::Var(symbol), variable)
|
env,
|
||||||
{
|
procs,
|
||||||
|
&roc_can::expr::Expr::Var(symbol, variable),
|
||||||
|
variable,
|
||||||
|
) {
|
||||||
let real_symbol =
|
let real_symbol =
|
||||||
procs
|
procs
|
||||||
.symbol_specializations
|
.symbol_specializations
|
||||||
|
@ -5046,7 +5049,7 @@ pub fn with_hole<'a>(
|
||||||
};
|
};
|
||||||
|
|
||||||
match loc_expr.value {
|
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
|
// a call by a known name
|
||||||
call_by_name(
|
call_by_name(
|
||||||
env,
|
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_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_pattern_args.push((arg_var, AnnotatedMark::known_exhaustive(), loc_pattern));
|
||||||
loc_expr_args.push((arg_var, loc_expr));
|
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 rest = from_can(env, variable, loc_continuation.value, procs, layout_cache);
|
||||||
let cond_symbol = env.unique_symbol();
|
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);
|
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 res_layout = layout_cache.from_var(env.arena, var, env.subs);
|
||||||
let layout = return_on_layout_error!(env, res_layout, "Expect");
|
let layout = return_on_layout_error!(env, res_layout, "Expect");
|
||||||
layouts.push(layout);
|
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 rest = from_can(env, variable, loc_continuation.value, procs, layout_cache);
|
||||||
let cond_symbol = env.unique_symbol();
|
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);
|
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 res_layout = layout_cache.from_var(env.arena, var, env.subs);
|
||||||
let layout = return_on_layout_error!(env, res_layout, "Expect");
|
let layout = return_on_layout_error!(env, res_layout, "Expect");
|
||||||
layouts.push(layout);
|
layouts.push(layout);
|
||||||
|
@ -7513,7 +7544,7 @@ fn can_reuse_symbol<'a>(
|
||||||
AbilityMember(member, specialization_id, _) => {
|
AbilityMember(member, specialization_id, _) => {
|
||||||
late_resolve_ability_specialization(env, *member, *specialization_id, expr_var)
|
late_resolve_ability_specialization(env, *member, *specialization_id, expr_var)
|
||||||
}
|
}
|
||||||
Var(symbol) => *symbol,
|
Var(symbol, _) => *symbol,
|
||||||
_ => return NotASymbol,
|
_ => return NotASymbol,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -87,7 +87,7 @@ fn expr<'a>(c: &Ctx, p: EPrec, f: &'a Arena<'a>, e: &'a Expr) -> DocBuilder<'a,
|
||||||
.append("]")
|
.append("]")
|
||||||
.group(),
|
.group(),
|
||||||
),
|
),
|
||||||
Var(sym) | AbilityMember(sym, _, _) => f.text(format!(
|
Var(sym, _) | AbilityMember(sym, _, _) => f.text(format!(
|
||||||
"{}.{}",
|
"{}.{}",
|
||||||
sym.module_string(c.interns),
|
sym.module_string(c.interns),
|
||||||
sym.as_str(c.interns),
|
sym.as_str(c.interns),
|
||||||
|
|
|
@ -10,6 +10,7 @@ bumpalo = {version = "3.11.0", features = ["collections"]}
|
||||||
target-lexicon = "0.12.2"
|
target-lexicon = "0.12.2"
|
||||||
|
|
||||||
roc_builtins = {path = "../compiler/builtins"}
|
roc_builtins = {path = "../compiler/builtins"}
|
||||||
|
roc_can = {path = "../compiler/can"}
|
||||||
roc_collections = {path = "../compiler/collections"}
|
roc_collections = {path = "../compiler/collections"}
|
||||||
roc_intern = {path = "../compiler/intern"}
|
roc_intern = {path = "../compiler/intern"}
|
||||||
roc_load = {path = "../compiler/load"}
|
roc_load = {path = "../compiler/load"}
|
||||||
|
|
|
@ -4,6 +4,7 @@ use bumpalo::collections::Vec as BumpVec;
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
use inkwell::context::Context;
|
use inkwell::context::Context;
|
||||||
use roc_build::link::llvm_module_to_dylib;
|
use roc_build::link::llvm_module_to_dylib;
|
||||||
|
use roc_can::expr::ExpectLookup;
|
||||||
use roc_collections::{MutSet, VecMap};
|
use roc_collections::{MutSet, VecMap};
|
||||||
use roc_gen_llvm::{
|
use roc_gen_llvm::{
|
||||||
llvm::{build::LlvmBackendMode, externs::add_default_roc_externs},
|
llvm::{build::LlvmBackendMode, externs::add_default_roc_externs},
|
||||||
|
@ -389,7 +390,16 @@ fn render_expect_failure<'a>(
|
||||||
};
|
};
|
||||||
let subs = arena.alloc(&mut data.subs);
|
let subs = arena.alloc(&mut data.subs);
|
||||||
|
|
||||||
let (symbols, variables): (Vec<_>, Vec<_>) = current.iter().map(|(a, b)| (*a, *b)).unzip();
|
let (symbols, variables): (Vec<_>, Vec<_>) = current
|
||||||
|
.iter()
|
||||||
|
.map(
|
||||||
|
|ExpectLookup {
|
||||||
|
symbol,
|
||||||
|
var,
|
||||||
|
ability_info: _,
|
||||||
|
}| (*symbol, *var),
|
||||||
|
)
|
||||||
|
.unzip();
|
||||||
|
|
||||||
let (offset, expressions) = crate::get_values(
|
let (offset, expressions) = crate::get_values(
|
||||||
target_info,
|
target_info,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue