mirror of
https://github.com/roc-lang/roc.git
synced 2024-09-20 15:27:45 +03:00
add record_var to Access and Accessor
This commit is contained in:
parent
e62ddc9ef5
commit
b43be95b19
@ -95,6 +95,7 @@ pub enum Expr {
|
||||
|
||||
/// Look up exactly one field on a record, e.g. (expr).foo.
|
||||
Access {
|
||||
record_var: Variable,
|
||||
ext_var: Variable,
|
||||
field_var: Variable,
|
||||
loc_expr: Box<Located<Expr>>,
|
||||
@ -102,6 +103,7 @@ pub enum Expr {
|
||||
},
|
||||
/// field accessor as a function, e.g. (.foo) expr
|
||||
Accessor {
|
||||
record_var: Variable,
|
||||
ext_var: Variable,
|
||||
field_var: Variable,
|
||||
field: Lowercase,
|
||||
@ -488,6 +490,7 @@ pub fn canonicalize_expr<'a>(
|
||||
|
||||
(
|
||||
Access {
|
||||
record_var: var_store.fresh(),
|
||||
field_var: var_store.fresh(),
|
||||
ext_var: var_store.fresh(),
|
||||
loc_expr: Box::new(loc_expr),
|
||||
@ -496,20 +499,15 @@ pub fn canonicalize_expr<'a>(
|
||||
output,
|
||||
)
|
||||
}
|
||||
ast::Expr::AccessorFunction(field) => {
|
||||
let ext_var = var_store.fresh();
|
||||
let field_var = var_store.fresh();
|
||||
let field_name: Lowercase = (*field).into();
|
||||
|
||||
(
|
||||
Accessor {
|
||||
field: field_name,
|
||||
ext_var,
|
||||
field_var,
|
||||
},
|
||||
Output::default(),
|
||||
)
|
||||
}
|
||||
ast::Expr::AccessorFunction(field) => (
|
||||
Accessor {
|
||||
record_var: var_store.fresh(),
|
||||
ext_var: var_store.fresh(),
|
||||
field_var: var_store.fresh(),
|
||||
field: (*field).into(),
|
||||
},
|
||||
Output::default(),
|
||||
),
|
||||
ast::Expr::GlobalTag(tag) => {
|
||||
let variant_var = var_store.fresh();
|
||||
let ext_var = var_store.fresh();
|
||||
|
@ -515,6 +515,7 @@ pub fn constrain_expr(
|
||||
exists(vec![cond_var, *expr_var], And(constraints))
|
||||
}
|
||||
Access {
|
||||
record_var,
|
||||
ext_var,
|
||||
field_var,
|
||||
loc_expr,
|
||||
@ -533,6 +534,8 @@ pub fn constrain_expr(
|
||||
let record_type = Type::Record(rec_field_types, Box::new(ext_type));
|
||||
let record_expected = Expected::NoExpectation(record_type);
|
||||
|
||||
let record_con = Eq(Type::Variable(*record_var), record_expected.clone(), region);
|
||||
|
||||
let constraint = constrain_expr(
|
||||
&Env {
|
||||
home: env.home,
|
||||
@ -544,12 +547,17 @@ pub fn constrain_expr(
|
||||
);
|
||||
|
||||
exists(
|
||||
vec![field_var, ext_var],
|
||||
And(vec![constraint, Eq(field_type, expected, region)]),
|
||||
vec![*record_var, field_var, ext_var],
|
||||
And(vec![
|
||||
constraint,
|
||||
Eq(field_type, expected, region),
|
||||
record_con,
|
||||
]),
|
||||
)
|
||||
}
|
||||
Accessor {
|
||||
field,
|
||||
record_var,
|
||||
ext_var,
|
||||
field_var,
|
||||
} => {
|
||||
@ -563,13 +571,19 @@ pub fn constrain_expr(
|
||||
field_types.insert(label, field_type.clone());
|
||||
let record_type = Type::Record(field_types, Box::new(ext_type));
|
||||
|
||||
let record_expected = Expected::NoExpectation(record_type.clone());
|
||||
let record_con = Eq(Type::Variable(*record_var), record_expected, region);
|
||||
|
||||
exists(
|
||||
vec![field_var, ext_var],
|
||||
Eq(
|
||||
Type::Function(vec![record_type], Box::new(field_type)),
|
||||
expected,
|
||||
region,
|
||||
),
|
||||
vec![*record_var, field_var, ext_var],
|
||||
And(vec![
|
||||
Eq(
|
||||
Type::Function(vec![record_type], Box::new(field_type)),
|
||||
expected,
|
||||
region,
|
||||
),
|
||||
record_con,
|
||||
]),
|
||||
)
|
||||
}
|
||||
LetRec(defs, loc_ret, var, aliases) => {
|
||||
|
@ -1141,6 +1141,7 @@ pub fn constrain_expr(
|
||||
}
|
||||
|
||||
Access {
|
||||
record_var,
|
||||
ext_var,
|
||||
field_var,
|
||||
loc_expr,
|
||||
@ -1163,6 +1164,8 @@ pub fn constrain_expr(
|
||||
);
|
||||
|
||||
let record_expected = Expected::NoExpectation(record_type);
|
||||
let record_con = Eq(Type::Variable(*record_var), record_expected.clone(), region);
|
||||
|
||||
let inner_constraint = constrain_expr(
|
||||
env,
|
||||
var_store,
|
||||
@ -1174,13 +1177,24 @@ pub fn constrain_expr(
|
||||
);
|
||||
|
||||
exists(
|
||||
vec![*field_var, *ext_var, field_uniq_var, record_uniq_var],
|
||||
And(vec![Eq(field_type, expected, region), inner_constraint]),
|
||||
vec![
|
||||
*record_var,
|
||||
*field_var,
|
||||
*ext_var,
|
||||
field_uniq_var,
|
||||
record_uniq_var,
|
||||
],
|
||||
And(vec![
|
||||
Eq(field_type, expected, region),
|
||||
inner_constraint,
|
||||
record_con,
|
||||
]),
|
||||
)
|
||||
}
|
||||
|
||||
Accessor {
|
||||
field,
|
||||
record_var,
|
||||
field_var,
|
||||
ext_var,
|
||||
} => {
|
||||
@ -1200,6 +1214,9 @@ pub fn constrain_expr(
|
||||
Type::Record(field_types, Box::new(Type::Variable(*ext_var))),
|
||||
);
|
||||
|
||||
let record_expected = Expected::NoExpectation(record_type.clone());
|
||||
let record_con = Eq(Type::Variable(*record_var), record_expected, region);
|
||||
|
||||
let fn_uniq_var = var_store.fresh();
|
||||
let fn_type = attr_type(
|
||||
Bool::variable(fn_uniq_var),
|
||||
@ -1208,13 +1225,14 @@ pub fn constrain_expr(
|
||||
|
||||
exists(
|
||||
vec![
|
||||
*record_var,
|
||||
*field_var,
|
||||
*ext_var,
|
||||
fn_uniq_var,
|
||||
field_uniq_var,
|
||||
record_uniq_var,
|
||||
],
|
||||
And(vec![Eq(fn_type, expected, region)]),
|
||||
And(vec![Eq(fn_type, expected, region), record_con]),
|
||||
)
|
||||
}
|
||||
RuntimeError(_) => True,
|
||||
|
@ -681,20 +681,22 @@ fn from_can<'a>(
|
||||
}
|
||||
|
||||
Access {
|
||||
ext_var,
|
||||
record_var,
|
||||
field_var,
|
||||
field,
|
||||
loc_expr,
|
||||
..
|
||||
} => {
|
||||
let arena = env.arena;
|
||||
|
||||
let struct_layout = match Layout::from_var(arena, ext_var, env.subs, env.pointer_size) {
|
||||
Ok(layout) => layout,
|
||||
Err(()) => {
|
||||
// Invalid field!
|
||||
panic!("TODO gracefully handle Access with invalid struct_layout");
|
||||
}
|
||||
};
|
||||
let struct_layout =
|
||||
match Layout::from_var(arena, record_var, env.subs, env.pointer_size) {
|
||||
Ok(layout) => layout,
|
||||
Err(()) => {
|
||||
// Invalid field!
|
||||
panic!("TODO gracefully handle Access with invalid struct_layout");
|
||||
}
|
||||
};
|
||||
|
||||
let field_layout = match Layout::from_var(arena, field_var, env.subs, env.pointer_size)
|
||||
{
|
||||
|
@ -2116,8 +2116,8 @@ mod test_uniq_solve {
|
||||
f
|
||||
"#
|
||||
),
|
||||
"Attr * (Attr (* | a | b) { p : (Attr a *), q : (Attr b *) }* -> Attr * (Num (Attr * *)))",
|
||||
//"Attr * (Attr (* | a | b) { p : (Attr b *), q : (Attr a *) }* -> Attr * (Num (Attr * *)))"
|
||||
//"Attr * (Attr (* | a | b) { p : (Attr a *), q : (Attr b *) }* -> Attr * (Num (Attr * *)))",
|
||||
"Attr * (Attr (* | a | b) { p : (Attr b *), q : (Attr a *) }* -> Attr * (Num (Attr * *)))"
|
||||
);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user