Merge pull request #5179 from roc-lang/i5143-tuple-abilities

Implement ability obligation checking and derivation for tuples
This commit is contained in:
Ayaz 2023-03-25 15:51:39 -05:00 committed by GitHub
commit 61dd5cc8c7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
36 changed files with 4225 additions and 2296 deletions

View file

@ -23,6 +23,7 @@ interface Decode
string,
list,
record,
tuple,
custom,
decodeWith,
fromBytesPartial,
@ -43,6 +44,7 @@ interface Decode
I32,
I64,
I128,
Nat,
F32,
F64,
Dec,
@ -76,8 +78,24 @@ DecoderFormatting has
bool : Decoder Bool fmt | fmt has DecoderFormatting
string : Decoder Str fmt | fmt has DecoderFormatting
list : Decoder elem fmt -> Decoder (List elem) fmt | fmt has DecoderFormatting
## `record state stepField finalizer` decodes a record field-by-field.
##
## `stepField` returns a decoder for the given field in the record, or
## `Skip` if the field is not a part of the decoded record.
##
## `finalizer` should produce the record value from the decoded `state`.
record : state, (state, Str -> [Keep (Decoder state fmt), Skip]), (state -> Result val DecodeError) -> Decoder val fmt | fmt has DecoderFormatting
## `tuple state stepElem finalizer` decodes a tuple element-by-element.
##
## `stepElem` returns a decoder for the nth index in the tuple, or
## `TooLong` if the index is larger than the expected size of the tuple. The
## index passed to `stepElem` is 0-indexed.
##
## `finalizer` should produce the tuple value from the decoded `state`.
tuple : state, (state, Nat -> [Next (Decoder state fmt), TooLong]), (state -> Result val DecodeError) -> Decoder val fmt | fmt has DecoderFormatting
custom : (List U8, fmt -> DecodeResult val) -> Decoder val fmt | fmt has DecoderFormatting
custom = \decode -> @Decoder decode

View file

@ -22,6 +22,7 @@ interface Encode
list,
record,
tag,
tuple,
custom,
appendWith,
append,
@ -69,6 +70,7 @@ EncoderFormatting has
string : Str -> Encoder fmt | fmt has EncoderFormatting
list : List elem, (elem -> Encoder fmt) -> Encoder fmt | fmt has EncoderFormatting
record : List { key : Str, value : Encoder fmt } -> Encoder fmt | fmt has EncoderFormatting
tuple : List (Encoder fmt) -> Encoder fmt | fmt has EncoderFormatting
tag : Str, List (Encoder fmt) -> Encoder fmt | fmt has EncoderFormatting
custom : (List U8, fmt -> List U8) -> Encoder fmt | fmt has EncoderFormatting

View file

@ -96,6 +96,7 @@ Json := {} has [
string: encodeString,
list: encodeList,
record: encodeRecord,
tuple: encodeTuple,
tag: encodeTag,
},
DecoderFormatting {
@ -116,6 +117,7 @@ Json := {} has [
string: decodeString,
list: decodeList,
record: decodeRecord,
tuple: decodeTuple,
},
]
@ -207,6 +209,25 @@ encodeRecord = \fields ->
List.append bytesWithRecord (Num.toU8 '}')
encodeTuple = \elems ->
Encode.custom \bytes, @Json {} ->
writeTuple = \{ buffer, elemsLeft }, elemEncoder ->
bufferWithElem =
appendWith buffer elemEncoder (@Json {})
bufferWithSuffix =
if elemsLeft > 1 then
List.append bufferWithElem (Num.toU8 ',')
else
bufferWithElem
{ buffer: bufferWithSuffix, elemsLeft: elemsLeft - 1 }
bytesHead = List.append bytes (Num.toU8 '[')
{ buffer: bytesWithRecord } = List.walk elems { buffer: bytesHead, elemsLeft: List.len elems } writeTuple
List.append bytesWithRecord (Num.toU8 ']')
encodeTag = \name, payload ->
Encode.custom \bytes, @Json {} ->
# Idea: encode `A v1 v2` as `{"A": [v1, v2]}`
@ -477,6 +498,12 @@ openBrace = \bytes -> parseExactChar bytes '{'
closingBrace : List U8 -> DecodeResult {}
closingBrace = \bytes -> parseExactChar bytes '}'
openBracket : List U8 -> DecodeResult {}
openBracket = \bytes -> parseExactChar bytes '['
closingBracket : List U8 -> DecodeResult {}
closingBracket = \bytes -> parseExactChar bytes ']'
recordKey : List U8 -> DecodeResult Str
recordKey = \bytes -> jsonString bytes
@ -527,6 +554,36 @@ decodeRecord = \initialState, stepField, finalizer -> Decode.custom \bytes, @Jso
Ok val -> { result: Ok val, rest: afterRecordBytes }
Err e -> { result: Err e, rest: afterRecordBytes }
decodeTuple = \initialState, stepElem, finalizer -> Decode.custom \initialBytes, @Json {} ->
# NB: the stepper function must be passed explicitly until #2894 is resolved.
decodeElems = \stepper, state, index, bytes ->
{ val: newState, rest: beforeCommaOrBreak } <- tryDecode
(
when stepper state index is
TooLong ->
{ rest: beforeCommaOrBreak } <- bytes |> anything |> tryDecode
{ result: Ok state, rest: beforeCommaOrBreak }
Next decoder ->
Decode.decodeWith bytes decoder (@Json {})
)
{ result: commaResult, rest: nextBytes } = comma beforeCommaOrBreak
when commaResult is
Ok {} -> decodeElems stepElem newState (index + 1) nextBytes
Err _ -> { result: Ok newState, rest: nextBytes }
{ rest: afterBracketBytes } <- initialBytes |> openBracket |> tryDecode
{ val: endStateResult, rest: beforeClosingBracketBytes } <- decodeElems stepElem initialState 0 afterBracketBytes |> tryDecode
{ rest: afterTupleBytes } <- beforeClosingBracketBytes |> closingBracket |> tryDecode
when finalizer endStateResult is
Ok val -> { result: Ok val, rest: afterTupleBytes }
Err e -> { result: Err e, rest: afterTupleBytes }
# Helper to eat leading Json whitespace characters
eatWhitespace = \input ->
when input is

View file

@ -330,7 +330,11 @@ fn expr<'a>(c: &Ctx, p: EPrec, f: &'a Arena<'a>, e: &'a Expr) -> DocBuilder<'a,
} => expr(c, AppArg, f, &loc_expr.value)
.append(f.text(format!(".{}", field.as_str())))
.group(),
TupleAccess { .. } => todo!(),
TupleAccess {
loc_expr, index, ..
} => expr(c, AppArg, f, &loc_expr.value)
.append(f.text(format!(".{index}")))
.group(),
OpaqueWrapFunction(OpaqueWrapFunctionData { opaque_name, .. }) => {
f.text(format!("@{}", opaque_name.as_str(c.interns)))
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,104 @@
use roc_can::expr::Expr;
use roc_error_macros::internal_error;
use roc_module::called_via::CalledVia;
use roc_module::symbol::Symbol;
use roc_region::all::Loc;
use roc_types::subs::{Content, FlatType, GetSubsSlice, SubsSlice, Variable};
use roc_types::types::AliasKind;
use crate::decoding::wrap_in_decode_custom_decode_with;
use crate::synth_var;
use crate::util::Env;
pub(crate) fn decoder(env: &mut Env<'_>, _def_symbol: Symbol) -> (Expr, Variable) {
// Build
//
// def_symbol : Decoder (List elem) fmt | elem has Decoding, fmt has DecoderFormatting
// def_symbol = Decode.custom \bytes, fmt -> Decode.decodeWith bytes (Decode.list Decode.decoder) fmt
//
// NB: reduction to `Decode.list Decode.decoder` is not possible to the HRR.
use Expr::*;
// Decode.list Decode.decoder : Decoder (List elem) fmt
let (decode_list_call, this_decode_list_ret_var) = {
// List elem
let elem_var = env.subs.fresh_unnamed_flex_var();
// Decode.decoder : Decoder elem fmt | elem has Decoding, fmt has EncoderFormatting
let (elem_decoder, elem_decoder_var) = {
// build `Decode.decoder : Decoder elem fmt` type
// Decoder val fmt | val has Decoding, fmt has EncoderFormatting
let elem_decoder_var = env.import_builtin_symbol_var(Symbol::DECODE_DECODER);
// set val ~ elem
let val_var = match env.subs.get_content_without_compacting(elem_decoder_var) {
Content::Alias(Symbol::DECODE_DECODER_OPAQUE, vars, _, AliasKind::Opaque)
if vars.type_variables_len == 2 =>
{
env.subs.get_subs_slice(vars.type_variables())[0]
}
_ => internal_error!("Decode.decode not an opaque type"),
};
env.unify(val_var, elem_var);
(
AbilityMember(Symbol::DECODE_DECODER, None, elem_decoder_var),
elem_decoder_var,
)
};
// Build `Decode.list Decode.decoder` type
// Decoder val fmt -[uls]-> Decoder (List val) fmt | fmt has DecoderFormatting
let decode_list_fn_var = env.import_builtin_symbol_var(Symbol::DECODE_LIST);
// Decoder elem fmt -a-> b
let elem_decoder_var_slice = SubsSlice::insert_into_subs(env.subs, [elem_decoder_var]);
let this_decode_list_clos_var = env.subs.fresh_unnamed_flex_var();
let this_decode_list_ret_var = env.subs.fresh_unnamed_flex_var();
let this_decode_list_fn_var = synth_var(
env.subs,
Content::Structure(FlatType::Func(
elem_decoder_var_slice,
this_decode_list_clos_var,
this_decode_list_ret_var,
)),
);
// Decoder val fmt -[uls]-> Decoder (List val) fmt | fmt has DecoderFormatting
// ~ Decoder elem fmt -a -> b
env.unify(decode_list_fn_var, this_decode_list_fn_var);
let decode_list_member = AbilityMember(Symbol::DECODE_LIST, None, this_decode_list_fn_var);
let decode_list_fn = Box::new((
decode_list_fn_var,
Loc::at_zero(decode_list_member),
this_decode_list_clos_var,
this_decode_list_ret_var,
));
let decode_list_call = Call(
decode_list_fn,
vec![(elem_decoder_var, Loc::at_zero(elem_decoder))],
CalledVia::Space,
);
(decode_list_call, this_decode_list_ret_var)
};
let bytes_sym = env.new_symbol("bytes");
let fmt_sym = env.new_symbol("fmt");
let fmt_var = env.subs.fresh_unnamed_flex_var();
let captures = vec![];
wrap_in_decode_custom_decode_with(
env,
bytes_sym,
(fmt_sym, fmt_var),
captures,
(decode_list_call, this_decode_list_ret_var),
)
}

View file

@ -0,0 +1,990 @@
use roc_can::expr::{
AnnotatedMark, ClosureData, Expr, Field, Recursive, WhenBranch, WhenBranchPattern,
};
use roc_can::pattern::Pattern;
use roc_collections::SendMap;
use roc_module::called_via::CalledVia;
use roc_module::ident::Lowercase;
use roc_module::symbol::Symbol;
use roc_region::all::{Loc, Region};
use roc_types::subs::{
Content, ExhaustiveMark, FlatType, LambdaSet, OptVariable, RecordFields, RedundantMark,
SubsSlice, TagExt, UnionLambdas, UnionTags, Variable,
};
use roc_types::types::RecordField;
use crate::synth_var;
use crate::util::{Env, ExtensionKind};
use super::wrap_in_decode_custom_decode_with;
/// Implements decoding of a record. For example, for
///
/// ```text
/// {first: a, second: b}
/// ```
///
/// we'd like to generate an impl like
///
/// ```roc
/// decoder : Decoder {first: a, second: b} fmt | a has Decoding, b has Decoding, fmt has DecoderFormatting
/// decoder =
/// initialState : {f0: Result a [NoField], f1: Result b [NoField]}
/// initialState = {f0: Err NoField, f1: Err NoField}
///
/// stepField = \state, field ->
/// when field is
/// "first" ->
/// Keep (Decode.custom \bytes, fmt ->
/// when Decode.decodeWith bytes Decode.decoder fmt is
/// {result, rest} ->
/// {result: Result.map result \val -> {state & f0: Ok val}, rest})
/// "second" ->
/// Keep (Decode.custom \bytes, fmt ->
/// when Decode.decodeWith bytes Decode.decoder fmt is
/// {result, rest} ->
/// {result: Result.map result \val -> {state & f1: Ok val}, rest})
/// _ -> Skip
///
/// finalizer = \{f0, f1} ->
/// when f0 is
/// Ok first ->
/// when f1 is
/// Ok second -> Ok {first, second}
/// Err NoField -> Err TooShort
/// Err NoField -> Err TooShort
///
/// Decode.custom \bytes, fmt -> Decode.decodeWith bytes (Decode.record initialState stepField finalizer) fmt
/// ```
pub(crate) fn decoder(
env: &mut Env,
_def_symbol: Symbol,
fields: Vec<Lowercase>,
) -> (Expr, Variable) {
// The decoded type of each field in the record, e.g. {first: a, second: b}.
let mut field_vars = Vec::with_capacity(fields.len());
// The type of each field in the decoding state, e.g. {first: Result a [NoField], second: Result b [NoField]}
let mut result_field_vars = Vec::with_capacity(fields.len());
// initialState = ...
let (initial_state_var, initial_state) =
initial_state(env, &fields, &mut field_vars, &mut result_field_vars);
// finalizer = ...
let (finalizer, finalizer_var, decode_err_var) = finalizer(
env,
initial_state_var,
&fields,
&field_vars,
&result_field_vars,
);
// stepField = ...
let (step_field, step_var) = step_field(
env,
fields,
&field_vars,
&result_field_vars,
initial_state_var,
decode_err_var,
);
// Build up the type of `Decode.record` we expect
let record_decoder_var = env.subs.fresh_unnamed_flex_var();
let decode_record_lambda_set = env.subs.fresh_unnamed_flex_var();
let decode_record_var = env.import_builtin_symbol_var(Symbol::DECODE_RECORD);
let this_decode_record_var = {
let flat_type = FlatType::Func(
SubsSlice::insert_into_subs(env.subs, [initial_state_var, step_var, finalizer_var]),
decode_record_lambda_set,
record_decoder_var,
);
synth_var(env.subs, Content::Structure(flat_type))
};
env.unify(decode_record_var, this_decode_record_var);
// Decode.record initialState stepField finalizer
let call_decode_record = Expr::Call(
Box::new((
this_decode_record_var,
Loc::at_zero(Expr::AbilityMember(
Symbol::DECODE_RECORD,
None,
this_decode_record_var,
)),
decode_record_lambda_set,
record_decoder_var,
)),
vec![
(initial_state_var, Loc::at_zero(initial_state)),
(step_var, Loc::at_zero(step_field)),
(finalizer_var, Loc::at_zero(finalizer)),
],
CalledVia::Space,
);
let (call_decode_custom, decode_custom_ret_var) = {
let bytes_sym = env.new_symbol("bytes");
let fmt_sym = env.new_symbol("fmt");
let fmt_var = env.subs.fresh_unnamed_flex_var();
let (decode_custom, decode_custom_var) = wrap_in_decode_custom_decode_with(
env,
bytes_sym,
(fmt_sym, fmt_var),
vec![],
(call_decode_record, record_decoder_var),
);
(decode_custom, decode_custom_var)
};
(call_decode_custom, decode_custom_ret_var)
}
// Example:
// stepField = \state, field ->
// when field is
// "first" ->
// Keep (Decode.custom \bytes, fmt ->
// # Uses a single-branch `when` because `let` is more expensive to monomorphize
// # due to checks for polymorphic expressions, and `rec` would be polymorphic.
// when Decode.decodeWith bytes Decode.decoder fmt is
// rec ->
// {
// rest: rec.rest,
// result: when rec.result is
// Ok val -> Ok {state & first: Ok val},
// Err err -> Err err
// })
//
// "second" ->
// Keep (Decode.custom \bytes, fmt ->
// when Decode.decodeWith bytes Decode.decoder fmt is
// rec ->
// {
// rest: rec.rest,
// result: when rec.result is
// Ok val -> Ok {state & second: Ok val},
// Err err -> Err err
// })
//
// _ -> Skip
fn step_field(
env: &mut Env,
fields: Vec<Lowercase>,
field_vars: &[Variable],
result_field_vars: &[Variable],
state_record_var: Variable,
decode_err_var: Variable,
) -> (Expr, Variable) {
let state_arg_symbol = env.new_symbol("stateRecord");
let field_arg_symbol = env.new_symbol("field");
// +1 because of the default branch.
let mut branches = Vec::with_capacity(fields.len() + 1);
let keep_payload_var = env.subs.fresh_unnamed_flex_var();
let keep_or_skip_var = {
let keep_payload_subs_slice = SubsSlice::insert_into_subs(env.subs, [keep_payload_var]);
let flat_type = FlatType::TagUnion(
UnionTags::insert_slices_into_subs(
env.subs,
[
("Keep".into(), keep_payload_subs_slice),
("Skip".into(), Default::default()),
],
),
TagExt::Any(Variable::EMPTY_TAG_UNION),
);
synth_var(env.subs, Content::Structure(flat_type))
};
for ((field_name, &field_var), &result_field_var) in fields
.into_iter()
.zip(field_vars.iter())
.zip(result_field_vars.iter())
{
// Example:
// "first" ->
// Keep (Decode.custom \bytes, fmt ->
// # Uses a single-branch `when` because `let` is more expensive to monomorphize
// # due to checks for polymorphic expressions, and `rec` would be polymorphic.
// when Decode.decodeWith bytes Decode.decoder fmt is
// rec ->
// {
// rest: rec.rest,
// result: when rec.result is
// Ok val -> Ok {state & first: Ok val},
// Err err -> Err err
// }
// )
let this_custom_callback_var;
let custom_callback_ret_var;
let custom_callback = {
// \bytes, fmt ->
// when Decode.decodeWith bytes Decode.decoder fmt is
// rec ->
// {
// rest: rec.rest,
// result: when rec.result is
// Ok val -> Ok {state & first: Ok val},
// Err err -> Err err
// }
let bytes_arg_symbol = env.new_symbol("bytes");
let fmt_arg_symbol = env.new_symbol("fmt");
let bytes_arg_var = env.subs.fresh_unnamed_flex_var();
let fmt_arg_var = env.subs.fresh_unnamed_flex_var();
// rec.result : [Ok field_var, Err DecodeError]
let rec_dot_result = {
let tag_union = FlatType::TagUnion(
UnionTags::for_result(env.subs, field_var, decode_err_var),
TagExt::Any(Variable::EMPTY_TAG_UNION),
);
synth_var(env.subs, Content::Structure(tag_union))
};
// rec : { rest: List U8, result: (typeof rec.result) }
let rec_var = {
let fields = RecordFields::insert_into_subs(
env.subs,
[
("rest".into(), RecordField::Required(Variable::LIST_U8)),
("result".into(), RecordField::Required(rec_dot_result)),
],
);
let record = FlatType::Record(fields, Variable::EMPTY_RECORD);
synth_var(env.subs, Content::Structure(record))
};
// `Decode.decoder` for the field's value
let decoder_var = env.import_builtin_symbol_var(Symbol::DECODE_DECODER);
let decode_with_var = env.import_builtin_symbol_var(Symbol::DECODE_DECODE_WITH);
let lambda_set_var = env.subs.fresh_unnamed_flex_var();
let this_decode_with_var = {
let subs_slice = SubsSlice::insert_into_subs(
env.subs,
[bytes_arg_var, decoder_var, fmt_arg_var],
);
let this_decode_with_var = synth_var(
env.subs,
Content::Structure(FlatType::Func(subs_slice, lambda_set_var, rec_var)),
);
env.unify(decode_with_var, this_decode_with_var);
this_decode_with_var
};
// The result of decoding this field's value - either the updated state, or a decoding error.
let when_expr_var = {
let flat_type = FlatType::TagUnion(
UnionTags::for_result(env.subs, state_record_var, decode_err_var),
TagExt::Any(Variable::EMPTY_TAG_UNION),
);
synth_var(env.subs, Content::Structure(flat_type))
};
// What our decoder passed to `Decode.custom` returns - the result of decoding the
// field's value, and the remaining bytes.
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 rec_symbol = env.new_symbol("rec");
// # Uses a single-branch `when` because `let` is more expensive to monomorphize
// # due to checks for polymorphic expressions, and `rec` would be polymorphic.
// when Decode.decodeWith bytes Decode.decoder fmt is
// rec ->
// {
// rest: rec.rest,
// result: when rec.result is
// Ok val -> Ok {state & first: Ok val},
// Err err -> Err err
// }
let branch_body = {
let result_val = {
// result: when rec.result is
// Ok val -> Ok {state & first: Ok val},
// Err err -> Err err
let ok_val_symbol = env.new_symbol("val");
let err_val_symbol = env.new_symbol("err");
let ok_branch_expr = {
// Ok {state & first: Ok val},
let mut updates = SendMap::default();
updates.insert(
field_name.clone(),
Field {
var: result_field_var,
region: Region::zero(),
loc_expr: Box::new(Loc::at_zero(Expr::Tag {
tag_union_var: result_field_var,
ext_var: env.new_ext_var(ExtensionKind::TagUnion),
name: "Ok".into(),
arguments: vec![(
field_var,
Loc::at_zero(Expr::Var(ok_val_symbol, field_var)),
)],
})),
},
);
let updated_record = Expr::RecordUpdate {
record_var: state_record_var,
ext_var: env.new_ext_var(ExtensionKind::Record),
symbol: state_arg_symbol,
updates,
};
Expr::Tag {
tag_union_var: when_expr_var,
ext_var: env.new_ext_var(ExtensionKind::TagUnion),
name: "Ok".into(),
arguments: vec![(state_record_var, Loc::at_zero(updated_record))],
}
};
let branches = vec![
// Ok val -> Ok {state & first: Ok val},
WhenBranch {
patterns: vec![WhenBranchPattern {
pattern: Loc::at_zero(Pattern::AppliedTag {
whole_var: rec_dot_result,
ext_var: Variable::EMPTY_TAG_UNION,
tag_name: "Ok".into(),
arguments: vec![(
field_var,
Loc::at_zero(Pattern::Identifier(ok_val_symbol)),
)],
}),
degenerate: false,
}],
value: Loc::at_zero(ok_branch_expr),
guard: None,
redundant: RedundantMark::known_non_redundant(),
},
// Err err -> Err err
WhenBranch {
patterns: vec![WhenBranchPattern {
pattern: Loc::at_zero(Pattern::AppliedTag {
whole_var: rec_dot_result,
ext_var: Variable::EMPTY_TAG_UNION,
tag_name: "Err".into(),
arguments: vec![(
decode_err_var,
Loc::at_zero(Pattern::Identifier(err_val_symbol)),
)],
}),
degenerate: false,
}],
value: Loc::at_zero(Expr::Tag {
tag_union_var: when_expr_var,
ext_var: env.new_ext_var(ExtensionKind::TagUnion),
name: "Err".into(),
arguments: vec![(
decode_err_var,
Loc::at_zero(Expr::Var(err_val_symbol, decode_err_var)),
)],
}),
guard: None,
redundant: RedundantMark::known_non_redundant(),
},
];
// when rec.result is
// Ok val -> Ok {state & first: Ok val},
// Err err -> Err err
Expr::When {
loc_cond: Box::new(Loc::at_zero(Expr::RecordAccess {
record_var: rec_var,
ext_var: env.new_ext_var(ExtensionKind::Record),
field_var: rec_dot_result,
loc_expr: Box::new(Loc::at_zero(Expr::Var(rec_symbol, rec_var))),
field: "result".into(),
})),
cond_var: rec_dot_result,
expr_var: when_expr_var,
region: Region::zero(),
branches,
branches_cond_var: rec_dot_result,
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::RecordAccess {
record_var: rec_var,
ext_var: env.new_ext_var(ExtensionKind::Record),
field_var: Variable::LIST_U8,
loc_expr: Box::new(Loc::at_zero(Expr::Var(rec_symbol, rec_var))),
field: "rest".into(),
})),
},
);
// result: when rec.result is
// Ok val -> Ok {state & first: Ok val},
// Err err -> Err err
fields_map.insert(
"result".into(),
Field {
var: when_expr_var,
region: Region::zero(),
loc_expr: Box::new(Loc::at_zero(result_val)),
},
);
Expr::Record {
record_var: custom_callback_ret_var,
fields: fields_map,
}
};
let branch = WhenBranch {
patterns: vec![WhenBranchPattern {
pattern: Loc::at_zero(Pattern::Identifier(rec_symbol)),
degenerate: false,
}],
value: Loc::at_zero(branch_body),
guard: None,
redundant: RedundantMark::known_non_redundant(),
};
let condition_expr = Expr::Call(
Box::new((
this_decode_with_var,
Loc::at_zero(Expr::Var(Symbol::DECODE_DECODE_WITH, this_decode_with_var)),
lambda_set_var,
rec_var,
)),
vec![
(
Variable::LIST_U8,
Loc::at_zero(Expr::Var(bytes_arg_symbol, Variable::LIST_U8)),
),
(
decoder_var,
Loc::at_zero(Expr::AbilityMember(
Symbol::DECODE_DECODER,
None,
decoder_var,
)),
),
(
fmt_arg_var,
Loc::at_zero(Expr::Var(fmt_arg_symbol, fmt_arg_var)),
),
],
CalledVia::Space,
);
// when Decode.decodeWith bytes Decode.decoder fmt is
Expr::When {
loc_cond: Box::new(Loc::at_zero(condition_expr)),
cond_var: rec_var,
expr_var: custom_callback_ret_var,
region: Region::zero(),
branches: vec![branch],
branches_cond_var: rec_var,
exhaustive: ExhaustiveMark::known_exhaustive(),
}
};
let custom_closure_symbol = env.new_symbol("customCallback");
this_custom_callback_var = env.subs.fresh_unnamed_flex_var();
let custom_callback_lambda_set_var = {
let content = Content::LambdaSet(LambdaSet {
solved: UnionLambdas::insert_into_subs(
env.subs,
[(custom_closure_symbol, [state_record_var])],
),
recursion_var: OptVariable::NONE,
unspecialized: Default::default(),
ambient_function: this_custom_callback_var,
});
let custom_callback_lambda_set_var = synth_var(env.subs, content);
let subs_slice =
SubsSlice::insert_into_subs(env.subs, [bytes_arg_var, fmt_arg_var]);
env.subs.set_content(
this_custom_callback_var,
Content::Structure(FlatType::Func(
subs_slice,
custom_callback_lambda_set_var,
custom_callback_ret_var,
)),
);
custom_callback_lambda_set_var
};
// \bytes, fmt -> …
Expr::Closure(ClosureData {
function_type: this_custom_callback_var,
closure_type: custom_callback_lambda_set_var,
return_type: custom_callback_ret_var,
name: custom_closure_symbol,
captured_symbols: vec![(state_arg_symbol, state_record_var)],
recursive: Recursive::NotRecursive,
arguments: vec![
(
bytes_arg_var,
AnnotatedMark::known_exhaustive(),
Loc::at_zero(Pattern::Identifier(bytes_arg_symbol)),
),
(
fmt_arg_var,
AnnotatedMark::known_exhaustive(),
Loc::at_zero(Pattern::Identifier(fmt_arg_symbol)),
),
],
loc_body: Box::new(Loc::at_zero(custom_callback_body)),
})
};
let decode_custom_ret_var = env.subs.fresh_unnamed_flex_var();
let decode_custom = {
let decode_custom_var = env.import_builtin_symbol_var(Symbol::DECODE_CUSTOM);
let decode_custom_closure_var = env.subs.fresh_unnamed_flex_var();
let this_decode_custom_var = {
let subs_slice = SubsSlice::insert_into_subs(env.subs, [this_custom_callback_var]);
let flat_type =
FlatType::Func(subs_slice, decode_custom_closure_var, decode_custom_ret_var);
synth_var(env.subs, Content::Structure(flat_type))
};
env.unify(decode_custom_var, this_decode_custom_var);
// Decode.custom \bytes, fmt -> …
Expr::Call(
Box::new((
this_decode_custom_var,
Loc::at_zero(Expr::Var(Symbol::DECODE_CUSTOM, this_decode_custom_var)),
decode_custom_closure_var,
decode_custom_ret_var,
)),
vec![(this_custom_callback_var, Loc::at_zero(custom_callback))],
CalledVia::Space,
)
};
env.unify(keep_payload_var, decode_custom_ret_var);
let keep = {
// Keep (Decode.custom \bytes, fmt ->
// when Decode.decodeWith bytes Decode.decoder fmt is
// rec ->
// {
// rest: rec.rest,
// result: when rec.result is
// Ok val -> Ok {state & first: Ok val},
// Err err -> Err err
// }
// )
Expr::Tag {
tag_union_var: keep_or_skip_var,
ext_var: env.new_ext_var(ExtensionKind::TagUnion),
name: "Keep".into(),
arguments: vec![(decode_custom_ret_var, Loc::at_zero(decode_custom))],
}
};
let branch = {
// "first" ->
// Keep (Decode.custom \bytes, fmt ->
// when Decode.decodeWith bytes Decode.decoder fmt is
// rec ->
// {
// rest: rec.rest,
// result: when rec.result is
// Ok val -> Ok {state & first: Ok val},
// Err err -> Err err
// }
// )
WhenBranch {
patterns: vec![WhenBranchPattern {
pattern: Loc::at_zero(Pattern::StrLiteral(field_name.into())),
degenerate: false,
}],
value: Loc::at_zero(keep),
guard: None,
redundant: RedundantMark::known_non_redundant(),
}
};
branches.push(branch);
}
// Example: `_ -> Skip`
let default_branch = WhenBranch {
patterns: vec![WhenBranchPattern {
pattern: Loc::at_zero(Pattern::Underscore),
degenerate: false,
}],
value: Loc::at_zero(Expr::Tag {
tag_union_var: keep_or_skip_var,
ext_var: env.new_ext_var(ExtensionKind::TagUnion),
name: "Skip".into(),
arguments: Vec::new(),
}),
guard: None,
redundant: RedundantMark::known_non_redundant(),
};
branches.push(default_branch);
// when field is
let body = Expr::When {
loc_cond: Box::new(Loc::at_zero(Expr::Var(field_arg_symbol, Variable::STR))),
cond_var: Variable::STR,
expr_var: keep_or_skip_var,
region: Region::zero(),
branches,
branches_cond_var: Variable::STR,
exhaustive: ExhaustiveMark::known_exhaustive(),
};
let step_field_closure = env.new_symbol("stepField");
let function_type = env.subs.fresh_unnamed_flex_var();
let closure_type = {
let lambda_set = LambdaSet {
solved: UnionLambdas::tag_without_arguments(env.subs, step_field_closure),
recursion_var: OptVariable::NONE,
unspecialized: Default::default(),
ambient_function: function_type,
};
synth_var(env.subs, Content::LambdaSet(lambda_set))
};
{
let args_slice = SubsSlice::insert_into_subs(env.subs, [state_record_var, Variable::STR]);
env.subs.set_content(
function_type,
Content::Structure(FlatType::Func(args_slice, closure_type, keep_or_skip_var)),
)
};
let expr = Expr::Closure(ClosureData {
function_type,
closure_type,
return_type: keep_or_skip_var,
name: step_field_closure,
captured_symbols: Vec::new(),
recursive: Recursive::NotRecursive,
arguments: vec![
(
state_record_var,
AnnotatedMark::known_exhaustive(),
Loc::at_zero(Pattern::Identifier(state_arg_symbol)),
),
(
Variable::STR,
AnnotatedMark::known_exhaustive(),
Loc::at_zero(Pattern::Identifier(field_arg_symbol)),
),
],
loc_body: Box::new(Loc::at_zero(body)),
});
(expr, function_type)
}
// Example:
// finalizer = \rec ->
// when rec.first is
// Ok first ->
// when rec.second is
// Ok second -> Ok {first, second}
// Err NoField -> Err TooShort
// Err NoField -> Err TooShort
fn finalizer(
env: &mut Env,
state_record_var: Variable,
fields: &[Lowercase],
field_vars: &[Variable],
result_field_vars: &[Variable],
) -> (Expr, Variable, Variable) {
let state_arg_symbol = env.new_symbol("stateRecord");
let mut fields_map = SendMap::default();
let mut pattern_symbols = Vec::with_capacity(fields.len());
let decode_err_var = {
let flat_type = FlatType::TagUnion(
UnionTags::tag_without_arguments(env.subs, "TooShort".into()),
TagExt::Any(Variable::EMPTY_TAG_UNION),
);
synth_var(env.subs, Content::Structure(flat_type))
};
for (field_name, &field_var) in fields.iter().zip(field_vars.iter()) {
let symbol = env.new_symbol(field_name.as_str());
pattern_symbols.push(symbol);
let field_expr = Expr::Var(symbol, field_var);
let field = Field {
var: field_var,
region: Region::zero(),
loc_expr: Box::new(Loc::at_zero(field_expr)),
};
fields_map.insert(field_name.clone(), field);
}
// The bottom of the happy path - return the decoded record {first: a, second: b} wrapped with
// "Ok".
let return_type_var;
let mut body = {
let subs = &mut env.subs;
let record_field_iter = fields
.iter()
.zip(field_vars.iter())
.map(|(field_name, &field_var)| (field_name.clone(), RecordField::Required(field_var)));
let flat_type = FlatType::Record(
RecordFields::insert_into_subs(subs, record_field_iter),
Variable::EMPTY_RECORD,
);
let done_record_var = synth_var(subs, Content::Structure(flat_type));
let done_record = Expr::Record {
record_var: done_record_var,
fields: fields_map,
};
return_type_var = {
let flat_type = FlatType::TagUnion(
UnionTags::for_result(subs, done_record_var, decode_err_var),
TagExt::Any(Variable::EMPTY_TAG_UNION),
);
synth_var(subs, Content::Structure(flat_type))
};
Expr::Tag {
tag_union_var: return_type_var,
ext_var: env.new_ext_var(ExtensionKind::TagUnion),
name: "Ok".into(),
arguments: vec![(done_record_var, Loc::at_zero(done_record))],
}
};
// Unwrap each result in the decoded state
//
// when rec.first is
// Ok first -> ...happy path...
// Err NoField -> Err TooShort
for (((symbol, field_name), &field_var), &result_field_var) in pattern_symbols
.iter()
.rev()
.zip(fields.iter().rev())
.zip(field_vars.iter().rev())
.zip(result_field_vars.iter().rev())
{
// when rec.first is
let cond_expr = Expr::RecordAccess {
record_var: state_record_var,
ext_var: env.new_ext_var(ExtensionKind::Record),
field_var: result_field_var,
loc_expr: Box::new(Loc::at_zero(Expr::Var(state_arg_symbol, state_record_var))),
field: field_name.clone(),
};
// Example: `Ok x -> expr`
let ok_branch = WhenBranch {
patterns: vec![WhenBranchPattern {
pattern: Loc::at_zero(Pattern::AppliedTag {
whole_var: result_field_var,
ext_var: Variable::EMPTY_TAG_UNION,
tag_name: "Ok".into(),
arguments: vec![(field_var, Loc::at_zero(Pattern::Identifier(*symbol)))],
}),
degenerate: false,
}],
value: Loc::at_zero(body),
guard: None,
redundant: RedundantMark::known_non_redundant(),
};
// Example: `_ -> Err TooShort`
let err_branch = WhenBranch {
patterns: vec![WhenBranchPattern {
pattern: Loc::at_zero(Pattern::Underscore),
degenerate: false,
}],
value: Loc::at_zero(Expr::Tag {
tag_union_var: return_type_var,
ext_var: env.new_ext_var(ExtensionKind::TagUnion),
name: "Err".into(),
arguments: vec![(
decode_err_var,
Loc::at_zero(Expr::Tag {
tag_union_var: decode_err_var,
ext_var: Variable::EMPTY_TAG_UNION,
name: "TooShort".into(),
arguments: Vec::new(),
}),
)],
}),
guard: None,
redundant: RedundantMark::known_non_redundant(),
};
body = Expr::When {
loc_cond: Box::new(Loc::at_zero(cond_expr)),
cond_var: result_field_var,
expr_var: return_type_var,
region: Region::zero(),
branches: vec![ok_branch, err_branch],
branches_cond_var: result_field_var,
exhaustive: ExhaustiveMark::known_exhaustive(),
};
}
let function_var = synth_var(env.subs, Content::Error); // We'll fix this up in subs later.
let function_symbol = env.new_symbol("finalizer");
let lambda_set = LambdaSet {
solved: UnionLambdas::tag_without_arguments(env.subs, function_symbol),
recursion_var: OptVariable::NONE,
unspecialized: Default::default(),
ambient_function: function_var,
};
let closure_type = synth_var(env.subs, Content::LambdaSet(lambda_set));
let flat_type = FlatType::Func(
SubsSlice::insert_into_subs(env.subs, [state_record_var]),
closure_type,
return_type_var,
);
// Fix up function_var so it's not Content::Error anymore
env.subs
.set_content(function_var, Content::Structure(flat_type));
let finalizer = Expr::Closure(ClosureData {
function_type: function_var,
closure_type,
return_type: return_type_var,
name: function_symbol,
captured_symbols: Vec::new(),
recursive: Recursive::NotRecursive,
arguments: vec![(
state_record_var,
AnnotatedMark::known_exhaustive(),
Loc::at_zero(Pattern::Identifier(state_arg_symbol)),
)],
loc_body: Box::new(Loc::at_zero(body)),
});
(finalizer, function_var, decode_err_var)
}
// Example:
// initialState : {first: Result a [NoField], second: Result b [NoField]}
// initialState = {first: Err NoField, second: Err NoField}
fn initial_state(
env: &mut Env<'_>,
field_names: &[Lowercase],
field_vars: &mut Vec<Variable>,
result_field_vars: &mut Vec<Variable>,
) -> (Variable, Expr) {
let mut initial_state_fields = SendMap::default();
for field_name in field_names {
let subs = &mut env.subs;
let field_var = subs.fresh_unnamed_flex_var();
field_vars.push(field_var);
let no_field_label = "NoField";
let union_tags = UnionTags::tag_without_arguments(subs, no_field_label.into());
let no_field_var = synth_var(
subs,
Content::Structure(FlatType::TagUnion(
union_tags,
TagExt::Any(Variable::EMPTY_TAG_UNION),
)),
);
let no_field = Expr::Tag {
tag_union_var: no_field_var,
ext_var: Variable::EMPTY_TAG_UNION,
name: no_field_label.into(),
arguments: Vec::new(),
};
let err_label = "Err";
let union_tags = UnionTags::for_result(subs, field_var, no_field_var);
let result_var = synth_var(
subs,
Content::Structure(FlatType::TagUnion(
union_tags,
TagExt::Any(Variable::EMPTY_TAG_UNION),
)),
);
let field_expr = Expr::Tag {
tag_union_var: result_var,
ext_var: env.new_ext_var(ExtensionKind::TagUnion),
name: err_label.into(),
arguments: vec![(no_field_var, Loc::at_zero(no_field))],
};
result_field_vars.push(result_var);
let field = Field {
var: result_var,
region: Region::zero(),
loc_expr: Box::new(Loc::at_zero(field_expr)),
};
initial_state_fields.insert(field_name.clone(), field);
}
let subs = &mut env.subs;
let record_field_iter = field_names
.iter()
.zip(result_field_vars.iter())
.map(|(field_name, &var)| (field_name.clone(), RecordField::Required(var)));
let flat_type = FlatType::Record(
RecordFields::insert_into_subs(subs, record_field_iter),
Variable::EMPTY_RECORD,
);
let state_record_var = synth_var(subs, Content::Structure(flat_type));
(
state_record_var,
Expr::Record {
record_var: state_record_var,
fields: initial_state_fields,
},
)
}

View file

@ -0,0 +1,994 @@
use roc_can::expr::{
AnnotatedMark, ClosureData, Expr, Field, IntValue, Recursive, WhenBranch, WhenBranchPattern,
};
use roc_can::num::{IntBound, IntLitWidth};
use roc_can::pattern::Pattern;
use roc_collections::SendMap;
use roc_module::called_via::CalledVia;
use roc_module::ident::Lowercase;
use roc_module::symbol::Symbol;
use roc_region::all::{Loc, Region};
use roc_types::subs::{
Content, ExhaustiveMark, FlatType, LambdaSet, OptVariable, RecordFields, RedundantMark,
SubsSlice, TagExt, TupleElems, UnionLambdas, UnionTags, Variable,
};
use roc_types::types::RecordField;
use crate::synth_var;
use crate::util::{Env, ExtensionKind};
use super::wrap_in_decode_custom_decode_with;
/// Implements decoding of a tuple. For example, for
///
/// ```text
/// (a, b)
/// ```
///
/// we'd like to generate an impl like
///
/// ```roc
/// decoder : Decoder (a, b) fmt | a has Decoding, b has Decoding, fmt has DecoderFormatting
/// decoder =
/// initialState : {e0: Result a [NoElem], e1: Result b [NoElem]}
/// initialState = {e0: Err NoElem, e1: Err NoElem}
///
/// stepElem = \state, index ->
/// when index is
/// 0 ->
/// Next (Decode.custom \bytes, fmt ->
/// when Decode.decodeWith bytes Decode.decoder fmt is
/// {result, rest} ->
/// {result: Result.map result \val -> {state & e0: Ok val}, rest})
/// 1 ->
/// Next (Decode.custom \bytes, fmt ->
/// when Decode.decodeWith bytes Decode.decoder fmt is
/// {result, rest} ->
/// {result: Result.map result \val -> {state & e1: Ok val}, rest})
/// _ -> TooLong
///
/// finalizer = \st ->
/// when st.e0 is
/// Ok e0 ->
/// when st.e1 is
/// Ok e1 -> Ok (e0, e1)
/// Err NoElem -> Err TooShort
/// Err NoElem -> Err TooShort
///
/// Decode.custom \bytes, fmt -> Decode.decodeWith bytes (Decode.tuple initialState stepElem finalizer) fmt
/// ```
pub(crate) fn decoder(env: &mut Env, _def_symbol: Symbol, arity: u32) -> (Expr, Variable) {
// The decoded type of each index in the tuple, e.g. (a, b).
let mut index_vars = Vec::with_capacity(arity as _);
// The type of each index in the decoding state, e.g. {e0: Result a [NoElem], e1: Result b [NoElem]}
let mut state_fields = Vec::with_capacity(arity as _);
let mut state_field_vars = Vec::with_capacity(arity as _);
// initialState = ...
let (state_var, initial_state) = initial_state(
env,
arity,
&mut index_vars,
&mut state_fields,
&mut state_field_vars,
);
// finalizer = ...
let (finalizer, finalizer_var, decode_err_var) = finalizer(
env,
&index_vars,
state_var,
&state_fields,
&state_field_vars,
);
// stepElem = ...
let (step_elem, step_var) = step_elem(
env,
&index_vars,
state_var,
&state_fields,
&state_field_vars,
decode_err_var,
);
// Build up the type of `Decode.tuple` we expect
let tuple_decoder_var = env.subs.fresh_unnamed_flex_var();
let decode_record_lambda_set = env.subs.fresh_unnamed_flex_var();
let decode_record_var = env.import_builtin_symbol_var(Symbol::DECODE_TUPLE);
let this_decode_record_var = {
let flat_type = FlatType::Func(
SubsSlice::insert_into_subs(env.subs, [state_var, step_var, finalizer_var]),
decode_record_lambda_set,
tuple_decoder_var,
);
synth_var(env.subs, Content::Structure(flat_type))
};
env.unify(decode_record_var, this_decode_record_var);
// Decode.tuple initialState stepElem finalizer
let call_decode_record = Expr::Call(
Box::new((
this_decode_record_var,
Loc::at_zero(Expr::AbilityMember(
Symbol::DECODE_TUPLE,
None,
this_decode_record_var,
)),
decode_record_lambda_set,
tuple_decoder_var,
)),
vec![
(state_var, Loc::at_zero(initial_state)),
(step_var, Loc::at_zero(step_elem)),
(finalizer_var, Loc::at_zero(finalizer)),
],
CalledVia::Space,
);
let (call_decode_custom, decode_custom_ret_var) = {
let bytes_sym = env.new_symbol("bytes");
let fmt_sym = env.new_symbol("fmt");
let fmt_var = env.subs.fresh_unnamed_flex_var();
let (decode_custom, decode_custom_var) = wrap_in_decode_custom_decode_with(
env,
bytes_sym,
(fmt_sym, fmt_var),
vec![],
(call_decode_record, tuple_decoder_var),
);
(decode_custom, decode_custom_var)
};
(call_decode_custom, decode_custom_ret_var)
}
// Example:
// stepElem = \state, index ->
// when index is
// 0 ->
// Next (Decode.custom \bytes, fmt ->
// # Uses a single-branch `when` because `let` is more expensive to monomorphize
// # due to checks for polymorphic expressions, and `rec` would be polymorphic.
// when Decode.decodeWith bytes Decode.decoder fmt is
// rec ->
// {
// rest: rec.rest,
// result: when rec.result is
// Ok val -> Ok {state & e0: Ok val},
// Err err -> Err err
// })
//
// "e1" ->
// Next (Decode.custom \bytes, fmt ->
// when Decode.decodeWith bytes Decode.decoder fmt is
// rec ->
// {
// rest: rec.rest,
// result: when rec.result is
// Ok val -> Ok {state & e1: Ok val},
// Err err -> Err err
// })
//
// _ -> TooLong
fn step_elem(
env: &mut Env,
index_vars: &[Variable],
state_record_var: Variable,
state_fields: &[Lowercase],
state_field_vars: &[Variable],
decode_err_var: Variable,
) -> (Expr, Variable) {
let state_arg_symbol = env.new_symbol("stateRecord");
let index_arg_symbol = env.new_symbol("index");
// +1 because of the default branch.
let mut branches = Vec::with_capacity(index_vars.len() + 1);
let keep_payload_var = env.subs.fresh_unnamed_flex_var();
let keep_or_skip_var = {
let keep_payload_subs_slice = SubsSlice::insert_into_subs(env.subs, [keep_payload_var]);
let flat_type = FlatType::TagUnion(
UnionTags::insert_slices_into_subs(
env.subs,
[
("Next".into(), keep_payload_subs_slice),
("TooLong".into(), Default::default()),
],
),
TagExt::Any(Variable::EMPTY_TAG_UNION),
);
synth_var(env.subs, Content::Structure(flat_type))
};
for (((index, state_field), &index_var), &result_index_var) in state_fields
.iter()
.enumerate()
.zip(index_vars)
.zip(state_field_vars)
{
// Example:
// 0 ->
// Next (Decode.custom \bytes, fmt ->
// when Decode.decodeWith bytes Decode.decoder fmt is
// rec ->
// {
// rest: rec.rest,
// result: when rec.result is
// Ok val -> Ok {state & e0: Ok val},
// Err err -> Err err
// }
// )
let this_custom_callback_var;
let custom_callback_ret_var;
let custom_callback = {
// \bytes, fmt ->
// when Decode.decodeWith bytes Decode.decoder fmt is
// rec ->
// {
// rest: rec.rest,
// result: when rec.result is
// Ok val -> Ok {state & e0: Ok val},
// Err err -> Err err
// }
let bytes_arg_symbol = env.new_symbol("bytes");
let fmt_arg_symbol = env.new_symbol("fmt");
let bytes_arg_var = env.subs.fresh_unnamed_flex_var();
let fmt_arg_var = env.subs.fresh_unnamed_flex_var();
// rec.result : [Ok index_var, Err DecodeError]
let rec_dot_result = {
let tag_union = FlatType::TagUnion(
UnionTags::for_result(env.subs, index_var, decode_err_var),
TagExt::Any(Variable::EMPTY_TAG_UNION),
);
synth_var(env.subs, Content::Structure(tag_union))
};
// rec : { rest: List U8, result: (typeof rec.result) }
let rec_var = {
let indexs = RecordFields::insert_into_subs(
env.subs,
[
("rest".into(), RecordField::Required(Variable::LIST_U8)),
("result".into(), RecordField::Required(rec_dot_result)),
],
);
let record = FlatType::Record(indexs, Variable::EMPTY_RECORD);
synth_var(env.subs, Content::Structure(record))
};
// `Decode.decoder` for the index's value
let decoder_var = env.import_builtin_symbol_var(Symbol::DECODE_DECODER);
let decode_with_var = env.import_builtin_symbol_var(Symbol::DECODE_DECODE_WITH);
let lambda_set_var = env.subs.fresh_unnamed_flex_var();
let this_decode_with_var = {
let subs_slice = SubsSlice::insert_into_subs(
env.subs,
[bytes_arg_var, decoder_var, fmt_arg_var],
);
let this_decode_with_var = synth_var(
env.subs,
Content::Structure(FlatType::Func(subs_slice, lambda_set_var, rec_var)),
);
env.unify(decode_with_var, this_decode_with_var);
this_decode_with_var
};
// The result of decoding this index's value - either the updated state, or a decoding error.
let when_expr_var = {
let flat_type = FlatType::TagUnion(
UnionTags::for_result(env.subs, state_record_var, decode_err_var),
TagExt::Any(Variable::EMPTY_TAG_UNION),
);
synth_var(env.subs, Content::Structure(flat_type))
};
// What our decoder passed to `Decode.custom` returns - the result of decoding the
// index's value, and the remaining bytes.
custom_callback_ret_var = {
let rest_index = RecordField::Required(Variable::LIST_U8);
let result_index = RecordField::Required(when_expr_var);
let flat_type = FlatType::Record(
RecordFields::insert_into_subs(
env.subs,
[("rest".into(), rest_index), ("result".into(), result_index)],
),
Variable::EMPTY_RECORD,
);
synth_var(env.subs, Content::Structure(flat_type))
};
let custom_callback_body = {
let rec_symbol = env.new_symbol("rec");
// # Uses a single-branch `when` because `let` is more expensive to monomorphize
// # due to checks for polymorphic expressions, and `rec` would be polymorphic.
// when Decode.decodeWith bytes Decode.decoder fmt is
// rec ->
// {
// rest: rec.rest,
// result: when rec.result is
// Ok val -> Ok {state & e0: Ok val},
// Err err -> Err err
// }
let branch_body = {
let result_val = {
// result: when rec.result is
// Ok val -> Ok {state & e0: Ok val},
// Err err -> Err err
let ok_val_symbol = env.new_symbol("val");
let err_val_symbol = env.new_symbol("err");
let ok_branch_expr = {
// Ok {state & e0: Ok val},
let mut updates = SendMap::default();
updates.insert(
state_field.clone(),
Field {
var: result_index_var,
region: Region::zero(),
loc_expr: Box::new(Loc::at_zero(Expr::Tag {
tag_union_var: result_index_var,
ext_var: env.new_ext_var(ExtensionKind::TagUnion),
name: "Ok".into(),
arguments: vec![(
index_var,
Loc::at_zero(Expr::Var(ok_val_symbol, index_var)),
)],
})),
},
);
let updated_record = Expr::RecordUpdate {
record_var: state_record_var,
ext_var: env.new_ext_var(ExtensionKind::Record),
symbol: state_arg_symbol,
updates,
};
Expr::Tag {
tag_union_var: when_expr_var,
ext_var: env.new_ext_var(ExtensionKind::TagUnion),
name: "Ok".into(),
arguments: vec![(state_record_var, Loc::at_zero(updated_record))],
}
};
let branches = vec![
// Ok val -> Ok {state & e0: Ok val},
WhenBranch {
patterns: vec![WhenBranchPattern {
pattern: Loc::at_zero(Pattern::AppliedTag {
whole_var: rec_dot_result,
ext_var: Variable::EMPTY_TAG_UNION,
tag_name: "Ok".into(),
arguments: vec![(
index_var,
Loc::at_zero(Pattern::Identifier(ok_val_symbol)),
)],
}),
degenerate: false,
}],
value: Loc::at_zero(ok_branch_expr),
guard: None,
redundant: RedundantMark::known_non_redundant(),
},
// Err err -> Err err
WhenBranch {
patterns: vec![WhenBranchPattern {
pattern: Loc::at_zero(Pattern::AppliedTag {
whole_var: rec_dot_result,
ext_var: Variable::EMPTY_TAG_UNION,
tag_name: "Err".into(),
arguments: vec![(
decode_err_var,
Loc::at_zero(Pattern::Identifier(err_val_symbol)),
)],
}),
degenerate: false,
}],
value: Loc::at_zero(Expr::Tag {
tag_union_var: when_expr_var,
ext_var: env.new_ext_var(ExtensionKind::TagUnion),
name: "Err".into(),
arguments: vec![(
decode_err_var,
Loc::at_zero(Expr::Var(err_val_symbol, decode_err_var)),
)],
}),
guard: None,
redundant: RedundantMark::known_non_redundant(),
},
];
// when rec.result is
// Ok val -> Ok {state & e0: Ok val},
// Err err -> Err err
Expr::When {
loc_cond: Box::new(Loc::at_zero(Expr::RecordAccess {
record_var: rec_var,
ext_var: env.new_ext_var(ExtensionKind::Record),
field_var: rec_dot_result,
loc_expr: Box::new(Loc::at_zero(Expr::Var(rec_symbol, rec_var))),
field: "result".into(),
})),
cond_var: rec_dot_result,
expr_var: when_expr_var,
region: Region::zero(),
branches,
branches_cond_var: rec_dot_result,
exhaustive: ExhaustiveMark::known_exhaustive(),
}
};
// {
// rest: rec.rest,
// result: when rec.result is
// Ok val -> Ok {state & e0: 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::RecordAccess {
record_var: rec_var,
ext_var: env.new_ext_var(ExtensionKind::Record),
field_var: Variable::LIST_U8,
loc_expr: Box::new(Loc::at_zero(Expr::Var(rec_symbol, rec_var))),
field: "rest".into(),
})),
},
);
// result: when rec.result is
// Ok val -> Ok {state & e0: Ok val},
// Err err -> Err err
fields_map.insert(
"result".into(),
Field {
var: when_expr_var,
region: Region::zero(),
loc_expr: Box::new(Loc::at_zero(result_val)),
},
);
Expr::Record {
record_var: custom_callback_ret_var,
fields: fields_map,
}
};
let branch = WhenBranch {
patterns: vec![WhenBranchPattern {
pattern: Loc::at_zero(Pattern::Identifier(rec_symbol)),
degenerate: false,
}],
value: Loc::at_zero(branch_body),
guard: None,
redundant: RedundantMark::known_non_redundant(),
};
let condition_expr = Expr::Call(
Box::new((
this_decode_with_var,
Loc::at_zero(Expr::Var(Symbol::DECODE_DECODE_WITH, this_decode_with_var)),
lambda_set_var,
rec_var,
)),
vec![
(
Variable::LIST_U8,
Loc::at_zero(Expr::Var(bytes_arg_symbol, Variable::LIST_U8)),
),
(
decoder_var,
Loc::at_zero(Expr::AbilityMember(
Symbol::DECODE_DECODER,
None,
decoder_var,
)),
),
(
fmt_arg_var,
Loc::at_zero(Expr::Var(fmt_arg_symbol, fmt_arg_var)),
),
],
CalledVia::Space,
);
// when Decode.decodeWith bytes Decode.decoder fmt is
Expr::When {
loc_cond: Box::new(Loc::at_zero(condition_expr)),
cond_var: rec_var,
expr_var: custom_callback_ret_var,
region: Region::zero(),
branches: vec![branch],
branches_cond_var: rec_var,
exhaustive: ExhaustiveMark::known_exhaustive(),
}
};
let custom_closure_symbol = env.new_symbol("customCallback");
this_custom_callback_var = env.subs.fresh_unnamed_flex_var();
let custom_callback_lambda_set_var = {
let content = Content::LambdaSet(LambdaSet {
solved: UnionLambdas::insert_into_subs(
env.subs,
[(custom_closure_symbol, [state_record_var])],
),
recursion_var: OptVariable::NONE,
unspecialized: Default::default(),
ambient_function: this_custom_callback_var,
});
let custom_callback_lambda_set_var = synth_var(env.subs, content);
let subs_slice =
SubsSlice::insert_into_subs(env.subs, [bytes_arg_var, fmt_arg_var]);
env.subs.set_content(
this_custom_callback_var,
Content::Structure(FlatType::Func(
subs_slice,
custom_callback_lambda_set_var,
custom_callback_ret_var,
)),
);
custom_callback_lambda_set_var
};
// \bytes, fmt -> …
Expr::Closure(ClosureData {
function_type: this_custom_callback_var,
closure_type: custom_callback_lambda_set_var,
return_type: custom_callback_ret_var,
name: custom_closure_symbol,
captured_symbols: vec![(state_arg_symbol, state_record_var)],
recursive: Recursive::NotRecursive,
arguments: vec![
(
bytes_arg_var,
AnnotatedMark::known_exhaustive(),
Loc::at_zero(Pattern::Identifier(bytes_arg_symbol)),
),
(
fmt_arg_var,
AnnotatedMark::known_exhaustive(),
Loc::at_zero(Pattern::Identifier(fmt_arg_symbol)),
),
],
loc_body: Box::new(Loc::at_zero(custom_callback_body)),
})
};
let decode_custom_ret_var = env.subs.fresh_unnamed_flex_var();
let decode_custom = {
let decode_custom_var = env.import_builtin_symbol_var(Symbol::DECODE_CUSTOM);
let decode_custom_closure_var = env.subs.fresh_unnamed_flex_var();
let this_decode_custom_var = {
let subs_slice = SubsSlice::insert_into_subs(env.subs, [this_custom_callback_var]);
let flat_type =
FlatType::Func(subs_slice, decode_custom_closure_var, decode_custom_ret_var);
synth_var(env.subs, Content::Structure(flat_type))
};
env.unify(decode_custom_var, this_decode_custom_var);
// Decode.custom \bytes, fmt -> …
Expr::Call(
Box::new((
this_decode_custom_var,
Loc::at_zero(Expr::Var(Symbol::DECODE_CUSTOM, this_decode_custom_var)),
decode_custom_closure_var,
decode_custom_ret_var,
)),
vec![(this_custom_callback_var, Loc::at_zero(custom_callback))],
CalledVia::Space,
)
};
env.unify(keep_payload_var, decode_custom_ret_var);
let keep = {
// Next (Decode.custom \bytes, fmt ->
// when Decode.decodeWith bytes Decode.decoder fmt is
// rec ->
// {
// rest: rec.rest,
// result: when rec.result is
// Ok val -> Ok {state & e0: Ok val},
// Err err -> Err err
// }
// )
Expr::Tag {
tag_union_var: keep_or_skip_var,
ext_var: env.new_ext_var(ExtensionKind::TagUnion),
name: "Next".into(),
arguments: vec![(decode_custom_ret_var, Loc::at_zero(decode_custom))],
}
};
let branch = {
// 0 ->
// Next (Decode.custom \bytes, fmt ->
// when Decode.decodeWith bytes Decode.decoder fmt is
// rec ->
// {
// rest: rec.rest,
// result: when rec.result is
// Ok val -> Ok {state & e0: Ok val},
// Err err -> Err err
// }
// )
WhenBranch {
patterns: vec![WhenBranchPattern {
pattern: Loc::at_zero(Pattern::IntLiteral(
Variable::NAT,
Variable::NATURAL,
index.to_string().into_boxed_str(),
IntValue::I128((index as i128).to_ne_bytes()),
IntBound::Exact(IntLitWidth::Nat),
)),
degenerate: false,
}],
value: Loc::at_zero(keep),
guard: None,
redundant: RedundantMark::known_non_redundant(),
}
};
branches.push(branch);
}
// Example: `_ -> TooLong`
let default_branch = WhenBranch {
patterns: vec![WhenBranchPattern {
pattern: Loc::at_zero(Pattern::Underscore),
degenerate: false,
}],
value: Loc::at_zero(Expr::Tag {
tag_union_var: keep_or_skip_var,
ext_var: env.new_ext_var(ExtensionKind::TagUnion),
name: "TooLong".into(),
arguments: Vec::new(),
}),
guard: None,
redundant: RedundantMark::known_non_redundant(),
};
branches.push(default_branch);
// when index is
let body = Expr::When {
loc_cond: Box::new(Loc::at_zero(Expr::Var(index_arg_symbol, Variable::NAT))),
cond_var: Variable::NAT,
expr_var: keep_or_skip_var,
region: Region::zero(),
branches,
branches_cond_var: Variable::NAT,
exhaustive: ExhaustiveMark::known_exhaustive(),
};
let step_elem_closure = env.new_symbol("stepElem");
let function_type = env.subs.fresh_unnamed_flex_var();
let closure_type = {
let lambda_set = LambdaSet {
solved: UnionLambdas::tag_without_arguments(env.subs, step_elem_closure),
recursion_var: OptVariable::NONE,
unspecialized: Default::default(),
ambient_function: function_type,
};
synth_var(env.subs, Content::LambdaSet(lambda_set))
};
{
let args_slice = SubsSlice::insert_into_subs(env.subs, [state_record_var, Variable::NAT]);
env.subs.set_content(
function_type,
Content::Structure(FlatType::Func(args_slice, closure_type, keep_or_skip_var)),
)
};
let expr = Expr::Closure(ClosureData {
function_type,
closure_type,
return_type: keep_or_skip_var,
name: step_elem_closure,
captured_symbols: Vec::new(),
recursive: Recursive::NotRecursive,
arguments: vec![
(
state_record_var,
AnnotatedMark::known_exhaustive(),
Loc::at_zero(Pattern::Identifier(state_arg_symbol)),
),
(
Variable::NAT,
AnnotatedMark::known_exhaustive(),
Loc::at_zero(Pattern::Identifier(index_arg_symbol)),
),
],
loc_body: Box::new(Loc::at_zero(body)),
});
(expr, function_type)
}
// Example:
// finalizer = \rec ->
// when rec.e0 is
// Ok e0 ->
// when rec.e1 is
// Ok e1 -> Ok (e0, e1)
// Err NoElem -> Err TooShort
// Err NoElem -> Err TooShort
fn finalizer(
env: &mut Env,
index_vars: &[Variable],
state_record_var: Variable,
state_fields: &[Lowercase],
state_field_vars: &[Variable],
) -> (Expr, Variable, Variable) {
let state_arg_symbol = env.new_symbol("stateRecord");
let mut tuple_elems = Vec::with_capacity(index_vars.len());
let mut pattern_symbols = Vec::with_capacity(index_vars.len());
let decode_err_var = {
let flat_type = FlatType::TagUnion(
UnionTags::tag_without_arguments(env.subs, "TooShort".into()),
TagExt::Any(Variable::EMPTY_TAG_UNION),
);
synth_var(env.subs, Content::Structure(flat_type))
};
for (i, &index_var) in index_vars.iter().enumerate() {
let symbol = env.new_symbol(i);
pattern_symbols.push(symbol);
let index_expr = Expr::Var(symbol, index_var);
tuple_elems.push((index_var, Box::new(Loc::at_zero(index_expr))));
}
// The bottom of the happy path - return the decoded tuple (a, b) wrapped with
// "Ok".
let return_type_var;
let mut body = {
let subs = &mut env.subs;
let tuple_indices_iter = index_vars.iter().copied().enumerate();
let flat_type = FlatType::Tuple(
TupleElems::insert_into_subs(subs, tuple_indices_iter),
Variable::EMPTY_TUPLE,
);
let done_tuple_var = synth_var(subs, Content::Structure(flat_type));
let done_record = Expr::Tuple {
tuple_var: done_tuple_var,
elems: tuple_elems,
};
return_type_var = {
let flat_type = FlatType::TagUnion(
UnionTags::for_result(subs, done_tuple_var, decode_err_var),
TagExt::Any(Variable::EMPTY_TAG_UNION),
);
synth_var(subs, Content::Structure(flat_type))
};
Expr::Tag {
tag_union_var: return_type_var,
ext_var: env.new_ext_var(ExtensionKind::TagUnion),
name: "Ok".into(),
arguments: vec![(done_tuple_var, Loc::at_zero(done_record))],
}
};
// Unwrap each result in the decoded state
//
// when rec.e0 is
// Ok e0 -> ...happy path...
// Err NoElem -> Err TooShort
for (((symbol, field), &index_var), &result_index_var) in pattern_symbols
.iter()
.zip(state_fields)
.zip(index_vars)
.zip(state_field_vars)
.rev()
{
// when rec.e0 is
let cond_expr = Expr::RecordAccess {
record_var: state_record_var,
ext_var: env.new_ext_var(ExtensionKind::Record),
field_var: result_index_var,
loc_expr: Box::new(Loc::at_zero(Expr::Var(state_arg_symbol, state_record_var))),
field: field.clone(),
};
// Example: `Ok x -> expr`
let ok_branch = WhenBranch {
patterns: vec![WhenBranchPattern {
pattern: Loc::at_zero(Pattern::AppliedTag {
whole_var: result_index_var,
ext_var: Variable::EMPTY_TAG_UNION,
tag_name: "Ok".into(),
arguments: vec![(index_var, Loc::at_zero(Pattern::Identifier(*symbol)))],
}),
degenerate: false,
}],
value: Loc::at_zero(body),
guard: None,
redundant: RedundantMark::known_non_redundant(),
};
// Example: `_ -> Err TooShort`
let err_branch = WhenBranch {
patterns: vec![WhenBranchPattern {
pattern: Loc::at_zero(Pattern::Underscore),
degenerate: false,
}],
value: Loc::at_zero(Expr::Tag {
tag_union_var: return_type_var,
ext_var: env.new_ext_var(ExtensionKind::TagUnion),
name: "Err".into(),
arguments: vec![(
decode_err_var,
Loc::at_zero(Expr::Tag {
tag_union_var: decode_err_var,
ext_var: Variable::EMPTY_TAG_UNION,
name: "TooShort".into(),
arguments: Vec::new(),
}),
)],
}),
guard: None,
redundant: RedundantMark::known_non_redundant(),
};
body = Expr::When {
loc_cond: Box::new(Loc::at_zero(cond_expr)),
cond_var: result_index_var,
expr_var: return_type_var,
region: Region::zero(),
branches: vec![ok_branch, err_branch],
branches_cond_var: result_index_var,
exhaustive: ExhaustiveMark::known_exhaustive(),
};
}
let function_var = synth_var(env.subs, Content::Error); // We'll fix this up in subs later.
let function_symbol = env.new_symbol("finalizer");
let lambda_set = LambdaSet {
solved: UnionLambdas::tag_without_arguments(env.subs, function_symbol),
recursion_var: OptVariable::NONE,
unspecialized: Default::default(),
ambient_function: function_var,
};
let closure_type = synth_var(env.subs, Content::LambdaSet(lambda_set));
let flat_type = FlatType::Func(
SubsSlice::insert_into_subs(env.subs, [state_record_var]),
closure_type,
return_type_var,
);
// Fix up function_var so it's not Content::Error anymore
env.subs
.set_content(function_var, Content::Structure(flat_type));
let finalizer = Expr::Closure(ClosureData {
function_type: function_var,
closure_type,
return_type: return_type_var,
name: function_symbol,
captured_symbols: Vec::new(),
recursive: Recursive::NotRecursive,
arguments: vec![(
state_record_var,
AnnotatedMark::known_exhaustive(),
Loc::at_zero(Pattern::Identifier(state_arg_symbol)),
)],
loc_body: Box::new(Loc::at_zero(body)),
});
(finalizer, function_var, decode_err_var)
}
// Example:
// initialState : {e0: Result a [NoElem], e1: Result b [NoElem]}
// initialState = {e0: Err NoElem, e1: Err NoElem}
fn initial_state(
env: &mut Env<'_>,
arity: u32,
index_vars: &mut Vec<Variable>,
state_fields: &mut Vec<Lowercase>,
state_field_vars: &mut Vec<Variable>,
) -> (Variable, Expr) {
let mut initial_state_fields = SendMap::default();
for i in 0..arity {
let subs = &mut env.subs;
let index_var = subs.fresh_unnamed_flex_var();
index_vars.push(index_var);
let state_field = Lowercase::from(format!("e{i}"));
state_fields.push(state_field.clone());
let no_index_label = "NoElem";
let union_tags = UnionTags::tag_without_arguments(subs, no_index_label.into());
let no_index_var = synth_var(
subs,
Content::Structure(FlatType::TagUnion(
union_tags,
TagExt::Any(Variable::EMPTY_TAG_UNION),
)),
);
let no_index = Expr::Tag {
tag_union_var: no_index_var,
ext_var: Variable::EMPTY_TAG_UNION,
name: no_index_label.into(),
arguments: Vec::new(),
};
let err_label = "Err";
let union_tags = UnionTags::for_result(subs, index_var, no_index_var);
let result_var = synth_var(
subs,
Content::Structure(FlatType::TagUnion(
union_tags,
TagExt::Any(Variable::EMPTY_TAG_UNION),
)),
);
let index_expr = Expr::Tag {
tag_union_var: result_var,
ext_var: env.new_ext_var(ExtensionKind::TagUnion),
name: err_label.into(),
arguments: vec![(no_index_var, Loc::at_zero(no_index))],
};
state_field_vars.push(result_var);
let index = Field {
var: result_var,
region: Region::zero(),
loc_expr: Box::new(Loc::at_zero(index_expr)),
};
initial_state_fields.insert(state_field, index);
}
let subs = &mut env.subs;
let record_index_iter = state_fields
.iter()
.zip(state_field_vars.iter())
.map(|(index_name, &var)| (index_name.clone(), RecordField::Required(var)));
let flat_type = FlatType::Record(
RecordFields::insert_into_subs(subs, record_index_iter),
Variable::EMPTY_RECORD,
);
let state_record_var = synth_var(subs, Content::Structure(flat_type));
(
state_record_var,
Expr::Record {
record_var: state_record_var,
fields: initial_state_fields,
},
)
}

View file

@ -14,7 +14,8 @@ use roc_module::symbol::Symbol;
use roc_region::all::{Loc, Region};
use roc_types::subs::{
Content, ExhaustiveMark, FlatType, GetSubsSlice, LambdaSet, OptVariable, RecordFields,
RedundantMark, SubsSlice, TagExt, UnionLambdas, UnionTags, Variable, VariableSubsSlice,
RedundantMark, SubsSlice, TagExt, TupleElems, UnionLambdas, UnionTags, Variable,
VariableSubsSlice,
};
use roc_types::types::RecordField;
@ -50,6 +51,21 @@ pub(crate) fn derive_to_encoder(
to_encoder_record(env, record_var, fields, def_symbol)
}
FlatEncodableKey::Tuple(arity) => {
// Generalized tuple var so we can reuse this impl between many tuples:
// if arity = n, this is (t1, ..., tn) for fresh t1, ..., tn.
let flex_elems = (0..arity)
.into_iter()
.map(|idx| (idx as usize, env.subs.fresh_unnamed_flex_var()))
.collect::<Vec<_>>();
let elems = TupleElems::insert_into_subs(env.subs, flex_elems);
let tuple_var = synth_var(
env.subs,
Content::Structure(FlatType::Tuple(elems, Variable::EMPTY_TUPLE)),
);
to_encoder_tuple(env, tuple_var, elems, def_symbol)
}
FlatEncodableKey::TagUnion(tags) => {
// Generalized tag union var so we can reuse this impl between many unions:
// if tags = [ A arity=2, B arity=1 ], this is [ A t1 t2, B t3 ] for fresh t1, t2, t3
@ -490,6 +506,189 @@ fn to_encoder_record(
(clos, fn_var)
}
fn to_encoder_tuple(
env: &mut Env<'_>,
tuple_var: Variable,
elems: TupleElems,
fn_name: Symbol,
) -> (Expr, Variable) {
// Suppose tup = (t1, t2). Build
//
// \tup -> Encode.tuple [
// Encode.toEncoder tup.0,
// Encode.toEncoder tup.1,
// ]
let tup_sym = env.new_symbol("tup");
let whole_encoder_in_list_var = env.subs.fresh_unnamed_flex_var(); // type of the encoder in the list
use Expr::*;
let elem_encoders_list = elems
.iter_all()
.map(|(elem_index, elem_var_index)| {
let index = env.subs[elem_index];
let elem_var = env.subs[elem_var_index];
let elem_var_slice = VariableSubsSlice::new(elem_var_index.index, 1);
// tup.0
let tuple_access = TupleAccess {
tuple_var,
ext_var: env.subs.fresh_unnamed_flex_var(),
elem_var,
loc_expr: Box::new(Loc::at_zero(Var(
tup_sym,
env.subs.fresh_unnamed_flex_var(),
))),
index,
};
// build `toEncoder tup.0` type
// val -[uls]-> Encoder fmt | fmt has EncoderFormatting
let to_encoder_fn_var = env.import_builtin_symbol_var(Symbol::ENCODE_TO_ENCODER);
// (typeof tup.0) -[clos]-> t1
let to_encoder_clos_var = env.subs.fresh_unnamed_flex_var(); // clos
let encoder_var = env.subs.fresh_unnamed_flex_var(); // t1
let this_to_encoder_fn_var = synth_var(
env.subs,
Content::Structure(FlatType::Func(
elem_var_slice,
to_encoder_clos_var,
encoder_var,
)),
);
// val -[uls]-> Encoder fmt | fmt has EncoderFormatting
// ~ (typeof tup.0) -[clos]-> t1
env.unify(to_encoder_fn_var, this_to_encoder_fn_var);
// toEncoder : (typeof tup.0) -[clos]-> Encoder fmt | fmt has EncoderFormatting
let to_encoder_var = AbilityMember(Symbol::ENCODE_TO_ENCODER, None, to_encoder_fn_var);
let to_encoder_fn = Box::new((
to_encoder_fn_var,
Loc::at_zero(to_encoder_var),
to_encoder_clos_var,
encoder_var,
));
// toEncoder tup.0
let to_encoder_call = Call(
to_encoder_fn,
vec![(elem_var, Loc::at_zero(tuple_access))],
CalledVia::Space,
);
// NOTE: must be done to unify the lambda sets under `encoder_var`
env.unify(encoder_var, whole_encoder_in_list_var);
Loc::at_zero(to_encoder_call)
})
.collect::<Vec<_>>();
// typeof [ toEncoder tup.0, toEncoder tup.1 ]
let whole_encoder_in_list_var_slice =
VariableSubsSlice::insert_into_subs(env.subs, once(whole_encoder_in_list_var));
let elem_encoders_list_var = synth_var(
env.subs,
Content::Structure(FlatType::Apply(
Symbol::LIST_LIST,
whole_encoder_in_list_var_slice,
)),
);
// [ toEncoder tup.0, toEncoder tup.1 ]
let elem_encoders_list = List {
elem_var: whole_encoder_in_list_var,
loc_elems: elem_encoders_list,
};
// build `Encode.tuple [ toEncoder tup.0, toEncoder tup.1 ]` type
// List (Encoder fmt) -[uls]-> Encoder fmt | fmt has EncoderFormatting
let encode_tuple_fn_var = env.import_builtin_symbol_var(Symbol::ENCODE_TUPLE);
// elem_encoders_list_var -[clos]-> t1
let elem_encoders_list_var_slice =
VariableSubsSlice::insert_into_subs(env.subs, once(elem_encoders_list_var));
let encode_tuple_clos_var = env.subs.fresh_unnamed_flex_var(); // clos
let encoder_var = env.subs.fresh_unnamed_flex_var(); // t1
let this_encode_tuple_fn_var = synth_var(
env.subs,
Content::Structure(FlatType::Func(
elem_encoders_list_var_slice,
encode_tuple_clos_var,
encoder_var,
)),
);
// List (Encoder fmt) -[uls]-> Encoder fmt | fmt has EncoderFormatting
// ~ elem_encoders_list_var -[clos]-> t1
env.unify(encode_tuple_fn_var, this_encode_tuple_fn_var);
// Encode.tuple : elem_encoders_list_var -[clos]-> Encoder fmt | fmt has EncoderFormatting
let encode_tuple_var = AbilityMember(Symbol::ENCODE_TUPLE, None, encode_tuple_fn_var);
let encode_tuple_fn = Box::new((
encode_tuple_fn_var,
Loc::at_zero(encode_tuple_var),
encode_tuple_clos_var,
encoder_var,
));
// Encode.tuple [ { key: .., value: .. }, .. ]
let encode_tuple_call = Call(
encode_tuple_fn,
vec![(elem_encoders_list_var, Loc::at_zero(elem_encoders_list))],
CalledVia::Space,
);
// Encode.custom \bytes, fmt -> Encode.appendWith bytes (Encode.tuple_var ..) fmt
let (body, this_encoder_var) =
wrap_in_encode_custom(env, encode_tuple_call, encoder_var, tup_sym, tuple_var);
// Create fn_var for ambient capture; we fix it up below.
let fn_var = synth_var(env.subs, Content::Error);
// -[fn_name]->
let fn_name_labels = UnionLambdas::insert_into_subs(env.subs, once((fn_name, vec![])));
let fn_clos_var = synth_var(
env.subs,
Content::LambdaSet(LambdaSet {
solved: fn_name_labels,
recursion_var: OptVariable::NONE,
unspecialized: SubsSlice::default(),
ambient_function: fn_var,
}),
);
// typeof tup -[fn_name]-> (typeof Encode.tuple [ .. ] = Encoder fmt)
let tuple_var_slice = SubsSlice::insert_into_subs(env.subs, once(tuple_var));
env.subs.set_content(
fn_var,
Content::Structure(FlatType::Func(
tuple_var_slice,
fn_clos_var,
this_encoder_var,
)),
);
// \tup -[fn_name]-> Encode.tuple [ { key: .., value: .. }, .. ]
let clos = Closure(ClosureData {
function_type: fn_var,
closure_type: fn_clos_var,
return_type: this_encoder_var,
name: fn_name,
captured_symbols: vec![],
recursive: Recursive::NotRecursive,
arguments: vec![(
tuple_var,
AnnotatedMark::known_exhaustive(),
Loc::at_zero(Pattern::Identifier(tup_sym)),
)],
loc_body: Box::new(Loc::at_zero(body)),
});
(clos, fn_var)
}
fn to_encoder_tag_union(
env: &mut Env<'_>,
tag_union_var: Variable,

View file

@ -19,8 +19,8 @@ use roc_types::{
num::int_lit_width_to_variable,
subs::{
Content, ExhaustiveMark, FlatType, GetSubsSlice, LambdaSet, OptVariable, RecordFields,
RedundantMark, Subs, SubsIndex, SubsSlice, TagExt, UnionLambdas, UnionTags, Variable,
VariableSubsSlice,
RedundantMark, Subs, SubsIndex, SubsSlice, TagExt, TupleElems, UnionLambdas, UnionTags,
Variable, VariableSubsSlice,
},
types::RecordField,
};
@ -30,6 +30,7 @@ use crate::{synth_var, util::Env, DerivedBody};
pub(crate) fn derive_hash(env: &mut Env<'_>, key: FlatHashKey, def_symbol: Symbol) -> DerivedBody {
let (body_type, body) = match key {
FlatHashKey::Record(fields) => hash_record(env, def_symbol, fields),
FlatHashKey::Tuple(arity) => hash_tuple(env, def_symbol, arity),
FlatHashKey::TagUnion(tags) => {
if tags.len() == 1 {
hash_newtype_tag_union(env, def_symbol, tags.into_iter().next().unwrap())
@ -122,6 +123,76 @@ fn hash_record(env: &mut Env<'_>, fn_name: Symbol, fields: Vec<Lowercase>) -> (V
)
}
fn hash_tuple(env: &mut Env<'_>, fn_name: Symbol, arity: u32) -> (Variable, Expr) {
// Suppose tup = (v1, ..., vn).
// Build a generalized type t_tup = (t1, ..., tn), with fresh t1, ..., tn,
// so that we can re-use the derived impl for many tuples of the same arity.
let (tuple_var, tuple_elems) = {
// TODO: avoid an allocation here by pre-allocating the indices and variables `TupleElems`
// will be instantiated with.
let flex_elems: Vec<_> = (0..arity)
.into_iter()
.map(|i| (i as usize, env.subs.fresh_unnamed_flex_var()))
.collect();
let elems = TupleElems::insert_into_subs(env.subs, flex_elems);
let tuple_var = synth_var(
env.subs,
Content::Structure(FlatType::Tuple(elems, Variable::EMPTY_TUPLE)),
);
(tuple_var, elems)
};
// Now, a hasher for this tuple is
//
// hash_tup : hasher, (t1, ..., tn) -> hasher | hasher has Hasher
// hash_tup = \hasher, tup ->
// Hash.hash (
// Hash.hash
// ...
// (Hash.hash hasher tup.0)
// ...
// tup.n1)
// tup.n
//
// So, just a build a fold travelling up the elements.
let tup_sym = env.new_symbol("tup");
let hasher_sym = env.new_symbol("hasher");
let hasher_var = synth_var(env.subs, Content::FlexAbleVar(None, Subs::AB_HASHER));
let (body_var, body) = tuple_elems.iter_all().fold(
(hasher_var, Expr::Var(hasher_sym, hasher_var)),
|total_hasher, (elem_idx, elem_var)| {
let index = env.subs[elem_idx];
let elem_var = env.subs[elem_var];
let elem_access = Expr::TupleAccess {
tuple_var,
elem_var,
ext_var: env.subs.fresh_unnamed_flex_var(),
loc_expr: Box::new(Loc::at_zero(Expr::Var(
tup_sym,
env.subs.fresh_unnamed_flex_var(),
))),
index,
};
call_hash_hash(env, total_hasher, (elem_var, elem_access))
},
);
// Finally, build the closure
// \hasher, rcd -> body
build_outer_derived_closure(
env,
fn_name,
(hasher_var, hasher_sym),
(tuple_var, Pattern::Identifier(tup_sym)),
(body_var, body),
)
}
/// Build a `hash` implementation for a non-singleton tag union.
fn hash_tag_union(
env: &mut Env<'_>,

View file

@ -18,19 +18,20 @@ pub(crate) struct Env<'a> {
}
impl Env<'_> {
pub fn new_symbol(&mut self, name_hint: &str) -> Symbol {
pub fn new_symbol(&mut self, name_hint: impl std::string::ToString) -> Symbol {
if cfg!(any(
debug_assertions,
test,
feature = "debug-derived-symbols"
)) {
let mut i = 0;
let hint = name_hint.to_string();
let debug_name = loop {
i += 1;
let name = if i == 1 {
name_hint.to_owned()
hint.clone()
} else {
format!("{}{}", name_hint, i)
format!("{}{}", hint, i)
};
if self.derived_ident_ids.get_id(&name).is_none() {
break name;

View file

@ -2,7 +2,7 @@ use roc_module::{ident::Lowercase, symbol::Symbol};
use roc_types::subs::{Content, FlatType, Subs, Variable};
use crate::{
util::{check_derivable_ext_var, debug_name_record},
util::{check_derivable_ext_var, debug_name_record, debug_name_tuple},
DeriveError,
};
@ -18,6 +18,7 @@ pub enum FlatDecodableKey {
// Unfortunate that we must allocate here, c'est la vie
Record(Vec<Lowercase>),
Tuple(u32),
}
impl FlatDecodableKey {
@ -25,6 +26,7 @@ impl FlatDecodableKey {
match self {
FlatDecodableKey::List() => "list".to_string(),
FlatDecodableKey::Record(fields) => debug_name_record(fields),
FlatDecodableKey::Tuple(arity) => debug_name_tuple(*arity),
}
}
}
@ -61,8 +63,14 @@ impl FlatDecodable {
Ok(Key(FlatDecodableKey::Record(field_names)))
}
FlatType::Tuple(_elems, _ext) => {
todo!()
FlatType::Tuple(elems, ext) => {
let (elems_iter, ext) = elems.sorted_iterator_and_ext(subs, ext);
check_derivable_ext_var(subs, ext, |ext| {
matches!(ext, Content::Structure(FlatType::EmptyTuple))
})?;
Ok(Key(FlatDecodableKey::Tuple(elems_iter.count() as _)))
}
FlatType::TagUnion(_tags, _ext) | FlatType::RecursiveTagUnion(_, _tags, _ext) => {
Err(Underivable) // yet

View file

@ -5,7 +5,7 @@ use roc_module::{
use roc_types::subs::{Content, FlatType, GetSubsSlice, Subs, Variable};
use crate::{
util::{check_derivable_ext_var, debug_name_record, debug_name_tag},
util::{check_derivable_ext_var, debug_name_record, debug_name_tag, debug_name_tuple},
DeriveError,
};
@ -22,6 +22,7 @@ pub enum FlatEncodableKey {
Dict(/* takes two variables */),
// Unfortunate that we must allocate here, c'est la vie
Record(Vec<Lowercase>),
Tuple(u32),
TagUnion(Vec<(TagName, u16)>),
}
@ -32,6 +33,7 @@ impl FlatEncodableKey {
FlatEncodableKey::Set() => "set".to_string(),
FlatEncodableKey::Dict() => "dict".to_string(),
FlatEncodableKey::Record(fields) => debug_name_record(fields),
FlatEncodableKey::Tuple(arity) => debug_name_tuple(*arity),
FlatEncodableKey::TagUnion(tags) => debug_name_tag(tags),
}
}
@ -66,8 +68,14 @@ impl FlatEncodable {
Ok(Key(FlatEncodableKey::Record(field_names)))
}
FlatType::Tuple(_elems, _ext) => {
todo!()
FlatType::Tuple(elems, ext) => {
let (elems_iter, ext) = elems.sorted_iterator_and_ext(subs, ext);
check_derivable_ext_var(subs, ext, |ext| {
matches!(ext, Content::Structure(FlatType::EmptyTuple))
})?;
Ok(Key(FlatEncodableKey::Tuple(elems_iter.count() as _)))
}
FlatType::TagUnion(tags, ext) | FlatType::RecursiveTagUnion(_, tags, ext) => {
// The recursion var doesn't matter, because the derived implementation will only

View file

@ -5,7 +5,7 @@ use roc_module::{
use roc_types::subs::{Content, FlatType, GetSubsSlice, Subs, Variable};
use crate::{
util::{check_derivable_ext_var, debug_name_record, debug_name_tag},
util::{check_derivable_ext_var, debug_name_record, debug_name_tag, debug_name_tuple},
DeriveError,
};
@ -21,6 +21,7 @@ pub enum FlatHash {
pub enum FlatHashKey {
// Unfortunate that we must allocate here, c'est la vie
Record(Vec<Lowercase>),
Tuple(u32),
TagUnion(Vec<(TagName, u16)>),
}
@ -28,6 +29,7 @@ impl FlatHashKey {
pub(crate) fn debug_name(&self) -> String {
match self {
FlatHashKey::Record(fields) => debug_name_record(fields),
FlatHashKey::Tuple(arity) => debug_name_tuple(*arity),
FlatHashKey::TagUnion(tags) => debug_name_tag(tags),
}
}
@ -65,8 +67,14 @@ impl FlatHash {
Ok(Key(FlatHashKey::Record(field_names)))
}
FlatType::Tuple(_elems, _ext) => {
todo!();
FlatType::Tuple(elems, ext) => {
let (elems_iter, ext) = elems.sorted_iterator_and_ext(subs, ext);
check_derivable_ext_var(subs, ext, |ext| {
matches!(ext, Content::Structure(FlatType::EmptyTuple))
})?;
Ok(Key(FlatHashKey::Tuple(elems_iter.count() as _)))
}
FlatType::TagUnion(tags, ext) | FlatType::RecursiveTagUnion(_, tags, ext) => {
// The recursion var doesn't matter, because the derived implementation will only

View file

@ -43,6 +43,10 @@ pub(crate) fn debug_name_record(fields: &[Lowercase]) -> String {
str
}
pub(crate) fn debug_name_tuple(arity: u32) -> String {
format!("(arity:{arity})")
}
pub(crate) fn debug_name_tag(tags: &[(TagName, u16)]) -> String {
let mut str = String::from('[');
tags.iter().enumerate().for_each(|(i, (tag, arity))| {

View file

@ -1500,11 +1500,12 @@ define_builtins! {
18 ENCODE_STRING: "string"
19 ENCODE_LIST: "list"
20 ENCODE_RECORD: "record"
21 ENCODE_TAG: "tag"
22 ENCODE_CUSTOM: "custom"
23 ENCODE_APPEND_WITH: "appendWith"
24 ENCODE_APPEND: "append"
25 ENCODE_TO_BYTES: "toBytes"
21 ENCODE_TUPLE: "tuple"
22 ENCODE_TAG: "tag"
23 ENCODE_CUSTOM: "custom"
24 ENCODE_APPEND_WITH: "appendWith"
25 ENCODE_APPEND: "append"
26 ENCODE_TO_BYTES: "toBytes"
}
12 DECODE: "Decode" => {
0 DECODE_DECODE_ERROR: "DecodeError" exposed_type=true
@ -1530,11 +1531,12 @@ define_builtins! {
20 DECODE_STRING: "string"
21 DECODE_LIST: "list"
22 DECODE_RECORD: "record"
23 DECODE_CUSTOM: "custom"
24 DECODE_DECODE_WITH: "decodeWith"
25 DECODE_FROM_BYTES_PARTIAL: "fromBytesPartial"
26 DECODE_FROM_BYTES: "fromBytes"
27 DECODE_MAP_RESULT: "mapResult"
23 DECODE_TUPLE: "tuple"
24 DECODE_CUSTOM: "custom"
25 DECODE_DECODE_WITH: "decodeWith"
26 DECODE_FROM_BYTES_PARTIAL: "fromBytesPartial"
27 DECODE_FROM_BYTES: "fromBytes"
28 DECODE_MAP_RESULT: "mapResult"
}
13 HASH: "Hash" => {
0 HASH_HASH_ABILITY: "Hash" exposed_type=true

View file

@ -881,6 +881,15 @@ impl DerivableVisitor for DeriveEncoding {
Ok(Descend(true))
}
#[inline(always)]
fn visit_tuple(
_subs: &Subs,
_var: Variable,
_elems: TupleElems,
) -> Result<Descend, NotDerivable> {
Ok(Descend(true))
}
#[inline(always)]
fn visit_tag_union(_var: Variable) -> Result<Descend, NotDerivable> {
Ok(Descend(true))
@ -988,6 +997,15 @@ impl DerivableVisitor for DeriveDecoding {
Ok(Descend(true))
}
#[inline(always)]
fn visit_tuple(
_subs: &Subs,
_var: Variable,
_elems: TupleElems,
) -> Result<Descend, NotDerivable> {
Ok(Descend(true))
}
#[inline(always)]
fn visit_tag_union(_var: Variable) -> Result<Descend, NotDerivable> {
Ok(Descend(true))
@ -1094,6 +1112,15 @@ impl DerivableVisitor for DeriveHash {
Ok(Descend(true))
}
#[inline(always)]
fn visit_tuple(
_subs: &Subs,
_var: Variable,
_elems: TupleElems,
) -> Result<Descend, NotDerivable> {
Ok(Descend(true))
}
#[inline(always)]
fn visit_tag_union(_var: Variable) -> Result<Descend, NotDerivable> {
Ok(Descend(true))
@ -1200,6 +1227,15 @@ impl DerivableVisitor for DeriveEq {
Ok(Descend(true))
}
#[inline(always)]
fn visit_tuple(
_subs: &Subs,
_var: Variable,
_elems: TupleElems,
) -> Result<Descend, NotDerivable> {
Ok(Descend(true))
}
#[inline(always)]
fn visit_tag_union(_var: Variable) -> Result<Descend, NotDerivable> {
Ok(Descend(true))

View file

@ -748,7 +748,7 @@ fn get_specialization_lambda_set_ambient_function<P: Phase>(
let specialized_lambda_set = *specialization
.specialization_lambda_sets
.get(&lset_region)
.expect("lambda set region not resolved");
.unwrap_or_else(|| panic!("lambda set region not resolved: {:?}", (spec_symbol, specialization)));
Ok(specialized_lambda_set)
}
MemberImpl::Error => todo_abilities!(),

View file

@ -28,6 +28,11 @@ test_key_eq! {
explicit_empty_record_and_implicit_empty_record:
v!(EMPTY_RECORD), v!({})
same_tuple:
v!((v!(U8), v!(U16),)), v!((v!(U8), v!(U16),))
same_tuple_fields_diff_types:
v!((v!(U8), v!(U16),)), v!((v!(U32), v!(U64),))
list_list_diff_types:
v!(Symbol::LIST_LIST v!(STR)), v!(Symbol::LIST_LIST v!(U8))
str_str:
@ -41,6 +46,9 @@ test_key_neq! {
v!({ a: v!(U8), }), v!({ b: v!(U8), })
record_empty_vs_nonempty:
v!(EMPTY_RECORD), v!({ a: v!(U8), })
different_tuple_arities:
v!((v!(U8), v!(U16),)), v!((v!(U8), v!(U16), v!(U32),))
}
#[test]
@ -167,3 +175,59 @@ fn record_2_fields() {
)
})
}
#[test]
fn tuple_2_fields() {
derive_test(Decoder, v!((v!(STR), v!(U8),)), |golden| {
assert_snapshot!(golden, @r###"
# derived for ( Str, U8 )*
# Decoder ( val, val1 )* fmt | fmt has DecoderFormatting, val has Decoding, val1 has Decoding
# List U8, fmt -[[custom(22)]]-> { rest : List U8, result : [Err [TooShort], Ok ( val, val1 )a] } | fmt has DecoderFormatting, val has Decoding, val1 has Decoding
# Specialization lambda sets:
# @<1>: [[custom(22)]]
#Derived.decoder_(arity:2) =
custom
\#Derived.bytes3, #Derived.fmt3 ->
decodeWith
#Derived.bytes3
(tuple
{ e1: Err NoElem, e0: Err NoElem }
\#Derived.stateRecord2, #Derived.index ->
when #Derived.index is
0 ->
Next (custom
\#Derived.bytes, #Derived.fmt ->
when decodeWith #Derived.bytes decoder #Derived.fmt is
#Derived.rec ->
{
result: when #Derived.rec.result is
Ok #Derived.val ->
Ok { stateRecord2 & e0: Ok #Derived.val }
Err #Derived.err -> Err #Derived.err,
rest: #Derived.rec.rest
})
1 ->
Next (custom
\#Derived.bytes2, #Derived.fmt2 ->
when decodeWith #Derived.bytes2 decoder #Derived.fmt2 is
#Derived.rec2 ->
{
result: when #Derived.rec2.result is
Ok #Derived.val2 ->
Ok { stateRecord2 & e1: Ok #Derived.val2 }
Err #Derived.err2 -> Err #Derived.err2,
rest: #Derived.rec2.rest
})
_ -> TooLong
\#Derived.stateRecord ->
when #Derived.stateRecord.e0 is
Ok #Derived.0 ->
when #Derived.stateRecord.e1 is
Ok #Derived.1 -> Ok ( #Derived.0, #Derived.1 )
_ -> Err TooShort
_ -> Err TooShort)
#Derived.fmt3
"###
)
})
}

View file

@ -33,6 +33,11 @@ test_key_eq! {
v!({ a: v!(U8), b: v!(U8), }),
v!({ ?a: v!(U8), ?b: v!(U8), })
same_tuple:
v!((v!(U8), v!(U16),)), v!((v!(U8), v!(U16),))
same_tuple_fields_diff_types:
v!((v!(U8), v!(U16),)), v!((v!(U32), v!(U64),))
same_tag_union:
v!([ A v!(U8) v!(STR), B v!(STR) ]), v!([ A v!(U8) v!(STR), B v!(STR) ])
same_tag_union_tags_diff_types:
@ -78,6 +83,9 @@ test_key_neq! {
record_empty_vs_nonempty:
v!(EMPTY_RECORD), v!({ a: v!(U8), })
different_tuple_arities:
v!((v!(U8), v!(U16),)), v!((v!(U8), v!(U16), v!(U32),))
different_tag_union_tags:
v!([ A v!(U8) ]), v!([ B v!(U8) ])
tag_union_empty_vs_nonempty:
@ -265,6 +273,29 @@ fn two_field_record() {
})
}
#[test]
fn two_field_tuple() {
derive_test(ToEncoder, v!((v!(U8), v!(STR),)), |golden| {
assert_snapshot!(golden, @r###"
# derived for ( U8, Str )*
# ( val, val1 )* -[[toEncoder_(arity:2)(0)]]-> Encoder fmt | fmt has EncoderFormatting, val has Encoding, val1 has Encoding
# ( val, val1 )a -[[toEncoder_(arity:2)(0)]]-> (List U8, fmt -[[custom(2) ( val, val1 )a]]-> List U8) | fmt has EncoderFormatting, val has Encoding, val1 has Encoding
# Specialization lambda sets:
# @<1>: [[toEncoder_(arity:2)(0)]]
# @<2>: [[custom(2) ( val, val1 )*]] | val has Encoding, val1 has Encoding
#Derived.toEncoder_(arity:2) =
\#Derived.tup ->
custom
\#Derived.bytes, #Derived.fmt ->
appendWith
#Derived.bytes
(tuple [toEncoder #Derived.tup.0, toEncoder #Derived.tup.1])
#Derived.fmt
"###
)
})
}
#[test]
#[ignore = "NOTE: this would never actually happen, because [] is uninhabited, and hence toEncoder can never be called with a value of []!
Rightfully it induces broken assertions in other parts of the compiler, so we ignore it."]

View file

@ -28,6 +28,11 @@ test_key_eq! {
explicit_empty_record_and_implicit_empty_record:
v!(EMPTY_RECORD), v!({})
same_tuple:
v!((v!(U8), v!(U16),)), v!((v!(U8), v!(U16),))
same_tuple_fields_diff_types:
v!((v!(U8), v!(U16),)), v!((v!(U32), v!(U64),))
same_tag_union:
v!([ A v!(U8) v!(STR), B v!(STR) ]), v!([ A v!(U8) v!(STR), B v!(STR) ])
same_tag_union_tags_diff_types:
@ -51,6 +56,9 @@ test_key_neq! {
record_empty_vs_nonempty:
v!(EMPTY_RECORD), v!({ a: v!(U8), })
different_tuple_arities:
v!((v!(U8), v!(U16),)), v!((v!(U8), v!(U16), v!(U32),))
different_tag_union_tags:
v!([ A v!(U8) ]), v!([ B v!(U8) ])
tag_union_empty_vs_nonempty:
@ -201,6 +209,23 @@ fn two_field_record() {
})
}
#[test]
fn two_element_tuple() {
derive_test(Hash, v!((v!(U8), v!(STR),)), |golden| {
assert_snapshot!(golden, @r###"
# derived for ( U8, Str )*
# hasher, ( a, a1 )* -[[hash_(arity:2)(0)]]-> hasher | a has Hash, a1 has Hash, hasher has Hasher
# hasher, ( a, a1 )* -[[hash_(arity:2)(0)]]-> hasher | a has Hash, a1 has Hash, hasher has Hasher
# Specialization lambda sets:
# @<1>: [[hash_(arity:2)(0)]]
#Derived.hash_(arity:2) =
\#Derived.hasher, #Derived.tup ->
hash (hash #Derived.hasher #Derived.tup.0) #Derived.tup.1
"###
)
})
}
#[test]
fn tag_one_label_no_payloads() {
derive_test(Hash, v!([A]), |golden| {

View file

@ -89,6 +89,22 @@ macro_rules! v {
roc_derive::synth_var(subs, Content::Structure(FlatType::Record(fields, ext)))
}
}};
(( $($make_v:expr,)* )$( $($ext:tt)+ )?) => {{
#[allow(unused)]
use roc_types::subs::{Subs, RecordFields, Content, FlatType, Variable, TupleElems};
|subs: &mut Subs| {
let elems = [
$($make_v(subs),)*
].into_iter().enumerate();
let elems = TupleElems::insert_into_subs(subs, elems);
#[allow(unused_mut, unused)]
let mut ext = Variable::EMPTY_TUPLE;
$( ext = $crate::v!($($ext)+)(subs); )?
roc_derive::synth_var(subs, Content::Structure(FlatType::Tuple(elems, ext)))
}
}};
([ $($tag:ident $($payload:expr)*),* ] as $rec_var:ident) => {{
use roc_types::subs::{Subs, SubsIndex, Variable, Content, FlatType, TagExt, UnionTags};
use roc_module::ident::TagName;

View file

@ -825,6 +825,52 @@ fn encode_derived_record_with_many_types() {
)
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn encode_derived_tuple_two_fields() {
assert_evals_to!(
indoc!(
r#"
app "test"
imports [Encode, Json]
provides [main] to "./platform"
main =
tup = ("foo", 10u8)
result = Str.fromUtf8 (Encode.toBytes tup Json.toUtf8)
when result is
Ok s -> s
_ -> "<bad>"
"#
),
RocStr::from(r#"["foo",10]"#),
RocStr
)
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn encode_derived_tuple_of_tuples() {
assert_evals_to!(
indoc!(
r#"
app "test"
imports [Encode, Json]
provides [main] to "./platform"
main =
tup = ( ("foo", 10u8), (23u8, "bar", 15u8) )
result = Str.fromUtf8 (Encode.toBytes tup Json.toUtf8)
when result is
Ok s -> s
_ -> "<bad>"
"#
),
RocStr::from(r#"[["foo",10],[23,"bar",15]]"#),
RocStr
)
}
#[test]
#[cfg(all(any(feature = "gen-llvm", feature = "gen-wasm")))]
fn encode_derived_generic_record_with_different_field_types() {
@ -1312,6 +1358,50 @@ fn decode_record_of_record() {
)
}
#[test]
#[cfg(all(
any(feature = "gen-llvm", feature = "gen-wasm"),
not(debug_assertions) // https://github.com/roc-lang/roc/issues/3898
))]
fn decode_tuple_two_elements() {
assert_evals_to!(
indoc!(
r#"
app "test" imports [Json] provides [main] to "./platform"
main =
when Str.toUtf8 "[\"ab\",10]" |> Decode.fromBytes Json.fromUtf8 is
Ok ("ab", 10u8) -> "abcd"
_ -> "something went wrong"
"#
),
RocStr::from("abcd"),
RocStr
)
}
#[test]
#[cfg(all(
any(feature = "gen-llvm", feature = "gen-wasm"),
not(debug_assertions) // https://github.com/roc-lang/roc/issues/3898
))]
fn decode_tuple_of_tuples() {
assert_evals_to!(
indoc!(
r#"
app "test" imports [Json] provides [main] to "./platform"
main =
when Str.toUtf8 "[[\"ab\",10],[\"cd\",25]]" |> Decode.fromBytes Json.fromUtf8 is
Ok ( ("ab", 10u8), ("cd", 25u8) ) -> "abcd"
_ -> "something went wrong"
"#
),
RocStr::from("abcd"),
RocStr
)
}
#[cfg(all(test, any(feature = "gen-llvm", feature = "gen-wasm")))]
mod hash {
#[cfg(feature = "gen-llvm")]
@ -1572,6 +1662,35 @@ mod hash {
)
}
#[test]
fn tuple_of_u8_and_str() {
assert_evals_to!(
&build_test(r#"(15u8, "bc")"#),
RocList::from_slice(&[15, 98, 99]),
RocList<u8>
)
}
#[test]
fn tuple_of_tuples() {
assert_evals_to!(
&build_test(r#"( (15u8, "bc"), (23u8, "ef") )"#),
RocList::from_slice(&[15, 98, 99, 23, 101, 102]),
RocList<u8>
)
}
#[test]
fn tuple_of_list_of_tuples() {
assert_evals_to!(
&build_test(
r#"( [ ( 15u8, 32u8 ), ( 23u8, 41u8 ) ], [ (45u8, 63u8), (58u8, 73u8) ] )"#
),
RocList::from_slice(&[15, 32, 23, 41, 45, 63, 58, 73]),
RocList<u8>
)
}
#[test]
fn hash_singleton_union() {
assert_evals_to!(
@ -1840,6 +1959,22 @@ mod eq {
use indoc::indoc;
use roc_std::RocStr;
#[test]
fn eq_tuple() {
assert_evals_to!(
indoc!(
r#"
app "test" provides [main] to "./platform"
main =
("a", "b") == ("a", "b")
"#
),
true,
bool
)
}
#[test]
fn custom_eq_impl() {
assert_evals_to!(

View file

@ -1,5 +1,5 @@
procedure #Derived.0 (#Derived.1):
let #Derived_gen.0 : Str = CallByName Encode.22 #Derived.1;
let #Derived_gen.0 : Str = CallByName Encode.23 #Derived.1;
ret #Derived_gen.0;
procedure #Derived.2 (#Derived.3, #Derived.4, #Derived.1):
@ -8,11 +8,11 @@ procedure #Derived.2 (#Derived.3, #Derived.4, #Derived.1):
let #Derived_gen.6 : {Str, Str} = Struct {#Derived_gen.7, #Derived_gen.8};
let #Derived_gen.5 : List {Str, Str} = Array [#Derived_gen.6];
let #Derived_gen.4 : List {Str, Str} = CallByName Json.20 #Derived_gen.5;
let #Derived_gen.3 : List U8 = CallByName Encode.23 #Derived.3 #Derived_gen.4 #Derived.4;
let #Derived_gen.3 : List U8 = CallByName Encode.24 #Derived.3 #Derived_gen.4 #Derived.4;
ret #Derived_gen.3;
procedure #Derived.5 (#Derived.6):
let #Derived_gen.14 : Str = CallByName Encode.22 #Derived.6;
let #Derived_gen.14 : Str = CallByName Encode.23 #Derived.6;
ret #Derived_gen.14;
procedure #Derived.7 (#Derived.8, #Derived.9, #Derived.6):
@ -21,195 +21,195 @@ procedure #Derived.7 (#Derived.8, #Derived.9, #Derived.6):
let #Derived_gen.20 : {Str, Str} = Struct {#Derived_gen.21, #Derived_gen.22};
let #Derived_gen.19 : List {Str, Str} = Array [#Derived_gen.20];
let #Derived_gen.18 : List {Str, Str} = CallByName Json.20 #Derived_gen.19;
let #Derived_gen.17 : List U8 = CallByName Encode.23 #Derived.8 #Derived_gen.18 #Derived.9;
let #Derived_gen.17 : List U8 = CallByName Encode.24 #Derived.8 #Derived_gen.18 #Derived.9;
ret #Derived_gen.17;
procedure Encode.22 (Encode.93):
ret Encode.93;
procedure Encode.23 (Encode.98):
ret Encode.98;
procedure Encode.22 (Encode.93):
ret Encode.93;
procedure Encode.23 (Encode.98):
ret Encode.98;
procedure Encode.22 (Encode.93):
ret Encode.93;
procedure Encode.23 (Encode.98):
ret Encode.98;
procedure Encode.22 (Encode.93):
ret Encode.93;
procedure Encode.23 (Encode.98):
ret Encode.98;
procedure Encode.22 (Encode.93):
ret Encode.93;
procedure Encode.23 (Encode.98):
ret Encode.98;
procedure Encode.23 (Encode.94, Encode.102, Encode.96):
let Encode.106 : List U8 = CallByName #Derived.2 Encode.94 Encode.96 Encode.102;
ret Encode.106;
procedure Encode.24 (Encode.99, Encode.107, Encode.101):
let Encode.111 : List U8 = CallByName #Derived.2 Encode.99 Encode.101 Encode.107;
ret Encode.111;
procedure Encode.23 (Encode.94, Encode.102, Encode.96):
let Encode.113 : List U8 = CallByName Json.114 Encode.94 Encode.96 Encode.102;
ret Encode.113;
procedure Encode.24 (Encode.99, Encode.107, Encode.101):
let Encode.118 : List U8 = CallByName Json.118 Encode.99 Encode.101 Encode.107;
ret Encode.118;
procedure Encode.23 (Encode.94, Encode.102, Encode.96):
let Encode.115 : List U8 = CallByName #Derived.7 Encode.94 Encode.96 Encode.102;
ret Encode.115;
procedure Encode.24 (Encode.99, Encode.107, Encode.101):
let Encode.120 : List U8 = CallByName #Derived.7 Encode.99 Encode.101 Encode.107;
ret Encode.120;
procedure Encode.23 (Encode.94, Encode.102, Encode.96):
let Encode.125 : List U8 = CallByName Json.114 Encode.94 Encode.96 Encode.102;
ret Encode.125;
procedure Encode.24 (Encode.99, Encode.107, Encode.101):
let Encode.130 : List U8 = CallByName Json.118 Encode.99 Encode.101 Encode.107;
ret Encode.130;
procedure Encode.23 (Encode.94, Encode.102, Encode.96):
let Encode.128 : List U8 = CallByName Json.98 Encode.94 Encode.96 Encode.102;
ret Encode.128;
procedure Encode.24 (Encode.99, Encode.107, Encode.101):
let Encode.133 : List U8 = CallByName Json.102 Encode.99 Encode.101 Encode.107;
ret Encode.133;
procedure Encode.25 (Encode.100, Encode.101):
let Encode.104 : List U8 = Array [];
let Encode.105 : Str = CallByName #Derived.0 Encode.100;
let Encode.103 : List U8 = CallByName Encode.23 Encode.104 Encode.105 Encode.101;
ret Encode.103;
procedure Encode.26 (Encode.105, Encode.106):
let Encode.109 : List U8 = Array [];
let Encode.110 : Str = CallByName #Derived.0 Encode.105;
let Encode.108 : List U8 = CallByName Encode.24 Encode.109 Encode.110 Encode.106;
ret Encode.108;
procedure Json.1 ():
let Json.425 : {} = Struct {};
ret Json.425;
let Json.483 : {} = Struct {};
ret Json.483;
procedure Json.114 (Json.115, Json.428, Json.113):
let Json.461 : I64 = 123i64;
let Json.460 : U8 = CallByName Num.127 Json.461;
let Json.117 : List U8 = CallByName List.4 Json.115 Json.460;
let Json.459 : U64 = CallByName List.6 Json.113;
let Json.436 : {List U8, U64} = Struct {Json.117, Json.459};
let Json.437 : {} = Struct {};
let Json.435 : {List U8, U64} = CallByName List.18 Json.113 Json.436 Json.437;
dec Json.113;
let Json.119 : List U8 = StructAtIndex 0 Json.435;
inc Json.119;
dec Json.435;
let Json.434 : I64 = 125i64;
let Json.433 : U8 = CallByName Num.127 Json.434;
let Json.432 : List U8 = CallByName List.4 Json.119 Json.433;
ret Json.432;
procedure Json.102 (Json.103, Json.562, Json.101):
let Json.571 : I64 = 34i64;
let Json.570 : U8 = CallByName Num.127 Json.571;
let Json.568 : List U8 = CallByName List.4 Json.103 Json.570;
let Json.569 : List U8 = CallByName Str.12 Json.101;
let Json.565 : List U8 = CallByName List.8 Json.568 Json.569;
let Json.567 : I64 = 34i64;
let Json.566 : U8 = CallByName Num.127 Json.567;
let Json.564 : List U8 = CallByName List.4 Json.565 Json.566;
ret Json.564;
procedure Json.114 (Json.115, Json.428, Json.113):
let Json.501 : I64 = 123i64;
let Json.500 : U8 = CallByName Num.127 Json.501;
let Json.117 : List U8 = CallByName List.4 Json.115 Json.500;
let Json.499 : U64 = CallByName List.6 Json.113;
let Json.476 : {List U8, U64} = Struct {Json.117, Json.499};
let Json.477 : {} = Struct {};
let Json.475 : {List U8, U64} = CallByName List.18 Json.113 Json.476 Json.477;
dec Json.113;
let Json.119 : List U8 = StructAtIndex 0 Json.475;
inc Json.119;
dec Json.475;
let Json.474 : I64 = 125i64;
let Json.473 : U8 = CallByName Num.127 Json.474;
let Json.472 : List U8 = CallByName List.4 Json.119 Json.473;
ret Json.472;
procedure Json.116 (Json.430, Json.431):
let Json.122 : Str = StructAtIndex 0 Json.431;
inc Json.122;
let Json.123 : Str = StructAtIndex 1 Json.431;
procedure Json.118 (Json.119, Json.486, Json.117):
let Json.519 : I64 = 123i64;
let Json.518 : U8 = CallByName Num.127 Json.519;
let Json.121 : List U8 = CallByName List.4 Json.119 Json.518;
let Json.517 : U64 = CallByName List.6 Json.117;
let Json.494 : {List U8, U64} = Struct {Json.121, Json.517};
let Json.495 : {} = Struct {};
let Json.493 : {List U8, U64} = CallByName List.18 Json.117 Json.494 Json.495;
dec Json.117;
let Json.123 : List U8 = StructAtIndex 0 Json.493;
inc Json.123;
dec Json.431;
let Json.120 : List U8 = StructAtIndex 0 Json.430;
inc Json.120;
let Json.121 : U64 = StructAtIndex 1 Json.430;
dec Json.430;
let Json.458 : I64 = 34i64;
let Json.457 : U8 = CallByName Num.127 Json.458;
let Json.455 : List U8 = CallByName List.4 Json.120 Json.457;
let Json.456 : List U8 = CallByName Str.12 Json.122;
let Json.452 : List U8 = CallByName List.8 Json.455 Json.456;
let Json.454 : I64 = 34i64;
let Json.453 : U8 = CallByName Num.127 Json.454;
let Json.449 : List U8 = CallByName List.4 Json.452 Json.453;
let Json.451 : I64 = 58i64;
let Json.450 : U8 = CallByName Num.127 Json.451;
let Json.447 : List U8 = CallByName List.4 Json.449 Json.450;
let Json.448 : {} = Struct {};
let Json.124 : List U8 = CallByName Encode.23 Json.447 Json.123 Json.448;
joinpoint Json.442 Json.125:
let Json.440 : U64 = 1i64;
let Json.439 : U64 = CallByName Num.20 Json.121 Json.440;
let Json.438 : {List U8, U64} = Struct {Json.125, Json.439};
ret Json.438;
in
let Json.446 : U64 = 1i64;
let Json.443 : Int1 = CallByName Num.24 Json.121 Json.446;
if Json.443 then
let Json.445 : I64 = 44i64;
let Json.444 : U8 = CallByName Num.127 Json.445;
let Json.441 : List U8 = CallByName List.4 Json.124 Json.444;
jump Json.442 Json.441;
else
jump Json.442 Json.124;
dec Json.493;
let Json.492 : I64 = 125i64;
let Json.491 : U8 = CallByName Num.127 Json.492;
let Json.490 : List U8 = CallByName List.4 Json.123 Json.491;
ret Json.490;
procedure Json.116 (Json.430, Json.431):
let Json.122 : Str = StructAtIndex 0 Json.431;
inc Json.122;
let Json.123 : Str = StructAtIndex 1 Json.431;
procedure Json.118 (Json.119, Json.486, Json.117):
let Json.559 : I64 = 123i64;
let Json.558 : U8 = CallByName Num.127 Json.559;
let Json.121 : List U8 = CallByName List.4 Json.119 Json.558;
let Json.557 : U64 = CallByName List.6 Json.117;
let Json.534 : {List U8, U64} = Struct {Json.121, Json.557};
let Json.535 : {} = Struct {};
let Json.533 : {List U8, U64} = CallByName List.18 Json.117 Json.534 Json.535;
dec Json.117;
let Json.123 : List U8 = StructAtIndex 0 Json.533;
inc Json.123;
dec Json.431;
let Json.120 : List U8 = StructAtIndex 0 Json.430;
inc Json.120;
let Json.121 : U64 = StructAtIndex 1 Json.430;
dec Json.430;
let Json.498 : I64 = 34i64;
let Json.497 : U8 = CallByName Num.127 Json.498;
let Json.495 : List U8 = CallByName List.4 Json.120 Json.497;
let Json.496 : List U8 = CallByName Str.12 Json.122;
let Json.492 : List U8 = CallByName List.8 Json.495 Json.496;
let Json.494 : I64 = 34i64;
let Json.493 : U8 = CallByName Num.127 Json.494;
let Json.489 : List U8 = CallByName List.4 Json.492 Json.493;
let Json.491 : I64 = 58i64;
let Json.490 : U8 = CallByName Num.127 Json.491;
let Json.487 : List U8 = CallByName List.4 Json.489 Json.490;
let Json.488 : {} = Struct {};
let Json.124 : List U8 = CallByName Encode.23 Json.487 Json.123 Json.488;
joinpoint Json.482 Json.125:
let Json.480 : U64 = 1i64;
let Json.479 : U64 = CallByName Num.20 Json.121 Json.480;
let Json.478 : {List U8, U64} = Struct {Json.125, Json.479};
ret Json.478;
in
let Json.486 : U64 = 1i64;
let Json.483 : Int1 = CallByName Num.24 Json.121 Json.486;
if Json.483 then
let Json.485 : I64 = 44i64;
let Json.484 : U8 = CallByName Num.127 Json.485;
let Json.481 : List U8 = CallByName List.4 Json.124 Json.484;
jump Json.482 Json.481;
else
jump Json.482 Json.124;
dec Json.533;
let Json.532 : I64 = 125i64;
let Json.531 : U8 = CallByName Num.127 Json.532;
let Json.530 : List U8 = CallByName List.4 Json.123 Json.531;
ret Json.530;
procedure Json.18 (Json.97):
let Json.502 : Str = CallByName Encode.22 Json.97;
ret Json.502;
procedure Json.20 (Json.113):
let Json.426 : List {Str, Str} = CallByName Encode.22 Json.113;
ret Json.426;
procedure Json.20 (Json.113):
let Json.468 : List {Str, Str} = CallByName Encode.22 Json.113;
ret Json.468;
procedure Json.98 (Json.99, Json.504, Json.97):
let Json.513 : I64 = 34i64;
let Json.512 : U8 = CallByName Num.127 Json.513;
let Json.510 : List U8 = CallByName List.4 Json.99 Json.512;
let Json.511 : List U8 = CallByName Str.12 Json.97;
let Json.507 : List U8 = CallByName List.8 Json.510 Json.511;
let Json.509 : I64 = 34i64;
procedure Json.120 (Json.488, Json.489):
let Json.126 : Str = StructAtIndex 0 Json.489;
inc Json.126;
let Json.127 : Str = StructAtIndex 1 Json.489;
inc Json.127;
dec Json.489;
let Json.124 : List U8 = StructAtIndex 0 Json.488;
inc Json.124;
let Json.125 : U64 = StructAtIndex 1 Json.488;
dec Json.488;
let Json.516 : I64 = 34i64;
let Json.515 : U8 = CallByName Num.127 Json.516;
let Json.513 : List U8 = CallByName List.4 Json.124 Json.515;
let Json.514 : List U8 = CallByName Str.12 Json.126;
let Json.510 : List U8 = CallByName List.8 Json.513 Json.514;
let Json.512 : I64 = 34i64;
let Json.511 : U8 = CallByName Num.127 Json.512;
let Json.507 : List U8 = CallByName List.4 Json.510 Json.511;
let Json.509 : I64 = 58i64;
let Json.508 : U8 = CallByName Num.127 Json.509;
let Json.506 : List U8 = CallByName List.4 Json.507 Json.508;
ret Json.506;
let Json.505 : List U8 = CallByName List.4 Json.507 Json.508;
let Json.506 : {} = Struct {};
let Json.128 : List U8 = CallByName Encode.24 Json.505 Json.127 Json.506;
joinpoint Json.500 Json.129:
let Json.498 : U64 = 1i64;
let Json.497 : U64 = CallByName Num.20 Json.125 Json.498;
let Json.496 : {List U8, U64} = Struct {Json.129, Json.497};
ret Json.496;
in
let Json.504 : U64 = 1i64;
let Json.501 : Int1 = CallByName Num.24 Json.125 Json.504;
if Json.501 then
let Json.503 : I64 = 44i64;
let Json.502 : U8 = CallByName Num.127 Json.503;
let Json.499 : List U8 = CallByName List.4 Json.128 Json.502;
jump Json.500 Json.499;
else
jump Json.500 Json.128;
procedure Json.120 (Json.488, Json.489):
let Json.126 : Str = StructAtIndex 0 Json.489;
inc Json.126;
let Json.127 : Str = StructAtIndex 1 Json.489;
inc Json.127;
dec Json.489;
let Json.124 : List U8 = StructAtIndex 0 Json.488;
inc Json.124;
let Json.125 : U64 = StructAtIndex 1 Json.488;
dec Json.488;
let Json.556 : I64 = 34i64;
let Json.555 : U8 = CallByName Num.127 Json.556;
let Json.553 : List U8 = CallByName List.4 Json.124 Json.555;
let Json.554 : List U8 = CallByName Str.12 Json.126;
let Json.550 : List U8 = CallByName List.8 Json.553 Json.554;
let Json.552 : I64 = 34i64;
let Json.551 : U8 = CallByName Num.127 Json.552;
let Json.547 : List U8 = CallByName List.4 Json.550 Json.551;
let Json.549 : I64 = 58i64;
let Json.548 : U8 = CallByName Num.127 Json.549;
let Json.545 : List U8 = CallByName List.4 Json.547 Json.548;
let Json.546 : {} = Struct {};
let Json.128 : List U8 = CallByName Encode.24 Json.545 Json.127 Json.546;
joinpoint Json.540 Json.129:
let Json.538 : U64 = 1i64;
let Json.537 : U64 = CallByName Num.20 Json.125 Json.538;
let Json.536 : {List U8, U64} = Struct {Json.129, Json.537};
ret Json.536;
in
let Json.544 : U64 = 1i64;
let Json.541 : Int1 = CallByName Num.24 Json.125 Json.544;
if Json.541 then
let Json.543 : I64 = 44i64;
let Json.542 : U8 = CallByName Num.127 Json.543;
let Json.539 : List U8 = CallByName List.4 Json.128 Json.542;
jump Json.540 Json.539;
else
jump Json.540 Json.128;
procedure Json.18 (Json.101):
let Json.560 : Str = CallByName Encode.23 Json.101;
ret Json.560;
procedure Json.20 (Json.117):
let Json.484 : List {Str, Str} = CallByName Encode.23 Json.117;
ret Json.484;
procedure Json.20 (Json.117):
let Json.526 : List {Str, Str} = CallByName Encode.23 Json.117;
ret Json.526;
procedure List.139 (List.140, List.141, List.138):
let List.535 : {List U8, U64} = CallByName Json.116 List.140 List.141;
let List.535 : {List U8, U64} = CallByName Json.120 List.140 List.141;
ret List.535;
procedure List.139 (List.140, List.141, List.138):
let List.608 : {List U8, U64} = CallByName Json.116 List.140 List.141;
let List.608 : {List U8, U64} = CallByName Json.120 List.140 List.141;
ret List.608;
procedure List.18 (List.136, List.137, List.138):
@ -348,7 +348,7 @@ procedure Str.9 (Str.77):
procedure Test.0 ():
let Test.12 : Str = "bar";
let Test.10 : {} = CallByName Json.1;
let Test.8 : List U8 = CallByName Encode.25 Test.12 Test.10;
let Test.8 : List U8 = CallByName Encode.26 Test.12 Test.10;
let Test.1 : [C {U64, U8}, C Str] = CallByName Str.9 Test.8;
let Test.5 : U8 = 1i64;
let Test.6 : U8 = GetTagId Test.1;

View file

@ -1,5 +1,5 @@
procedure #Derived.0 (#Derived.1):
let #Derived_gen.0 : Str = CallByName Encode.22 #Derived.1;
let #Derived_gen.0 : Str = CallByName Encode.23 #Derived.1;
ret #Derived_gen.0;
procedure #Derived.2 (#Derived.3, #Derived.4, #Derived.1):
@ -8,117 +8,117 @@ procedure #Derived.2 (#Derived.3, #Derived.4, #Derived.1):
let #Derived_gen.6 : {Str, Str} = Struct {#Derived_gen.7, #Derived_gen.8};
let #Derived_gen.5 : List {Str, Str} = Array [#Derived_gen.6];
let #Derived_gen.4 : List {Str, Str} = CallByName Json.20 #Derived_gen.5;
let #Derived_gen.3 : List U8 = CallByName Encode.23 #Derived.3 #Derived_gen.4 #Derived.4;
let #Derived_gen.3 : List U8 = CallByName Encode.24 #Derived.3 #Derived_gen.4 #Derived.4;
ret #Derived_gen.3;
procedure Encode.22 (Encode.93):
ret Encode.93;
procedure Encode.23 (Encode.98):
ret Encode.98;
procedure Encode.22 (Encode.93):
ret Encode.93;
procedure Encode.23 (Encode.98):
ret Encode.98;
procedure Encode.22 (Encode.93):
ret Encode.93;
procedure Encode.23 (Encode.98):
ret Encode.98;
procedure Encode.23 (Encode.94, Encode.102, Encode.96):
let Encode.106 : List U8 = CallByName #Derived.2 Encode.94 Encode.96 Encode.102;
ret Encode.106;
procedure Encode.24 (Encode.99, Encode.107, Encode.101):
let Encode.111 : List U8 = CallByName #Derived.2 Encode.99 Encode.101 Encode.107;
ret Encode.111;
procedure Encode.23 (Encode.94, Encode.102, Encode.96):
let Encode.113 : List U8 = CallByName Json.114 Encode.94 Encode.96 Encode.102;
ret Encode.113;
procedure Encode.24 (Encode.99, Encode.107, Encode.101):
let Encode.118 : List U8 = CallByName Json.118 Encode.99 Encode.101 Encode.107;
ret Encode.118;
procedure Encode.23 (Encode.94, Encode.102, Encode.96):
let Encode.116 : List U8 = CallByName Json.98 Encode.94 Encode.96 Encode.102;
ret Encode.116;
procedure Encode.24 (Encode.99, Encode.107, Encode.101):
let Encode.121 : List U8 = CallByName Json.102 Encode.99 Encode.101 Encode.107;
ret Encode.121;
procedure Encode.25 (Encode.100, Encode.101):
let Encode.104 : List U8 = Array [];
let Encode.105 : Str = CallByName #Derived.0 Encode.100;
let Encode.103 : List U8 = CallByName Encode.23 Encode.104 Encode.105 Encode.101;
ret Encode.103;
procedure Encode.26 (Encode.105, Encode.106):
let Encode.109 : List U8 = Array [];
let Encode.110 : Str = CallByName #Derived.0 Encode.105;
let Encode.108 : List U8 = CallByName Encode.24 Encode.109 Encode.110 Encode.106;
ret Encode.108;
procedure Json.1 ():
let Json.425 : {} = Struct {};
ret Json.425;
let Json.483 : {} = Struct {};
ret Json.483;
procedure Json.114 (Json.115, Json.428, Json.113):
let Json.461 : I64 = 123i64;
let Json.460 : U8 = CallByName Num.127 Json.461;
let Json.117 : List U8 = CallByName List.4 Json.115 Json.460;
let Json.459 : U64 = CallByName List.6 Json.113;
let Json.436 : {List U8, U64} = Struct {Json.117, Json.459};
let Json.437 : {} = Struct {};
let Json.435 : {List U8, U64} = CallByName List.18 Json.113 Json.436 Json.437;
dec Json.113;
let Json.119 : List U8 = StructAtIndex 0 Json.435;
inc Json.119;
dec Json.435;
let Json.434 : I64 = 125i64;
let Json.433 : U8 = CallByName Num.127 Json.434;
let Json.432 : List U8 = CallByName List.4 Json.119 Json.433;
ret Json.432;
procedure Json.102 (Json.103, Json.522, Json.101):
let Json.531 : I64 = 34i64;
let Json.530 : U8 = CallByName Num.127 Json.531;
let Json.528 : List U8 = CallByName List.4 Json.103 Json.530;
let Json.529 : List U8 = CallByName Str.12 Json.101;
let Json.525 : List U8 = CallByName List.8 Json.528 Json.529;
let Json.527 : I64 = 34i64;
let Json.526 : U8 = CallByName Num.127 Json.527;
let Json.524 : List U8 = CallByName List.4 Json.525 Json.526;
ret Json.524;
procedure Json.116 (Json.430, Json.431):
let Json.122 : Str = StructAtIndex 0 Json.431;
inc Json.122;
let Json.123 : Str = StructAtIndex 1 Json.431;
procedure Json.118 (Json.119, Json.486, Json.117):
let Json.519 : I64 = 123i64;
let Json.518 : U8 = CallByName Num.127 Json.519;
let Json.121 : List U8 = CallByName List.4 Json.119 Json.518;
let Json.517 : U64 = CallByName List.6 Json.117;
let Json.494 : {List U8, U64} = Struct {Json.121, Json.517};
let Json.495 : {} = Struct {};
let Json.493 : {List U8, U64} = CallByName List.18 Json.117 Json.494 Json.495;
dec Json.117;
let Json.123 : List U8 = StructAtIndex 0 Json.493;
inc Json.123;
dec Json.431;
let Json.120 : List U8 = StructAtIndex 0 Json.430;
inc Json.120;
let Json.121 : U64 = StructAtIndex 1 Json.430;
dec Json.430;
let Json.458 : I64 = 34i64;
let Json.457 : U8 = CallByName Num.127 Json.458;
let Json.455 : List U8 = CallByName List.4 Json.120 Json.457;
let Json.456 : List U8 = CallByName Str.12 Json.122;
let Json.452 : List U8 = CallByName List.8 Json.455 Json.456;
let Json.454 : I64 = 34i64;
let Json.453 : U8 = CallByName Num.127 Json.454;
let Json.449 : List U8 = CallByName List.4 Json.452 Json.453;
let Json.451 : I64 = 58i64;
let Json.450 : U8 = CallByName Num.127 Json.451;
let Json.447 : List U8 = CallByName List.4 Json.449 Json.450;
let Json.448 : {} = Struct {};
let Json.124 : List U8 = CallByName Encode.23 Json.447 Json.123 Json.448;
joinpoint Json.442 Json.125:
let Json.440 : U64 = 1i64;
let Json.439 : U64 = CallByName Num.20 Json.121 Json.440;
let Json.438 : {List U8, U64} = Struct {Json.125, Json.439};
ret Json.438;
dec Json.493;
let Json.492 : I64 = 125i64;
let Json.491 : U8 = CallByName Num.127 Json.492;
let Json.490 : List U8 = CallByName List.4 Json.123 Json.491;
ret Json.490;
procedure Json.120 (Json.488, Json.489):
let Json.126 : Str = StructAtIndex 0 Json.489;
inc Json.126;
let Json.127 : Str = StructAtIndex 1 Json.489;
inc Json.127;
dec Json.489;
let Json.124 : List U8 = StructAtIndex 0 Json.488;
inc Json.124;
let Json.125 : U64 = StructAtIndex 1 Json.488;
dec Json.488;
let Json.516 : I64 = 34i64;
let Json.515 : U8 = CallByName Num.127 Json.516;
let Json.513 : List U8 = CallByName List.4 Json.124 Json.515;
let Json.514 : List U8 = CallByName Str.12 Json.126;
let Json.510 : List U8 = CallByName List.8 Json.513 Json.514;
let Json.512 : I64 = 34i64;
let Json.511 : U8 = CallByName Num.127 Json.512;
let Json.507 : List U8 = CallByName List.4 Json.510 Json.511;
let Json.509 : I64 = 58i64;
let Json.508 : U8 = CallByName Num.127 Json.509;
let Json.505 : List U8 = CallByName List.4 Json.507 Json.508;
let Json.506 : {} = Struct {};
let Json.128 : List U8 = CallByName Encode.24 Json.505 Json.127 Json.506;
joinpoint Json.500 Json.129:
let Json.498 : U64 = 1i64;
let Json.497 : U64 = CallByName Num.20 Json.125 Json.498;
let Json.496 : {List U8, U64} = Struct {Json.129, Json.497};
ret Json.496;
in
let Json.446 : U64 = 1i64;
let Json.443 : Int1 = CallByName Num.24 Json.121 Json.446;
if Json.443 then
let Json.445 : I64 = 44i64;
let Json.444 : U8 = CallByName Num.127 Json.445;
let Json.441 : List U8 = CallByName List.4 Json.124 Json.444;
jump Json.442 Json.441;
let Json.504 : U64 = 1i64;
let Json.501 : Int1 = CallByName Num.24 Json.125 Json.504;
if Json.501 then
let Json.503 : I64 = 44i64;
let Json.502 : U8 = CallByName Num.127 Json.503;
let Json.499 : List U8 = CallByName List.4 Json.128 Json.502;
jump Json.500 Json.499;
else
jump Json.442 Json.124;
jump Json.500 Json.128;
procedure Json.18 (Json.97):
let Json.462 : Str = CallByName Encode.22 Json.97;
ret Json.462;
procedure Json.18 (Json.101):
let Json.520 : Str = CallByName Encode.23 Json.101;
ret Json.520;
procedure Json.20 (Json.113):
let Json.426 : List {Str, Str} = CallByName Encode.22 Json.113;
ret Json.426;
procedure Json.98 (Json.99, Json.464, Json.97):
let Json.473 : I64 = 34i64;
let Json.472 : U8 = CallByName Num.127 Json.473;
let Json.470 : List U8 = CallByName List.4 Json.99 Json.472;
let Json.471 : List U8 = CallByName Str.12 Json.97;
let Json.467 : List U8 = CallByName List.8 Json.470 Json.471;
let Json.469 : I64 = 34i64;
let Json.468 : U8 = CallByName Num.127 Json.469;
let Json.466 : List U8 = CallByName List.4 Json.467 Json.468;
ret Json.466;
procedure Json.20 (Json.117):
let Json.484 : List {Str, Str} = CallByName Encode.23 Json.117;
ret Json.484;
procedure List.139 (List.140, List.141, List.138):
let List.541 : {List U8, U64} = CallByName Json.116 List.140 List.141;
let List.541 : {List U8, U64} = CallByName Json.120 List.140 List.141;
ret List.541;
procedure List.18 (List.136, List.137, List.138):
@ -225,7 +225,7 @@ procedure Str.9 (Str.77):
procedure Test.0 ():
let Test.11 : Str = "foo";
let Test.10 : {} = CallByName Json.1;
let Test.8 : List U8 = CallByName Encode.25 Test.11 Test.10;
let Test.8 : List U8 = CallByName Encode.26 Test.11 Test.10;
let Test.1 : [C {U64, U8}, C Str] = CallByName Str.9 Test.8;
let Test.5 : U8 = 1i64;
let Test.6 : U8 = GetTagId Test.1;

View file

@ -1,5 +1,5 @@
procedure #Derived.0 (#Derived.1):
let #Derived_gen.0 : {Str, Str} = CallByName Encode.22 #Derived.1;
let #Derived_gen.0 : {Str, Str} = CallByName Encode.23 #Derived.1;
ret #Derived_gen.0;
procedure #Derived.2 (#Derived.3, #Derived.4, #Derived.1):
@ -16,117 +16,117 @@ procedure #Derived.2 (#Derived.3, #Derived.4, #Derived.1):
let #Derived_gen.7 : {Str, Str} = Struct {#Derived_gen.8, #Derived_gen.9};
let #Derived_gen.5 : List {Str, Str} = Array [#Derived_gen.6, #Derived_gen.7];
let #Derived_gen.4 : List {Str, Str} = CallByName Json.20 #Derived_gen.5;
let #Derived_gen.3 : List U8 = CallByName Encode.23 #Derived.3 #Derived_gen.4 #Derived.4;
let #Derived_gen.3 : List U8 = CallByName Encode.24 #Derived.3 #Derived_gen.4 #Derived.4;
ret #Derived_gen.3;
procedure Encode.22 (Encode.93):
ret Encode.93;
procedure Encode.23 (Encode.98):
ret Encode.98;
procedure Encode.22 (Encode.93):
ret Encode.93;
procedure Encode.23 (Encode.98):
ret Encode.98;
procedure Encode.22 (Encode.93):
ret Encode.93;
procedure Encode.23 (Encode.98):
ret Encode.98;
procedure Encode.23 (Encode.94, Encode.102, Encode.96):
let Encode.106 : List U8 = CallByName #Derived.2 Encode.94 Encode.96 Encode.102;
ret Encode.106;
procedure Encode.24 (Encode.99, Encode.107, Encode.101):
let Encode.111 : List U8 = CallByName #Derived.2 Encode.99 Encode.101 Encode.107;
ret Encode.111;
procedure Encode.23 (Encode.94, Encode.102, Encode.96):
let Encode.113 : List U8 = CallByName Json.114 Encode.94 Encode.96 Encode.102;
ret Encode.113;
procedure Encode.24 (Encode.99, Encode.107, Encode.101):
let Encode.118 : List U8 = CallByName Json.118 Encode.99 Encode.101 Encode.107;
ret Encode.118;
procedure Encode.23 (Encode.94, Encode.102, Encode.96):
let Encode.117 : List U8 = CallByName Json.98 Encode.94 Encode.96 Encode.102;
ret Encode.117;
procedure Encode.24 (Encode.99, Encode.107, Encode.101):
let Encode.122 : List U8 = CallByName Json.102 Encode.99 Encode.101 Encode.107;
ret Encode.122;
procedure Encode.25 (Encode.100, Encode.101):
let Encode.104 : List U8 = Array [];
let Encode.105 : {Str, Str} = CallByName #Derived.0 Encode.100;
let Encode.103 : List U8 = CallByName Encode.23 Encode.104 Encode.105 Encode.101;
ret Encode.103;
procedure Encode.26 (Encode.105, Encode.106):
let Encode.109 : List U8 = Array [];
let Encode.110 : {Str, Str} = CallByName #Derived.0 Encode.105;
let Encode.108 : List U8 = CallByName Encode.24 Encode.109 Encode.110 Encode.106;
ret Encode.108;
procedure Json.1 ():
let Json.425 : {} = Struct {};
ret Json.425;
let Json.483 : {} = Struct {};
ret Json.483;
procedure Json.114 (Json.115, Json.428, Json.113):
let Json.461 : I64 = 123i64;
let Json.460 : U8 = CallByName Num.127 Json.461;
let Json.117 : List U8 = CallByName List.4 Json.115 Json.460;
let Json.459 : U64 = CallByName List.6 Json.113;
let Json.436 : {List U8, U64} = Struct {Json.117, Json.459};
let Json.437 : {} = Struct {};
let Json.435 : {List U8, U64} = CallByName List.18 Json.113 Json.436 Json.437;
dec Json.113;
let Json.119 : List U8 = StructAtIndex 0 Json.435;
inc Json.119;
dec Json.435;
let Json.434 : I64 = 125i64;
let Json.433 : U8 = CallByName Num.127 Json.434;
let Json.432 : List U8 = CallByName List.4 Json.119 Json.433;
ret Json.432;
procedure Json.102 (Json.103, Json.522, Json.101):
let Json.531 : I64 = 34i64;
let Json.530 : U8 = CallByName Num.127 Json.531;
let Json.528 : List U8 = CallByName List.4 Json.103 Json.530;
let Json.529 : List U8 = CallByName Str.12 Json.101;
let Json.525 : List U8 = CallByName List.8 Json.528 Json.529;
let Json.527 : I64 = 34i64;
let Json.526 : U8 = CallByName Num.127 Json.527;
let Json.524 : List U8 = CallByName List.4 Json.525 Json.526;
ret Json.524;
procedure Json.116 (Json.430, Json.431):
let Json.122 : Str = StructAtIndex 0 Json.431;
inc Json.122;
let Json.123 : Str = StructAtIndex 1 Json.431;
procedure Json.118 (Json.119, Json.486, Json.117):
let Json.519 : I64 = 123i64;
let Json.518 : U8 = CallByName Num.127 Json.519;
let Json.121 : List U8 = CallByName List.4 Json.119 Json.518;
let Json.517 : U64 = CallByName List.6 Json.117;
let Json.494 : {List U8, U64} = Struct {Json.121, Json.517};
let Json.495 : {} = Struct {};
let Json.493 : {List U8, U64} = CallByName List.18 Json.117 Json.494 Json.495;
dec Json.117;
let Json.123 : List U8 = StructAtIndex 0 Json.493;
inc Json.123;
dec Json.431;
let Json.120 : List U8 = StructAtIndex 0 Json.430;
inc Json.120;
let Json.121 : U64 = StructAtIndex 1 Json.430;
dec Json.430;
let Json.458 : I64 = 34i64;
let Json.457 : U8 = CallByName Num.127 Json.458;
let Json.455 : List U8 = CallByName List.4 Json.120 Json.457;
let Json.456 : List U8 = CallByName Str.12 Json.122;
let Json.452 : List U8 = CallByName List.8 Json.455 Json.456;
let Json.454 : I64 = 34i64;
let Json.453 : U8 = CallByName Num.127 Json.454;
let Json.449 : List U8 = CallByName List.4 Json.452 Json.453;
let Json.451 : I64 = 58i64;
let Json.450 : U8 = CallByName Num.127 Json.451;
let Json.447 : List U8 = CallByName List.4 Json.449 Json.450;
let Json.448 : {} = Struct {};
let Json.124 : List U8 = CallByName Encode.23 Json.447 Json.123 Json.448;
joinpoint Json.442 Json.125:
let Json.440 : U64 = 1i64;
let Json.439 : U64 = CallByName Num.20 Json.121 Json.440;
let Json.438 : {List U8, U64} = Struct {Json.125, Json.439};
ret Json.438;
dec Json.493;
let Json.492 : I64 = 125i64;
let Json.491 : U8 = CallByName Num.127 Json.492;
let Json.490 : List U8 = CallByName List.4 Json.123 Json.491;
ret Json.490;
procedure Json.120 (Json.488, Json.489):
let Json.126 : Str = StructAtIndex 0 Json.489;
inc Json.126;
let Json.127 : Str = StructAtIndex 1 Json.489;
inc Json.127;
dec Json.489;
let Json.124 : List U8 = StructAtIndex 0 Json.488;
inc Json.124;
let Json.125 : U64 = StructAtIndex 1 Json.488;
dec Json.488;
let Json.516 : I64 = 34i64;
let Json.515 : U8 = CallByName Num.127 Json.516;
let Json.513 : List U8 = CallByName List.4 Json.124 Json.515;
let Json.514 : List U8 = CallByName Str.12 Json.126;
let Json.510 : List U8 = CallByName List.8 Json.513 Json.514;
let Json.512 : I64 = 34i64;
let Json.511 : U8 = CallByName Num.127 Json.512;
let Json.507 : List U8 = CallByName List.4 Json.510 Json.511;
let Json.509 : I64 = 58i64;
let Json.508 : U8 = CallByName Num.127 Json.509;
let Json.505 : List U8 = CallByName List.4 Json.507 Json.508;
let Json.506 : {} = Struct {};
let Json.128 : List U8 = CallByName Encode.24 Json.505 Json.127 Json.506;
joinpoint Json.500 Json.129:
let Json.498 : U64 = 1i64;
let Json.497 : U64 = CallByName Num.20 Json.125 Json.498;
let Json.496 : {List U8, U64} = Struct {Json.129, Json.497};
ret Json.496;
in
let Json.446 : U64 = 1i64;
let Json.443 : Int1 = CallByName Num.24 Json.121 Json.446;
if Json.443 then
let Json.445 : I64 = 44i64;
let Json.444 : U8 = CallByName Num.127 Json.445;
let Json.441 : List U8 = CallByName List.4 Json.124 Json.444;
jump Json.442 Json.441;
let Json.504 : U64 = 1i64;
let Json.501 : Int1 = CallByName Num.24 Json.125 Json.504;
if Json.501 then
let Json.503 : I64 = 44i64;
let Json.502 : U8 = CallByName Num.127 Json.503;
let Json.499 : List U8 = CallByName List.4 Json.128 Json.502;
jump Json.500 Json.499;
else
jump Json.442 Json.124;
jump Json.500 Json.128;
procedure Json.18 (Json.97):
let Json.474 : Str = CallByName Encode.22 Json.97;
ret Json.474;
procedure Json.18 (Json.101):
let Json.532 : Str = CallByName Encode.23 Json.101;
ret Json.532;
procedure Json.20 (Json.113):
let Json.426 : List {Str, Str} = CallByName Encode.22 Json.113;
ret Json.426;
procedure Json.98 (Json.99, Json.464, Json.97):
let Json.473 : I64 = 34i64;
let Json.472 : U8 = CallByName Num.127 Json.473;
let Json.470 : List U8 = CallByName List.4 Json.99 Json.472;
let Json.471 : List U8 = CallByName Str.12 Json.97;
let Json.467 : List U8 = CallByName List.8 Json.470 Json.471;
let Json.469 : I64 = 34i64;
let Json.468 : U8 = CallByName Num.127 Json.469;
let Json.466 : List U8 = CallByName List.4 Json.467 Json.468;
ret Json.466;
procedure Json.20 (Json.117):
let Json.484 : List {Str, Str} = CallByName Encode.23 Json.117;
ret Json.484;
procedure List.139 (List.140, List.141, List.138):
let List.541 : {List U8, U64} = CallByName Json.116 List.140 List.141;
let List.541 : {List U8, U64} = CallByName Json.120 List.140 List.141;
ret List.541;
procedure List.18 (List.136, List.137, List.138):
@ -235,7 +235,7 @@ procedure Test.0 ():
let Test.12 : Str = "bar";
let Test.9 : {Str, Str} = Struct {Test.11, Test.12};
let Test.10 : {} = CallByName Json.1;
let Test.8 : List U8 = CallByName Encode.25 Test.9 Test.10;
let Test.8 : List U8 = CallByName Encode.26 Test.9 Test.10;
let Test.1 : [C {U64, U8}, C Str] = CallByName Str.9 Test.8;
let Test.5 : U8 = 1i64;
let Test.6 : U8 = GetTagId Test.1;

View file

@ -1,34 +1,34 @@
procedure Encode.22 (Encode.93):
ret Encode.93;
procedure Encode.23 (Encode.98):
ret Encode.98;
procedure Encode.23 (Encode.94, Encode.102, Encode.96):
let Encode.106 : List U8 = CallByName Json.98 Encode.94 Encode.96 Encode.102;
ret Encode.106;
procedure Encode.24 (Encode.99, Encode.107, Encode.101):
let Encode.111 : List U8 = CallByName Json.102 Encode.99 Encode.101 Encode.107;
ret Encode.111;
procedure Encode.25 (Encode.100, Encode.101):
let Encode.104 : List U8 = Array [];
let Encode.105 : Str = CallByName Json.18 Encode.100;
let Encode.103 : List U8 = CallByName Encode.23 Encode.104 Encode.105 Encode.101;
ret Encode.103;
procedure Encode.26 (Encode.105, Encode.106):
let Encode.109 : List U8 = Array [];
let Encode.110 : Str = CallByName Json.18 Encode.105;
let Encode.108 : List U8 = CallByName Encode.24 Encode.109 Encode.110 Encode.106;
ret Encode.108;
procedure Json.1 ():
let Json.425 : {} = Struct {};
ret Json.425;
let Json.483 : {} = Struct {};
ret Json.483;
procedure Json.18 (Json.97):
let Json.426 : Str = CallByName Encode.22 Json.97;
ret Json.426;
procedure Json.102 (Json.103, Json.486, Json.101):
let Json.495 : I64 = 34i64;
let Json.494 : U8 = CallByName Num.127 Json.495;
let Json.492 : List U8 = CallByName List.4 Json.103 Json.494;
let Json.493 : List U8 = CallByName Str.12 Json.101;
let Json.489 : List U8 = CallByName List.8 Json.492 Json.493;
let Json.491 : I64 = 34i64;
let Json.490 : U8 = CallByName Num.127 Json.491;
let Json.488 : List U8 = CallByName List.4 Json.489 Json.490;
ret Json.488;
procedure Json.98 (Json.99, Json.428, Json.97):
let Json.437 : I64 = 34i64;
let Json.436 : U8 = CallByName Num.127 Json.437;
let Json.434 : List U8 = CallByName List.4 Json.99 Json.436;
let Json.435 : List U8 = CallByName Str.12 Json.97;
let Json.431 : List U8 = CallByName List.8 Json.434 Json.435;
let Json.433 : I64 = 34i64;
let Json.432 : U8 = CallByName Num.127 Json.433;
let Json.430 : List U8 = CallByName List.4 Json.431 Json.432;
ret Json.430;
procedure Json.18 (Json.101):
let Json.484 : Str = CallByName Encode.23 Json.101;
ret Json.484;
procedure List.4 (List.107, List.108):
let List.503 : U64 = 1i64;
@ -86,7 +86,7 @@ procedure Str.9 (Str.77):
procedure Test.0 ():
let Test.9 : Str = "abc";
let Test.10 : {} = CallByName Json.1;
let Test.8 : List U8 = CallByName Encode.25 Test.9 Test.10;
let Test.8 : List U8 = CallByName Encode.26 Test.9 Test.10;
let Test.1 : [C {U64, U8}, C Str] = CallByName Str.9 Test.8;
let Test.5 : U8 = 1i64;
let Test.6 : U8 = GetTagId Test.1;

View file

@ -1,133 +1,133 @@
procedure #Derived.0 (#Derived.1):
let #Derived_gen.0 : Str = CallByName Encode.22 #Derived.1;
let #Derived_gen.0 : Str = CallByName Encode.23 #Derived.1;
ret #Derived_gen.0;
procedure #Derived.3 (#Derived.4, #Derived.5, #Derived.1):
joinpoint #Derived_gen.5 #Derived_gen.4:
let #Derived_gen.3 : List U8 = CallByName Encode.23 #Derived.4 #Derived_gen.4 #Derived.5;
let #Derived_gen.3 : List U8 = CallByName Encode.24 #Derived.4 #Derived_gen.4 #Derived.5;
ret #Derived_gen.3;
in
let #Derived_gen.7 : Str = "A";
let #Derived_gen.9 : Str = CallByName Json.18 #Derived.1;
let #Derived_gen.8 : List Str = Array [#Derived_gen.9];
let #Derived_gen.6 : {Str, List Str} = CallByName Json.21 #Derived_gen.7 #Derived_gen.8;
let #Derived_gen.6 : {Str, List Str} = CallByName Json.22 #Derived_gen.7 #Derived_gen.8;
jump #Derived_gen.5 #Derived_gen.6;
procedure Encode.22 (Encode.93):
ret Encode.93;
procedure Encode.23 (Encode.98):
ret Encode.98;
procedure Encode.22 (Encode.93):
ret Encode.93;
procedure Encode.23 (Encode.98):
ret Encode.98;
procedure Encode.22 (Encode.93):
ret Encode.93;
procedure Encode.23 (Encode.98):
ret Encode.98;
procedure Encode.23 (Encode.94, Encode.102, Encode.96):
let Encode.106 : List U8 = CallByName #Derived.3 Encode.94 Encode.96 Encode.102;
ret Encode.106;
procedure Encode.24 (Encode.99, Encode.107, Encode.101):
let Encode.111 : List U8 = CallByName #Derived.3 Encode.99 Encode.101 Encode.107;
ret Encode.111;
procedure Encode.23 (Encode.94, Encode.102, Encode.96):
let Encode.113 : List U8 = CallByName Json.128 Encode.94 Encode.96 Encode.102;
ret Encode.113;
procedure Encode.24 (Encode.99, Encode.107, Encode.101):
let Encode.118 : List U8 = CallByName Json.144 Encode.99 Encode.101 Encode.107;
ret Encode.118;
procedure Encode.23 (Encode.94, Encode.102, Encode.96):
let Encode.116 : List U8 = CallByName Json.98 Encode.94 Encode.96 Encode.102;
ret Encode.116;
procedure Encode.24 (Encode.99, Encode.107, Encode.101):
let Encode.121 : List U8 = CallByName Json.102 Encode.99 Encode.101 Encode.107;
ret Encode.121;
procedure Encode.25 (Encode.100, Encode.101):
let Encode.104 : List U8 = Array [];
let Encode.105 : Str = CallByName #Derived.0 Encode.100;
let Encode.103 : List U8 = CallByName Encode.23 Encode.104 Encode.105 Encode.101;
ret Encode.103;
procedure Encode.26 (Encode.105, Encode.106):
let Encode.109 : List U8 = Array [];
let Encode.110 : Str = CallByName #Derived.0 Encode.105;
let Encode.108 : List U8 = CallByName Encode.24 Encode.109 Encode.110 Encode.106;
ret Encode.108;
procedure Json.1 ():
let Json.425 : {} = Struct {};
ret Json.425;
let Json.483 : {} = Struct {};
ret Json.483;
procedure Json.128 (Json.129, Json.428, #Attr.12):
let Json.127 : List Str = StructAtIndex 1 #Attr.12;
inc Json.127;
let Json.126 : Str = StructAtIndex 0 #Attr.12;
inc Json.126;
procedure Json.102 (Json.103, Json.527, Json.101):
let Json.536 : I64 = 34i64;
let Json.535 : U8 = CallByName Num.127 Json.536;
let Json.533 : List U8 = CallByName List.4 Json.103 Json.535;
let Json.534 : List U8 = CallByName Str.12 Json.101;
let Json.530 : List U8 = CallByName List.8 Json.533 Json.534;
let Json.532 : I64 = 34i64;
let Json.531 : U8 = CallByName Num.127 Json.532;
let Json.529 : List U8 = CallByName List.4 Json.530 Json.531;
ret Json.529;
procedure Json.144 (Json.145, Json.486, #Attr.12):
let Json.143 : List Str = StructAtIndex 1 #Attr.12;
inc Json.143;
let Json.142 : Str = StructAtIndex 0 #Attr.12;
inc Json.142;
dec #Attr.12;
let Json.466 : I64 = 123i64;
let Json.465 : U8 = CallByName Num.127 Json.466;
let Json.462 : List U8 = CallByName List.4 Json.129 Json.465;
let Json.464 : I64 = 34i64;
let Json.463 : U8 = CallByName Num.127 Json.464;
let Json.460 : List U8 = CallByName List.4 Json.462 Json.463;
let Json.461 : List U8 = CallByName Str.12 Json.126;
let Json.457 : List U8 = CallByName List.8 Json.460 Json.461;
let Json.459 : I64 = 34i64;
let Json.458 : U8 = CallByName Num.127 Json.459;
let Json.454 : List U8 = CallByName List.4 Json.457 Json.458;
let Json.456 : I64 = 58i64;
let Json.455 : U8 = CallByName Num.127 Json.456;
let Json.451 : List U8 = CallByName List.4 Json.454 Json.455;
let Json.453 : I64 = 91i64;
let Json.452 : U8 = CallByName Num.127 Json.453;
let Json.131 : List U8 = CallByName List.4 Json.451 Json.452;
let Json.450 : U64 = CallByName List.6 Json.127;
let Json.438 : {List U8, U64} = Struct {Json.131, Json.450};
let Json.439 : {} = Struct {};
let Json.437 : {List U8, U64} = CallByName List.18 Json.127 Json.438 Json.439;
dec Json.127;
let Json.133 : List U8 = StructAtIndex 0 Json.437;
inc Json.133;
dec Json.437;
let Json.436 : I64 = 93i64;
let Json.435 : U8 = CallByName Num.127 Json.436;
let Json.432 : List U8 = CallByName List.4 Json.133 Json.435;
let Json.434 : I64 = 125i64;
let Json.433 : U8 = CallByName Num.127 Json.434;
let Json.431 : List U8 = CallByName List.4 Json.432 Json.433;
ret Json.431;
let Json.524 : I64 = 123i64;
let Json.523 : U8 = CallByName Num.127 Json.524;
let Json.520 : List U8 = CallByName List.4 Json.145 Json.523;
let Json.522 : I64 = 34i64;
let Json.521 : U8 = CallByName Num.127 Json.522;
let Json.518 : List U8 = CallByName List.4 Json.520 Json.521;
let Json.519 : List U8 = CallByName Str.12 Json.142;
let Json.515 : List U8 = CallByName List.8 Json.518 Json.519;
let Json.517 : I64 = 34i64;
let Json.516 : U8 = CallByName Num.127 Json.517;
let Json.512 : List U8 = CallByName List.4 Json.515 Json.516;
let Json.514 : I64 = 58i64;
let Json.513 : U8 = CallByName Num.127 Json.514;
let Json.509 : List U8 = CallByName List.4 Json.512 Json.513;
let Json.511 : I64 = 91i64;
let Json.510 : U8 = CallByName Num.127 Json.511;
let Json.147 : List U8 = CallByName List.4 Json.509 Json.510;
let Json.508 : U64 = CallByName List.6 Json.143;
let Json.496 : {List U8, U64} = Struct {Json.147, Json.508};
let Json.497 : {} = Struct {};
let Json.495 : {List U8, U64} = CallByName List.18 Json.143 Json.496 Json.497;
dec Json.143;
let Json.149 : List U8 = StructAtIndex 0 Json.495;
inc Json.149;
dec Json.495;
let Json.494 : I64 = 93i64;
let Json.493 : U8 = CallByName Num.127 Json.494;
let Json.490 : List U8 = CallByName List.4 Json.149 Json.493;
let Json.492 : I64 = 125i64;
let Json.491 : U8 = CallByName Num.127 Json.492;
let Json.489 : List U8 = CallByName List.4 Json.490 Json.491;
ret Json.489;
procedure Json.130 (Json.430, Json.136):
let Json.134 : List U8 = StructAtIndex 0 Json.430;
inc Json.134;
let Json.135 : U64 = StructAtIndex 1 Json.430;
dec Json.430;
let Json.449 : {} = Struct {};
let Json.137 : List U8 = CallByName Encode.23 Json.134 Json.136 Json.449;
joinpoint Json.444 Json.138:
let Json.442 : U64 = 1i64;
let Json.441 : U64 = CallByName Num.20 Json.135 Json.442;
let Json.440 : {List U8, U64} = Struct {Json.138, Json.441};
ret Json.440;
procedure Json.146 (Json.488, Json.152):
let Json.150 : List U8 = StructAtIndex 0 Json.488;
inc Json.150;
let Json.151 : U64 = StructAtIndex 1 Json.488;
dec Json.488;
let Json.507 : {} = Struct {};
let Json.153 : List U8 = CallByName Encode.24 Json.150 Json.152 Json.507;
joinpoint Json.502 Json.154:
let Json.500 : U64 = 1i64;
let Json.499 : U64 = CallByName Num.20 Json.151 Json.500;
let Json.498 : {List U8, U64} = Struct {Json.154, Json.499};
ret Json.498;
in
let Json.448 : U64 = 1i64;
let Json.445 : Int1 = CallByName Num.24 Json.135 Json.448;
if Json.445 then
let Json.447 : I64 = 44i64;
let Json.446 : U8 = CallByName Num.127 Json.447;
let Json.443 : List U8 = CallByName List.4 Json.137 Json.446;
jump Json.444 Json.443;
let Json.506 : U64 = 1i64;
let Json.503 : Int1 = CallByName Num.24 Json.151 Json.506;
if Json.503 then
let Json.505 : I64 = 44i64;
let Json.504 : U8 = CallByName Num.127 Json.505;
let Json.501 : List U8 = CallByName List.4 Json.153 Json.504;
jump Json.502 Json.501;
else
jump Json.444 Json.137;
jump Json.502 Json.153;
procedure Json.18 (Json.97):
let Json.467 : Str = CallByName Encode.22 Json.97;
ret Json.467;
procedure Json.18 (Json.101):
let Json.525 : Str = CallByName Encode.23 Json.101;
ret Json.525;
procedure Json.21 (Json.126, Json.127):
let Json.427 : {Str, List Str} = Struct {Json.126, Json.127};
let Json.426 : {Str, List Str} = CallByName Encode.22 Json.427;
ret Json.426;
procedure Json.98 (Json.99, Json.469, Json.97):
let Json.478 : I64 = 34i64;
let Json.477 : U8 = CallByName Num.127 Json.478;
let Json.475 : List U8 = CallByName List.4 Json.99 Json.477;
let Json.476 : List U8 = CallByName Str.12 Json.97;
let Json.472 : List U8 = CallByName List.8 Json.475 Json.476;
let Json.474 : I64 = 34i64;
let Json.473 : U8 = CallByName Num.127 Json.474;
let Json.471 : List U8 = CallByName List.4 Json.472 Json.473;
ret Json.471;
procedure Json.22 (Json.142, Json.143):
let Json.485 : {Str, List Str} = Struct {Json.142, Json.143};
let Json.484 : {Str, List Str} = CallByName Encode.23 Json.485;
ret Json.484;
procedure List.139 (List.140, List.141, List.138):
let List.547 : {List U8, U64} = CallByName Json.130 List.140 List.141;
let List.547 : {List U8, U64} = CallByName Json.146 List.140 List.141;
ret List.547;
procedure List.18 (List.136, List.137, List.138):
@ -234,7 +234,7 @@ procedure Str.9 (Str.77):
procedure Test.0 ():
let Test.12 : Str = "foo";
let Test.11 : {} = CallByName Json.1;
let Test.10 : List U8 = CallByName Encode.25 Test.12 Test.11;
let Test.10 : List U8 = CallByName Encode.26 Test.12 Test.11;
let Test.2 : [C {U64, U8}, C Str] = CallByName Str.9 Test.10;
let Test.7 : U8 = 1i64;
let Test.8 : U8 = GetTagId Test.2;

View file

@ -1,10 +1,10 @@
procedure #Derived.0 (#Derived.1):
let #Derived_gen.0 : {Str, Str} = CallByName Encode.22 #Derived.1;
let #Derived_gen.0 : {Str, Str} = CallByName Encode.23 #Derived.1;
ret #Derived_gen.0;
procedure #Derived.4 (#Derived.5, #Derived.6, #Derived.1):
joinpoint #Derived_gen.5 #Derived_gen.4:
let #Derived_gen.3 : List U8 = CallByName Encode.23 #Derived.5 #Derived_gen.4 #Derived.6;
let #Derived_gen.3 : List U8 = CallByName Encode.24 #Derived.5 #Derived_gen.4 #Derived.6;
ret #Derived_gen.3;
in
let #Derived.2 : Str = StructAtIndex 0 #Derived.1;
@ -16,124 +16,124 @@ procedure #Derived.4 (#Derived.5, #Derived.6, #Derived.1):
let #Derived_gen.9 : Str = CallByName Json.18 #Derived.2;
let #Derived_gen.10 : Str = CallByName Json.18 #Derived.3;
let #Derived_gen.8 : List Str = Array [#Derived_gen.9, #Derived_gen.10];
let #Derived_gen.6 : {Str, List Str} = CallByName Json.21 #Derived_gen.7 #Derived_gen.8;
let #Derived_gen.6 : {Str, List Str} = CallByName Json.22 #Derived_gen.7 #Derived_gen.8;
jump #Derived_gen.5 #Derived_gen.6;
procedure Encode.22 (Encode.93):
ret Encode.93;
procedure Encode.23 (Encode.98):
ret Encode.98;
procedure Encode.22 (Encode.93):
ret Encode.93;
procedure Encode.23 (Encode.98):
ret Encode.98;
procedure Encode.22 (Encode.93):
ret Encode.93;
procedure Encode.23 (Encode.98):
ret Encode.98;
procedure Encode.23 (Encode.94, Encode.102, Encode.96):
let Encode.106 : List U8 = CallByName #Derived.4 Encode.94 Encode.96 Encode.102;
ret Encode.106;
procedure Encode.24 (Encode.99, Encode.107, Encode.101):
let Encode.111 : List U8 = CallByName #Derived.4 Encode.99 Encode.101 Encode.107;
ret Encode.111;
procedure Encode.23 (Encode.94, Encode.102, Encode.96):
let Encode.113 : List U8 = CallByName Json.128 Encode.94 Encode.96 Encode.102;
ret Encode.113;
procedure Encode.24 (Encode.99, Encode.107, Encode.101):
let Encode.118 : List U8 = CallByName Json.144 Encode.99 Encode.101 Encode.107;
ret Encode.118;
procedure Encode.23 (Encode.94, Encode.102, Encode.96):
let Encode.117 : List U8 = CallByName Json.98 Encode.94 Encode.96 Encode.102;
ret Encode.117;
procedure Encode.24 (Encode.99, Encode.107, Encode.101):
let Encode.122 : List U8 = CallByName Json.102 Encode.99 Encode.101 Encode.107;
ret Encode.122;
procedure Encode.25 (Encode.100, Encode.101):
let Encode.104 : List U8 = Array [];
let Encode.105 : {Str, Str} = CallByName #Derived.0 Encode.100;
let Encode.103 : List U8 = CallByName Encode.23 Encode.104 Encode.105 Encode.101;
ret Encode.103;
procedure Encode.26 (Encode.105, Encode.106):
let Encode.109 : List U8 = Array [];
let Encode.110 : {Str, Str} = CallByName #Derived.0 Encode.105;
let Encode.108 : List U8 = CallByName Encode.24 Encode.109 Encode.110 Encode.106;
ret Encode.108;
procedure Json.1 ():
let Json.425 : {} = Struct {};
ret Json.425;
let Json.483 : {} = Struct {};
ret Json.483;
procedure Json.128 (Json.129, Json.428, #Attr.12):
let Json.127 : List Str = StructAtIndex 1 #Attr.12;
inc Json.127;
let Json.126 : Str = StructAtIndex 0 #Attr.12;
inc Json.126;
procedure Json.102 (Json.103, Json.527, Json.101):
let Json.536 : I64 = 34i64;
let Json.535 : U8 = CallByName Num.127 Json.536;
let Json.533 : List U8 = CallByName List.4 Json.103 Json.535;
let Json.534 : List U8 = CallByName Str.12 Json.101;
let Json.530 : List U8 = CallByName List.8 Json.533 Json.534;
let Json.532 : I64 = 34i64;
let Json.531 : U8 = CallByName Num.127 Json.532;
let Json.529 : List U8 = CallByName List.4 Json.530 Json.531;
ret Json.529;
procedure Json.144 (Json.145, Json.486, #Attr.12):
let Json.143 : List Str = StructAtIndex 1 #Attr.12;
inc Json.143;
let Json.142 : Str = StructAtIndex 0 #Attr.12;
inc Json.142;
dec #Attr.12;
let Json.466 : I64 = 123i64;
let Json.465 : U8 = CallByName Num.127 Json.466;
let Json.462 : List U8 = CallByName List.4 Json.129 Json.465;
let Json.464 : I64 = 34i64;
let Json.463 : U8 = CallByName Num.127 Json.464;
let Json.460 : List U8 = CallByName List.4 Json.462 Json.463;
let Json.461 : List U8 = CallByName Str.12 Json.126;
let Json.457 : List U8 = CallByName List.8 Json.460 Json.461;
let Json.459 : I64 = 34i64;
let Json.458 : U8 = CallByName Num.127 Json.459;
let Json.454 : List U8 = CallByName List.4 Json.457 Json.458;
let Json.456 : I64 = 58i64;
let Json.455 : U8 = CallByName Num.127 Json.456;
let Json.451 : List U8 = CallByName List.4 Json.454 Json.455;
let Json.453 : I64 = 91i64;
let Json.452 : U8 = CallByName Num.127 Json.453;
let Json.131 : List U8 = CallByName List.4 Json.451 Json.452;
let Json.450 : U64 = CallByName List.6 Json.127;
let Json.438 : {List U8, U64} = Struct {Json.131, Json.450};
let Json.439 : {} = Struct {};
let Json.437 : {List U8, U64} = CallByName List.18 Json.127 Json.438 Json.439;
dec Json.127;
let Json.133 : List U8 = StructAtIndex 0 Json.437;
inc Json.133;
dec Json.437;
let Json.436 : I64 = 93i64;
let Json.435 : U8 = CallByName Num.127 Json.436;
let Json.432 : List U8 = CallByName List.4 Json.133 Json.435;
let Json.434 : I64 = 125i64;
let Json.433 : U8 = CallByName Num.127 Json.434;
let Json.431 : List U8 = CallByName List.4 Json.432 Json.433;
ret Json.431;
let Json.524 : I64 = 123i64;
let Json.523 : U8 = CallByName Num.127 Json.524;
let Json.520 : List U8 = CallByName List.4 Json.145 Json.523;
let Json.522 : I64 = 34i64;
let Json.521 : U8 = CallByName Num.127 Json.522;
let Json.518 : List U8 = CallByName List.4 Json.520 Json.521;
let Json.519 : List U8 = CallByName Str.12 Json.142;
let Json.515 : List U8 = CallByName List.8 Json.518 Json.519;
let Json.517 : I64 = 34i64;
let Json.516 : U8 = CallByName Num.127 Json.517;
let Json.512 : List U8 = CallByName List.4 Json.515 Json.516;
let Json.514 : I64 = 58i64;
let Json.513 : U8 = CallByName Num.127 Json.514;
let Json.509 : List U8 = CallByName List.4 Json.512 Json.513;
let Json.511 : I64 = 91i64;
let Json.510 : U8 = CallByName Num.127 Json.511;
let Json.147 : List U8 = CallByName List.4 Json.509 Json.510;
let Json.508 : U64 = CallByName List.6 Json.143;
let Json.496 : {List U8, U64} = Struct {Json.147, Json.508};
let Json.497 : {} = Struct {};
let Json.495 : {List U8, U64} = CallByName List.18 Json.143 Json.496 Json.497;
dec Json.143;
let Json.149 : List U8 = StructAtIndex 0 Json.495;
inc Json.149;
dec Json.495;
let Json.494 : I64 = 93i64;
let Json.493 : U8 = CallByName Num.127 Json.494;
let Json.490 : List U8 = CallByName List.4 Json.149 Json.493;
let Json.492 : I64 = 125i64;
let Json.491 : U8 = CallByName Num.127 Json.492;
let Json.489 : List U8 = CallByName List.4 Json.490 Json.491;
ret Json.489;
procedure Json.130 (Json.430, Json.136):
let Json.134 : List U8 = StructAtIndex 0 Json.430;
inc Json.134;
let Json.135 : U64 = StructAtIndex 1 Json.430;
dec Json.430;
let Json.449 : {} = Struct {};
let Json.137 : List U8 = CallByName Encode.23 Json.134 Json.136 Json.449;
joinpoint Json.444 Json.138:
let Json.442 : U64 = 1i64;
let Json.441 : U64 = CallByName Num.20 Json.135 Json.442;
let Json.440 : {List U8, U64} = Struct {Json.138, Json.441};
ret Json.440;
procedure Json.146 (Json.488, Json.152):
let Json.150 : List U8 = StructAtIndex 0 Json.488;
inc Json.150;
let Json.151 : U64 = StructAtIndex 1 Json.488;
dec Json.488;
let Json.507 : {} = Struct {};
let Json.153 : List U8 = CallByName Encode.24 Json.150 Json.152 Json.507;
joinpoint Json.502 Json.154:
let Json.500 : U64 = 1i64;
let Json.499 : U64 = CallByName Num.20 Json.151 Json.500;
let Json.498 : {List U8, U64} = Struct {Json.154, Json.499};
ret Json.498;
in
let Json.448 : U64 = 1i64;
let Json.445 : Int1 = CallByName Num.24 Json.135 Json.448;
if Json.445 then
let Json.447 : I64 = 44i64;
let Json.446 : U8 = CallByName Num.127 Json.447;
let Json.443 : List U8 = CallByName List.4 Json.137 Json.446;
jump Json.444 Json.443;
let Json.506 : U64 = 1i64;
let Json.503 : Int1 = CallByName Num.24 Json.151 Json.506;
if Json.503 then
let Json.505 : I64 = 44i64;
let Json.504 : U8 = CallByName Num.127 Json.505;
let Json.501 : List U8 = CallByName List.4 Json.153 Json.504;
jump Json.502 Json.501;
else
jump Json.444 Json.137;
jump Json.502 Json.153;
procedure Json.18 (Json.97):
let Json.479 : Str = CallByName Encode.22 Json.97;
ret Json.479;
procedure Json.18 (Json.101):
let Json.537 : Str = CallByName Encode.23 Json.101;
ret Json.537;
procedure Json.21 (Json.126, Json.127):
let Json.427 : {Str, List Str} = Struct {Json.126, Json.127};
let Json.426 : {Str, List Str} = CallByName Encode.22 Json.427;
ret Json.426;
procedure Json.98 (Json.99, Json.469, Json.97):
let Json.478 : I64 = 34i64;
let Json.477 : U8 = CallByName Num.127 Json.478;
let Json.475 : List U8 = CallByName List.4 Json.99 Json.477;
let Json.476 : List U8 = CallByName Str.12 Json.97;
let Json.472 : List U8 = CallByName List.8 Json.475 Json.476;
let Json.474 : I64 = 34i64;
let Json.473 : U8 = CallByName Num.127 Json.474;
let Json.471 : List U8 = CallByName List.4 Json.472 Json.473;
ret Json.471;
procedure Json.22 (Json.142, Json.143):
let Json.485 : {Str, List Str} = Struct {Json.142, Json.143};
let Json.484 : {Str, List Str} = CallByName Encode.23 Json.485;
ret Json.484;
procedure List.139 (List.140, List.141, List.138):
let List.547 : {List U8, U64} = CallByName Json.130 List.140 List.141;
let List.547 : {List U8, U64} = CallByName Json.146 List.140 List.141;
ret List.547;
procedure List.18 (List.136, List.137, List.138):
@ -242,7 +242,7 @@ procedure Test.0 ():
let Test.12 : Str = "foo";
let Test.1 : {Str, Str} = Struct {Test.12, Test.13};
let Test.11 : {} = CallByName Json.1;
let Test.10 : List U8 = CallByName Encode.25 Test.1 Test.11;
let Test.10 : List U8 = CallByName Encode.26 Test.1 Test.11;
let Test.2 : [C {U64, U8}, C Str] = CallByName Str.9 Test.10;
let Test.7 : U8 = 1i64;
let Test.8 : U8 = GetTagId Test.2;

View file

@ -28,229 +28,229 @@ procedure Bool.7 (Bool.19, Bool.20):
let Bool.37 : Int1 = CallByName Bool.12 Bool.19 Bool.20;
ret Bool.37;
procedure Decode.23 (Decode.94):
ret Decode.94;
procedure Decode.24 (Decode.101):
ret Decode.101;
procedure Decode.24 (Decode.95, Decode.114, Decode.97):
let Decode.127 : {List U8, [C {}, C Str]} = CallByName Json.299 Decode.95 Decode.97;
ret Decode.127;
procedure Decode.25 (Decode.102, Decode.121, Decode.104):
let Decode.134 : {List U8, [C {}, C Str]} = CallByName Json.315 Decode.102 Decode.104;
ret Decode.134;
procedure Decode.25 (Decode.98, Decode.99):
let Decode.126 : {} = CallByName Json.42;
let Decode.125 : {List U8, [C {}, C Str]} = CallByName Decode.24 Decode.98 Decode.126 Decode.99;
ret Decode.125;
procedure Decode.26 (Decode.105, Decode.106):
let Decode.133 : {} = CallByName Json.43;
let Decode.132 : {List U8, [C {}, C Str]} = CallByName Decode.25 Decode.105 Decode.133 Decode.106;
ret Decode.132;
procedure Decode.26 (Decode.100, Decode.101):
let Decode.115 : {List U8, [C {}, C Str]} = CallByName Decode.25 Decode.100 Decode.101;
let Decode.103 : List U8 = StructAtIndex 0 Decode.115;
inc Decode.103;
let Decode.102 : [C {}, C Str] = StructAtIndex 1 Decode.115;
inc Decode.102;
dec Decode.115;
let Decode.118 : Int1 = CallByName List.1 Decode.103;
if Decode.118 then
dec Decode.103;
let Decode.122 : U8 = 1i64;
let Decode.123 : U8 = GetTagId Decode.102;
let Decode.124 : Int1 = lowlevel Eq Decode.122 Decode.123;
if Decode.124 then
let Decode.104 : Str = UnionAtIndex (Id 1) (Index 0) Decode.102;
inc Decode.104;
dec Decode.102;
let Decode.119 : [C [C List U8, C ], C Str] = TagId(1) Decode.104;
ret Decode.119;
procedure Decode.27 (Decode.107, Decode.108):
let Decode.122 : {List U8, [C {}, C Str]} = CallByName Decode.26 Decode.107 Decode.108;
let Decode.110 : List U8 = StructAtIndex 0 Decode.122;
inc Decode.110;
let Decode.109 : [C {}, C Str] = StructAtIndex 1 Decode.122;
inc Decode.109;
dec Decode.122;
let Decode.125 : Int1 = CallByName List.1 Decode.110;
if Decode.125 then
dec Decode.110;
let Decode.129 : U8 = 1i64;
let Decode.130 : U8 = GetTagId Decode.109;
let Decode.131 : Int1 = lowlevel Eq Decode.129 Decode.130;
if Decode.131 then
let Decode.111 : Str = UnionAtIndex (Id 1) (Index 0) Decode.109;
inc Decode.111;
dec Decode.109;
let Decode.126 : [C [C List U8, C ], C Str] = TagId(1) Decode.111;
ret Decode.126;
else
dec Decode.102;
let Decode.121 : [C List U8, C ] = TagId(1) ;
let Decode.120 : [C [C List U8, C ], C Str] = TagId(0) Decode.121;
ret Decode.120;
dec Decode.109;
let Decode.128 : [C List U8, C ] = TagId(1) ;
let Decode.127 : [C [C List U8, C ], C Str] = TagId(0) Decode.128;
ret Decode.127;
else
dec Decode.102;
let Decode.117 : [C List U8, C ] = TagId(0) Decode.103;
let Decode.116 : [C [C List U8, C ], C Str] = TagId(0) Decode.117;
ret Decode.116;
dec Decode.109;
let Decode.124 : [C List U8, C ] = TagId(0) Decode.110;
let Decode.123 : [C [C List U8, C ], C Str] = TagId(0) Decode.124;
ret Decode.123;
procedure Json.144 (Json.512, Json.513):
joinpoint Json.450 Json.447 Json.143:
let Json.146 : List U8 = StructAtIndex 0 Json.447;
inc Json.146;
let Json.145 : List U8 = StructAtIndex 1 Json.447;
inc Json.145;
dec Json.447;
joinpoint Json.490:
let Json.487 : {List U8, List U8} = Struct {Json.146, Json.145};
ret Json.487;
procedure Json.160 (Json.570, Json.571):
joinpoint Json.508 Json.505 Json.159:
let Json.162 : List U8 = StructAtIndex 0 Json.505;
inc Json.162;
let Json.161 : List U8 = StructAtIndex 1 Json.505;
inc Json.161;
dec Json.505;
joinpoint Json.548:
let Json.545 : {List U8, List U8} = Struct {Json.162, Json.161};
ret Json.545;
in
let Json.496 : U64 = lowlevel ListLen Json.146;
let Json.497 : U64 = 2i64;
let Json.498 : Int1 = lowlevel NumGte Json.496 Json.497;
if Json.498 then
let Json.489 : U64 = 0i64;
let Json.147 : U8 = lowlevel ListGetUnsafe Json.146 Json.489;
let Json.488 : U64 = 1i64;
let Json.148 : U8 = lowlevel ListGetUnsafe Json.146 Json.488;
let Json.458 : Int1 = CallByName Json.22 Json.147 Json.148;
if Json.458 then
let Json.465 : U64 = 2i64;
let Json.462 : List U8 = CallByName List.29 Json.146 Json.465;
let Json.464 : List U8 = CallByName List.4 Json.145 Json.147;
let Json.463 : List U8 = CallByName List.4 Json.464 Json.148;
let Json.460 : {List U8, List U8} = Struct {Json.462, Json.463};
jump Json.450 Json.460 Json.143;
let Json.554 : U64 = lowlevel ListLen Json.162;
let Json.555 : U64 = 2i64;
let Json.556 : Int1 = lowlevel NumGte Json.554 Json.555;
if Json.556 then
let Json.547 : U64 = 0i64;
let Json.163 : U8 = lowlevel ListGetUnsafe Json.162 Json.547;
let Json.546 : U64 = 1i64;
let Json.164 : U8 = lowlevel ListGetUnsafe Json.162 Json.546;
let Json.516 : Int1 = CallByName Json.23 Json.163 Json.164;
if Json.516 then
let Json.523 : U64 = 2i64;
let Json.520 : List U8 = CallByName List.29 Json.162 Json.523;
let Json.522 : List U8 = CallByName List.4 Json.161 Json.163;
let Json.521 : List U8 = CallByName List.4 Json.522 Json.164;
let Json.518 : {List U8, List U8} = Struct {Json.520, Json.521};
jump Json.508 Json.518 Json.159;
else
let Json.452 : Int1 = CallByName Json.289 Json.147;
if Json.452 then
let Json.456 : List U8 = CallByName List.38 Json.146;
let Json.457 : List U8 = CallByName List.4 Json.145 Json.147;
let Json.454 : {List U8, List U8} = Struct {Json.456, Json.457};
jump Json.450 Json.454 Json.143;
let Json.510 : Int1 = CallByName Json.305 Json.163;
if Json.510 then
let Json.514 : List U8 = CallByName List.38 Json.162;
let Json.515 : List U8 = CallByName List.4 Json.161 Json.163;
let Json.512 : {List U8, List U8} = Struct {Json.514, Json.515};
jump Json.508 Json.512 Json.159;
else
let Json.451 : {List U8, List U8} = Struct {Json.146, Json.145};
ret Json.451;
let Json.509 : {List U8, List U8} = Struct {Json.162, Json.161};
ret Json.509;
else
let Json.493 : U64 = lowlevel ListLen Json.146;
let Json.494 : U64 = 1i64;
let Json.495 : Int1 = lowlevel NumGte Json.493 Json.494;
if Json.495 then
let Json.492 : U64 = 0i64;
let Json.149 : U8 = lowlevel ListGetUnsafe Json.146 Json.492;
joinpoint Json.485 Json.491:
if Json.491 then
let Json.483 : List U8 = CallByName List.38 Json.146;
let Json.484 : List U8 = CallByName List.4 Json.145 Json.149;
let Json.481 : {List U8, List U8} = Struct {Json.483, Json.484};
jump Json.450 Json.481 Json.143;
let Json.551 : U64 = lowlevel ListLen Json.162;
let Json.552 : U64 = 1i64;
let Json.553 : Int1 = lowlevel NumGte Json.551 Json.552;
if Json.553 then
let Json.550 : U64 = 0i64;
let Json.165 : U8 = lowlevel ListGetUnsafe Json.162 Json.550;
joinpoint Json.543 Json.549:
if Json.549 then
let Json.541 : List U8 = CallByName List.38 Json.162;
let Json.542 : List U8 = CallByName List.4 Json.161 Json.165;
let Json.539 : {List U8, List U8} = Struct {Json.541, Json.542};
jump Json.508 Json.539 Json.159;
else
jump Json.490;
jump Json.548;
in
let Json.486 : Int1 = CallByName Json.289 Json.149;
jump Json.485 Json.486;
let Json.544 : Int1 = CallByName Json.305 Json.165;
jump Json.543 Json.544;
else
jump Json.490;
jump Json.548;
in
jump Json.450 Json.512 Json.513;
jump Json.508 Json.570 Json.571;
procedure Json.2 ():
let Json.425 : {} = Struct {};
ret Json.425;
let Json.483 : {} = Struct {};
ret Json.483;
procedure Json.22 (Json.139, Json.140):
let Json.466 : {U8, U8} = Struct {Json.139, Json.140};
joinpoint Json.475:
let Json.474 : Int1 = CallByName Bool.1;
ret Json.474;
procedure Json.23 (Json.155, Json.156):
let Json.524 : {U8, U8} = Struct {Json.155, Json.156};
joinpoint Json.533:
let Json.532 : Int1 = CallByName Bool.1;
ret Json.532;
in
let Json.477 : U8 = StructAtIndex 0 Json.466;
let Json.478 : U8 = 92i64;
let Json.479 : Int1 = lowlevel Eq Json.478 Json.477;
if Json.479 then
let Json.476 : U8 = StructAtIndex 1 Json.466;
switch Json.476:
let Json.535 : U8 = StructAtIndex 0 Json.524;
let Json.536 : U8 = 92i64;
let Json.537 : Int1 = lowlevel Eq Json.536 Json.535;
if Json.537 then
let Json.534 : U8 = StructAtIndex 1 Json.524;
switch Json.534:
case 98:
let Json.467 : Int1 = CallByName Bool.2;
ret Json.467;
let Json.525 : Int1 = CallByName Bool.2;
ret Json.525;
case 102:
let Json.468 : Int1 = CallByName Bool.2;
ret Json.468;
let Json.526 : Int1 = CallByName Bool.2;
ret Json.526;
case 110:
let Json.469 : Int1 = CallByName Bool.2;
ret Json.469;
let Json.527 : Int1 = CallByName Bool.2;
ret Json.527;
case 114:
let Json.470 : Int1 = CallByName Bool.2;
ret Json.470;
let Json.528 : Int1 = CallByName Bool.2;
ret Json.528;
case 116:
let Json.471 : Int1 = CallByName Bool.2;
ret Json.471;
let Json.529 : Int1 = CallByName Bool.2;
ret Json.529;
case 34:
let Json.472 : Int1 = CallByName Bool.2;
ret Json.472;
let Json.530 : Int1 = CallByName Bool.2;
ret Json.530;
case 92:
let Json.473 : Int1 = CallByName Bool.2;
ret Json.473;
let Json.531 : Int1 = CallByName Bool.2;
ret Json.531;
default:
jump Json.475;
jump Json.533;
else
jump Json.475;
jump Json.533;
procedure Json.23 (Json.142, Json.143):
let Json.500 : List U8 = Array [];
let Json.449 : {List U8, List U8} = Struct {Json.142, Json.500};
let Json.448 : {List U8, List U8} = CallByName Json.144 Json.449 Json.143;
ret Json.448;
procedure Json.24 (Json.158, Json.159):
let Json.558 : List U8 = Array [];
let Json.507 : {List U8, List U8} = Struct {Json.158, Json.558};
let Json.506 : {List U8, List U8} = CallByName Json.160 Json.507 Json.159;
ret Json.506;
procedure Json.289 (Json.290):
let Json.502 : U8 = 34i64;
let Json.501 : Int1 = CallByName Bool.7 Json.290 Json.502;
ret Json.501;
procedure Json.305 (Json.306):
let Json.560 : U8 = 34i64;
let Json.559 : Int1 = CallByName Bool.7 Json.306 Json.560;
ret Json.559;
procedure Json.299 (Json.300, Json.428):
let Json.429 : {List U8, [C {}, C Str]} = CallByName Json.41 Json.300;
ret Json.429;
procedure Json.315 (Json.316, Json.486):
let Json.487 : {List U8, [C {}, C Str]} = CallByName Json.42 Json.316;
ret Json.487;
procedure Json.41 (Json.282):
let Json.506 : U64 = 1i64;
inc Json.282;
let Json.505 : {List U8, List U8} = CallByName List.52 Json.282 Json.506;
let Json.283 : List U8 = StructAtIndex 0 Json.505;
inc Json.283;
let Json.285 : List U8 = StructAtIndex 1 Json.505;
inc Json.285;
dec Json.505;
let Json.504 : U8 = 34i64;
let Json.503 : List U8 = Array [Json.504];
let Json.433 : Int1 = CallByName Bool.11 Json.283 Json.503;
dec Json.503;
dec Json.283;
if Json.433 then
dec Json.282;
let Json.446 : {} = Struct {};
let Json.445 : {List U8, List U8} = CallByName Json.23 Json.285 Json.446;
let Json.288 : List U8 = StructAtIndex 0 Json.445;
inc Json.288;
let Json.287 : List U8 = StructAtIndex 1 Json.445;
inc Json.287;
dec Json.445;
let Json.434 : [C {U64, U8}, C Str] = CallByName Str.9 Json.287;
let Json.442 : U8 = 1i64;
let Json.443 : U8 = GetTagId Json.434;
let Json.444 : Int1 = lowlevel Eq Json.442 Json.443;
if Json.444 then
let Json.291 : Str = UnionAtIndex (Id 1) (Index 0) Json.434;
inc Json.291;
dec Json.434;
let Json.438 : U64 = 1i64;
let Json.437 : {List U8, List U8} = CallByName List.52 Json.288 Json.438;
let Json.293 : List U8 = StructAtIndex 1 Json.437;
inc Json.293;
dec Json.437;
let Json.436 : [C {}, C Str] = TagId(1) Json.291;
let Json.435 : {List U8, [C {}, C Str]} = Struct {Json.293, Json.436};
ret Json.435;
procedure Json.42 (Json.298):
let Json.564 : U64 = 1i64;
inc Json.298;
let Json.563 : {List U8, List U8} = CallByName List.52 Json.298 Json.564;
let Json.299 : List U8 = StructAtIndex 0 Json.563;
inc Json.299;
let Json.301 : List U8 = StructAtIndex 1 Json.563;
inc Json.301;
dec Json.563;
let Json.562 : U8 = 34i64;
let Json.561 : List U8 = Array [Json.562];
let Json.491 : Int1 = CallByName Bool.11 Json.299 Json.561;
dec Json.561;
dec Json.299;
if Json.491 then
dec Json.298;
let Json.504 : {} = Struct {};
let Json.503 : {List U8, List U8} = CallByName Json.24 Json.301 Json.504;
let Json.304 : List U8 = StructAtIndex 0 Json.503;
inc Json.304;
let Json.303 : List U8 = StructAtIndex 1 Json.503;
inc Json.303;
dec Json.503;
let Json.492 : [C {U64, U8}, C Str] = CallByName Str.9 Json.303;
let Json.500 : U8 = 1i64;
let Json.501 : U8 = GetTagId Json.492;
let Json.502 : Int1 = lowlevel Eq Json.500 Json.501;
if Json.502 then
let Json.307 : Str = UnionAtIndex (Id 1) (Index 0) Json.492;
inc Json.307;
dec Json.492;
let Json.496 : U64 = 1i64;
let Json.495 : {List U8, List U8} = CallByName List.52 Json.304 Json.496;
let Json.309 : List U8 = StructAtIndex 1 Json.495;
inc Json.309;
dec Json.495;
let Json.494 : [C {}, C Str] = TagId(1) Json.307;
let Json.493 : {List U8, [C {}, C Str]} = Struct {Json.309, Json.494};
ret Json.493;
else
dec Json.434;
let Json.441 : {} = Struct {};
let Json.440 : [C {}, C Str] = TagId(0) Json.441;
let Json.439 : {List U8, [C {}, C Str]} = Struct {Json.288, Json.440};
ret Json.439;
dec Json.492;
let Json.499 : {} = Struct {};
let Json.498 : [C {}, C Str] = TagId(0) Json.499;
let Json.497 : {List U8, [C {}, C Str]} = Struct {Json.304, Json.498};
ret Json.497;
else
dec Json.285;
let Json.432 : {} = Struct {};
let Json.431 : [C {}, C Str] = TagId(0) Json.432;
let Json.430 : {List U8, [C {}, C Str]} = Struct {Json.282, Json.431};
ret Json.430;
dec Json.301;
let Json.490 : {} = Struct {};
let Json.489 : [C {}, C Str] = TagId(0) Json.490;
let Json.488 : {List U8, [C {}, C Str]} = Struct {Json.298, Json.489};
ret Json.488;
procedure Json.42 ():
let Json.427 : {} = Struct {};
let Json.426 : {} = CallByName Decode.23 Json.427;
ret Json.426;
procedure Json.43 ():
let Json.485 : {} = Struct {};
let Json.484 : {} = CallByName Decode.24 Json.485;
ret Json.484;
procedure List.1 (List.95):
let List.495 : U64 = CallByName List.6 List.95;
@ -374,7 +374,7 @@ procedure Test.3 ():
let Test.0 : List U8 = Array [82i64, 111i64, 99i64];
let Test.8 : {} = CallByName Json.2;
inc Test.0;
let Test.1 : [C [C List U8, C ], C Str] = CallByName Decode.26 Test.0 Test.8;
let Test.1 : [C [C List U8, C ], C Str] = CallByName Decode.27 Test.0 Test.8;
let Test.7 : Str = "Roc";
let Test.6 : [C [C List U8, C ], C Str] = TagId(1) Test.7;
inc Test.1;

View file

@ -32,199 +32,199 @@ procedure Bool.7 (Bool.19, Bool.20):
let Bool.37 : Int1 = CallByName Bool.12 Bool.19 Bool.20;
ret Bool.37;
procedure Decode.23 (Decode.94):
ret Decode.94;
procedure Decode.24 (Decode.101):
ret Decode.101;
procedure Decode.24 (Decode.95, Decode.114, Decode.97):
let Decode.117 : {List U8, [C {}, C Str]} = CallByName Json.299 Decode.95 Decode.97;
ret Decode.117;
procedure Decode.25 (Decode.102, Decode.121, Decode.104):
let Decode.124 : {List U8, [C {}, C Str]} = CallByName Json.315 Decode.102 Decode.104;
ret Decode.124;
procedure Decode.25 (Decode.98, Decode.99):
let Decode.116 : {} = CallByName Json.42;
let Decode.115 : {List U8, [C {}, C Str]} = CallByName Decode.24 Decode.98 Decode.116 Decode.99;
ret Decode.115;
procedure Decode.26 (Decode.105, Decode.106):
let Decode.123 : {} = CallByName Json.43;
let Decode.122 : {List U8, [C {}, C Str]} = CallByName Decode.25 Decode.105 Decode.123 Decode.106;
ret Decode.122;
procedure Json.144 (Json.512, Json.513):
joinpoint Json.450 Json.447 Json.143:
let Json.146 : List U8 = StructAtIndex 0 Json.447;
inc Json.146;
let Json.145 : List U8 = StructAtIndex 1 Json.447;
inc Json.145;
dec Json.447;
joinpoint Json.490:
let Json.487 : {List U8, List U8} = Struct {Json.146, Json.145};
ret Json.487;
procedure Json.160 (Json.570, Json.571):
joinpoint Json.508 Json.505 Json.159:
let Json.162 : List U8 = StructAtIndex 0 Json.505;
inc Json.162;
let Json.161 : List U8 = StructAtIndex 1 Json.505;
inc Json.161;
dec Json.505;
joinpoint Json.548:
let Json.545 : {List U8, List U8} = Struct {Json.162, Json.161};
ret Json.545;
in
let Json.496 : U64 = lowlevel ListLen Json.146;
let Json.497 : U64 = 2i64;
let Json.498 : Int1 = lowlevel NumGte Json.496 Json.497;
if Json.498 then
let Json.489 : U64 = 0i64;
let Json.147 : U8 = lowlevel ListGetUnsafe Json.146 Json.489;
let Json.488 : U64 = 1i64;
let Json.148 : U8 = lowlevel ListGetUnsafe Json.146 Json.488;
let Json.458 : Int1 = CallByName Json.22 Json.147 Json.148;
if Json.458 then
let Json.465 : U64 = 2i64;
let Json.462 : List U8 = CallByName List.29 Json.146 Json.465;
let Json.464 : List U8 = CallByName List.4 Json.145 Json.147;
let Json.463 : List U8 = CallByName List.4 Json.464 Json.148;
let Json.460 : {List U8, List U8} = Struct {Json.462, Json.463};
jump Json.450 Json.460 Json.143;
let Json.554 : U64 = lowlevel ListLen Json.162;
let Json.555 : U64 = 2i64;
let Json.556 : Int1 = lowlevel NumGte Json.554 Json.555;
if Json.556 then
let Json.547 : U64 = 0i64;
let Json.163 : U8 = lowlevel ListGetUnsafe Json.162 Json.547;
let Json.546 : U64 = 1i64;
let Json.164 : U8 = lowlevel ListGetUnsafe Json.162 Json.546;
let Json.516 : Int1 = CallByName Json.23 Json.163 Json.164;
if Json.516 then
let Json.523 : U64 = 2i64;
let Json.520 : List U8 = CallByName List.29 Json.162 Json.523;
let Json.522 : List U8 = CallByName List.4 Json.161 Json.163;
let Json.521 : List U8 = CallByName List.4 Json.522 Json.164;
let Json.518 : {List U8, List U8} = Struct {Json.520, Json.521};
jump Json.508 Json.518 Json.159;
else
let Json.452 : Int1 = CallByName Json.289 Json.147;
if Json.452 then
let Json.456 : List U8 = CallByName List.38 Json.146;
let Json.457 : List U8 = CallByName List.4 Json.145 Json.147;
let Json.454 : {List U8, List U8} = Struct {Json.456, Json.457};
jump Json.450 Json.454 Json.143;
let Json.510 : Int1 = CallByName Json.305 Json.163;
if Json.510 then
let Json.514 : List U8 = CallByName List.38 Json.162;
let Json.515 : List U8 = CallByName List.4 Json.161 Json.163;
let Json.512 : {List U8, List U8} = Struct {Json.514, Json.515};
jump Json.508 Json.512 Json.159;
else
let Json.451 : {List U8, List U8} = Struct {Json.146, Json.145};
ret Json.451;
let Json.509 : {List U8, List U8} = Struct {Json.162, Json.161};
ret Json.509;
else
let Json.493 : U64 = lowlevel ListLen Json.146;
let Json.494 : U64 = 1i64;
let Json.495 : Int1 = lowlevel NumGte Json.493 Json.494;
if Json.495 then
let Json.492 : U64 = 0i64;
let Json.149 : U8 = lowlevel ListGetUnsafe Json.146 Json.492;
joinpoint Json.485 Json.491:
if Json.491 then
let Json.483 : List U8 = CallByName List.38 Json.146;
let Json.484 : List U8 = CallByName List.4 Json.145 Json.149;
let Json.481 : {List U8, List U8} = Struct {Json.483, Json.484};
jump Json.450 Json.481 Json.143;
let Json.551 : U64 = lowlevel ListLen Json.162;
let Json.552 : U64 = 1i64;
let Json.553 : Int1 = lowlevel NumGte Json.551 Json.552;
if Json.553 then
let Json.550 : U64 = 0i64;
let Json.165 : U8 = lowlevel ListGetUnsafe Json.162 Json.550;
joinpoint Json.543 Json.549:
if Json.549 then
let Json.541 : List U8 = CallByName List.38 Json.162;
let Json.542 : List U8 = CallByName List.4 Json.161 Json.165;
let Json.539 : {List U8, List U8} = Struct {Json.541, Json.542};
jump Json.508 Json.539 Json.159;
else
jump Json.490;
jump Json.548;
in
let Json.486 : Int1 = CallByName Json.289 Json.149;
jump Json.485 Json.486;
let Json.544 : Int1 = CallByName Json.305 Json.165;
jump Json.543 Json.544;
else
jump Json.490;
jump Json.548;
in
jump Json.450 Json.512 Json.513;
jump Json.508 Json.570 Json.571;
procedure Json.2 ():
let Json.425 : {} = Struct {};
ret Json.425;
let Json.483 : {} = Struct {};
ret Json.483;
procedure Json.22 (Json.139, Json.140):
let Json.466 : {U8, U8} = Struct {Json.139, Json.140};
joinpoint Json.475:
let Json.474 : Int1 = CallByName Bool.1;
ret Json.474;
procedure Json.23 (Json.155, Json.156):
let Json.524 : {U8, U8} = Struct {Json.155, Json.156};
joinpoint Json.533:
let Json.532 : Int1 = CallByName Bool.1;
ret Json.532;
in
let Json.477 : U8 = StructAtIndex 0 Json.466;
let Json.478 : U8 = 92i64;
let Json.479 : Int1 = lowlevel Eq Json.478 Json.477;
if Json.479 then
let Json.476 : U8 = StructAtIndex 1 Json.466;
switch Json.476:
let Json.535 : U8 = StructAtIndex 0 Json.524;
let Json.536 : U8 = 92i64;
let Json.537 : Int1 = lowlevel Eq Json.536 Json.535;
if Json.537 then
let Json.534 : U8 = StructAtIndex 1 Json.524;
switch Json.534:
case 98:
let Json.467 : Int1 = CallByName Bool.2;
ret Json.467;
let Json.525 : Int1 = CallByName Bool.2;
ret Json.525;
case 102:
let Json.468 : Int1 = CallByName Bool.2;
ret Json.468;
let Json.526 : Int1 = CallByName Bool.2;
ret Json.526;
case 110:
let Json.469 : Int1 = CallByName Bool.2;
ret Json.469;
let Json.527 : Int1 = CallByName Bool.2;
ret Json.527;
case 114:
let Json.470 : Int1 = CallByName Bool.2;
ret Json.470;
let Json.528 : Int1 = CallByName Bool.2;
ret Json.528;
case 116:
let Json.471 : Int1 = CallByName Bool.2;
ret Json.471;
let Json.529 : Int1 = CallByName Bool.2;
ret Json.529;
case 34:
let Json.472 : Int1 = CallByName Bool.2;
ret Json.472;
let Json.530 : Int1 = CallByName Bool.2;
ret Json.530;
case 92:
let Json.473 : Int1 = CallByName Bool.2;
ret Json.473;
let Json.531 : Int1 = CallByName Bool.2;
ret Json.531;
default:
jump Json.475;
jump Json.533;
else
jump Json.475;
jump Json.533;
procedure Json.23 (Json.142, Json.143):
let Json.500 : List U8 = Array [];
let Json.449 : {List U8, List U8} = Struct {Json.142, Json.500};
let Json.448 : {List U8, List U8} = CallByName Json.144 Json.449 Json.143;
ret Json.448;
procedure Json.24 (Json.158, Json.159):
let Json.558 : List U8 = Array [];
let Json.507 : {List U8, List U8} = Struct {Json.158, Json.558};
let Json.506 : {List U8, List U8} = CallByName Json.160 Json.507 Json.159;
ret Json.506;
procedure Json.289 (Json.290):
let Json.502 : U8 = 34i64;
let Json.501 : Int1 = CallByName Bool.7 Json.290 Json.502;
ret Json.501;
procedure Json.305 (Json.306):
let Json.560 : U8 = 34i64;
let Json.559 : Int1 = CallByName Bool.7 Json.306 Json.560;
ret Json.559;
procedure Json.299 (Json.300, Json.428):
let Json.429 : {List U8, [C {}, C Str]} = CallByName Json.41 Json.300;
ret Json.429;
procedure Json.315 (Json.316, Json.486):
let Json.487 : {List U8, [C {}, C Str]} = CallByName Json.42 Json.316;
ret Json.487;
procedure Json.41 (Json.282):
let Json.506 : U64 = 1i64;
inc Json.282;
let Json.505 : {List U8, List U8} = CallByName List.52 Json.282 Json.506;
let Json.283 : List U8 = StructAtIndex 0 Json.505;
inc Json.283;
let Json.285 : List U8 = StructAtIndex 1 Json.505;
inc Json.285;
dec Json.505;
let Json.504 : U8 = 34i64;
let Json.503 : List U8 = Array [Json.504];
let Json.433 : Int1 = CallByName Bool.11 Json.283 Json.503;
dec Json.503;
dec Json.283;
if Json.433 then
dec Json.282;
let Json.446 : {} = Struct {};
let Json.445 : {List U8, List U8} = CallByName Json.23 Json.285 Json.446;
let Json.288 : List U8 = StructAtIndex 0 Json.445;
inc Json.288;
let Json.287 : List U8 = StructAtIndex 1 Json.445;
inc Json.287;
dec Json.445;
let Json.434 : [C {U64, U8}, C Str] = CallByName Str.9 Json.287;
let Json.442 : U8 = 1i64;
let Json.443 : U8 = GetTagId Json.434;
let Json.444 : Int1 = lowlevel Eq Json.442 Json.443;
if Json.444 then
let Json.291 : Str = UnionAtIndex (Id 1) (Index 0) Json.434;
inc Json.291;
dec Json.434;
let Json.438 : U64 = 1i64;
let Json.437 : {List U8, List U8} = CallByName List.52 Json.288 Json.438;
let Json.293 : List U8 = StructAtIndex 1 Json.437;
inc Json.293;
dec Json.437;
let Json.436 : [C {}, C Str] = TagId(1) Json.291;
let Json.435 : {List U8, [C {}, C Str]} = Struct {Json.293, Json.436};
ret Json.435;
procedure Json.42 (Json.298):
let Json.564 : U64 = 1i64;
inc Json.298;
let Json.563 : {List U8, List U8} = CallByName List.52 Json.298 Json.564;
let Json.299 : List U8 = StructAtIndex 0 Json.563;
inc Json.299;
let Json.301 : List U8 = StructAtIndex 1 Json.563;
inc Json.301;
dec Json.563;
let Json.562 : U8 = 34i64;
let Json.561 : List U8 = Array [Json.562];
let Json.491 : Int1 = CallByName Bool.11 Json.299 Json.561;
dec Json.561;
dec Json.299;
if Json.491 then
dec Json.298;
let Json.504 : {} = Struct {};
let Json.503 : {List U8, List U8} = CallByName Json.24 Json.301 Json.504;
let Json.304 : List U8 = StructAtIndex 0 Json.503;
inc Json.304;
let Json.303 : List U8 = StructAtIndex 1 Json.503;
inc Json.303;
dec Json.503;
let Json.492 : [C {U64, U8}, C Str] = CallByName Str.9 Json.303;
let Json.500 : U8 = 1i64;
let Json.501 : U8 = GetTagId Json.492;
let Json.502 : Int1 = lowlevel Eq Json.500 Json.501;
if Json.502 then
let Json.307 : Str = UnionAtIndex (Id 1) (Index 0) Json.492;
inc Json.307;
dec Json.492;
let Json.496 : U64 = 1i64;
let Json.495 : {List U8, List U8} = CallByName List.52 Json.304 Json.496;
let Json.309 : List U8 = StructAtIndex 1 Json.495;
inc Json.309;
dec Json.495;
let Json.494 : [C {}, C Str] = TagId(1) Json.307;
let Json.493 : {List U8, [C {}, C Str]} = Struct {Json.309, Json.494};
ret Json.493;
else
dec Json.434;
let Json.441 : {} = Struct {};
let Json.440 : [C {}, C Str] = TagId(0) Json.441;
let Json.439 : {List U8, [C {}, C Str]} = Struct {Json.288, Json.440};
ret Json.439;
dec Json.492;
let Json.499 : {} = Struct {};
let Json.498 : [C {}, C Str] = TagId(0) Json.499;
let Json.497 : {List U8, [C {}, C Str]} = Struct {Json.304, Json.498};
ret Json.497;
else
dec Json.285;
let Json.432 : {} = Struct {};
let Json.431 : [C {}, C Str] = TagId(0) Json.432;
let Json.430 : {List U8, [C {}, C Str]} = Struct {Json.282, Json.431};
ret Json.430;
dec Json.301;
let Json.490 : {} = Struct {};
let Json.489 : [C {}, C Str] = TagId(0) Json.490;
let Json.488 : {List U8, [C {}, C Str]} = Struct {Json.298, Json.489};
ret Json.488;
procedure Json.42 ():
let Json.427 : {} = Struct {};
let Json.426 : {} = CallByName Decode.23 Json.427;
ret Json.426;
procedure Json.43 ():
let Json.485 : {} = Struct {};
let Json.484 : {} = CallByName Decode.24 Json.485;
ret Json.484;
procedure List.29 (List.298, List.299):
let List.543 : U64 = CallByName List.6 List.298;
@ -368,7 +368,7 @@ procedure Test.0 ():
let Test.37 : Str = "-1234";
let Test.35 : List U8 = CallByName Str.12 Test.37;
let Test.36 : {} = CallByName Json.2;
let Test.34 : {List U8, [C {}, C Str]} = CallByName Decode.25 Test.35 Test.36;
let Test.34 : {List U8, [C {}, C Str]} = CallByName Decode.26 Test.35 Test.36;
let Test.2 : List U8 = StructAtIndex 0 Test.34;
inc Test.2;
let Test.1 : [C {}, C Str] = StructAtIndex 1 Test.34;

View file

@ -2,121 +2,121 @@ procedure Bool.2 ():
let Bool.23 : Int1 = true;
ret Bool.23;
procedure Encode.22 (Encode.93):
ret Encode.93;
procedure Encode.23 (Encode.98):
ret Encode.98;
procedure Encode.22 (Encode.93):
ret Encode.93;
procedure Encode.23 (Encode.98):
ret Encode.98;
procedure Encode.22 (Encode.93):
ret Encode.93;
procedure Encode.23 (Encode.98):
ret Encode.98;
procedure Encode.23 (Encode.94, Encode.102, Encode.96):
let Encode.106 : List U8 = CallByName Test.5 Encode.94 Encode.96 Encode.102;
ret Encode.106;
procedure Encode.24 (Encode.99, Encode.107, Encode.101):
let Encode.111 : List U8 = CallByName Test.5 Encode.99 Encode.101 Encode.107;
ret Encode.111;
procedure Encode.23 (Encode.94, Encode.102, Encode.96):
let Encode.113 : List U8 = CallByName Json.128 Encode.94 Encode.96 Encode.102;
ret Encode.113;
procedure Encode.23 (Encode.94, Encode.102, Encode.96):
let Encode.118 : List U8 = CallByName Json.98 Encode.94 Encode.96 Encode.102;
procedure Encode.24 (Encode.99, Encode.107, Encode.101):
let Encode.118 : List U8 = CallByName Json.144 Encode.99 Encode.101 Encode.107;
ret Encode.118;
procedure Encode.25 (Encode.100, Encode.101):
let Encode.104 : List U8 = Array [];
let Encode.105 : {Str, Str} = CallByName Test.2 Encode.100;
let Encode.103 : List U8 = CallByName Encode.23 Encode.104 Encode.105 Encode.101;
ret Encode.103;
procedure Encode.24 (Encode.99, Encode.107, Encode.101):
let Encode.123 : List U8 = CallByName Json.102 Encode.99 Encode.101 Encode.107;
ret Encode.123;
procedure Encode.26 (Encode.105, Encode.106):
let Encode.109 : List U8 = Array [];
let Encode.110 : {Str, Str} = CallByName Test.2 Encode.105;
let Encode.108 : List U8 = CallByName Encode.24 Encode.109 Encode.110 Encode.106;
ret Encode.108;
procedure Json.1 ():
let Json.425 : {} = Struct {};
ret Json.425;
let Json.483 : {} = Struct {};
ret Json.483;
procedure Json.128 (Json.129, Json.428, #Attr.12):
let Json.127 : List Str = StructAtIndex 1 #Attr.12;
inc Json.127;
let Json.126 : Str = StructAtIndex 0 #Attr.12;
inc Json.126;
procedure Json.102 (Json.103, Json.530, Json.101):
let Json.539 : I64 = 34i64;
let Json.538 : U8 = CallByName Num.127 Json.539;
let Json.536 : List U8 = CallByName List.4 Json.103 Json.538;
let Json.537 : List U8 = CallByName Str.12 Json.101;
let Json.533 : List U8 = CallByName List.8 Json.536 Json.537;
let Json.535 : I64 = 34i64;
let Json.534 : U8 = CallByName Num.127 Json.535;
let Json.532 : List U8 = CallByName List.4 Json.533 Json.534;
ret Json.532;
procedure Json.144 (Json.145, Json.486, #Attr.12):
let Json.143 : List Str = StructAtIndex 1 #Attr.12;
inc Json.143;
let Json.142 : Str = StructAtIndex 0 #Attr.12;
inc Json.142;
dec #Attr.12;
let Json.466 : I64 = 123i64;
let Json.465 : U8 = CallByName Num.127 Json.466;
let Json.462 : List U8 = CallByName List.4 Json.129 Json.465;
let Json.464 : I64 = 34i64;
let Json.463 : U8 = CallByName Num.127 Json.464;
let Json.460 : List U8 = CallByName List.4 Json.462 Json.463;
let Json.461 : List U8 = CallByName Str.12 Json.126;
let Json.457 : List U8 = CallByName List.8 Json.460 Json.461;
let Json.459 : I64 = 34i64;
let Json.458 : U8 = CallByName Num.127 Json.459;
let Json.454 : List U8 = CallByName List.4 Json.457 Json.458;
let Json.456 : I64 = 58i64;
let Json.455 : U8 = CallByName Num.127 Json.456;
let Json.451 : List U8 = CallByName List.4 Json.454 Json.455;
let Json.453 : I64 = 91i64;
let Json.452 : U8 = CallByName Num.127 Json.453;
let Json.131 : List U8 = CallByName List.4 Json.451 Json.452;
let Json.450 : U64 = CallByName List.6 Json.127;
let Json.438 : {List U8, U64} = Struct {Json.131, Json.450};
let Json.439 : {} = Struct {};
let Json.437 : {List U8, U64} = CallByName List.18 Json.127 Json.438 Json.439;
dec Json.127;
let Json.133 : List U8 = StructAtIndex 0 Json.437;
inc Json.133;
dec Json.437;
let Json.436 : I64 = 93i64;
let Json.435 : U8 = CallByName Num.127 Json.436;
let Json.432 : List U8 = CallByName List.4 Json.133 Json.435;
let Json.434 : I64 = 125i64;
let Json.433 : U8 = CallByName Num.127 Json.434;
let Json.431 : List U8 = CallByName List.4 Json.432 Json.433;
ret Json.431;
let Json.524 : I64 = 123i64;
let Json.523 : U8 = CallByName Num.127 Json.524;
let Json.520 : List U8 = CallByName List.4 Json.145 Json.523;
let Json.522 : I64 = 34i64;
let Json.521 : U8 = CallByName Num.127 Json.522;
let Json.518 : List U8 = CallByName List.4 Json.520 Json.521;
let Json.519 : List U8 = CallByName Str.12 Json.142;
let Json.515 : List U8 = CallByName List.8 Json.518 Json.519;
let Json.517 : I64 = 34i64;
let Json.516 : U8 = CallByName Num.127 Json.517;
let Json.512 : List U8 = CallByName List.4 Json.515 Json.516;
let Json.514 : I64 = 58i64;
let Json.513 : U8 = CallByName Num.127 Json.514;
let Json.509 : List U8 = CallByName List.4 Json.512 Json.513;
let Json.511 : I64 = 91i64;
let Json.510 : U8 = CallByName Num.127 Json.511;
let Json.147 : List U8 = CallByName List.4 Json.509 Json.510;
let Json.508 : U64 = CallByName List.6 Json.143;
let Json.496 : {List U8, U64} = Struct {Json.147, Json.508};
let Json.497 : {} = Struct {};
let Json.495 : {List U8, U64} = CallByName List.18 Json.143 Json.496 Json.497;
dec Json.143;
let Json.149 : List U8 = StructAtIndex 0 Json.495;
inc Json.149;
dec Json.495;
let Json.494 : I64 = 93i64;
let Json.493 : U8 = CallByName Num.127 Json.494;
let Json.490 : List U8 = CallByName List.4 Json.149 Json.493;
let Json.492 : I64 = 125i64;
let Json.491 : U8 = CallByName Num.127 Json.492;
let Json.489 : List U8 = CallByName List.4 Json.490 Json.491;
ret Json.489;
procedure Json.130 (Json.430, Json.136):
let Json.134 : List U8 = StructAtIndex 0 Json.430;
inc Json.134;
let Json.135 : U64 = StructAtIndex 1 Json.430;
dec Json.430;
let Json.449 : {} = Struct {};
let Json.137 : List U8 = CallByName Encode.23 Json.134 Json.136 Json.449;
joinpoint Json.444 Json.138:
let Json.442 : U64 = 1i64;
let Json.441 : U64 = CallByName Num.20 Json.135 Json.442;
let Json.440 : {List U8, U64} = Struct {Json.138, Json.441};
ret Json.440;
procedure Json.146 (Json.488, Json.152):
let Json.150 : List U8 = StructAtIndex 0 Json.488;
inc Json.150;
let Json.151 : U64 = StructAtIndex 1 Json.488;
dec Json.488;
let Json.507 : {} = Struct {};
let Json.153 : List U8 = CallByName Encode.24 Json.150 Json.152 Json.507;
joinpoint Json.502 Json.154:
let Json.500 : U64 = 1i64;
let Json.499 : U64 = CallByName Num.20 Json.151 Json.500;
let Json.498 : {List U8, U64} = Struct {Json.154, Json.499};
ret Json.498;
in
let Json.448 : U64 = 1i64;
let Json.445 : Int1 = CallByName Num.24 Json.135 Json.448;
if Json.445 then
let Json.447 : I64 = 44i64;
let Json.446 : U8 = CallByName Num.127 Json.447;
let Json.443 : List U8 = CallByName List.4 Json.137 Json.446;
jump Json.444 Json.443;
let Json.506 : U64 = 1i64;
let Json.503 : Int1 = CallByName Num.24 Json.151 Json.506;
if Json.503 then
let Json.505 : I64 = 44i64;
let Json.504 : U8 = CallByName Num.127 Json.505;
let Json.501 : List U8 = CallByName List.4 Json.153 Json.504;
jump Json.502 Json.501;
else
jump Json.444 Json.137;
jump Json.502 Json.153;
procedure Json.18 (Json.97):
let Json.482 : Str = CallByName Encode.22 Json.97;
ret Json.482;
procedure Json.18 (Json.101):
let Json.540 : Str = CallByName Encode.23 Json.101;
ret Json.540;
procedure Json.21 (Json.126, Json.127):
let Json.468 : {Str, List Str} = Struct {Json.126, Json.127};
let Json.467 : {Str, List Str} = CallByName Encode.22 Json.468;
ret Json.467;
procedure Json.98 (Json.99, Json.472, Json.97):
let Json.481 : I64 = 34i64;
let Json.480 : U8 = CallByName Num.127 Json.481;
let Json.478 : List U8 = CallByName List.4 Json.99 Json.480;
let Json.479 : List U8 = CallByName Str.12 Json.97;
let Json.475 : List U8 = CallByName List.8 Json.478 Json.479;
let Json.477 : I64 = 34i64;
let Json.476 : U8 = CallByName Num.127 Json.477;
let Json.474 : List U8 = CallByName List.4 Json.475 Json.476;
ret Json.474;
procedure Json.22 (Json.142, Json.143):
let Json.526 : {Str, List Str} = Struct {Json.142, Json.143};
let Json.525 : {Str, List Str} = CallByName Encode.23 Json.526;
ret Json.525;
procedure List.139 (List.140, List.141, List.138):
let List.545 : {List U8, U64} = CallByName Json.130 List.140 List.141;
let List.545 : {List U8, U64} = CallByName Json.146 List.140 List.141;
ret List.545;
procedure List.18 (List.136, List.137, List.138):
@ -194,7 +194,7 @@ procedure Str.12 (#Attr.2):
ret Str.267;
procedure Test.2 (Test.10):
let Test.15 : {Str, Str} = CallByName Encode.22 Test.10;
let Test.15 : {Str, Str} = CallByName Encode.23 Test.10;
ret Test.15;
procedure Test.3 ():
@ -205,7 +205,7 @@ procedure Test.3 ():
procedure Test.5 (Test.6, Test.7, Test.4):
joinpoint Test.20 Test.8:
let Test.18 : List U8 = CallByName Encode.23 Test.6 Test.8 Test.7;
let Test.18 : List U8 = CallByName Encode.24 Test.6 Test.8 Test.7;
ret Test.18;
in
let Test.25 : Int1 = CallByName Bool.2;
@ -216,7 +216,7 @@ procedure Test.5 (Test.6, Test.7, Test.4):
dec Test.4;
let Test.28 : Str = CallByName Json.18 Test.29;
let Test.27 : List Str = Array [Test.28];
let Test.19 : {Str, List Str} = CallByName Json.21 Test.26 Test.27;
let Test.19 : {Str, List Str} = CallByName Json.22 Test.26 Test.27;
jump Test.20 Test.19;
else
let Test.21 : Str = "B";
@ -225,11 +225,11 @@ procedure Test.5 (Test.6, Test.7, Test.4):
dec Test.4;
let Test.23 : Str = CallByName Json.18 Test.24;
let Test.22 : List Str = Array [Test.23];
let Test.19 : {Str, List Str} = CallByName Json.21 Test.21 Test.22;
let Test.19 : {Str, List Str} = CallByName Json.22 Test.21 Test.22;
jump Test.20 Test.19;
procedure Test.0 ():
let Test.12 : {Str, Str} = CallByName Test.3;
let Test.13 : {} = CallByName Json.1;
let Test.11 : List U8 = CallByName Encode.25 Test.12 Test.13;
let Test.11 : List U8 = CallByName Encode.26 Test.12 Test.13;
ret Test.11;

View file

@ -1,230 +1,230 @@
procedure #Derived.0 (#Derived.1):
let #Derived_gen.10 : [C {}, C {}] = TagId(0) #Derived.1;
let #Derived_gen.9 : [C {}, C {}] = CallByName Encode.22 #Derived_gen.10;
let #Derived_gen.9 : [C {}, C {}] = CallByName Encode.23 #Derived_gen.10;
ret #Derived_gen.9;
procedure #Derived.2 (#Derived.3, #Derived.4, #Attr.12):
let #Derived.1 : {} = UnionAtIndex (Id 0) (Index 0) #Attr.12;
joinpoint #Derived_gen.14 #Derived_gen.13:
let #Derived_gen.12 : List U8 = CallByName Encode.23 #Derived.3 #Derived_gen.13 #Derived.4;
let #Derived_gen.12 : List U8 = CallByName Encode.24 #Derived.3 #Derived_gen.13 #Derived.4;
ret #Derived_gen.12;
in
let #Derived_gen.16 : Str = "A";
let #Derived_gen.17 : List [] = Array [];
let #Derived_gen.15 : {Str, List []} = CallByName Json.21 #Derived_gen.16 #Derived_gen.17;
let #Derived_gen.15 : {Str, List []} = CallByName Json.22 #Derived_gen.16 #Derived_gen.17;
jump #Derived_gen.14 #Derived_gen.15;
procedure #Derived.5 (#Derived.6):
let #Derived_gen.1 : [C {}, C {}] = TagId(1) #Derived.6;
let #Derived_gen.0 : [C {}, C {}] = CallByName Encode.22 #Derived_gen.1;
let #Derived_gen.0 : [C {}, C {}] = CallByName Encode.23 #Derived_gen.1;
ret #Derived_gen.0;
procedure #Derived.7 (#Derived.8, #Derived.9, #Attr.12):
let #Derived.6 : {} = UnionAtIndex (Id 1) (Index 0) #Attr.12;
joinpoint #Derived_gen.5 #Derived_gen.4:
let #Derived_gen.3 : List U8 = CallByName Encode.23 #Derived.8 #Derived_gen.4 #Derived.9;
let #Derived_gen.3 : List U8 = CallByName Encode.24 #Derived.8 #Derived_gen.4 #Derived.9;
ret #Derived_gen.3;
in
let #Derived_gen.7 : Str = "B";
let #Derived_gen.8 : List [] = Array [];
let #Derived_gen.6 : {Str, List []} = CallByName Json.21 #Derived_gen.7 #Derived_gen.8;
let #Derived_gen.6 : {Str, List []} = CallByName Json.22 #Derived_gen.7 #Derived_gen.8;
jump #Derived_gen.5 #Derived_gen.6;
procedure Bool.2 ():
let Bool.23 : Int1 = true;
ret Bool.23;
procedure Encode.22 (Encode.93):
ret Encode.93;
procedure Encode.23 (Encode.98):
ret Encode.98;
procedure Encode.22 (Encode.93):
ret Encode.93;
procedure Encode.23 (Encode.98):
ret Encode.98;
procedure Encode.22 (Encode.93):
ret Encode.93;
procedure Encode.23 (Encode.98):
ret Encode.98;
procedure Encode.22 (Encode.93):
ret Encode.93;
procedure Encode.23 (Encode.98):
ret Encode.98;
procedure Encode.23 (Encode.94, Encode.102, Encode.96):
let Encode.106 : List U8 = CallByName Test.5 Encode.94 Encode.96 Encode.102;
ret Encode.106;
procedure Encode.24 (Encode.99, Encode.107, Encode.101):
let Encode.111 : List U8 = CallByName Test.5 Encode.99 Encode.101 Encode.107;
ret Encode.111;
procedure Encode.23 (Encode.94, Encode.102, Encode.96):
let Encode.113 : List U8 = CallByName Json.128 Encode.94 Encode.96 Encode.102;
ret Encode.113;
procedure Encode.24 (Encode.99, Encode.107, Encode.101):
let Encode.118 : List U8 = CallByName Json.144 Encode.99 Encode.101 Encode.107;
ret Encode.118;
procedure Encode.23 (Encode.94, Encode.102, Encode.96):
let Encode.117 : U8 = GetTagId Encode.102;
switch Encode.117:
procedure Encode.24 (Encode.99, Encode.107, Encode.101):
let Encode.122 : U8 = GetTagId Encode.107;
switch Encode.122:
case 0:
let Encode.116 : List U8 = CallByName #Derived.2 Encode.94 Encode.96 Encode.102;
ret Encode.116;
let Encode.121 : List U8 = CallByName #Derived.2 Encode.99 Encode.101 Encode.107;
ret Encode.121;
default:
let Encode.116 : List U8 = CallByName #Derived.7 Encode.94 Encode.96 Encode.102;
ret Encode.116;
let Encode.121 : List U8 = CallByName #Derived.7 Encode.99 Encode.101 Encode.107;
ret Encode.121;
procedure Encode.23 (Encode.94, Encode.102, Encode.96):
let Encode.129 : List U8 = CallByName Json.128 Encode.94 Encode.96 Encode.102;
ret Encode.129;
procedure Encode.24 (Encode.99, Encode.107, Encode.101):
let Encode.134 : List U8 = CallByName Json.144 Encode.99 Encode.101 Encode.107;
ret Encode.134;
procedure Encode.23 (Encode.94, Encode.102, Encode.96):
let Encode.133 : Str = "a Lambda Set is empty. Most likely there is a type error in your program.";
Crash Encode.133
procedure Encode.24 (Encode.99, Encode.107, Encode.101):
let Encode.138 : Str = "a Lambda Set is empty. Most likely there is a type error in your program.";
Crash Encode.138
procedure Encode.25 (Encode.100, Encode.101):
let Encode.104 : List U8 = Array [];
let Encode.105 : {{}, {}} = CallByName Test.2 Encode.100;
let Encode.103 : List U8 = CallByName Encode.23 Encode.104 Encode.105 Encode.101;
ret Encode.103;
procedure Encode.26 (Encode.105, Encode.106):
let Encode.109 : List U8 = Array [];
let Encode.110 : {{}, {}} = CallByName Test.2 Encode.105;
let Encode.108 : List U8 = CallByName Encode.24 Encode.109 Encode.110 Encode.106;
ret Encode.108;
procedure Json.1 ():
let Json.425 : {} = Struct {};
ret Json.425;
let Json.483 : {} = Struct {};
ret Json.483;
procedure Json.128 (Json.129, Json.428, #Attr.12):
let Json.127 : List [C {}, C {}] = StructAtIndex 1 #Attr.12;
inc Json.127;
let Json.126 : Str = StructAtIndex 0 #Attr.12;
inc Json.126;
procedure Json.144 (Json.145, Json.486, #Attr.12):
let Json.143 : List [C {}, C {}] = StructAtIndex 1 #Attr.12;
inc Json.143;
let Json.142 : Str = StructAtIndex 0 #Attr.12;
inc Json.142;
dec #Attr.12;
let Json.466 : I64 = 123i64;
let Json.465 : U8 = CallByName Num.127 Json.466;
let Json.462 : List U8 = CallByName List.4 Json.129 Json.465;
let Json.464 : I64 = 34i64;
let Json.463 : U8 = CallByName Num.127 Json.464;
let Json.460 : List U8 = CallByName List.4 Json.462 Json.463;
let Json.461 : List U8 = CallByName Str.12 Json.126;
let Json.457 : List U8 = CallByName List.8 Json.460 Json.461;
let Json.459 : I64 = 34i64;
let Json.458 : U8 = CallByName Num.127 Json.459;
let Json.454 : List U8 = CallByName List.4 Json.457 Json.458;
let Json.456 : I64 = 58i64;
let Json.455 : U8 = CallByName Num.127 Json.456;
let Json.451 : List U8 = CallByName List.4 Json.454 Json.455;
let Json.453 : I64 = 91i64;
let Json.452 : U8 = CallByName Num.127 Json.453;
let Json.131 : List U8 = CallByName List.4 Json.451 Json.452;
let Json.450 : U64 = CallByName List.6 Json.127;
let Json.438 : {List U8, U64} = Struct {Json.131, Json.450};
let Json.439 : {} = Struct {};
let Json.437 : {List U8, U64} = CallByName List.18 Json.127 Json.438 Json.439;
dec Json.127;
let Json.133 : List U8 = StructAtIndex 0 Json.437;
inc Json.133;
dec Json.437;
let Json.436 : I64 = 93i64;
let Json.435 : U8 = CallByName Num.127 Json.436;
let Json.432 : List U8 = CallByName List.4 Json.133 Json.435;
let Json.434 : I64 = 125i64;
let Json.433 : U8 = CallByName Num.127 Json.434;
let Json.431 : List U8 = CallByName List.4 Json.432 Json.433;
ret Json.431;
procedure Json.128 (Json.129, Json.428, #Attr.12):
let Json.127 : List [] = StructAtIndex 1 #Attr.12;
inc Json.127;
let Json.126 : Str = StructAtIndex 0 #Attr.12;
inc Json.126;
dec #Attr.12;
let Json.516 : I64 = 123i64;
let Json.515 : U8 = CallByName Num.127 Json.516;
let Json.512 : List U8 = CallByName List.4 Json.129 Json.515;
let Json.514 : I64 = 34i64;
let Json.524 : I64 = 123i64;
let Json.523 : U8 = CallByName Num.127 Json.524;
let Json.520 : List U8 = CallByName List.4 Json.145 Json.523;
let Json.522 : I64 = 34i64;
let Json.521 : U8 = CallByName Num.127 Json.522;
let Json.518 : List U8 = CallByName List.4 Json.520 Json.521;
let Json.519 : List U8 = CallByName Str.12 Json.142;
let Json.515 : List U8 = CallByName List.8 Json.518 Json.519;
let Json.517 : I64 = 34i64;
let Json.516 : U8 = CallByName Num.127 Json.517;
let Json.512 : List U8 = CallByName List.4 Json.515 Json.516;
let Json.514 : I64 = 58i64;
let Json.513 : U8 = CallByName Num.127 Json.514;
let Json.510 : List U8 = CallByName List.4 Json.512 Json.513;
let Json.511 : List U8 = CallByName Str.12 Json.126;
let Json.507 : List U8 = CallByName List.8 Json.510 Json.511;
let Json.509 : I64 = 34i64;
let Json.508 : U8 = CallByName Num.127 Json.509;
let Json.504 : List U8 = CallByName List.4 Json.507 Json.508;
let Json.506 : I64 = 58i64;
let Json.505 : U8 = CallByName Num.127 Json.506;
let Json.501 : List U8 = CallByName List.4 Json.504 Json.505;
let Json.503 : I64 = 91i64;
let Json.502 : U8 = CallByName Num.127 Json.503;
let Json.131 : List U8 = CallByName List.4 Json.501 Json.502;
let Json.500 : U64 = CallByName List.6 Json.127;
let Json.488 : {List U8, U64} = Struct {Json.131, Json.500};
let Json.489 : {} = Struct {};
let Json.487 : {List U8, U64} = CallByName List.18 Json.127 Json.488 Json.489;
dec Json.127;
let Json.133 : List U8 = StructAtIndex 0 Json.487;
inc Json.133;
dec Json.487;
let Json.486 : I64 = 93i64;
let Json.485 : U8 = CallByName Num.127 Json.486;
let Json.482 : List U8 = CallByName List.4 Json.133 Json.485;
let Json.484 : I64 = 125i64;
let Json.483 : U8 = CallByName Num.127 Json.484;
let Json.481 : List U8 = CallByName List.4 Json.482 Json.483;
ret Json.481;
let Json.509 : List U8 = CallByName List.4 Json.512 Json.513;
let Json.511 : I64 = 91i64;
let Json.510 : U8 = CallByName Num.127 Json.511;
let Json.147 : List U8 = CallByName List.4 Json.509 Json.510;
let Json.508 : U64 = CallByName List.6 Json.143;
let Json.496 : {List U8, U64} = Struct {Json.147, Json.508};
let Json.497 : {} = Struct {};
let Json.495 : {List U8, U64} = CallByName List.18 Json.143 Json.496 Json.497;
dec Json.143;
let Json.149 : List U8 = StructAtIndex 0 Json.495;
inc Json.149;
dec Json.495;
let Json.494 : I64 = 93i64;
let Json.493 : U8 = CallByName Num.127 Json.494;
let Json.490 : List U8 = CallByName List.4 Json.149 Json.493;
let Json.492 : I64 = 125i64;
let Json.491 : U8 = CallByName Num.127 Json.492;
let Json.489 : List U8 = CallByName List.4 Json.490 Json.491;
ret Json.489;
procedure Json.130 (Json.430, Json.136):
let Json.134 : List U8 = StructAtIndex 0 Json.430;
inc Json.134;
let Json.135 : U64 = StructAtIndex 1 Json.430;
dec Json.430;
let Json.449 : {} = Struct {};
let Json.137 : List U8 = CallByName Encode.23 Json.134 Json.136 Json.449;
joinpoint Json.444 Json.138:
let Json.442 : U64 = 1i64;
let Json.441 : U64 = CallByName Num.20 Json.135 Json.442;
let Json.440 : {List U8, U64} = Struct {Json.138, Json.441};
ret Json.440;
procedure Json.144 (Json.145, Json.486, #Attr.12):
let Json.143 : List [] = StructAtIndex 1 #Attr.12;
inc Json.143;
let Json.142 : Str = StructAtIndex 0 #Attr.12;
inc Json.142;
dec #Attr.12;
let Json.574 : I64 = 123i64;
let Json.573 : U8 = CallByName Num.127 Json.574;
let Json.570 : List U8 = CallByName List.4 Json.145 Json.573;
let Json.572 : I64 = 34i64;
let Json.571 : U8 = CallByName Num.127 Json.572;
let Json.568 : List U8 = CallByName List.4 Json.570 Json.571;
let Json.569 : List U8 = CallByName Str.12 Json.142;
let Json.565 : List U8 = CallByName List.8 Json.568 Json.569;
let Json.567 : I64 = 34i64;
let Json.566 : U8 = CallByName Num.127 Json.567;
let Json.562 : List U8 = CallByName List.4 Json.565 Json.566;
let Json.564 : I64 = 58i64;
let Json.563 : U8 = CallByName Num.127 Json.564;
let Json.559 : List U8 = CallByName List.4 Json.562 Json.563;
let Json.561 : I64 = 91i64;
let Json.560 : U8 = CallByName Num.127 Json.561;
let Json.147 : List U8 = CallByName List.4 Json.559 Json.560;
let Json.558 : U64 = CallByName List.6 Json.143;
let Json.546 : {List U8, U64} = Struct {Json.147, Json.558};
let Json.547 : {} = Struct {};
let Json.545 : {List U8, U64} = CallByName List.18 Json.143 Json.546 Json.547;
dec Json.143;
let Json.149 : List U8 = StructAtIndex 0 Json.545;
inc Json.149;
dec Json.545;
let Json.544 : I64 = 93i64;
let Json.543 : U8 = CallByName Num.127 Json.544;
let Json.540 : List U8 = CallByName List.4 Json.149 Json.543;
let Json.542 : I64 = 125i64;
let Json.541 : U8 = CallByName Num.127 Json.542;
let Json.539 : List U8 = CallByName List.4 Json.540 Json.541;
ret Json.539;
procedure Json.146 (Json.488, Json.152):
let Json.150 : List U8 = StructAtIndex 0 Json.488;
inc Json.150;
let Json.151 : U64 = StructAtIndex 1 Json.488;
dec Json.488;
let Json.507 : {} = Struct {};
let Json.153 : List U8 = CallByName Encode.24 Json.150 Json.152 Json.507;
joinpoint Json.502 Json.154:
let Json.500 : U64 = 1i64;
let Json.499 : U64 = CallByName Num.20 Json.151 Json.500;
let Json.498 : {List U8, U64} = Struct {Json.154, Json.499};
ret Json.498;
in
let Json.448 : U64 = 1i64;
let Json.445 : Int1 = CallByName Num.24 Json.135 Json.448;
if Json.445 then
let Json.447 : I64 = 44i64;
let Json.446 : U8 = CallByName Num.127 Json.447;
let Json.443 : List U8 = CallByName List.4 Json.137 Json.446;
jump Json.444 Json.443;
let Json.506 : U64 = 1i64;
let Json.503 : Int1 = CallByName Num.24 Json.151 Json.506;
if Json.503 then
let Json.505 : I64 = 44i64;
let Json.504 : U8 = CallByName Num.127 Json.505;
let Json.501 : List U8 = CallByName List.4 Json.153 Json.504;
jump Json.502 Json.501;
else
jump Json.444 Json.137;
jump Json.502 Json.153;
procedure Json.130 (Json.430, Json.136):
let Json.134 : List U8 = StructAtIndex 0 Json.430;
inc Json.134;
let Json.135 : U64 = StructAtIndex 1 Json.430;
dec Json.430;
let Json.499 : {} = Struct {};
let Json.137 : List U8 = CallByName Encode.23 Json.134 Json.136 Json.499;
dec Json.134;
joinpoint Json.494 Json.138:
let Json.492 : U64 = 1i64;
let Json.491 : U64 = CallByName Num.20 Json.135 Json.492;
let Json.490 : {List U8, U64} = Struct {Json.138, Json.491};
ret Json.490;
procedure Json.146 (Json.488, Json.152):
let Json.150 : List U8 = StructAtIndex 0 Json.488;
inc Json.150;
let Json.151 : U64 = StructAtIndex 1 Json.488;
dec Json.488;
let Json.557 : {} = Struct {};
let Json.153 : List U8 = CallByName Encode.24 Json.150 Json.152 Json.557;
dec Json.150;
joinpoint Json.552 Json.154:
let Json.550 : U64 = 1i64;
let Json.549 : U64 = CallByName Num.20 Json.151 Json.550;
let Json.548 : {List U8, U64} = Struct {Json.154, Json.549};
ret Json.548;
in
let Json.498 : U64 = 1i64;
let Json.495 : Int1 = CallByName Num.24 Json.135 Json.498;
if Json.495 then
let Json.497 : I64 = 44i64;
let Json.496 : U8 = CallByName Num.127 Json.497;
let Json.493 : List U8 = CallByName List.4 Json.137 Json.496;
jump Json.494 Json.493;
let Json.556 : U64 = 1i64;
let Json.553 : Int1 = CallByName Num.24 Json.151 Json.556;
if Json.553 then
let Json.555 : I64 = 44i64;
let Json.554 : U8 = CallByName Num.127 Json.555;
let Json.551 : List U8 = CallByName List.4 Json.153 Json.554;
jump Json.552 Json.551;
else
jump Json.494 Json.137;
jump Json.552 Json.153;
procedure Json.21 (Json.126, Json.127):
let Json.468 : {Str, List [C {}, C {}]} = Struct {Json.126, Json.127};
let Json.467 : {Str, List [C {}, C {}]} = CallByName Encode.22 Json.468;
ret Json.467;
procedure Json.22 (Json.142, Json.143):
let Json.526 : {Str, List [C {}, C {}]} = Struct {Json.142, Json.143};
let Json.525 : {Str, List [C {}, C {}]} = CallByName Encode.23 Json.526;
ret Json.525;
procedure Json.21 (Json.126, Json.127):
let Json.518 : {Str, List []} = Struct {Json.126, Json.127};
let Json.517 : {Str, List []} = CallByName Encode.22 Json.518;
ret Json.517;
procedure Json.22 (Json.142, Json.143):
let Json.576 : {Str, List []} = Struct {Json.142, Json.143};
let Json.575 : {Str, List []} = CallByName Encode.23 Json.576;
ret Json.575;
procedure List.139 (List.140, List.141, List.138):
let List.539 : {List U8, U64} = CallByName Json.130 List.140 List.141;
let List.539 : {List U8, U64} = CallByName Json.146 List.140 List.141;
ret List.539;
procedure List.139 (List.140, List.141, List.138):
let List.612 : {List U8, U64} = CallByName Json.130 List.140 List.141;
let List.612 : {List U8, U64} = CallByName Json.146 List.140 List.141;
ret List.612;
procedure List.18 (List.136, List.137, List.138):
@ -334,7 +334,7 @@ procedure Str.12 (#Attr.2):
ret Str.268;
procedure Test.2 (Test.11):
let Test.18 : {{}, {}} = CallByName Encode.22 Test.11;
let Test.18 : {{}, {}} = CallByName Encode.23 Test.11;
ret Test.18;
procedure Test.3 ():
@ -345,7 +345,7 @@ procedure Test.3 ():
procedure Test.5 (Test.6, Test.7, Test.4):
joinpoint Test.23 Test.8:
let Test.21 : List U8 = CallByName Encode.23 Test.6 Test.8 Test.7;
let Test.21 : List U8 = CallByName Encode.24 Test.6 Test.8 Test.7;
ret Test.21;
in
let Test.28 : Int1 = CallByName Bool.2;
@ -354,18 +354,18 @@ procedure Test.5 (Test.6, Test.7, Test.4):
let Test.32 : {} = StructAtIndex 0 Test.4;
let Test.31 : [C {}, C {}] = CallByName #Derived.0 Test.32;
let Test.30 : List [C {}, C {}] = Array [Test.31];
let Test.22 : {Str, List [C {}, C {}]} = CallByName Json.21 Test.29 Test.30;
let Test.22 : {Str, List [C {}, C {}]} = CallByName Json.22 Test.29 Test.30;
jump Test.23 Test.22;
else
let Test.24 : Str = "B";
let Test.27 : {} = StructAtIndex 1 Test.4;
let Test.26 : [C {}, C {}] = CallByName #Derived.5 Test.27;
let Test.25 : List [C {}, C {}] = Array [Test.26];
let Test.22 : {Str, List [C {}, C {}]} = CallByName Json.21 Test.24 Test.25;
let Test.22 : {Str, List [C {}, C {}]} = CallByName Json.22 Test.24 Test.25;
jump Test.23 Test.22;
procedure Test.0 ():
let Test.13 : {{}, {}} = CallByName Test.3;
let Test.14 : {} = CallByName Json.1;
let Test.12 : List U8 = CallByName Encode.25 Test.13 Test.14;
let Test.12 : List U8 = CallByName Encode.26 Test.13 Test.14;
ret Test.12;

View file

@ -4459,6 +4459,7 @@ pub struct StorageSubs {
struct StorageSubsOffsets {
utable: u32,
variables: u32,
tuple_elem_indices: u32,
tag_names: u32,
symbol_names: u32,
field_names: u32,
@ -4542,6 +4543,7 @@ impl StorageSubs {
let self_offsets = StorageSubsOffsets {
utable: self.subs.utable.len() as u32,
variables: self.subs.variables.len() as u32,
tuple_elem_indices: self.subs.tuple_elem_indices.len() as u32,
tag_names: self.subs.tag_names.len() as u32,
symbol_names: self.subs.symbol_names.len() as u32,
field_names: self.subs.field_names.len() as u32,
@ -4553,6 +4555,7 @@ impl StorageSubs {
let offsets = StorageSubsOffsets {
utable: (target.utable.len() - Variable::NUM_RESERVED_VARS) as u32,
variables: target.variables.len() as u32,
tuple_elem_indices: target.tuple_elem_indices.len() as u32,
tag_names: target.tag_names.len() as u32,
symbol_names: target.symbol_names.len() as u32,
field_names: target.field_names.len() as u32,
@ -4593,6 +4596,10 @@ impl StorageSubs {
.map(|v| Self::offset_variable(&offsets, *v)),
);
target
.tuple_elem_indices
.extend(self.subs.tuple_elem_indices);
target.variable_slices.extend(
self.subs
.variable_slices
@ -4613,6 +4620,11 @@ impl StorageSubs {
(self_offsets.utable + offsets.utable) as usize
);
debug_assert_eq!(
target.tuple_elem_indices.len(),
(self_offsets.tuple_elem_indices + offsets.tuple_elem_indices) as usize
);
debug_assert_eq!(
target.tag_names.len(),
(self_offsets.tag_names + offsets.tag_names) as usize
@ -4756,6 +4768,7 @@ impl StorageSubs {
}
fn offset_tuple_elems(offsets: &StorageSubsOffsets, mut tuple_elems: TupleElems) -> TupleElems {
tuple_elems.elem_index_start += offsets.tuple_elem_indices;
tuple_elems.variables_start += offsets.variables;
tuple_elems