Add math built-ins: log, trig, constants, utilities (closes #467, v0.0.116)#498
Conversation
|
Note Reviews pausedIt 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 Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds 15 math built‑ins (log/log2/log10, sin/cos/tan, asin/acos/atan/atan2, pi, e, sign, clamp, float_clamp); threads per‑op host‑import tracking through the compiler and WASM emission; conditionally inlines or emits imports; updates browser/runtime bindings, tests, specs, docs, and bumps version + conformance count (76→77). Changes
Sequence Diagram(s)sequenceDiagram
participant CLI as CLI / Frontend
participant Core as CodeGen Core
participant Asm as WASM Assembly
participant Runtime as Host (JS / Python)
CLI->>Core: compile(program with math calls)
Core->>Core: scan AST → record math_ops_used
Core->>Asm: translate calls (math translators or inline)
alt op requires host import
Asm->>Asm: emit call $vera.<op> and mark import
Asm->>Core: include op in CompileResult.math_ops_used
else op inlined
Asm->>Asm: emit f64.const or select-based sequence
end
Core->>Runtime: produce module + CompileResult.math_ops_used
Runtime->>Runtime: bind vera.<op> → Math.* / python math.* when declared
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested labels
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #498 +/- ##
==========================================
+ Coverage 90.25% 90.27% +0.02%
==========================================
Files 58 58
Lines 20137 20276 +139
Branches 233 236 +3
==========================================
+ Hits 18174 18304 +130
- Misses 1959 1968 +9
Partials 4 4
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Actionable comments posted: 10
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@ROADMAP.md`:
- Line 3: The roadmap's version anchors are stale: update occurrences of
"v0.0.108" (currently line 3) and "as of v0.0.115" (currently line 269) to
reflect the release this PR targets ("v0.0.116"), and scan the rest of
ROADMAP.md for any other mentions of v0.0.108 or v0.0.115 to replace them for
consistency; ensure the opening summary and the historical note both read
"v0.0.116" so the document remains accurate and synchronized with this release.
In `@spec/09-standard-library.md`:
- Around line 866-867: The spec currently lists the built-ins pi and e with the
wrong signature (Unit -> Float64); update their documented signatures to the
zero-argument form () -> Float64 to match the implemented/runtime usage (so
change the entries for `pi` and `e` from `Unit -> Float64` to `() -> Float64` in
the standard library docs).
In `@spec/12-runtime.md`:
- Around line 48-57: The import subsection text currently states it imports host
functions only for effect operations but the runtime now also imports
host-backed built-ins such as vera.log, vera.log2, vera.log10, vera.sin,
vera.cos, vera.tan, vera.asin, vera.acos, vera.atan and vera.atan2; update the
subsection wording to say it imports host functions both for side-effecting
operations and for host-backed built-ins (built-in math functions), and adjust
any examples or sentences that assert “only for effect operations” so they
acknowledge these vera.* math functions as imported host-backed built-ins.
In `@TESTING.md`:
- Line 76: Update the stale test count in TESTING.md's runner snippet: locate
the reference to the conformance suite for test_conformance.py (the phrase that
currently reads “parametrized — 375 tests”) and change the number from 375 to
385 so it matches the table entry that lists 385 conformance tests.
In `@tests/test_browser.py`:
- Around line 513-599: Add domain-edge parity tests that invoke the browser
runtime with out-of-domain inputs and assert the process completes and the
result is NaN: create tests (e.g. test_log_negative, test_asin_out_of_domain,
test_acos_out_of_domain) that compile sources using _compile_vera and run them
via _run_node with expressions IO.print(float_to_string(log(-1.0))) ,
IO.print(float_to_string(asin(2.0))) and IO.print(float_to_string(acos(2.0))).
Parse node["stdout"] to a float and use math.isnan(...) to assert the printed
value is NaN (and not an error/trap). Ensure each test imports math and uses the
same helpers (_compile_vera, _run_node) as the other tests.
In `@tests/test_codegen.py`:
- Around line 10487-10496: Add tests to tests/test_codegen.py that exercise the
lo > hi semantic branch for the built-ins clamp and clamp_float: extend the
existing cases list (used for clamp/clamp_float tests) to include inputs where
lo > hi (e.g., (v, lo, hi, expected) cases such as lo greater than hi where
expected follows the specified behaviour), and mirror these additions in the
other cases block referenced around the second location (the one at 10516-10521)
so both clamp and clamp_float cover the negative/invalid-range branch and
prevent regressions.
- Around line 10388-10390: The assertion checking for "$vera.log" can false-pass
because it matches substrings in "$vera.log2" and "$vera.log10"; update the test
in tests/test_codegen.py that uses result.wat to assert the import token with
token-boundary semantics instead of a plain substring check (for example,
replace assert "$vera.log" in result.wat with a regex/assert that matches a word
boundary like re.search(r'\$vera\.log\b', result.wat) or assert for the exact
token surrounded by non-word delimiters), keeping the existing checks for
"$vera.log2" and "$vera.log10".
- Around line 10415-10434: The test test_inverse_trig_at_known_points currently
doesn't validate atan2 argument order nor exercise asin/acos; update the test's
source so it computes and returns multiple values (or multiple assertions) that
exercise asin(0.0), acos(1.0), atan(1.0) and atan2 in both orders
(atan2(1.0,1.0) and atan2(1.0,1.0) with swapped args as appropriate) and then
assert expected numeric relationships (asin(0)==0, acos(1)==0, atan(1)≈π/4,
atan2(1,1)≈π/4 and atan2(y,x) respects argument order differences), and also
keep the existing checks that "$vera.atan" and "$vera.atan2" appear in
result.wat; modify the test_inverse_trig_at_known_points source string and the
execution/assertion logic accordingly to ensure all four functions are actually
exercised and the atan2 argument-order behavior is validated.
In `@vera/codegen/api.py`:
- Around line 2256-2313: The math host wrappers currently call Python math
functions directly (see _math_unary_host used with _math_unary_specs and
host_atan2) which lets Python ValueError domain errors become traps; update the
wrappers to catch ValueError around the py_fn(x) call in _math_unary_host and
around _math_mod.atan2(y, x) in host_atan2, and return float("nan") on
ValueError so IEEE‑754 NaN semantics (and existing linker.define_func usage) are
preserved across the WASM boundary.
In `@vera/wasm/inference.py`:
- Around line 328-338: _infer_fncall_vera_type is missing branches for the new
math builtins so calls like "log", "sin", "pi", "clamp_float", "sign", and
"clamp" can return None; update _infer_fncall_vera_type to mirror the logic in
_infer_fncall_wasm_type by adding the same name sets: treat "log", "log2",
"log10", "sin", "cos", "tan", "asin", "acos", "atan", "atan2", "pi", "e",
"clamp_float" as the Vera float type and treat "sign" and "clamp" as the Vera
integer type (use the same Vera type identifiers used elsewhere in the file),
matching on expr.name and returning the appropriate Vera-type value.
🪄 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: fe8736b4-054c-45d1-a094-ce8fe4ff905d
⛔ Files ignored due to path filters (4)
docs/SKILL.mdis excluded by!docs/**docs/index.htmlis excluded by!docs/**tests/conformance/ch09_math_builtins.verais excluded by!**/*.verauv.lockis excluded by!**/*.lock,!uv.lock
📒 Files selected for processing (30)
AGENTS.mdCHANGELOG.mdCLAUDE.mdDESIGN.mdFAQ.mdHISTORY.mdREADME.mdROADMAP.mdSKILL.mdTESTING.mdpyproject.tomlscripts/check_skill_examples.pyspec/09-standard-library.mdspec/12-runtime.mdtests/conformance/manifest.jsontests/test_browser.pytests/test_codegen.pyvera/__init__.pyvera/browser/runtime.mjsvera/codegen/api.pyvera/codegen/assembly.pyvera/codegen/compilability.pyvera/codegen/core.pyvera/codegen/functions.pyvera/codegen/modules.pyvera/environment.pyvera/wasm/calls.pyvera/wasm/calls_math.pyvera/wasm/context.pyvera/wasm/inference.py
There was a problem hiding this comment.
Actionable comments posted: 5
♻️ Duplicate comments (11)
vera/wasm/inference.py (1)
328-338:⚠️ Potential issue | 🟠 MajorMirror these math built-ins in
_infer_fncall_vera_type.Line 328 adds WASM inference, but Vera-type inference still has no corresponding branch for these functions, so type inference can fall through to
Nonein downstream rewriting paths.Proposed fix
@@ if call.name in ("sqrt", "pow"): return "Float64" + if call.name in ( + "log", "log2", "log10", + "sin", "cos", "tan", "asin", "acos", "atan", "atan2", + "pi", "e", "float_clamp", + ): + return "Float64" + if call.name in ("sign", "clamp"): + return "Int"🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@vera/wasm/inference.py` around lines 328 - 338, The Vera-type inference function _infer_fncall_vera_type is missing the branch for the math built-ins added to WASM inference; add a corresponding conditional that checks expr.name for ("log", "log2", "log10", "sin", "cos", "tan", "asin", "acos", "atan", "atan2", "pi", "e", "float_clamp") and returns "f64", and another for ("sign", "clamp") returning "i64", so _infer_fncall_vera_type mirrors the WASM logic and avoids falling through to None.ROADMAP.md (1)
3-3:⚠️ Potential issue | 🟡 MinorVersion anchors are stale against this release update.
Line 3 still anchors current capabilities to
v0.0.108, and Line 269 still says “as of v0.0.115” despite this PR targetingv0.0.116. Please synchronise both anchors so the roadmap remains historically accurate.Suggested fix
-Vera v0.0.108 delivers a complete compiler pipeline ... +Vera v0.0.116 delivers a complete compiler pipeline ... -**810+ commits, 115 tagged releases (as of v0.0.115), 3,387 tests, 96% coverage, 77 conformance programs, 30 examples, 13 spec chapters.** +**810+ commits, 116 tagged releases (as of v0.0.116), 3,387 tests, 96% coverage, 77 conformance programs, 30 examples, 13 spec chapters.**As per coding guidelines
**/*.md: review Markdown for factual accuracy and outdated information.Also applies to: 269-269
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@ROADMAP.md` at line 3, Update the stale version anchors in the roadmap: replace the first occurrence referencing "v0.0.108" and the later note that reads "as of v0.0.115" so they both reflect the actual target release "v0.0.116"; edit the lines containing those exact version strings to "v0.0.116" (search for "v0.0.108" and "v0.0.115" in ROADMAP.md and update them) to keep the historical record accurate.spec/12-runtime.md (1)
48-57:⚠️ Potential issue | 🟡 MinorImport-condition text is now outdated after adding pure math imports.
Line 67 still says imports are emitted only for effect operations, but Line 48–57 adds host imports for pure math builtins (
log*, trig,atan2). Please widen this sentence to cover host-backed builtins as well.Suggested wording
-Imports are only emitted when the program actually uses the corresponding effect operations. A pure program produces a module with no imports. +Imports are only emitted when the program actually uses the corresponding host-backed operations (effect operations and selected pure builtins). A pure program that uses only inlined builtins produces a module with no imports.As per coding guidelines
spec/**/*.md: Language specification files must be factually accurate against the codebase.Also applies to: 67-67
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@spec/12-runtime.md` around lines 48 - 57, Update the import-condition wording around the sentence at line 67 to reflect that imports are emitted not only for effectful operations but also for host-backed pure builtins (e.g., vera.log, vera.log2, vera.log10, vera.sin, vera.cos, vera.tan, vera.asin, vera.acos, vera.atan, vera.atan2); change the sentence to state that imports are emitted for operations that require host backing (effectful ops and host-backed builtins) so the spec matches the added pure math imports listed in the table.spec/09-standard-library.md (1)
866-867:⚠️ Potential issue | 🟠 MajorCorrect
pi/eto zero-argument signatures.These entries still document
Unit -> Float64, but this PR’s API uses zero-arg calls (pi(),e()). Please keep the spec aligned with the implemented call form.Suggested fix
-| `pi` | `Unit -> Float64` | `3.141592653589793` | -| `e` | `Unit -> Float64` | `2.718281828459045` | +| `pi` | `() -> Float64` | `3.141592653589793` | +| `e` | `() -> Float64` | `2.718281828459045` |As per coding guidelines: “
spec/**/*.md: Language specification. Review for factual accuracy and broken code examples.”🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@spec/09-standard-library.md` around lines 866 - 867, Update the documented signatures for the constants pi and e from the current "Unit -> Float64" to the zero-argument call form used by the implementation (e.g., "() -> Float64") so the spec shows the actual call form pi() and e(); modify the table entries for the symbols "pi" and "e" to use the zero-argument signature and corresponding example call form.TESTING.md (1)
76-76:⚠️ Potential issue | 🟡 MinorUpdate the stale conformance count in the runner snippet.
This file now states 385 conformance tests here, but the “Via pytest” snippet later still says 375. Please make those counts consistent.
As per coding guidelines: “
**/*.md: Review Markdown files for factual accuracy against the codebase, broken links, and outdated information.”🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@TESTING.md` at line 76, Update the mismatched conformance test count in the "Via pytest" runner snippet so it matches the table entry for `test_conformance.py` (which lists 385 tests); locate the "Via pytest" code/snippet that currently says 375 and change that numeric literal to 385 so both references to `test_conformance.py` are consistent.tests/test_codegen.py (4)
10487-10496:⚠️ Potential issue | 🟠 MajorAdd
lo > hicoverage forclampto pin edge semantics.The current cases do not exercise the inverted-bound branch, so regressions there would go undetected.
Proposed fix
cases = [ # (v, lo, hi, expected) (5, 0, 10, 5), # within range → v (-3, 0, 10, 0), # below lo → lo (15, 0, 10, 10), # above hi → hi + (5, 10, 0, 0), # lo > hi semantics -> hi (-10, -5, 5, -5), # negative range, below (100, -5, 5, 5), # negative range, above (7, 7, 7, 7), # singleton (lo == hi == v) (0, 0, 0, 0), # zero singleton ]As per coding guidelines "Add codegen/runtime tests in
tests/test_codegen.pyfor built-in functions — cover normal cases, edge cases (empty inputs, zero values), and composition with other built-ins".🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/test_codegen.py` around lines 10487 - 10496, Add test cases to the existing "cases" list for the clamp tests to cover the inverted-bound branch (lo > hi) so pin-edge semantics are exercised; update the test vector list near the clamp checks (the "cases" variable used by the clamp tests) with entries where lo > hi (e.g., v within, below, and above the inverted range) to assert the expected pinned value, ensuring the clamp function's inverted-bound behavior is validated.
10388-10390:⚠️ Potential issue | 🟡 MinorHarden the
logimport assertion to avoid substring false-positives.
assert "$vera.log" in result.watcan pass when only$vera.log2/$vera.log10is present. Match the import token exactly.Proposed fix
- assert "$vera.log" in result.wat + assert any( + '(import "vera" "log"' in line + for line in result.wat.splitlines() + )🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/test_codegen.py` around lines 10388 - 10390, The assertion for the "$vera.log" import is too permissive and can match "$vera.log2" or "$vera.log10"; update the test in tests/test_codegen.py to assert the exact import token instead of a substring match—e.g., check result.wat for a whole-token match of "$vera.log" (use a word-boundary/regex like \$vera\.log\b or otherwise ensure surrounding non-word characters) while keeping the existing checks for "$vera.log2" and "$vera.log10".
10516-10521:⚠️ Potential issue | 🟠 MajorAdd
lo > hicoverage forfloat_clampas well.
float_clamphas the same uncovered inverted-bound edge case.Proposed fix
cases = [ (0.5, 0.0, 1.0, 0.5), (3.5, 0.0, 1.0, 1.0), (-3.5, 0.0, 1.0, 0.0), (-1.5, -2.0, -1.0, -1.5), # negative in-range + (0.5, 2.0, 1.0, 1.0), # lo > hi semantics -> hi ]As per coding guidelines "Add codegen/runtime tests in
tests/test_codegen.pyfor built-in functions — cover normal cases, edge cases (empty inputs, zero values), and composition with other built-ins".🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/test_codegen.py` around lines 10516 - 10521, The float_clamp tests are missing coverage for the inverted-bound case (lo > hi); update the cases list used by the float_clamp test to include a tuple that represents this edge (value, lo, hi, expected) mirroring the integer clamp inverted-bound entry (i.e., add an entry where lo > hi and set the expected result to whatever the float_clamp implementation returns in that scenario), referencing the float_clamp test's cases variable so the test suite exercises the lo>hi behavior.
10415-10434:⚠️ Potential issue | 🟠 Major
atan2ordering is not truly validated, andasin/acosare not exercised.Using
atan2(1.0, 1.0)is symmetric, so swapped argument order would still pass. The test docstring also claimsasin/acoscoverage but the body never calls them.Proposed fix
def test_inverse_trig_at_known_points(self) -> None: - """asin(0)==0, acos(1)==0, atan(1)≈π/4, atan2(1,1)≈π/4. + """asin/acos known points and non-symmetric atan2(y, x) order.""" + import math source = """\ public fn main(-> `@Float64`) requires(true) ensures(true) effects(pure) { - atan(1.0) - atan2(1.0, 1.0) + asin(0.0) + acos(1.0) + atan2(1.0, -1.0) } """ result = _compile_ok(source) + assert "$vera.asin" in result.wat + assert "$vera.acos" in result.wat assert "$vera.atan" in result.wat assert "$vera.atan2" in result.wat v = execute(result, fn_name="main").value - # Both values equal π/4; difference should be exactly 0. - assert v == 0.0, f"atan(1) vs atan2(1,1) disagreement: {v}" + assert abs(v - math.atan2(1.0, -1.0)) < 1e-12As per coding guidelines "Add codegen/runtime tests in
tests/test_codegen.pyfor built-in functions — cover normal cases, edge cases (empty inputs, zero values), and composition with other built-ins".🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/test_codegen.py` around lines 10415 - 10434, The test test_inverse_trig_at_known_points currently only compares atan(1.0) vs atan2(1.0, 1.0) (a symmetric case) and never exercises asin/acos; update the test body (function main) to call and assert asin(0.0)==0.0 and acos(1.0)==0.0 and to include a non-symmetric atan2 call to validate argument ordering (e.g., compute atan2(1.0, -1.0) and compare to the expected sign/value relative to atan2(-1.0, 1.0) or known constants), and add asserts that "$vera.asin" and "$vera.acos" appear in result.wat along with existing "$vera.atan" and "$vera.atan2"; modify the execute/result assertions in test_inverse_trig_at_known_points to check these new numeric expectations and wat symbols so the test truly covers asin/acos and verifies atan2 argument ordering.tests/test_browser.py (1)
504-599:⚠️ Potential issue | 🟠 MajorAdd domain-edge parity tests for the new math built-ins.
The new suite is strong on happy paths, but it still misses boundary/domain cases (
log(-1.0),log(0.0),asin(2.0),acos(2.0)). Without these, regressions in non-trapping NaN/±inf behaviour can slip through.Suggested test additions
+ def test_log_negative_is_nan(self, tmp_path: Path) -> None: + source = '''\ +public fn main(-> `@Unit`) + requires(true) ensures(true) effects(<IO>) +{ + IO.print(float_to_string(log(-1.0))) +} +''' + wasm_path, _ = _compile_vera(source, tmp_path) + node = _run_node(wasm_path) + import math + assert math.isnan(float(node["stdout"])) + + def test_log_zero_is_neg_inf(self, tmp_path: Path) -> None: + source = '''\ +public fn main(-> `@Unit`) + requires(true) ensures(true) effects(<IO>) +{ + IO.print(float_to_string(log(0.0))) +} +''' + wasm_path, _ = _compile_vera(source, tmp_path) + node = _run_node(wasm_path) + import math + assert math.isinf(float(node["stdout"])) and float(node["stdout"]) < 0.0As per coding guidelines "DO flag: Missing edge cases for new compiler features".
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/test_browser.py` around lines 504 - 599, Add domain-edge parity tests to TestBrowserMathBuiltins that exercise log(-1.0), log(0.0), asin(2.0) and acos(2.0): for each case compile/run the same way as existing tests using _compile_vera and _run_node with small Vera programs that print float_to_string of the expression, parse node["stdout"] and assert the runtime produces the expected IEEE results (use math.isnan for NaN cases: log(-1.0), asin(2.0), acos(2.0); and math.isinf plus sign check for -inf from log(0.0)). Name the new test functions clearly (e.g. test_log_domain_edges, test_asin_acos_domain_edges) and follow the same pattern as test_log_identity and others so they run under the same test harness.vera/codegen/api.py (1)
2255-2313:⚠️ Potential issue | 🔴 CriticalHandle math domain exceptions to prevent runtime traps.
Line 2259 promises IEEE-754-style behaviour, but Line 2280 directly calls
py_fn(x). Python raisesValueErrorfor several domain-edge inputs (e.g.log(-1),asin(2)), which currently escape as traps instead of returning Float64 sentinels.Proposed fix
- def _math_unary_host( - py_fn: Callable[[float], float], + def _math_unary_host( + op_name: str, + py_fn: Callable[[float], float], ) -> Callable[[wasmtime.Caller, float], float]: @@ def host(_caller: wasmtime.Caller, x: float) -> float: - return py_fn(x) + try: + return py_fn(x) + except ValueError: + # Match JS/IEEE-style non-trapping behaviour. + if op_name in {"log", "log2", "log10"} and x == 0.0: + return float("-inf") + return float("nan") return host @@ - _math_unary_host(py_fn), access_caller=True, + _math_unary_host(op_name, py_fn), access_caller=True, )#!/bin/bash # Verify Python math domain behaviour that currently propagates as traps. python - <<'PY' import math cases = [ ("log", -1.0), ("log", 0.0), ("log2", 0.0), ("asin", 2.0), ("acos", 2.0), ] for name, x in cases: fn = getattr(math, name) try: print(f"{name}({x}) -> {fn(x)!r}") except Exception as exc: print(f"{name}({x}) raised {type(exc).__name__}: {exc}") PY🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@vera/codegen/api.py` around lines 2255 - 2313, Wrap the direct calls to math functions in _math_unary_host.host and in host_atan2 with try/except so Python domain/overflow exceptions are converted to IEEE-754 sentinels: catch ValueError and return float("nan"); catch OverflowError and return math.copysign(math.inf, x) (for unary host) or math.copysign(math.inf, y) (for host_atan2); keep using the same identifiers (_math_unary_host, host, host_atan2, linker.define_func) so the wrappers still get registered via linker.define_func.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@scripts/check_skill_examples.py`:
- Around line 46-47: Two allowlist entries have their reasons swapped: find the
ALLOWLIST tuples for the keys "FRAGMENT" and "QUALIFIED_CALLS" where one
currently uses the reason "Effect handler syntax template" and the other uses
"Qualified calls fragment" and swap those reason strings so each key maps to the
correct descriptive reason; repeat the same swap for the other duplicate pair of
"FRAGMENT"/"QUALIFIED_CALLS" tuples elsewhere in the file so both occurrences
are corrected.
In `@spec/09-standard-library.md`:
- Line 985: Section numbering got duplicated after inserting §9.6.10: the
heading "Float64 Predicates" now marked 9.6.12 conflicts with "String Search"
also starting at 9.6.12; renumber all subsequent §9.6.x headings in
spec/09-standard-library.md (starting from the "Float64 Predicates" and "String
Search" headings) so they form a contiguous sequence, and update any inline
cross-references or links that mention those section numbers (search for the
literal "9.6.12", "Float64 Predicates", and "String Search" to locate affected
headings and references), also update the table of contents entries and any code
examples/comments that reference the old section numbers.
In `@tests/test_codegen.py`:
- Around line 10364-10369: The tests refer to the utility function as
float_clamp while the spec/issue uses clamp_float; choose the canonical name and
make them consistent by renaming all occurrences: if you adopt clamp_float,
update the test cases, any inlined WAT utility declarations, and references in
tests and runtime generation (search for float_clamp) to clamp_float, or vice
versa; ensure function identifiers in the groups listing (e.g., the Utilities
group and any asserts that call float_clamp) match the chosen name and run tests
to verify no remaining references to the old identifier.
In `@vera/browser/runtime.mjs`:
- Around line 1780-1802: The JS math functions in _mathUnary (and
imports.vera.atan2) return NaN for out-of-domain inputs but the Python runtime
raises ValueError, so wrap each function assigned to imports.vera (e.g., via the
_mathUnary loop where you currently do imports.vera[name] = fn) with a wrapper
that calls the JS Math function, checks Number.isNaN(result) and if so throws
the Python ValueError (e.g., new imports.vera.ValueError(`${name} domain
error`)); leave Math.atan2 behavior unchanged but keep the argument-order note
for atan2. Ensure you reference the same symbols: _mathUnary,
imports.vera[name], and atan2 when making the change.
---
Duplicate comments:
In `@ROADMAP.md`:
- Line 3: Update the stale version anchors in the roadmap: replace the first
occurrence referencing "v0.0.108" and the later note that reads "as of v0.0.115"
so they both reflect the actual target release "v0.0.116"; edit the lines
containing those exact version strings to "v0.0.116" (search for "v0.0.108" and
"v0.0.115" in ROADMAP.md and update them) to keep the historical record
accurate.
In `@spec/09-standard-library.md`:
- Around line 866-867: Update the documented signatures for the constants pi and
e from the current "Unit -> Float64" to the zero-argument call form used by the
implementation (e.g., "() -> Float64") so the spec shows the actual call form
pi() and e(); modify the table entries for the symbols "pi" and "e" to use the
zero-argument signature and corresponding example call form.
In `@spec/12-runtime.md`:
- Around line 48-57: Update the import-condition wording around the sentence at
line 67 to reflect that imports are emitted not only for effectful operations
but also for host-backed pure builtins (e.g., vera.log, vera.log2, vera.log10,
vera.sin, vera.cos, vera.tan, vera.asin, vera.acos, vera.atan, vera.atan2);
change the sentence to state that imports are emitted for operations that
require host backing (effectful ops and host-backed builtins) so the spec
matches the added pure math imports listed in the table.
In `@TESTING.md`:
- Line 76: Update the mismatched conformance test count in the "Via pytest"
runner snippet so it matches the table entry for `test_conformance.py` (which
lists 385 tests); locate the "Via pytest" code/snippet that currently says 375
and change that numeric literal to 385 so both references to
`test_conformance.py` are consistent.
In `@tests/test_browser.py`:
- Around line 504-599: Add domain-edge parity tests to TestBrowserMathBuiltins
that exercise log(-1.0), log(0.0), asin(2.0) and acos(2.0): for each case
compile/run the same way as existing tests using _compile_vera and _run_node
with small Vera programs that print float_to_string of the expression, parse
node["stdout"] and assert the runtime produces the expected IEEE results (use
math.isnan for NaN cases: log(-1.0), asin(2.0), acos(2.0); and math.isinf plus
sign check for -inf from log(0.0)). Name the new test functions clearly (e.g.
test_log_domain_edges, test_asin_acos_domain_edges) and follow the same pattern
as test_log_identity and others so they run under the same test harness.
In `@tests/test_codegen.py`:
- Around line 10487-10496: Add test cases to the existing "cases" list for the
clamp tests to cover the inverted-bound branch (lo > hi) so pin-edge semantics
are exercised; update the test vector list near the clamp checks (the "cases"
variable used by the clamp tests) with entries where lo > hi (e.g., v within,
below, and above the inverted range) to assert the expected pinned value,
ensuring the clamp function's inverted-bound behavior is validated.
- Around line 10388-10390: The assertion for the "$vera.log" import is too
permissive and can match "$vera.log2" or "$vera.log10"; update the test in
tests/test_codegen.py to assert the exact import token instead of a substring
match—e.g., check result.wat for a whole-token match of "$vera.log" (use a
word-boundary/regex like \$vera\.log\b or otherwise ensure surrounding non-word
characters) while keeping the existing checks for "$vera.log2" and
"$vera.log10".
- Around line 10516-10521: The float_clamp tests are missing coverage for the
inverted-bound case (lo > hi); update the cases list used by the float_clamp
test to include a tuple that represents this edge (value, lo, hi, expected)
mirroring the integer clamp inverted-bound entry (i.e., add an entry where lo >
hi and set the expected result to whatever the float_clamp implementation
returns in that scenario), referencing the float_clamp test's cases variable so
the test suite exercises the lo>hi behavior.
- Around line 10415-10434: The test test_inverse_trig_at_known_points currently
only compares atan(1.0) vs atan2(1.0, 1.0) (a symmetric case) and never
exercises asin/acos; update the test body (function main) to call and assert
asin(0.0)==0.0 and acos(1.0)==0.0 and to include a non-symmetric atan2 call to
validate argument ordering (e.g., compute atan2(1.0, -1.0) and compare to the
expected sign/value relative to atan2(-1.0, 1.0) or known constants), and add
asserts that "$vera.asin" and "$vera.acos" appear in result.wat along with
existing "$vera.atan" and "$vera.atan2"; modify the execute/result assertions in
test_inverse_trig_at_known_points to check these new numeric expectations and
wat symbols so the test truly covers asin/acos and verifies atan2 argument
ordering.
In `@vera/codegen/api.py`:
- Around line 2255-2313: Wrap the direct calls to math functions in
_math_unary_host.host and in host_atan2 with try/except so Python
domain/overflow exceptions are converted to IEEE-754 sentinels: catch ValueError
and return float("nan"); catch OverflowError and return math.copysign(math.inf,
x) (for unary host) or math.copysign(math.inf, y) (for host_atan2); keep using
the same identifiers (_math_unary_host, host, host_atan2, linker.define_func) so
the wrappers still get registered via linker.define_func.
In `@vera/wasm/inference.py`:
- Around line 328-338: The Vera-type inference function _infer_fncall_vera_type
is missing the branch for the math built-ins added to WASM inference; add a
corresponding conditional that checks expr.name for ("log", "log2", "log10",
"sin", "cos", "tan", "asin", "acos", "atan", "atan2", "pi", "e", "float_clamp")
and returns "f64", and another for ("sign", "clamp") returning "i64", so
_infer_fncall_vera_type mirrors the WASM logic and avoids falling through to
None.
🪄 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: 813e5c8c-5b68-497d-aa8f-9f5985892132
⛔ Files ignored due to path filters (4)
docs/SKILL.mdis excluded by!docs/**docs/index.htmlis excluded by!docs/**tests/conformance/ch09_math_builtins.verais excluded by!**/*.verauv.lockis excluded by!**/*.lock,!uv.lock
📒 Files selected for processing (31)
AGENTS.mdCHANGELOG.mdCLAUDE.mdDESIGN.mdFAQ.mdHISTORY.mdREADME.mdROADMAP.mdSKILL.mdTESTING.mdpyproject.tomlscripts/check_skill_examples.pyscripts/check_spec_examples.pyspec/09-standard-library.mdspec/12-runtime.mdtests/conformance/manifest.jsontests/test_browser.pytests/test_codegen.pyvera/__init__.pyvera/browser/runtime.mjsvera/codegen/api.pyvera/codegen/assembly.pyvera/codegen/compilability.pyvera/codegen/core.pyvera/codegen/functions.pyvera/codegen/modules.pyvera/environment.pyvera/wasm/calls.pyvera/wasm/calls_math.pyvera/wasm/context.pyvera/wasm/inference.py
There was a problem hiding this comment.
Actionable comments posted: 5
♻️ Duplicate comments (2)
tests/test_codegen.py (1)
10420-10441:⚠️ Potential issue | 🟠 Major
atan2argument-order is still not actually validatedLine 10431 uses
atan2(1.0, 1.0), which is symmetric, so a swapped(x, y)implementation would still pass. This leaves the POSIX(y, x)contract unguarded.Suggested test fix
def test_inverse_trig_at_known_points(self) -> None: - """asin(0)==0, acos(1)==0, atan(1)≈π/4, atan2(1,1)≈π/4. + """asin/acos known points and non-symmetric atan2(y, x) ordering. Each expression exercises a distinct host import; the final - subtraction (atan vs atan2) is zero because both equal π/4, - confirming the two share consistent host implementations. + value must respect atan2(y, x) argument order. """ + import math source = """\ public fn main(-> `@Float64`) requires(true) ensures(true) effects(pure) { - asin(0.0) + acos(1.0) + (atan(1.0) - atan2(1.0, 1.0)) + asin(0.0) + acos(1.0) + atan(1.0) + atan2(1.0, -1.0) } """ result = _compile_ok(source) assert "$vera.asin" in result.wat assert "$vera.acos" in result.wat assert "$vera.atan" in result.wat assert "$vera.atan2" in result.wat v = execute(result, fn_name="main").value - # asin(0) = 0, acos(1) = 0, atan(1) - atan2(1, 1) = 0 → sum 0. - assert v == 0.0, f"inverse-trig identity broken: got {v}" + expected = math.asin(0.0) + math.acos(1.0) + math.atan(1.0) + math.atan2(1.0, -1.0) + assert abs(v - expected) < 1e-12, f"inverse-trig check failed: got {v}, expected {expected}"As per coding guidelines "Add codegen/runtime tests in
tests/test_codegen.pyfor built-in functions — cover normal cases, edge cases (empty inputs, zero values), and composition with other built-ins".🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/test_codegen.py` around lines 10420 - 10441, The test test_inverse_trig_at_known_points currently uses symmetric arguments atan2(1.0, 1.0) so a swapped-arg implementation would still pass; change the test to use asymmetric values (e.g., atan2(0.5, 1.0)) and assert the POSIX contract by comparing atan2(y,x) to atan(y/x) (for x>0) — update the source string in test_inverse_trig_at_known_points (and any related asserts that inspect the compiled wat or execute(result, fn_name="main").value) to use the asymmetric inputs and the corresponding expected numeric check so that a swapped (x,y) implementation fails.spec/12-runtime.md (1)
31-31:⚠️ Potential issue | 🟡 MinorUpdate the subsection prose to match the new import table.
Line 67 still says imports are emitted only for effect operations, but Lines 48-57 now include pure host-backed math imports (
vera.log,vera.sin, etc.). Please align the sentence to avoid an internal contradiction.Suggested fix
-Imports are only emitted when the program actually uses the corresponding effect operations. A pure program produces a module with no imports. +Imports are only emitted when the program actually uses the corresponding host-backed operations (effect operations and selected pure built-ins). A program that uses only inlined built-ins produces a module with no imports.As per coding guidelines
**/*.md: Review Markdown files for factual accuracy against the codebase, broken links, and outdated information.Also applies to: 48-57, 67-67
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@spec/12-runtime.md` at line 31, Update the subsection prose so it no longer claims imports are emitted only for effect operations; instead state that the module imports host functions for both effectful operations and pure host-backed built-ins (e.g., vera.log, vera.sin and other math imports shown in the table). Edit the sentence that currently asserts "imports are emitted only for effect operations" to explicitly mention pure host-backed math imports and align the surrounding text with the import table entries (vera.log, vera.sin, etc.) so the paragraph is factually consistent.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@HISTORY.md`:
- Line 252: Update the HISTORY.md sentence to clearly distinguish
implementations: state that only float_clamp uses f64.max/f64.min in its inline
WAT sequence, while sign and clamp are implemented as short WAT sequences using
select (or whatever their actual implementation is) without referencing
f64.max/f64.min; reference the symbols sign, clamp, and float_clamp so the
wording unambiguously ties float_clamp to f64.max/f64.min and keeps sign/clamp
described separately.
In `@spec/09-standard-library.md`:
- Around line 874-879: The fenced code block that starts with "let `@Float64` =
log(e())" is missing a language tag which triggers MD040 in CI; fix it by adding
the Vera language identifier immediately after the opening backticks (e.g.,
```vera) for that block so the snippet containing expressions like log(e()),
atan2(1.0, 1.0), sign(-42), and clamp(15, 0, 10) is properly tagged.
In `@tests/conformance/manifest.json`:
- Line 809: The manifest entry for the new math built-ins incorrectly references
"Section 9.6.3"; update the spec reference for the conformance entry by changing
the value of the spec_ref field in tests/conformance/manifest.json from "Section
9.6.3" to "Section 9.6.10" so it points to the log/trig/constants/utilities
section that documents the new functions (ensure the same manifest entry that
mentions the new math built-ins and float_clamp uses the corrected spec_ref).
In `@tests/test_browser.py`:
- Around line 513-624: Add parity assertions for the newly-wired unary host ops
by extending tests in tests/test_browser.py: create a small parametrised test
(similar to test_log_identity/test_pi_constant) that compiles and runs snippets
calling log2, log10, tan, and atan via IO.print(float_to_string(...)) using
_compile_vera and _run_node, then compare the stdout-parsed float to the
corresponding math.* value (math.log2, math.log10, math.tan, math.atan) within a
suitable tolerance; name the test something like test_unary_host_parity and
reuse helpers float_to_string, _compile_vera, and _run_node to keep parity
checks consistent.
In `@vera/environment.py`:
- Around line 1471-1474: The comment describing the clamp invariant is incorrect
for inverted bounds; update the documentation near the numeric utilities
(sign/clamp/float_clamp) in vera/environment.py to state that clamp semantics
are defined as min(max(v, lo), hi) and therefore the result equals min(max(v,
lo), hi) (which, when lo > hi, will yield hi), rather than unconditionally
claiming lo <= result <= hi; mention that tests (tests/test_codegen.py) expect
this inverted-bounds behavior for clamp(Int) and float_clamp(Float64).
---
Duplicate comments:
In `@spec/12-runtime.md`:
- Line 31: Update the subsection prose so it no longer claims imports are
emitted only for effect operations; instead state that the module imports host
functions for both effectful operations and pure host-backed built-ins (e.g.,
vera.log, vera.sin and other math imports shown in the table). Edit the sentence
that currently asserts "imports are emitted only for effect operations" to
explicitly mention pure host-backed math imports and align the surrounding text
with the import table entries (vera.log, vera.sin, etc.) so the paragraph is
factually consistent.
In `@tests/test_codegen.py`:
- Around line 10420-10441: The test test_inverse_trig_at_known_points currently
uses symmetric arguments atan2(1.0, 1.0) so a swapped-arg implementation would
still pass; change the test to use asymmetric values (e.g., atan2(0.5, 1.0)) and
assert the POSIX contract by comparing atan2(y,x) to atan(y/x) (for x>0) —
update the source string in test_inverse_trig_at_known_points (and any related
asserts that inspect the compiled wat or execute(result, fn_name="main").value)
to use the asymmetric inputs and the corresponding expected numeric check so
that a swapped (x,y) implementation fails.
🪄 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: a7d4c330-a39f-4aad-ab40-eb467b1f5522
⛔ Files ignored due to path filters (8)
docs/SKILL.mdis excluded by!docs/**docs/index.htmlis excluded by!docs/**docs/index.mdis excluded by!docs/**docs/llms-full.txtis excluded by!docs/**docs/llms.txtis excluded by!docs/**docs/sitemap.xmlis excluded by!docs/**tests/conformance/ch09_math_builtins.verais excluded by!**/*.verauv.lockis excluded by!**/*.lock,!uv.lock
📒 Files selected for processing (31)
AGENTS.mdCHANGELOG.mdCLAUDE.mdDESIGN.mdFAQ.mdHISTORY.mdREADME.mdROADMAP.mdSKILL.mdTESTING.mdpyproject.tomlscripts/check_skill_examples.pyscripts/check_spec_examples.pyspec/09-standard-library.mdspec/12-runtime.mdtests/conformance/manifest.jsontests/test_browser.pytests/test_codegen.pyvera/__init__.pyvera/browser/runtime.mjsvera/codegen/api.pyvera/codegen/assembly.pyvera/codegen/compilability.pyvera/codegen/core.pyvera/codegen/functions.pyvera/codegen/modules.pyvera/environment.pyvera/wasm/calls.pyvera/wasm/calls_math.pyvera/wasm/context.pyvera/wasm/inference.py
There was a problem hiding this comment.
Actionable comments posted: 3
♻️ Duplicate comments (1)
spec/12-runtime.md (1)
31-67:⚠️ Potential issue | 🟡 MinorResolve the contradictory import-emission statement.
Line 67 still says imports are emitted only for effect operations, but Lines 31 and 48-57 now document pure host-backed math imports. Please align that sentence so the subsection is internally consistent.
Suggested doc fix
-Imports are only emitted when the program actually uses the corresponding effect operations. A pure program produces a module with no imports. +Imports are only emitted when the program actually uses the corresponding host-backed operations (effect operations and selected pure built-ins such as log/trig). A pure program that uses only inlined built-ins can produce a module with no imports.As per coding guidelines
**/*.md: Review Markdown files for factual accuracy against the codebase, broken links, and outdated information.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@spec/12-runtime.md` around lines 31 - 67, The paragraph stating "Imports are only emitted when the program actually uses the corresponding effect operations" contradicts the earlier table that shows pure host-backed built-ins (e.g. vera.log, vera.sin, vera.atan2) are also imported; update that sentence to say that imports are emitted for any host-backed features the module uses — including both effect operations (IO.*, State.*, Random.*, etc.) and pure host-backed built-ins (e.g. vera.log, vera.sin, vera.cos, vera.atan2) — so the subsection consistently reflects that a module only imports the host functions it actually uses.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@DESIGN.md`:
- Line 32: The table row referencing "Standard library | 137 built-in functions
| Strings, arrays, maps, sets, decimals, JSON, HTML, Markdown, regex, base64,
URL — no external deps" is missing "math" in the domain breakdown; update that
row to include "math" (and adjust the surrounding rationale text if it mentions
domains) and verify/update the "137 built-in functions" number if the math
additions change the total so the count and domain list remain consistent.
In `@README.md`:
- Line 188: The features list in the README is missing the built-in "math"
domain while still claiming 137 built-ins; update the feature string that
currently includes "typed De Bruijn indices (`@T.n`), mandatory contracts,
algebraic effects (...), 137 built-in functions (...)" to include "math" in the
parenthetical domains (and, if available, add a link to the math docs like
(math) similar to other domains); ensure the wording still matches the 137
built-ins count and existing comma/parenthesis formatting around the built-in
domains.
In `@tests/test_codegen.py`:
- Around line 10363-10590: Add tests in TestMathBuiltins that assert domain-edge
inputs produce NaN by compiling small functions with log(-1.0), asin(2.0), and
acos(2.0) and checking the runtime result is NaN (use math.isnan or compare to
float("nan")). Locate the test class TestMathBuiltins and add a new test method
(e.g. test_math_domain_nan) that uses _compile_ok to compile each
single-expression source and execute(result, fn_name="main").value to assert NaN
for the three builtins (log, asin, acos); reuse the existing pattern from other
tests for compilation and execution.
---
Duplicate comments:
In `@spec/12-runtime.md`:
- Around line 31-67: The paragraph stating "Imports are only emitted when the
program actually uses the corresponding effect operations" contradicts the
earlier table that shows pure host-backed built-ins (e.g. vera.log, vera.sin,
vera.atan2) are also imported; update that sentence to say that imports are
emitted for any host-backed features the module uses — including both effect
operations (IO.*, State.*, Random.*, etc.) and pure host-backed built-ins (e.g.
vera.log, vera.sin, vera.cos, vera.atan2) — so the subsection consistently
reflects that a module only imports the host functions it actually uses.
🪄 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: 4c871554-734b-4812-b483-d801a3d5ef2c
⛔ Files ignored due to path filters (8)
docs/SKILL.mdis excluded by!docs/**docs/index.htmlis excluded by!docs/**docs/index.mdis excluded by!docs/**docs/llms-full.txtis excluded by!docs/**docs/llms.txtis excluded by!docs/**docs/sitemap.xmlis excluded by!docs/**tests/conformance/ch09_math_builtins.verais excluded by!**/*.verauv.lockis excluded by!**/*.lock,!uv.lock
📒 Files selected for processing (31)
AGENTS.mdCHANGELOG.mdCLAUDE.mdDESIGN.mdFAQ.mdHISTORY.mdREADME.mdROADMAP.mdSKILL.mdTESTING.mdpyproject.tomlscripts/check_skill_examples.pyscripts/check_spec_examples.pyspec/09-standard-library.mdspec/12-runtime.mdtests/conformance/manifest.jsontests/test_browser.pytests/test_codegen.pyvera/__init__.pyvera/browser/runtime.mjsvera/codegen/api.pyvera/codegen/assembly.pyvera/codegen/compilability.pyvera/codegen/core.pyvera/codegen/functions.pyvera/codegen/modules.pyvera/environment.pyvera/wasm/calls.pyvera/wasm/calls_math.pyvera/wasm/context.pyvera/wasm/inference.py
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@tests/test_browser.py`:
- Around line 505-660: Add two new browser-parity tests to
TestBrowserMathBuiltins: implement test_float_clamp and test_sign following the
same pattern as existing tests (use _compile_vera to build a small main that
prints float_to_string(float_clamp(...)) and float_to_string(sign(...)), run
with _run_node, and assert the returned stdout matches expected values). For
test_float_clamp include typical and edge cases (values inside range, below min,
above max, and exact bounds) and compare numeric results with tolerances similar
to other float checks; for test_sign include positive, negative, zero, and NaN
semantics (use float_is_nan to assert NaN behavior) and ensure comparisons use
float_to_string/parsing or boolean checks consistent with other tests. Name the
methods test_float_clamp and test_sign so they integrate with pytest and
reference the helper functions _compile_vera, _run_node, float_to_string, and
float_is_nan in the new tests.
🪄 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: ea5412da-232f-4340-9a27-cf07eace4e90
⛔ Files ignored due to path filters (8)
docs/SKILL.mdis excluded by!docs/**docs/index.htmlis excluded by!docs/**docs/index.mdis excluded by!docs/**docs/llms-full.txtis excluded by!docs/**docs/llms.txtis excluded by!docs/**docs/sitemap.xmlis excluded by!docs/**tests/conformance/ch09_math_builtins.verais excluded by!**/*.verauv.lockis excluded by!**/*.lock,!uv.lock
📒 Files selected for processing (31)
AGENTS.mdCHANGELOG.mdCLAUDE.mdDESIGN.mdFAQ.mdHISTORY.mdREADME.mdROADMAP.mdSKILL.mdTESTING.mdpyproject.tomlscripts/check_skill_examples.pyscripts/check_spec_examples.pyspec/09-standard-library.mdspec/12-runtime.mdtests/conformance/manifest.jsontests/test_browser.pytests/test_codegen.pyvera/__init__.pyvera/browser/runtime.mjsvera/codegen/api.pyvera/codegen/assembly.pyvera/codegen/compilability.pyvera/codegen/core.pyvera/codegen/functions.pyvera/codegen/modules.pyvera/environment.pyvera/wasm/calls.pyvera/wasm/calls_math.pyvera/wasm/context.pyvera/wasm/inference.py
Fifteen new pure functions across four groups — the standard math library every other language has. Unlocks scientific computing, graphics, audio, physics, and statistics workloads. Operations: - Logarithmic: log, log2, log10 - Trigonometric: sin, cos, tan, asin, acos, atan, atan2 - Constants: pi(), e() - Numeric utilities: sign, clamp, clamp_float Implementation split by whether WASM has native instructions: HOST-IMPORTED (10): The log/trig functions have no WASM equivalent, so they route through host imports wrapping Python's `math` module and the browser's `Math` global. Per-op gated via `_math_ops_used` — a program that only uses `sin` imports only `vera.sin`, keeping modules small. IEEE 754 semantics: NaN for out-of-domain inputs, ±Infinity for overflow. atan2 takes `(y, x)` matching POSIX. INLINED AS WAT (5): - pi() / e() become `f64.const 3.141592653589793` / `f64.const 2.718281828459045` — no host call for a constant. - sign(x) inlines as `(x > 0) - (x < 0)` using two comparison widenings and a subtraction, branchless. - clamp(v, lo, hi) uses two WASM `select` instructions for min(max(v, lo), hi). When lo > hi the outer min dominates and the result is hi (matches Rust's pre-1.50 behaviour). - clamp_float uses native `f64.max` and `f64.min`. NaN propagates through both, intentional. Files touched (the pattern is now well-trodden after #463, #465): - environment.py: 15 FunctionInfo entries, all pure-effect - codegen/core.py: _math_ops_used set + propagation to 4 CompileResult sites (caught a bug where the primary return path was missing the field — would have silently emitted no host functions for modules that need them) - codegen/api.py: CompileResult.math_ops_used field, 10 host functions via a factory to avoid the classic late-binding closure trap - codegen/compilability.py: _MATH_BUILTINS frozenset + scan - codegen/functions.py: propagate WasmContext._math_ops_used back to codegen - codegen/assembly.py: gated import declarations for the 10 host-imported ops - codegen/modules.py: known-names allowlist for all 15 - wasm/context.py: _math_ops_used mixin state - wasm/calls_math.py: _translate_math_unary_host, _translate_atan2, _translate_pi, _translate_e, _translate_sign, _translate_clamp, _translate_clamp_float - wasm/calls.py: dispatch branches for all 15 - wasm/inference.py: Float64/Int return types for all 15 — the inferencer needs to know that `log(x)` returns f64, otherwise `log(x) + log(y)` emits `i64.add` and wasmtime rejects the module at load time - browser/runtime.mjs: `Math.log`/`Math.sin`/etc. bindings + `atan2` argument-order comment Tests: - tests/conformance/ch09_math_builtins.vera — verify level; covers signature plumbing for all 15 without the wall-clock / FP-precision flake of run-level assertions on trig - TestMathBuiltins with 8 tests: identities (log/e, sin/cos at zero, atan vs atan2), pi/e exact constant values, sign across -/0/+, clamp on 7 cases including negative ranges and singletons, clamp_float on 4 cases, and a gating regression that confirms trivial programs don't emit unused math imports - TestBrowserMathBuiltins with 5 parity tests Documentation: - SKILL.md: new "Logarithmic, trigonometric, and numeric utility functions" subsection - spec/09-standard-library.md: new §9.6.10 with the full table; Float64 Predicates renumbered §9.6.12 - spec/12-runtime.md: 10 new import table rows - Doc counts: 76 → 77 conformance, 3,369 → 3,387 tests Also bundled (per workflow: closing PR owns the shuffle): - ROADMAP: #467 removed from "What's next" and from Phase 4a - HISTORY: v0.0.116 row added to Stage 11 table - Version bump 0.0.115 → 0.0.116 in pyproject.toml, vera/__init__.py, docs/index.html, README.md, and uv.lock - Built-in function count 122 → 137 in README / HISTORY / ROADMAP / FAQ Co-Authored-By: Claude <noreply@anthropic.invalid>
Summary
Fifteen new pure math functions. Closes #467.
Logarithmic:
log,log2,log10Trigonometric:
sin,cos,tan,asin,acos,atan,atan2(POSIX(y, x)argument order)Constants:
pi(),e()Numeric utilities:
sign,clamp,clamp_floatImplementation split
vera.{op}wrapping Python'smathmodule (Python runtime) orMath.*(browser). Per-op gated via_math_ops_usedso unused imports don't bloat modules.pi()/e()becomef64.const 3.141592…(no host call for a constant);signuses branchless(x > 0) - (x < 0);clampuses two WASMselectinstructions;clamp_floatuses nativef64.max/f64.min.Tests
tests/conformance/ch09_math_builtins.vera— verify level (covers signatures + effect inference for all 15; no run-level assertions because floating-point precision would flake).tests/test_codegen.py::TestMathBuiltins— 8 tests: identities (log(e()) == 1,sin(0) + cos(0) == 1,atan(1) == atan2(1,1)), exact pi/e constants, sign across negative/zero/positive, 7-case clamp, 4-case clamp_float, and a gating regression that confirms trivial programs don't emit unused math imports.tests/test_browser.py::TestBrowserMathBuiltins— 5 parity tests including anatan2(1, -1)case that disambiguates (y,x) vs (x,y) argument order.Documentation
SKILL.md: new "Logarithmic, trigonometric, and numeric utility functions" subsection.spec/09-standard-library.md: new §9.6.10 with the full table; Float64 Predicates renumbered §9.6.12.spec/12-runtime.md: 10 new import-table rows.Also bundled
Per workflow (closing PR owns the roadmap→history shuffle):
Test plan
mypy vera/cleanruff check --select S vera/clean (the CI lint)pytest tests/ -q— 3,373 passed, 14 skipped (13 new tests)check_spec_examples.py,check_skill_examples.py,check_conformance.py,check_doc_counts.py,check_version_sync.pyall greenvera runon a program exercising all 15 functions🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Documentation
Tests
Chores