add record_var to Access and Accessor

This commit is contained in:
Folkert 2020-03-14 01:13:44 +01:00
parent e62ddc9ef5
commit b43be95b19
5 changed files with 67 additions and 35 deletions

View File

@ -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();

View File

@ -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) => {

View File

@ -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,

View File

@ -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)
{

View File

@ -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 * *)))"
);
}