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, string,
list, list,
record, record,
tuple,
custom, custom,
decodeWith, decodeWith,
fromBytesPartial, fromBytesPartial,
@ -43,6 +44,7 @@ interface Decode
I32, I32,
I64, I64,
I128, I128,
Nat,
F32, F32,
F64, F64,
Dec, Dec,
@ -76,8 +78,24 @@ DecoderFormatting has
bool : Decoder Bool fmt | fmt has DecoderFormatting bool : Decoder Bool fmt | fmt has DecoderFormatting
string : Decoder Str fmt | fmt has DecoderFormatting string : Decoder Str fmt | fmt has DecoderFormatting
list : Decoder elem fmt -> Decoder (List elem) 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 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 : (List U8, fmt -> DecodeResult val) -> Decoder val fmt | fmt has DecoderFormatting
custom = \decode -> @Decoder decode custom = \decode -> @Decoder decode

View file

@ -22,6 +22,7 @@ interface Encode
list, list,
record, record,
tag, tag,
tuple,
custom, custom,
appendWith, appendWith,
append, append,
@ -69,6 +70,7 @@ EncoderFormatting has
string : Str -> Encoder fmt | fmt has EncoderFormatting string : Str -> Encoder fmt | fmt has EncoderFormatting
list : List elem, (elem -> Encoder fmt) -> 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 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 tag : Str, List (Encoder fmt) -> Encoder fmt | fmt has EncoderFormatting
custom : (List U8, fmt -> List U8) -> 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, string: encodeString,
list: encodeList, list: encodeList,
record: encodeRecord, record: encodeRecord,
tuple: encodeTuple,
tag: encodeTag, tag: encodeTag,
}, },
DecoderFormatting { DecoderFormatting {
@ -116,6 +117,7 @@ Json := {} has [
string: decodeString, string: decodeString,
list: decodeList, list: decodeList,
record: decodeRecord, record: decodeRecord,
tuple: decodeTuple,
}, },
] ]
@ -207,6 +209,25 @@ encodeRecord = \fields ->
List.append bytesWithRecord (Num.toU8 '}') 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 -> encodeTag = \name, payload ->
Encode.custom \bytes, @Json {} -> Encode.custom \bytes, @Json {} ->
# Idea: encode `A v1 v2` as `{"A": [v1, v2]}` # Idea: encode `A v1 v2` as `{"A": [v1, v2]}`
@ -477,6 +498,12 @@ openBrace = \bytes -> parseExactChar bytes '{'
closingBrace : List U8 -> DecodeResult {} closingBrace : List U8 -> DecodeResult {}
closingBrace = \bytes -> parseExactChar bytes '}' 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 : List U8 -> DecodeResult Str
recordKey = \bytes -> jsonString bytes recordKey = \bytes -> jsonString bytes
@ -527,6 +554,36 @@ decodeRecord = \initialState, stepField, finalizer -> Decode.custom \bytes, @Jso
Ok val -> { result: Ok val, rest: afterRecordBytes } Ok val -> { result: Ok val, rest: afterRecordBytes }
Err e -> { result: Err e, 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 # Helper to eat leading Json whitespace characters
eatWhitespace = \input -> eatWhitespace = \input ->
when input is 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) } => expr(c, AppArg, f, &loc_expr.value)
.append(f.text(format!(".{}", field.as_str()))) .append(f.text(format!(".{}", field.as_str())))
.group(), .group(),
TupleAccess { .. } => todo!(), TupleAccess {
loc_expr, index, ..
} => expr(c, AppArg, f, &loc_expr.value)
.append(f.text(format!(".{index}")))
.group(),
OpaqueWrapFunction(OpaqueWrapFunctionData { opaque_name, .. }) => { OpaqueWrapFunction(OpaqueWrapFunctionData { opaque_name, .. }) => {
f.text(format!("@{}", opaque_name.as_str(c.interns))) 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_region::all::{Loc, Region};
use roc_types::subs::{ use roc_types::subs::{
Content, ExhaustiveMark, FlatType, GetSubsSlice, LambdaSet, OptVariable, RecordFields, 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; use roc_types::types::RecordField;
@ -50,6 +51,21 @@ pub(crate) fn derive_to_encoder(
to_encoder_record(env, record_var, fields, def_symbol) 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) => { FlatEncodableKey::TagUnion(tags) => {
// Generalized tag union var so we can reuse this impl between many unions: // 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 // 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) (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( fn to_encoder_tag_union(
env: &mut Env<'_>, env: &mut Env<'_>,
tag_union_var: Variable, tag_union_var: Variable,

View file

@ -19,8 +19,8 @@ use roc_types::{
num::int_lit_width_to_variable, num::int_lit_width_to_variable,
subs::{ subs::{
Content, ExhaustiveMark, FlatType, GetSubsSlice, LambdaSet, OptVariable, RecordFields, Content, ExhaustiveMark, FlatType, GetSubsSlice, LambdaSet, OptVariable, RecordFields,
RedundantMark, Subs, SubsIndex, SubsSlice, TagExt, UnionLambdas, UnionTags, Variable, RedundantMark, Subs, SubsIndex, SubsSlice, TagExt, TupleElems, UnionLambdas, UnionTags,
VariableSubsSlice, Variable, VariableSubsSlice,
}, },
types::RecordField, 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 { pub(crate) fn derive_hash(env: &mut Env<'_>, key: FlatHashKey, def_symbol: Symbol) -> DerivedBody {
let (body_type, body) = match key { let (body_type, body) = match key {
FlatHashKey::Record(fields) => hash_record(env, def_symbol, fields), FlatHashKey::Record(fields) => hash_record(env, def_symbol, fields),
FlatHashKey::Tuple(arity) => hash_tuple(env, def_symbol, arity),
FlatHashKey::TagUnion(tags) => { FlatHashKey::TagUnion(tags) => {
if tags.len() == 1 { if tags.len() == 1 {
hash_newtype_tag_union(env, def_symbol, tags.into_iter().next().unwrap()) 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. /// Build a `hash` implementation for a non-singleton tag union.
fn hash_tag_union( fn hash_tag_union(
env: &mut Env<'_>, env: &mut Env<'_>,

View file

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

View file

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

View file

@ -5,7 +5,7 @@ use roc_module::{
use roc_types::subs::{Content, FlatType, GetSubsSlice, Subs, Variable}; use roc_types::subs::{Content, FlatType, GetSubsSlice, Subs, Variable};
use crate::{ 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, DeriveError,
}; };
@ -22,6 +22,7 @@ pub enum FlatEncodableKey {
Dict(/* takes two variables */), Dict(/* takes two variables */),
// Unfortunate that we must allocate here, c'est la vie // Unfortunate that we must allocate here, c'est la vie
Record(Vec<Lowercase>), Record(Vec<Lowercase>),
Tuple(u32),
TagUnion(Vec<(TagName, u16)>), TagUnion(Vec<(TagName, u16)>),
} }
@ -32,6 +33,7 @@ impl FlatEncodableKey {
FlatEncodableKey::Set() => "set".to_string(), FlatEncodableKey::Set() => "set".to_string(),
FlatEncodableKey::Dict() => "dict".to_string(), FlatEncodableKey::Dict() => "dict".to_string(),
FlatEncodableKey::Record(fields) => debug_name_record(fields), FlatEncodableKey::Record(fields) => debug_name_record(fields),
FlatEncodableKey::Tuple(arity) => debug_name_tuple(*arity),
FlatEncodableKey::TagUnion(tags) => debug_name_tag(tags), FlatEncodableKey::TagUnion(tags) => debug_name_tag(tags),
} }
} }
@ -66,8 +68,14 @@ impl FlatEncodable {
Ok(Key(FlatEncodableKey::Record(field_names))) Ok(Key(FlatEncodableKey::Record(field_names)))
} }
FlatType::Tuple(_elems, _ext) => { FlatType::Tuple(elems, ext) => {
todo!() 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) => { FlatType::TagUnion(tags, ext) | FlatType::RecursiveTagUnion(_, tags, ext) => {
// The recursion var doesn't matter, because the derived implementation will only // 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 roc_types::subs::{Content, FlatType, GetSubsSlice, Subs, Variable};
use crate::{ 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, DeriveError,
}; };
@ -21,6 +21,7 @@ pub enum FlatHash {
pub enum FlatHashKey { pub enum FlatHashKey {
// Unfortunate that we must allocate here, c'est la vie // Unfortunate that we must allocate here, c'est la vie
Record(Vec<Lowercase>), Record(Vec<Lowercase>),
Tuple(u32),
TagUnion(Vec<(TagName, u16)>), TagUnion(Vec<(TagName, u16)>),
} }
@ -28,6 +29,7 @@ impl FlatHashKey {
pub(crate) fn debug_name(&self) -> String { pub(crate) fn debug_name(&self) -> String {
match self { match self {
FlatHashKey::Record(fields) => debug_name_record(fields), FlatHashKey::Record(fields) => debug_name_record(fields),
FlatHashKey::Tuple(arity) => debug_name_tuple(*arity),
FlatHashKey::TagUnion(tags) => debug_name_tag(tags), FlatHashKey::TagUnion(tags) => debug_name_tag(tags),
} }
} }
@ -65,8 +67,14 @@ impl FlatHash {
Ok(Key(FlatHashKey::Record(field_names))) Ok(Key(FlatHashKey::Record(field_names)))
} }
FlatType::Tuple(_elems, _ext) => { FlatType::Tuple(elems, ext) => {
todo!(); 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) => { FlatType::TagUnion(tags, ext) | FlatType::RecursiveTagUnion(_, tags, ext) => {
// The recursion var doesn't matter, because the derived implementation will only // 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 str
} }
pub(crate) fn debug_name_tuple(arity: u32) -> String {
format!("(arity:{arity})")
}
pub(crate) fn debug_name_tag(tags: &[(TagName, u16)]) -> String { pub(crate) fn debug_name_tag(tags: &[(TagName, u16)]) -> String {
let mut str = String::from('['); let mut str = String::from('[');
tags.iter().enumerate().for_each(|(i, (tag, arity))| { tags.iter().enumerate().for_each(|(i, (tag, arity))| {

View file

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

View file

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

View file

@ -748,7 +748,7 @@ fn get_specialization_lambda_set_ambient_function<P: Phase>(
let specialized_lambda_set = *specialization let specialized_lambda_set = *specialization
.specialization_lambda_sets .specialization_lambda_sets
.get(&lset_region) .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) Ok(specialized_lambda_set)
} }
MemberImpl::Error => todo_abilities!(), MemberImpl::Error => todo_abilities!(),

View file

@ -28,6 +28,11 @@ test_key_eq! {
explicit_empty_record_and_implicit_empty_record: explicit_empty_record_and_implicit_empty_record:
v!(EMPTY_RECORD), v!({}) 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: list_list_diff_types:
v!(Symbol::LIST_LIST v!(STR)), v!(Symbol::LIST_LIST v!(U8)) v!(Symbol::LIST_LIST v!(STR)), v!(Symbol::LIST_LIST v!(U8))
str_str: str_str:
@ -41,6 +46,9 @@ test_key_neq! {
v!({ a: v!(U8), }), v!({ b: v!(U8), }) v!({ a: v!(U8), }), v!({ b: v!(U8), })
record_empty_vs_nonempty: record_empty_vs_nonempty:
v!(EMPTY_RECORD), v!({ a: v!(U8), }) v!(EMPTY_RECORD), v!({ a: v!(U8), })
different_tuple_arities:
v!((v!(U8), v!(U16),)), v!((v!(U8), v!(U16), v!(U32),))
} }
#[test] #[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), }),
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: same_tag_union:
v!([ A v!(U8) v!(STR), B v!(STR) ]), v!([ A v!(U8) v!(STR), B v!(STR) ]) v!([ A v!(U8) v!(STR), B v!(STR) ]), v!([ A v!(U8) v!(STR), B v!(STR) ])
same_tag_union_tags_diff_types: same_tag_union_tags_diff_types:
@ -78,6 +83,9 @@ test_key_neq! {
record_empty_vs_nonempty: record_empty_vs_nonempty:
v!(EMPTY_RECORD), v!({ a: v!(U8), }) 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: different_tag_union_tags:
v!([ A v!(U8) ]), v!([ B v!(U8) ]) v!([ A v!(U8) ]), v!([ B v!(U8) ])
tag_union_empty_vs_nonempty: 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] #[test]
#[ignore = "NOTE: this would never actually happen, because [] is uninhabited, and hence toEncoder can never be called with a value of []! #[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."] 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: explicit_empty_record_and_implicit_empty_record:
v!(EMPTY_RECORD), v!({}) 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: same_tag_union:
v!([ A v!(U8) v!(STR), B v!(STR) ]), v!([ A v!(U8) v!(STR), B v!(STR) ]) v!([ A v!(U8) v!(STR), B v!(STR) ]), v!([ A v!(U8) v!(STR), B v!(STR) ])
same_tag_union_tags_diff_types: same_tag_union_tags_diff_types:
@ -51,6 +56,9 @@ test_key_neq! {
record_empty_vs_nonempty: record_empty_vs_nonempty:
v!(EMPTY_RECORD), v!({ a: v!(U8), }) 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: different_tag_union_tags:
v!([ A v!(U8) ]), v!([ B v!(U8) ]) v!([ A v!(U8) ]), v!([ B v!(U8) ])
tag_union_empty_vs_nonempty: 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] #[test]
fn tag_one_label_no_payloads() { fn tag_one_label_no_payloads() {
derive_test(Hash, v!([A]), |golden| { 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))) 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) => {{ ([ $($tag:ident $($payload:expr)*),* ] as $rec_var:ident) => {{
use roc_types::subs::{Subs, SubsIndex, Variable, Content, FlatType, TagExt, UnionTags}; use roc_types::subs::{Subs, SubsIndex, Variable, Content, FlatType, TagExt, UnionTags};
use roc_module::ident::TagName; 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] #[test]
#[cfg(all(any(feature = "gen-llvm", feature = "gen-wasm")))] #[cfg(all(any(feature = "gen-llvm", feature = "gen-wasm")))]
fn encode_derived_generic_record_with_different_field_types() { 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")))] #[cfg(all(test, any(feature = "gen-llvm", feature = "gen-wasm")))]
mod hash { mod hash {
#[cfg(feature = "gen-llvm")] #[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] #[test]
fn hash_singleton_union() { fn hash_singleton_union() {
assert_evals_to!( assert_evals_to!(
@ -1840,6 +1959,22 @@ mod eq {
use indoc::indoc; use indoc::indoc;
use roc_std::RocStr; 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] #[test]
fn custom_eq_impl() { fn custom_eq_impl() {
assert_evals_to!( assert_evals_to!(

View file

@ -1,5 +1,5 @@
procedure #Derived.0 (#Derived.1): 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; ret #Derived_gen.0;
procedure #Derived.2 (#Derived.3, #Derived.4, #Derived.1): 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.6 : {Str, Str} = Struct {#Derived_gen.7, #Derived_gen.8};
let #Derived_gen.5 : List {Str, Str} = Array [#Derived_gen.6]; 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.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; ret #Derived_gen.3;
procedure #Derived.5 (#Derived.6): 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; ret #Derived_gen.14;
procedure #Derived.7 (#Derived.8, #Derived.9, #Derived.6): 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.20 : {Str, Str} = Struct {#Derived_gen.21, #Derived_gen.22};
let #Derived_gen.19 : List {Str, Str} = Array [#Derived_gen.20]; 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.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; ret #Derived_gen.17;
procedure Encode.22 (Encode.93): procedure Encode.23 (Encode.98):
ret Encode.93; ret Encode.98;
procedure Encode.22 (Encode.93): procedure Encode.23 (Encode.98):
ret Encode.93; ret Encode.98;
procedure Encode.22 (Encode.93): procedure Encode.23 (Encode.98):
ret Encode.93; ret Encode.98;
procedure Encode.22 (Encode.93): procedure Encode.23 (Encode.98):
ret Encode.93; ret Encode.98;
procedure Encode.22 (Encode.93): procedure Encode.23 (Encode.98):
ret Encode.93; ret Encode.98;
procedure Encode.23 (Encode.94, Encode.102, Encode.96): procedure Encode.24 (Encode.99, Encode.107, Encode.101):
let Encode.106 : List U8 = CallByName #Derived.2 Encode.94 Encode.96 Encode.102; let Encode.111 : List U8 = CallByName #Derived.2 Encode.99 Encode.101 Encode.107;
ret Encode.106; ret Encode.111;
procedure Encode.23 (Encode.94, Encode.102, Encode.96): procedure Encode.24 (Encode.99, Encode.107, Encode.101):
let Encode.113 : List U8 = CallByName Json.114 Encode.94 Encode.96 Encode.102; let Encode.118 : List U8 = CallByName Json.118 Encode.99 Encode.101 Encode.107;
ret Encode.113; ret Encode.118;
procedure Encode.23 (Encode.94, Encode.102, Encode.96): procedure Encode.24 (Encode.99, Encode.107, Encode.101):
let Encode.115 : List U8 = CallByName #Derived.7 Encode.94 Encode.96 Encode.102; let Encode.120 : List U8 = CallByName #Derived.7 Encode.99 Encode.101 Encode.107;
ret Encode.115; ret Encode.120;
procedure Encode.23 (Encode.94, Encode.102, Encode.96): procedure Encode.24 (Encode.99, Encode.107, Encode.101):
let Encode.125 : List U8 = CallByName Json.114 Encode.94 Encode.96 Encode.102; let Encode.130 : List U8 = CallByName Json.118 Encode.99 Encode.101 Encode.107;
ret Encode.125; ret Encode.130;
procedure Encode.23 (Encode.94, Encode.102, Encode.96): procedure Encode.24 (Encode.99, Encode.107, Encode.101):
let Encode.128 : List U8 = CallByName Json.98 Encode.94 Encode.96 Encode.102; let Encode.133 : List U8 = CallByName Json.102 Encode.99 Encode.101 Encode.107;
ret Encode.128; ret Encode.133;
procedure Encode.25 (Encode.100, Encode.101): procedure Encode.26 (Encode.105, Encode.106):
let Encode.104 : List U8 = Array []; let Encode.109 : List U8 = Array [];
let Encode.105 : Str = CallByName #Derived.0 Encode.100; let Encode.110 : Str = CallByName #Derived.0 Encode.105;
let Encode.103 : List U8 = CallByName Encode.23 Encode.104 Encode.105 Encode.101; let Encode.108 : List U8 = CallByName Encode.24 Encode.109 Encode.110 Encode.106;
ret Encode.103; ret Encode.108;
procedure Json.1 (): procedure Json.1 ():
let Json.425 : {} = Struct {}; let Json.483 : {} = Struct {};
ret Json.425; ret Json.483;
procedure Json.114 (Json.115, Json.428, Json.113): procedure Json.102 (Json.103, Json.562, Json.101):
let Json.461 : I64 = 123i64; let Json.571 : I64 = 34i64;
let Json.460 : U8 = CallByName Num.127 Json.461; let Json.570 : U8 = CallByName Num.127 Json.571;
let Json.117 : List U8 = CallByName List.4 Json.115 Json.460; let Json.568 : List U8 = CallByName List.4 Json.103 Json.570;
let Json.459 : U64 = CallByName List.6 Json.113; let Json.569 : List U8 = CallByName Str.12 Json.101;
let Json.436 : {List U8, U64} = Struct {Json.117, Json.459}; let Json.565 : List U8 = CallByName List.8 Json.568 Json.569;
let Json.437 : {} = Struct {}; let Json.567 : I64 = 34i64;
let Json.435 : {List U8, U64} = CallByName List.18 Json.113 Json.436 Json.437; let Json.566 : U8 = CallByName Num.127 Json.567;
dec Json.113; let Json.564 : List U8 = CallByName List.4 Json.565 Json.566;
let Json.119 : List U8 = StructAtIndex 0 Json.435; ret Json.564;
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.114 (Json.115, Json.428, Json.113): procedure Json.118 (Json.119, Json.486, Json.117):
let Json.501 : I64 = 123i64; let Json.519 : I64 = 123i64;
let Json.500 : U8 = CallByName Num.127 Json.501; let Json.518 : U8 = CallByName Num.127 Json.519;
let Json.117 : List U8 = CallByName List.4 Json.115 Json.500; let Json.121 : List U8 = CallByName List.4 Json.119 Json.518;
let Json.499 : U64 = CallByName List.6 Json.113; let Json.517 : U64 = CallByName List.6 Json.117;
let Json.476 : {List U8, U64} = Struct {Json.117, Json.499}; let Json.494 : {List U8, U64} = Struct {Json.121, Json.517};
let Json.477 : {} = Struct {}; let Json.495 : {} = Struct {};
let Json.475 : {List U8, U64} = CallByName List.18 Json.113 Json.476 Json.477; let Json.493 : {List U8, U64} = CallByName List.18 Json.117 Json.494 Json.495;
dec Json.113; dec Json.117;
let Json.119 : List U8 = StructAtIndex 0 Json.475; let Json.123 : List U8 = StructAtIndex 0 Json.493;
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;
inc Json.123; inc Json.123;
dec Json.431; dec Json.493;
let Json.120 : List U8 = StructAtIndex 0 Json.430; let Json.492 : I64 = 125i64;
inc Json.120; let Json.491 : U8 = CallByName Num.127 Json.492;
let Json.121 : U64 = StructAtIndex 1 Json.430; let Json.490 : List U8 = CallByName List.4 Json.123 Json.491;
dec Json.430; ret Json.490;
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;
procedure Json.116 (Json.430, Json.431): procedure Json.118 (Json.119, Json.486, Json.117):
let Json.122 : Str = StructAtIndex 0 Json.431; let Json.559 : I64 = 123i64;
inc Json.122; let Json.558 : U8 = CallByName Num.127 Json.559;
let Json.123 : Str = StructAtIndex 1 Json.431; 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; inc Json.123;
dec Json.431; dec Json.533;
let Json.120 : List U8 = StructAtIndex 0 Json.430; let Json.532 : I64 = 125i64;
inc Json.120; let Json.531 : U8 = CallByName Num.127 Json.532;
let Json.121 : U64 = StructAtIndex 1 Json.430; let Json.530 : List U8 = CallByName List.4 Json.123 Json.531;
dec Json.430; ret Json.530;
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;
procedure Json.18 (Json.97): procedure Json.120 (Json.488, Json.489):
let Json.502 : Str = CallByName Encode.22 Json.97; let Json.126 : Str = StructAtIndex 0 Json.489;
ret Json.502; inc Json.126;
let Json.127 : Str = StructAtIndex 1 Json.489;
procedure Json.20 (Json.113): inc Json.127;
let Json.426 : List {Str, Str} = CallByName Encode.22 Json.113; dec Json.489;
ret Json.426; let Json.124 : List U8 = StructAtIndex 0 Json.488;
inc Json.124;
procedure Json.20 (Json.113): let Json.125 : U64 = StructAtIndex 1 Json.488;
let Json.468 : List {Str, Str} = CallByName Encode.22 Json.113; dec Json.488;
ret Json.468; let Json.516 : I64 = 34i64;
let Json.515 : U8 = CallByName Num.127 Json.516;
procedure Json.98 (Json.99, Json.504, Json.97): let Json.513 : List U8 = CallByName List.4 Json.124 Json.515;
let Json.513 : I64 = 34i64; let Json.514 : List U8 = CallByName Str.12 Json.126;
let Json.512 : U8 = CallByName Num.127 Json.513; let Json.510 : List U8 = CallByName List.8 Json.513 Json.514;
let Json.510 : List U8 = CallByName List.4 Json.99 Json.512; let Json.512 : I64 = 34i64;
let Json.511 : List U8 = CallByName Str.12 Json.97; let Json.511 : U8 = CallByName Num.127 Json.512;
let Json.507 : List U8 = CallByName List.8 Json.510 Json.511; let Json.507 : List U8 = CallByName List.4 Json.510 Json.511;
let Json.509 : I64 = 34i64; let Json.509 : I64 = 58i64;
let Json.508 : U8 = CallByName Num.127 Json.509; let Json.508 : U8 = CallByName Num.127 Json.509;
let Json.506 : List U8 = CallByName List.4 Json.507 Json.508; let Json.505 : List U8 = CallByName List.4 Json.507 Json.508;
ret Json.506; 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): 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; ret List.535;
procedure List.139 (List.140, List.141, List.138): 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; ret List.608;
procedure List.18 (List.136, List.137, List.138): procedure List.18 (List.136, List.137, List.138):
@ -348,7 +348,7 @@ procedure Str.9 (Str.77):
procedure Test.0 (): procedure Test.0 ():
let Test.12 : Str = "bar"; let Test.12 : Str = "bar";
let Test.10 : {} = CallByName Json.1; 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.1 : [C {U64, U8}, C Str] = CallByName Str.9 Test.8;
let Test.5 : U8 = 1i64; let Test.5 : U8 = 1i64;
let Test.6 : U8 = GetTagId Test.1; let Test.6 : U8 = GetTagId Test.1;

View file

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

View file

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

View file

@ -1,34 +1,34 @@
procedure Encode.22 (Encode.93): procedure Encode.23 (Encode.98):
ret Encode.93; ret Encode.98;
procedure Encode.23 (Encode.94, Encode.102, Encode.96): procedure Encode.24 (Encode.99, Encode.107, Encode.101):
let Encode.106 : List U8 = CallByName Json.98 Encode.94 Encode.96 Encode.102; let Encode.111 : List U8 = CallByName Json.102 Encode.99 Encode.101 Encode.107;
ret Encode.106; ret Encode.111;
procedure Encode.25 (Encode.100, Encode.101): procedure Encode.26 (Encode.105, Encode.106):
let Encode.104 : List U8 = Array []; let Encode.109 : List U8 = Array [];
let Encode.105 : Str = CallByName Json.18 Encode.100; let Encode.110 : Str = CallByName Json.18 Encode.105;
let Encode.103 : List U8 = CallByName Encode.23 Encode.104 Encode.105 Encode.101; let Encode.108 : List U8 = CallByName Encode.24 Encode.109 Encode.110 Encode.106;
ret Encode.103; ret Encode.108;
procedure Json.1 (): procedure Json.1 ():
let Json.425 : {} = Struct {}; let Json.483 : {} = Struct {};
ret Json.425; ret Json.483;
procedure Json.18 (Json.97): procedure Json.102 (Json.103, Json.486, Json.101):
let Json.426 : Str = CallByName Encode.22 Json.97; let Json.495 : I64 = 34i64;
ret Json.426; 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): procedure Json.18 (Json.101):
let Json.437 : I64 = 34i64; let Json.484 : Str = CallByName Encode.23 Json.101;
let Json.436 : U8 = CallByName Num.127 Json.437; ret Json.484;
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 List.4 (List.107, List.108): procedure List.4 (List.107, List.108):
let List.503 : U64 = 1i64; let List.503 : U64 = 1i64;
@ -86,7 +86,7 @@ procedure Str.9 (Str.77):
procedure Test.0 (): procedure Test.0 ():
let Test.9 : Str = "abc"; let Test.9 : Str = "abc";
let Test.10 : {} = CallByName Json.1; 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.1 : [C {U64, U8}, C Str] = CallByName Str.9 Test.8;
let Test.5 : U8 = 1i64; let Test.5 : U8 = 1i64;
let Test.6 : U8 = GetTagId Test.1; let Test.6 : U8 = GetTagId Test.1;

View file

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

View file

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

View file

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

View file

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

View file

@ -4459,6 +4459,7 @@ pub struct StorageSubs {
struct StorageSubsOffsets { struct StorageSubsOffsets {
utable: u32, utable: u32,
variables: u32, variables: u32,
tuple_elem_indices: u32,
tag_names: u32, tag_names: u32,
symbol_names: u32, symbol_names: u32,
field_names: u32, field_names: u32,
@ -4542,6 +4543,7 @@ impl StorageSubs {
let self_offsets = StorageSubsOffsets { let self_offsets = StorageSubsOffsets {
utable: self.subs.utable.len() as u32, utable: self.subs.utable.len() as u32,
variables: self.subs.variables.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, tag_names: self.subs.tag_names.len() as u32,
symbol_names: self.subs.symbol_names.len() as u32, symbol_names: self.subs.symbol_names.len() as u32,
field_names: self.subs.field_names.len() as u32, field_names: self.subs.field_names.len() as u32,
@ -4553,6 +4555,7 @@ impl StorageSubs {
let offsets = StorageSubsOffsets { let offsets = StorageSubsOffsets {
utable: (target.utable.len() - Variable::NUM_RESERVED_VARS) as u32, utable: (target.utable.len() - Variable::NUM_RESERVED_VARS) as u32,
variables: target.variables.len() 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, tag_names: target.tag_names.len() as u32,
symbol_names: target.symbol_names.len() as u32, symbol_names: target.symbol_names.len() as u32,
field_names: target.field_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)), .map(|v| Self::offset_variable(&offsets, *v)),
); );
target
.tuple_elem_indices
.extend(self.subs.tuple_elem_indices);
target.variable_slices.extend( target.variable_slices.extend(
self.subs self.subs
.variable_slices .variable_slices
@ -4613,6 +4620,11 @@ impl StorageSubs {
(self_offsets.utable + offsets.utable) as usize (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!( debug_assert_eq!(
target.tag_names.len(), target.tag_names.len(),
(self_offsets.tag_names + offsets.tag_names) as usize (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 { 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.variables_start += offsets.variables;
tuple_elems tuple_elems

View file

@ -11177,6 +11177,55 @@ I recommend using camelCase. It's the standard style in Roc code!
"### "###
); );
test_no_problem!(
derive_hash_for_tuple,
indoc!(
r#"
app "test" provides [main] to "./platform"
foo : a -> {} | a has Hash
main = foo ("", 1)
"#
)
);
test_report!(
cannot_hash_tuple_with_non_hash_element,
indoc!(
r#"
app "test" provides [main] to "./platform"
foo : a -> {} | a has Hash
main = foo ("", \{} -> {})
"#
),
@r###"
TYPE MISMATCH /code/proj/Main.roc
This expression has a type that does not implement the abilities it's expected to:
5 main = foo ("", \{} -> {})
^^^^^^^^^^^^^^^
I can't generate an implementation of the `Hash` ability for
(
Str,
{}a -> {},
)a
In particular, an implementation for
{}a -> {}
cannot be generated.
Note: `Hash` cannot be generated for functions.
"###
);
test_report!( test_report!(
shift_by_negative, shift_by_negative,
indoc!( indoc!(
@ -11559,6 +11608,58 @@ I recommend using camelCase. It's the standard style in Roc code!
"### "###
); );
test_no_problem!(
derive_eq_for_tuple,
indoc!(
r#"
app "test" provides [main] to "./platform"
foo : a -> {} | a has Eq
main = foo ("", 1)
"#
)
);
test_report!(
cannot_eq_tuple_with_non_eq_element,
indoc!(
r#"
app "test" provides [main] to "./platform"
foo : a -> {} | a has Eq
main = foo ("", 1.0f64)
"#
),
@r###"
TYPE MISMATCH /code/proj/Main.roc
This expression has a type that does not implement the abilities it's expected to:
5 main = foo ("", 1.0f64)
^^^^^^^^^^^^
I can't generate an implementation of the `Eq` ability for
(
Str,
F64,
)a
In particular, an implementation for
F64
cannot be generated.
Note: I can't derive `Bool.isEq` for floating-point types. That's
because Roc's floating-point numbers cannot be compared for total
equality - in Roc, `NaN` is never comparable to `NaN`. If a type
doesn't support total equality, it cannot support the `Eq` ability!
"###
);
test_report!( test_report!(
cannot_import_structural_eq_not_eq, cannot_import_structural_eq_not_eq,
indoc!( indoc!(
@ -13127,6 +13228,90 @@ I recommend using camelCase. It's the standard style in Roc code!
"### "###
); );
test_no_problem!(
derive_decoding_for_tuple,
indoc!(
r#"
app "test" imports [Decode.{decoder}] provides [main] to "./platform"
main =
myDecoder : Decoder (U32, Str) fmt | fmt has DecoderFormatting
myDecoder = decoder
myDecoder
"#
)
);
test_report!(
cannot_decode_tuple_with_non_decode_element,
indoc!(
r#"
app "test" imports [Decode.{decoder}] provides [main] to "./platform"
main =
myDecoder : Decoder (U32, {} -> {}) fmt | fmt has DecoderFormatting
myDecoder = decoder
myDecoder
"#
),
@r###"
TYPE MISMATCH /code/proj/Main.roc
This expression has a type that does not implement the abilities it's expected to:
5 myDecoder = decoder
^^^^^^^
I can't generate an implementation of the `Decoding` ability for
U32, {} -> {}
Note: `Decoding` cannot be generated for functions.
"###
);
test_no_problem!(
derive_encoding_for_tuple,
indoc!(
r#"
app "test" imports [] provides [main] to "./platform"
x : (U32, Str)
main = Encode.toEncoder x
"#
)
);
test_report!(
cannot_encode_tuple_with_non_encode_element,
indoc!(
r#"
app "test" imports [] provides [main] to "./platform"
x : (U32, {} -> {})
main = Encode.toEncoder x
"#
),
@r###"
TYPE MISMATCH /code/proj/Main.roc
This expression has a type that does not implement the abilities it's expected to:
5 main = Encode.toEncoder x
^
I can't generate an implementation of the `Encoding` ability for
U32, {} -> {}
Note: `Encoding` cannot be generated for functions.
"###
);
test_report!( test_report!(
exhaustiveness_check_function_or_tag_union_issue_4994, exhaustiveness_check_function_or_tag_union_issue_4994,
indoc!( indoc!(

View file

@ -19,6 +19,7 @@ EnvFormat := {} has [
string: envString, string: envString,
list: envList, list: envList,
record: envRecord, record: envRecord,
tuple: envTuple,
}, },
] ]
@ -93,3 +94,10 @@ envList = \decodeElem -> Decode.custom \bytes, @EnvFormat {} ->
envRecord : _, (_, _ -> [Keep (Decoder _ _), Skip]), (_ -> _) -> Decoder _ _ envRecord : _, (_, _ -> [Keep (Decoder _ _), Skip]), (_ -> _) -> Decoder _ _
envRecord = \_initialState, _stepField, _finalizer -> Decode.custom \bytes, @EnvFormat {} -> envRecord = \_initialState, _stepField, _finalizer -> Decode.custom \bytes, @EnvFormat {} ->
{ result: Err TooShort, rest: bytes } { result: Err TooShort, rest: bytes }
# TODO: we must currently annotate the arrows here so that the lambda sets are
# exercised, and the solver can find an ambient lambda set for the
# specialization.
envTuple : _, (_, _ -> [Next (Decoder _ _), TooLong]), (_ -> _) -> Decoder _ _
envTuple = \_initialState, _stepElem, _finalizer -> Decode.custom \bytes, @EnvFormat {} ->
{ result: Err TooShort, rest: bytes }