Merge pull request #5775 from roc-lang/inspect-derive

Derive Inspect
This commit is contained in:
Brendan Hansknecht 2023-11-29 08:22:27 -08:00 committed by GitHub
commit ead90313d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
45 changed files with 4791 additions and 416 deletions

View File

@ -942,7 +942,7 @@ mod cli_run {
test_roc_app_slim(
"examples",
"inspect-logging.roc",
r#"{people: [{firstName: "John", lastName: "Smith", age: 27, hasBeard: true, favoriteColor: Blue}, {firstName: "Debby", lastName: "Johnson", age: 47, hasBeard: false, favoriteColor: Green}, {firstName: "Jane", lastName: "Doe", age: 33, hasBeard: false, favoriteColor: (RGB (255, 255, 0))}], friends: [{2}, {2}, {0, 1}]}
r#"{friends: [{2}, {2}, {0, 1}], people: [{age: 27, favoriteColor: Blue, firstName: "John", hasBeard: Bool.true, lastName: "Smith"}, {age: 47, favoriteColor: Green, firstName: "Debby", hasBeard: Bool.false, lastName: "Johnson"}, {age: 33, favoriteColor: (RGB (255, 255, 0)), firstName: "Jane", hasBeard: Bool.false, lastName: "Doe"}]}
"#,
UseValgrind::Yes,
)

View File

@ -32,6 +32,7 @@ interface Dict
Str,
Num.{ Nat, U64, U8, I8 },
Hash.{ Hasher, Hash },
Inspect.{ Inspect, Inspector, InspectFormatter },
]
## A [dictionary](https://en.wikipedia.org/wiki/Associative_array) that lets you
@ -108,6 +109,9 @@ Dict k v := {
Hash {
hash: hashDict,
},
Inspect {
toInspector: toInspectorDict,
},
]
isEq : Dict k v, Dict k v -> Bool where k implements Hash & Eq, v implements Eq
@ -126,6 +130,11 @@ isEq = \xs, ys ->
hashDict : hasher, Dict k v -> hasher where k implements Hash & Eq, v implements Hash, hasher implements Hasher
hashDict = \hasher, dict -> Hash.hashUnordered hasher (toList dict) List.walk
toInspectorDict : Dict k v -> Inspector f where k implements Inspect & Hash & Eq, v implements Inspect, f implements InspectFormatter
toInspectorDict = \dict ->
fmt <- Inspect.custom
Inspect.apply (Inspect.dict dict walk Inspect.toInspector Inspect.toInspector) fmt
## Return an empty dictionary.
## ```
## emptyDict = Dict.empty {}

View File

@ -15,6 +15,7 @@ interface Inspect
record,
bool,
str,
function,
opaque,
u8,
i8,
@ -26,16 +27,19 @@ interface Inspect
i64,
u128,
i128,
nat,
f32,
f64,
dec,
custom,
apply,
toInspector,
DbgFormatter,
toDbgStr,
]
imports [
Bool.{ Bool },
Num.{ U8, U16, U32, U64, U128, I8, I16, I32, I64, I128, F32, F64, Dec },
Num.{ U8, U16, U32, U64, U128, I8, I16, I32, I64, I128, F32, F64, Dec, Nat },
List,
Str,
]
@ -56,12 +60,13 @@ InspectFormatter implements
set : set, ElemWalker state set elem, (elem -> Inspector f) -> Inspector f where f implements InspectFormatter
dict : dict, KeyValWalker state dict key value, (key -> Inspector f), (value -> Inspector f) -> Inspector f where f implements InspectFormatter
# Note opaque is used for both opaque types and functions.
# The auto deriver for functions probably could put the function type.
# For regular opaque types, I think we can use the type name, though that may lead to some reflection related issues that still need to be discussed.
# As a simple baseline, it can just use the exact words `opaque` and `function` for now.
# In text, this would render as `<opaque>`, `<function>`, etc
opaque : Str -> Inspector f where f implements InspectFormatter
# In text, this would render as `<opaque>`
# TODO: Pass the type name to opaque so that it can be displayed.
opaque : * -> Inspector f where f implements InspectFormatter
# In text, this would render as `<function>`
# TODO: Maybe pass the the function name or signiture to function so that it can be displayed.
function : * -> Inspector f where f implements InspectFormatter
u8 : U8 -> Inspector f where f implements InspectFormatter
i8 : I8 -> Inspector f where f implements InspectFormatter
@ -73,6 +78,7 @@ InspectFormatter implements
i64 : I64 -> Inspector f where f implements InspectFormatter
u128 : U128 -> Inspector f where f implements InspectFormatter
i128 : I128 -> Inspector f where f implements InspectFormatter
nat : Nat -> Inspector f where f implements InspectFormatter
f32 : F32 -> Inspector f where f implements InspectFormatter
f64 : F64 -> Inspector f where f implements InspectFormatter
dec : Dec -> Inspector f where f implements InspectFormatter
@ -80,7 +86,7 @@ InspectFormatter implements
Inspector f := f -> f where f implements InspectFormatter
custom : (f -> f) -> Inspector f where f implements InspectFormatter
custom = @Inspector
custom = \fn -> @Inspector fn
apply : Inspector f, f -> f where f implements InspectFormatter
apply = \@Inspector fn, fmt -> fn fmt
@ -92,3 +98,252 @@ inspect : val -> f where val implements Inspect, f implements InspectFormatter
inspect = \val ->
(@Inspector valFn) = toInspector val
valFn (init {})
# The current default formatter for inspect.
# This just returns a simple string for debugging.
# More powerful formatters will likely be wanted in the future.
DbgFormatter := { data : Str }
implements [
InspectFormatter {
init: dbgInit,
list: dbgList,
set: dbgSet,
dict: dbgDict,
tag: dbgTag,
tuple: dbgTuple,
record: dbgRecord,
bool: dbgBool,
str: dbgStr,
opaque: dbgOpaque,
function: dbgFunction,
u8: dbgU8,
i8: dbgI8,
u16: dbgU16,
i16: dbgI16,
u32: dbgU32,
i32: dbgI32,
u64: dbgU64,
i64: dbgI64,
u128: dbgU128,
i128: dbgI128,
nat: dbgNat,
f32: dbgF32,
f64: dbgF64,
dec: dbgDec,
},
]
dbgInit : {} -> DbgFormatter
dbgInit = \{} -> @DbgFormatter { data: "" }
dbgList : list, ElemWalker (DbgFormatter, Bool) list elem, (elem -> Inspector DbgFormatter) -> Inspector DbgFormatter
dbgList = \content, walkFn, toDbgInspector ->
f0 <- custom
dbgWrite f0 "["
|> \f1 ->
(f2, prependSep), elem <- walkFn content (f1, Bool.false)
f3 =
if prependSep then
dbgWrite f2 ", "
else
f2
elem
|> toDbgInspector
|> apply f3
|> \f4 -> (f4, Bool.true)
|> .0
|> dbgWrite "]"
dbgSet : set, ElemWalker (DbgFormatter, Bool) set elem, (elem -> Inspector DbgFormatter) -> Inspector DbgFormatter
dbgSet = \content, walkFn, toDbgInspector ->
f0 <- custom
dbgWrite f0 "{"
|> \f1 ->
(f2, prependSep), elem <- walkFn content (f1, Bool.false)
f3 =
if prependSep then
dbgWrite f2 ", "
else
f2
elem
|> toDbgInspector
|> apply f3
|> \f4 -> (f4, Bool.true)
|> .0
|> dbgWrite "}"
dbgDict : dict, KeyValWalker (DbgFormatter, Bool) dict key value, (key -> Inspector DbgFormatter), (value -> Inspector DbgFormatter) -> Inspector DbgFormatter
dbgDict = \d, walkFn, keyToInspector, valueToInspector ->
f0 <- custom
dbgWrite f0 "{"
|> \f1 ->
(f2, prependSep), key, value <- walkFn d (f1, Bool.false)
f3 =
if prependSep then
dbgWrite f2 ", "
else
f2
apply (keyToInspector key) f3
|> dbgWrite ": "
|> \x -> apply (valueToInspector value) x
|> \f4 -> (f4, Bool.true)
|> .0
|> dbgWrite "}"
dbgTag : Str, List (Inspector DbgFormatter) -> Inspector DbgFormatter
dbgTag = \name, fields ->
if List.isEmpty fields then
f0 <- custom
dbgWrite f0 name
else
f0 <- custom
dbgWrite f0 "("
|> dbgWrite name
|> \f1 ->
f2, inspector <- List.walk fields f1
dbgWrite f2 " "
|> \x -> apply inspector x
|> dbgWrite ")"
dbgTuple : List (Inspector DbgFormatter) -> Inspector DbgFormatter
dbgTuple = \fields ->
f0 <- custom
dbgWrite f0 "("
|> \f1 ->
(f2, prependSep), inspector <- List.walk fields (f1, Bool.false)
f3 =
if prependSep then
dbgWrite f2 ", "
else
f2
apply inspector f3
|> \f4 -> (f4, Bool.true)
|> .0
|> dbgWrite ")"
dbgRecord : List { key : Str, value : Inspector DbgFormatter } -> Inspector DbgFormatter
dbgRecord = \fields ->
f0 <- custom
dbgWrite f0 "{"
|> \f1 ->
(f2, prependSep), { key, value } <- List.walk fields (f1, Bool.false)
f3 =
if prependSep then
dbgWrite f2 ", "
else
f2
dbgWrite f3 key
|> dbgWrite ": "
|> \x -> apply value x
|> \f4 -> (f4, Bool.true)
|> .0
|> dbgWrite "}"
dbgBool : Bool -> Inspector DbgFormatter
dbgBool = \b ->
if b then
f0 <- custom
dbgWrite f0 "Bool.true"
else
f0 <- custom
dbgWrite f0 "Bool.false"
dbgStr : Str -> Inspector DbgFormatter
dbgStr = \s ->
f0 <- custom
f0
|> dbgWrite "\""
|> dbgWrite s # TODO: Should we be escaping strings for dbg/logging?
|> dbgWrite "\""
dbgOpaque : * -> Inspector DbgFormatter
dbgOpaque = \_ ->
f0 <- custom
dbgWrite f0 "<opaque>"
dbgFunction : * -> Inspector DbgFormatter
dbgFunction = \_ ->
f0 <- custom
dbgWrite f0 "<function>"
dbgU8 : U8 -> Inspector DbgFormatter
dbgU8 = \num ->
f0 <- custom
dbgWrite f0 (num |> Num.toStr)
dbgI8 : I8 -> Inspector DbgFormatter
dbgI8 = \num ->
f0 <- custom
dbgWrite f0 (num |> Num.toStr)
dbgU16 : U16 -> Inspector DbgFormatter
dbgU16 = \num ->
f0 <- custom
dbgWrite f0 (num |> Num.toStr)
dbgI16 : I16 -> Inspector DbgFormatter
dbgI16 = \num ->
f0 <- custom
dbgWrite f0 (num |> Num.toStr)
dbgU32 : U32 -> Inspector DbgFormatter
dbgU32 = \num ->
f0 <- custom
dbgWrite f0 (num |> Num.toStr)
dbgI32 : I32 -> Inspector DbgFormatter
dbgI32 = \num ->
f0 <- custom
dbgWrite f0 (num |> Num.toStr)
dbgU64 : U64 -> Inspector DbgFormatter
dbgU64 = \num ->
f0 <- custom
dbgWrite f0 (num |> Num.toStr)
dbgI64 : I64 -> Inspector DbgFormatter
dbgI64 = \num ->
f0 <- custom
dbgWrite f0 (num |> Num.toStr)
dbgU128 : U128 -> Inspector DbgFormatter
dbgU128 = \num ->
f0 <- custom
dbgWrite f0 (num |> Num.toStr)
dbgI128 : I128 -> Inspector DbgFormatter
dbgI128 = \num ->
f0 <- custom
dbgWrite f0 (num |> Num.toStr)
dbgNat : Nat -> Inspector DbgFormatter
dbgNat = \num ->
f0 <- custom
dbgWrite f0 (num |> Num.toStr)
dbgF32 : F32 -> Inspector DbgFormatter
dbgF32 = \num ->
f0 <- custom
dbgWrite f0 (num |> Num.toStr)
dbgF64 : F64 -> Inspector DbgFormatter
dbgF64 = \num ->
f0 <- custom
dbgWrite f0 (num |> Num.toStr)
dbgDec : Dec -> Inspector DbgFormatter
dbgDec = \num ->
f0 <- custom
dbgWrite f0 (num |> Num.toStr)
dbgWrite : DbgFormatter, Str -> DbgFormatter
dbgWrite = \@DbgFormatter { data }, added ->
@DbgFormatter { data: Str.concat data added }
toDbgStr : DbgFormatter -> Str
toDbgStr = \@DbgFormatter { data } -> data

View File

@ -25,6 +25,7 @@ interface Set
Dict.{ Dict },
Num.{ Nat },
Hash.{ Hash, Hasher },
Inspect.{ Inspect, Inspector, InspectFormatter },
]
## Provides a [set](https://en.wikipedia.org/wiki/Set_(abstract_data_type))
@ -37,6 +38,9 @@ Set k := Dict.Dict k {} where k implements Hash & Eq
Hash {
hash: hashSet,
},
Inspect {
toInspector: toInspectorSet,
},
]
isEq : Set k, Set k -> Bool where k implements Hash & Eq
@ -53,6 +57,11 @@ isEq = \xs, ys ->
hashSet : hasher, Set k -> hasher where k implements Hash & Eq, hasher implements Hasher
hashSet = \hasher, @Set inner -> Hash.hash hasher inner
toInspectorSet : Set k -> Inspector f where k implements Inspect & Hash & Eq, f implements InspectFormatter
toInspectorSet = \set ->
fmt <- Inspect.custom
Inspect.apply (Inspect.set set walk Inspect.toInspector) fmt
## Creates a new empty `Set`.
## ```
## emptySet = Set.empty {}

View File

@ -718,6 +718,7 @@ fn canonicalize_opaque<'a>(
let ability_region = ability.region;
// Op := {} has [Eq]
let (ability, members) = match ability.value {
ast::TypeAnnotation::Apply(module_name, ident, []) => {
match make_apply_symbol(env, region, scope, module_name, ident) {

View File

@ -213,6 +213,48 @@ fn is_eq<'a>(env: &mut Env<'a>, at_opaque: &'a str) -> ast::Expr<'a> {
)
}
fn to_inspector<'a>(env: &mut Env<'a>, at_opaque: &'a str) -> ast::Expr<'a> {
let alloc_pat = |it| env.arena.alloc(Loc::at(DERIVED_REGION, it));
let alloc_expr = |it| env.arena.alloc(Loc::at(DERIVED_REGION, it));
let payload = "#payload";
// \@Opaq payload
let opaque_ref = alloc_pat(ast::Pattern::OpaqueRef(at_opaque));
let opaque_apply_pattern = ast::Pattern::Apply(
opaque_ref,
&*env
.arena
.alloc([Loc::at(DERIVED_REGION, ast::Pattern::Identifier(payload))]),
);
// Inspect.toInspector payload
let call_member = alloc_expr(ast::Expr::Apply(
alloc_expr(ast::Expr::Var {
module_name: "Inspect",
ident: "toInspector",
}),
&*env.arena.alloc([&*alloc_expr(ast::Expr::Var {
module_name: "",
ident: payload,
})]),
roc_module::called_via::CalledVia::Space,
));
// TODO: change the derived implementation to be something that includes the opaque symbol in
// the derivation, e.g. something like
//
// \@Opaq payload ->
// Inspect.opaqueWrapper "toString symbol" payload
// \@Opaq payload -> Inspect.toInspector payload
ast::Expr::Closure(
env.arena
.alloc([Loc::at(DERIVED_REGION, opaque_apply_pattern)]),
call_member,
)
}
pub const DERIVED_REGION: Region = Region::zero();
pub(crate) fn synthesize_member_impl<'a>(
@ -232,6 +274,10 @@ pub(crate) fn synthesize_member_impl<'a>(
Symbol::DECODE_DECODER => (format!("#{opaque_name}_decoder"), decoder(env, at_opaque)),
Symbol::HASH_HASH => (format!("#{opaque_name}_hash"), hash(env, at_opaque)),
Symbol::BOOL_IS_EQ => (format!("#{opaque_name}_isEq"), is_eq(env, at_opaque)),
Symbol::INSPECT_TO_INSPECTOR => (
format!("#{opaque_name}_toInspector"),
to_inspector(env, at_opaque),
),
other => internal_error!("{:?} is not a derivable ability member!", other),
};

File diff suppressed because it is too large Load Diff

View File

@ -19,7 +19,7 @@ use util::Env;
mod decoding;
mod encoding;
mod hash;
mod inspect;
mod util;
pub(crate) const DERIVED_SYNTH: ModuleId = ModuleId::DERIVED_SYNTH;
@ -79,6 +79,9 @@ fn build_derived_body(
decoding::derive_decoder(&mut env, decoder_key, derived_symbol)
}
DeriveKey::Hash(hash_key) => hash::derive_hash(&mut env, hash_key, derived_symbol),
DeriveKey::ToInspector(to_inspector_key) => {
inspect::derive_to_inspector(&mut env, to_inspector_key, derived_symbol)
}
};
let def = Def {

View File

@ -55,6 +55,7 @@ impl FlatEncodable {
FlatType::Record(fields, ext) => {
let (fields_iter, ext) = fields.unsorted_iterator_and_ext(subs, ext);
// TODO someday we can put #[cfg(debug_assertions)] around this, but for now let's always do it.
check_derivable_ext_var(subs, ext, |ext| {
matches!(ext, Content::Structure(FlatType::EmptyRecord))
})?;
@ -71,6 +72,7 @@ impl FlatEncodable {
FlatType::Tuple(elems, ext) => {
let (elems_iter, ext) = elems.sorted_iterator_and_ext(subs, ext);
// TODO someday we can put #[cfg(debug_assertions)] around this, but for now let's always do it.
check_derivable_ext_var(subs, ext, |ext| {
matches!(ext, Content::Structure(FlatType::EmptyTuple))
})?;
@ -89,6 +91,7 @@ impl FlatEncodable {
// `t`-prefixed payload types.
let (tags_iter, ext) = tags.unsorted_tags_and_ext(subs, ext);
// TODO someday we can put #[cfg(debug_assertions)] around this, but for now let's always do it.
check_derivable_ext_var(subs, ext.var(), |ext| {
matches!(ext, Content::Structure(FlatType::EmptyTagUnion))
})?;
@ -115,10 +118,9 @@ impl FlatEncodable {
)))
}
FlatType::EmptyRecord => Ok(Key(FlatEncodableKey::Record(vec![]))),
FlatType::EmptyTuple => todo!(),
FlatType::EmptyTagUnion => Ok(Key(FlatEncodableKey::TagUnion(vec![]))),
//
FlatType::Func(..) => Err(Underivable),
FlatType::EmptyTuple => unreachable!("Somehow Encoding derivation got an expression that's an empty tuple, which shouldn't be possible!"),
},
Content::Alias(sym, _, real_var, _) => match from_builtin_symbol(sym) {
Some(lambda) => lambda,
@ -129,9 +131,7 @@ impl FlatEncodable {
Content::RangedNumber(range) => {
Self::from_var(subs, range.default_compilation_variable())
}
//
Content::RecursionVar { structure, .. } => Self::from_var(subs, structure),
//
Content::Error => Err(Underivable),
Content::FlexVar(_)
| Content::RigidVar(_)

View File

@ -0,0 +1,211 @@
use roc_module::{
ident::{Lowercase, TagName},
symbol::Symbol,
};
use roc_types::{
subs::{Content, FlatType, GetSubsSlice, Subs, Variable},
types::AliasKind,
};
use crate::util::{
check_derivable_ext_var, debug_name_fn, debug_name_record, debug_name_tag, debug_name_tuple,
};
#[derive(Hash, Debug)]
pub enum FlatInspectable {
Immediate(Symbol),
Key(FlatInspectableKey),
}
#[derive(Hash, PartialEq, Eq, Debug, Clone)]
pub enum FlatInspectableKey {
List(/* takes one variable */),
Set(/* takes one variable */),
Dict(/* takes two variables */),
// Unfortunate that we must allocate here, c'est la vie
Record(Vec<Lowercase>),
Tuple(u32),
TagUnion(Vec<(TagName, u16)>),
Function(u32 /* arity; +1 for return type */),
/// This means specifically an opaque type where the author hasn't requested that it derive Inspect (or implemented it)
Opaque,
Error,
}
impl FlatInspectableKey {
pub(crate) fn debug_name(&self) -> String {
match self {
FlatInspectableKey::List() => "list".to_string(),
FlatInspectableKey::Set() => "set".to_string(),
FlatInspectableKey::Dict() => "dict".to_string(),
FlatInspectableKey::Record(fields) => debug_name_record(fields),
FlatInspectableKey::Tuple(arity) => debug_name_tuple(*arity),
FlatInspectableKey::TagUnion(tags) => debug_name_tag(tags),
FlatInspectableKey::Function(arity) => debug_name_fn(*arity),
FlatInspectableKey::Error => "error".to_string(),
FlatInspectableKey::Opaque => "opaque".to_string(),
}
}
}
impl FlatInspectable {
pub(crate) fn from_var(subs: &Subs, var: Variable) -> FlatInspectable {
use FlatInspectable::*;
match *subs.get_content_without_compacting(var) {
Content::Structure(flat_type) => match flat_type {
FlatType::Apply(sym, _) => match sym {
Symbol::LIST_LIST => Key(FlatInspectableKey::List()),
Symbol::SET_SET => Key(FlatInspectableKey::Set()),
Symbol::DICT_DICT => Key(FlatInspectableKey::Dict()),
Symbol::STR_STR => Immediate(Symbol::INSPECT_STR),
_ => Immediate(Symbol::INSPECT_OPAQUE),
},
FlatType::Record(fields, ext) => {
let (fields_iter, ext) = fields.unsorted_iterator_and_ext(subs, ext);
// TODO someday we can put #[cfg(debug_assertions)] around this, but for now let's always do it.
check_derivable_ext_var(subs, ext, |ext| {
matches!(ext, Content::Structure(FlatType::EmptyRecord))
}).expect("Compiler error: unexpected nonempty ext var when deriving Inspect for record");
let mut field_names = Vec::with_capacity(fields.len());
for (field_name, _) in fields_iter {
field_names.push(field_name.clone());
}
field_names.sort();
Key(FlatInspectableKey::Record(field_names))
}
FlatType::Tuple(elems, ext) => {
let (elems_iter, ext) = elems.sorted_iterator_and_ext(subs, ext);
// TODO someday we can put #[cfg(debug_assertions)] around this, but for now let's always do it.
check_derivable_ext_var(subs, ext, |ext| {
matches!(ext, Content::Structure(FlatType::EmptyTuple))
}).expect("Compiler error: unexpected nonempty ext var when deriving Inspect for tuple");
Key(FlatInspectableKey::Tuple(elems_iter.count() as _))
}
FlatType::TagUnion(tags, ext) | FlatType::RecursiveTagUnion(_, tags, ext) => {
// The recursion var doesn't matter, because the derived implementation will only
// look on the surface of the tag union type, and more over the payloads of the
// arguments will be left generic for the monomorphizer to fill in with the
// appropriate type. That is,
// [ A t1, B t1 t2 ]
// and
// [ A t1, B t1 t2 ] as R
// look the same on the surface, because `R` is only somewhere inside of the
// `t`-prefixed payload types.
let (tags_iter, ext) = tags.unsorted_tags_and_ext(subs, ext);
// TODO someday we can put #[cfg(debug_assertions)] around this, but for now let's always do it.
check_derivable_ext_var(subs, ext.var(), |ext| {
matches!(ext, Content::Structure(FlatType::EmptyTagUnion))
}).expect("Compiler error: unexpected nonempty ext var when deriving Inspect for tag union");
let mut tag_names_and_payload_sizes: Vec<_> = tags_iter
.tags
.into_iter()
.map(|(name, payload_slice)| {
let payload_size = payload_slice.len();
(name.clone(), payload_size as _)
})
.collect();
tag_names_and_payload_sizes.sort_by(|(t1, _), (t2, _)| t1.cmp(t2));
Key(FlatInspectableKey::TagUnion(tag_names_and_payload_sizes))
}
FlatType::FunctionOrTagUnion(names_index, _, _) => {
Key(FlatInspectableKey::TagUnion(
subs.get_subs_slice(names_index)
.iter()
.map(|t| (t.clone(), 0))
.collect(),
))
}
FlatType::EmptyRecord => Key(FlatInspectableKey::Record(Vec::new())),
FlatType::EmptyTagUnion => Key(FlatInspectableKey::TagUnion(Vec::new())),
FlatType::Func(..) => {
Immediate(Symbol::INSPECT_FUNCTION)
}
FlatType::EmptyTuple => unreachable!("Somehow Inspect derivation got an expression that's an empty tuple, which shouldn't be possible!"),
},
Content::Alias(sym, _, real_var, kind) => match Self::from_builtin_alias(sym) {
Some(lambda) => lambda,
_ => {
match kind {
AliasKind::Structural => {
Self::from_var(subs, real_var)
}
// Special case, an unbound `Frac *` will become a `Dec`.
AliasKind::Opaque if matches!(*subs.get_content_without_compacting(real_var), Content::FlexVar(_) | Content::FlexAbleVar(_, _)) => {
Immediate(Symbol::INSPECT_DEC)
}
AliasKind::Opaque if sym.is_builtin() => {
Self::from_var(subs, real_var)
}
AliasKind::Opaque => {
// There are two cases in which `Inspect` can be derived for an opaque
// type.
// 1. An opaque type claims to implement `Inspect` and asks us to
// auto-derive it. E.g.
//
// ```text
// Op := {} implements [Inspect]
// ```
//
// In this case, we generate a synthetic implementation during
// canonicalization that defers to `inspect`ing the inner type. As
// such, this case is never reached in this branch.
//
// 2. An opaque type does not explicitly claim to implement
// `Inspect`. In this case, we print a default opaque string for
// the opaque type.
Immediate(Symbol::INSPECT_OPAQUE)
}
}
}
},
Content::RangedNumber(range) => {
Self::from_var(subs, range.default_compilation_variable())
}
Content::RecursionVar { structure, .. } => Self::from_var(subs, structure),
Content::Error => Key(FlatInspectableKey::Error),
Content::FlexVar(_)
| Content::RigidVar(_)
| Content::FlexAbleVar(_, _)
| Content::RigidAbleVar(_, _)
| Content::LambdaSet(_) | Content::ErasedLambda => {
unreachable!("There must have been a bug in the solver, because we're trying to derive Inspect on a non-concrete type.");
}
}
}
pub(crate) const fn from_builtin_alias(symbol: Symbol) -> Option<FlatInspectable> {
use FlatInspectable::*;
match symbol {
Symbol::BOOL_BOOL => Some(Immediate(Symbol::INSPECT_BOOL)),
Symbol::NUM_U8 | Symbol::NUM_UNSIGNED8 => Some(Immediate(Symbol::INSPECT_U8)),
Symbol::NUM_U16 | Symbol::NUM_UNSIGNED16 => Some(Immediate(Symbol::INSPECT_U16)),
Symbol::NUM_U32 | Symbol::NUM_UNSIGNED32 => Some(Immediate(Symbol::INSPECT_U32)),
Symbol::NUM_U64 | Symbol::NUM_UNSIGNED64 => Some(Immediate(Symbol::INSPECT_U64)),
Symbol::NUM_U128 | Symbol::NUM_UNSIGNED128 => Some(Immediate(Symbol::INSPECT_U128)),
Symbol::NUM_I8 | Symbol::NUM_SIGNED8 => Some(Immediate(Symbol::INSPECT_I8)),
Symbol::NUM_I16 | Symbol::NUM_SIGNED16 => Some(Immediate(Symbol::INSPECT_I16)),
Symbol::NUM_I32 | Symbol::NUM_SIGNED32 => Some(Immediate(Symbol::INSPECT_I32)),
Symbol::NUM_I64 | Symbol::NUM_SIGNED64 => Some(Immediate(Symbol::INSPECT_I64)),
Symbol::NUM_I128 | Symbol::NUM_SIGNED128 => Some(Immediate(Symbol::INSPECT_I128)),
Symbol::NUM_DEC | Symbol::NUM_DECIMAL => Some(Immediate(Symbol::INSPECT_DEC)),
Symbol::NUM_F32 | Symbol::NUM_BINARY32 => Some(Immediate(Symbol::INSPECT_F32)),
Symbol::NUM_F64 | Symbol::NUM_BINARY64 => Some(Immediate(Symbol::INSPECT_F64)),
Symbol::NUM_NAT | Symbol::NUM_NATURAL => Some(Immediate(Symbol::INSPECT_NAT)),
_ => None,
}
}
}

View File

@ -16,12 +16,14 @@
pub mod decoding;
pub mod encoding;
pub mod hash;
pub mod inspect;
mod util;
use decoding::{FlatDecodable, FlatDecodableKey};
use encoding::{FlatEncodable, FlatEncodableKey};
use hash::{FlatHash, FlatHashKey};
use inspect::{FlatInspectable, FlatInspectableKey};
use roc_module::symbol::Symbol;
use roc_types::subs::{Subs, Variable};
@ -40,6 +42,7 @@ pub enum DeriveKey {
ToEncoder(FlatEncodableKey),
Decoder(FlatDecodableKey),
Hash(FlatHashKey),
ToInspector(FlatInspectableKey),
}
impl DeriveKey {
@ -48,6 +51,7 @@ impl DeriveKey {
DeriveKey::ToEncoder(key) => format!("toEncoder_{}", key.debug_name()),
DeriveKey::Decoder(key) => format!("decoder_{}", key.debug_name()),
DeriveKey::Hash(key) => format!("hash_{}", key.debug_name()),
DeriveKey::ToInspector(key) => format!("toInspector_{}", key.debug_name()),
}
}
}
@ -77,6 +81,7 @@ pub enum DeriveBuiltin {
Decoder,
Hash,
IsEq,
ToInspector,
}
impl TryFrom<Symbol> for DeriveBuiltin {
@ -88,6 +93,7 @@ impl TryFrom<Symbol> for DeriveBuiltin {
Symbol::DECODE_DECODER => Ok(DeriveBuiltin::Decoder),
Symbol::HASH_HASH => Ok(DeriveBuiltin::Hash),
Symbol::BOOL_IS_EQ => Ok(DeriveBuiltin::IsEq),
Symbol::INSPECT_TO_INSPECTOR => Ok(DeriveBuiltin::ToInspector),
_ => Err(value),
}
}
@ -121,6 +127,10 @@ impl Derived {
Symbol::BOOL_STRUCTURAL_EQ,
))
}
DeriveBuiltin::ToInspector => match FlatInspectable::from_var(subs, var) {
FlatInspectable::Immediate(imm) => Ok(Derived::Immediate(imm)),
FlatInspectable::Key(repr) => Ok(Derived::Key(DeriveKey::ToInspector(repr))),
},
}
}
@ -151,6 +161,12 @@ impl Derived {
Symbol::BOOL_STRUCTURAL_EQ,
))
}
DeriveBuiltin::ToInspector => {
match inspect::FlatInspectable::from_builtin_alias(symbol).unwrap() {
FlatInspectable::Immediate(imm) => Ok(Derived::Immediate(imm)),
FlatInspectable::Key(repr) => Ok(Derived::Key(DeriveKey::ToInspector(repr))),
}
}
}
}
}

View File

@ -60,3 +60,7 @@ pub(crate) fn debug_name_tag(tags: &[(TagName, u16)]) -> String {
str.push(']');
str
}
pub(crate) fn debug_name_fn(arity: u32) -> String {
format!("(arity:{arity} -> _)")
}

View File

@ -2252,7 +2252,7 @@ impl<'a> LowLevelCall<'a> {
fn num_to_str(&self, backend: &mut WasmBackend<'a, '_>) {
let arg_layout = backend.storage.symbol_layouts[&self.arguments[0]];
match backend.layout_interner.get_repr(arg_layout) {
match backend.layout_interner.runtime_representation(arg_layout) {
LayoutRepr::Builtin(Builtin::Int(width)) => {
self.load_args_and_call_zig(backend, &bitcode::STR_FROM_INT[width])
}

View File

@ -9798,7 +9798,7 @@ In roc, functions are always written as a lambda, like{}
Only builtin abilities can be derived.
Note: The builtin abilities are `Encoding`, `Decoding`, `Hash`, `Eq`
Note: The builtin abilities are `Encoding`, `Decoding`, `Hash`, `Eq`, `Inspect`
"###
);

View File

@ -53,6 +53,10 @@ pub const DERIVABLE_ABILITIES: &[(Symbol, &[Symbol])] = &[
(Symbol::DECODE_DECODING, &[Symbol::DECODE_DECODER]),
(Symbol::HASH_HASH_ABILITY, &[Symbol::HASH_HASH]),
(Symbol::BOOL_EQ, &[Symbol::BOOL_IS_EQ]),
(
Symbol::INSPECT_INSPECT_ABILITY,
&[Symbol::INSPECT_TO_INSPECTOR],
),
];
/// In Debug builds only, Symbol has a name() method that lets
@ -1609,22 +1613,26 @@ define_builtins! {
13 INSPECT_BOOL: "bool"
14 INSPECT_STR: "str"
15 INSPECT_OPAQUE: "opaque"
16 INSPECT_U8: "u8"
17 INSPECT_I8: "i8"
18 INSPECT_U16: "u16"
19 INSPECT_I16: "i16"
20 INSPECT_U32: "u32"
21 INSPECT_I32: "i32"
22 INSPECT_U64: "u64"
23 INSPECT_I64: "i64"
24 INSPECT_U128: "u128"
25 INSPECT_I128: "i128"
26 INSPECT_F32: "f32"
27 INSPECT_F64: "f64"
28 INSPECT_DEC: "dec"
29 INSPECT_CUSTOM: "custom"
30 INSPECT_APPLY: "apply"
31 INSPECT_TO_INSPECTOR: "toInspector"
16 INSPECT_FUNCTION: "function"
17 INSPECT_U8: "u8"
18 INSPECT_I8: "i8"
19 INSPECT_U16: "u16"
20 INSPECT_I16: "i16"
21 INSPECT_U32: "u32"
22 INSPECT_I32: "i32"
23 INSPECT_U64: "u64"
24 INSPECT_I64: "i64"
25 INSPECT_U128: "u128"
26 INSPECT_I128: "i128"
27 INSPECT_F32: "f32"
28 INSPECT_F64: "f64"
29 INSPECT_DEC: "dec"
30 INSPECT_CUSTOM: "custom"
31 INSPECT_APPLY: "apply"
32 INSPECT_TO_INSPECTOR: "toInspector"
33 INSPECT_NAT: "nat"
34 INSPECT_DBG_FORMATTER: "DbgFormatter" exposed_type=true
35 INSPECT_TO_DBG_STR: "toDbgStr"
}
15 JSON: "TotallyNotJson" => {
0 JSON_JSON: "TotallyNotJson"

View File

@ -304,6 +304,13 @@ impl ObligationCache {
Symbol::BOOL_EQ => Some(DeriveEq::is_derivable(self, abilities_store, subs, var)),
Symbol::INSPECT_INSPECT_ABILITY => Some(DeriveInspect::is_derivable(
self,
abilities_store,
subs,
var,
)),
_ => None,
};
@ -373,7 +380,10 @@ impl ObligationCache {
let ImplKey { opaque, ability } = impl_key;
let has_declared_impl = abilities_store.has_declared_implementation(opaque, ability);
// Every type has the Inspect ability automatically, even opaques with no `implements` declaration.
let is_inspect = ability == Symbol::INSPECT_INSPECT_ABILITY;
let has_known_impl =
is_inspect || abilities_store.has_declared_implementation(opaque, ability);
// Some builtins, like Float32 and Bool, would have a cyclic dependency on Encode/Decode/etc.
// if their Roc implementations explicitly defined some abilities they support.
@ -382,18 +392,17 @@ impl ObligationCache {
DeriveDecoding::ABILITY => DeriveDecoding::is_derivable_builtin_opaque(opaque),
DeriveEq::ABILITY => DeriveEq::is_derivable_builtin_opaque(opaque),
DeriveHash::ABILITY => DeriveHash::is_derivable_builtin_opaque(opaque),
DeriveInspect::ABILITY => DeriveInspect::is_derivable_builtin_opaque(opaque),
_ => false,
};
let has_declared_impl = has_declared_impl || builtin_opaque_impl_ok();
let obligation_result = if !has_declared_impl {
let obligation_result = if has_known_impl || builtin_opaque_impl_ok() {
Ok(())
} else {
Err(Unfulfilled::OpaqueDoesNotImplement {
typ: opaque,
ability,
})
} else {
Ok(())
};
self.impl_cache.insert(impl_key, obligation_result);
@ -849,6 +858,93 @@ trait DerivableVisitor {
}
}
struct DeriveInspect;
impl DerivableVisitor for DeriveInspect {
const ABILITY: Symbol = Symbol::INSPECT_INSPECT_ABILITY;
const ABILITY_SLICE: SubsSlice<Symbol> = Subs::AB_INSPECT;
#[inline(always)]
fn is_derivable_builtin_opaque(_: Symbol) -> bool {
true
}
#[inline(always)]
fn visit_recursion(_var: Variable) -> Result<Descend, NotDerivable> {
Ok(Descend(true))
}
#[inline(always)]
fn visit_apply(_: Variable, _: Symbol) -> Result<Descend, NotDerivable> {
Ok(Descend(true))
}
#[inline(always)]
fn visit_record(
_subs: &Subs,
_var: Variable,
_fields: RecordFields,
) -> Result<Descend, NotDerivable> {
Ok(Descend(true))
}
#[inline(always)]
fn visit_tuple(
_subs: &Subs,
_var: Variable,
_elems: TupleElems,
) -> Result<Descend, NotDerivable> {
Ok(Descend(true))
}
#[inline(always)]
fn visit_tag_union(_var: Variable) -> Result<Descend, NotDerivable> {
Ok(Descend(true))
}
#[inline(always)]
fn visit_recursive_tag_union(_var: Variable) -> Result<Descend, NotDerivable> {
Ok(Descend(true))
}
#[inline(always)]
fn visit_function_or_tag_union(_var: Variable) -> Result<Descend, NotDerivable> {
Ok(Descend(true))
}
#[inline(always)]
fn visit_empty_record(_var: Variable) -> Result<(), NotDerivable> {
Ok(())
}
#[inline(always)]
fn visit_empty_tag_union(_var: Variable) -> Result<(), NotDerivable> {
Ok(())
}
#[inline(always)]
fn visit_alias(_var: Variable, symbol: Symbol) -> Result<Descend, NotDerivable> {
if is_builtin_number_alias(symbol) {
Ok(Descend(false))
} else {
Ok(Descend(true))
}
}
#[inline(always)]
fn visit_ranged_number(_var: Variable, _range: NumericRange) -> Result<(), NotDerivable> {
Ok(())
}
#[inline(always)]
fn visit_floating_point_content(
_var: Variable,
_subs: &mut Subs,
_content_var: Variable,
) -> Result<Descend, NotDerivable> {
Ok(Descend(false))
}
}
struct DeriveEncoding;
impl DerivableVisitor for DeriveEncoding {
const ABILITY: Symbol = Symbol::ENCODE_ENCODING;
@ -1392,7 +1488,7 @@ impl AbilityResolver for AbilitiesStore {
}
}
/// Whether this a module whose types' ability implementations should be checked via derive_key,
/// Whether this is a module whose types' ability implementations should be checked via derive_key,
/// because they do not explicitly list ability implementations due to circular dependencies.
#[inline]
pub(crate) fn builtin_module_with_unlisted_ability_impl(module_id: ModuleId) -> bool {

View File

@ -628,29 +628,7 @@ fn make_specialization_decision<P: Phase>(
} else {
// Solving within a module.
phase.with_module_abilities_store(opaque.module_id(), |abilities_store| {
let impl_key = ImplKey {
opaque: *opaque,
ability_member,
};
match abilities_store.get_implementation(impl_key) {
None => {
// Doesn't specialize; an error will already be reported for this.
SpecializeDecision::Drop
}
Some(MemberImpl::Error) => {
// TODO: probably not right, we may want to choose a derive decision!
SpecializeDecision::Specialize(Opaque(*opaque))
}
Some(MemberImpl::Impl(specialization_symbol)) => {
match abilities_store.specialization_info(*specialization_symbol) {
Some(_) => SpecializeDecision::Specialize(Opaque(*opaque)),
// If we expect a specialization impl but don't yet know it, we must hold off
// compacting the lambda set until the specialization is well-known.
None => SpecializeDecision::PendingSpecialization(impl_key),
}
}
}
make_ability_specialization_decision(*opaque, ability_member, abilities_store)
})
}
}
@ -698,6 +676,46 @@ fn make_specialization_decision<P: Phase>(
}
}
fn make_ability_specialization_decision(
opaque: Symbol,
ability_member: Symbol,
abilities_store: &AbilitiesStore,
) -> SpecializeDecision {
use SpecializationTypeKey::*;
let impl_key = ImplKey {
opaque,
ability_member,
};
match abilities_store.get_implementation(impl_key) {
None => {
match ability_member {
// Inspect is special - if there is no implementation for the
// opaque type, we always emit a default implementation.
Symbol::INSPECT_TO_INSPECTOR => {
SpecializeDecision::Specialize(Immediate(Symbol::INSPECT_OPAQUE))
}
_ => {
// Doesn't specialize; an error will already be reported for this.
SpecializeDecision::Drop
}
}
}
Some(MemberImpl::Error) => {
// TODO: probably not right, we may want to choose a derive decision!
SpecializeDecision::Specialize(Opaque(opaque))
}
Some(MemberImpl::Impl(specialization_symbol)) => {
match abilities_store.specialization_info(*specialization_symbol) {
Some(_) => SpecializeDecision::Specialize(Opaque(opaque)),
// If we expect a specialization impl but don't yet know it, we must hold off
// compacting the lambda set until the specialization is well-known.
None => SpecializeDecision::PendingSpecialization(impl_key),
}
}
}
}
#[allow(clippy::too_many_arguments)]
fn get_specialization_lambda_set_ambient_function<P: Phase>(
subs: &mut Subs,

View File

@ -68,6 +68,11 @@ fn module_source_and_path(builtin: DeriveBuiltin) -> (ModuleId, &'static str, Pa
module_source(ModuleId::BOOL),
builtins_path.join("Bool.roc"),
),
DeriveBuiltin::ToInspector => (
ModuleId::INSPECT,
module_source(ModuleId::INSPECT),
builtins_path.join("Inspect.roc"),
),
}
}

View File

@ -2159,19 +2159,19 @@ fn issue_4772_weakened_monomorphic_destructure() {
getNumber =
{ result, rest } = Decode.fromBytesPartial (Str.toUtf8 "\"1234\"") TotallyNotJson.json
when result is
Ok val ->
when Str.toI64 val is
when result is
Ok val ->
when Str.toI64 val is
Ok number ->
Ok {val : number, input : rest}
Err InvalidNumStr ->
Err (ParsingFailure "not a number")
Err _ ->
Err _ ->
Err (ParsingFailure "not a number")
main =
main =
getNumber |> Result.map .val |> Result.withDefault 0
"###
),
@ -2180,3 +2180,112 @@ fn issue_4772_weakened_monomorphic_destructure() {
)
})
}
mod inspect {
#[cfg(feature = "gen-llvm")]
use crate::helpers::llvm::assert_evals_to;
#[cfg(feature = "gen-wasm")]
use crate::helpers::wasm::assert_evals_to;
#[cfg(all(test, any(feature = "gen-llvm", feature = "gen-wasm")))]
use indoc::indoc;
#[cfg(all(test, any(feature = "gen-llvm", feature = "gen-wasm")))]
use roc_std::RocStr;
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn bool() {
assert_evals_to!(
indoc!(
r#"
app "test" provides [main] to "./platform"
main = [
Inspect.inspect Bool.true,
Inspect.inspect Bool.false,
] |> List.map Inspect.toDbgStr |> Str.joinWith ", "
"#
),
RocStr::from("Bool.true, Bool.false"),
RocStr
);
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn num() {
assert_evals_to!(
indoc!(
r#"
app "test" provides [main] to "./platform"
main = [
Inspect.inspect 0, # Num a
Inspect.inspect 1u8, # U8
Inspect.inspect 2i8, # I8
Inspect.inspect 3u16, # U16
Inspect.inspect 4i16, # I16
Inspect.inspect 5u32, # U32
Inspect.inspect 6i32, # I32
Inspect.inspect 7u64, # U64
Inspect.inspect 8i64, # I64
Inspect.inspect 9u128, # U128
Inspect.inspect 10i128, # I128
Inspect.inspect 0.5, # Frac a
Inspect.inspect 1.5f32, # F32
Inspect.inspect 2.2f64, # F64
Inspect.inspect (1.1dec + 2.2), # Dec
] |> List.map Inspect.toDbgStr |> Str.joinWith ", "
"#
),
RocStr::from("0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0.5, 1.5, 2.2, 3.3"),
RocStr
);
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn list() {
assert_evals_to!(
indoc!(
r#"
app "test" provides [main] to "./platform"
main = [
Inspect.inspect [0, 1, 2], # List (Num *)
Inspect.inspect [1, 0x2, 3], # List (Int *)
Inspect.inspect [0.1 + 0.2, 0.4], # List (Frac *)
Inspect.inspect [1u8, 2u8], # List U8
Inspect.inspect ["foo"], # List Str
] |> List.map Inspect.toDbgStr |> Str.joinWith ", "
"#
),
RocStr::from("[0, 1, 2], [1, 2, 3], [0.3, 0.4], [1, 2], [\"foo\"]"),
RocStr
);
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn str() {
assert_evals_to!(
indoc!(
r#"
app "test" provides [main] to "./platform"
main = [
Inspect.inspect "",
Inspect.inspect "a small string",
Inspect.inspect "an extraordinarily long string - so long it's on the heap!",
] |> List.map Inspect.toDbgStr |> Str.joinWith ", "
"#
),
RocStr::from(
r#""", "a small string", "an extraordinarily long string - so long it's on the heap!""#
),
RocStr
);
}
}

View File

@ -1,28 +1,28 @@
procedure Dict.1 (Dict.554):
let Dict.563 : List {[], []} = Array [];
procedure Dict.1 (Dict.557):
let Dict.567 : List {[], []} = Array [];
let Dict.574 : U64 = 0i64;
let Dict.575 : U64 = 8i64;
let Dict.568 : List U64 = CallByName List.11 Dict.574 Dict.575;
let Dict.571 : I8 = CallByName Dict.40;
let Dict.572 : U64 = 8i64;
let Dict.569 : List I8 = CallByName List.11 Dict.571 Dict.572;
let Dict.570 : U64 = 0i64;
let Dict.571 : U64 = 8i64;
let Dict.564 : List U64 = CallByName List.11 Dict.570 Dict.571;
let Dict.567 : I8 = CallByName Dict.39;
let Dict.568 : U64 = 8i64;
let Dict.565 : List I8 = CallByName List.11 Dict.567 Dict.568;
let Dict.566 : U64 = 0i64;
let Dict.562 : {List {[], []}, List U64, List I8, U64} = Struct {Dict.563, Dict.564, Dict.565, Dict.566};
ret Dict.562;
let Dict.566 : {List {[], []}, List U64, List I8, U64} = Struct {Dict.567, Dict.568, Dict.569, Dict.570};
ret Dict.566;
procedure Dict.39 ():
let Dict.569 : I8 = -128i64;
ret Dict.569;
procedure Dict.4 (Dict.560):
let Dict.101 : U64 = StructAtIndex 3 Dict.560;
let #Derived_gen.8 : List {[], []} = StructAtIndex 0 Dict.560;
procedure Dict.4 (Dict.564):
let Dict.105 : U64 = StructAtIndex 3 Dict.564;
let #Derived_gen.8 : List {[], []} = StructAtIndex 0 Dict.564;
dec #Derived_gen.8;
let #Derived_gen.7 : List U64 = StructAtIndex 1 Dict.560;
let #Derived_gen.7 : List U64 = StructAtIndex 1 Dict.564;
dec #Derived_gen.7;
let #Derived_gen.6 : List I8 = StructAtIndex 2 Dict.560;
let #Derived_gen.6 : List I8 = StructAtIndex 2 Dict.564;
dec #Derived_gen.6;
ret Dict.101;
ret Dict.105;
procedure Dict.40 ():
let Dict.573 : I8 = -128i64;
ret Dict.573;
procedure List.11 (List.133, List.134):
let List.554 : List I8 = CallByName List.68 List.134;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,172 @@
procedure #Derived.0 (#Derived.1):
let #Derived_gen.0 : List I64 = CallByName Inspect.30 #Derived.1;
ret #Derived_gen.0;
procedure #Derived.3 (#Derived.2):
let #Derived_gen.7 : I64 = CallByName Inspect.54 #Derived.2;
ret #Derived_gen.7;
procedure #Derived.4 (#Derived.5, #Derived.1):
let #Derived_gen.5 : {} = Struct {};
let #Derived_gen.6 : {} = Struct {};
let #Derived_gen.4 : {List I64, {}, {}} = CallByName Inspect.37 #Derived.1 #Derived_gen.5 #Derived_gen.6;
let #Derived_gen.3 : Str = CallByName Inspect.31 #Derived_gen.4 #Derived.5;
ret #Derived_gen.3;
procedure Bool.1 ():
let Bool.24 : Int1 = false;
ret Bool.24;
procedure Bool.2 ():
let Bool.23 : Int1 = true;
ret Bool.23;
procedure Inspect.155 (Inspect.156, #Attr.12):
let Inspect.154 : {} = StructAtIndex 2 #Attr.12;
let Inspect.153 : {} = StructAtIndex 1 #Attr.12;
let Inspect.152 : List I64 = StructAtIndex 0 #Attr.12;
let Inspect.345 : Str = "[";
let Inspect.328 : Str = CallByName Inspect.61 Inspect.156 Inspect.345;
let Inspect.329 : {List I64, {}, {}} = Struct {Inspect.152, Inspect.153, Inspect.154};
let Inspect.324 : {Str, Int1} = CallByName Inspect.157 Inspect.328 Inspect.329;
let Inspect.325 : {} = Struct {};
let Inspect.320 : Str = CallByName Inspect.166 Inspect.324;
let Inspect.321 : Str = "]";
let Inspect.319 : Str = CallByName Inspect.61 Inspect.320 Inspect.321;
ret Inspect.319;
procedure Inspect.157 (Inspect.158, #Attr.12):
let Inspect.154 : {} = StructAtIndex 2 #Attr.12;
let Inspect.153 : {} = StructAtIndex 1 #Attr.12;
let Inspect.152 : List I64 = StructAtIndex 0 #Attr.12;
let Bool.1 : Int1 = CallByName Bool.1;
let Inspect.332 : {Str, Int1} = Struct {Inspect.158, Bool.1};
let Inspect.331 : {Str, Int1} = CallByName List.18 Inspect.152 Inspect.332 Inspect.154;
ret Inspect.331;
procedure Inspect.159 (Inspect.334, Inspect.162, Inspect.154):
let Inspect.160 : Str = StructAtIndex 0 Inspect.334;
let Inspect.161 : Int1 = StructAtIndex 1 Inspect.334;
joinpoint Inspect.343 Inspect.163:
let Inspect.340 : I64 = CallByName #Derived.3 Inspect.162;
let Inspect.337 : Str = CallByName Inspect.31 Inspect.340 Inspect.163;
let Inspect.338 : {} = Struct {};
let Inspect.336 : {Str, Int1} = CallByName Inspect.164 Inspect.337;
ret Inspect.336;
in
if Inspect.161 then
let Inspect.344 : Str = ", ";
let Inspect.342 : Str = CallByName Inspect.61 Inspect.160 Inspect.344;
jump Inspect.343 Inspect.342;
else
jump Inspect.343 Inspect.160;
procedure Inspect.164 (Inspect.165):
let Bool.2 : Int1 = CallByName Bool.2;
let Inspect.339 : {Str, Int1} = Struct {Inspect.165, Bool.2};
ret Inspect.339;
procedure Inspect.166 (Inspect.326):
let Inspect.327 : Str = StructAtIndex 0 Inspect.326;
ret Inspect.327;
procedure Inspect.277 (Inspect.278, Inspect.276):
let Inspect.351 : Str = CallByName Num.96 Inspect.276;
let Inspect.350 : Str = CallByName Inspect.61 Inspect.278 Inspect.351;
ret Inspect.350;
procedure Inspect.30 (Inspect.147):
ret Inspect.147;
procedure Inspect.30 (Inspect.147):
ret Inspect.147;
procedure Inspect.30 (Inspect.147):
ret Inspect.147;
procedure Inspect.31 (Inspect.305, Inspect.149):
let Inspect.314 : Str = CallByName Inspect.155 Inspect.149 Inspect.305;
ret Inspect.314;
procedure Inspect.31 (Inspect.305, Inspect.149):
let Inspect.341 : Str = CallByName Inspect.277 Inspect.149 Inspect.305;
ret Inspect.341;
procedure Inspect.35 (Inspect.300):
ret Inspect.300;
procedure Inspect.36 (Inspect.304):
let Inspect.311 : Str = "";
ret Inspect.311;
procedure Inspect.37 (Inspect.152, Inspect.153, Inspect.154):
let Inspect.316 : {List I64, {}, {}} = Struct {Inspect.152, Inspect.153, Inspect.154};
let Inspect.315 : {List I64, {}, {}} = CallByName Inspect.30 Inspect.316;
ret Inspect.315;
procedure Inspect.5 (Inspect.150):
let Inspect.312 : List I64 = CallByName #Derived.0 Inspect.150;
let Inspect.309 : {} = Struct {};
let Inspect.308 : Str = CallByName Inspect.36 Inspect.309;
let Inspect.307 : Str = CallByName #Derived.4 Inspect.308 Inspect.312;
ret Inspect.307;
procedure Inspect.54 (Inspect.276):
let Inspect.346 : I64 = CallByName Inspect.30 Inspect.276;
ret Inspect.346;
procedure Inspect.61 (Inspect.303, Inspect.298):
let Inspect.323 : Str = CallByName Str.3 Inspect.303 Inspect.298;
dec Inspect.298;
ret Inspect.323;
procedure List.18 (List.154, List.155, List.156):
let List.554 : U64 = 0i64;
let List.555 : U64 = CallByName List.6 List.154;
let List.553 : {Str, Int1} = CallByName List.88 List.154 List.155 List.156 List.554 List.555;
ret List.553;
procedure List.6 (#Attr.2):
let List.564 : U64 = lowlevel ListLen #Attr.2;
ret List.564;
procedure List.66 (#Attr.2, #Attr.3):
let List.563 : I64 = lowlevel ListGetUnsafe #Attr.2 #Attr.3;
ret List.563;
procedure List.88 (#Derived_gen.17, #Derived_gen.18, #Derived_gen.19, #Derived_gen.20, #Derived_gen.21):
joinpoint List.556 List.157 List.158 List.159 List.160 List.161:
let List.558 : Int1 = CallByName Num.22 List.160 List.161;
if List.558 then
let List.562 : I64 = CallByName List.66 List.157 List.160;
let List.162 : {Str, Int1} = CallByName Inspect.159 List.158 List.562 List.159;
let List.561 : U64 = 1i64;
let List.560 : U64 = CallByName Num.51 List.160 List.561;
jump List.556 List.157 List.162 List.159 List.560 List.161;
else
dec List.157;
ret List.158;
in
jump List.556 #Derived_gen.17 #Derived_gen.18 #Derived_gen.19 #Derived_gen.20 #Derived_gen.21;
procedure Num.22 (#Attr.2, #Attr.3):
let Num.293 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;
ret Num.293;
procedure Num.51 (#Attr.2, #Attr.3):
let Num.292 : U64 = lowlevel NumAddWrap #Attr.2 #Attr.3;
ret Num.292;
procedure Num.96 (#Attr.2):
let Num.291 : Str = lowlevel NumToStr #Attr.2;
ret Num.291;
procedure Str.3 (#Attr.2, #Attr.3):
let Str.292 : Str = lowlevel StrConcat #Attr.2 #Attr.3;
ret Str.292;
procedure Test.0 ():
let Test.3 : List I64 = Array [1i64, 2i64, 3i64];
let Test.2 : Str = CallByName Inspect.5 Test.3;
let Test.1 : Str = CallByName Inspect.35 Test.2;
ret Test.1;

View File

@ -0,0 +1,274 @@
procedure #Derived.0 (#Derived.1):
let #Derived_gen.0 : Str = CallByName Inspect.30 #Derived.1;
ret #Derived_gen.0;
procedure #Derived.2 (#Derived.3, #Derived.1):
let #Derived_gen.7 : Str = "a";
let #Derived_gen.8 : Str = CallByName #Derived.4 #Derived.1;
let #Derived_gen.6 : {Str, Str} = Struct {#Derived_gen.7, #Derived_gen.8};
let #Derived_gen.5 : List {Str, Str} = Array [#Derived_gen.6];
let #Derived_gen.4 : List {Str, Str} = CallByName Inspect.42 #Derived_gen.5;
let #Derived_gen.3 : Str = CallByName Inspect.31 #Derived_gen.4 #Derived.3;
ret #Derived_gen.3;
procedure #Derived.4 (#Derived.5):
let #Derived_gen.10 : Str = CallByName Inspect.30 #Derived.5;
ret #Derived_gen.10;
procedure #Derived.6 (#Derived.7, #Derived.5):
let #Derived_gen.17 : Str = "b";
let #Derived_gen.18 : Str = CallByName Inspect.44 #Derived.5;
let #Derived_gen.16 : {Str, Str} = Struct {#Derived_gen.17, #Derived_gen.18};
let #Derived_gen.15 : List {Str, Str} = Array [#Derived_gen.16];
let #Derived_gen.14 : List {Str, Str} = CallByName Inspect.42 #Derived_gen.15;
let #Derived_gen.13 : Str = CallByName Inspect.31 #Derived_gen.14 #Derived.7;
ret #Derived_gen.13;
procedure Bool.1 ():
let Bool.26 : Int1 = false;
ret Bool.26;
procedure Bool.2 ():
let Bool.25 : Int1 = true;
ret Bool.25;
procedure Inspect.228 (Inspect.229, Inspect.227):
let Inspect.350 : Str = "{";
let Inspect.328 : Str = CallByName Inspect.61 Inspect.229 Inspect.350;
let Inspect.324 : {Str, Int1} = CallByName Inspect.230 Inspect.328 Inspect.227;
let Inspect.325 : {} = Struct {};
let Inspect.320 : Str = CallByName Inspect.242 Inspect.324;
let Inspect.321 : Str = "}";
let Inspect.319 : Str = CallByName Inspect.61 Inspect.320 Inspect.321;
ret Inspect.319;
procedure Inspect.228 (Inspect.229, Inspect.227):
let Inspect.388 : Str = "{";
let Inspect.366 : Str = CallByName Inspect.61 Inspect.229 Inspect.388;
let Inspect.362 : {Str, Int1} = CallByName Inspect.230 Inspect.366 Inspect.227;
let Inspect.363 : {} = Struct {};
let Inspect.358 : Str = CallByName Inspect.242 Inspect.362;
let Inspect.359 : Str = "}";
let Inspect.357 : Str = CallByName Inspect.61 Inspect.358 Inspect.359;
ret Inspect.357;
procedure Inspect.230 (Inspect.231, Inspect.227):
let Bool.1 : Int1 = CallByName Bool.1;
let Inspect.332 : {Str, Int1} = Struct {Inspect.231, Bool.1};
let Inspect.333 : {} = Struct {};
let Inspect.331 : {Str, Int1} = CallByName List.18 Inspect.227 Inspect.332 Inspect.333;
ret Inspect.331;
procedure Inspect.230 (Inspect.231, Inspect.227):
let Bool.1 : Int1 = CallByName Bool.1;
let Inspect.370 : {Str, Int1} = Struct {Inspect.231, Bool.1};
let Inspect.371 : {} = Struct {};
let Inspect.369 : {Str, Int1} = CallByName List.18 Inspect.227 Inspect.370 Inspect.371;
ret Inspect.369;
procedure Inspect.232 (Inspect.334, Inspect.335):
let Inspect.235 : Str = StructAtIndex 0 Inspect.335;
let Inspect.236 : Str = StructAtIndex 1 Inspect.335;
let Inspect.233 : Str = StructAtIndex 0 Inspect.334;
let Inspect.234 : Int1 = StructAtIndex 1 Inspect.334;
joinpoint Inspect.348 Inspect.237:
let Inspect.345 : Str = CallByName Inspect.61 Inspect.237 Inspect.235;
let Inspect.346 : Str = ": ";
let Inspect.340 : Str = CallByName Inspect.61 Inspect.345 Inspect.346;
let Inspect.337 : Str = CallByName Inspect.238 Inspect.340 Inspect.236;
let Inspect.338 : {} = Struct {};
let Inspect.336 : {Str, Int1} = CallByName Inspect.240 Inspect.337;
ret Inspect.336;
in
if Inspect.234 then
let Inspect.349 : Str = ", ";
let Inspect.347 : Str = CallByName Inspect.61 Inspect.233 Inspect.349;
jump Inspect.348 Inspect.347;
else
jump Inspect.348 Inspect.233;
procedure Inspect.232 (Inspect.334, Inspect.335):
let Inspect.235 : Str = StructAtIndex 0 Inspect.335;
let Inspect.236 : Str = StructAtIndex 1 Inspect.335;
let Inspect.233 : Str = StructAtIndex 0 Inspect.334;
let Inspect.234 : Int1 = StructAtIndex 1 Inspect.334;
joinpoint Inspect.386 Inspect.237:
let Inspect.383 : Str = CallByName Inspect.61 Inspect.237 Inspect.235;
let Inspect.384 : Str = ": ";
let Inspect.378 : Str = CallByName Inspect.61 Inspect.383 Inspect.384;
let Inspect.375 : Str = CallByName Inspect.238 Inspect.378 Inspect.236;
let Inspect.376 : {} = Struct {};
let Inspect.374 : {Str, Int1} = CallByName Inspect.240 Inspect.375;
ret Inspect.374;
in
if Inspect.234 then
let Inspect.387 : Str = ", ";
let Inspect.385 : Str = CallByName Inspect.61 Inspect.233 Inspect.387;
jump Inspect.386 Inspect.385;
else
jump Inspect.386 Inspect.233;
procedure Inspect.238 (Inspect.239, Inspect.236):
let Inspect.343 : Str = CallByName Inspect.31 Inspect.236 Inspect.239;
ret Inspect.343;
procedure Inspect.238 (Inspect.239, Inspect.236):
let Inspect.381 : Str = CallByName Inspect.31 Inspect.236 Inspect.239;
ret Inspect.381;
procedure Inspect.240 (Inspect.241):
let Bool.2 : Int1 = CallByName Bool.2;
let Inspect.377 : {Str, Int1} = Struct {Inspect.241, Bool.2};
ret Inspect.377;
procedure Inspect.242 (Inspect.326):
let Inspect.365 : Str = StructAtIndex 0 Inspect.326;
ret Inspect.365;
procedure Inspect.249 (Inspect.250, Inspect.248):
let Inspect.397 : Str = "\"";
let Inspect.396 : Str = CallByName Inspect.61 Inspect.250 Inspect.397;
let Inspect.394 : Str = CallByName Inspect.61 Inspect.396 Inspect.248;
let Inspect.395 : Str = "\"";
let Inspect.393 : Str = CallByName Inspect.61 Inspect.394 Inspect.395;
ret Inspect.393;
procedure Inspect.30 (Inspect.147):
ret Inspect.147;
procedure Inspect.30 (Inspect.147):
ret Inspect.147;
procedure Inspect.30 (Inspect.147):
ret Inspect.147;
procedure Inspect.30 (Inspect.147):
ret Inspect.147;
procedure Inspect.30 (Inspect.147):
ret Inspect.147;
procedure Inspect.31 (Inspect.305, Inspect.149):
let Inspect.314 : Str = CallByName Inspect.228 Inspect.149 Inspect.305;
ret Inspect.314;
procedure Inspect.31 (Inspect.305, Inspect.149):
let Inspect.344 : Str = CallByName #Derived.6 Inspect.149 Inspect.305;
ret Inspect.344;
procedure Inspect.31 (Inspect.305, Inspect.149):
let Inspect.352 : Str = CallByName Inspect.228 Inspect.149 Inspect.305;
ret Inspect.352;
procedure Inspect.31 (Inspect.305, Inspect.149):
let Inspect.382 : Str = CallByName Inspect.249 Inspect.149 Inspect.305;
ret Inspect.382;
procedure Inspect.35 (Inspect.300):
ret Inspect.300;
procedure Inspect.36 (Inspect.304):
let Inspect.311 : Str = "";
ret Inspect.311;
procedure Inspect.42 (Inspect.227):
let Inspect.315 : List {Str, Str} = CallByName Inspect.30 Inspect.227;
ret Inspect.315;
procedure Inspect.42 (Inspect.227):
let Inspect.353 : List {Str, Str} = CallByName Inspect.30 Inspect.227;
ret Inspect.353;
procedure Inspect.44 (Inspect.248):
let Inspect.389 : Str = CallByName Inspect.30 Inspect.248;
ret Inspect.389;
procedure Inspect.5 (Inspect.150):
let Inspect.312 : Str = CallByName #Derived.0 Inspect.150;
let Inspect.309 : {} = Struct {};
let Inspect.308 : Str = CallByName Inspect.36 Inspect.309;
let Inspect.307 : Str = CallByName #Derived.2 Inspect.308 Inspect.312;
ret Inspect.307;
procedure Inspect.61 (Inspect.303, Inspect.298):
let Inspect.361 : Str = CallByName Str.3 Inspect.303 Inspect.298;
dec Inspect.298;
ret Inspect.361;
procedure List.18 (List.154, List.155, List.156):
let List.554 : U64 = 0i64;
let List.555 : U64 = CallByName List.6 List.154;
let List.553 : {Str, Int1} = CallByName List.88 List.154 List.155 List.156 List.554 List.555;
ret List.553;
procedure List.18 (List.154, List.155, List.156):
let List.566 : U64 = 0i64;
let List.567 : U64 = CallByName List.6 List.154;
let List.565 : {Str, Int1} = CallByName List.88 List.154 List.155 List.156 List.566 List.567;
ret List.565;
procedure List.6 (#Attr.2):
let List.564 : U64 = lowlevel ListLen #Attr.2;
ret List.564;
procedure List.6 (#Attr.2):
let List.576 : U64 = lowlevel ListLen #Attr.2;
ret List.576;
procedure List.66 (#Attr.2, #Attr.3):
let List.563 : {Str, Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3;
ret List.563;
procedure List.66 (#Attr.2, #Attr.3):
let List.575 : {Str, Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3;
ret List.575;
procedure List.88 (#Derived_gen.30, #Derived_gen.31, #Derived_gen.32, #Derived_gen.33, #Derived_gen.34):
joinpoint List.568 List.157 List.158 List.159 List.160 List.161:
let List.570 : Int1 = CallByName Num.22 List.160 List.161;
if List.570 then
let List.574 : {Str, Str} = CallByName List.66 List.157 List.160;
inc List.574;
let List.162 : {Str, Int1} = CallByName Inspect.232 List.158 List.574;
let List.573 : U64 = 1i64;
let List.572 : U64 = CallByName Num.51 List.160 List.573;
jump List.568 List.157 List.162 List.159 List.572 List.161;
else
dec List.157;
ret List.158;
in
jump List.568 #Derived_gen.30 #Derived_gen.31 #Derived_gen.32 #Derived_gen.33 #Derived_gen.34;
procedure List.88 (#Derived_gen.41, #Derived_gen.42, #Derived_gen.43, #Derived_gen.44, #Derived_gen.45):
joinpoint List.556 List.157 List.158 List.159 List.160 List.161:
let List.558 : Int1 = CallByName Num.22 List.160 List.161;
if List.558 then
let List.562 : {Str, Str} = CallByName List.66 List.157 List.160;
inc List.562;
let List.162 : {Str, Int1} = CallByName Inspect.232 List.158 List.562;
let List.561 : U64 = 1i64;
let List.560 : U64 = CallByName Num.51 List.160 List.561;
jump List.556 List.157 List.162 List.159 List.560 List.161;
else
dec List.157;
ret List.158;
in
jump List.556 #Derived_gen.41 #Derived_gen.42 #Derived_gen.43 #Derived_gen.44 #Derived_gen.45;
procedure Num.22 (#Attr.2, #Attr.3):
let Num.294 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;
ret Num.294;
procedure Num.51 (#Attr.2, #Attr.3):
let Num.293 : U64 = lowlevel NumAddWrap #Attr.2 #Attr.3;
ret Num.293;
procedure Str.3 (#Attr.2, #Attr.3):
let Str.293 : Str = lowlevel StrConcat #Attr.2 #Attr.3;
ret Str.293;
procedure Test.0 ():
let Test.5 : Str = "bar";
let Test.2 : Str = CallByName Inspect.5 Test.5;
let Test.1 : Str = CallByName Inspect.35 Test.2;
ret Test.1;

View File

@ -0,0 +1,204 @@
procedure #Derived.0 (#Derived.1):
let #Derived_gen.0 : {Decimal, I64} = CallByName Inspect.30 #Derived.1;
ret #Derived_gen.0;
procedure #Derived.2 (#Derived.3, #Derived.1):
let #Derived_gen.13 : I64 = StructAtIndex 1 #Derived.1;
let #Derived_gen.11 : [C I64, C Decimal] = CallByName Inspect.54 #Derived_gen.13;
let #Derived_gen.12 : Str = "a";
let #Derived_gen.6 : {[C I64, C Decimal], Str} = Struct {#Derived_gen.11, #Derived_gen.12};
let #Derived_gen.10 : Decimal = StructAtIndex 0 #Derived.1;
let #Derived_gen.8 : [C I64, C Decimal] = CallByName Inspect.60 #Derived_gen.10;
let #Derived_gen.9 : Str = "b";
let #Derived_gen.7 : {[C I64, C Decimal], Str} = Struct {#Derived_gen.8, #Derived_gen.9};
let #Derived_gen.5 : List {[C I64, C Decimal], Str} = Array [#Derived_gen.6, #Derived_gen.7];
let #Derived_gen.4 : List {[C I64, C Decimal], Str} = CallByName Inspect.42 #Derived_gen.5;
let #Derived_gen.3 : Str = CallByName Inspect.31 #Derived_gen.4 #Derived.3;
ret #Derived_gen.3;
procedure Bool.1 ():
let Bool.24 : Int1 = false;
ret Bool.24;
procedure Bool.2 ():
let Bool.23 : Int1 = true;
ret Bool.23;
procedure Inspect.228 (Inspect.229, Inspect.227):
let Inspect.351 : Str = "{";
let Inspect.328 : Str = CallByName Inspect.61 Inspect.229 Inspect.351;
let Inspect.324 : {Str, Int1} = CallByName Inspect.230 Inspect.328 Inspect.227;
let Inspect.325 : {} = Struct {};
let Inspect.320 : Str = CallByName Inspect.242 Inspect.324;
let Inspect.321 : Str = "}";
let Inspect.319 : Str = CallByName Inspect.61 Inspect.320 Inspect.321;
ret Inspect.319;
procedure Inspect.230 (Inspect.231, Inspect.227):
let Bool.1 : Int1 = CallByName Bool.1;
let Inspect.332 : {Str, Int1} = Struct {Inspect.231, Bool.1};
let Inspect.333 : {} = Struct {};
let Inspect.331 : {Str, Int1} = CallByName List.18 Inspect.227 Inspect.332 Inspect.333;
ret Inspect.331;
procedure Inspect.232 (Inspect.334, Inspect.335):
let Inspect.236 : [C I64, C Decimal] = StructAtIndex 0 Inspect.335;
let Inspect.235 : Str = StructAtIndex 1 Inspect.335;
let Inspect.233 : Str = StructAtIndex 0 Inspect.334;
let Inspect.234 : Int1 = StructAtIndex 1 Inspect.334;
joinpoint Inspect.349 Inspect.237:
let Inspect.346 : Str = CallByName Inspect.61 Inspect.237 Inspect.235;
let Inspect.347 : Str = ": ";
let Inspect.340 : Str = CallByName Inspect.61 Inspect.346 Inspect.347;
let Inspect.337 : Str = CallByName Inspect.238 Inspect.340 Inspect.236;
let Inspect.338 : {} = Struct {};
let Inspect.336 : {Str, Int1} = CallByName Inspect.240 Inspect.337;
ret Inspect.336;
in
if Inspect.234 then
let Inspect.350 : Str = ", ";
let Inspect.348 : Str = CallByName Inspect.61 Inspect.233 Inspect.350;
jump Inspect.349 Inspect.348;
else
jump Inspect.349 Inspect.233;
procedure Inspect.238 (Inspect.239, Inspect.236):
let Inspect.343 : Str = CallByName Inspect.31 Inspect.236 Inspect.239;
ret Inspect.343;
procedure Inspect.240 (Inspect.241):
let Bool.2 : Int1 = CallByName Bool.2;
let Inspect.339 : {Str, Int1} = Struct {Inspect.241, Bool.2};
ret Inspect.339;
procedure Inspect.242 (Inspect.326):
let Inspect.327 : Str = StructAtIndex 0 Inspect.326;
ret Inspect.327;
procedure Inspect.277 (Inspect.278, #Attr.12):
let Inspect.364 : I64 = UnionAtIndex (Id 0) (Index 0) #Attr.12;
let Inspect.363 : Str = CallByName Num.96 Inspect.364;
let Inspect.362 : Str = CallByName Inspect.61 Inspect.278 Inspect.363;
ret Inspect.362;
procedure Inspect.295 (Inspect.296, #Attr.12):
let Inspect.358 : Decimal = UnionAtIndex (Id 1) (Index 0) #Attr.12;
let Inspect.357 : Str = CallByName Num.96 Inspect.358;
let Inspect.356 : Str = CallByName Inspect.61 Inspect.296 Inspect.357;
ret Inspect.356;
procedure Inspect.30 (Inspect.147):
ret Inspect.147;
procedure Inspect.30 (Inspect.147):
ret Inspect.147;
procedure Inspect.30 (Inspect.147):
ret Inspect.147;
procedure Inspect.31 (Inspect.305, Inspect.149):
let Inspect.314 : Str = CallByName Inspect.228 Inspect.149 Inspect.305;
ret Inspect.314;
procedure Inspect.31 (Inspect.305, Inspect.149):
let Inspect.345 : U8 = GetTagId Inspect.305;
switch Inspect.345:
case 0:
let Inspect.344 : Str = CallByName Inspect.277 Inspect.149 Inspect.305;
ret Inspect.344;
default:
let Inspect.344 : Str = CallByName Inspect.295 Inspect.149 Inspect.305;
ret Inspect.344;
procedure Inspect.35 (Inspect.300):
ret Inspect.300;
procedure Inspect.36 (Inspect.304):
let Inspect.311 : Str = "";
ret Inspect.311;
procedure Inspect.42 (Inspect.227):
let Inspect.315 : List {[C I64, C Decimal], Str} = CallByName Inspect.30 Inspect.227;
ret Inspect.315;
procedure Inspect.5 (Inspect.150):
let Inspect.312 : {Decimal, I64} = CallByName #Derived.0 Inspect.150;
let Inspect.309 : {} = Struct {};
let Inspect.308 : Str = CallByName Inspect.36 Inspect.309;
let Inspect.307 : Str = CallByName #Derived.2 Inspect.308 Inspect.312;
ret Inspect.307;
procedure Inspect.54 (Inspect.276):
let Inspect.360 : [C I64, C Decimal] = TagId(0) Inspect.276;
let Inspect.359 : [C I64, C Decimal] = CallByName Inspect.30 Inspect.360;
ret Inspect.359;
procedure Inspect.60 (Inspect.294):
let Inspect.353 : [C I64, C Decimal] = TagId(1) Inspect.294;
let Inspect.352 : [C I64, C Decimal] = CallByName Inspect.30 Inspect.353;
ret Inspect.352;
procedure Inspect.61 (Inspect.303, Inspect.298):
let Inspect.323 : Str = CallByName Str.3 Inspect.303 Inspect.298;
dec Inspect.298;
ret Inspect.323;
procedure List.18 (List.154, List.155, List.156):
let List.554 : U64 = 0i64;
let List.555 : U64 = CallByName List.6 List.154;
let List.553 : {Str, Int1} = CallByName List.88 List.154 List.155 List.156 List.554 List.555;
ret List.553;
procedure List.6 (#Attr.2):
let List.564 : U64 = lowlevel ListLen #Attr.2;
ret List.564;
procedure List.66 (#Attr.2, #Attr.3):
let List.563 : {[C I64, C Decimal], Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3;
ret List.563;
procedure List.88 (#Derived_gen.14, #Derived_gen.15, #Derived_gen.16, #Derived_gen.17, #Derived_gen.18):
joinpoint List.556 List.157 List.158 List.159 List.160 List.161:
let List.558 : Int1 = CallByName Num.22 List.160 List.161;
if List.558 then
let List.562 : {[C I64, C Decimal], Str} = CallByName List.66 List.157 List.160;
inc List.562;
let List.162 : {Str, Int1} = CallByName Inspect.232 List.158 List.562;
let List.561 : U64 = 1i64;
let List.560 : U64 = CallByName Num.51 List.160 List.561;
jump List.556 List.157 List.162 List.159 List.560 List.161;
else
dec List.157;
ret List.158;
in
jump List.556 #Derived_gen.14 #Derived_gen.15 #Derived_gen.16 #Derived_gen.17 #Derived_gen.18;
procedure Num.22 (#Attr.2, #Attr.3):
let Num.294 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;
ret Num.294;
procedure Num.51 (#Attr.2, #Attr.3):
let Num.293 : U64 = lowlevel NumAddWrap #Attr.2 #Attr.3;
ret Num.293;
procedure Num.96 (#Attr.2):
let Num.291 : Str = lowlevel NumToStr #Attr.2;
ret Num.291;
procedure Num.96 (#Attr.2):
let Num.292 : Str = lowlevel NumToStr #Attr.2;
ret Num.292;
procedure Str.3 (#Attr.2, #Attr.3):
let Str.292 : Str = lowlevel StrConcat #Attr.2 #Attr.3;
ret Str.292;
procedure Test.0 ():
let Test.4 : Decimal = 3dec;
let Test.5 : I64 = 7i64;
let Test.3 : {Decimal, I64} = Struct {Test.4, Test.5};
let Test.2 : Str = CallByName Inspect.5 Test.3;
let Test.1 : Str = CallByName Inspect.35 Test.2;
ret Test.1;

View File

@ -0,0 +1,171 @@
procedure #Derived.0 (#Derived.1):
let #Derived_gen.0 : Str = CallByName Inspect.30 #Derived.1;
ret #Derived_gen.0;
procedure #Derived.2 (#Derived.3, #Derived.1):
let #Derived_gen.7 : Str = "a";
let #Derived_gen.8 : Str = CallByName Inspect.44 #Derived.1;
let #Derived_gen.6 : {Str, Str} = Struct {#Derived_gen.7, #Derived_gen.8};
let #Derived_gen.5 : List {Str, Str} = Array [#Derived_gen.6];
let #Derived_gen.4 : List {Str, Str} = CallByName Inspect.42 #Derived_gen.5;
let #Derived_gen.3 : Str = CallByName Inspect.31 #Derived_gen.4 #Derived.3;
ret #Derived_gen.3;
procedure Bool.1 ():
let Bool.24 : Int1 = false;
ret Bool.24;
procedure Bool.2 ():
let Bool.23 : Int1 = true;
ret Bool.23;
procedure Inspect.228 (Inspect.229, Inspect.227):
let Inspect.350 : Str = "{";
let Inspect.328 : Str = CallByName Inspect.61 Inspect.229 Inspect.350;
let Inspect.324 : {Str, Int1} = CallByName Inspect.230 Inspect.328 Inspect.227;
let Inspect.325 : {} = Struct {};
let Inspect.320 : Str = CallByName Inspect.242 Inspect.324;
let Inspect.321 : Str = "}";
let Inspect.319 : Str = CallByName Inspect.61 Inspect.320 Inspect.321;
ret Inspect.319;
procedure Inspect.230 (Inspect.231, Inspect.227):
let Bool.1 : Int1 = CallByName Bool.1;
let Inspect.332 : {Str, Int1} = Struct {Inspect.231, Bool.1};
let Inspect.333 : {} = Struct {};
let Inspect.331 : {Str, Int1} = CallByName List.18 Inspect.227 Inspect.332 Inspect.333;
ret Inspect.331;
procedure Inspect.232 (Inspect.334, Inspect.335):
let Inspect.235 : Str = StructAtIndex 0 Inspect.335;
let Inspect.236 : Str = StructAtIndex 1 Inspect.335;
let Inspect.233 : Str = StructAtIndex 0 Inspect.334;
let Inspect.234 : Int1 = StructAtIndex 1 Inspect.334;
joinpoint Inspect.348 Inspect.237:
let Inspect.345 : Str = CallByName Inspect.61 Inspect.237 Inspect.235;
let Inspect.346 : Str = ": ";
let Inspect.340 : Str = CallByName Inspect.61 Inspect.345 Inspect.346;
let Inspect.337 : Str = CallByName Inspect.238 Inspect.340 Inspect.236;
let Inspect.338 : {} = Struct {};
let Inspect.336 : {Str, Int1} = CallByName Inspect.240 Inspect.337;
ret Inspect.336;
in
if Inspect.234 then
let Inspect.349 : Str = ", ";
let Inspect.347 : Str = CallByName Inspect.61 Inspect.233 Inspect.349;
jump Inspect.348 Inspect.347;
else
jump Inspect.348 Inspect.233;
procedure Inspect.238 (Inspect.239, Inspect.236):
let Inspect.343 : Str = CallByName Inspect.31 Inspect.236 Inspect.239;
ret Inspect.343;
procedure Inspect.240 (Inspect.241):
let Bool.2 : Int1 = CallByName Bool.2;
let Inspect.339 : {Str, Int1} = Struct {Inspect.241, Bool.2};
ret Inspect.339;
procedure Inspect.242 (Inspect.326):
let Inspect.327 : Str = StructAtIndex 0 Inspect.326;
ret Inspect.327;
procedure Inspect.249 (Inspect.250, Inspect.248):
let Inspect.359 : Str = "\"";
let Inspect.358 : Str = CallByName Inspect.61 Inspect.250 Inspect.359;
let Inspect.356 : Str = CallByName Inspect.61 Inspect.358 Inspect.248;
let Inspect.357 : Str = "\"";
let Inspect.355 : Str = CallByName Inspect.61 Inspect.356 Inspect.357;
ret Inspect.355;
procedure Inspect.30 (Inspect.147):
ret Inspect.147;
procedure Inspect.30 (Inspect.147):
ret Inspect.147;
procedure Inspect.30 (Inspect.147):
ret Inspect.147;
procedure Inspect.31 (Inspect.305, Inspect.149):
let Inspect.314 : Str = CallByName Inspect.228 Inspect.149 Inspect.305;
ret Inspect.314;
procedure Inspect.31 (Inspect.305, Inspect.149):
let Inspect.344 : Str = CallByName Inspect.249 Inspect.149 Inspect.305;
ret Inspect.344;
procedure Inspect.35 (Inspect.300):
ret Inspect.300;
procedure Inspect.36 (Inspect.304):
let Inspect.311 : Str = "";
ret Inspect.311;
procedure Inspect.42 (Inspect.227):
let Inspect.315 : List {Str, Str} = CallByName Inspect.30 Inspect.227;
ret Inspect.315;
procedure Inspect.44 (Inspect.248):
let Inspect.351 : Str = CallByName Inspect.30 Inspect.248;
ret Inspect.351;
procedure Inspect.5 (Inspect.150):
let Inspect.312 : Str = CallByName #Derived.0 Inspect.150;
let Inspect.309 : {} = Struct {};
let Inspect.308 : Str = CallByName Inspect.36 Inspect.309;
let Inspect.307 : Str = CallByName #Derived.2 Inspect.308 Inspect.312;
ret Inspect.307;
procedure Inspect.61 (Inspect.303, Inspect.298):
let Inspect.323 : Str = CallByName Str.3 Inspect.303 Inspect.298;
dec Inspect.298;
ret Inspect.323;
procedure List.18 (List.154, List.155, List.156):
let List.554 : U64 = 0i64;
let List.555 : U64 = CallByName List.6 List.154;
let List.553 : {Str, Int1} = CallByName List.88 List.154 List.155 List.156 List.554 List.555;
ret List.553;
procedure List.6 (#Attr.2):
let List.564 : U64 = lowlevel ListLen #Attr.2;
ret List.564;
procedure List.66 (#Attr.2, #Attr.3):
let List.563 : {Str, Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3;
ret List.563;
procedure List.88 (#Derived_gen.14, #Derived_gen.15, #Derived_gen.16, #Derived_gen.17, #Derived_gen.18):
joinpoint List.556 List.157 List.158 List.159 List.160 List.161:
let List.558 : Int1 = CallByName Num.22 List.160 List.161;
if List.558 then
let List.562 : {Str, Str} = CallByName List.66 List.157 List.160;
inc List.562;
let List.162 : {Str, Int1} = CallByName Inspect.232 List.158 List.562;
let List.561 : U64 = 1i64;
let List.560 : U64 = CallByName Num.51 List.160 List.561;
jump List.556 List.157 List.162 List.159 List.560 List.161;
else
dec List.157;
ret List.158;
in
jump List.556 #Derived_gen.14 #Derived_gen.15 #Derived_gen.16 #Derived_gen.17 #Derived_gen.18;
procedure Num.22 (#Attr.2, #Attr.3):
let Num.292 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;
ret Num.292;
procedure Num.51 (#Attr.2, #Attr.3):
let Num.291 : U64 = lowlevel NumAddWrap #Attr.2 #Attr.3;
ret Num.291;
procedure Str.3 (#Attr.2, #Attr.3):
let Str.292 : Str = lowlevel StrConcat #Attr.2 #Attr.3;
ret Str.292;
procedure Test.0 ():
let Test.4 : Str = "foo";
let Test.2 : Str = CallByName Inspect.5 Test.4;
let Test.1 : Str = CallByName Inspect.35 Test.2;
ret Test.1;

View File

@ -0,0 +1,180 @@
procedure #Derived.0 (#Derived.1):
let #Derived_gen.0 : {Str, Str} = CallByName Inspect.30 #Derived.1;
ret #Derived_gen.0;
procedure #Derived.2 (#Derived.3, #Derived.1):
let #Derived_gen.11 : Str = "a";
let #Derived_gen.13 : Str = StructAtIndex 0 #Derived.1;
inc #Derived_gen.13;
let #Derived_gen.12 : Str = CallByName Inspect.44 #Derived_gen.13;
let #Derived_gen.6 : {Str, Str} = Struct {#Derived_gen.11, #Derived_gen.12};
let #Derived_gen.8 : Str = "b";
let #Derived_gen.10 : Str = StructAtIndex 1 #Derived.1;
dec #Derived_gen.13;
let #Derived_gen.9 : Str = CallByName Inspect.44 #Derived_gen.10;
let #Derived_gen.7 : {Str, Str} = Struct {#Derived_gen.8, #Derived_gen.9};
let #Derived_gen.5 : List {Str, Str} = Array [#Derived_gen.6, #Derived_gen.7];
let #Derived_gen.4 : List {Str, Str} = CallByName Inspect.42 #Derived_gen.5;
let #Derived_gen.3 : Str = CallByName Inspect.31 #Derived_gen.4 #Derived.3;
ret #Derived_gen.3;
procedure Bool.1 ():
let Bool.24 : Int1 = false;
ret Bool.24;
procedure Bool.2 ():
let Bool.23 : Int1 = true;
ret Bool.23;
procedure Inspect.228 (Inspect.229, Inspect.227):
let Inspect.350 : Str = "{";
let Inspect.328 : Str = CallByName Inspect.61 Inspect.229 Inspect.350;
let Inspect.324 : {Str, Int1} = CallByName Inspect.230 Inspect.328 Inspect.227;
let Inspect.325 : {} = Struct {};
let Inspect.320 : Str = CallByName Inspect.242 Inspect.324;
let Inspect.321 : Str = "}";
let Inspect.319 : Str = CallByName Inspect.61 Inspect.320 Inspect.321;
ret Inspect.319;
procedure Inspect.230 (Inspect.231, Inspect.227):
let Bool.1 : Int1 = CallByName Bool.1;
let Inspect.332 : {Str, Int1} = Struct {Inspect.231, Bool.1};
let Inspect.333 : {} = Struct {};
let Inspect.331 : {Str, Int1} = CallByName List.18 Inspect.227 Inspect.332 Inspect.333;
ret Inspect.331;
procedure Inspect.232 (Inspect.334, Inspect.335):
let Inspect.235 : Str = StructAtIndex 0 Inspect.335;
let Inspect.236 : Str = StructAtIndex 1 Inspect.335;
let Inspect.233 : Str = StructAtIndex 0 Inspect.334;
let Inspect.234 : Int1 = StructAtIndex 1 Inspect.334;
joinpoint Inspect.348 Inspect.237:
let Inspect.345 : Str = CallByName Inspect.61 Inspect.237 Inspect.235;
let Inspect.346 : Str = ": ";
let Inspect.340 : Str = CallByName Inspect.61 Inspect.345 Inspect.346;
let Inspect.337 : Str = CallByName Inspect.238 Inspect.340 Inspect.236;
let Inspect.338 : {} = Struct {};
let Inspect.336 : {Str, Int1} = CallByName Inspect.240 Inspect.337;
ret Inspect.336;
in
if Inspect.234 then
let Inspect.349 : Str = ", ";
let Inspect.347 : Str = CallByName Inspect.61 Inspect.233 Inspect.349;
jump Inspect.348 Inspect.347;
else
jump Inspect.348 Inspect.233;
procedure Inspect.238 (Inspect.239, Inspect.236):
let Inspect.343 : Str = CallByName Inspect.31 Inspect.236 Inspect.239;
ret Inspect.343;
procedure Inspect.240 (Inspect.241):
let Bool.2 : Int1 = CallByName Bool.2;
let Inspect.339 : {Str, Int1} = Struct {Inspect.241, Bool.2};
ret Inspect.339;
procedure Inspect.242 (Inspect.326):
let Inspect.327 : Str = StructAtIndex 0 Inspect.326;
ret Inspect.327;
procedure Inspect.249 (Inspect.250, Inspect.248):
let Inspect.359 : Str = "\"";
let Inspect.358 : Str = CallByName Inspect.61 Inspect.250 Inspect.359;
let Inspect.356 : Str = CallByName Inspect.61 Inspect.358 Inspect.248;
let Inspect.357 : Str = "\"";
let Inspect.355 : Str = CallByName Inspect.61 Inspect.356 Inspect.357;
ret Inspect.355;
procedure Inspect.30 (Inspect.147):
ret Inspect.147;
procedure Inspect.30 (Inspect.147):
ret Inspect.147;
procedure Inspect.30 (Inspect.147):
ret Inspect.147;
procedure Inspect.31 (Inspect.305, Inspect.149):
let Inspect.314 : Str = CallByName Inspect.228 Inspect.149 Inspect.305;
ret Inspect.314;
procedure Inspect.31 (Inspect.305, Inspect.149):
let Inspect.344 : Str = CallByName Inspect.249 Inspect.149 Inspect.305;
ret Inspect.344;
procedure Inspect.35 (Inspect.300):
ret Inspect.300;
procedure Inspect.36 (Inspect.304):
let Inspect.311 : Str = "";
ret Inspect.311;
procedure Inspect.42 (Inspect.227):
let Inspect.315 : List {Str, Str} = CallByName Inspect.30 Inspect.227;
ret Inspect.315;
procedure Inspect.44 (Inspect.248):
let Inspect.360 : Str = CallByName Inspect.30 Inspect.248;
ret Inspect.360;
procedure Inspect.5 (Inspect.150):
let Inspect.312 : {Str, Str} = CallByName #Derived.0 Inspect.150;
let Inspect.309 : {} = Struct {};
let Inspect.308 : Str = CallByName Inspect.36 Inspect.309;
let Inspect.307 : Str = CallByName #Derived.2 Inspect.308 Inspect.312;
ret Inspect.307;
procedure Inspect.61 (Inspect.303, Inspect.298):
let Inspect.323 : Str = CallByName Str.3 Inspect.303 Inspect.298;
dec Inspect.298;
ret Inspect.323;
procedure List.18 (List.154, List.155, List.156):
let List.554 : U64 = 0i64;
let List.555 : U64 = CallByName List.6 List.154;
let List.553 : {Str, Int1} = CallByName List.88 List.154 List.155 List.156 List.554 List.555;
ret List.553;
procedure List.6 (#Attr.2):
let List.564 : U64 = lowlevel ListLen #Attr.2;
ret List.564;
procedure List.66 (#Attr.2, #Attr.3):
let List.563 : {Str, Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3;
ret List.563;
procedure List.88 (#Derived_gen.18, #Derived_gen.19, #Derived_gen.20, #Derived_gen.21, #Derived_gen.22):
joinpoint List.556 List.157 List.158 List.159 List.160 List.161:
let List.558 : Int1 = CallByName Num.22 List.160 List.161;
if List.558 then
let List.562 : {Str, Str} = CallByName List.66 List.157 List.160;
inc List.562;
let List.162 : {Str, Int1} = CallByName Inspect.232 List.158 List.562;
let List.561 : U64 = 1i64;
let List.560 : U64 = CallByName Num.51 List.160 List.561;
jump List.556 List.157 List.162 List.159 List.560 List.161;
else
dec List.157;
ret List.158;
in
jump List.556 #Derived_gen.18 #Derived_gen.19 #Derived_gen.20 #Derived_gen.21 #Derived_gen.22;
procedure Num.22 (#Attr.2, #Attr.3):
let Num.292 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;
ret Num.292;
procedure Num.51 (#Attr.2, #Attr.3):
let Num.291 : U64 = lowlevel NumAddWrap #Attr.2 #Attr.3;
ret Num.291;
procedure Str.3 (#Attr.2, #Attr.3):
let Str.292 : Str = lowlevel StrConcat #Attr.2 #Attr.3;
ret Str.292;
procedure Test.0 ():
let Test.4 : Str = "foo";
let Test.5 : Str = "bar";
let Test.3 : {Str, Str} = Struct {Test.4, Test.5};
let Test.2 : Str = CallByName Inspect.5 Test.3;
let Test.1 : Str = CallByName Inspect.35 Test.2;
ret Test.1;

View File

@ -0,0 +1,43 @@
procedure Inspect.249 (Inspect.250, Inspect.248):
let Inspect.323 : Str = "\"";
let Inspect.322 : Str = CallByName Inspect.61 Inspect.250 Inspect.323;
let Inspect.318 : Str = CallByName Inspect.61 Inspect.322 Inspect.248;
let Inspect.319 : Str = "\"";
let Inspect.317 : Str = CallByName Inspect.61 Inspect.318 Inspect.319;
ret Inspect.317;
procedure Inspect.30 (Inspect.147):
ret Inspect.147;
procedure Inspect.35 (Inspect.300):
ret Inspect.300;
procedure Inspect.36 (Inspect.304):
let Inspect.311 : Str = "";
ret Inspect.311;
procedure Inspect.44 (Inspect.248):
let Inspect.313 : Str = CallByName Inspect.30 Inspect.248;
ret Inspect.313;
procedure Inspect.5 (Inspect.150):
let Inspect.312 : Str = CallByName Inspect.44 Inspect.150;
let Inspect.309 : {} = Struct {};
let Inspect.308 : Str = CallByName Inspect.36 Inspect.309;
let Inspect.307 : Str = CallByName Inspect.249 Inspect.308 Inspect.312;
ret Inspect.307;
procedure Inspect.61 (Inspect.303, Inspect.298):
let Inspect.321 : Str = CallByName Str.3 Inspect.303 Inspect.298;
dec Inspect.298;
ret Inspect.321;
procedure Str.3 (#Attr.2, #Attr.3):
let Str.292 : Str = lowlevel StrConcat #Attr.2 #Attr.3;
ret Str.292;
procedure Test.0 ():
let Test.3 : Str = "abc";
let Test.2 : Str = CallByName Inspect.5 Test.3;
let Test.1 : Str = CallByName Inspect.35 Test.2;
ret Test.1;

View File

@ -0,0 +1,173 @@
procedure #Derived.0 (#Derived.1):
let #Derived_gen.0 : Str = CallByName Inspect.30 #Derived.1;
ret #Derived_gen.0;
procedure #Derived.3 (#Derived.4, #Derived.1):
joinpoint #Derived_gen.5 #Derived_gen.4:
let #Derived_gen.3 : Str = CallByName Inspect.31 #Derived_gen.4 #Derived.4;
ret #Derived_gen.3;
in
let #Derived_gen.7 : Str = "A";
let #Derived_gen.9 : Str = CallByName Inspect.44 #Derived.1;
let #Derived_gen.8 : List Str = Array [#Derived_gen.9];
let #Derived_gen.6 : [C Str, C Str List Str] = CallByName Inspect.40 #Derived_gen.7 #Derived_gen.8;
jump #Derived_gen.5 #Derived_gen.6;
procedure Bool.11 (#Attr.2, #Attr.3):
let Bool.23 : Int1 = lowlevel Eq #Attr.2 #Attr.3;
ret Bool.23;
procedure Inspect.203 (Inspect.204, #Attr.12):
let Inspect.346 : Str = UnionAtIndex (Id 0) (Index 0) #Attr.12;
let Inspect.345 : Str = CallByName Inspect.61 Inspect.204 Inspect.346;
ret Inspect.345;
procedure Inspect.205 (Inspect.206, #Attr.12):
let Inspect.340 : List Str = UnionAtIndex (Id 1) (Index 1) #Attr.12;
let Inspect.339 : Str = UnionAtIndex (Id 1) (Index 0) #Attr.12;
let Inspect.338 : Str = "(";
let Inspect.337 : Str = CallByName Inspect.61 Inspect.206 Inspect.338;
let Inspect.325 : Str = CallByName Inspect.61 Inspect.337 Inspect.339;
let Inspect.321 : Str = CallByName Inspect.207 Inspect.325 Inspect.340;
let Inspect.322 : Str = ")";
let Inspect.320 : Str = CallByName Inspect.61 Inspect.321 Inspect.322;
ret Inspect.320;
procedure Inspect.207 (Inspect.208, Inspect.202):
let Inspect.329 : {} = Struct {};
let Inspect.328 : Str = CallByName List.18 Inspect.202 Inspect.208 Inspect.329;
ret Inspect.328;
procedure Inspect.209 (Inspect.210, Inspect.211):
let Inspect.336 : Str = " ";
let Inspect.331 : Str = CallByName Inspect.61 Inspect.210 Inspect.336;
let Inspect.330 : Str = CallByName Inspect.212 Inspect.331 Inspect.211;
ret Inspect.330;
procedure Inspect.212 (Inspect.213, Inspect.211):
let Inspect.334 : Str = CallByName Inspect.31 Inspect.211 Inspect.213;
ret Inspect.334;
procedure Inspect.249 (Inspect.250, Inspect.248):
let Inspect.355 : Str = "\"";
let Inspect.354 : Str = CallByName Inspect.61 Inspect.250 Inspect.355;
let Inspect.352 : Str = CallByName Inspect.61 Inspect.354 Inspect.248;
let Inspect.353 : Str = "\"";
let Inspect.351 : Str = CallByName Inspect.61 Inspect.352 Inspect.353;
ret Inspect.351;
procedure Inspect.30 (Inspect.147):
ret Inspect.147;
procedure Inspect.30 (Inspect.147):
ret Inspect.147;
procedure Inspect.30 (Inspect.147):
ret Inspect.147;
procedure Inspect.31 (Inspect.305, Inspect.149):
let Inspect.315 : U8 = GetTagId Inspect.305;
switch Inspect.315:
case 0:
let Inspect.314 : Str = CallByName Inspect.203 Inspect.149 Inspect.305;
ret Inspect.314;
default:
let Inspect.314 : Str = CallByName Inspect.205 Inspect.149 Inspect.305;
ret Inspect.314;
procedure Inspect.31 (Inspect.305, Inspect.149):
let Inspect.335 : Str = CallByName Inspect.249 Inspect.149 Inspect.305;
ret Inspect.335;
procedure Inspect.35 (Inspect.300):
ret Inspect.300;
procedure Inspect.36 (Inspect.304):
let Inspect.311 : Str = "";
ret Inspect.311;
procedure Inspect.40 (Inspect.201, Inspect.202):
inc Inspect.202;
let Inspect.341 : Int1 = CallByName List.1 Inspect.202;
if Inspect.341 then
dec Inspect.202;
let Inspect.343 : [C Str, C Str List Str] = TagId(0) Inspect.201;
let Inspect.342 : [C Str, C Str List Str] = CallByName Inspect.30 Inspect.343;
ret Inspect.342;
else
let Inspect.317 : [C Str, C Str List Str] = TagId(1) Inspect.201 Inspect.202;
let Inspect.316 : [C Str, C Str List Str] = CallByName Inspect.30 Inspect.317;
ret Inspect.316;
procedure Inspect.44 (Inspect.248):
let Inspect.347 : Str = CallByName Inspect.30 Inspect.248;
ret Inspect.347;
procedure Inspect.5 (Inspect.150):
let Inspect.312 : Str = CallByName #Derived.0 Inspect.150;
let Inspect.309 : {} = Struct {};
let Inspect.308 : Str = CallByName Inspect.36 Inspect.309;
let Inspect.307 : Str = CallByName #Derived.3 Inspect.308 Inspect.312;
ret Inspect.307;
procedure Inspect.61 (Inspect.303, Inspect.298):
let Inspect.324 : Str = CallByName Str.3 Inspect.303 Inspect.298;
dec Inspect.298;
ret Inspect.324;
procedure List.1 (List.102):
let List.566 : U64 = CallByName List.6 List.102;
dec List.102;
let List.567 : U64 = 0i64;
let List.565 : Int1 = CallByName Bool.11 List.566 List.567;
ret List.565;
procedure List.18 (List.154, List.155, List.156):
let List.554 : U64 = 0i64;
let List.555 : U64 = CallByName List.6 List.154;
let List.553 : Str = CallByName List.88 List.154 List.155 List.156 List.554 List.555;
ret List.553;
procedure List.6 (#Attr.2):
let List.564 : U64 = lowlevel ListLen #Attr.2;
ret List.564;
procedure List.66 (#Attr.2, #Attr.3):
let List.563 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3;
ret List.563;
procedure List.88 (#Derived_gen.18, #Derived_gen.19, #Derived_gen.20, #Derived_gen.21, #Derived_gen.22):
joinpoint List.556 List.157 List.158 List.159 List.160 List.161:
let List.558 : Int1 = CallByName Num.22 List.160 List.161;
if List.558 then
let List.562 : Str = CallByName List.66 List.157 List.160;
inc List.562;
let List.162 : Str = CallByName Inspect.209 List.158 List.562;
let List.561 : U64 = 1i64;
let List.560 : U64 = CallByName Num.51 List.160 List.561;
jump List.556 List.157 List.162 List.159 List.560 List.161;
else
dec List.157;
ret List.158;
in
jump List.556 #Derived_gen.18 #Derived_gen.19 #Derived_gen.20 #Derived_gen.21 #Derived_gen.22;
procedure Num.22 (#Attr.2, #Attr.3):
let Num.292 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;
ret Num.292;
procedure Num.51 (#Attr.2, #Attr.3):
let Num.291 : U64 = lowlevel NumAddWrap #Attr.2 #Attr.3;
ret Num.291;
procedure Str.3 (#Attr.2, #Attr.3):
let Str.292 : Str = lowlevel StrConcat #Attr.2 #Attr.3;
ret Str.292;
procedure Test.0 ():
let Test.5 : Str = "foo";
let Test.4 : Str = CallByName Inspect.5 Test.5;
let Test.3 : Str = CallByName Inspect.35 Test.4;
ret Test.3;

View File

@ -0,0 +1,178 @@
procedure #Derived.0 (#Derived.1):
let #Derived_gen.0 : {Str, Str} = CallByName Inspect.30 #Derived.1;
ret #Derived_gen.0;
procedure #Derived.4 (#Derived.5, #Derived.1):
joinpoint #Derived_gen.5 #Derived_gen.4:
let #Derived_gen.3 : Str = CallByName Inspect.31 #Derived_gen.4 #Derived.5;
ret #Derived_gen.3;
in
let #Derived.2 : Str = StructAtIndex 0 #Derived.1;
let #Derived.3 : Str = StructAtIndex 1 #Derived.1;
let #Derived_gen.7 : Str = "A";
let #Derived_gen.9 : Str = CallByName Inspect.44 #Derived.2;
let #Derived_gen.10 : Str = CallByName Inspect.44 #Derived.3;
let #Derived_gen.8 : List Str = Array [#Derived_gen.9, #Derived_gen.10];
let #Derived_gen.6 : [C Str, C Str List Str] = CallByName Inspect.40 #Derived_gen.7 #Derived_gen.8;
jump #Derived_gen.5 #Derived_gen.6;
procedure Bool.11 (#Attr.2, #Attr.3):
let Bool.23 : Int1 = lowlevel Eq #Attr.2 #Attr.3;
ret Bool.23;
procedure Inspect.203 (Inspect.204, #Attr.12):
let Inspect.346 : Str = UnionAtIndex (Id 0) (Index 0) #Attr.12;
let Inspect.345 : Str = CallByName Inspect.61 Inspect.204 Inspect.346;
ret Inspect.345;
procedure Inspect.205 (Inspect.206, #Attr.12):
let Inspect.340 : List Str = UnionAtIndex (Id 1) (Index 1) #Attr.12;
let Inspect.339 : Str = UnionAtIndex (Id 1) (Index 0) #Attr.12;
let Inspect.338 : Str = "(";
let Inspect.337 : Str = CallByName Inspect.61 Inspect.206 Inspect.338;
let Inspect.325 : Str = CallByName Inspect.61 Inspect.337 Inspect.339;
let Inspect.321 : Str = CallByName Inspect.207 Inspect.325 Inspect.340;
let Inspect.322 : Str = ")";
let Inspect.320 : Str = CallByName Inspect.61 Inspect.321 Inspect.322;
ret Inspect.320;
procedure Inspect.207 (Inspect.208, Inspect.202):
let Inspect.329 : {} = Struct {};
let Inspect.328 : Str = CallByName List.18 Inspect.202 Inspect.208 Inspect.329;
ret Inspect.328;
procedure Inspect.209 (Inspect.210, Inspect.211):
let Inspect.336 : Str = " ";
let Inspect.331 : Str = CallByName Inspect.61 Inspect.210 Inspect.336;
let Inspect.330 : Str = CallByName Inspect.212 Inspect.331 Inspect.211;
ret Inspect.330;
procedure Inspect.212 (Inspect.213, Inspect.211):
let Inspect.334 : Str = CallByName Inspect.31 Inspect.211 Inspect.213;
ret Inspect.334;
procedure Inspect.249 (Inspect.250, Inspect.248):
let Inspect.355 : Str = "\"";
let Inspect.354 : Str = CallByName Inspect.61 Inspect.250 Inspect.355;
let Inspect.352 : Str = CallByName Inspect.61 Inspect.354 Inspect.248;
let Inspect.353 : Str = "\"";
let Inspect.351 : Str = CallByName Inspect.61 Inspect.352 Inspect.353;
ret Inspect.351;
procedure Inspect.30 (Inspect.147):
ret Inspect.147;
procedure Inspect.30 (Inspect.147):
ret Inspect.147;
procedure Inspect.30 (Inspect.147):
ret Inspect.147;
procedure Inspect.31 (Inspect.305, Inspect.149):
let Inspect.315 : U8 = GetTagId Inspect.305;
switch Inspect.315:
case 0:
let Inspect.314 : Str = CallByName Inspect.203 Inspect.149 Inspect.305;
ret Inspect.314;
default:
let Inspect.314 : Str = CallByName Inspect.205 Inspect.149 Inspect.305;
ret Inspect.314;
procedure Inspect.31 (Inspect.305, Inspect.149):
let Inspect.335 : Str = CallByName Inspect.249 Inspect.149 Inspect.305;
ret Inspect.335;
procedure Inspect.35 (Inspect.300):
ret Inspect.300;
procedure Inspect.36 (Inspect.304):
let Inspect.311 : Str = "";
ret Inspect.311;
procedure Inspect.40 (Inspect.201, Inspect.202):
inc Inspect.202;
let Inspect.341 : Int1 = CallByName List.1 Inspect.202;
if Inspect.341 then
dec Inspect.202;
let Inspect.343 : [C Str, C Str List Str] = TagId(0) Inspect.201;
let Inspect.342 : [C Str, C Str List Str] = CallByName Inspect.30 Inspect.343;
ret Inspect.342;
else
let Inspect.317 : [C Str, C Str List Str] = TagId(1) Inspect.201 Inspect.202;
let Inspect.316 : [C Str, C Str List Str] = CallByName Inspect.30 Inspect.317;
ret Inspect.316;
procedure Inspect.44 (Inspect.248):
let Inspect.356 : Str = CallByName Inspect.30 Inspect.248;
ret Inspect.356;
procedure Inspect.5 (Inspect.150):
let Inspect.312 : {Str, Str} = CallByName #Derived.0 Inspect.150;
let Inspect.309 : {} = Struct {};
let Inspect.308 : Str = CallByName Inspect.36 Inspect.309;
let Inspect.307 : Str = CallByName #Derived.4 Inspect.308 Inspect.312;
ret Inspect.307;
procedure Inspect.61 (Inspect.303, Inspect.298):
let Inspect.324 : Str = CallByName Str.3 Inspect.303 Inspect.298;
dec Inspect.298;
ret Inspect.324;
procedure List.1 (List.102):
let List.566 : U64 = CallByName List.6 List.102;
dec List.102;
let List.567 : U64 = 0i64;
let List.565 : Int1 = CallByName Bool.11 List.566 List.567;
ret List.565;
procedure List.18 (List.154, List.155, List.156):
let List.554 : U64 = 0i64;
let List.555 : U64 = CallByName List.6 List.154;
let List.553 : Str = CallByName List.88 List.154 List.155 List.156 List.554 List.555;
ret List.553;
procedure List.6 (#Attr.2):
let List.564 : U64 = lowlevel ListLen #Attr.2;
ret List.564;
procedure List.66 (#Attr.2, #Attr.3):
let List.563 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3;
ret List.563;
procedure List.88 (#Derived_gen.19, #Derived_gen.20, #Derived_gen.21, #Derived_gen.22, #Derived_gen.23):
joinpoint List.556 List.157 List.158 List.159 List.160 List.161:
let List.558 : Int1 = CallByName Num.22 List.160 List.161;
if List.558 then
let List.562 : Str = CallByName List.66 List.157 List.160;
inc List.562;
let List.162 : Str = CallByName Inspect.209 List.158 List.562;
let List.561 : U64 = 1i64;
let List.560 : U64 = CallByName Num.51 List.160 List.561;
jump List.556 List.157 List.162 List.159 List.560 List.161;
else
dec List.157;
ret List.158;
in
jump List.556 #Derived_gen.19 #Derived_gen.20 #Derived_gen.21 #Derived_gen.22 #Derived_gen.23;
procedure Num.22 (#Attr.2, #Attr.3):
let Num.292 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;
ret Num.292;
procedure Num.51 (#Attr.2, #Attr.3):
let Num.291 : U64 = lowlevel NumAddWrap #Attr.2 #Attr.3;
ret Num.291;
procedure Str.3 (#Attr.2, #Attr.3):
let Str.292 : Str = lowlevel StrConcat #Attr.2 #Attr.3;
ret Str.292;
procedure Test.0 ():
let Test.6 : Str = "foo";
let Test.5 : Str = "foo";
let Test.1 : {Str, Str} = Struct {Test.5, Test.6};
let Test.4 : Str = CallByName Inspect.5 Test.1;
let Test.3 : Str = CallByName Inspect.35 Test.4;
ret Test.3;

View File

@ -3289,3 +3289,150 @@ fn non_nullable_unwrapped_instead_of_nullable_wrapped() {
"#
)
}
#[mono_test]
#[ignore = "Hits an unimplemented for abilities, not sure why..."]
fn inspect_custom_type() {
indoc!(
r#"
app "test"
imports []
provides [main] to "./platform"
HelloWorld := {} implements [Inspect { toInspector: myToInspector }]
myToInspector : HelloWorld -> Inspector f where f implements InspectFormatter
myToInspector = \@HellowWorld {} ->
fmt <- Inspect.custom
Inspect.apply (Inspect.str "Hello, World!\n") fmt
main =
Inspect.inspect (@HelloWorld {})
"#
)
}
#[mono_test]
fn inspect_derived_string() {
indoc!(
r#"
app "test"
imports []
provides [main] to "./platform"
main = Inspect.inspect "abc" |> Inspect.toDbgStr
"#
)
}
#[mono_test]
fn inspect_derived_record() {
indoc!(
r#"
app "test"
imports []
provides [main] to "./platform"
main = Inspect.inspect {a: 7, b: 3dec} |> Inspect.toDbgStr
"#
)
}
#[mono_test]
fn inspect_derived_record_one_field_string() {
indoc!(
r#"
app "test"
imports []
provides [main] to "./platform"
main = Inspect.inspect {a: "foo"} |> Inspect.toDbgStr
"#
)
}
#[mono_test]
fn inspect_derived_record_two_field_strings() {
indoc!(
r#"
app "test"
imports []
provides [main] to "./platform"
main = Inspect.inspect {a: "foo", b: "bar"} |> Inspect.toDbgStr
"#
)
}
#[mono_test]
fn inspect_derived_nested_record_string() {
indoc!(
r#"
app "test"
imports []
provides [main] to "./platform"
main = Inspect.inspect {a: {b: "bar"}} |> Inspect.toDbgStr
"#
)
}
#[mono_test]
fn inspect_derived_tag_one_field_string() {
indoc!(
r#"
app "test"
imports []
provides [main] to "./platform"
main =
x : [A Str]
x = A "foo"
Inspect.inspect x |> Inspect.toDbgStr
"#
)
}
#[mono_test]
fn inspect_derived_tag_two_payloads_string() {
indoc!(
r#"
app "test"
imports []
provides [main] to "./platform"
main =
x : [A Str Str]
x = A "foo" "foo"
Inspect.inspect x |> Inspect.toDbgStr
"#
)
}
#[mono_test]
fn inspect_derived_list() {
indoc!(
r#"
app "test"
imports []
provides [main] to "./platform"
main = Inspect.inspect [1, 2, 3] |> Inspect.toDbgStr
"#
)
}
#[mono_test(large_stack = "true")]
fn inspect_derived_dict() {
indoc!(
r#"
app "test"
imports []
provides [main] to "./platform"
main =
Dict.fromList [("a", 1), ("b", 2)]
|> Inspect.inspect
|> Inspect.toDbgStr
"#
)
}

View File

@ -1726,6 +1726,8 @@ impl Subs {
pub const AB_HASH: SubsSlice<Symbol> = SubsSlice::new(3, 1);
#[rustfmt::skip]
pub const AB_EQ: SubsSlice<Symbol> = SubsSlice::new(4, 1);
#[rustfmt::skip]
pub const AB_INSPECT: SubsSlice<Symbol> = SubsSlice::new(5, 1);
// END INIT-SymbolSubsSlice
pub fn new() -> Self {
@ -1746,7 +1748,7 @@ impl Subs {
tag_names.push(TagName("OutOfBounds".into()));
// END INIT-TagNames
// IFTTT INIT-SymbolNames
// IFTTT INIT-SymbolSubsSlice
let mut symbol_names = Vec::with_capacity(32);
symbol_names.push(Symbol::ENCODE_ENCODING);
@ -1754,7 +1756,8 @@ impl Subs {
symbol_names.push(Symbol::HASH_HASHER);
symbol_names.push(Symbol::HASH_HASH_ABILITY);
symbol_names.push(Symbol::BOOL_EQ);
// END INIT-SymbolNames
symbol_names.push(Symbol::INSPECT_INSPECT_ABILITY);
// END INIT-SymbolSubsSlice
// IFTTT INIT-VariableSubsSlice
let variables = vec![Variable::STR];

View File

@ -0,0 +1,4 @@
app "test" provides [main] to "./platform"
main = Inspect.toInspector Bool.true |> Inspect.apply (Inspect.init {}) |> Inspect.toDbgStr
# ^^^^^^^^^^^^^^^^^^^ Inspect#Inspect.toInspector(32): Bool -[[Inspect.dbgBool(43)]]-> Inspector DbgFormatter

View File

@ -0,0 +1,4 @@
app "test" provides [main] to "./platform"
main = Inspect.toInspector 7dec |> Inspect.apply (Inspect.init {}) |> Inspect.toDbgStr
# ^^^^^^^^^^^^^^^^^^^ Inspect#Inspect.toInspector(32): Dec -[[Inspect.dbgDec(60)]]-> Inspector DbgFormatter

View File

@ -0,0 +1,6 @@
app "test" provides [main] to "./platform"
Op := {}
main = Inspect.toInspector (@Op {}) |> Inspect.apply (Inspect.init {}) |> Inspect.toDbgStr
# ^^^^^^^^^^^^^^^^^^^ Inspect#Inspect.toInspector(32): Op -[[Inspect.dbgOpaque(45)]]-> Inspector DbgFormatter

View File

@ -0,0 +1,9 @@
app "test" provides [main] to "./platform"
Op := U8 implements [Inspect { toInspector: myToInspector }]
myToInspector : Op -> Inspector f where f implements InspectFormatter
myToInspector = \@Op num -> Inspect.u8 num
main = Inspect.toInspector (@Op 1u8) |> Inspect.apply (Inspect.init {}) |> Inspect.toDbgStr
# ^^^^^^^^^^^^^^^^^^^ Op#Inspect.toInspector(2): Op -[[myToInspector(2)]]-> Inspector DbgFormatter

View File

@ -0,0 +1,6 @@
app "test" provides [main] to "./platform"
Op := U8 implements [Inspect]
main = Inspect.toInspector (@Op 1u8) |> Inspect.apply (Inspect.init {}) |> Inspect.toDbgStr
# ^^^^^^^^^^^^^^^^^^^ Op#Inspect.toInspector(3): Op -[[#Op_toInspector(3)]]-> Inspector DbgFormatter

View File

@ -0,0 +1,4 @@
app "test" provides [main] to "./platform"
main = Inspect.toInspector 7 |> Inspect.apply (Inspect.init {}) |> Inspect.toDbgStr
# ^^^^^^^^^^^^^^^^^^^ Inspect#Inspect.toInspector(32): I64 -[[Inspect.dbgI64(54)]]-> Inspector DbgFormatter

View File

@ -0,0 +1,4 @@
app "test" provides [main] to "./platform"
main = Inspect.toInspector { a: "" } |> Inspect.apply (Inspect.init {}) |> Inspect.toDbgStr
# ^^^^^^^^^^^^^^^^^^^ Inspect#Inspect.toInspector(32): { a : Str } -[[#Derived.toInspector_{a}(0)]]-> Inspector DbgFormatter

View File

@ -0,0 +1,9 @@
app "test" provides [main] to "./platform"
Op := U8 implements [Inspect { toInspector: myToInspector }]
myToInspector : Op -> Inspector f where f implements InspectFormatter
myToInspector = \@Op num -> Inspect.u8 num
main = Inspect.toInspector { op: @Op 1u8 } |> Inspect.apply (Inspect.init {}) |> Inspect.toDbgStr
# ^^^^^^^^^^^^^^^^^^^ Inspect#Inspect.toInspector(32): { op : Op } -[[#Derived.toInspector_{op}(0)]]-> Inspector DbgFormatter

View File

@ -0,0 +1,4 @@
app "test" provides [main] to "./platform"
main = Inspect.toInspector 7u8 |> Inspect.apply (Inspect.init {}) |> Inspect.toDbgStr
# ^^^^^^^^^^^^^^^^^^^ Inspect#Inspect.toInspector(32): U8 -[[Inspect.dbgU8(47)]]-> Inspector DbgFormatter

View File

@ -3,22 +3,22 @@
app "test" provides [main] to "./platform"
f = \{} ->
#^{-1} <1874><117>{} -<120>[[f(1)]]-> <116>[Ok <1882>{}]<80>*
#^{-1} <2858><117>{} -<120>[[f(1)]]-> <116>[Ok <2866>{}]<80>*
when g {} is
# ^ <1864><1882>{} -<1872>[[g(2)]]-> <72>[Ok <1882>{}]<102>*
# ^ <2848><2866>{} -<2856>[[g(2)]]-> <72>[Ok <2866>{}]<102>*
_ -> Ok {}
g = \{} ->
#^{-1} <1864><1882>{} -<1872>[[g(2)]]-> <72>[Ok <1882>{}]<102>*
#^{-1} <2848><2866>{} -<2856>[[g(2)]]-> <72>[Ok <2866>{}]<102>*
when h {} is
# ^ <1869><1882>{} -<1877>[[h(3)]]-> <94>[Ok <1882>{}]<124>*
# ^ <2853><2866>{} -<2861>[[h(3)]]-> <94>[Ok <2866>{}]<124>*
_ -> Ok {}
h = \{} ->
#^{-1} <1869><1882>{} -<1877>[[h(3)]]-> <94>[Ok <1882>{}]<124>*
#^{-1} <2853><2866>{} -<2861>[[h(3)]]-> <94>[Ok <2866>{}]<124>*
when f {} is
# ^ <1874><117>{} -<120>[[f(1)]]-> <116>[Ok <1882>{}]<80>*
# ^ <2858><117>{} -<120>[[f(1)]]-> <116>[Ok <2866>{}]<80>*
_ -> Ok {}
main = f {}
# ^ <1884><133>{} -<136>[[f(1)]]-> <138>[Ok <1882>{}]<1883>w_a
# ^ <2868><133>{} -<136>[[f(1)]]-> <138>[Ok <2866>{}]<2867>w_a

View File

@ -15,11 +15,7 @@ Community := {
people : List Person,
friends : List (Set Nat),
}
implements [
Inspect {
toInspector: inspectCommunity,
},
]
implements [Inspect]
Person := {
firstName : Str,
@ -28,11 +24,7 @@ Person := {
hasBeard : Bool,
favoriteColor : Color,
}
implements [
Inspect {
toInspector: inspectPerson,
},
]
implements [Inspect]
Color : [
Red,
@ -90,61 +82,3 @@ walkFriendNames = \@Community { people, friends }, s0, nextFn ->
(nextFn s1 personName friendNames, id + 1)
out
# The functions below will be auto-generated in the future
inspectCommunity : Community -> Inspector f where f implements InspectFormatter
inspectCommunity = \@Community { people, friends } ->
f0 <- Inspect.custom
[
{ key: "people", value: Inspect.list people List.walk Inspect.toInspector },
{
key: "friends",
value: Inspect.list
friends
List.walk
(\s -> Inspect.set
s
Set.walk
(\num -> num |> Num.toU64 |> Inspect.u64)
),
# value: Inspect.dict
# (@Community { people, friends })
# walkFriendNames
# Inspect.str
# (\s -> Inspect.set s Set.walk Inspect.str),
},
]
|> Inspect.record
|> Inspect.apply f0
inspectPerson : Person -> Inspector f where f implements InspectFormatter
inspectPerson = \@Person { firstName, lastName, age, hasBeard, favoriteColor } ->
# In practice, this would never be done manually due to autoderive.
# Instead you would just write:
# Inspect.inspect innerRecord
# This is what the auto-derive would generate.
f0 <- Inspect.custom
favoriteColorTag =
when favoriteColor is
Red ->
Inspect.tag "Red" []
Green ->
Inspect.tag "Green" []
Blue ->
Inspect.tag "Blue" []
RGB (r, g, b) ->
Inspect.tag "RGB" [Inspect.tuple [Inspect.u8 r, Inspect.u8 g, Inspect.u8 b]]
[
{ key: "firstName", value: Inspect.str firstName },
{ key: "lastName", value: Inspect.str lastName },
{ key: "age", value: Inspect.u8 age },
{ key: "hasBeard", value: Inspect.bool hasBeard },
{ key: "favoriteColor", value: favoriteColorTag },
]
|> Inspect.record
|> Inspect.apply f0

View File

@ -25,6 +25,7 @@ GuiFormatter := { nodes : List Elem }
record: record,
bool: bool,
str: str,
function: function,
opaque: opaque,
u8: u8,
i8: i8,
@ -36,6 +37,7 @@ GuiFormatter := { nodes : List Elem }
i64: i64,
u128: u128,
i128: i128,
nat: nat,
f32: f32,
f64: f64,
dec: dec,
@ -149,10 +151,15 @@ str = \s ->
f0 <- Inspect.custom
addNode f0 (Text "\"\(s)\"")
opaque : Str -> Inspector GuiFormatter
opaque = \s ->
opaque : * -> Inspector GuiFormatter
opaque = \_ ->
f0 <- Inspect.custom
addNode f0 (Text "<\(s)>")
addNode f0 (Text "<opaque>")
function : * -> Inspector GuiFormatter
function = \_ ->
f0 <- Inspect.custom
addNode f0 (Text "<function>")
u8 : U8 -> Inspector GuiFormatter
u8 = \num ->
@ -204,6 +211,11 @@ i128 = \num ->
f0 <- Inspect.custom
addNode f0 (num |> Num.toStr |> Text)
nat : Nat -> Inspector GuiFormatter
nat = \num ->
f0 <- Inspect.custom
addNode f0 (num |> Num.toStr |> Text)
f32 : F32 -> Inspector GuiFormatter
f32 = \num ->
f0 <- Inspect.custom

View File

@ -1,246 +0,0 @@
interface LogFormatter
exposes [
LogFormatter,
toStr,
]
imports []
## Creates String representations of Roc values, for use in inspect-logging.roc
LogFormatter := { data : Str }
implements [
InspectFormatter {
init: init,
list: list,
set: set,
dict: dict,
tag: tag,
tuple: tuple,
record: record,
bool: bool,
str: str,
opaque: opaque,
u8: u8,
i8: i8,
u16: u16,
i16: i16,
u32: u32,
i32: i32,
u64: u64,
i64: i64,
u128: u128,
i128: i128,
f32: f32,
f64: f64,
dec: dec,
},
]
init : {} -> LogFormatter
init = \{} -> @LogFormatter { data: "" }
list : list, ElemWalker (LogFormatter, Bool) list elem, (elem -> Inspector LogFormatter) -> Inspector LogFormatter
list = \content, walkFn, toInspector ->
f0 <- Inspect.custom
write f0 "["
|> \f1 ->
(f2, prependSep), elem <- walkFn content (f1, Bool.false)
f3 =
if prependSep then
write f2 ", "
else
f2
elem
|> toInspector
|> Inspect.apply f3
|> \f4 -> (f4, Bool.true)
|> .0
|> write "]"
set : set, ElemWalker (LogFormatter, Bool) set elem, (elem -> Inspector LogFormatter) -> Inspector LogFormatter
set = \content, walkFn, toInspector ->
f0 <- Inspect.custom
write f0 "{"
|> \f1 ->
(f2, prependSep), elem <- walkFn content (f1, Bool.false)
f3 =
if prependSep then
write f2 ", "
else
f2
elem
|> toInspector
|> Inspect.apply f3
|> \f4 -> (f4, Bool.true)
|> .0
|> write "}"
dict : dict, KeyValWalker (LogFormatter, Bool) dict key value, (key -> Inspector LogFormatter), (value -> Inspector LogFormatter) -> Inspector LogFormatter
dict = \d, walkFn, keyToInspector, valueToInspector ->
f0 <- Inspect.custom
write f0 "{"
|> \f1 ->
(f2, prependSep), key, value <- walkFn d (f1, Bool.false)
f3 =
if prependSep then
write f2 ", "
else
f2
Inspect.apply (keyToInspector key) f3
|> write ": "
|> \x -> Inspect.apply (valueToInspector value) x
|> \f4 -> (f4, Bool.true)
|> .0
|> write "}"
tag : Str, List (Inspector LogFormatter) -> Inspector LogFormatter
tag = \name, fields ->
if List.isEmpty fields then
f0 <- Inspect.custom
write f0 name
else
f0 <- Inspect.custom
write f0 "("
|> write name
|> \f1 ->
f2, inspector <- List.walk fields f1
write f2 " "
|> \x -> Inspect.apply inspector x
|> write ")"
tuple : List (Inspector LogFormatter) -> Inspector LogFormatter
tuple = \fields ->
f0 <- Inspect.custom
write f0 "("
|> \f1 ->
(f2, prependSep), inspector <- List.walk fields (f1, Bool.false)
f3 =
if prependSep then
write f2 ", "
else
f2
Inspect.apply inspector f3
|> \f4 -> (f4, Bool.true)
|> .0
|> write ")"
record : List { key : Str, value : Inspector LogFormatter } -> Inspector LogFormatter
record = \fields ->
f0 <- Inspect.custom
write f0 "{"
|> \f1 ->
(f2, prependSep), { key, value } <- List.walk fields (f1, Bool.false)
f3 =
if prependSep then
write f2 ", "
else
f2
write f3 key
|> write ": "
|> \x -> Inspect.apply value x
|> \f4 -> (f4, Bool.true)
|> .0
|> write "}"
bool : Bool -> Inspector LogFormatter
bool = \b ->
if b then
f0 <- Inspect.custom
write f0 "true"
else
f0 <- Inspect.custom
write f0 "false"
str : Str -> Inspector LogFormatter
str = \s ->
f0 <- Inspect.custom
f0
|> write "\""
|> write s
|> write "\""
opaque : Str -> Inspector LogFormatter
opaque = \s ->
f0 <- Inspect.custom
f0
|> write "<"
|> write s
|> write ">"
u8 : U8 -> Inspector LogFormatter
u8 = \num ->
f0 <- Inspect.custom
write f0 (num |> Num.toStr)
i8 : I8 -> Inspector LogFormatter
i8 = \num ->
f0 <- Inspect.custom
write f0 (num |> Num.toStr)
u16 : U16 -> Inspector LogFormatter
u16 = \num ->
f0 <- Inspect.custom
write f0 (num |> Num.toStr)
i16 : I16 -> Inspector LogFormatter
i16 = \num ->
f0 <- Inspect.custom
write f0 (num |> Num.toStr)
u32 : U32 -> Inspector LogFormatter
u32 = \num ->
f0 <- Inspect.custom
write f0 (num |> Num.toStr)
i32 : I32 -> Inspector LogFormatter
i32 = \num ->
f0 <- Inspect.custom
write f0 (num |> Num.toStr)
u64 : U64 -> Inspector LogFormatter
u64 = \num ->
f0 <- Inspect.custom
write f0 (num |> Num.toStr)
i64 : I64 -> Inspector LogFormatter
i64 = \num ->
f0 <- Inspect.custom
write f0 (num |> Num.toStr)
u128 : U128 -> Inspector LogFormatter
u128 = \num ->
f0 <- Inspect.custom
write f0 (num |> Num.toStr)
i128 : I128 -> Inspector LogFormatter
i128 = \num ->
f0 <- Inspect.custom
write f0 (num |> Num.toStr)
f32 : F32 -> Inspector LogFormatter
f32 = \num ->
f0 <- Inspect.custom
write f0 (num |> Num.toStr)
f64 : F64 -> Inspector LogFormatter
f64 = \num ->
f0 <- Inspect.custom
write f0 (num |> Num.toStr)
dec : Dec -> Inspector LogFormatter
dec = \num ->
f0 <- Inspect.custom
write f0 (num |> Num.toStr)
write : LogFormatter, Str -> LogFormatter
write = \@LogFormatter { data }, added ->
@LogFormatter { data: Str.concat data added }
toStr : LogFormatter -> Str
toStr = \@LogFormatter { data } -> data

View File

@ -5,7 +5,6 @@ app "inspect-logging"
packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.6.0/QOQW08n38nHHrVVkJNiPIjzjvbR3iMjXeFY5w1aT46w.tar.br" }
imports [
pf.Stdout,
LogFormatter,
Community,
]
provides [main] to pf
@ -36,5 +35,5 @@ main =
|> Community.addFriend 0 2
|> Community.addFriend 1 2
|> Inspect.inspect
|> LogFormatter.toStr
|> Inspect.toDbgStr
|> Stdout.line