mirror of
https://github.com/roc-lang/roc.git
synced 2024-11-11 05:34:11 +03:00
Merge branch 'main' into patch-1
This commit is contained in:
commit
1cf2a4e738
6
.github/workflows/benchmarks.yml
vendored
6
.github/workflows/benchmarks.yml
vendored
@ -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
|
||||
|
1
.github/workflows/ci_cleanup.yml
vendored
1
.github/workflows/ci_cleanup.yml
vendored
@ -1,4 +1,5 @@
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '0 5 * * 1'
|
||||
|
||||
|
17
.github/workflows/ci_cleanup_nix_mac.yml
vendored
Normal file
17
.github/workflows/ci_cleanup_nix_mac.yml
vendored
Normal 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
99
.github/workflows/ci_manager.yml
vendored
Normal 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."
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
6
.github/workflows/macos_x86_64.yml
vendored
6
.github/workflows/macos_x86_64.yml
vendored
@ -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
|
||||
|
||||
|
6
.github/workflows/nix_linux_arm64_cargo.yml
vendored
6
.github/workflows/nix_linux_arm64_cargo.yml
vendored
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
6
.github/workflows/nix_linux_x86_64.yml
vendored
6
.github/workflows/nix_linux_x86_64.yml
vendored
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
6
.github/workflows/nix_macos_x86_64.yml
vendored
6
.github/workflows/nix_macos_x86_64.yml
vendored
@ -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
|
||||
|
||||
|
6
.github/workflows/ubuntu_x86_64.yml
vendored
6
.github/workflows/ubuntu_x86_64.yml
vendored
@ -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
|
||||
|
||||
|
6
.github/workflows/windows_release_build.yml
vendored
6
.github/workflows/windows_release_build.yml
vendored
@ -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
|
||||
|
||||
|
6
.github/workflows/windows_tests.yml
vendored
6
.github/workflows/windows_tests.yml
vendored
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
)
|
||||
|
@ -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 {}
|
||||
|
@ -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
|
||||
|
@ -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 {}
|
||||
|
@ -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) {
|
||||
|
@ -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),
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
);
|
||||
|
@ -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>>>,
|
||||
|
1089
crates/compiler/derive/src/inspect.rs
Normal file
1089
crates/compiler/derive/src/inspect.rs
Normal file
File diff suppressed because it is too large
Load Diff
@ -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 {
|
||||
|
@ -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(_)
|
||||
|
211
crates/compiler/derive_key/src/inspect.rs
Normal file
211
crates/compiler/derive_key/src/inspect.rs
Normal 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,
|
||||
}
|
||||
}
|
||||
}
|
@ -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))),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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} -> _)")
|
||||
}
|
||||
|
@ -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!(
|
||||
|
@ -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;
|
||||
|
@ -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(®) {
|
||||
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(®) {
|
||||
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() {
|
||||
|
@ -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.
|
||||
|
@ -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])
|
||||
}
|
||||
|
@ -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`
|
||||
"###
|
||||
);
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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];
|
||||
|
@ -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) => {
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
|
@ -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"),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
);
|
||||
}
|
||||
|
@ -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;
|
||||
|
1202
crates/compiler/test_mono/generated/inspect_derived_dict.txt
Normal file
1202
crates/compiler/test_mono/generated/inspect_derived_dict.txt
Normal file
File diff suppressed because it is too large
Load Diff
172
crates/compiler/test_mono/generated/inspect_derived_list.txt
Normal file
172
crates/compiler/test_mono/generated/inspect_derived_list.txt
Normal 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;
|
@ -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;
|
204
crates/compiler/test_mono/generated/inspect_derived_record.txt
Normal file
204
crates/compiler/test_mono/generated/inspect_derived_record.txt
Normal 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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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
|
||||
"#
|
||||
)
|
||||
}
|
||||
|
@ -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];
|
||||
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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 & 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}
|
||||
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user