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