Skip to content

perf(codegen): lower proven booleans into native numeric ops - #8031

Merged
proggeramlug merged 3 commits into
PerryTS:mainfrom
proggeramlug:feat/5497-type-directed-native-ops
Aug 13, 2026
Merged

perf(codegen): lower proven booleans into native numeric ops#8031
proggeramlug merged 3 commits into
PerryTS:mainfrom
proggeramlug:feat/5497-type-directed-native-ops

Conversation

@proggeramlug

@proggeramlug proggeramlug commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Summary

  • convert guard-proven Boolean i1 literals and locals directly to f64 with uitofp for arithmetic consumers
  • lower proven Boolean/number relational comparisons to native fcmp instead of js_rel_*
  • keep annotation-only and invalidated Boolean facts on dynamic coercion/dispatch, preserving as any semantics
  • add IR-census coverage plus Boolean arithmetic parity coverage

This is a focused Lever E slice that advances #5497; it does not close the broader tracker.

Validation

  • cargo test -p perry-codegen boolean_number_tests --lib
  • cargo test -p perry-codegen --lib (967 passed)
  • ./scripts/test_affected_crates.sh --base origin/main
  • Node 26.5.1 parity: test_bool_arithmetic (1/1 passed)
  • python3 scripts/check_test_registration.py
  • ./scripts/pre-tag-check.sh --quick (all relevant checks passed; the run reports the existing GC inventory ratchet at unchanged crates/perry-codegen/src/expr/property_set.rs:1457)

No version files were changed. The required PR-numbered changelog fragment is included.

Summary by CodeRabbit

  • New Features

    • Improved arithmetic and comparison handling for statically proven Boolean values.
    • Boolean values can now convert directly to numbers for supported numeric operations.
    • Added optimized Boolean-to-number relational comparisons.
  • Bug Fixes

    • Preserved dynamic coercion and string concatenation when Boolean values are invalidated or cannot be safely proven numeric.
  • Tests

    • Added coverage for Boolean arithmetic, comparisons, nested expressions, and invalidated Boolean annotations.
  • Documentation

    • Updated the type-lowering checklist and changelog with the new behavior.

@coderabbitai

coderabbitai Bot commented Aug 13, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ef7f7ec3-a05b-4a23-bc45-62c9637b8d7e

📥 Commits

Reviewing files that changed from the base of the PR and between 8b40f26 and 490958a.

📒 Files selected for processing (8)
  • TYPE_LOWERING.md
  • changelog.d/8031-boolean-native-numeric-ops.md
  • crates/perry-codegen/src/expr/binary.rs
  • crates/perry-codegen/src/expr/boolean_number_tests.rs
  • crates/perry-codegen/src/expr/mod.rs
  • crates/perry-codegen/src/stmt/let_stmt.rs
  • crates/perry-codegen/src/type_analysis/numeric.rs
  • test-files/test_bool_arithmetic.ts

📝 Walkthrough

Walkthrough

Proven native Booleans now convert directly to f64 for arithmetic and Boolean/number comparisons. Declared-only or invalidated Boolean and numeric proofs retain dynamic coercion and dispatch. New IR-census and end-to-end tests cover both paths.

Changes

Boolean numeric lowering

Layer / File(s) Summary
Proven Boolean conversion and comparison
crates/perry-codegen/src/expr/mod.rs
Proven Boolean literals, locals, and compiler-private async controls convert from i1 to f64 with uitofp. Boolean/number comparisons use native ordered fcmp when operand proofs are valid.
Arithmetic dispatch integration
crates/perry-codegen/src/type_analysis/numeric.rs, crates/perry-codegen/src/stmt/let_stmt.rs, crates/perry-codegen/src/expr/binary.rs
Canonical raw-f64 analysis excludes declared-only binary proofs. Numeric locals track non-numeric initializers. Arithmetic lowering uses native Boolean conversion only for proven-safe operands.
Lowering validation and acceptance evidence
crates/perry-codegen/src/expr/boolean_number_tests.rs, test-files/test_bool_arithmetic.ts, TYPE_LOWERING.md, changelog.d/8031-boolean-native-numeric-ops.md
Tests and documentation cover native Boolean arithmetic, relational comparisons, nested declared-only expressions, and dynamic fallback after string assignment.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Mergeability Score: ⚪ Minimal · up to 49095

The PR makes a focused boolean numeric-lowering change with passing validation; no actionable merge-blocking risk remains beyond normal checks and review.

Sequence Diagram(s)

sequenceDiagram
  participant BooleanExpression
  participant ExprLowering
  participant BinaryLowering
  participant LLVM
  BooleanExpression->>ExprLowering: provide proven i1 value
  ExprLowering->>LLVM: emit uitofp i1 to f64
  BinaryLowering->>LLVM: emit native arithmetic or ordered fcmp
  BooleanExpression->>BinaryLowering: provide invalidated or declared-only value
  BinaryLowering->>LLVM: retain dynamic coercion and dispatch
Loading

Possibly related PRs

  • PerryTS/perry#7831: Extends its declared-only numeric tracking and lowering safeguards.
  • PerryTS/perry#6860: Uses related proven-type fast paths in binary numeric code generation.
  • PerryTS/perry#7839: Addresses related + dispatch guards for erased TypeScript type declarations.

Suggested reviewers: thehypnoo

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main codegen change: lowering proven booleans into native numeric operations.
Description check ✅ Passed The description explains the changes, scope, related issue, and validation steps, but it omits explicit template headings for Changes, Related issue, and Checklist.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@proggeramlug proggeramlug left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Blocking on exact head 7a1f654. I reproduced a semantic regression with a focused IR test: let flag = true; let liar: number = "4" as any; flag < (liar + 1). JavaScript evaluates this as true because the RHS is "41". This head emits a raw fadd on the NaN-boxed string followed by fcmp olt, producing false, and omits js_rel_lt. The new relational gate accepts the nested Add because expr_produces_canonical_raw_f64 blanket-admits Binary via type-level is_numeric_expr, even though a declared-only Add tree can carry a boxed/string result. Please make the Boolean gate reject declared-only/noncanonical nested binary trees and add this regression. This is independent proof from emitted IR, not a CI result. No version bump needed.

@proggeramlug
proggeramlug force-pushed the feat/5497-type-directed-native-ops branch from 7a1f654 to 490958a Compare August 13, 2026 11:16
@proggeramlug

proggeramlug commented Aug 13, 2026

Copy link
Copy Markdown
Contributor Author

Addressed in 490958a.

The fix makes the existing proof boundary explicit in both places involved:

  • a numeric local initialized by a non-numeric value (for example const liar: number = "4" as any) now carries the declared-only hazard;
  • expr_produces_canonical_raw_f64 rejects binary trees carrying that hazard, so the Boolean relational fast path cannot admit the nested +.

I added the exact flag < (liar + 1) IR regression. It now requires both js_dynamic_string_or_number_add and js_rel_lt, while the positive flag < 2 case still requires native uitofp + fcmp.

Validated with all 968 perry-codegen library tests, the affected-crate sweep, and the optimized test_bool_arithmetic parity fixture (1/1 pass). No version bump.

@proggeramlug proggeramlug left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Re-audited exact head 490958a against the previously demonstrated nested declared-only numeric regression. The corrected IR retains both js_dynamic_string_or_number_add and js_rel_lt for a Number-annotated local holding a string, while the positive proven-boolean case retains native fcmp. The new declared-only seed and canonical-f64 rejection are aligned, the focused boolean-number tests pass, and the full perry-codegen library suite passes (968/968). No blocking issue found.

@proggeramlug
proggeramlug merged commit 056b6b8 into PerryTS:main Aug 13, 2026
7 of 18 checks passed
@proggeramlug
proggeramlug deleted the feat/5497-type-directed-native-ops branch August 13, 2026 12:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant