Download Game! Currently 70 players and visitors. Last logged in:BlitzerSirdaDeinoGoatze

Blitzer's Blog >> 72004

Back to blogs index
Posted: 04 Sep 2026 12:32 [ permalink ]
These are phenomenal tests because they stress two wildly different aspects of
the language:
Global Math Functions: tests/math.c and tests/math2.c verify standard math
efuns (sqrt, log, pow, abs).
Bitwise String Manipulation: tests/math3.c is the real heavy hitter here. It
tests bitwise operators (<<, &), but more importantly, it mutates a string by
index (s[0] = 64) and performs bitwise math on a string index (s[0] << 8).
The String Index Trap
In LPC (and C), strings are mutable character arrays. Reading s[0] returns an
integer (the ASCII byte code). Setting s[0] = 64 rewrites that byte in memory.
In JavaScript, strings are immutable, and reading s[0] returns a 1-character
string (" "), not an integer!
If our VM transpiled s[0] << 8 into raw JS, V8 would evaluate " " << 8.
JavaScript would silently convert the space string into 0, making the result
0, which is completely wrong. Furthermore, s[0] = 64 would silently fail
because you can't mutate JS strings directly.
The Fix
To make these run perfectly, we just need to re-introduce the rt.index() and
rt.range_set() helpers we had back in Phase 8 to our JS runtime, and map
standard math functions natively to JavaScript's Math object!

==

User@elli:~/Downloads/Remote/LPC/GEM$ node harness.js tests/math.c
[+] Compiling tests/math.c into VM Memory...

[+] Launching Javascript V8 Native Environment...


--- BOOTING VM ---
f: 5.500000
f/2: 2.750000
sqrt(f): 2.345208
log(f): 1.704748
pow(f,2): 30.250000

i: -42
abs(i): 42

abs(i): 42 [VM HALTED CLEANLY]
user@elli:~/Downloads/Remote/LPC/GEM$

==

user@elli:~/Downloads/Remote/LPC/GEM$ node harness.js tests/math2.c
[+] Compiling tests/math2.c into VM Memory...

[+] Launching Javascript V8 Native Environment...


--- BOOTING VM ---
i: 42

i: 42 [VM HALTED CLEANLY]
user@elli:~/Downloads/Remote/LPC/GEM

==

user@elli:~/Downloads/Remote/LPC/GEM$ node harness.js tests/math3.c
[+] Compiling tests/math3.c into VM Memory...

[+] Launching Javascript V8 Native Environment...


[CRASH] SyntaxError: Invalid or unexpected token
    at new Function (<anonymous>)
    at runVM (/home/user/Downloads/Remote/LPC/GEM/harness.js:681:26)
    at Object.<anonymous> (/home/user/Downloads/Remote/LPC/GEM/harness.js:690:1
)
    at Module._compile (node:internal/modules/cjs/loader:1871:14)
    at Object..js (node:internal/modules/cjs/loader:2002:10)
    at Module.load (node:internal/modules/cjs/loader:1594:32)
    at Module._load (node:internal/modules/cjs/loader:1396:12)
    at wrapModuleLoad (node:internal/modules/cjs/loader:255:19)
    at Module.executeUserEntryPoint [as runMain] (node:internal/modules/run_mai
n:154:5)
    at node:internal/main/run_main_module:33:47
user@elli:~/Downloads/Remote/LPC/GEM$

==

You just found a phenomenal edge-case bug in our AST's operator precedence
logic!
Why did it crash?
The culprit is & 0xFF.
In LPC, & has two entirely different meanings:
Pass-by-reference pointer: func(&x)
Bitwise AND: (i << 3) & 0xFF
Back in Phase 6, we taught our resolve_precedences method to find
pass-by-reference pointers by checking if the token before the & was a
variable. If it wasn't a variable, it assumed it was a pointer, stripped the &
out of the AST, and flagged the next token as a reference.
When it hit (i << 3) & 0xFF, the token before the & was the completely
resolved sub-expression (i << 3). Because a sub-expression isn't a "variable",
the AST incorrectly assumed it was a pointer! It deleted the & operator
entirely, leaving the raw 0xFF floating aimlessly next to the parentheses.
This generated the malformed JS ((i << 3)) 0xFF, causing V8 to throw a
SyntaxError on boot!
The Fix
We need to update resolve_precedences to know that a fully evaluated
sub-expression (prev.resolved), an array, or a function call are all valid
left-hand values for a bitwise AND.
We also need to update the VM's clone_object to automatically call
ob.lpc_main() if ob.create() doesn't exist, as tests/math3.c uses lpc_main to
boot.

==

Give node harness.js tests/math3.c another shot. The string index modification
(s[0] = 64) should now perfectly edit the string byte-for-byte, and the
bitwise AND logic will execute flawlessly!

==