mirror of
https://github.com/roc-lang/roc.git
synced 2024-09-20 15:27:45 +03:00
Type-check lots of step_field
This commit is contained in:
parent
1587bfbeb5
commit
13e3146ac1
@ -45,8 +45,16 @@ fn decoder_record(env: &mut Env, _def_symbol: Symbol, fields: Vec<Lowercase>) ->
|
|||||||
let mut result_field_vars = Vec::with_capacity(fields.len());
|
let mut result_field_vars = Vec::with_capacity(fields.len());
|
||||||
let (record_var, initial_state) =
|
let (record_var, initial_state) =
|
||||||
decoder_initial_state(env, &fields, &mut field_vars, &mut result_field_vars);
|
decoder_initial_state(env, &fields, &mut field_vars, &mut result_field_vars);
|
||||||
let finalizer = decoder_finalizer(env, record_var, &fields, &field_vars, &result_field_vars);
|
let (finalizer, decode_err_var) =
|
||||||
let step_field = decoder_step_field(env, fields);
|
decoder_finalizer(env, record_var, &fields, &field_vars, &result_field_vars);
|
||||||
|
let step_field = decoder_step_field(
|
||||||
|
env,
|
||||||
|
fields,
|
||||||
|
&field_vars,
|
||||||
|
&result_field_vars,
|
||||||
|
record_var,
|
||||||
|
decode_err_var,
|
||||||
|
);
|
||||||
let expr_var = Variable::NULL; // TODO type of entire expression, namely something like this:
|
let expr_var = Variable::NULL; // TODO type of entire expression, namely something like this:
|
||||||
// Decoder {first: a, second: b} fmt | a has Decoding, b has Decoding, fmt has DecoderFormatting
|
// Decoder {first: a, second: b} fmt | a has Decoding, b has Decoding, fmt has DecoderFormatting
|
||||||
|
|
||||||
@ -172,14 +180,25 @@ fn decoder_record(env: &mut Env, _def_symbol: Symbol, fields: Vec<Lowercase>) ->
|
|||||||
/// {result, rest} ->
|
/// {result, rest} ->
|
||||||
/// {result: Result.map result \val -> {state & second: Ok val}, rest})
|
/// {result: Result.map result \val -> {state & second: Ok val}, rest})
|
||||||
/// _ -> Skip
|
/// _ -> Skip
|
||||||
fn decoder_step_field(env: &mut Env, fields: Vec<Lowercase>) -> Expr {
|
fn decoder_step_field(
|
||||||
|
env: &mut Env,
|
||||||
|
fields: Vec<Lowercase>,
|
||||||
|
field_vars: &[Variable],
|
||||||
|
result_field_vars: &[Variable],
|
||||||
|
state_record_var: Variable,
|
||||||
|
decode_err_var: Variable,
|
||||||
|
) -> Expr {
|
||||||
let state_arg_symbol = env.new_symbol("stateRecord");
|
let state_arg_symbol = env.new_symbol("stateRecord");
|
||||||
let field_arg_symbol = env.new_symbol("field");
|
let field_arg_symbol = env.new_symbol("field");
|
||||||
|
|
||||||
// +1 because of the default branch.
|
// +1 because of the default branch.
|
||||||
let mut branches = Vec::with_capacity(fields.len() + 1);
|
let mut branches = Vec::with_capacity(fields.len() + 1);
|
||||||
|
|
||||||
for field_name in fields {
|
for ((field_name, &field_var), &result_field_var) in fields
|
||||||
|
.into_iter()
|
||||||
|
.zip(field_vars.iter())
|
||||||
|
.zip(result_field_vars.iter())
|
||||||
|
{
|
||||||
// Example:
|
// Example:
|
||||||
// "first" ->
|
// "first" ->
|
||||||
// Keep (Decode.custom \bytes, fmt ->
|
// Keep (Decode.custom \bytes, fmt ->
|
||||||
@ -196,6 +215,8 @@ fn decoder_step_field(env: &mut Env, fields: Vec<Lowercase>) -> Expr {
|
|||||||
// )
|
// )
|
||||||
|
|
||||||
let custom_callback = {
|
let custom_callback = {
|
||||||
|
let rec_var = env.subs.fresh_unnamed_flex_var(); // TODO unify this
|
||||||
|
|
||||||
// \bytes, fmt ->
|
// \bytes, fmt ->
|
||||||
// # Uses a single-branch `when` because `let` is more expensive to monomorphize
|
// # Uses a single-branch `when` because `let` is more expensive to monomorphize
|
||||||
// # due to checks for polymorphic expressions, and `rec` would be polymorphic.
|
// # due to checks for polymorphic expressions, and `rec` would be polymorphic.
|
||||||
@ -209,6 +230,27 @@ fn decoder_step_field(env: &mut Env, fields: Vec<Lowercase>) -> Expr {
|
|||||||
// }
|
// }
|
||||||
let bytes_arg_symbol = env.new_symbol("bytes");
|
let bytes_arg_symbol = env.new_symbol("bytes");
|
||||||
let fmt_arg_symbol = env.new_symbol("fmt");
|
let fmt_arg_symbol = env.new_symbol("fmt");
|
||||||
|
let when_expr_var = {
|
||||||
|
let flat_type = FlatType::TagUnion(
|
||||||
|
UnionTags::for_result(env.subs, state_record_var, decode_err_var),
|
||||||
|
Variable::EMPTY_TAG_UNION,
|
||||||
|
);
|
||||||
|
|
||||||
|
synth_var(env.subs, Content::Structure(flat_type))
|
||||||
|
};
|
||||||
|
let custom_callback_ret_var = {
|
||||||
|
let rest_field = RecordField::Required(Variable::LIST_U8);
|
||||||
|
let result_field = RecordField::Required(when_expr_var);
|
||||||
|
let flat_type = FlatType::Record(
|
||||||
|
RecordFields::insert_into_subs(
|
||||||
|
env.subs,
|
||||||
|
[("rest".into(), rest_field), ("result".into(), result_field)],
|
||||||
|
),
|
||||||
|
Variable::EMPTY_RECORD,
|
||||||
|
);
|
||||||
|
|
||||||
|
synth_var(env.subs, Content::Structure(flat_type))
|
||||||
|
};
|
||||||
|
|
||||||
let custom_callback_body = {
|
let custom_callback_body = {
|
||||||
let rec_symbol = env.new_symbol("rec");
|
let rec_symbol = env.new_symbol("rec");
|
||||||
@ -224,28 +266,17 @@ fn decoder_step_field(env: &mut Env, fields: Vec<Lowercase>) -> Expr {
|
|||||||
// Err err -> Err err
|
// Err err -> Err err
|
||||||
// }
|
// }
|
||||||
let branch_body = {
|
let branch_body = {
|
||||||
// {
|
// when rec.result is
|
||||||
// rest: rec.rest,
|
// Ok val -> Ok {state & first: Ok val},
|
||||||
// result: when rec.result is
|
// Err err -> Err err
|
||||||
// Ok val -> Ok {state & first: Ok val},
|
let rec_dot_result = {
|
||||||
// Err err -> Err err
|
let flat_type = FlatType::TagUnion(
|
||||||
// }
|
UnionTags::for_result(env.subs, field_var, decode_err_var),
|
||||||
let mut fields_map = SendMap::default();
|
Variable::EMPTY_TAG_UNION,
|
||||||
|
);
|
||||||
|
|
||||||
fields_map.insert(
|
synth_var(env.subs, Content::Structure(flat_type))
|
||||||
"rest".into(),
|
};
|
||||||
Field {
|
|
||||||
var: Variable::NULL, // TODO
|
|
||||||
region: Region::zero(),
|
|
||||||
loc_expr: Box::new(Loc::at_zero(Expr::Access {
|
|
||||||
record_var: Variable::NULL, // TODO
|
|
||||||
ext_var: Variable::EMPTY_RECORD,
|
|
||||||
field_var: Variable::NULL, // TODO
|
|
||||||
loc_expr: Box::new(Loc::at_zero(Expr::Var(rec_symbol))),
|
|
||||||
field: "rest".into(),
|
|
||||||
})),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
let result_val = {
|
let result_val = {
|
||||||
// result: when rec.result is
|
// result: when rec.result is
|
||||||
@ -253,7 +284,6 @@ fn decoder_step_field(env: &mut Env, fields: Vec<Lowercase>) -> Expr {
|
|||||||
// Err err -> Err err
|
// Err err -> Err err
|
||||||
let ok_val_symbol = env.new_symbol("val");
|
let ok_val_symbol = env.new_symbol("val");
|
||||||
let err_val_symbol = env.new_symbol("err");
|
let err_val_symbol = env.new_symbol("err");
|
||||||
|
|
||||||
let ok_branch_expr = {
|
let ok_branch_expr = {
|
||||||
// Ok {state & first: Ok val},
|
// Ok {state & first: Ok val},
|
||||||
let mut updates = SendMap::default();
|
let mut updates = SendMap::default();
|
||||||
@ -261,14 +291,14 @@ fn decoder_step_field(env: &mut Env, fields: Vec<Lowercase>) -> Expr {
|
|||||||
updates.insert(
|
updates.insert(
|
||||||
field_name.clone(),
|
field_name.clone(),
|
||||||
Field {
|
Field {
|
||||||
var: Variable::NULL, // TODO
|
var: result_field_var,
|
||||||
region: Region::zero(),
|
region: Region::zero(),
|
||||||
loc_expr: Box::new(Loc::at_zero(Expr::Tag {
|
loc_expr: Box::new(Loc::at_zero(Expr::Tag {
|
||||||
tag_union_var: Variable::NULL, // TODO
|
tag_union_var: result_field_var,
|
||||||
ext_var: Variable::NULL, // TODO
|
ext_var: Variable::EMPTY_TAG_UNION,
|
||||||
name: "Ok".into(),
|
name: "Ok".into(),
|
||||||
arguments: vec![(
|
arguments: vec![(
|
||||||
Variable::NULL, // TODO
|
field_var,
|
||||||
Loc::at_zero(Expr::Var(ok_val_symbol)),
|
Loc::at_zero(Expr::Var(ok_val_symbol)),
|
||||||
)],
|
)],
|
||||||
})),
|
})),
|
||||||
@ -276,20 +306,17 @@ fn decoder_step_field(env: &mut Env, fields: Vec<Lowercase>) -> Expr {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let updated_record = Expr::Update {
|
let updated_record = Expr::Update {
|
||||||
record_var: Variable::NULL, // TODO
|
record_var: state_record_var,
|
||||||
ext_var: Variable::EMPTY_RECORD,
|
ext_var: Variable::EMPTY_RECORD,
|
||||||
symbol: state_arg_symbol,
|
symbol: state_arg_symbol,
|
||||||
updates,
|
updates,
|
||||||
};
|
};
|
||||||
|
|
||||||
Expr::Tag {
|
Expr::Tag {
|
||||||
tag_union_var: Variable::NULL, // TODO
|
tag_union_var: when_expr_var,
|
||||||
ext_var: Variable::NULL, // TODO
|
ext_var: Variable::EMPTY_TAG_UNION,
|
||||||
name: "Ok".into(),
|
name: "Ok".into(),
|
||||||
arguments: vec![(
|
arguments: vec![(state_record_var, Loc::at_zero(updated_record))],
|
||||||
Variable::NULL, // TODO
|
|
||||||
Loc::at_zero(updated_record),
|
|
||||||
)],
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -298,11 +325,11 @@ fn decoder_step_field(env: &mut Env, fields: Vec<Lowercase>) -> Expr {
|
|||||||
WhenBranch {
|
WhenBranch {
|
||||||
patterns: vec![WhenBranchPattern {
|
patterns: vec![WhenBranchPattern {
|
||||||
pattern: Loc::at_zero(Pattern::AppliedTag {
|
pattern: Loc::at_zero(Pattern::AppliedTag {
|
||||||
whole_var: Variable::NULL, // TODO
|
whole_var: rec_dot_result,
|
||||||
ext_var: Variable::EMPTY_TAG_UNION,
|
ext_var: Variable::EMPTY_TAG_UNION,
|
||||||
tag_name: "Ok".into(),
|
tag_name: "Ok".into(),
|
||||||
arguments: vec![(
|
arguments: vec![(
|
||||||
Variable::NULL, // TODO
|
field_var,
|
||||||
Loc::at_zero(Pattern::Identifier(ok_val_symbol)),
|
Loc::at_zero(Pattern::Identifier(ok_val_symbol)),
|
||||||
)],
|
)],
|
||||||
}),
|
}),
|
||||||
@ -316,22 +343,22 @@ fn decoder_step_field(env: &mut Env, fields: Vec<Lowercase>) -> Expr {
|
|||||||
WhenBranch {
|
WhenBranch {
|
||||||
patterns: vec![WhenBranchPattern {
|
patterns: vec![WhenBranchPattern {
|
||||||
pattern: Loc::at_zero(Pattern::AppliedTag {
|
pattern: Loc::at_zero(Pattern::AppliedTag {
|
||||||
whole_var: Variable::NULL, // TODO
|
whole_var: rec_dot_result,
|
||||||
ext_var: Variable::EMPTY_TAG_UNION,
|
ext_var: Variable::EMPTY_TAG_UNION,
|
||||||
tag_name: "Err".into(),
|
tag_name: "Err".into(),
|
||||||
arguments: vec![(
|
arguments: vec![(
|
||||||
Variable::NULL, // TODO
|
decode_err_var,
|
||||||
Loc::at_zero(Pattern::Identifier(err_val_symbol)),
|
Loc::at_zero(Pattern::Identifier(err_val_symbol)),
|
||||||
)],
|
)],
|
||||||
}),
|
}),
|
||||||
degenerate: false,
|
degenerate: false,
|
||||||
}],
|
}],
|
||||||
value: Loc::at_zero(Expr::Tag {
|
value: Loc::at_zero(Expr::Tag {
|
||||||
tag_union_var: Variable::NULL, // TODO
|
tag_union_var: when_expr_var,
|
||||||
ext_var: Variable::NULL, // TODO
|
ext_var: Variable::EMPTY_TAG_UNION,
|
||||||
name: "Err".into(),
|
name: "Err".into(),
|
||||||
arguments: vec![(
|
arguments: vec![(
|
||||||
Variable::NULL, // TODO
|
decode_err_var,
|
||||||
Loc::at_zero(Expr::Var(err_val_symbol)),
|
Loc::at_zero(Expr::Var(err_val_symbol)),
|
||||||
)],
|
)],
|
||||||
}),
|
}),
|
||||||
@ -345,32 +372,58 @@ fn decoder_step_field(env: &mut Env, fields: Vec<Lowercase>) -> Expr {
|
|||||||
// Err err -> Err err
|
// Err err -> Err err
|
||||||
Expr::When {
|
Expr::When {
|
||||||
loc_cond: Box::new(Loc::at_zero(Expr::Access {
|
loc_cond: Box::new(Loc::at_zero(Expr::Access {
|
||||||
record_var: Variable::NULL, // TODO
|
record_var: rec_var,
|
||||||
ext_var: Variable::EMPTY_RECORD,
|
ext_var: Variable::EMPTY_RECORD,
|
||||||
field_var: Variable::NULL, // TODO
|
field_var: rec_dot_result,
|
||||||
loc_expr: Box::new(Loc::at_zero(Expr::Var(rec_symbol))),
|
loc_expr: Box::new(Loc::at_zero(Expr::Var(rec_symbol))),
|
||||||
field: "result".into(),
|
field: "result".into(),
|
||||||
})),
|
})),
|
||||||
cond_var: Variable::NULL, // TODO
|
cond_var: rec_dot_result,
|
||||||
expr_var: Variable::NULL, // TODO
|
expr_var: when_expr_var,
|
||||||
region: Region::zero(),
|
region: Region::zero(),
|
||||||
branches,
|
branches,
|
||||||
branches_cond_var: Variable::NULL, // TODO
|
branches_cond_var: rec_dot_result,
|
||||||
exhaustive: ExhaustiveMark::known_exhaustive(),
|
exhaustive: ExhaustiveMark::known_exhaustive(),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// {
|
||||||
|
// rest: rec.rest,
|
||||||
|
// result: when rec.result is
|
||||||
|
// Ok val -> Ok {state & first: Ok val},
|
||||||
|
// Err err -> Err err
|
||||||
|
// }
|
||||||
|
let mut fields_map = SendMap::default();
|
||||||
|
|
||||||
|
fields_map.insert(
|
||||||
|
"rest".into(),
|
||||||
|
Field {
|
||||||
|
var: Variable::LIST_U8,
|
||||||
|
region: Region::zero(),
|
||||||
|
loc_expr: Box::new(Loc::at_zero(Expr::Access {
|
||||||
|
record_var: rec_var,
|
||||||
|
ext_var: Variable::EMPTY_RECORD,
|
||||||
|
field_var: Variable::LIST_U8,
|
||||||
|
loc_expr: Box::new(Loc::at_zero(Expr::Var(rec_symbol))),
|
||||||
|
field: "rest".into(),
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// result: when rec.result is
|
||||||
|
// Ok val -> Ok {state & first: Ok val},
|
||||||
|
// Err err -> Err err
|
||||||
fields_map.insert(
|
fields_map.insert(
|
||||||
"result".into(),
|
"result".into(),
|
||||||
Field {
|
Field {
|
||||||
var: Variable::NULL, // TODO
|
var: when_expr_var,
|
||||||
region: Region::zero(),
|
region: Region::zero(),
|
||||||
loc_expr: Box::new(Loc::at_zero(result_val)),
|
loc_expr: Box::new(Loc::at_zero(result_val)),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
Expr::Record {
|
Expr::Record {
|
||||||
record_var: Variable::NULL, // TODO this is the type of the entire record
|
record_var: custom_callback_ret_var,
|
||||||
fields: fields_map,
|
fields: fields_map,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -412,7 +465,7 @@ fn decoder_step_field(env: &mut Env, fields: Vec<Lowercase>) -> Expr {
|
|||||||
Expr::When {
|
Expr::When {
|
||||||
loc_cond: Box::new(Loc::at_zero(condition_expr)),
|
loc_cond: Box::new(Loc::at_zero(condition_expr)),
|
||||||
cond_var: Variable::NULL, // TODO
|
cond_var: Variable::NULL, // TODO
|
||||||
expr_var: Variable::NULL, // TODO
|
expr_var: custom_callback_ret_var,
|
||||||
region: Region::zero(),
|
region: Region::zero(),
|
||||||
branches: vec![branch],
|
branches: vec![branch],
|
||||||
branches_cond_var: Variable::NULL, // TODO
|
branches_cond_var: Variable::NULL, // TODO
|
||||||
@ -590,7 +643,7 @@ fn decoder_finalizer(
|
|||||||
fields: &[Lowercase],
|
fields: &[Lowercase],
|
||||||
field_vars: &[Variable],
|
field_vars: &[Variable],
|
||||||
result_field_vars: &[Variable],
|
result_field_vars: &[Variable],
|
||||||
) -> Expr {
|
) -> (Expr, Variable) {
|
||||||
let state_arg_symbol = env.new_symbol("stateRecord");
|
let state_arg_symbol = env.new_symbol("stateRecord");
|
||||||
let mut fields_map = SendMap::default();
|
let mut fields_map = SendMap::default();
|
||||||
let mut pattern_symbols = Vec::with_capacity(fields.len());
|
let mut pattern_symbols = Vec::with_capacity(fields.len());
|
||||||
@ -738,7 +791,7 @@ fn decoder_finalizer(
|
|||||||
env.subs
|
env.subs
|
||||||
.set_content(function_var, Content::Structure(flat_type));
|
.set_content(function_var, Content::Structure(flat_type));
|
||||||
|
|
||||||
Expr::Closure(ClosureData {
|
let finalizer = Expr::Closure(ClosureData {
|
||||||
function_type: function_var,
|
function_type: function_var,
|
||||||
closure_type,
|
closure_type,
|
||||||
return_type: return_type_var,
|
return_type: return_type_var,
|
||||||
@ -751,7 +804,9 @@ fn decoder_finalizer(
|
|||||||
Loc::at_zero(Pattern::Identifier(state_arg_symbol)),
|
Loc::at_zero(Pattern::Identifier(state_arg_symbol)),
|
||||||
)],
|
)],
|
||||||
loc_body: Box::new(Loc::at_zero(body)),
|
loc_body: Box::new(Loc::at_zero(body)),
|
||||||
})
|
});
|
||||||
|
|
||||||
|
(finalizer, decode_err_var)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Example:
|
/// Example:
|
||||||
|
Loading…
Reference in New Issue
Block a user