mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-02 08:11:12 +00:00
Store and use Variable in Let/LetRec
This commit is contained in:
parent
dcf79c469f
commit
be9f784eca
6 changed files with 44 additions and 25 deletions
|
@ -870,7 +870,7 @@ pub fn can_defs_with_return<'a>(
|
|||
for declaration in decls.into_iter().rev() {
|
||||
loc_expr = Located {
|
||||
region: Region::zero(),
|
||||
value: decl_to_let(declaration, loc_expr),
|
||||
value: decl_to_let(var_store, declaration, loc_expr),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -880,10 +880,12 @@ pub fn can_defs_with_return<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
fn decl_to_let(decl: Declaration, loc_ret: Located<Expr>) -> Expr {
|
||||
fn decl_to_let(var_store: &VarStore, decl: Declaration, loc_ret: Located<Expr>) -> Expr {
|
||||
match decl {
|
||||
Declaration::Declare(def) => Expr::LetNonRec(Box::new(def), Box::new(loc_ret)),
|
||||
Declaration::DeclareRec(defs) => Expr::LetRec(defs, Box::new(loc_ret)),
|
||||
Declaration::Declare(def) => {
|
||||
Expr::LetNonRec(Box::new(def), Box::new(loc_ret), var_store.fresh())
|
||||
}
|
||||
Declaration::DeclareRec(defs) => Expr::LetRec(defs, Box::new(loc_ret), var_store.fresh()),
|
||||
Declaration::InvalidCycle(symbols, regions) => {
|
||||
Expr::RuntimeError(RuntimeError::CircularDef(symbols, regions))
|
||||
}
|
||||
|
|
|
@ -56,8 +56,8 @@ pub enum Expr {
|
|||
loc_cond: Box<Located<Expr>>,
|
||||
branches: Vec<(Located<Pattern>, Located<Expr>)>,
|
||||
},
|
||||
LetRec(Vec<Def>, Box<Located<Expr>>),
|
||||
LetNonRec(Box<Def>, Box<Located<Expr>>),
|
||||
LetRec(Vec<Def>, Box<Located<Expr>>, Variable),
|
||||
LetNonRec(Box<Def>, Box<Located<Expr>>, Variable),
|
||||
|
||||
/// This is *only* for calling functions, not for tag application.
|
||||
/// The Tag variant contains any applied values inside it.
|
||||
|
|
|
@ -393,17 +393,28 @@ pub fn constrain_expr(
|
|||
),
|
||||
)
|
||||
}
|
||||
LetRec(defs, loc_ret) => constrain_defs_with_return(
|
||||
rigids,
|
||||
defs,
|
||||
expected,
|
||||
Info::with_capacity(defs.len()),
|
||||
Info::with_capacity(defs.len()),
|
||||
loc_ret,
|
||||
),
|
||||
LetNonRec(def, loc_ret) => {
|
||||
let body_con = constrain_expr(rigids, loc_ret.region, &loc_ret.value, expected);
|
||||
constrain_def(rigids, &mut SendMap::default(), def, body_con)
|
||||
LetRec(defs, loc_ret, var) => And(vec![
|
||||
constrain_defs_with_return(
|
||||
rigids,
|
||||
defs,
|
||||
expected.clone(),
|
||||
Info::with_capacity(defs.len()),
|
||||
Info::with_capacity(defs.len()),
|
||||
loc_ret,
|
||||
),
|
||||
// Record the type of tne entire def-expression in the variable.
|
||||
// Code gen will need that later!
|
||||
Eq(Type::Variable(*var), expected, loc_ret.region),
|
||||
]),
|
||||
LetNonRec(def, loc_ret, var) => {
|
||||
let body_con = constrain_expr(rigids, loc_ret.region, &loc_ret.value, expected.clone());
|
||||
|
||||
And(vec![
|
||||
constrain_def(rigids, &mut SendMap::default(), def, body_con),
|
||||
// Record the type of tne entire def-expression in the variable.
|
||||
// Code gen will need that later!
|
||||
Eq(Type::Variable(*var), expected, loc_ret.region),
|
||||
])
|
||||
}
|
||||
Tag(_, _) => {
|
||||
panic!("TODO constrain Tag");
|
||||
|
|
|
@ -197,7 +197,7 @@ fn compile_expr<'ctx, 'env>(
|
|||
panic!("TODO support when-expressions of more than 2 branches.");
|
||||
}
|
||||
}
|
||||
LetNonRec(ref def, ref loc_ret) => {
|
||||
LetNonRec(ref def, ref loc_ret, _) => {
|
||||
match &def.loc_pattern.value {
|
||||
Pattern::Identifier(symbol) => {
|
||||
let expr = &def.loc_expr.value;
|
||||
|
@ -241,8 +241,11 @@ fn content_from_expr(scope: &Scope<'_>, subs: &Subs, expr: &Expr) -> Content {
|
|||
use crate::can::expr::Expr::*;
|
||||
|
||||
match expr {
|
||||
Int(var, _) => subs.get_without_compacting(*var).content,
|
||||
Float(var, _) => subs.get_without_compacting(*var).content,
|
||||
Int(var, _)
|
||||
| Float(var, _)
|
||||
| When { expr_var: var, .. }
|
||||
| LetNonRec(_, _, var)
|
||||
| LetRec(_, _, var) => subs.get_without_compacting(*var).content,
|
||||
Str(_) | BlockStr(_) => Content::Structure(FlatType::Apply {
|
||||
module_name: "Str".into(),
|
||||
name: "Str".into(),
|
||||
|
@ -253,7 +256,10 @@ fn content_from_expr(scope: &Scope<'_>, subs: &Subs, expr: &Expr) -> Content {
|
|||
..
|
||||
} => {
|
||||
let (content, _) = scope.get(resolved_symbol).unwrap_or_else(|| {
|
||||
panic!("Couldn't find {:?} in scope {:?}", resolved_symbol, scope)
|
||||
panic!(
|
||||
"Code gen problem: Couldn't find {:?} in scope {:?}",
|
||||
resolved_symbol, scope
|
||||
)
|
||||
});
|
||||
|
||||
content.clone()
|
||||
|
|
|
@ -474,11 +474,11 @@ pub fn canonicalize_expr(
|
|||
),
|
||||
)
|
||||
}
|
||||
LetRec(defs, loc_ret) => (
|
||||
LetRec(defs, loc_ret, _) => (
|
||||
Output::default(),
|
||||
can_defs(rigids, var_store, var_usage, defs, expected, loc_ret),
|
||||
),
|
||||
LetNonRec(def, loc_ret) => {
|
||||
LetNonRec(def, loc_ret, _) => {
|
||||
let (_, body_con) = canonicalize_expr(
|
||||
rigids,
|
||||
var_store,
|
||||
|
|
|
@ -262,14 +262,14 @@ mod test_canonicalize {
|
|||
|
||||
fn get_closure(expr: &Expr, i: usize) -> roc::can::expr::Recursive {
|
||||
match expr {
|
||||
LetRec(assignments, _) => match &assignments.get(i).map(|def| &def.loc_expr.value) {
|
||||
LetRec(assignments, _, _) => match &assignments.get(i).map(|def| &def.loc_expr.value) {
|
||||
Some(Closure(_, recursion, _, _)) => recursion.clone(),
|
||||
Some(other @ _) => {
|
||||
panic!("assignment at {} is not a closure, but a {:?}", i, other)
|
||||
}
|
||||
None => panic!("Looking for assignment at {} but the list is too short", i),
|
||||
},
|
||||
LetNonRec(def, body) => {
|
||||
LetNonRec(def, body, _) => {
|
||||
if i > 0 {
|
||||
// recurse in the body (not the def!)
|
||||
get_closure(&body.value, i - 1)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue