Skip to content

v0.0.135: fix #584 (Unit fn non-tail), #583 (Array<T> aliases), #568 (url_parse leading colon)#585

Merged
aallan merged 5 commits into
mainfrom
claude/fix-584-583-codegen-bugs
May 6, 2026
Merged

v0.0.135: fix #584 (Unit fn non-tail), #583 (Array<T> aliases), #568 (url_parse leading colon)#585
aallan merged 5 commits into
mainfrom
claude/fix-584-583-codegen-bugs

Conversation

@aallan

@aallan aallan commented May 6, 2026

Copy link
Copy Markdown
Owner

Summary

Closes #584.
Closes #583.
Closes #568.

All three are codegen bugs in the same class — type checker accepts code that the WASM codegen handles incorrectly, with no Vera-native diagnostic in between. #584 and #583 surfaced via a sandboxed Claude.ai instance writing a cellular-automaton program; #568 was a pre-existing leading-colon round-trip bug. Bundled together because all three are small, surgical fixes (#568 is two lines of WAT plus a comment).

A fourth fix — a CLI display polish for String-returning main — was added after testing the alias work surfaced it. Details in its own section below.

#584 — user @Unit-returning fn in non-tail position

Block-statement sequencing in vera/wasm/context.py::_is_void_expr recognised IO.* qualified calls, UnitLit, effect-op FnCalls, and compound expressions as void, but missed FnCall to a user-declared @Unit fn. The surrounding sequencer fell through to "produces a value", emitted a stray drop, and WASM validation failed with expected a type but nothing on stack. The natural render(grid); IO.sleep(120); recurse(...) shape lands directly on this whenever render is a user helper.

Fix (5 lines logic + comment):

  • vera/codegen/functions.py — flip the _fn_ret_types filter from if ret_wt and ret_wt != "unsupported" (which excluded Unit returns because None is falsy) to if ret_wt != "unsupported" so Unit-returning fns are registered with None value. Already done this way in vera/codegen/closures.py; this brings the two builders into agreement.
  • vera/wasm/context.py — add a FnCall clause to _is_void_expr that returns True when the call target is in _fn_ret_types with value None.

#583 — type aliases over Array<T>

_is_pair_type_name in vera/wasm/inference.py was a @staticmethod doing string-pattern matching against unresolved alias names, so type Row = Array<Bool> left "Row" unrecognised as a pair type. Two failure modes from the issue body:

  • SlotRef @Row.0 emitted only local.get ptr not (ptr, len) — parameter use yielded invalid WAT at instantiate.
  • _slot_name_to_wasm_type("Row") returned None for a let binding, triggering silent E602 skip of the enclosing function.

Fix:

  • vera/wasm/inference.py — convert _is_pair_type_name from @staticmethod to instance method that resolves aliases via _resolve_base_type_name first. All existing callers already passed names through self._is_pair_type_name(...) so call sites need no change.
  • vera/wasm/data.py::_translate_array_lit — resolve element-type aliases before the pair-layout helpers (so [@Row.0, @Row.0] lays out elements at the correct stride, not the 4-byte i32 path).
  • vera/wasm/inference.py::_infer_index_element_type_expr — follow type aliases on the collection type so @Row.0[1] resolves the element type correctly. New helper _alias_array_element handles the common case of a non-generic alias pointing at a concrete Array<T>.

Aliases now work in parameter, let-binding, indexing, and array-literal-element positions.

#568url_parse / url_join leading-colon round-trip

url_parse(":foo") returned Ok with empty scheme; url_join then emitted bare "foo", losing the leading colon. Two viable fixes were noted in the issue body — RFC 3986-strict rejection vs. round-trip preservation flag. Going with RFC 3986 §3.1-aligned rejection (the cleaner option per maintainer call).

Fix (2 lines WAT + comment):

  • vera/wasm/calls_encoding.py::_translate_url_parse — after the colon-scan loop, branch to $err_up if colon_pos == 0. Returns Err("missing scheme") (the existing error message — empty scheme is also a missing scheme). No changes to url_join; the s_len > 0 gate stays since post-fix it can never see an empty scheme.

We don't yet enforce the full ALPHA / [ALPHA / DIGIT / "+" / "-" / "."]* scheme grammar from RFC 3986 — that's a wider RFC-conformance follow-up — but the empty-scheme case alone is the only one that lost its leading colon in the round-trip; full grammar enforcement isn't needed to close #568.

CLI display polish — vera run on String-returning main decodes the pair

Spotted while testing the #583 alias fixes against host-handle types: a public main(@Unit -> @String) returning "hello" printed something like 147492 instead of hello. The (ptr, len) i32_pair return was being collapsed to its first half — the heap pointer — by the value extractor in execute(). Distinct from the codegen bugs above (the WAT was already correct; only the CLI display was lying), but small enough to bundle.

Fix:

  • vera/codegen/api.py — new CompileResult.fn_string_returns: set[str] populated by compile_program from each FnDecl's return type. Alias-resolved via a new _return_type_is_string helper in vera/codegen/core.py so type Greeting = String participates (cooperates with Type aliases over Array<T> break WASM codegen (parameter case: invalid WAT; let-binding case: silent E602 skip) #583's alias work).
  • vera/codegen/api.py::execute — when raw_result is a 2-tuple AND fn_name is in fn_string_returns, read memory[ptr:ptr+len] and decode as UTF-8. Stored in ExecuteResult.value (type widened from int | float | Noneint | float | str | None). CLI's print(value) then renders the actual string.

Array<T> returns deliberately keep the bare-pointer fallback — their bytes-at-ptr aren't UTF-8 and rendering them meaningfully would need element-type-aware formatting (separate scope). A new test_array_return_unchanged test pins this asymmetry.

Test plan

Doc updates

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Fixed WASM array handling when element types use aliases
    • Corrected handling of Unit-returning functions in non-tail positions
    • Prevented empty-scheme URLs from parsing/round-tripping
  • New Features

    • Runtime now decodes String results into host strings when returned from functions
  • Documentation

    • Updated docs and guides to reflect an expanded conformance suite (84 programs) and project metrics
    • Updated Known Issues entry
  • Tests

    • Added two conformance tests for array aliases and non-tail Unit returns
  • Chores

    • Bumped project version to v0.0.135

Both bugs were in the same class - the type checker accepted code that
the WASM codegen emitted invalid WAT for, with no Vera-native diagnostic
in between. Found in the wild by a sandboxed Claude.ai instance writing
Conway-style cellular automata.

#584 - user-defined @Unit-returning fn in non-tail block-statement
position emitted invalid WAT. _is_void_expr (vera/wasm/context.py)
recognised IO.* qualified calls, UnitLit, effect-op FnCalls, and
compound expressions, but missed FnCall to a user fn declared with
@Unit return. The surrounding statement-sequencer fell through to
"produces a value", emitted a stray drop, and WASM validation failed
with "expected a type but nothing on stack". Fix: expand the codegen
registry filter (_fn_ret_types in vera/codegen/functions.py) to
include Unit-returning fns explicitly with None, then add a clause to
_is_void_expr that recognises them. Recursive cases (Unit fn nested
inside if/match arms in non-tail position) come for free via the
existing recursion.

#583 - type aliases over Array<T> broke codegen. _is_pair_type_name
in vera/wasm/inference.py did string-pattern matching against
unresolved alias names, so "type Row = Array<Bool>" left "Row"
unrecognised as a pair type. Two failure modes:
  - SlotRef @Row.0 emitted only "local.get ptr" not (ptr, len);
    parameter use yielded invalid WAT at instantiate.
  - _slot_name_to_wasm_type("Row") returned None for a let binding,
    triggering silent E602 skip of the enclosing function.
Fix: convert _is_pair_type_name from staticmethod to instance method
that resolves aliases via _resolve_base_type_name first; complementary
alias resolution added in _translate_array_lit (so [@Row.0, @Row.0]
lays out elements at the correct stride) and _infer_index_element_type_expr
(so @Row.0[1] resolves the element type correctly). Aliases work in
parameter, let-binding, indexing, and array-literal-element positions.

Conformance tests: tests/conformance/ch07_unit_fn_nontail.vera (#584;
covers mid-block, leading, and if-arm-non-tail positions),
tests/conformance/ch02_type_alias_array.vera (#583; covers all four
alias-codegen positions). Conformance count: 82 -> 84.

Doc / count sync: KNOWN_ISSUES.md drops the two closed bugs; SKILL.md
drops their workaround entries (still-open #549 and #568 remain);
CHANGELOG/version files bumped to 0.0.135.

Co-Authored-By: Claude <noreply@anthropic.invalid>
@coderabbitai

coderabbitai Bot commented May 6, 2026

Copy link
Copy Markdown

Caution

Review failed

Failed to post review comments

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Fixes WASM codegen bugs for type-alias-over-Array and user @Unit functions in non-tail positions, adds two conformance tests, bumps package to v0.0.135, updates docs and example allowlists, and adds a non-empty-scheme check to url_parse.

Changes

WASM codegen fixes, tests, and release metadata

Layer / File(s) Summary
Type alias / inference
vera/wasm/inference.py
Convert _is_pair_type_name to an instance method; add _alias_array_element to resolve Array<T> element types through type aliases; update call sites to use alias-aware resolution.
Array literal translation
vera/wasm/data.py
_translate_array_lit resolves base type names for element types before computing element size to handle aliased element types.
Function return-type propagation
vera/codegen/functions.py
Build fn_ret_types map including Unit-returning functions (None sentinel) and wire it into WasmContext via set_fn_ret_types.
Void-expression detection
vera/wasm/context.py
Extend _is_void_expr to treat FnCall names present in _fn_ret_types as void when mapped to None, preventing erroneous drop emission for user-defined @Unit functions in non-tail positions.
Calls encoding validation
vera/wasm/calls_encoding.py
url_parse adds an early check to reject empty scheme (colon at position 0) and branch to error.
Conformance tests
tests/conformance/manifest.json
Add ch02_type_alias_array and ch07_unit_fn_nontail manifest entries covering the two fixed cases.
Runtime String-return decoding
vera/codegen/core.py, vera/codegen/api.py, tests/test_codegen.py
Detect functions that return Vera String and decode (ptr,len) returns into Python str; update CompileResult/ExecuteResult and add tests verifying decoding and alias-returned Strings.
Example allowlist sync
scripts/check_skill_examples.py
Expanded and reindexed the ALLOWLIST FRAGMENT entries to match SKILL.md edits (many entries added/moved).
Docs & metadata
AGENTS.md, CHANGELOG.md, CLAUDE.md, FAQ.md, KNOWN_ISSUES.md, README.md, ROADMAP.md, SKILL.md, TESTING.md, pyproject.toml, vera/__init__.py, HISTORY.md
Version bumped to 0.0.135; CHANGELOG and HISTORY updated; conformance counts updated (82→84) and tests totals adjusted; KNOWN_ISSUES edited; release anchors updated.

Sequence Diagram(s)

sequenceDiagram
    participant Codegen as Codegen
    participant Ctx as WasmContext
    participant Inf as Inference
    participant Data as Data
    participant Exec as Execute (runtime)

    Codegen->>Codegen: build fn_ret_types map (include Unit → None)
    Codegen->>Ctx: set_fn_ret_types(fn_ret_types)

    Inf->>Inf: _alias_array_element() resolves Array<T> aliases
    Inf->>Data: request resolved element type

    Data->>Data: _translate_array_lit() resolve elem type and compute size

    Ctx->>Ctx: _is_void_expr(FnCall)
    alt FnCall in fn_ret_types mapped to None
        Ctx->>Ctx: treat FnCall as void (no value)
    else
        Ctx->>Ctx: existing void checks (effects, UnitLit, QualifiedCall, etc.)
    end

    Codegen->>Exec: mark exported fns in fn_string_returns
    Exec->>Exec: on execute(), decode (ptr,len) to Python str when fn listed
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • aallan/vera#567: Related changes to url_parse/url_join parsing and encoding logic.
  • aallan/vera#581: Updates to the same scripts/check_skill_examples.py allowlist (FRAGMENT entries).
  • aallan/vera#414: Prior work touching codegen/api execute/return handling (related to fn return decoding).

Suggested labels

compiler, tests, docs, ci

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarises the three primary fixes (Unit fn non-tail, Array aliases, url_parse leading colon) with issue references, directly matching the changeset scope.
Linked Issues check ✅ Passed All coding objectives from #584, #583, and #568 are met: Unit-returning fn tracking [#584], type-alias resolution in codegen [#583], and url_parse colon validation [#568]. Conformance tests added; no gaps detected.
Out of Scope Changes check ✅ Passed String-return decoding (CompileResult.fn_string_returns, ExecuteResult.value type expansion) surfaces as ancillary runtime support discovered during testing; whilst beyond the three stated fixes, it enables proper test validation of String-typed results and does not conflict with primary objectives.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/fix-584-583-codegen-bugs

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov

codecov Bot commented May 6, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 86.20690% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 90.97%. Comparing base (0dfe47c) to head (77e8000).
⚠️ Report is 6 commits behind head on main.

Files with missing lines Patch % Lines
vera/wasm/inference.py 64.70% 6 Missing ⚠️
vera/codegen/api.py 86.66% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #585      +/-   ##
==========================================
- Coverage   90.98%   90.97%   -0.02%     
==========================================
  Files          59       59              
  Lines       22884    22930      +46     
  Branches      259      259              
==========================================
+ Hits        20821    20860      +39     
- Misses       2056     2063       +7     
  Partials        7        7              
Flag Coverage Δ
javascript 57.36% <ø> (ø)
python 94.80% <86.20%> (-0.03%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Bundled into the same release because the fix is two lines of WAT plus
a comment. RFC 3986 sec 3.1 requires a non-empty scheme, so
url_parse(":foo") now returns Err("missing scheme") instead of Ok with
empty scheme that round-tripped through url_join as bare "foo".

The behaviour change is contained: any caller that relied on the old
Ok(...) had a malformed UrlParts (empty scheme_ptr/scheme_len) which
url_join would have emitted incorrectly anyway. Existing
ch09_url_parsing.vera test_parse_full / test_parse_no_query /
test_parse_err / test_join_full / test_roundtrip all still pass.

We don't yet enforce the full ALPHA / [ALPHA / DIGIT / "+" / "-" / "."]*
scheme grammar from RFC 3986 - that's a wider RFC-conformance follow-up.
Only the empty-scheme case lost its leading colon in the round-trip; the
full grammar enforcement isn't needed to close #568.

Conformance: extended ch09_url_parsing.vera with test_parse_empty_scheme
asserting Err return on ":foo". Conformance program count unchanged
(extension, not new file).

Doc updates: KNOWN_ISSUES.md drops #568 row; SKILL.md drops #568
from Known Bugs and Workarounds table; CHANGELOG.md adds #568 entry
to v0.0.135 Fixed section above the existing #584 + #583 entries.

Co-Authored-By: Claude <noreply@anthropic.invalid>
@aallan aallan changed the title v0.0.135: fix #584 (user Unit fn non-tail) and #583 (Array<T> aliases) v0.0.135: fix #584 (Unit fn non-tail), #583 (Array<T> aliases), #568 (url_parse leading colon) May 6, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@ROADMAP.md`:
- Line 253: Update the tagged-release summary string in ROADMAP.md from "134
tagged releases (as of v0.0.134)" to "135 tagged releases (as of v0.0.135)" to
reflect the new release; also update the corresponding release-count line in
HISTORY.md so both files remain consistent with the v0.0.135 bump.

In `@TESTING.md`:
- Line 9: Update the test-metrics row in TESTING.md so the numbers add up: the
current row reads "| **Tests** | 3,726 across 29 files (~34,800 lines of test
code; 3,702 passed, 14 skipped) |" which is inconsistent; change the passed
count to 3,712 (so 3,712 passed + 14 skipped = 3,726 total). Ensure the same
corrected string is used wherever that table row or exact phrase appears.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 75e98b10-eb7b-4931-8397-cd3ae2e94f0b

📥 Commits

Reviewing files that changed from the base of the PR and between 0dfe47c and 1cb3cf3.

⛔ Files ignored due to path filters (7)
  • docs/SKILL.md is excluded by !docs/**
  • docs/index.html is excluded by !docs/**
  • docs/index.md is excluded by !docs/**
  • docs/llms-full.txt is excluded by !docs/**
  • docs/llms.txt is excluded by !docs/**
  • tests/conformance/ch02_type_alias_array.vera is excluded by !**/*.vera
  • tests/conformance/ch07_unit_fn_nontail.vera is excluded by !**/*.vera
📒 Files selected for processing (17)
  • AGENTS.md
  • CHANGELOG.md
  • CLAUDE.md
  • FAQ.md
  • KNOWN_ISSUES.md
  • README.md
  • ROADMAP.md
  • SKILL.md
  • TESTING.md
  • pyproject.toml
  • scripts/check_skill_examples.py
  • tests/conformance/manifest.json
  • vera/__init__.py
  • vera/codegen/functions.py
  • vera/wasm/context.py
  • vera/wasm/data.py
  • vera/wasm/inference.py
💤 Files with no reviewable changes (1)
  • KNOWN_ISSUES.md

Comment thread ROADMAP.md Outdated
Comment thread TESTING.md Outdated
Three small fixes addressed in this commit:

ROADMAP.md / HISTORY.md - tagged-release count was stale at 134
(reflecting v0.0.134) but this PR bumps to v0.0.135. Both files now
report "135 tagged releases (as of v0.0.135)" / "135 tagged releases".

TESTING.md - the test-metrics row was internally inconsistent:
"3,726 across 29 files (3,702 passed, 14 skipped)". 3,702 + 14 = 3,716,
not 3,726. Updated to 3,712 passed (3,712 + 14 = 3,726). The 3,702
figure was a stale leftover from before this PR added the two new
conformance tests for #584 + #583.

uv.lock - CI lint job ran "uv lock --check" which failed because
pyproject.toml's version bumped 0.0.134 -> 0.0.135 but uv.lock still
recorded vera at 0.0.134. Single-line change, regenerated via `uv lock`.

Co-Authored-By: Claude <noreply@anthropic.invalid>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
HISTORY.md (1)

272-273: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Add Stage 11 table entry for v0.0.135.

The Stage 11 table shows individual version entries through v0.0.134 (line 272), but this PR releases v0.0.135 with three codegen bug fixes (#584, #583, #568) and two new conformance tests. Following the established pattern where bug-fix releases like v0.0.128 and v0.0.129 received Stage 11 rows, this release warrants a table entry:

 | v0.0.134 | 6 May | **Active reclamation of host-store handles via heap-wrap-as-ADT — closes [`#573`](https://github.com/aallan/vera/issues/573), [`#575`](https://github.com/aallan/vera/issues/575), [`#576`](https://github.com/aallan/vera/issues/576), [`#579`](https://github.com/aallan/vera/issues/579)** (Map / Set / Decimal). |
+| v0.0.135 | 6 May | **Codegen fixes: Unit-returning functions in non-tail positions, Array<T> type-alias resolution, url_parse empty-scheme rejection — closes [`#584`](https://github.com/aallan/vera/issues/584), [`#583`](https://github.com/aallan/vera/issues/583), [`#568`](https://github.com/aallan/vera/issues/568)**. Two new conformance tests (ch02_type_alias_array, ch07_unit_fn_nontail). |

The footer release count (line 311) was correctly updated to 135. Based on learnings, per-release entries maintain the version ledger's completeness.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@HISTORY.md` around lines 272 - 273, Add a new Stage 11 row for v0.0.135 in
the Stage 11 table to mirror the existing per-release pattern (see the v0.0.134
and earlier entries such as v0.0.128/v0.0.129), noting the three codegen bug
fixes (`#584`, `#583`, `#568`) and the two new conformance tests; ensure the entry
format matches surrounding rows exactly (version, brief note of fixes/tests, and
any links/PR numbers) so the release ledger remains continuous with the
already-updated footer count of 135.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@HISTORY.md`:
- Around line 272-273: Add a new Stage 11 row for v0.0.135 in the Stage 11 table
to mirror the existing per-release pattern (see the v0.0.134 and earlier entries
such as v0.0.128/v0.0.129), noting the three codegen bug fixes (`#584`, `#583`,
`#568`) and the two new conformance tests; ensure the entry format matches
surrounding rows exactly (version, brief note of fixes/tests, and any links/PR
numbers) so the release ledger remains continuous with the already-updated
footer count of 135.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 8d8ddebe-61ce-49a7-aae9-6b15c3f6b190

📥 Commits

Reviewing files that changed from the base of the PR and between d30e1f4 and caa80ec.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock, !uv.lock
📒 Files selected for processing (3)
  • HISTORY.md
  • ROADMAP.md
  • TESTING.md

CodeRabbit finding (valid): the Stage 11 ledger ended at v0.0.134
but this PR bumps to v0.0.135 with three closed issues. Adding the
row for ledger continuity, matching the format used by adjacent
entries (one-liner with closes-N issue links plus a parenthetical
summary).

Co-Authored-By: Claude <noreply@anthropic.invalid>
@aallan

aallan commented May 6, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai re: HISTORY.md Stage 11 ledger v0.0.135 row — valid finding, fixed in b9a1591. Added a row matching the format of the surrounding entries: terse one-liner with closes-N issue links plus a parenthetical summary of the three fixes (#584 user @Unit non-tail, #583 Array<T> aliases, #568 url_parse(":foo") RFC 3986 §3.1).

@coderabbitai

coderabbitai Bot commented May 6, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

@aallan: Confirmed — the approach is correct. A terse one-liner with closes-N links and a parenthetical tuple of the three fixes matches the surrounding ledger format precisely and keeps the entry diff-reviewable. Commit b9a1591 looks good.

Discovered while testing #583/#584 reproducers - vera run on a public
main returning @string printed the heap pointer (e.g. "147492"),
not the actual string. The (ptr, len) pair was being collapsed to its
first half by the value extractor in execute().

Fix tracks which functions have a Vera return type that resolves to
String (after alias resolution) via a new CompileResult.fn_string_returns
set, populated in compile_program by walking each FnDecl's return type.
execute() then reads memory[ptr:ptr+len] and UTF-8-decodes the bytes
when fn_name is in that set, storing the decoded str in
ExecuteResult.value.

Array<T> returns deliberately keep the existing bare-pointer fallback -
their bytes-at-ptr aren't UTF-8 and rendering them meaningfully would
need element-type-aware formatting (separate scope). The asymmetry is
locked in by the new test_array_return_unchanged regression.

ExecuteResult.value type widens from "int | float | None" to
"int | float | str | None". Only one existing test was checking for
the pre-fix pointer value; updated to assert the decoded str.

Tests added (test_codegen.py TestStringArraySignatures):
  - test_string_return_execution rewritten to assert == "hello"
  - test_string_alias_return_execution covering "type Greeting = String"
  - test_array_return_unchanged pinning the asymmetry

Doc / count updates:
  - test_codegen.py: 1,065 -> 1,067 tests, 16,482 -> 16,521 lines
  - Total tests: 3,726 -> 3,728 (3,714 passed + 14 skipped)
  - TESTING.md and ROADMAP.md updated

CHANGELOG entry added in [0.0.135] Fixed section above the existing
#568 / #584 / #583 entries (no version bump - this rolls into the
already-bumped 0.0.135).

Co-Authored-By: Claude <noreply@anthropic.invalid>
@aallan aallan merged commit c5c0263 into main May 6, 2026
20 checks passed
@aallan aallan deleted the claude/fix-584-583-codegen-bugs branch May 6, 2026 14:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant