Merge branch 'main' into patch-1

This commit is contained in:
Becker A 2023-11-29 18:17:02 -07:00 committed by GitHub
commit 1cf2a4e738
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
78 changed files with 5394 additions and 525 deletions

View File

@ -1,12 +1,8 @@
on:
pull_request:
workflow_call:
name: Benchmarks
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
RUST_BACKTRACE: 1
ROC_NUM_WORKERS: 1

View File

@ -1,4 +1,5 @@
on:
workflow_dispatch:
schedule:
- cron: '0 5 * * 1'

View File

@ -0,0 +1,17 @@
on:
workflow_dispatch:
schedule:
- cron: '0 5 * * *'
name: Clean up nix on mac mini m1
jobs:
clean-mac-mini-arm64:
runs-on: [self-hosted, macOS, ARM64]
timeout-minutes: 120
steps:
- name: Clean up nix store
run: nix-store --gc
- name: Clean up old nix shells
run: rm -rf /private/tmp/nix-shell.*

99
.github/workflows/ci_manager.yml vendored Normal file
View File

@ -0,0 +1,99 @@
on:
pull_request:
name: CI manager
# cancel current runs when a new commit is pushed
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
check-changes:
runs-on: ubuntu-22.04
outputs:
run_tests: ${{ steps.filecheck.outputs.run_tests }}
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Check if only css, html or md files changed
id: filecheck
run: |
git fetch origin ${{ github.base_ref }}
if git diff --name-only origin/${{ github.base_ref }} HEAD | grep -qvE '(\.md$|\.css$|\.html$)'; then
echo "run_tests=full" >> $GITHUB_OUTPUT
else
echo "run_tests=none" >> $GITHUB_OUTPUT
fi
- run: echo "debug output ${{ steps.filecheck.outputs.run_tests }}"
start-nix-linux-x86-64-tests:
needs: check-changes
if: needs.check-changes.outputs.run_tests == 'full'
uses: ./.github/workflows/nix_linux_x86_64.yml
start-nix-linux-aarch64-build-default-test:
needs: check-changes
if: needs.check-changes.outputs.run_tests == 'full'
uses: ./.github/workflows/nix_linux_arm64_default.yml
start-nix-linux-aarch64-cargo-build-test:
needs: check-changes
if: needs.check-changes.outputs.run_tests == 'full'
uses: ./.github/workflows/nix_linux_arm64_cargo.yml
start-nix-macos-apple-silicon-tests:
needs: check-changes
if: needs.check-changes.outputs.run_tests == 'full'
uses: ./.github/workflows/nix_macos_apple_silicon.yml
start-macos-x86-64-tests:
needs: check-changes
if: needs.check-changes.outputs.run_tests == 'full'
uses: ./.github/workflows/ubuntu_x86_64.yml
start-ubuntu-x86-64-tests:
needs: check-changes
if: needs.check-changes.outputs.run_tests == 'full'
uses: ./.github/workflows/ubuntu_x86_64.yml
start-windows-release-build-test:
needs: check-changes
if: needs.check-changes.outputs.run_tests == 'full'
uses: ./.github/workflows/windows_release_build.yml
start-windows-tests:
needs: check-changes
if: needs.check-changes.outputs.run_tests == 'full'
uses: ./.github/workflows/windows_tests.yml
start-roc-benchmarks:
needs: check-changes
if: needs.check-changes.outputs.run_tests == 'full'
uses: ./.github/workflows/benchmarks.yml
finish-full:
runs-on: ubuntu-22.04
needs: [
start-nix-linux-x86-64-tests,
start-nix-linux-aarch64-build-default-test,
start-nix-linux-aarch64-cargo-build-test,
start-nix-macos-apple-silicon-tests,
start-macos-x86-64-tests,
start-ubuntu-x86-64-tests,
start-windows-release-build-test,
start-windows-tests,
start-roc-benchmarks
]
steps:
- run: echo "all workflows succeeded!"
finish-none:
runs-on: ubuntu-22.04
needs: [check-changes]
if: needs.check-changes.outputs.run_tests == 'none'
steps:
- run: echo "Only non-code files changed. CI manager did not run any workflows."

View File

@ -1,11 +1,11 @@
on:
pull_request:
pull_request:
name: devtools nix files test - linux
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
devtools-test-linux:

View File

@ -1,11 +1,11 @@
on:
pull_request:
pull_request:
name: devtools nix files test - macos
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
devtools-test-macos:

View File

@ -1,12 +1,8 @@
on:
pull_request:
workflow_call:
name: Macos x86-64 rust tests
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
RUST_BACKTRACE: 1

View File

@ -1,12 +1,8 @@
on:
pull_request:
workflow_call:
name: test cargo build on linux arm64 inside nix
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
RUST_BACKTRACE: 1

View File

@ -1,12 +1,8 @@
on:
pull_request:
workflow_call:
name: test default.nix on linux arm64
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
RUST_BACKTRACE: 1

View File

@ -1,12 +1,8 @@
on:
pull_request:
workflow_call:
name: Nix linux x86_64 cargo test
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
RUST_BACKTRACE: 1

View File

@ -1,12 +1,8 @@
on:
pull_request:
workflow_call:
name: Nix apple silicon cargo test
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
RUST_BACKTRACE: 1

View File

@ -1,12 +1,8 @@
on:
pull_request:
workflow_call:
name: Nix macOS x86_64 cargo test
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
RUST_BACKTRACE: 1

View File

@ -1,12 +1,8 @@
on:
pull_request:
workflow_call:
name: CI
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
RUST_BACKTRACE: 1

View File

@ -1,12 +1,8 @@
on:
pull_request:
workflow_call:
name: windows - release build
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
RUST_BACKTRACE: 1

View File

@ -1,12 +1,8 @@
on:
pull_request:
workflow_call:
name: windows - subset of tests
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
RUST_BACKTRACE: 1

View File

@ -34,7 +34,7 @@ install-zig-llvm:
RUN apt -y install libssl-dev
RUN OPENSSL_NO_VENDOR=1 cargo install wasm-pack
# sccache
RUN cargo install sccache
RUN cargo install sccache --locked
RUN sccache -V
ENV RUSTC_WRAPPER=/usr/local/cargo/bin/sccache
ENV SCCACHE_DIR=/earthbuild/sccache_dir

View File

@ -30,6 +30,8 @@ If you would like your company to become a corporate sponsor of Roc's developmen
We'd also like to express our gratitude to our generous [individual sponsors](https://github.com/sponsors/roc-lang/)! A special thanks to those sponsoring $25/month or more:
* [Alex Binaei](https://github.com/mrmizz)
* [Jono Mallanyk](https://github.com/jonomallanyk)
* [Chris Packett](https://github.com/chris-packett)
* [James Birtles](https://github.com/jamesbirtles)
* [Ivo Balbaert](https://github.com/Ivo-Balbaert)

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),
};

View File

@ -1062,10 +1062,10 @@ pub fn canonicalize_expr<'a>(
})
}
ast::Expr::RecordBuilder(_) => {
unreachable!("RecordBuilder should have been desugared by now")
internal_error!("RecordBuilder should have been desugared by now")
}
ast::Expr::Backpassing(_, _, _) => {
unreachable!("Backpassing should have been desugared by now")
internal_error!("Backpassing should have been desugared by now")
}
ast::Expr::Closure(loc_arg_patterns, loc_body_expr) => {
let (closure_data, output) =
@ -2338,10 +2338,10 @@ pub fn inline_calls(var_store: &mut VarStore, expr: Expr) -> Expr {
loc_answer.value
}
Some(_) => {
unreachable!("Tried to inline a non-function");
internal_error!("Tried to inline a non-function");
}
None => {
unreachable!(
internal_error!(
"Tried to inline a builtin that wasn't registered: {:?}",
symbol
);

View File

@ -8,7 +8,8 @@ use roc_module::called_via::{BinOp, CalledVia};
use roc_module::ident::ModuleName;
use roc_parse::ast::Expr::{self, *};
use roc_parse::ast::{
AssignedField, Collection, RecordBuilderField, StrLiteral, StrSegment, ValueDef, WhenBranch,
AssignedField, Collection, Pattern, RecordBuilderField, StrLiteral, StrSegment, ValueDef,
WhenBranch,
};
use roc_region::all::{Loc, Region};
@ -70,7 +71,10 @@ fn desugar_value_def<'a>(arena: &'a Bump, def: &'a ValueDef<'a>) -> ValueDef<'a>
use ValueDef::*;
match def {
Body(loc_pattern, loc_expr) => Body(loc_pattern, desugar_expr(arena, loc_expr)),
Body(loc_pattern, loc_expr) => Body(
desugar_loc_pattern(arena, loc_pattern),
desugar_expr(arena, loc_expr),
),
ann @ Annotation(_, _) => *ann,
AnnotatedBody {
ann_pattern,
@ -238,7 +242,10 @@ pub fn desugar_expr<'a>(arena: &'a Bump, loc_expr: &'a Loc<Expr<'a>>) -> &'a Loc
}
Closure(loc_patterns, loc_ret) => arena.alloc(Loc {
region: loc_expr.region,
value: Closure(loc_patterns, desugar_expr(arena, loc_ret)),
value: Closure(
desugar_loc_patterns(arena, loc_patterns),
desugar_expr(arena, loc_ret),
),
}),
Backpassing(loc_patterns, loc_body, loc_ret) => {
// loc_patterns <- loc_body
@ -249,7 +256,8 @@ pub fn desugar_expr<'a>(arena: &'a Bump, loc_expr: &'a Loc<Expr<'a>>) -> &'a Loc
let desugared_body = desugar_expr(arena, loc_body);
let desugared_ret = desugar_expr(arena, loc_ret);
let closure = Expr::Closure(loc_patterns, desugared_ret);
let desugared_loc_patterns = desugar_loc_patterns(arena, loc_patterns);
let closure = Expr::Closure(desugared_loc_patterns, desugared_ret);
let loc_closure = Loc::at(loc_expr.region, closure);
match &desugared_body.value {
@ -352,10 +360,8 @@ pub fn desugar_expr<'a>(arena: &'a Bump, loc_expr: &'a Loc<Expr<'a>>) -> &'a Loc
let mut desugared_branches = Vec::with_capacity_in(branches.len(), arena);
for branch in branches.iter() {
let desugared = desugar_expr(arena, &branch.value);
let mut alternatives = Vec::with_capacity_in(branch.patterns.len(), arena);
alternatives.extend(branch.patterns.iter().copied());
let desugared_expr = desugar_expr(arena, &branch.value);
let desugared_patterns = desugar_loc_patterns(arena, branch.patterns);
let desugared_guard = if let Some(guard) = &branch.guard {
Some(*desugar_expr(arena, guard))
@ -363,11 +369,9 @@ pub fn desugar_expr<'a>(arena: &'a Bump, loc_expr: &'a Loc<Expr<'a>>) -> &'a Loc
None
};
let alternatives = alternatives.into_bump_slice();
desugared_branches.push(&*arena.alloc(WhenBranch {
patterns: alternatives,
value: *desugared,
patterns: desugared_patterns,
value: *desugared_expr,
guard: desugared_guard,
}));
}
@ -544,6 +548,85 @@ fn desugar_field<'a>(
}
}
fn desugar_loc_patterns<'a>(
arena: &'a Bump,
loc_patterns: &'a [Loc<Pattern<'a>>],
) -> &'a [Loc<Pattern<'a>>] {
Vec::from_iter_in(
loc_patterns.iter().map(|loc_pattern| Loc {
region: loc_pattern.region,
value: desugar_pattern(arena, loc_pattern.value),
}),
arena,
)
.into_bump_slice()
}
fn desugar_loc_pattern<'a>(
arena: &'a Bump,
loc_pattern: &'a Loc<Pattern<'a>>,
) -> &'a Loc<Pattern<'a>> {
arena.alloc(Loc {
region: loc_pattern.region,
value: desugar_pattern(arena, loc_pattern.value),
})
}
fn desugar_pattern<'a>(arena: &'a Bump, pattern: Pattern<'a>) -> Pattern<'a> {
use roc_parse::ast::Pattern::*;
match pattern {
Identifier(_)
| Tag(_)
| OpaqueRef(_)
| NumLiteral(_)
| NonBase10Literal { .. }
| FloatLiteral(_)
| StrLiteral(_)
| Underscore(_)
| SingleQuote(_)
| ListRest(_)
| Malformed(_)
| MalformedIdent(_, _)
| QualifiedIdentifier { .. } => pattern,
Apply(tag, arg_patterns) => {
// Skip desugaring the tag, it should either be a Tag or OpaqueRef
let desugared_arg_patterns = Vec::from_iter_in(
arg_patterns.iter().map(|arg_pattern| Loc {
region: arg_pattern.region,
value: desugar_pattern(arena, arg_pattern.value),
}),
arena,
)
.into_bump_slice();
Apply(tag, desugared_arg_patterns)
}
RecordDestructure(field_patterns) => {
RecordDestructure(field_patterns.map_items(arena, |field_pattern| Loc {
region: field_pattern.region,
value: desugar_pattern(arena, field_pattern.value),
}))
}
RequiredField(name, field_pattern) => {
RequiredField(name, desugar_loc_pattern(arena, field_pattern))
}
OptionalField(name, expr) => OptionalField(name, desugar_expr(arena, expr)),
Tuple(patterns) => Tuple(patterns.map_items(arena, |elem_pattern| Loc {
region: elem_pattern.region,
value: desugar_pattern(arena, elem_pattern.value),
})),
List(patterns) => List(patterns.map_items(arena, |elem_pattern| Loc {
region: elem_pattern.region,
value: desugar_pattern(arena, elem_pattern.value),
})),
As(sub_pattern, symbol) => As(desugar_loc_pattern(arena, sub_pattern), symbol),
SpaceBefore(sub_pattern, _spaces) => desugar_pattern(arena, *sub_pattern),
SpaceAfter(sub_pattern, _spaces) => desugar_pattern(arena, *sub_pattern),
}
}
struct RecordBuilderArg<'a> {
closure: &'a Loc<Expr<'a>>,
apply_exprs: Vec<'a, &'a Loc<Expr<'a>>>,

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

@ -365,6 +365,7 @@ impl CallConv<AArch64GeneralReg, AArch64FloatReg, AArch64Assembler> for AArch64C
/// 213568: f90033fd str x29, [sp, #96]
const SHADOW_SPACE_SIZE: u8 = 16;
// These are registers that a called function must save and restore if it wants to use them.
#[inline(always)]
fn general_callee_saved(reg: &AArch64GeneralReg) -> bool {
matches!(

View File

@ -82,8 +82,8 @@ pub trait CallConv<GeneralReg: RegTrait, FloatReg: RegTrait, ASM: Assembler<Gene
fn setup_stack(
buf: &mut Vec<'_, u8>,
general_saved_regs: &[GeneralReg],
float_saved_regs: &[FloatReg],
saved_general_regs: &[GeneralReg],
saved_float_regs: &[FloatReg],
requested_stack_size: i32,
fn_call_stack_size: i32,
) -> i32;
@ -900,8 +900,11 @@ impl<
let mut out = bumpalo::vec![in self.env.arena];
// Setup stack.
let used_general_regs = self.storage_manager.general_used_callee_saved_regs();
let used_float_regs = self.storage_manager.float_used_callee_saved_regs();
let (used_general_regs, used_float_regs) = self
.storage_manager
.used_callee_saved_regs
.as_vecs(self.env.arena);
let aligned_stack_size = CC::setup_stack(
&mut out,
&used_general_regs,
@ -1199,6 +1202,12 @@ impl<
max_branch_stack_size =
std::cmp::max(max_branch_stack_size, self.storage_manager.stack_size());
base_storage.update_fn_call_stack_size(self.storage_manager.fn_call_stack_size());
// make sure that used callee-saved registers get saved/restored even if used in only
// one of the branches of the switch
base_storage
.used_callee_saved_regs
.extend(&self.storage_manager.used_callee_saved_regs);
}
self.storage_manager = base_storage;
self.literal_map = base_literal_map;

View File

@ -3,7 +3,7 @@ use crate::{
pointer_layouts, sign_extended_int_builtins, single_register_floats,
single_register_int_builtins, single_register_integers, single_register_layouts, Env,
};
use bumpalo::collections::Vec;
use bumpalo::collections::{CollectIn, Vec};
use roc_builtins::bitcode::{FloatWidth, IntWidth};
use roc_collections::all::{MutMap, MutSet};
use roc_error_macros::{internal_error, todo_lambda_erasure};
@ -118,10 +118,7 @@ pub struct StorageManager<
general_used_regs: Vec<'a, (GeneralReg, Symbol)>,
float_used_regs: Vec<'a, (FloatReg, Symbol)>,
// TODO: it probably would be faster to make these a list that linearly scans rather than hashing.
// used callee saved regs must be tracked for pushing and popping at the beginning/end of the function.
general_used_callee_saved_regs: MutSet<GeneralReg>,
float_used_callee_saved_regs: MutSet<FloatReg>,
pub(crate) used_callee_saved_regs: UsedCalleeRegisters<GeneralReg, FloatReg>,
free_stack_chunks: Vec<'a, (i32, u32)>,
stack_size: u32,
@ -152,16 +149,62 @@ pub fn new_storage_manager<
join_param_map: MutMap::default(),
general_free_regs: bumpalo::vec![in env.arena],
general_used_regs: bumpalo::vec![in env.arena],
general_used_callee_saved_regs: MutSet::default(),
// must be saved on entering a function, and restored before returning
used_callee_saved_regs: UsedCalleeRegisters::default(),
float_free_regs: bumpalo::vec![in env.arena],
float_used_regs: bumpalo::vec![in env.arena],
float_used_callee_saved_regs: MutSet::default(),
free_stack_chunks: bumpalo::vec![in env.arena],
stack_size: 0,
fn_call_stack_size: 0,
}
}
// optimization idea: use a bitset
#[derive(Debug, Clone)]
pub(crate) struct UsedCalleeRegisters<GeneralReg, FloatReg> {
general: MutSet<GeneralReg>,
float: MutSet<FloatReg>,
}
impl<GeneralReg: RegTrait, FloatReg: RegTrait> UsedCalleeRegisters<GeneralReg, FloatReg> {
fn clear(&mut self) {
self.general.clear();
self.float.clear();
}
fn insert_general(&mut self, reg: GeneralReg) -> bool {
self.general.insert(reg)
}
fn insert_float(&mut self, reg: FloatReg) -> bool {
self.float.insert(reg)
}
pub(crate) fn extend(&mut self, other: &Self) {
self.general.extend(other.general.iter().copied());
self.float.extend(other.float.iter().copied());
}
pub(crate) fn as_vecs<'a>(
&self,
arena: &'a bumpalo::Bump,
) -> (Vec<'a, GeneralReg>, Vec<'a, FloatReg>) {
(
self.general.iter().copied().collect_in(arena),
self.float.iter().copied().collect_in(arena),
)
}
}
impl<GeneralReg, FloatReg> Default for UsedCalleeRegisters<GeneralReg, FloatReg> {
fn default() -> Self {
Self {
general: Default::default(),
float: Default::default(),
}
}
}
impl<
'a,
'r,
@ -175,16 +218,16 @@ impl<
self.symbol_storage_map.clear();
self.allocation_map.clear();
self.join_param_map.clear();
self.general_used_callee_saved_regs.clear();
self.used_callee_saved_regs.clear();
self.general_free_regs.clear();
self.general_used_regs.clear();
self.general_free_regs
.extend_from_slice(CC::GENERAL_DEFAULT_FREE_REGS);
self.float_used_callee_saved_regs.clear();
self.float_free_regs.clear();
self.float_used_regs.clear();
self.float_free_regs
.extend_from_slice(CC::FLOAT_DEFAULT_FREE_REGS);
self.used_callee_saved_regs.clear();
self.free_stack_chunks.clear();
self.stack_size = 0;
self.fn_call_stack_size = 0;
@ -198,18 +241,6 @@ impl<
self.fn_call_stack_size
}
pub fn general_used_callee_saved_regs(&self) -> Vec<'a, GeneralReg> {
let mut used_regs = bumpalo::vec![in self.env.arena];
used_regs.extend(&self.general_used_callee_saved_regs);
used_regs
}
pub fn float_used_callee_saved_regs(&self) -> Vec<'a, FloatReg> {
let mut used_regs = bumpalo::vec![in self.env.arena];
used_regs.extend(&self.float_used_callee_saved_regs);
used_regs
}
/// Returns true if the symbol is storing a primitive value.
pub fn is_stored_primitive(&self, sym: &Symbol) -> bool {
matches!(
@ -223,7 +254,7 @@ impl<
fn get_general_reg(&mut self, buf: &mut Vec<'a, u8>) -> GeneralReg {
if let Some(reg) = self.general_free_regs.pop() {
if CC::general_callee_saved(&reg) {
self.general_used_callee_saved_regs.insert(reg);
self.used_callee_saved_regs.insert_general(reg);
}
reg
} else if !self.general_used_regs.is_empty() {
@ -240,7 +271,7 @@ impl<
fn get_float_reg(&mut self, buf: &mut Vec<'a, u8>) -> FloatReg {
if let Some(reg) = self.float_free_regs.pop() {
if CC::float_callee_saved(&reg) {
self.float_used_callee_saved_regs.insert(reg);
self.used_callee_saved_regs.insert_float(reg);
}
reg
} else if !self.float_used_regs.is_empty() {

View File

@ -199,6 +199,7 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Syste
];
const SHADOW_SPACE_SIZE: u8 = 0;
// These are registers that a called function must save and restore if it wants to use them.
#[inline(always)]
fn general_callee_saved(reg: &X86_64GeneralReg) -> bool {
matches!(
@ -1409,6 +1410,8 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Windo
];
const SHADOW_SPACE_SIZE: u8 = 32;
// These are registers that a called function must save and restore if it wants to use them.
//
// Refer https://learn.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-170#callercallee-saved-registers
// > The x64 ABI considers registers RBX, RBP, RDI, RSI, RSP, R12, R13, R14, R15, and XMM6-XMM15 nonvolatile.
// > They must be saved and restored by a function that uses them.

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

@ -5982,6 +5982,60 @@ In roc, functions are always written as a lambda, like{}
)
}
#[test]
fn provides_missing_to_in_app_header() {
report_header_problem_as(
indoc!(
r#"
app "broken"
provides [main]
"#
),
indoc!(
r#"
WEIRD PROVIDES /code/proj/Main.roc
I am partway through parsing a header, but I got stuck here:
1 app "broken"
2 provides [main]
^
I am expecting the `to` keyword next, like:
to pf
"#
),
)
}
#[test]
fn provides_to_missing_platform_in_app_header() {
report_header_problem_as(
indoc!(
r#"
app "broken"
provides [main] to
"#
),
indoc!(
r#"
WEIRD PROVIDES /code/proj/Main.roc
I am partway through parsing a header, but I got stuck here:
1 app "broken"
2 provides [main] to
^
I am expecting the platform name next, like:
to pf
"#
),
)
}
#[test]
fn platform_requires_rigids() {
report_header_problem_as(
@ -9744,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

@ -673,7 +673,25 @@ impl<'a> CallerProc<'a> {
let argument_layouts = match capture_layout {
None => passed_function.argument_layouts,
Some(_) => &passed_function.argument_layouts[1..],
Some(_capture_layout) => {
let capture_layout_index = passed_function.argument_layouts.len() - 1;
#[cfg(debug_assertions)]
{
let passed_capture_layout =
passed_function.argument_layouts[capture_layout_index];
let repr = layout_interner.get_repr(passed_capture_layout);
if let LayoutRepr::LambdaSet(lambda_set) = repr {
assert!(layout_interner
.equiv(_capture_layout, lambda_set.runtime_representation()));
} else {
panic!("unexpected layout for capture argument");
}
}
&passed_function.argument_layouts[..capture_layout_index]
}
};
let capture_symbol = ARG_SYMBOLS[0];

View File

@ -6020,7 +6020,12 @@ fn compile_struct_like<'a, L, UnusedLayout>(
match take_elem_expr(index) {
Some((var, loc_expr)) => {
match can_reuse_symbol(env, layout_cache, procs, &loc_expr.value, var) {
Imported(symbol) | LocalFunction(symbol) | UnspecializedExpr(symbol) => {
Imported(symbol) => {
// we cannot re-use the symbol in this case; it is used as a value, but defined as a thunk
elem_symbols.push(env.unique_symbol());
can_elems.push(Field::FunctionOrUnspecialized(symbol, variable));
}
LocalFunction(symbol) | UnspecializedExpr(symbol) => {
elem_symbols.push(symbol);
can_elems.push(Field::FunctionOrUnspecialized(symbol, variable));
}
@ -6068,15 +6073,15 @@ fn compile_struct_like<'a, L, UnusedLayout>(
Field::ValueSymbol => {
// this symbol is already defined; nothing to do
}
Field::FunctionOrUnspecialized(symbol, variable) => {
Field::FunctionOrUnspecialized(can_symbol, variable) => {
stmt = specialize_symbol(
env,
procs,
layout_cache,
Some(variable),
symbol,
*symbol,
env.arena.alloc(stmt),
symbol,
can_symbol,
);
}
Field::Field(var, loc_expr) => {

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

@ -4630,3 +4630,36 @@ fn many_arguments() {
i64
);
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
fn multiple_uses_of_bool_true_record() {
assert_evals_to!(
indoc!(
r#"
(Bool.true, Bool.true).0
"#
),
true,
bool
);
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
fn multiple_uses_of_bool_true_tag_union() {
assert_evals_to!(
indoc!(
r#"
x : [ One Bool Bool, Empty ]
x = One Bool.true Bool.true
when x is
One a _ -> a
Empty -> Bool.false
"#
),
true,
bool
);
}

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

@ -0,0 +1,15 @@
procedure Num.19 (#Attr.2, #Attr.3):
let Num.292 : I64 = lowlevel NumAdd #Attr.2 #Attr.3;
ret Num.292;
procedure Test.0 ():
let Test.7 : I64 = 1i64;
let Test.8 : I64 = 2i64;
let Test.9 : I64 = 3i64;
let Test.1 : {I64, I64, I64} = Struct {Test.7, Test.8, Test.9};
let Test.2 : I64 = StructAtIndex 0 Test.1;
let Test.3 : I64 = StructAtIndex 1 Test.1;
let Test.4 : I64 = StructAtIndex 2 Test.1;
let Test.6 : I64 = CallByName Num.19 Test.2 Test.3;
let Test.5 : I64 = CallByName Num.19 Test.6 Test.4;
ret Test.5;

View File

@ -0,0 +1,23 @@
procedure Num.19 (#Attr.2, #Attr.3):
let Num.291 : I64 = lowlevel NumAdd #Attr.2 #Attr.3;
ret Num.291;
procedure Test.0 ():
let Test.17 : {} = Struct {};
let Test.15 : List {} = Array [Test.17];
let Test.16 : Str = "foo";
let Test.14 : {List {}, Str} = Struct {Test.15, Test.16};
let Test.10 : List {} = StructAtIndex 0 Test.14;
dec Test.16;
let Test.11 : U64 = lowlevel ListLen Test.10;
dec Test.10;
let Test.12 : U64 = 1i64;
let Test.13 : Int1 = lowlevel Eq Test.11 Test.12;
if Test.13 then
let Test.5 : I64 = 1i64;
let Test.6 : I64 = 1i64;
let Test.2 : I64 = CallByName Num.19 Test.5 Test.6;
ret Test.2;
else
let Test.7 : I64 = 0i64;
ret Test.7;

View File

@ -0,0 +1,10 @@
procedure Num.19 (#Attr.2, #Attr.3):
let Num.291 : I64 = lowlevel NumAdd #Attr.2 #Attr.3;
ret Num.291;
procedure Test.0 ():
let Test.5 : {} = Struct {};
let Test.3 : I64 = 1i64;
let Test.4 : I64 = 1i64;
let Test.1 : I64 = CallByName Num.19 Test.3 Test.4;
ret Test.1;

View File

@ -893,6 +893,37 @@ fn optional_when() {
"#
}
#[mono_test]
fn optional_field_with_binary_op() {
r#"
{ bar ? 1 + 1 } = {}
bar
"#
}
#[mono_test]
fn nested_optional_field_with_binary_op() {
r#"
when { x: ([{}], "foo") } is
{ x: ([{ bar ? 1 + 1 }], _) } -> bar
_ -> 0
"#
}
#[mono_test]
fn multiline_record_pattern() {
r#"
x = { a: 1, b: 2, c: 3 }
{
a,
b,
c,
} = x
a + b + c
"#
}
#[mono_test]
fn nested_pattern_match() {
r#"
@ -3258,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

@ -3515,6 +3515,52 @@ fn to_provides_report<'a>(
EProvides::Space(error, pos) => to_space_report(alloc, lines, filename, &error, pos),
EProvides::IndentTo(pos) => {
let surroundings = Region::new(start, pos);
let region = LineColumnRegion::from_pos(lines.convert_pos(pos));
let doc = alloc.stack([
alloc.reflow(r"I am partway through parsing a header, but I got stuck here:"),
alloc.region_with_subregion(lines.convert_region(surroundings), region),
alloc.concat([
alloc.reflow("I am expecting the "),
alloc.keyword("to"),
alloc.reflow(" keyword next, like:"),
]),
alloc
.parser_suggestion("to pf")
.indent(4),
]);
Report {
filename,
doc,
title: "WEIRD PROVIDES".to_string(),
severity: Severity::RuntimeError,
}
}
EProvides::IndentListStart(pos) => {
let surroundings = Region::new(start, pos);
let region = LineColumnRegion::from_pos(lines.convert_pos(pos));
let doc = alloc.stack([
alloc.reflow(r"I am partway through parsing a header, but I got stuck here:"),
alloc.region_with_subregion(lines.convert_region(surroundings), region),
alloc.reflow("I am expecting the platform name next, like:"),
alloc
.parser_suggestion("to pf")
.indent(4),
]);
Report {
filename,
doc,
title: "WEIRD PROVIDES".to_string(),
severity: Severity::RuntimeError,
}
}
_ => todo!("unhandled parse error {:?}", parse_problem),
}
}

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

View File

@ -144,6 +144,8 @@ If you would like your organization to become an official sponsor of Roc's devel
We'd also like to express our gratitude to our generous [individual sponsors](https://github.com/sponsors/roc-lang/)! A special thanks to those sponsoring $25/month or more:
<ul id="individual-sponsors">
<li><a href="https://github.com/mrmizz">Alex Binaei</a>
<li><a href="https://github.com/jonomallanyk">Jono Mallanyk</a>
<li><a href="https://github.com/chris-packett">Chris Packett</a></li>
<li><a href="https://github.com/jamesbirtles">James Birtles</a></li>
<li><a href="https://github.com/Ivo-Balbaert">Ivo Balbaert</a></li>

View File

@ -510,7 +510,7 @@ outside a record field. Optionality is a concept that exists only in record
fields, and it's intended for the use case of config records like this. The
ergonomics of destructuring mean this wouldn't be a good fit for data modeling, consider using a `Result` type instead.
## [Tags](#tags) {#tags}
## [Tags &amp; Pattern Matching](#tags) {#tags}
Sometimes we want to represent that something can have one of several values. For example:
@ -661,6 +661,8 @@ This can be both more concise and more efficient (at runtime) than calling [`Lis
> **Note:** Each list pattern can only have one `..`, which is known as the "rest pattern" because it's where the _rest_ of the list goes.
See the [Pattern Matching example](https://www.roc-lang.org/examples/PatternMatching/README.html) which shows different ways to do pattern matching in Roc using tags, strings, and numbers.
## [Booleans](#booleans) {#booleans}
In many programming languages, `true` and `false` are special language keywords that refer to the two [boolean](https://en.wikipedia.org/wiki/Boolean_data_type) values. In Roc, booleans do not get special keywords; instead, they are exposed as the ordinary values `Bool.true` and `Bool.false`.
@ -1491,6 +1493,19 @@ See [Html Interface](https://github.com/roc-lang/roc/blob/main/examples/virtual-
See [Platform Switching Rust](https://github.com/roc-lang/roc/blob/main/examples/platform-switching/rust-platform/main.roc) for an example.
### [Importing Files](#importing-files) {#importing-files}
You can import files directly into your module as a `Str` or a `List U8` at compile time. This is can be useful for when working with data you would like to keep in a separate file, e.g. JSON or YAML configuration.
```roc
imports [
"some-file" as someStr : Str,
"some-file" as someBytes : List U8,
]
```
See the [Ingest Files Example](https://www.roc-lang.org/examples/IngestFiles/README.html) for a demonstration on using this feature.
## [Tasks](#tasks) {#tasks}
Tasks are technically not part of the Roc language, but they're very common in platforms. Let's continue using the [basic-cli](https://github.com/roc-lang/basic-cli) platform we've been using up to this point as an example!
@ -1685,10 +1700,20 @@ Some important things to note about backpassing and `await`:
- Backpassing syntax does not need to be used with `await` in particular. It can be used with any function.
- Roc's compiler treats functions defined with backpassing exactly the same way as functions defined the other way. The only difference between `\text ->` and `text <-` is how they look, so feel free to use whichever looks nicer to you!
See the [Task & Error Handling example](https://www.roc-lang.org/examples/Tasks/README.html) for a more detailed explanation of how to use tasks to help with error handling in a larger program.
## [Abilities](#abilities) {#abilities}
\[This part of the tutorial has not been written yet. Coming soon!\]
## Examples
Well done on making it this far!
We've covered all of the basic syntax and features of Roc in this Tutorial. You should now have a good foundation and be ready to start writing your own applications.
You can continue reading through more advanced topics below, or perhaps checkout some of the [Examples](/example) for more a detailed exploration of ways to do various things.
## [Appendix: Advanced Concepts](#appendix-advanced-concepts) {#appendix-advanced-concepts}
Here are some concepts you likely won't need as a beginner, but may want to know about eventually. This is listed as an appendix rather than the main tutorial, to emphasize that it's totally fine to stop reading here and go build things!
@ -1992,9 +2017,35 @@ For this reason, any time you see a function that only runs a `when` on its only
>
> Also just like with records, you can use this to compose tag union type aliases. For example, you can write `NetworkError : [Timeout, Disconnected]` and then `Problem : [InvalidInput, UnknownFormat]NetworkError`
### [Phantom Types](#phantom-types) {#phantom-types}
### [Record Builder](#record-builder) {#record-builder}
\[This part of the tutorial has not been written yet. Coming soon!\]
The record builder syntax sugar is a useful feature which leverages the functional programming concept of [applicative functors](https://lucamug.medium.com/functors-applicatives-and-monads-in-pictures-784c2b5786f7), to provide a flexible method for constructing complex types.
The record builder syntax sugar helps to build up a record by applying a series of functions to it.
For example, let's say we write a record-builder as follows:
```roc
{ aliceID, bobID, trudyID } =
initIDCount {
aliceID: <- incID,
bobID: <- incID,
trudyID: <- incID,
} |> extractState
```
The above desguars to the following.
```roc
{ aliceID, bobID, trudyID } =
initIDCount (\aID -> \bID -> \cID -> { aliceID: aID, bobID: bID, trudyID: cID })
|> incID
|> incID
|> incID
|> extractState
```
See the [Record Builder Example](https://www.roc-lang.org/examples/RecordBuilder/README.html) for an explanation of how to use this feature.
### [Reserved Keywords](#reserved-keywords) {#reserved-keywords}

View File

@ -55,7 +55,7 @@ body {
width: 100%;
height: 100%;
box-sizing: border-box;
overflow-x: hidden; /* This shouldn't be necessary, but without it, mobile has a right gutter. */
overflow-x: hidden; /* This shouldn't be necessary, but without it mobile has a right gutter. */
}
p {