The objective is to implement the syntactic analysis engine in pure JavaScript.
- 1.1. Implement the core Monadic Parser:
- Create the base structure (
Parser(state) -> { result, rest, error }). - Implement fundamental combinators:
sequence,sequenceObj,choice,many,optional,lazy. - Implement transformation combinators:
map(for AST generation). - Optimize token parsers (using strict
strmatching overregexfor static symbols/keywords to boost performance).
- Create the base structure (
- 1.2. Create base Lexers (Primitives):
- Line-Based Architecture: Create the strict
eos(End Of Statement) token to rigorously handle line breaks\n, colons:, and empty lines. - Horizontal spaces (
ws,optWs) and comments (ignored until line break). - Numbers (integers and floats, e.g.,
100,.5). - Strings (
"..."). - Case-insensitive identifiers (variables, function names, including type suffixes like
$,%).
- Line-Based Architecture: Create the strict
- 1.3. Custom Test Framework (Quality Harness):
- Implement test orchestrator with performance KPIs (execution time per test) and global pass/fail summaries.
- Add V8 stack trace extraction to accurately map syntax/parse errors to specific source files during CI.
Parse the Nibbles source code to build a typed Abstract Syntax Tree (AST).
- 2.1. Parse Declarations and Types:
- Handle
DEFINT A-Z. - Handle structure creation with
TYPE ... END TYPE. - Handle array and global variable declarations
DIM [SHARED] array(x TO y) AS type. - Handle constants
CONST name = value.
- Handle
- 2.2. Parse Control Flow:
- Conditions:
IF ... THEN ... ELSE ... END IF. - Loops:
FOR ... TO ... STEP ... NEXT,DO ... LOOP UNTIL. - To do (if necessary):
WHILE ... WEND,SELECT CASE ... END SELECT.
- Conditions:
- 2.3. Parse Subroutines and Functions:
-
DECLARE SUB / FUNCTION. - Definitions
SUB name (args) ... END SUB.
-
- 2.4. Parse Operators and Expressions:
- Mathematical operators (
+,-,*,/,MOD,INT()). - Logical operators (
AND,OR,NOT,>,<,<>). - Complex access: array calls or type properties (
arena(r, c).sister).
- Mathematical operators (
Create the state machine (Virtual Memory) that will store the program's state.
- 3.1. Memory and Scope Management:
- Create a chained
Environmentmanager to store global and local variables. - [CRITICAL] Enforce MS-DOS "Flat Scoping" to prevent JS-style lexical bleeding, isolating the Main Module strictly from Subroutine scopes by restricting hierarchical traversal to the Tier 1 Global Environment.
- Create a chained
- 3.2. QBasic Array Abstraction:
- Implement the
QArrayclass to flatten multi-dimensional arrays with custom bounds (e.g.,1 TO 50).
- Implement the
Bridge the gap between specific QBasic DOS commands and browser APIs.
- 4.1. VGA Text Mode Video Engine (80x25):
- Implement Pixel-Perfect rendering via bitwise manipulation of an
ImageDatabuffer on a<canvas>. - Use the authentic DOSBox bitmapped ROM (Code Page 437) for absolute block fidelity (CHR$ 219, 220, 223).
- Wire commands:
COLOR(text, background),CLS,LOCATE,PRINT.
- Implement Pixel-Perfect rendering via bitwise manipulation of an
- 4.2. I/O Engine (Keyboard & Time):
- Wire
INKEY$to JavaScriptkeydown/keyupevents with a FIFO keystroke buffer. - Wire
TIMERto local time (seconds since midnight). - Add interactive console commands like
LINE INPUT.
- Wire
- 4.3. Basic Audio Engine (PC Speaker):
- Wire the
PLAYcommand (e.g.,"MBT160O1L8CDEDCDL4ECC") using the Web Audio API (Macro Music Language).
- Wire the
- 4.4. Motherboard and BIOS (Segmented Memory):
- Purist wiring of a 1MB RAM space (Segment:Offset) for
DEF SEG,PEEK, andPOKE. - Simulation of the BIOS Data Area (Equipment Word) and implementation of Memory-Mapped I/O (keyboard buffer flush hack via address
&H41A).
- Purist wiring of a 1MB RAM space (Segment:Offset) for
Connect the AST to the hardware via a virtual processor.
- 5.1. Generator-Based Evaluation Engine (Anti-Freeze):
- Transform the Evaluator into a synchronous iterator (
function*andyield*) to avoid Promise (async/await) hell and guarantee performance.
- Transform the Evaluator into a synchronous iterator (
- 5.2. Parse Hardware Instructions:
- Add instruction parsers (
statements.js) for hardware:CLS,PRINT,LOCATE,COLOR,POKE,ASSIGN.
- Add instruction parsers (
- 5.3. CPU Loop (Runner):
- Implement "Instruction Cycle" (Ticks) pacing limited by
requestAnimationFrame(e.g., 5000 cycles / frame) allowing total control over execution speed.
- Implement "Instruction Cycle" (Ticks) pacing limited by
Implement complex structures necessary for game logic.
- 6.1. Arrays and Types (UDT) at Runtime:
- Teach the Evaluator to handle
TYPE_DECLnodes (register the structure's "blueprint"). - Teach the Evaluator to instantiate
DIM(and dynamically resize viaREDIM), handling both array structures and single scalar variable declarations (DIM x AS type). - Implement deep cloning for UDTs to prevent JavaScript object reference mutation during
SWAPandASSIGN.
- Teach the Evaluator to handle
- 6.2. Subroutines (
SUBandFUNCTION):- Handle
SUBdefinition registration. - Implement the
CALLmechanism: creating a sub-scope (new memory "bubble") and passing arguments. - [CRITICAL] Implement Pass-by-Reference for arguments.
- [CRITICAL] Handle
FUNCTIONreturn values (assignment to the function's name).
- Handle
- 6.3. Jumps and Advanced Control Flow:
- Implement
GOSUB ... RETURN(heavily used in Nibbles for screen/music mini-routines). - [CRITICAL] Refactor AST to allow Single-Line IFs (
IF ... THEN statementwithoutEND IF). - [CRITICAL] Add
WHILE ... WENDloop structure. - Add support for conditions at the beginning of DO loops (
DO WHILE/UNTIL cond ... LOOP).
- Implement
- 6.4. Missing Operators and Literals:
- Add integer division
\with operand rounding, andMODoperator. - Add logical operators
AND,OR,NOT. - Add exponentiation
^and bitwise operatorsXOR,EQV,IMP. - Add support for octal format (
&O) and scientific notation (E,D).
- Add integer division
The final boss: Assemble everything to run the original game, correcting critical architectural flaws.
- 7.1. Source File Integration:
- Fetch text loading of the original
NIBBLES.BASfile. - Full end-to-to parsing (requires prior patching of the
eosregex against ReDoS).
- Fetch text loading of the original
- 7.2. Debugging and Structural Corrections:
- Scope Correction: Isolate
LABELtags by scope (Main vs Sub/Function) inevaluator.jsto avoid collisions. - Memory-Mapped VRAM: Link
POKEinstructions from the&HB800segment (Memory) toVGAengine cells.
- Scope Correction: Isolate
- 7.3. Engine Tweaks (Pre-JIT):
- VGA Optimization (Memory): Implement rendering via
Uint32Arrayfor fast buffer manipulation and pure Dependency Injection (DOM decoupling). - VGA Optimization (CPU): Implement a "Dirty Rectangles" system to update only modified areas and secure framerate.
- CPU Lightening: Optimize Generator Tick frequency (per-statement instead of per-node) and implement Hybrid Runner (Retro/Turbo UI).
- VGA Optimization (Memory): Implement rendering via
- 7.4. Play Nibbles!
Decouple the Virtual Machine core from the Web interface to ensure a clean architecture.
- 7.5.1. Entry Point Renaming:
- Rename
main.jstowebvm.jsto explicitly designate it as the browser orchestrator.
- Rename
- 7.5.2. UI Logic Extraction:
- Create
src/ui.jsto encapsulate all DOM manipulations (Sliders, Checkboxes, Event Listeners). - Establish a clean event-driven communication layer between
ui.jsandwebvm.js.
- Create
Finalize the user experience with dynamic loading, emulator-standard controls, and source inspection.
- 7.6.1. Dynamic ROM Loader & Build System:
- Implement VM reset capabilities (Clear RAM, Reset Environment, Cancel AnimationFrame) in
webvm.js. - Create
tools/build_catalog.jswith private draft filtering to statically generate the ROM index. - Wire the
#rom-selectorto fetch the catalog and execute new.basfiles on the fly.
- Implement VM reset capabilities (Clear RAM, Reset Environment, Cancel AnimationFrame) in
- 7.6.2. Fullscreen & Pixel-Perfect Scaling:
- Implement the HTML5 Fullscreen API.
- Add CSS logic to maintain the original 4:3 aspect ratio and
image-rendering: pixelatedduring viewport resizes.
- 7.6.3. Split-Screen Pro IDE Layout:
- Redesign the interface into a modern workspace (Editor on the left, Execution on the right).
- Display the raw, original
.bassource code currently being executed. - Upgrade the CPU speed visualizer to reflect realistic retro hardware frequencies (MHz).
- 7.6.4. VM Execution Controls (State Management):
- Implement a
Play / Pausetoggle to freeze/resume the Virtual CPUrequestAnimationFrameloop. - Implement
Restart(halt execution, clear VRAM, and reboot the current ROM).
- Implement a
- 7.6.5. Canvas Screenshot Tool:
- Add a "Screenshot" button using native
canvas.toBlob. - Ensure the output is a clean, lossless PNG preserving the DOS pixel ratio.
- Add a "Screenshot" button using native
- 7.6.6. Native Syntax Highlighting (Dog Fooding):
- Refactor
lexers.jsto explicitly yieldCOMMENTandWHITESPACEtokens instead of silently swallowing them ineos. (Included strict regex exclusion of\r\nin comments to fix UI line break rendering). - Build a lightweight
Tokenizerthat processes the loaded source code through our Monadic Lexers. - Render the token stream as colored HTML in the UI without external dependencies.
- Refactor
- 7.6.7. Source File Injection:
- Allow users to import or drag-and-drop local
.BASfiles directly into the WebVM for instant execution.
- Allow users to import or drag-and-drop local
- 7.6.8. Execution Context Tracking:
- Implement a visual tracker in the IDE that highlights the exact line of code currently being executed when the VM is paused.
- 7.6.9. Zero-Backend Media Studio:
- Implement a Web Worker-based 24FPS GIF recorder to capture pixel-perfect XOR graphics without blocking the CPU loop.
Ensure safe and authentic loading of legacy source files.
- 8.1. CP437 / Unicode Translation Layer:
- Create a bidirectional mapping table (
toCP437/fromCP437). - Update
main.jsto load standard UTF-8 raw files and transpile them into CP437 bytes, ensuring rigorous preservation of legacy control bytes. - Implement debugging and CLI helpers (
convert_bas.js) for legacy file restoration.
- Create a bidirectional mapping table (
Implement complex language features required by advanced Microsoft demos.
- 9.1. Static Data Structures:
- Implement
DATA,READ, andRESTOREwith a global data pointer in theEnvironment. - Handle unquoted strings and empty entries in
DATA.
- Implement
- 9.2. Exception Handling:
- Implement
ON ERROR GOTO,RESUME, andRESUME NEXTto catch runtime hardware/software faults.
- Implement
- 9.3. Implicit Typing & Macros:
- Support
DEFINT,DEFSNG, etc., for default variable typing. - Parse and evaluate single-line macros:
DEF FNname(args) = expr. - Support multiple
CONSTdeclarations andSTATICsubroutine scoping. - Support fixed-length string allocation (
AS STRING * N). - Support implicit function calls strictly by base name (without type suffix).
- Implement memory aliasing (
VariableVault) to natively link explicitly typed variables (e.g.,AS STRING) to their MS-DOS suffixed counterparts ($). - Support empty parentheses
()in array declarations for dynamic or shared arrays. - Unify AST generation between
DIM/SHAREDstatements and Subroutine parameter lists.
- Support
- 9.4. Math, Strings & Built-ins:
- Abstract all pure native functions into a
builtins.jsstandard library. - Implement strict
PRINT USINGformatting engine (variable-length string interception&and decimal precision###.###). - Implement math:
INT,FIX,ABS,SQR,RND,SIN,COS,TAN,ATN,EXP,LOG,CINT. - Implement strings:
CHR$,ASC,STR$,HEX$,VAL(including Hex&Hand Octal&Oprefixes),LEN,MID$,LEFT$,RIGHT$,UCASE$,LTRIM$,RTRIM$,INSTR,STRING$,SPC. - Add memory/variable utilities:
SWAP,ERASE. - Add hardware intercepts:
TAB,INPUT$.
- Abstract all pure native functions into a
- 9.5. The "Truth Vector" Compatibility Framework (Automated DOSBox):
A rigorous, automated infrastructure to prove the VirtualCPU's exact historical accuracy against MS-DOS originals without polluting the repository.
- Design a language-agnostic format (e.g., JSON/YAML) to strictly document QBasic/MS-DOS quirks and edge cases.
- Isolation & Clean Repository: Move truth vectors out of
examples/into a dedicated sandbox (tools/truth_vectors/). Implement strict.gitignorerules (engines/) to keep proprietary MS-DOS binaries (QB45/TP7) out of version control. - Orchestration Node.js (CLI Runner): Develop a headless DOSBox controller (
runner.js) that dynamically mounts workspaces, triggers native MS-DOS compilers/interpreters via batch scripts, and captures standard output (output.txt) for direct comparison. - Contributor DX: Write a comprehensive
README.mddetailing the local DOSBox setup and binary sourcing (Archive.org) to make truth vector validation reproducible for anyone. - Build a generator that compiles these vectors into a native
.BASself-testing suite. - Build a companion generator that translates these verified vectors into JavaScript unit tests for the Sysclone engine.
- Generate comprehensive Markdown documentation automatically from the Truth Vectors to serve as a definitive guide to QBasic behavior.
- 9.6. Exhaustive Truth Vector Implementation (Instruction by Instruction):
Systematically port and document every QBasic instruction and built-in function to the Truth Vector JSON format. Each entry must detail standard behavior (Black Box) and historical MS-DOS quirks (White Box).
- Suite 1: Strings & Type Casting (
builtins_string.json):-
STR$,HEX$,VAL(Hex/Octal). -
MID$,LEFT$,RIGHT$,LEN,UCASE$,LCASE$,LTRIM$,RTRIM$,SPACE$,STRING$. -
CHR$,ASC,INSTR.
-
- Suite 2: Math & Floating-Point Unit (
builtins_math.json):-
INT,FIX,CINT,\,/,MOD. -
ABS,SQR,EXP,LOG,RND. - Trigonometry (
SIN,COS,TAN,ATN).
-
- Suite 3: Memory, Scoping, & Structures (
memory_scoping.json):- Explicit Aliasing (
DIM X AS STRINGtoX$mapping). - Implicit Typing (
DEFINT,DEFSNG). - Fixed-Length Strings (
AS STRING * N). -
STATIC&SHARED(Tier 1 global routing vs localized shadowing). -
SWAP,ERASE.
- Explicit Aliasing (
- Suite 4: Control Flow & Jumps (
control_flow.json):-
FOR ... NEXT,EXIT FOR(Iterator mutation and overshoot). -
DO WHILE/UNTIL ... LOOP(Pre-test vs Post-test Truthiness). -
WHILE ... WEND(Legacy fallback handling). -
SELECT CASE(TOranges,ISrelational operators, no fallthrough). -
GOSUB ... RETURN(Mini-callstack and spatial scoping). - Single-Line
IF: Statement chaining via colons (:) andELSEbinding.
-
- Suite 5: Procedures & Functions (
procedures.json):-
CALL/SUB: Pass-by-Reference vs Forced Pass-by-Value via parenthesis. -
FUNCTION: Return value assignment via function name.
-
- Suite 6: Data & Error Handling (
data_errors.json):-
DATA,READ,RESTORE: Global data pointer manipulation and unquoted string parsing. -
ON ERROR GOTO,RESUME [NEXT]: Hardware stubbing verification.
-
- Suite 7: I/O, Formatting & Terminal (
io_terminal.json):-
PRINT: Spacing rules for positive/negative numbers and ghost commas. -
PRINT USING: Variable-length string interception (&) and decimal precision (###.##). -
LOCATE: Ghost parameter handling (LOCATE ,,0) and out-of-bounds protection.
-
- Suite 8: Graphics & VRAM - Silent Probing (
graphics_vram.json):-
WINDOW: Cartesian inversion and viewport clipping logic. -
PSET,PRESET: Bounds checking and default background fallback. -
LINE: Bresenham accuracy,B/BFflags, andSTEPrelativity. -
CIRCLE: Aspect ratio normalization, negative aspect ellipses, and 0-crossing arcs. -
PAINT: Boundary collision tracking. -
GET,PUT: Little-Endian header packing,XORblending, and EGA/VGA translation.
-
- Suite 1: Strings & Type Casting (
Expand the engine capabilities to support computationally and graphically intensive classics.
- 10.1. Viewports & Coordinate Systems:
- Support
WINDOWto map logical coordinates to physical screen pixels natively in the VGA router. - Support
STEPrelative coordinate tracking (Graphic Cursor) across all geometry primitives. - Support
VIEW PRINTto restrict text rendering and scrolling to specific screen rows.
- Support
- 10.2. Palettes & Screen Modes:
- Implement generic
setPaletteand default hardware palettes (CGA, EGA, MCGA/VGA). - Implement high-resolution simplified
SCREEN 9(EGA 640x350),SCREEN 12(VGA 640x480), alongsideSCREEN 13(VGA 320x200). - Load mode-specific, dynamic hardware typography (DOSBox 8x8 font for VGA, authentic 8x14 font for EGA block alignment).
- Implement elegant, dynamic viewport resizing and CSS scaling to seamlessly transition between native hardware resolutions (e.g., SCREEN 0 Text Mode, SCREEN 12 VGA 640x480, SCREEN 13 VGA 320x200) without breaking the DOM layout or pixel aspect ratio.
- Add
PALETTEandPALETTE USINGdynamic mapping support.
- Implement generic
- 10.3. Geometry Primitives (SCREEN 7, 8, 9, 13):
- Implement
PSET,PRESET, andPOINT(Pixel Write/Read). - Add geometry rendering:
LINE(Bresenham, Box, Box Fill), including relative origin supportLINE - (x, y). - Support
STEP(Relative coordinates) dynamically across all geometric primitives. - Implement advanced
CIRCLElogic: accurately emulating QBasic's default screen aspect ratios, undocumented negative aspect inversions, arc drawing, and 4-connected Midpoint anti-aliasing to prevent Moire holes in concentric loops. - Add algorithmic drawing:
PAINT(Iterative Stack-based Flood Fill algorithm).
- Implement
- 10.4. Hardware Blitting (
GET/PUT):- Emulate legacy QBasic sprite array formats (Little-Endian Header + Pixel data).
- Implement generic
GETandPUTwith bitwise operations (PSET,XOR,AND,OR,PRESET). - Implement intelligent formatting logic: processing EGA Planar bit-packing (Bitplanes) vs VGA Linear chunk packing seamlessly based on the active hardware driver.
- 11.1. Advanced Keyboard Controller:
- Upgrade state tracking with a strict 16-byte FIFO buffer.
- Implement deep anti-ghosting safeties (filtering
e.repeatheld-down keys) to prevent input flooding and game logic corruption (e.g., Gorillas 0-velocity bugs).
- 11.2. Time & Audio Engine:
- Wire
SLEEPandSOUNDto trigger aSYS_DELAYhardware interrupt, yielding execution control asynchronously to the Orchestrator without freezing the browser UI. - Implement preliminary
BEEPinstruction. - Wire the full
PLAYcommand to the Web Audio API (AudioContext).
- Wire
- 12.1. Rosetta Code Mandelbrot:
- Execute math-heavy visual rendering (
WINDOW,PSET, MCGA).
- Execute math-heavy visual rendering (
- 12.2. Gorillas.bas:
- Full execution (projectile math, explosive
PAINTrendering,XORsprite blitting, sound effects).
- Full execution (projectile math, explosive
- 12.3. SortDemo.bas & Reversi.bas:
- 100% Parsing achieved.
- Full execution of board logic (Reversi) and preliminary sorting algorithms (SortDemo).
Before splitting the architecture, establish a strict diagnostic layer. The Linter must catch syntax errors and logic flaws directly from the AST, protecting the VirtualCPU from runtime crashes.
- 12.3.1. Core Linter Engine:
- Create
tools/linter.js. - Implement an AST traversal mechanism to silently dry-run
.basprograms.
- Create
- 12.3.2. Lexical & Semantic Validation:
- Reserved Keyword Protection: Flag variables explicitly named after reserved QBasic Native Functions or Tokens (e.g.,
VAL = 5,LEN = 10). - Label Integrity: Detect and report duplicated jump labels (
EndTest:used twice) and "Label Not Found" jumps. - Block Matching: Verify structural integrity (e.g.,
FORwithoutNEXT,DOwithoutLOOP).
- Reserved Keyword Protection: Flag variables explicitly named after reserved QBasic Native Functions or Tokens (e.g.,
Before introducing Turbo Pascal or JIT compilation, the monolithic engine must be strictly decoupled. The goal is to separate the universal components from language-specific execution rules and memory behaviors.
- 12.5.1. Environment Decoupling (Memory & Scoping):
- Extract the core memory interactions (RAM mapping, Data Bank skeleton) into an abstract
BaseEnvironment. - Create
QBasicEnvironment(inheriting from Base): Isolate the 3-Tier Flat Scoping,VariableVaultaliasing, andDEFINTimplicit typing rules. - Create
PascalEnvironment(inheriting from Base): Implement standard Lexical Scoping (this.parenttraversal) and prepare a mock Heap Allocator for typed pointers.
- Extract the core memory interactions (RAM mapping, Data Bank skeleton) into an abstract
- 12.5.2. Evaluator Specialization (Monolithic Pattern):
- Rename
EvaluatortoQBasicEvaluatorand move tosrc/runtime/qbasic/to explicitly reflect its language-specific nature. - Create
PascalEvaluator(Stub) to handle strict lexical and procedural execution.
- Rename
- 12.5.3. UI & Bootstrapping (Dynamic Strategy):
- Create the
QBasicTokenizerextendingBaseTokenizer. - Create the
PascalTokenizerextendingBaseTokenizerto handle TP keywords and syntax (BEGIN,END,;). - Update
src/ui.jsandsrc/webvm.jsto dynamically inject the correct Tokenizer, Environment, and Evaluator based on the loaded file extension (.basvs.pas).
- Create the
Transform the interpreter into a true Just-In-Time compiler to fulfill the project's vision.
- 13.1. Strict Memory Typing:
- Replace standard JS arrays in
QArraywith Typed Arrays (Int16Array,Float32Array) based on the defined QBasic type.
- Replace standard JS arrays in
- 13.2. AST to JS Compilation (Level 1 JIT):
- Create an AST visitor that generates pure JavaScript code instead of evaluating it dynamically.
- 13.3. WebAssembly Compilation (Level 2 JIT):
- Translate the intermediate code (IR) into WASM binary for near-native performance.
Bring the Sysclone engine to the backend, allowing QBasic scripts to be executed or compiled as standalone CLI applications.
- 14.1. Core CLI Orchestrator:
- Create
tools/nodevm.js(or a compiler CLI) to load, parse, and execute.basfiles directly from the terminal. - Implement command-line argument handling (e.g.,
node tools/nodevm.js script.bas).
- Create
- 14.2. Headless Hardware Abstraction (HAL):
- Implement
ConsoleVGA: A headless display driver that maps basicPRINTstatements toprocess.stdoutand ignores graphical commands (PSET,WINDOW). - Implement
NodeIO: A headless input driver mappingINKEY$andINPUTtoprocess.stdin.
- Implement
- 14.3. Backend Math & Logic:
- Validate the execution of heavy computational scripts (e.g., algorithmic math, text-based data processing) without browser overhead.