Repository navigation
A Nat crosses to a JS host as a plain number - #1506
Conversation
Lorenzobattistela
left a comment
There was a problem hiding this comment.
The core change looks right: C output is byte-identical, gates pass (repo 54/54, test 1600/1600, ping 49/49, perf 124/124), comp.ts drops to 62,766, JS export calls get 2-5x faster, and #1150 is fixed.
One regression: a bad Nat answer from a JS host is no longer caught. On main it fail-stopped, and C still does. With a top-level IO(Nat) effect:
-3prints-and., exits 0 (C fail-stops at first use)-1givesn+1 = 01.5prints1,2NaNhangs in Nat.show"5"gives51forn+1
So the description's "JS runs a negative host answer raw, the same as C" isn't accurate: C fail-stops on -3, JS prints garbage. Deleting nat_host_neg drops the one test that pinned the two lanes together. Could you keep a small check on effect answers whose type is exactly Nat (one wrapper per effect call, no walk, no export cost), and keep nat_host_neg? Nested fields and exported-def args can stay unchecked.
Also, deleting marshal_tag_unknown means B.kind({$:"Sq"}) across two libraries now silently takes the wrong branch instead of throwing the #1105 error. That's fine if #1488 lands too, since it removes the cause. The two PRs conflict (comp.ts, marshal_tag_unknown), so I'd merge this one first and have #1488 rebase without its marshal parts.
The JS runtime has held Nats as numbers since 87a1e9c; only the host seam converted them to BigInt and back. js_marshal, js_host and nat_host are gone: an effect gets and answers a number, and an exported def takes and returns one, so the C and JS lanes agree on the value model. Deletes nat_host_neg (a negative host Nat was caught only by the marshal) and marshal_tag_unknown (the bendlang#1105 tag check ran only for types holding a Nat). Renames marshal_nat_bigint to marshal_nat_number. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An exported def checks each argument whose type is Nat, and a foreign def checks an answer whose type is Nat, through nat_in: a negative, fractional or BigInt value, or one past 2^53, stops with the Nat error as C does, instead of running on as a bad Nat. A Nat inside a value is the host's to keep in range, as EFFECTS.md says. Brings back nat_host_neg on every lane and adds nat_host_export. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Rebased on main (c25ee78, after #1509 and #1515) and added a check for Nats coming in from JS. Check. A runtime
So Tests. Numbers. comp.ts is 62,883 tokens against 63,788 on main. The check costs 221 of the 1,126 this PR saves. GUIDE.md is unchanged. Gates ( Unsupervised AI review. |
485374e to
2ac8896
Compare
|
Linux check (x86_64, bun 1.4.2, gcc 16): Unsupervised AI review. |
The JS runtime has held Nats as numbers since 87a1e9c (2.3x), and it kept BigInt only at the host seam. This PR removes that seam conversion. An effect's
.jsgets and answers a number, and a def exported through the.bendloader or-o x.mjstakes and returns one.js_marshal,js_host,nat_hostand themarshmemo are gone.comp.tsgoes from 63,788 to 62,883 ttok.Breaking for JS callers: a host that passed or expected
5nnow uses5. EFFECTS.md, main.ts's header,effs/now.jsand theapp_win_is_bug_2ddemo are updated.Nat check at the seam
nat_inlets a value through only if it's a whole number from 0 to 2^53. Anything else stops the run with the usual Nat error, as the C lane does. It runs on:NatNatargument of an exported def, curried calls includedNats nested in fields or containers aren't checked. EFFECTS.md says so.
Tests
marshal_nat_bigint→marshal_nat_number.marshal_nat_pairandmarshal_native_formsnow expectnumber.marshal_array_depthandnat_host_boundsanswer numbers.nat_host_negis kept: a negative host answer fail-stops on interp, C and JS.nat_host_export:inc(-1),inc(1.5),inc(1n),inc(2^53+2)andadd(1)(-1)throw the Nat error, and good calls still run.marshal_tag_unknown: the JS lane: a Nat inside a value passed between two loaded .bend libraries stays a BigInt (constructor tags depend on the importing root), since 2.0.29 (still in 2.0.30) #1105 tag check lived insidejs_marshal. fix(compiler)!: stabilize JS constructor tags across modules #1488 removes the cause.This also fixes the return-type marshal behind #1150.
Validation (on main c25ee78)
mainfor all 17 runtime benches.inccalls take 74 ms on main, 21 ms here (20 ms without the check).