mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 13:29:12 +00:00
more boilerplate
This commit is contained in:
parent
10b6f33ed2
commit
7e6a3ddc15
7 changed files with 138 additions and 9 deletions
|
@ -613,6 +613,16 @@ fn deep_copy_expr_help<C: CopyEnv>(env: &mut C, copied: &mut Vec<Variable>, expr
|
||||||
lookups_in_cond: lookups_in_cond.to_vec(),
|
lookups_in_cond: lookups_in_cond.to_vec(),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
ExpectFx {
|
||||||
|
loc_condition,
|
||||||
|
loc_continuation,
|
||||||
|
lookups_in_cond,
|
||||||
|
} => ExpectFx {
|
||||||
|
loc_condition: Box::new(loc_condition.map(|e| go_help!(e))),
|
||||||
|
loc_continuation: Box::new(loc_continuation.map(|e| go_help!(e))),
|
||||||
|
lookups_in_cond: lookups_in_cond.to_vec(),
|
||||||
|
},
|
||||||
|
|
||||||
TypedHole(v) => TypedHole(sub!(*v)),
|
TypedHole(v) => TypedHole(sub!(*v)),
|
||||||
|
|
||||||
RuntimeError(err) => RuntimeError(err.clone()),
|
RuntimeError(err) => RuntimeError(err.clone()),
|
||||||
|
|
|
@ -231,6 +231,13 @@ pub enum Expr {
|
||||||
lookups_in_cond: Vec<(Symbol, Variable)>,
|
lookups_in_cond: Vec<(Symbol, Variable)>,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 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)>,
|
||||||
|
},
|
||||||
|
|
||||||
/// Rendered as empty box in editor
|
/// Rendered as empty box in editor
|
||||||
TypedHole(Variable),
|
TypedHole(Variable),
|
||||||
|
|
||||||
|
@ -277,6 +284,7 @@ impl Expr {
|
||||||
Category::OpaqueWrap(opaque_name)
|
Category::OpaqueWrap(opaque_name)
|
||||||
}
|
}
|
||||||
Self::Expect { .. } => Category::Expect,
|
Self::Expect { .. } => Category::Expect,
|
||||||
|
Self::ExpectFx { .. } => Category::Expect,
|
||||||
|
|
||||||
// these nodes place no constraints on the expression's type
|
// these nodes place no constraints on the expression's type
|
||||||
Self::TypedHole(_) | Self::RuntimeError(..) => Category::Unknown,
|
Self::TypedHole(_) | Self::RuntimeError(..) => Category::Unknown,
|
||||||
|
@ -1772,6 +1780,28 @@ pub fn inline_calls(var_store: &mut VarStore, scope: &mut Scope, expr: Expr) ->
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExpectFx {
|
||||||
|
loc_condition,
|
||||||
|
loc_continuation,
|
||||||
|
lookups_in_cond,
|
||||||
|
} => {
|
||||||
|
let loc_condition = Loc {
|
||||||
|
region: loc_condition.region,
|
||||||
|
value: inline_calls(var_store, scope, loc_condition.value),
|
||||||
|
};
|
||||||
|
|
||||||
|
let loc_continuation = Loc {
|
||||||
|
region: loc_continuation.region,
|
||||||
|
value: inline_calls(var_store, scope, loc_continuation.value),
|
||||||
|
};
|
||||||
|
|
||||||
|
ExpectFx {
|
||||||
|
loc_condition: Box::new(loc_condition),
|
||||||
|
loc_continuation: Box::new(loc_continuation),
|
||||||
|
lookups_in_cond,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LetRec(defs, loc_expr, mark) => {
|
LetRec(defs, loc_expr, mark) => {
|
||||||
let mut new_defs = Vec::with_capacity(defs.len());
|
let mut new_defs = Vec::with_capacity(defs.len());
|
||||||
|
|
||||||
|
@ -2513,13 +2543,13 @@ impl Declarations {
|
||||||
}
|
}
|
||||||
Expectation => {
|
Expectation => {
|
||||||
let loc_expr =
|
let loc_expr =
|
||||||
toplevel_expect_to_inline_expect(self.expressions[index].clone());
|
toplevel_expect_to_inline_expect_pure(self.expressions[index].clone());
|
||||||
|
|
||||||
collector.visit_expr(&loc_expr.value, loc_expr.region, var);
|
collector.visit_expr(&loc_expr.value, loc_expr.region, var);
|
||||||
}
|
}
|
||||||
ExpectationFx => {
|
ExpectationFx => {
|
||||||
let loc_expr =
|
let loc_expr =
|
||||||
toplevel_expect_to_inline_expect(self.expressions[index].clone());
|
toplevel_expect_to_inline_expect_fx(self.expressions[index].clone());
|
||||||
|
|
||||||
collector.visit_expr(&loc_expr.value, loc_expr.region, var);
|
collector.visit_expr(&loc_expr.value, loc_expr.region, var);
|
||||||
}
|
}
|
||||||
|
@ -2658,6 +2688,9 @@ fn get_lookup_symbols(expr: &Expr, var_store: &mut VarStore) -> Vec<(Symbol, Var
|
||||||
}
|
}
|
||||||
Expr::Expect {
|
Expr::Expect {
|
||||||
loc_continuation, ..
|
loc_continuation, ..
|
||||||
|
}
|
||||||
|
| Expr::ExpectFx {
|
||||||
|
loc_continuation, ..
|
||||||
} => {
|
} => {
|
||||||
stack.push(&(*loc_continuation).value);
|
stack.push(&(*loc_continuation).value);
|
||||||
|
|
||||||
|
@ -2705,7 +2738,15 @@ fn get_lookup_symbols(expr: &Expr, var_store: &mut VarStore) -> Vec<(Symbol, Var
|
||||||
/// This is supposed to happen just before monomorphization:
|
/// This is supposed to happen just before monomorphization:
|
||||||
/// all type errors and such are generated from the user source,
|
/// all type errors and such are generated from the user source,
|
||||||
/// but this transformation means that we don't need special codegen for toplevel expects
|
/// but this transformation means that we don't need special codegen for toplevel expects
|
||||||
pub fn toplevel_expect_to_inline_expect(mut loc_expr: Loc<Expr>) -> Loc<Expr> {
|
pub fn toplevel_expect_to_inline_expect_pure(loc_expr: Loc<Expr>) -> Loc<Expr> {
|
||||||
|
toplevel_expect_to_inline_expect_help(loc_expr, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn toplevel_expect_to_inline_expect_fx(loc_expr: Loc<Expr>) -> Loc<Expr> {
|
||||||
|
toplevel_expect_to_inline_expect_help(loc_expr, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn toplevel_expect_to_inline_expect_help(mut loc_expr: Loc<Expr>, has_effects: bool) -> Loc<Expr> {
|
||||||
enum StoredDef {
|
enum StoredDef {
|
||||||
NonRecursive(Region, Box<Def>),
|
NonRecursive(Region, Box<Def>),
|
||||||
Recursive(Region, Vec<Def>, IllegalCycleMark),
|
Recursive(Region, Vec<Def>, IllegalCycleMark),
|
||||||
|
@ -2735,10 +2776,18 @@ pub fn toplevel_expect_to_inline_expect(mut loc_expr: Loc<Expr>) -> Loc<Expr> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let expect_region = loc_expr.region;
|
let expect_region = loc_expr.region;
|
||||||
let expect = Expr::Expect {
|
let expect = if has_effects {
|
||||||
loc_condition: Box::new(loc_expr),
|
Expr::ExpectFx {
|
||||||
loc_continuation: Box::new(Loc::at_zero(Expr::EmptyRecord)),
|
loc_condition: Box::new(loc_expr),
|
||||||
lookups_in_cond,
|
loc_continuation: Box::new(Loc::at_zero(Expr::EmptyRecord)),
|
||||||
|
lookups_in_cond,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Expr::Expect {
|
||||||
|
loc_condition: Box::new(loc_expr),
|
||||||
|
loc_continuation: Box::new(Loc::at_zero(Expr::EmptyRecord)),
|
||||||
|
lookups_in_cond,
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut loc_expr = Loc::at(expect_region, expect);
|
let mut loc_expr = Loc::at(expect_region, expect);
|
||||||
|
|
|
@ -872,6 +872,15 @@ fn fix_values_captured_in_closure_expr(
|
||||||
fix_values_captured_in_closure_expr(&mut loc_continuation.value, no_capture_symbols);
|
fix_values_captured_in_closure_expr(&mut loc_continuation.value, no_capture_symbols);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExpectFx {
|
||||||
|
loc_condition,
|
||||||
|
loc_continuation,
|
||||||
|
lookups_in_cond: _,
|
||||||
|
} => {
|
||||||
|
fix_values_captured_in_closure_expr(&mut loc_condition.value, no_capture_symbols);
|
||||||
|
fix_values_captured_in_closure_expr(&mut loc_continuation.value, no_capture_symbols);
|
||||||
|
}
|
||||||
|
|
||||||
Closure(ClosureData {
|
Closure(ClosureData {
|
||||||
captured_symbols,
|
captured_symbols,
|
||||||
name,
|
name,
|
||||||
|
|
|
@ -276,6 +276,19 @@ pub fn walk_expr<V: Visitor>(visitor: &mut V, expr: &Expr, var: Variable) {
|
||||||
Variable::NULL,
|
Variable::NULL,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Expr::ExpectFx {
|
||||||
|
loc_condition,
|
||||||
|
loc_continuation,
|
||||||
|
lookups_in_cond: _,
|
||||||
|
} => {
|
||||||
|
// TODO: what type does an expect have? bool
|
||||||
|
visitor.visit_expr(&loc_condition.value, loc_condition.region, Variable::NULL);
|
||||||
|
visitor.visit_expr(
|
||||||
|
&loc_continuation.value,
|
||||||
|
loc_continuation.region,
|
||||||
|
Variable::NULL,
|
||||||
|
);
|
||||||
|
}
|
||||||
Expr::TypedHole(_) => { /* terminal */ }
|
Expr::TypedHole(_) => { /* terminal */ }
|
||||||
Expr::RuntimeError(..) => { /* terminal */ }
|
Expr::RuntimeError(..) => { /* terminal */ }
|
||||||
}
|
}
|
||||||
|
|
|
@ -520,6 +520,53 @@ pub fn constrain_expr(
|
||||||
constraints.exists_many(vars, all_constraints)
|
constraints.exists_many(vars, all_constraints)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExpectFx {
|
||||||
|
loc_condition,
|
||||||
|
loc_continuation,
|
||||||
|
lookups_in_cond,
|
||||||
|
} => {
|
||||||
|
let expect_bool = |region| {
|
||||||
|
let bool_type = Type::Variable(Variable::BOOL);
|
||||||
|
Expected::ForReason(Reason::ExpectCondition, bool_type, region)
|
||||||
|
};
|
||||||
|
|
||||||
|
let cond_con = constrain_expr(
|
||||||
|
constraints,
|
||||||
|
env,
|
||||||
|
loc_condition.region,
|
||||||
|
&loc_condition.value,
|
||||||
|
expect_bool(loc_condition.region),
|
||||||
|
);
|
||||||
|
|
||||||
|
let continuation_con = constrain_expr(
|
||||||
|
constraints,
|
||||||
|
env,
|
||||||
|
loc_continuation.region,
|
||||||
|
&loc_continuation.value,
|
||||||
|
expected,
|
||||||
|
);
|
||||||
|
|
||||||
|
// + 2 for cond_con and continuation_con
|
||||||
|
let mut all_constraints = Vec::with_capacity(lookups_in_cond.len() + 2);
|
||||||
|
|
||||||
|
all_constraints.push(cond_con);
|
||||||
|
all_constraints.push(continuation_con);
|
||||||
|
|
||||||
|
let mut vars = Vec::with_capacity(lookups_in_cond.len());
|
||||||
|
|
||||||
|
for (symbol, var) in lookups_in_cond.iter() {
|
||||||
|
vars.push(*var);
|
||||||
|
|
||||||
|
all_constraints.push(constraints.lookup(
|
||||||
|
*symbol,
|
||||||
|
NoExpectation(Type::Variable(*var)),
|
||||||
|
Region::zero(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
constraints.exists_many(vars, all_constraints)
|
||||||
|
}
|
||||||
|
|
||||||
If {
|
If {
|
||||||
cond_var,
|
cond_var,
|
||||||
branch_var,
|
branch_var,
|
||||||
|
|
|
@ -5047,7 +5047,7 @@ fn build_pending_specializations<'a>(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let body = roc_can::expr::toplevel_expect_to_inline_expect(body);
|
let body = roc_can::expr::toplevel_expect_to_inline_expect_pure(body);
|
||||||
|
|
||||||
let proc = PartialProc {
|
let proc = PartialProc {
|
||||||
annotation: expr_var,
|
annotation: expr_var,
|
||||||
|
@ -5121,7 +5121,7 @@ fn build_pending_specializations<'a>(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let body = roc_can::expr::toplevel_expect_to_inline_expect(body);
|
let body = roc_can::expr::toplevel_expect_to_inline_expect_fx(body);
|
||||||
|
|
||||||
let proc = PartialProc {
|
let proc = PartialProc {
|
||||||
annotation: expr_var,
|
annotation: expr_var,
|
||||||
|
|
|
@ -4077,6 +4077,7 @@ pub fn with_hole<'a>(
|
||||||
EmptyRecord => let_empty_struct(assigned, hole),
|
EmptyRecord => let_empty_struct(assigned, hole),
|
||||||
|
|
||||||
Expect { .. } => unreachable!("I think this is unreachable"),
|
Expect { .. } => unreachable!("I think this is unreachable"),
|
||||||
|
ExpectFx { .. } => unreachable!("I think this is unreachable"),
|
||||||
|
|
||||||
If {
|
If {
|
||||||
cond_var,
|
cond_var,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue