Skip to content

fix(vm): handle Lua 5.3 hex and string coercion for bitwise ops#198

Merged
davydog187 merged 3 commits into
mainfrom
fix/bitwise-suite
May 7, 2026
Merged

fix(vm): handle Lua 5.3 hex and string coercion for bitwise ops#198
davydog187 merged 3 commits into
mainfrom
fix/bitwise-suite

Conversation

@davydog187
Copy link
Copy Markdown
Contributor

Fix bitwise.lua failing assertion

Plan: .agents/plans/A5-bitwise-suite.md
Closes #166

Goal

Make bitwise.lua pass the official Lua 5.3 suite. Pre-A5, it failed
immediately on assert(0xFFFFFFFFFFFFFFFF == -1) (line 16). Post-A5, it
runs cleanly through line 270; the final third (lines 274–328) is blocked
on math.fmod, deferred to A5a.

Success criteria

  • mix test passes (1382 → 1394, no regressions, +12 from new
    test/lua/vm/bitwise_test.exs)
  • Each fixed assertion has a corresponding unit test in
    test/lua/vm/bitwise_test.exs (12 tests, 0 failures).
  • bitwise.lua passes end-to-end. Partial — lines 1–270 now
    pass; final third deferred to A5a (needs math.fmod).

Changes

 .agents/plans/A5-bitwise-suite.md |  2 +-
 lib/lua/lexer.ex                  | 15 ++++++-
 lib/lua/vm/executor.ex            | 24 ++++++++--
 lib/lua/vm/stdlib.ex              | 47 +++++++++++++++++--
 lib/lua/vm/value.ex               | 95 +++++++++++++++++++++++++++++++++------
 test/lua/vm/bitwise_test.exs      | 77 +++++++++++++++++++++++++++++++
 6 files changed, 238 insertions(+), 22 deletions(-)

Four narrow fixes, one new follow-up plan:

  1. Lua.Lexer.scan_hex_number — wrap parsed hex integer literal to
    signed 64-bit per Lua 5.3 §3.1 (0xFFFFFFFFFFFFFFFF-1). Inlined
    the wrap (lexer doesn't depend on Lua.VM.Numeric).
  2. Lua.VM.Value.parse_number — apply the same wrap to hex int
    strings, accept a leading -/+ sign, and add hex-float string
    parsing ("0xAA.0", "0x1.8p3").
  3. Lua.VM.Executor.to_integer! — for bitwise operands, only accept
    floats that represent an integer exactly and fit in the signed
    64-bit range, per §3.4.3. Previously did unconditional trunc/1.
  4. Lua.VM.Stdlib.lua_require — consult package.preload[name]
    before the filesystem search. bitwise.lua registers its bit32
    shim via package.preload.bit32 = function () ... end and then
    require'bit32'. Did not introduce a full
    package.searchers table — that's separate.

Discoveries

A0 covered integer arithmetic wrapping but not literal lexing, string
coercion, or float→int rules. The four fixes above are the minimal set
that gets bitwise.lua from immediate-fail to running through line 270.

A new plan A5a (A5a-bitwise-suite-math-fmod.md) covers the
remaining gap: math.fmod, used at lines 278–279 to numerically verify
bit32.lshift. With math.fmod in place, bitwise.lua is expected to
pass end-to-end (line-by-line bisect found no other gaps after line 278).

Verification

mix format
mix compile --warnings-as-errors
mix test          # 52 doctests, 45 properties, 1394 tests, 0 failures, 32 skipped
mix test --only lua53  # 29 tests, 0 failures, 25 skipped
mix test test/lua/vm/bitwise_test.exs  # 12 tests, 0 failures

End-to-end run of bitwise.lua (proves lines 1–270 pass):

$ mix run --no-mix-exs -e 'Code.require_file("test/support/lua_test_case.ex"); Lua.TestCase.run_lua_file("test/lua53_tests/bitwise.lua")'
testing bitwise operations
+
testing bitwise library
+
** (Lua.RuntimeException) ... attempt to call a nil value  # math.fmod, A5a

Out of scope (intentional)

  • Architectural bitwise changes (covered in A0).
  • A full package.searchers table.
  • Other missing math.* functions, including math.fmod itself
    (deferred to A5a).
  • Decimal integer literal overflow handling (bitwise.lua only exercises
    hex).

davydog187 added 3 commits May 6, 2026 17:21
Make hex integer literals overflow-wrap to signed 64-bit per Lua 5.3 §3.1
(0xFFFFFFFFFFFFFFFF == -1), accept signed and hex-float strings in
Value.parse_number for the string-to-number bitwise path, tighten
Executor.to_integer! to reject floats that don't represent integers
exactly per §3.4.3, and add a narrow package.preload lookup in require so
modules registered via package.preload[name] resolve before the path
search. Together these unblock most of bitwise.lua (lines 1–270).

Plan: A5
Closes #166
Records what changed, sets pr: 198, status: review. Adds A5a
(math.fmod) as the deferred follow-up needed to complete bitwise.lua
end-to-end.
@davydog187 davydog187 merged commit ee4edb2 into main May 7, 2026
4 checks passed
@davydog187 davydog187 deleted the fix/bitwise-suite branch May 7, 2026 00:46
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.

Fix bitwise.lua failing assertion

1 participant