refactor to combine params

This commit is contained in:
faldor20 2024-04-02 12:01:26 +10:00
parent 384bf7ca5b
commit 612fa4c75a
No known key found for this signature in database
GPG key ID: F2216079B890CD57
2 changed files with 128 additions and 92 deletions

View file

@ -47,16 +47,28 @@ use super::wrap_in_decode_custom_decode_with;
/// {result: Result.map result \val -> {state & f1: Ok val}, rest}) /// {result: Result.map result \val -> {state & f1: Ok val}, rest})
/// _ -> Skip /// _ -> Skip
/// ///
/// finalizer = \{f0, f1} -> /// finalizer = \rec, fmt ->
/// when f0 is /// when
/// Ok first -> /// when rec.f0 is
/// when f1 is /// Err NoField ->
/// Ok second -> Ok {first, second} /// when Decode.decodeWith [] Decode.decoder fmt is
/// rec2 -> rec2.result
/// Ok a -> Ok a
/// is
/// Ok f0 ->
/// when
/// when rec.f1 is
/// Err NoField ->
/// when Decode.decodeWith [] Decode.decoder fmt is
/// rec2 -> rec2.result
/// Ok a -> Ok a
/// is
/// Ok f1 -> Ok { f1, f0 }
/// Err _ -> Err TooShort /// Err _ -> Err TooShort
/// Err _ -> Err TooShort /// Err _ -> Err TooShort
/// ///
/// Decode.custom \bytes, fmt -> Decode.decodeWith bytes (Decode.record initialState stepField finalizer) fmt /// Decode.custom \bytes, fmt -> Decode.decodeWith bytes (Decode.record initialState stepField finalizer) fmt
/// ``` ///```
pub(crate) fn decoder( pub(crate) fn decoder(
env: &mut Env, env: &mut Env,
_def_symbol: Symbol, _def_symbol: Symbol,
@ -225,12 +237,14 @@ pub(super) fn step_field(
let (decode_custom_ret_var, decode_custom) = custom_decoder( let (decode_custom_ret_var, decode_custom) = custom_decoder(
env, env,
DecodingFieldArgs {
field_name: field_name.clone(),
field_var, field_var,
decode_err_var,
state_record_var,
&field_name,
result_field_var,
state_arg_symbol, state_arg_symbol,
state_record_var,
result_field_var,
decode_err_var,
},
); );
env.unify(keep_payload_var, decode_custom_ret_var); env.unify(keep_payload_var, decode_custom_ret_var);
@ -355,6 +369,14 @@ pub(super) fn step_field(
(expr, function_type) (expr, function_type)
} }
struct DecodingFieldArgs {
field_name: Lowercase,
field_var: Variable,
state_arg_symbol: Symbol,
state_record_var: Variable,
result_field_var: Variable,
decode_err_var: Variable,
}
/// ```roc /// ```roc
/// Decode.custom \bytes, fmt -> /// Decode.custom \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
@ -370,24 +392,8 @@ pub(super) fn step_field(
/// ) /// )
/// ``` /// ```
/// Expression for custom decoder /// Expression for custom decoder
fn custom_decoder( fn custom_decoder(env: &mut Env<'_>, args: DecodingFieldArgs) -> (Variable, Expr) {
env: &mut Env<'_>, let (this_custom_callback_var, custom_callback) = custom_decoder_lambda(env, args);
field_var: Variable,
decode_err_var: Variable,
state_record_var: Variable,
field_name: &Lowercase,
result_field_var: Variable,
state_arg_symbol: Symbol,
) -> (Variable, Expr) {
let (this_custom_callback_var, custom_callback) = custom_decoder_lambda(
env,
field_name,
field_var,
state_arg_symbol,
state_record_var,
result_field_var,
decode_err_var,
);
let decode_custom_ret_var = env.subs.fresh_unnamed_flex_var(); let decode_custom_ret_var = env.subs.fresh_unnamed_flex_var();
let decode_custom = { let decode_custom = {
@ -417,6 +423,7 @@ fn custom_decoder(
}; };
(decode_custom_ret_var, decode_custom) (decode_custom_ret_var, decode_custom)
} }
/// ```roc /// ```roc
/// \bytes, fmt -> /// \bytes, fmt ->
/// when Decode.decodeWith bytes Decode.decoder fmt is /// when Decode.decodeWith bytes Decode.decoder fmt is
@ -429,16 +436,15 @@ fn custom_decoder(
/// } /// }
/// ///
/// ``` /// ```
fn custom_decoder_lambda(env: &mut Env<'_>, args: DecodingFieldArgs) -> (Variable, Expr) {
let DecodingFieldArgs {
field_var,
state_arg_symbol,
state_record_var,
decode_err_var,
..
} = args;
fn custom_decoder_lambda(
env: &mut Env<'_>,
field_name: &Lowercase,
field_var: Variable,
state_arg_symbol: Symbol,
state_record_var: Variable,
result_field_var: Variable,
decode_err_var: Variable,
) -> (Variable, Expr) {
let this_custom_callback_var; let this_custom_callback_var;
let custom_callback_ret_var; let custom_callback_ret_var;
@ -513,17 +519,12 @@ fn custom_decoder_lambda(
// } // }
let branch_body = state_record_update( let branch_body = state_record_update(
env, env,
field_name, args,
field_var,
state_arg_symbol,
state_record_var,
rec_symbol, rec_symbol,
rec_var, rec_var,
rec_dot_result, rec_dot_result,
when_expr_var, when_expr_var,
custom_callback_ret_var, custom_callback_ret_var,
decode_err_var,
result_field_var,
); );
let branch = WhenBranch { let branch = WhenBranch {
@ -611,17 +612,19 @@ fn custom_decoder_lambda(
/// ``` /// ```
fn state_record_update( fn state_record_update(
env: &mut Env<'_>, env: &mut Env<'_>,
field_name: &Lowercase, DecodingFieldArgs {
field_var: Variable, field_name,
state_arg_symbol: Symbol, field_var,
state_record_var: Variable, state_arg_symbol,
state_record_var,
result_field_var,
decode_err_var,
}: DecodingFieldArgs,
rec_symbol: Symbol, rec_symbol: Symbol,
rec_var: Variable, rec_var: Variable,
rec_dot_result: Variable, rec_dot_result: Variable,
when_expr_var: Variable, when_expr_var: Variable,
custom_callback_ret_var: Variable, custom_callback_ret_var: Variable,
decode_err_var: Variable,
result_field_var: Variable,
) -> Expr { ) -> Expr {
{ {
// result: when rec.result is // result: when rec.result is
@ -636,7 +639,7 @@ fn state_record_update(
let mut updates = SendMap::default(); let mut updates = SendMap::default();
updates.insert( updates.insert(
field_name.clone(), field_name,
Field { Field {
var: result_field_var, var: result_field_var,
region: Region::zero(), region: Region::zero(),
@ -776,16 +779,26 @@ fn state_record_update(
} }
} }
// Example: /// Example:
// finalizer = \rec -> /// finalizer = \rec, fmt ->
// when rec.f0 is /// when
// Ok f0 -> /// when rec.f0 is
// when rec.f1 is /// Err NoField ->
// Ok f1 -> Ok {f0, f1} /// when Decode.decodeWith [] Decode.decoder fmt is
// Err _ -> Err TooShort /// rec2 -> rec2.result
// Err _ -> Err TooShort /// Ok a -> Ok a
/// is
// THis is my new one /// Ok f0 ->
/// when
/// when rec.f1 is
/// Err NoField ->
/// when Decode.decodeWith [] Decode.decoder fmt is
/// rec2 -> rec2.result
/// Ok a -> Ok a
/// is
/// Ok f1 -> Ok { f1, f0 }
/// Err _ -> Err TooShort
/// Err _ -> Err TooShort
pub(super) fn finalizer( pub(super) fn finalizer(
env: &mut Env, env: &mut Env,
state_record_var: Variable, state_record_var: Variable,
@ -878,15 +891,17 @@ pub(super) fn finalizer(
// rec2 -> rec2.result // rec2 -> rec2.result
// Ok a -> Ok a // Ok a -> Ok a
let (attempt_empty_decode_expr, attempt_empty_decode_var) = attempt_empty_decode_if_missing( let (attempt_empty_decode_expr, attempt_empty_decode_var) = attempt_empty_decode_if_missing(
state_record_var,
env, env,
DecodingFieldArgs {
field_name: field_name.clone(),
field_var, field_var,
result_field_var,
state_arg_symbol, state_arg_symbol,
field_name, state_record_var,
result_field_var,
decode_err_var,
},
fmt_arg_var, fmt_arg_var,
fmt_arg_symbol, fmt_arg_symbol,
decode_err_var,
symbol, symbol,
); );
@ -1008,15 +1023,17 @@ pub(super) fn finalizer(
/// field_var: The variable of the field in the state record: `Result var NoField` /// field_var: The variable of the field in the state record: `Result var NoField`
/// result_field_var: The variable of the actual field /// result_field_var: The variable of the actual field
fn attempt_empty_decode_if_missing( fn attempt_empty_decode_if_missing(
state_record_var: Variable,
env: &mut Env<'_>, env: &mut Env<'_>,
field_var: Variable, DecodingFieldArgs {
result_field_var: Variable, field_name,
state_arg_symbol: Symbol, field_var,
field_name: &Lowercase, state_arg_symbol,
state_record_var,
result_field_var,
decode_err_var,
}: DecodingFieldArgs,
fmt_arg_var: Variable, fmt_arg_var: Variable,
fmt_arg_symbol: Symbol, fmt_arg_symbol: Symbol,
decode_err_var: Variable,
symbol: &Symbol, symbol: &Symbol,
) -> (Expr, Variable) { ) -> (Expr, Variable) {
let (decode_expr, rec_result, rec_dot_result) = decode_with( let (decode_expr, rec_result, rec_dot_result) = decode_with(
@ -1115,6 +1132,7 @@ fn attempt_empty_decode_if_missing(
}; };
(expr, rec_dot_result) (expr, rec_dot_result)
} }
// Example: // Example:
// initialState : {first: Result a [NoField], second: Result b [NoField]} // initialState : {first: Result a [NoField], second: Result b [NoField]}
// initialState = {first: Err NoField, second: Err NoField} // initialState = {first: Err NoField, second: Err NoField}
@ -1193,6 +1211,20 @@ fn initial_state(
) )
} }
struct DecodeWithVars {
/// Type of the record returned by `Decode.decodeWith`
/// `rec : { rest: List U8, result: (typeof rec.result) }``
rec_var: Variable,
/// Type of the result field of the record returned by `Decode.decodeWith`
rec_dot_result: Variable,
/// type of `Decode.decoder`
decoder_var: Variable,
/// lambda set for `Decode.decodeWith` call
lambda_set_var: Variable,
/// specialised type of this specific call to `Decode.decodeWith`
this_decode_with_var: Variable,
}
/// Makes the vars for decoding this particular field and decode format /// Makes the vars for decoding this particular field and decode format
fn make_decode_with_vars( fn make_decode_with_vars(
env: &mut Env<'_>, env: &mut Env<'_>,
@ -1200,7 +1232,7 @@ fn make_decode_with_vars(
bytes_arg_var: Variable, bytes_arg_var: Variable,
fmt_arg_var: Variable, fmt_arg_var: Variable,
decode_err_var: Variable, decode_err_var: Variable,
) -> (Variable, Variable, Variable, Variable, Variable) { ) -> DecodeWithVars {
// rec.result : [Ok field_var, Err DecodeError] // rec.result : [Ok field_var, Err DecodeError]
let rec_dot_result = { let rec_dot_result = {
let tag_union = FlatType::TagUnion( let tag_union = FlatType::TagUnion(
@ -1242,13 +1274,13 @@ fn make_decode_with_vars(
this_decode_with_var this_decode_with_var
}; };
( DecodeWithVars {
rec_var, rec_var,
rec_dot_result, rec_dot_result,
decoder_var, decoder_var,
lambda_set_var, lambda_set_var,
this_decode_with_var, this_decode_with_var,
) }
} }
/// `Decode.decodeWith bytes Decode.decoder fmt` /// `Decode.decodeWith bytes Decode.decoder fmt`
@ -1265,8 +1297,13 @@ pub(super) fn decode_with(
decode_err_var: Variable, decode_err_var: Variable,
) -> (Expr, Variable, Variable) { ) -> (Expr, Variable, Variable) {
// Creates all the vars we need to call decode_with for the specific field and fmt we are going to call it with // Creates all the vars we need to call decode_with for the specific field and fmt we are going to call it with
let (decode_rec_var, decode_rec_dot_result, decoder_var, lambda_set_var, this_decode_with_var) = let DecodeWithVars {
make_decode_with_vars( rec_var,
rec_dot_result,
decoder_var,
lambda_set_var,
this_decode_with_var,
} = make_decode_with_vars(
env, env,
field_var, field_var,
Variable::LIST_U8, Variable::LIST_U8,
@ -1278,7 +1315,7 @@ pub(super) fn decode_with(
this_decode_with_var, this_decode_with_var,
Loc::at_zero(Expr::Var(Symbol::DECODE_DECODE_WITH, this_decode_with_var)), Loc::at_zero(Expr::Var(Symbol::DECODE_DECODE_WITH, this_decode_with_var)),
lambda_set_var, lambda_set_var,
decode_rec_var, rec_var,
)), )),
vec![ vec![
(Variable::LIST_U8, Loc::at_zero(bytes_arg_expr)), (Variable::LIST_U8, Loc::at_zero(bytes_arg_expr)),
@ -1297,5 +1334,5 @@ pub(super) fn decode_with(
], ],
CalledVia::Space, CalledVia::Space,
); );
(decode_expr, decode_rec_var, decode_rec_dot_result) (decode_expr, rec_var, rec_dot_result)
} }

View file

@ -218,7 +218,6 @@ pub(crate) fn ok_to_ok_branch(
symbol: &Symbol, symbol: &Symbol,
env: &mut Env<'_>, env: &mut Env<'_>,
) -> WhenBranch { ) -> WhenBranch {
WhenBranch { WhenBranch {
patterns: vec![WhenBranchPattern { patterns: vec![WhenBranchPattern {
pattern: Loc::at_zero(Pattern::AppliedTag { pattern: Loc::at_zero(Pattern::AppliedTag {