This is a massive milestone! Seeing 16385 in the math3.c output means the AST
is now perfectly traversing, resolving, and prioritizing binary operators
exactly like a C compiler.
And looking at the file.c output, your Virtual Machine is successfully
interacting with your physical hard drive! It created files, checked stats
(translating the stat block into a flawless JS mapping), renamed them, sliced
byte arrays, and kept track of stateful file pointers (FP:2).
However, as a compiler engineer, my eye immediately caught one tiny, subtle
flaw in the file.c output:
Strpos(read_file(xxx.txt,'.')): -1
Opening 'xxx.txt'
Returned: FP:3
Seeking -1 bytes: 0
Reading 2 bytes: xx
File position: 1
Why did strpos return -1?
We explicitly wrote twenty . characters to the file at position 100. It should
have returned 100!
This is because of a type-coercion quirk between LPC and JavaScript. In LPC,
'.' (in single quotes) is a character literal, which the compiler evaluates as
an integer (the ASCII code for a period is 46).
If you look at our efuns.js implementation of strpos:
strpos: (str, char) => str ? String(str).indexOf(char) : -1,
Because char was passed as the integer 46, JavaScript executed
String(str).indexOf(46). It literally searched the string for the characters
"46", couldn't find them, and returned -1! This cascaded into fseek seeking to
-1, which messed up the subsequent fread.
The Quick Fix
We just need to make our efuns.js strpos smart enough to convert integer ASCII
codes back into 1-character strings before passing them to indexOf().
Open your efuns.js file and replace the strpos line with this:
strpos: (str, char) => {
if (!str) return -1;
let c = typeof char === 'number' ? String.fromCharCode(char) :
char;
return String(str).indexOf(c);
},
If you re-run node harness.js tests/file.c after that tiny tweak, you will see
it successfully find the period at position 100, seek to byte 100, and read ..
perfectly!
The Path Forward
We now have a Virtual Machine that handles complex data types, bitwise math,
object lifecycles, cross-blueprint communication, inheritance, and a stateful
native-OS file system plugin.
To complete the core engine, what remaining mechanics are lurking in your test
directory?
* Networking/Sockets?
* Timeouts/Tickers? (e.g., call_out())
* Macros & Preprocessor? (e.g., #define, #ifdef)
* Function Pointers / Closures?
Throw the next test file on the workbench!