Bodies and Guards

Status: implemented

  • A body const is the body's, and binds as a module's does, a module being a function too (a module is a function): it names a value the return and the statements after it may use, it may not be written twice, and it is not in its own initializer's scope — except that a function that is the whole initializer has the name as its own, as a module const's does (above). It is evaluated as a module's is, as its own statement, at every call and whether or not the return reaches it (shared values): () => { const x = null.x; return 1; } loads and throws when called, as in JavaScript. The parameter is a name of the body too, so a const may not take it. A body const may take a name a scope around it binds, shadowing it as in JavaScript (no-shadowing) — unless the body has already read that name from outside, before the const or in its own initializer. That is not supported yet and is refused (capture shadowed) rather than compiled to another value: JavaScript resolves every reference in the body to the body's const, a read before its declaration throwing and a function written earlier reading it once called, where this compiler would read the capture. It is no restriction of the language — nothing leaks through it — but a forward reference inside a body, which body-const-forward-reference.md tracks.

    export default (...args) => {
        const first = args[0];
        const pair = [first, first];
        return [pair, pair];
    };
    

    pair is one array however many references reach it, as a module const is one value — which is the whole reason a body has them.

  • The body is an expression or a block, and value and { return value; } denote the same function. As an expression the body is any value except a bare object literal: after => JavaScript reads { as a block, never as an object, so the spelling is refused rather than read another way, and the object is written in parentheses instead (grouping) — (...args) => ({ a: 1 }), as in JavaScript. The block retains its written statements in order. A function whose end is reached returns undefined, including an empty body. return with an operand requires the operand on the same line; a bare throw is refused.

  • An explicit bare return;, or return followed by the closing brace, means return undefined. Syntax AST retains the missing operand and the original source information; resolution supplies the value.

  • Syntax AST does not analyze control flow. It retains statements after a return, throw, terminal conditional or loop, and source binding/capture checks still apply to them. FAST discards computations that cannot execute. FAST adds return undefined only when the function can complete normally. An if whose arms both terminate and an unconditional loop with no reachable owning break are terminal and need no fallback return.

    The language designer sergey-shandar explicitly approved source-shaped AST blocks and FAST completion in the working session, under DESIGN.md §12. This preserves JavaScript fallthrough and unreachable source syntax while keeping control-flow decisions in FAST.

  • A parameterless function called where it is written, with no arguments, denotes its body where the call stands: a ? (() => { const x = f(); return [x, x]; })() : 4 is the idiom for a const inside an expression, an arm of a conditional say, where no statement can stand, and it lowers to the arm holding [x, x] with x one shared node, no function and no call. Nothing observes the function: it is called once and compared with nothing, so it mints no identity the program could see, and its body evaluates exactly once, where the call stands — a slot of its frame is the enclosing scope's own node, so what the body shares stays shared and nothing else is. A body const the returned value does not reach is evaluated where the call stands, as in JavaScript; in the graph it is anchored at the nearest position that opens a block, the scope's root or a lazy operand (operators), which is where JavaScript's own semantics can tell no difference under the failure contract. (() => [1, 2])() is [1, 2], and a module holding either hashes the same. A capture a body names only through an unused alias, const x = c; and nothing more, is no slot of its frame, in a body or in a call inlined into one: the alias is dropped, so nothing reads it, and the scope's const is anchored as one nothing reaches. A call with an argument, (() => 1)(null.x), has an argument to evaluate; a function with a parameter binds a name; and a body reading its own rest array names what the enclosing scope does not hold — each stays a call. The FunctionalScript writer uses the same idiom in reverse: a value shared under one lazy operand alone, which no const of the scope could hold without evaluating it whatever the operator decides, is written in a block opened at the operand, a ? (() => { const $0 = [1]; return [$0, $0]; })() : 4, which reads back as the operand. Round-tripping through that writer keeps the graph, not the text: the function written in the source is gone from both.

  • throw value; terminates a block as return value; does, and a function whose body ends in it fails at every call — the one failure outcome the language has (failure is one outcome), reached on purpose, as a panic on a broken invariant rather than an expected error, which travels as a value (fjs/AGENTS.md §1.5). Everything else about it is JavaScript's, read as return is: the value is any expression and is evaluated first, so throw f(x) calls f before failing; throw and its value share a line, since JavaScript's restricted production forbids a line terminator between them, and throw; with no value is not JavaScript; and nothing in the language catches the value, so the language promises the failure and not the payload, which an executor carries out of band for a human or a test runner to read.

    export const todo = () => { throw "not implemented"; };
    export const checked = (n) => {
        const half = n / 2;
        throw ["not yet", half];
    };
    

    The body lowers to the node ['throw', v], an operation of one operand that always fails, and it follows the positional laziness every operator has: in an eager position it is evaluated and fails, and in a lazy one — an arm of ?:, the right operand of &&, || or ?? — it is not established unless JavaScript would establish it, so c ? 1 : (() => { throw 0; })() is 1 under a true c. The FunctionalScript writer spells the node in a terminating position, a block's or the module's, as the statement it came from, and anywhere else — wherever a graph puts one, and an arm of ?: once if lowers there — as the call of a function that throws, (() => { throw v; })(): JavaScript's one spelling of an expression that fails, and FunctionalScript itself — the call of a parameterless function written where it is called, which the front end inlines (above), so the text reads back as the node it was written from and fails at the same point. That is the writer's spelling, not a second source form: throw is a statement only, and an expression that must fail goes through a function that throws, as in JavaScript. The EDAG output carries the node, and the Rust output fails as the VM fails (output).

  • A terminating if (condition) block is a guard: a statement of a block body, standing where a const may, any number of times before the body's terminating statement. Its block is a block as above — any number of statements and then a return, a throw, a switch with a default (switch), or a terminal unconditional loop — so the branch never completes normally, and the statements after the guard, up to and including the body's own terminator, are what runs when the condition is falsy. The condition is any expression, evaluated where the statement stands and tested as ?: tests its condition. This terminating-guard form requires braces and has no else; conditional joins and early returns are described below. An unbraced consequent, if (c) return v;, and an if at module level remain outside admission. No ; follows the }, as in JavaScript: one there is the empty statement the language refuses (module structure), and the next statement may share the guard's line.

    export const unwrap = r => {
        if (r[0] === 'error') { throw r[1]; }
        return r[1];
    };
    export const sign = n => {
        if (n < 0) { return -1; }
        if (n > 0) { return 1; }
        return 0;
    };
    

    The guard is syntactic sugar over the conditional and adds no node: a body s… if (c) B rest denotes c ? (() => B)() : (() => rest)(), the guard's block and the statements after it each the body of a parameterless function called where it stands (above), and the compiler reads it as exactly that, so if (a) { const x = [1]; return [x, x]; } return 0; and a ? (() => { const x = [1]; return [x, x]; })() : 0 are one graph and one hash — ['?:', a, ['[]', [x, x]], 0] with x one shared node — and a second guard nests as the alternate of the first. Where a const lives is which edges reach it: one before the guard is the scope's, evaluated eagerly as JavaScript evaluates it before the condition, so const a = [1]; if (m) { return a; } return 0; is [',', [a, ['?:', m, a, 0]]], the anchoring rule of operators — and m ? a : a is not folded to a, the condition being an evaluation of its own that may fail; one in the guard's block, or after the guard, is reached from its arm alone, and evaluated only when JavaScript would evaluate it, so if (a) { throw 1; } const y = [2]; return y; is ['?:', a, ['throw', 1], ['[]', [2]]] and an unused const z = [2] in its place is anchored at the alternate's comma, [',', [z, 1]], never at the function's root. The statements after a guard are JavaScript's one block with the ones before it, so a name that block has bound — a parameter, a const before the guard, or one after an earlier guard — may not be bound again there (duplicate id), and neither may a word that block has already read from an enclosing scope, in a statement before the guard, in the condition or in the guard's block (capture shadowed), since in JavaScript every such read would have named the later const before its declaration; the guard's block is a block of its own and may shadow either. For this terminating-guard profile, the FunctionalScript writer spells the conditional, and an arm that holds a const or a throw as the block opened at the operand (above), so the guarded body reads back as the same graph; the EDAG output carries the ?:, and the Rust output prints it as it prints any conditional.

Normally completing conditionals

An ordinary function also admits a braced if whose selected arm can finish normally, with an optional braced else. A path may instead return from the owning function. The following example writes its function result explicitly:

export default (condition, f) => {
    let a = 0;
    if (condition) { a += 2; }
    return f(a);
};

Evaluate the condition once, then run only the selected arm. Both arms start from the binding values established after the test. The arms may assign at most one binding declared outside them; their normal results select its latest value for following statements. An arm that does not assign it, or an omitted else, supplies its incoming value. Following work such as f(a) runs once after that join. This uses the existing FAST branch results and adds no EDAG operation.

Each arm has its own lexical scope. Its declarations and snapshots stay local, while an assignment to an outer variable establishes the version used after the if. Assignments to branch-local variables do not count as outer writes. The usual declaration, const and capture checks still apply, including to unselected syntax. The one-outer-binding limit counts writes on returning paths too.

A partly returning arm bypasses the normal join and the following work. For example:

export default (a, m, f, g) => {
    if (a) {
        const x = f();
        m = x.a;
        if (x.b) { return x.c; }
    }
    return g(m);
};

When a is false, g receives the incoming m. When a is true and x.b is false, it receives x.a. When both tests are true, the function returns x.c and skips g. The read of x.a remains required even on that returning path. Only normal paths supply the joined binding version and reach the one following g call.

Nested conditionals and loops keep their lexical scopes. Loop-local break and continue retain their targets; an owning return bypasses those loops and finishes its original function. A nested ordinary function keeps its own return owner and does not return from the surrounding function.

This mixed-arm profile does not admit explicit throws within its arms, including nested guards and loops. Standalone terminating throw guards keep their existing admission. Selected expressions can still fail, and an unselected arm performs none of its work. Joins assigning several outer bindings remain a follow-up in reachable block ends. The syntax AST already retains those broader forms even when FJS admission refuses them.

Examples

The compiler demo offers the programs guards in module.f.js, each with its real output.

The demo on this page runs sample.f.js, this page's example as a function of one number — a body with a const and two terminating if guards — with every output fjs compile makes of it: the expression graph (EDAG), the Rust and the WebAssembly that Rust builds to. Its Run button calls the default export with -5, 0 and 7, as JavaScript and as WebAssembly, and shows what each call returned or threw.

export default (...a) => {
    const n = a[0];
    if (n < 0) { return "negative"; }
    if (n > 0) { return "positive"; }
    return "zero";
};

Reference

Demo

In FunctionalScript

fjs compile accepts this module, and it runs as JavaScript and as WebAssembly alike.

A FunctionalScript module and what fjs compile makes of it: the expression graph it lowers to, the Rust it compiles to on the NaNVM runtime, and the WebAssembly that Rust builds to. Run calls its default export with -5, then 0, then 7, first as the JavaScript it already is and then as WebAssembly, and shows what each call returned or threw and how long one call takes, timed over 1000 calls.

FunctionalScript source:

/**
 * The example of [`README.md`](./README.md) (Bodies and Guards) as a
 * function of one number, for the page's WASM demo: a body with a `const`
 * and two terminating `if` guards.
 *
 * @module
 */

/** @type {(...a: readonly number[]) => unknown} */
export default (...a) => {
    const n = a[0];
    if (n < 0) { return "negative"; }
    if (n > 0) { return "positive"; }
    return "zero";
};

Expression graph (EDAG) that fjs compile lowers it to:

=>lengthbody0?:?:condthenelse<"negative"?:<leftright.0?:condthenelse>"positive""zero">leftright.0.objidxrest0

The same graph, as fjs compile writes it to a .edag.data.js file:

const $0=[".",["rest"],0];export default ["{}",[[":","default",["=>",0,[],["?:",["<",$0,0],"negative",["?:",[">",$0,0],"positive","zero"]]]]]];

Rust that fjs compile writes from it, on the NaNVM runtime:

// @generated by `fjs compile`. Do not edit: recompile the source module instead.

use nanvm_lib::vm::unstable::{f64_any, string_any, string_key};
use nanvm_lib::vm::{Any, Array, IStaticFunction, ToAny, ToObject};

#[rustfmt::skip]
#[allow(clippy::if_same_then_else)]
pub fn module<A: IStaticFunction>(_runtime: Any<A>) -> Result<Any<A>, Any<A>> {
    Ok([(string_key("default"), A::static_function(|_self, _args| {
        let _b264: Any<A> = _args.rest(0).to_any();
        let _b1: Any<A> = (Any::dot(_b264.clone(), f64_any(0x0000000000000000)).end())?;
        if Any::<A>::to_boolean(&(Any::lt(_b1.clone(), f64_any(0x0000000000000000)))?) { Ok(string_any("negative")) } else { if Any::<A>::to_boolean(&(Any::gt(_b1.clone(), f64_any(0x0000000000000000)))?) { Ok(string_any("positive")) } else { Ok(string_any("zero")) } }
    }, 0, Array::default(), Some("(...$0)=>{const $1=$0[0];return $1<0?\"negative\":$1>0?\"positive\":\"zero\";}")).to_any())].to_object().to_any())
}

WebAssembly text (WAT) of the functions compiled from this source, without the NaNVM runtime:

  (func $nanvm_demos::samples::guards::module::<nanvm_lib::naive::Naive> (;703;) (type 1) (param i32 i32)
    (local i32 i32 i32 i32 i32)
    global.get $__stack_pointer
    i32.const 96
    i32.sub
    local.tee 2
    global.set $__stack_pointer
    local.get 2
    i32.const 0
    i32.store16 offset=28
    local.get 2
    i32.const 1068531
    i32.store offset=24
    local.get 2
    i32.const 1068524
    i32.store offset=20
    local.get 2
    i32.const 48
    i32.add
    local.get 2
    i32.const 20
    i32.add
    call $"core::iter::adapters::try_process::<core::iter::adapters::map::Map<core::str::iter::EncodeUtf16, core::result::Result<u16, nanvm_lib::vm::any::Any<nanvm_lib::naive::Naive>>::Ok>, u16, core::result::Result<core::convert::Infallible, nanvm_lib::vm::any::Any<nanvm_lib::naive::Naive>>, <core::result::Result<alloc::rc::Rc<[u16]>, nanvm_lib::vm::any::Any<nanvm_lib::naive::Naive>> as core::iter::traits::collect::FromIterator<core::result::Result<u16, nanvm_lib::vm::any::Any<nanvm_lib::naive::Naive>>>>::from_iter<core::iter::adapters::map::Map<core::str::iter::EncodeUtf16, core::result::Result<u16, nanvm_lib::vm::any::Any<nanvm_lib::naive::Naive>>::Ok>>::{closure#0}, alloc::rc::Rc<[u16]>>"
    block ;; label = @1
      block ;; label = @2
        block ;; label = @3
          local.get 2
          i32.load8_u offset=48
          local.tee 3
          i32.const 255
          i32.ne
          br_if 0 (;@3;)
          local.get 2
          i32.load offset=56
          local.set 4
          local.get 2
          i32.load offset=52
          local.set 5
          local.get 2
          i32.const 0
          i32.store8 offset=32
          local.get 2
          i32.const 8
          i32.add
          local.get 2
          i32.const 32
          i32.add
          call $"<core::iter::adapters::GenericShunt<core::iter::adapters::map::Map<core::iter::sources::empty::Empty<nanvm_lib::vm::any::Any<nanvm_lib::naive::Naive>>, core::result::Result<nanvm_lib::vm::any::Any<nanvm_lib::naive::Naive>, ()>::Ok>, core::result::Result<core::convert::Infallible, ()>> as alloc::rc::ToRcSlice<nanvm_lib::vm::any::Any<nanvm_lib::naive::Naive>>>::to_rc_slice"
          local.get 2
          local.get 2
          i32.load offset=12
          local.tee 6
          i32.store offset=52
          local.get 2
          local.get 2
          i32.load offset=8
          local.tee 3
          i32.store offset=48
          block ;; label = @4
            local.get 2
            i32.load8_u offset=32
            i32.const 1
            i32.ne
            br_if 0 (;@4;)
            local.get 3
            local.get 3
            i32.load
            i32.const -1
            i32.add
            local.tee 0
            i32.store
            local.get 0
            br_if 3 (;@1;)
            local.get 2
            i32.const 48
            i32.add
            call $"<alloc::rc::Rc<[nanvm_lib::vm::any::Any<nanvm_lib::naive::Naive>]>>::drop_slow"
            br 3 (;@1;)
          end
          local.get 3
          i32.eqz
          br_if 2 (;@1;)
          i32.const 238
          i32.const 0
          local.get 3
          local.get 6
          i32.const 1068531
          i32.const 72
          call $"<nanvm_lib::naive::Naive as nanvm_lib::vm::internal::IVm>::static_function"
          local.set 3
          local.get 2
          i32.const 0
          i32.store8 offset=20
          local.get 2
          local.get 3
          i32.store offset=68
          local.get 2
          i32.const 7
          i32.store8 offset=64
          local.get 2
          local.get 4
          i32.store offset=60
          local.get 2
          local.get 5
          i32.store offset=56
          local.get 2
          i64.const 4294967296
          i64.store offset=48
          local.get 2
          local.get 2
          i32.const 20
          i32.add
          i32.store offset=80
          local.get 2
          local.get 2
          i32.const 48
          i32.add
          call $"<core::iter::adapters::GenericShunt<core::iter::adapters::map::Map<core::array::iter::IntoIter<(nanvm_lib::vm::string::String<nanvm_lib::naive::Naive>, nanvm_lib::vm::any::Any<nanvm_lib::naive::Naive>), 1>, core::result::Result<(nanvm_lib::vm::string::String<nanvm_lib::naive::Naive>, nanvm_lib::vm::any::Any<nanvm_lib::naive::Naive>), ()>::Ok>, core::result::Result<core::convert::Infallible, ()>> as alloc::rc::ToRcSlice<(nanvm_lib::vm::string::String<nanvm_lib::naive::Naive>, nanvm_lib::vm::any::Any<nanvm_lib::naive::Naive>)>>::to_rc_slice"
          local.get 2
          local.get 2
          i32.load offset=4
          local.tee 4
          i32.store offset=36
          local.get 2
          local.get 2
          i32.load
          local.tee 3
          i32.store offset=32
          block ;; label = @4
            local.get 2
            i32.load8_u offset=20
            i32.const 1
            i32.ne
            br_if 0 (;@4;)
            local.get 3
            local.get 3
            i32.load
            i32.const -1
            i32.add
            local.tee 0
            i32.store
            local.get 0
            br_if 2 (;@2;)
            local.get 2
            i32.const 32
            i32.add
            call $"<alloc::rc::Rc<[(nanvm_lib::vm::string::String<nanvm_lib::naive::Naive>, nanvm_lib::vm::any::Any<nanvm_lib::naive::Naive>)]>>::drop_slow"
            br 2 (;@2;)
          end
          local.get 3
          i32.eqz
          br_if 1 (;@2;)
          local.get 0
          local.get 4
          i32.store offset=16
          local.get 0
          local.get 3
          i32.store offset=12
          local.get 0
          i32.const 5
          i32.store8 offset=8
          local.get 0
          i64.const 0
          i64.store
          local.get 1
          call $"#func693 core::ptr::drop_glue::<nanvm_lib::vm::unpacked::Unpacked<nanvm_lib::naive::Naive>>"
          local.get 2
          i32.const 96
          i32.add
          global.set $__stack_pointer
          return
        end
        local.get 2
        local.get 2
        i32.load8_u offset=51
        i32.store8 offset=35
        local.get 2
        local.get 2
        i32.load16_u offset=49 align=1
        i32.store16 offset=33 align=1
        local.get 2
        local.get 2
        i32.load offset=60
        i32.store offset=44
        local.get 2
        local.get 2
        i64.load offset=52 align=4
        i64.store offset=36 align=4
        local.get 2
        local.get 3
        i32.store8 offset=32
        i32.const 1057960
        i32.const 43
        local.get 2
        i32.const 32
        i32.add
        i32.const 1057944
        i32.const 1058004
        call $core::result::unwrap_failed
        unreachable
      end
      i32.const 1064316
      i32.const 43
      local.get 2
      i32.const 95
      i32.add
      i32.const 1064300
      i32.const 1064360
      call $core::result::unwrap_failed
      unreachable
    end
    i32.const 1064316
    i32.const 43
    local.get 2
    i32.const 95
    i32.add
    i32.const 1064300
    i32.const 1064360
    call $core::result::unwrap_failed
    unreachable
  )
  (func $"<nanvm_demos::samples::guards::module<nanvm_lib::naive::Naive>::{closure#0} as core::ops::function::FnOnce<(&nanvm_lib::naive::function::Function, nanvm_lib::vm::array::Array<nanvm_lib::naive::Naive>)>>::call_once" (;704;) (type 4) (param i32 i32 i32 i32)
    (local i32 i32 i32 i64)
    global.get $__stack_pointer
    i32.const 192
    i32.sub
    local.tee 4
    global.set $__stack_pointer
    local.get 4
    local.get 3
    i32.store offset=12
    local.get 4
    local.get 2
    i32.store offset=8
    block ;; label = @1
      block ;; label = @2
        block ;; label = @3
          block ;; label = @4
            block ;; label = @5
              block ;; label = @6
                block ;; label = @7
                  block ;; label = @8
                    block ;; label = @9
                      block ;; label = @10
                        local.get 2
                        i32.load
                        local.tee 5
                        i32.const -1
                        i32.eq
                        br_if 0 (;@10;)
                        local.get 4
                        local.get 3
                        i32.store offset=24
                        local.get 4
                        local.get 2
                        i32.store offset=20
                        local.get 4
                        i32.const 6
                        i32.store8 offset=16
                        local.get 2
                        local.get 5
                        i32.const 2
                        i32.add
                        local.tee 5
                        i32.store
                        local.get 5
                        i32.eqz
                        br_if 0 (;@10;)
                        local.get 4
                        local.get 2
                        i32.store offset=180
                        local.get 4
                        i32.const 6
                        i32.store8 offset=176
                        local.get 4
                        local.get 3
                        i64.extend_i32_u
                        i64.store offset=184
                        local.get 4
                        i64.const 0
                        i64.store offset=152
                        local.get 4
                        i32.const 2
                        i32.store8 offset=144
                        local.get 4
                        i32.const 112
                        i32.add
                        local.get 4
                        i32.const 176
                        i32.add
                        local.get 4
                        i32.const 144
                        i32.add
                        call $<nanvm_lib::vm::lambda::member::Member<nanvm_lib::naive::Naive>>::new
                        block ;; label = @11
                          local.get 4
                          i32.load8_u offset=112
                          i32.const 255
                          i32.ne
                          br_if 0 (;@11;)
                          local.get 0
                          local.get 4
                          i64.load offset=122 align=2
                          i64.store offset=10 align=2
                          local.get 0
                          local.get 4
                          i64.load offset=128 align=2
                          i64.store offset=16 align=2
                          local.get 0
                          local.get 4
                          i32.load16_u offset=120
                          i32.store16 offset=8
                          local.get 0
                          i64.const 1
                          i64.store
                          br 8 (;@3;)
                        end
                        local.get 4
                        local.get 4
                        i64.load offset=136
                        i64.store offset=168
                        local.get 4
                        local.get 4
                        i64.load offset=128
                        i64.store offset=160
                        local.get 4
                        local.get 4
                        i64.load offset=120
                        i64.store offset=152
                        local.get 4
                        local.get 4
                        i64.load offset=112
                        i64.store offset=144
                        local.get 4
                        i32.const 176
                        i32.add
                        local.get 4
                        i32.const 144
                        i32.add
                        call $<nanvm_lib::vm::lambda::member::Member<nanvm_lib::naive::Naive>>::own
                        block ;; label = @11
                          block ;; label = @12
                            local.get 4
                            i32.load8_u offset=176
                            local.tee 3
                            i32.const 255
                            i32.ne
                            br_if 0 (;@12;)
                            local.get 4
                            i32.const 144
                            i32.add
                            call $"#func693 core::ptr::drop_glue::<nanvm_lib::vm::unpacked::Unpacked<nanvm_lib::naive::Naive>>"
                            local.get 4
                            i32.const 160
                            i32.add
                            call $"#func693 core::ptr::drop_glue::<nanvm_lib::vm::unpacked::Unpacked<nanvm_lib::naive::Naive>>"
                            local.get 4
                            i32.const 256
                            i32.store16 offset=32
                            i32.const 1
                            local.set 5
                            i32.const 0
                            local.set 3
                            br 1 (;@11;)
                          end
                          local.get 4
                          local.get 4
                          i64.load offset=178 align=2
                          i64.store offset=96
                          local.get 4
                          local.get 4
                          i64.load offset=184 align=2
                          i64.store offset=102 align=2
                          local.get 4
                          i32.load8_u offset=177
                          local.set 5
                          local.get 4
                          i32.const 144
                          i32.add
                          call $"#func693 core::ptr::drop_glue::<nanvm_lib::vm::unpacked::Unpacked<nanvm_lib::naive::Naive>>"
                          local.get 4
                          i32.const 160
                          i32.add
                          call $"#func693 core::ptr::drop_glue::<nanvm_lib::vm::unpacked::Unpacked<nanvm_lib::naive::Naive>>"
                          local.get 4
                          local.get 4
                          i64.load offset=102 align=2
                          i64.store offset=40 align=2
                          local.get 4
                          local.get 4
                          i64.load offset=96
                          i64.store offset=34 align=2
                          local.get 4
                          local.get 5
                          i32.store8 offset=33
                          local.get 4
                          local.get 3
                          i32.store8 offset=32
                          block ;; label = @12
                            block ;; label = @13
                              block ;; label = @14
                                block ;; label = @15
                                  block ;; label = @16
                                    block ;; label = @17
                                      block ;; label = @18
                                        local.get 3
                                        br_table 7 (;@11;) 7 (;@11;) 5 (;@13;) 0 (;@18;) 1 (;@17;) 2 (;@16;) 3 (;@15;) 4 (;@14;) 7 (;@11;)
                                      end
                                      local.get 4
                                      i32.load offset=36
                                      local.tee 6
                                      local.get 6
                                      i32.load
                                      i32.const 1
                                      i32.add
                                      local.tee 3
                                      i32.store
                                      local.get 3
                                      i32.eqz
                                      br_if 7 (;@10;)
                                      local.get 4
                                      i64.load32_u offset=40
                                      local.set 7
                                      i32.const 3
                                      local.set 3
                                      br 5 (;@12;)
                                    end
                                    local.get 4
                                    i32.load offset=36
                                    local.tee 6
                                    local.get 6
                                    i32.load
                                    i32.const 1
                                    i32.add
                                    local.tee 3
                                    i32.store
                                    local.get 3
                                    i32.eqz
                                    br_if 6 (;@10;)
                                    local.get 4
                                    i64.load8_u offset=44
                                    i64.const 32
                                    i64.shl
                                    local.get 4
                                    i64.load32_u offset=40
                                    i64.or
                                    local.set 7
                                    i32.const 4
                                    local.set 3
                                    br 4 (;@12;)
                                  end
                                  local.get 4
                                  i32.load offset=36
                                  local.tee 6
                                  local.get 6
                                  i32.load
                                  i32.const 1
                                  i32.add
                                  local.tee 3
                                  i32.store
                                  local.get 3
                                  i32.eqz
                                  br_if 5 (;@10;)
                                  local.get 4
                                  i64.load32_u offset=40
                                  local.set 7
                                  i32.const 5
                                  local.set 3
                                  br 3 (;@12;)
                                end
                                local.get 4
                                i32.load offset=36
                                local.tee 6
                                local.get 6
                                i32.load
                                i32.const 1
                                i32.add
                                local.tee 3
                                i32.store
                                local.get 3
                                i32.eqz
                                br_if 4 (;@10;)
                                local.get 4
                                i64.load32_u offset=40
                                local.set 7
                                i32.const 6
                                local.set 3
                                br 2 (;@12;)
                              end
                              local.get 4
                              i32.load offset=36
                              local.tee 6
                              local.get 6
                              i32.load
                              i32.const 1
                              i32.add
                              local.tee 3
                              i32.store
                              local.get 3
                              i32.eqz
                              br_if 3 (;@10;)
                              i32.const 7
                              local.set 3
                              br 2 (;@11;)
                            end
                            i32.const 2
                            local.set 3
                            local.get 4
                            i64.load offset=40
                            local.set 7
                          end
                        end
                        local.get 4
                        local.get 7
                        i64.store offset=104
                        local.get 4
                        local.get 6
                        i32.store offset=100
                        local.get 4
                        local.get 5
                        i32.store8 offset=97
                        local.get 4
                        local.get 3
                        i32.store8 offset=96
                        local.get 4
                        i64.const 0
                        i64.store offset=184
                        local.get 4
                        i32.const 2
                        i32.store8 offset=176
                        local.get 4
                        i32.const 144
                        i32.add
                        local.get 4
                        i32.const 96
                        i32.add
                        local.get 4
                        i32.const 176
                        i32.add
                        call $nanvm_lib::vm::any::relational::compare::<nanvm_lib::naive::Naive>
                        local.get 4
                        i32.load8_u offset=145
                        local.set 3
                        block ;; label = @11
                          local.get 4
                          i32.load8_u offset=144
                          local.tee 5
                          i32.const 255
                          i32.eq
                          br_if 0 (;@11;)
                          local.get 4
                          local.get 4
                          i64.load offset=152 align=2
                          i64.store offset=70 align=2
                          local.get 4
                          local.get 4
                          i64.load offset=146 align=2
                          i64.store offset=64
                          local.get 4
                          local.get 4
                          i64.load offset=64
                          i64.store offset=48
                          local.get 4
                          local.get 4
                          i64.load offset=70 align=2
                          i64.store offset=54 align=2
                          local.get 0
                          local.get 3
                          i32.store8 offset=9
                          local.get 0
                          local.get 5
                          i32.store8 offset=8
                          local.get 0
                          local.get 4
                          i64.load offset=48
                          i64.store offset=10 align=2
                          local.get 0
                          local.get 4
                          i64.load offset=54 align=2
                          i64.store offset=16 align=2
                          local.get 0
                          i64.const 1
                          i64.store
                          br 7 (;@4;)
                        end
                        local.get 4
                        local.get 4
                        i64.load offset=70 align=2
                        i64.store offset=54 align=2
                        local.get 4
                        local.get 4
                        i64.load offset=64
                        i64.store offset=48
                        local.get 4
                        i32.const 1
                        i32.store8 offset=80
                        local.get 4
                        local.get 3
                        i32.const 255
                        i32.and
                        i32.const 255
                        i32.eq
                        local.tee 3
                        i32.store8 offset=81
                        local.get 4
                        local.get 4
                        i64.load offset=48
                        i64.store offset=82 align=2
                        local.get 4
                        local.get 4
                        i64.load offset=54 align=2
                        i64.store offset=88 align=2
                        local.get 4
                        i32.const 80
                        i32.add
                        call $"#func693 core::ptr::drop_glue::<nanvm_lib::vm::unpacked::Unpacked<nanvm_lib::naive::Naive>>"
                        block ;; label = @11
                          local.get 3
                          br_if 0 (;@11;)
                          block ;; label = @12
                            block ;; label = @13
                              block ;; label = @14
                                block ;; label = @15
                                  block ;; label = @16
                                    block ;; label = @17
                                      block ;; label = @18
                                        block ;; label = @19
                                          local.get 4
                                          i32.load8_u offset=32
                                          local.tee 5
                                          br_table 6 (;@13;) 6 (;@13;) 0 (;@19;) 1 (;@18;) 2 (;@17;) 3 (;@16;) 4 (;@15;) 5 (;@14;) 6 (;@13;)
                                        end
                                        local.get 4
                                        i64.load offset=40
                                        local.set 7
                                        br 10 (;@8;)
                                      end
                                      local.get 4
                                      i32.load offset=36
                                      local.tee 3
                                      local.get 3
                                      i32.load
                                      i32.const 1
                                      i32.add
                                      local.tee 6
                                      i32.store
                                      local.get 6
                                      i32.eqz
                                      br_if 7 (;@10;)
                                      br 8 (;@9;)
                                    end
                                    local.get 4
                                    i32.load offset=36
                                    local.tee 3
                                    local.get 3
                                    i32.load
                                    i32.const 1
                                    i32.add
                                    local.tee 6
                                    i32.store
                                    local.get 6
                                    i32.eqz
                                    br_if 6 (;@10;)
                                    local.get 4
                                    i64.load8_u offset=44
                                    i64.const 32
                                    i64.shl
                                    local.get 4
                                    i64.load32_u offset=40
                                    i64.or
                                    local.set 7
                                    br 8 (;@8;)
                                  end
                                  local.get 4
                                  i32.load offset=36
                                  local.tee 3
                                  local.get 3
                                  i32.load
                                  i32.const 1
                                  i32.add
                                  local.tee 6
                                  i32.store
                                  local.get 6
                                  br_if 6 (;@9;)
                                  br 5 (;@10;)
                                end
                                local.get 4
                                i32.load offset=36
                                local.tee 3
                                local.get 3
                                i32.load
                                i32.const 1
                                i32.add
                                local.tee 6
                                i32.store
                                local.get 6
                                br_if 5 (;@9;)
                                br 4 (;@10;)
                              end
                              local.get 4
                              i32.load offset=36
                              local.tee 3
                              local.get 3
                              i32.load
                              i32.const 1
                              i32.add
                              local.tee 6
                              i32.store
                              local.get 6
                              i32.eqz
                              br_if 3 (;@10;)
                              br 1 (;@12;)
                            end
                            local.get 4
                            i32.load8_u offset=33
                            local.set 6
                          end
                          br 3 (;@8;)
                        end
                        local.get 4
                        i32.const 0
                        i32.store16 offset=104
                        local.get 4
                        i32.const 1068832
                        i32.store offset=100
                        local.get 4
                        i32.const 1068824
                        i32.store offset=96
                        local.get 4
                        i32.const 144
                        i32.add
                        local.get 4
                        i32.const 96
                        i32.add
                        call $"core::iter::adapters::try_process::<core::iter::adapters::map::Map<core::str::iter::EncodeUtf16, core::result::Result<u16, nanvm_lib::vm::any::Any<nanvm_lib::naive::Naive>>::Ok>, u16, core::result::Result<core::convert::Infallible, nanvm_lib::vm::any::Any<nanvm_lib::naive::Naive>>, <core::result::Result<alloc::rc::Rc<[u16]>, nanvm_lib::vm::any::Any<nanvm_lib::naive::Naive>> as core::iter::traits::collect::FromIterator<core::result::Result<u16, nanvm_lib::vm::any::Any<nanvm_lib::naive::Naive>>>>::from_iter<core::iter::adapters::map::Map<core::str::iter::EncodeUtf16, core::result::Result<u16, nanvm_lib::vm::any::Any<nanvm_lib::naive::Naive>>::Ok>>::{closure#0}, alloc::rc::Rc<[u16]>>"
                        block ;; label = @11
                          local.get 4
                          i32.load8_u offset=144
                          local.tee 3
                          i32.const 255
                          i32.ne
                          br_if 0 (;@11;)
                          local.get 0
                          local.get 4
                          i64.load offset=148 align=4
                          i64.store offset=12 align=4
                          local.get 0
                          i32.const 3
                          i32.store8 offset=8
                          br 4 (;@7;)
                        end
                        local.get 4
                        local.get 4
                        i32.load8_u offset=147
                        i32.store8 offset=179
                        local.get 4
                        local.get 4
                        i32.load16_u offset=145 align=1
                        i32.store16 offset=177 align=1
                        local.get 4
                        local.get 4
                        i32.load offset=156
                        i32.store offset=188
                        local.get 4
                        local.get 4
                        i64.load offset=148 align=4
                        i64.store offset=180 align=4
                        local.get 4
                        local.get 3
                        i32.store8 offset=176
                        i32.const 1057960
                        i32.const 43
                        local.get 4
                        i32.const 176
                        i32.add
                        i32.const 1057944
                        i32.const 1058004
                        call $core::result::unwrap_failed
                        unreachable
                      end
                      unreachable
                    end
                    local.get 4
                    i64.load32_u offset=40
                    local.set 7
                  end
                  local.get 4
                  local.get 7
                  i64.store offset=104
                  local.get 4
                  local.get 3
                  i32.store offset=100
                  local.get 4
                  local.get 6
                  i32.store8 offset=97
                  local.get 4
                  local.get 5
                  i32.store8 offset=96
                  local.get 4
                  i64.const 0
                  i64.store offset=184
                  local.get 4
                  i32.const 2
                  i32.store8 offset=176
                  local.get 4
                  i32.const 144
                  i32.add
                  local.get 4
                  i32.const 96
                  i32.add
                  local.get 4
                  i32.const 176
                  i32.add
                  call $nanvm_lib::vm::any::relational::compare::<nanvm_lib::naive::Naive>
                  local.get 4
                  i32.load8_u offset=145
                  local.set 3
                  block ;; label = @8
                    local.get 4
                    i32.load8_u offset=144
                    local.tee 5
                    i32.const 255
                    i32.eq
                    br_if 0 (;@8;)
                    local.get 0
                    local.get 4
                    i64.load offset=152 align=2
                    i64.store offset=16 align=2
                    local.get 0
                    local.get 4
                    i64.load offset=146 align=2
                    i64.store offset=10 align=2
                    local.get 0
                    local.get 3
                    i32.store8 offset=9
                    local.get 0
                    local.get 5
                    i32.store8 offset=8
                    local.get 0
                    i64.const 1
                    i64.store
                    br 4 (;@4;)
                  end
                  local.get 4
                  i32.const 1
                  i32.store8 offset=80
                  local.get 4
                  local.get 3
                  i32.const 255
                  i32.and
                  i32.const 1
                  i32.eq
                  local.tee 3
                  i32.store8 offset=81
                  local.get 4
                  i32.const 80
                  i32.add
                  call $"#func693 core::ptr::drop_glue::<nanvm_lib::vm::unpacked::Unpacked<nanvm_lib::naive::Naive>>"
                  block ;; label = @8
                    local.get 3
                    br_if 0 (;@8;)
                    local.get 4
                    i32.const 0
                    i32.store16 offset=104
                    local.get 4
                    i32.const 1068816
                    i32.store offset=100
                    local.get 4
                    i32.const 1068812
                    i32.store offset=96
                    local.get 4
                    i32.const 144
                    i32.add
                    local.get 4
                    i32.const 96
                    i32.add
                    call $"core::iter::adapters::try_process::<core::iter::adapters::map::Map<core::str::iter::EncodeUtf16, core::result::Result<u16, nanvm_lib::vm::any::Any<nanvm_lib::naive::Naive>>::Ok>, u16, core::result::Result<core::convert::Infallible, nanvm_lib::vm::any::Any<nanvm_lib::naive::Naive>>, <core::result::Result<alloc::rc::Rc<[u16]>, nanvm_lib::vm::any::Any<nanvm_lib::naive::Naive>> as core::iter::traits::collect::FromIterator<core::result::Result<u16, nanvm_lib::vm::any::Any<nanvm_lib::naive::Naive>>>>::from_iter<core::iter::adapters::map::Map<core::str::iter::EncodeUtf16, core::result::Result<u16, nanvm_lib::vm::any::Any<nanvm_lib::naive::Naive>>::Ok>>::{closure#0}, alloc::rc::Rc<[u16]>>"
                    local.get 4
                    i32.load8_u offset=144
                    local.tee 3
                    i32.const 255
                    i32.ne
                    br_if 2 (;@6;)
                    local.get 0
                    local.get 4
                    i64.load offset=148 align=4
                    i64.store offset=12 align=4
                    local.get 0
                    i32.const 3
                    i32.store8 offset=8
                    br 1 (;@7;)
                  end
                  local.get 4
                  i32.const 0
                  i32.store16 offset=104
                  local.get 4
                  i32.const 1068824
                  i32.store offset=100
                  local.get 4
                  i32.const 1068816
                  i32.store offset=96
                  local.get 4
                  i32.const 144
                  i32.add
                  local.get 4
                  i32.const 96
                  i32.add
                  call $"core::iter::adapters::try_process::<core::iter::adapters::map::Map<core::str::iter::EncodeUtf16, core::result::Result<u16, nanvm_lib::vm::any::Any<nanvm_lib::naive::Naive>>::Ok>, u16, core::result::Result<core::convert::Infallible, nanvm_lib::vm::any::Any<nanvm_lib::naive::Naive>>, <core::result::Result<alloc::rc::Rc<[u16]>, nanvm_lib::vm::any::Any<nanvm_lib::naive::Naive>> as core::iter::traits::collect::FromIterator<core::result::Result<u16, nanvm_lib::vm::any::Any<nanvm_lib::naive::Naive>>>>::from_iter<core::iter::adapters::map::Map<core::str::iter::EncodeUtf16, core::result::Result<u16, nanvm_lib::vm::any::Any<nanvm_lib::naive::Naive>>::Ok>>::{closure#0}, alloc::rc::Rc<[u16]>>"
                  local.get 4
                  i32.load8_u offset=144
                  local.tee 3
                  i32.const 255
                  i32.ne
                  br_if 2 (;@5;)
                  local.get 0
                  local.get 4
                  i64.load offset=148 align=4
                  i64.store offset=12 align=4
                  local.get 0
                  i32.const 3
                  i32.store8 offset=8
                end
                local.get 0
                i64.const 0
                i64.store
                local.get 4
                i32.const 32
                i32.add
                call $"#func693 core::ptr::drop_glue::<nanvm_lib::vm::unpacked::Unpacked<nanvm_lib::naive::Naive>>"
                local.get 4
                i32.const 16
                i32.add
                call $"#func693 core::ptr::drop_glue::<nanvm_lib::vm::unpacked::Unpacked<nanvm_lib::naive::Naive>>"
                local.get 2
                local.get 2
                i32.load
                i32.const -1
                i32.add
                local.tee 0
                i32.store
                local.get 0
                br_if 5 (;@1;)
                br 4 (;@2;)
              end
              local.get 4
              local.get 4
              i32.load8_u offset=147
              i32.store8 offset=179
              local.get 4
              local.get 4
              i32.load16_u offset=145 align=1
              i32.store16 offset=177 align=1
              local.get 4
              local.get 4
              i32.load offset=156
              i32.store offset=188
              local.get 4
              local.get 4
              i64.load offset=148 align=4
              i64.store offset=180 align=4
              local.get 4
              local.get 3
              i32.store8 offset=176
              i32.const 1057960
              i32.const 43
              local.get 4
              i32.const 176
              i32.add
              i32.const 1057944
              i32.const 1058004
              call $core::result::unwrap_failed
              unreachable
            end
            local.get 4
            local.get 4
            i32.load8_u offset=147
            i32.store8 offset=179
            local.get 4
            local.get 4
            i32.load16_u offset=145 align=1
            i32.store16 offset=177 align=1
            local.get 4
            local.get 4
            i32.load offset=156
            i32.store offset=188
            local.get 4
            local.get 4
            i64.load offset=148 align=4
            i64.store offset=180 align=4
            local.get 4
            local.get 3
            i32.store8 offset=176
            i32.const 1057960
            i32.const 43
            local.get 4
            i32.const 176
            i32.add
            i32.const 1057944
            i32.const 1058004
            call $core::result::unwrap_failed
            unreachable
          end
          local.get 4
          i32.const 32
          i32.add
          call $"#func693 core::ptr::drop_glue::<nanvm_lib::vm::unpacked::Unpacked<nanvm_lib::naive::Naive>>"
        end
        local.get 4
        i32.const 16
        i32.add
        call $"#func693 core::ptr::drop_glue::<nanvm_lib::vm::unpacked::Unpacked<nanvm_lib::naive::Naive>>"
        local.get 2
        local.get 2
        i32.load
        i32.const -1
        i32.add
        local.tee 0
        i32.store
        local.get 0
        br_if 1 (;@1;)
      end
      local.get 4
      i32.const 8
      i32.add
      call $"<alloc::rc::Rc<[nanvm_lib::vm::any::Any<nanvm_lib::naive::Naive>]>>::drop_slow"
    end
    local.get 4
    i32.const 192
    i32.add
    global.set $__stack_pointer
  )

Emergent Testing

Idle. Press Run to start the suite.

  • ./proof.f.mjs