fix(compiler): char_from_int(0) NUL string (B1) + top-level float-const binop (B2)#12
Merged
Conversation
…st binop (B2) Two independent codegen fixes, co-landed under one self-compile bootstrap; both fixed-point-safe by construction (compile.rail has no top-level float consts and never calls char_from_int, so its own self-compiled asm is unchanged). B1 (char_from_int NUL): the emit branch (~compile.rail:1156) built 1-byte strings via _rail_wrap_str, which re-derives length with _strlen and truncates at an embedded NUL, so char_from_int(0) returned an empty string. Now builds a correct 1-byte tagged string [tag=9, len=1, byte, NUL] directly. SCOPE: a correct single 1-byte NUL string only; embedded NULs still do not survive cat/join concat (that needs full length-tracked strings, a much larger change). t171 locks it. B2 (top-level float const in binary op): is_float's V-node branch (~:978) checked only __float_NAME, never __float_ret_NAME (the A-node branch already did), so a top-level float constant used in a binary op was misclassified and segfaulted / returned garbage. Added the __float_ret_ check. Also repairs the same-rooted tuple-destructure-float bug. t172 locks it. CAVEAT (unreachable in suite/stdlib/ armsim/compile.rail, noted for the future): a local 'let X = INT_EXPR' shadowing a top-level float-returning fn X would now misclassify as float (env shadowing only re-adds __int_/__float_, never removes the stale __float_ret_X). GATE: ./rail_native test -> 177/177 (was 175; t171+t172 added, count bumped), ./rail_native self twice -> byte-identical fixed point. Lands on master via fast-forward (authorized). The public builds.json badge regen is a separate follow-up. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two independent codegen fixes, gated on the full self-compile fixed point.
char_from_int(0)returned""(the 1-byte string went through_rail_wrap_str, which re-derives length via_strlenand truncates at the NUL). Now builds a correct 1-byte tagged string[tag=9, len=1, byte, NUL]directly. Scope: a single correct NUL byte; embedded NULs throughcat/joinare still out of scope.t171locks it.is_float's V-node branch checked only__float_NAME, never__float_ret_NAME(the A-node branch already did), so a top-level float constant in a binary op was misclassified → segfault/garbage. Added the__float_ret_check. Also repairs the same-rooted tuple-destructure-float bug.t172locks it.Gate:
./rail_native test→ 177/177 (was 175; t171+t172 added),./rail_native self×2 → byte-identical fixed point. Both fixes are fixed-point-safe by construction (compile.rail has no top-level float consts and never calls char_from_int, so its own self-compiled asm is unchanged).Public
builds.jsonbadge regen is a separate follow-up.🤖 Generated with Claude Code