@echo off setlocal enabledelayedexpansion set "SOURCE_ARG=%~f2" cd /d "%~dp0" title TinyVM - Windows Interactive Build ^& Run if /i "%~1"=="help" goto :show_help if /i "%~1"=="--help" goto :show_help if /i "%~1"=="-h" goto :show_help REM ========================================================================= REM Compiler Detection & Environment Setup REM ========================================================================= set "CC_NAME=" REM preserve a compiler selected by the caller. if defined CC ( set "CC_NAME=Configured [%CC%]" goto :has_compiler ) REM 1. Search WinGet LLVM-MinGW portable packages first (self-contained with CRT headers) for /d %%D in ("%LOCALAPPDATA%\Microsoft\WinGet\Packages\MartinStorsjo.LLVM-MinGW*") do ( for /d %%B in ("%%D\llvm-mingw*") do ( if exist "%%B\bin\clang.exe" ( set "PATH=%%B\bin;!PATH!" set "CC=clang" set "CC_NAME=LLVM-MinGW Clang [WinGet]" goto :compiler_found ) ) ) REM 2. Check if clang or gcc is already in PATH where clang >nul 2>nul if %errorlevel% equ 0 ( set "CC=clang" set "CC_NAME=Clang [in PATH]" goto :compiler_found ) where gcc >nul 2>nul if %errorlevel% equ 0 ( set "CC=gcc" set "CC_NAME=GCC [in PATH]" goto :compiler_found ) REM 3. Search C:\Program Files\LLVM\bin if exist "%ProgramFiles%\LLVM\bin\clang.exe" ( set "PATH=%ProgramFiles%\LLVM\bin;%PATH%" set "CC=clang" set "CC_NAME=LLVM Clang [Program Files]" goto :compiler_found ) set "PFX86=%ProgramFiles(x86)%" if defined PFX86 if exist "!PFX86!\LLVM\bin\clang.exe" ( set "PATH=!PFX86!\LLVM\bin;%PATH%" set "CC=clang" set "CC_NAME=LLVM Clang [Program Files x86]" goto :compiler_found ) :compiler_found if not "%CC%"=="" goto :has_compiler echo [ERROR] No suitable C compiler [clang or gcc] found on this system. echo. echo Please install LLVM / Clang: echo winget install MartinStorsjo.LLVM-MinGW.UCRT echo or: winget install LLVM.LLVM echo. pause exit /b 1 :has_compiler REM Handle CLI Arguments if provided if not "%~1"=="" goto :handle_cli REM ========================================================================= REM Interactive Main Menu REM ========================================================================= :main_menu cls echo =============================================================================== echo TinyVM - Windows Toolchain echo =============================================================================== echo Compiler : %CC_NAME% echo Working : %CD% echo ------------------------------------------------------------------------------- echo executable status: if exist "bin\zy.exe" ( echo [X] bin\zy.exe - VM core interpreter ) else ( echo [ ] bin\zy.exe - not built ) if exist "bin\zym.exe" ( echo [X] bin\zym.exe - portable microcore ) else ( echo [ ] bin\zym.exe - not built ) if exist "bin\zc0.exe" ( echo [X] bin\zc0.exe - stage 0 bootstrap compiler ) else ( echo [ ] bin\zc0.exe - not built ) if exist "bin\mkgenome.exe" ( echo [X] bin\mkgenome.exe - genome header generator ) else ( echo [ ] bin\mkgenome.exe - not built ) if exist "bin\genmap.exe" ( echo [X] bin\genmap.exe - memory map generator ) else ( echo [ ] bin\genmap.exe - not built ) if exist "bin\zclsp.exe" ( echo [X] bin\zclsp.exe - language server protocol ^& highlighter ) else ( echo [ ] bin\zclsp.exe - not built ) echo =============================================================================== echo [1] build VM core (bin\zy.exe) echo [2] build microcore (bin\zym.exe) echo [3] build bootstrap tools (bin\zc0.exe, bin\mkgenome.exe, bin\genmap.exe) echo [4] build LSP server ^& highlighter (bin\zclsp.exe) echo [5] build everything echo [6] run Windows test suite (native, LSP, JS, bootstrap) echo [7] run an example on the native VM (bin\zy.exe) echo [8] run an example in the JavaScript VM (node build/js/tinyvm.js) echo [9] run a custom .zc source file echo [L] check/highlight .zc with LSP (bin\zclsp.exe) echo [R] launch the interactive REPL (resident compiler) echo [B] bootstrap and run the full test suite echo [C] clean generated build directories (bin, build) echo [Q] quit echo =============================================================================== set /p "CHOICE=select an option [1-9, L, R, B, C, Q]: " if /i "%CHOICE%"=="1" goto :menu_build_core if /i "%CHOICE%"=="2" goto :menu_build_micro if /i "%CHOICE%"=="3" goto :menu_build_tools if /i "%CHOICE%"=="4" goto :menu_build_lsp if /i "%CHOICE%"=="5" goto :menu_build_all if /i "%CHOICE%"=="6" goto :menu_test if /i "%CHOICE%"=="7" goto :menu_examples if /i "%CHOICE%"=="8" goto :menu_examples_js if /i "%CHOICE%"=="9" goto :menu_run_custom if /i "%CHOICE%"=="l" goto :menu_lsp_check if /i "%CHOICE%"=="r" goto :menu_repl if /i "%CHOICE%"=="b" goto :menu_bootstrap if /i "%CHOICE%"=="c" goto :menu_clean if /i "%CHOICE%"=="q" exit /b 0 echo Invalid choice. Please try again. timeout /t 2 >nul goto :main_menu REM ========================================================================= REM Actions REM ========================================================================= :menu_build_core echo. echo [Building zy.exe]... call :build_core echo. pause goto :main_menu :menu_build_micro echo. echo [Building zym.exe]... call :build_micro echo. pause goto :main_menu :menu_build_tools echo. echo [Building tools: zc0.exe, mkgenome.exe, genmap.exe]... call :build_tools echo. pause goto :main_menu :menu_build_lsp echo. echo [Building zclsp.exe (LSP Server ^& Highlighter)]... call :build_lsp echo. pause goto :main_menu :menu_build_all echo. echo [Building all components]... call :build_core if errorlevel 1 goto :build_failed call :build_micro if errorlevel 1 goto :build_failed call :build_tools if errorlevel 1 goto :build_failed call :build_lsp if errorlevel 1 goto :build_failed echo. echo [OK] Build complete. pause goto :main_menu :build_failed echo. echo [ERROR] Build failed. See the messages above. pause goto :main_menu :menu_test echo. if not exist "bin\zy.exe" ( call :build_core if errorlevel 1 goto :build_failed ) if not exist "bin\zym.exe" ( call :build_micro if errorlevel 1 goto :build_failed ) echo [Running test suite]... powershell -NoProfile -ExecutionPolicy Bypass -File "tests\test_win.ps1" if errorlevel 1 echo [ERROR] Test suite failed. echo. pause goto :main_menu :menu_bootstrap echo. echo [Running Bootstrap and Full Test Verification]... call :build_tools if errorlevel 1 goto :build_failed if not exist "bin\zy.exe" ( call :build_core if errorlevel 1 goto :build_failed ) powershell -NoProfile -ExecutionPolicy Bypass -File "tests\test_win.ps1" if errorlevel 1 echo [ERROR] Test suite failed. echo. pause goto :main_menu :menu_clean echo. echo [Cleaning build artifacts]... rmdir /s /q build bin 2>nul echo [OK] Generated bin and build directories removed. echo. pause goto :main_menu :menu_run_custom echo. set /p "CUSTOM_FILE=Enter path to .zc file (or drag & drop here): " REM Remove quotes if user dragged & dropped set "CUSTOM_FILE=%CUSTOM_FILE:"=%" if not exist "%CUSTOM_FILE%" ( echo [ERROR] File not found: %CUSTOM_FILE% echo. pause goto :main_menu ) if not exist "bin\zy.exe" ( echo bin\zy.exe not found, building first... call :build_core if errorlevel 1 goto :build_failed ) echo. echo =============================================================================== echo Running: %CUSTOM_FILE% echo =============================================================================== bin\zy.exe < "%CUSTOM_FILE%" echo. echo =============================================================================== pause goto :main_menu :menu_lsp_check echo. set /p "LSP_FILE=Enter path to .zc file to check/highlight (or drag & drop here): " set "LSP_FILE=%LSP_FILE:"=%" if not exist "%LSP_FILE%" ( echo [ERROR] File not found: %LSP_FILE% echo. pause goto :main_menu ) if not exist "bin\zclsp.exe" ( echo bin\zclsp.exe not found, building first... call :build_lsp if errorlevel 1 goto :build_failed ) echo. echo =============================================================================== echo Analyzing with bin\zclsp.exe: %LSP_FILE% echo =============================================================================== bin\zclsp.exe < "%LSP_FILE%" echo. echo =============================================================================== pause goto :main_menu :menu_repl echo. if not exist "bin\zy.exe" ( echo bin\zy.exe not found, building first... call :build_core if errorlevel 1 goto :build_failed ) echo =============================================================================== echo TinyVM Interactive REPL (resident compiler) echo Each input chunk separated by backtick (`) is compiled and run. echo Type expression or function, terminate with ` (or EOF / Ctrl+Z). echo Type 'quit;' then backtick or press Ctrl+C to exit. echo =============================================================================== (type examples\repl.zc & echo ` & more) | bin\zy.exe echo. pause goto :main_menu REM ========================================================================= REM Example Selection Sub-menu REM ========================================================================= :menu_examples cls echo =============================================================================== echo Run TinyVM Examples on Native VM (zy.exe) echo =============================================================================== echo [1] hello.zc - Classic "hello, world!" echo [2] fact.zc - Recursive & iterative factorial computation echo [3] mandel.zc - Mandelbrot ASCII set using custom enhancement opcode echo [4] primes.zc - Sieve of Eratosthenes with o3 region compilation echo [5] life.zc - Conway's Game of Life on a typed torus board echo [6] lists.zc - Dynamic array with ownership tracking (u, m, d tags) echo [7] typed.zc - Structs, generic vectors, and reflection echo [8] wiring.zc - Runtime custom enhancement opcodes demo echo [9] bf.zc - Brainfuck JIT compiler running inside TinyVM echo [B] Back to main menu echo =============================================================================== set /p "EX_CHOICE=Select an example [1-9, B]: " if /i "%EX_CHOICE%"=="b" goto :main_menu set "EX_FILE=" if "%EX_CHOICE%"=="1" set "EX_FILE=examples\hello.zc" if "%EX_CHOICE%"=="2" set "EX_FILE=examples\fact.zc" if "%EX_CHOICE%"=="3" set "EX_FILE=examples\mandel.zc" if "%EX_CHOICE%"=="4" set "EX_FILE=examples\primes.zc" if "%EX_CHOICE%"=="5" set "EX_FILE=examples\life.zc" if "%EX_CHOICE%"=="6" set "EX_FILE=examples\lists.zc" if "%EX_CHOICE%"=="7" set "EX_FILE=examples\typed.zc" if "%EX_CHOICE%"=="8" set "EX_FILE=examples\wiring.zc" if "%EX_CHOICE%"=="9" set "EX_FILE=examples\bf.zc" if "%EX_FILE%"=="" ( echo Invalid choice. timeout /t 2 >nul goto :menu_examples ) if not exist "bin\zy.exe" ( call :build_core if errorlevel 1 goto :build_failed ) echo. echo =============================================================================== echo Running: %EX_FILE% echo =============================================================================== bin\zy.exe < "%EX_FILE%" echo. echo =============================================================================== pause goto :menu_examples :menu_examples_js cls echo =============================================================================== echo Run TinyVM Examples in JavaScript VM (Node.js) echo =============================================================================== echo [1] hello.zc - Classic "hello, world!" echo [2] fact.zc - Recursive & iterative factorial computation echo [3] mandel.zc - Mandelbrot ASCII set using custom enhancement opcode echo [4] primes.zc - Sieve of Eratosthenes with o3 region compilation echo [5] life.zc - Conway's Game of Life on a typed torus board echo [6] lists.zc - Dynamic array with ownership tracking (u, m, d tags) echo [7] typed.zc - Structs, generic vectors, and reflection echo [8] wiring.zc - Runtime custom enhancement opcodes demo echo [9] bf.zc - Brainfuck JIT compiler running inside TinyVM echo [B] Back to main menu echo =============================================================================== set /p "JS_EX_CHOICE=Select an example [1-9, B]: " if /i "%JS_EX_CHOICE%"=="b" goto :main_menu set "JS_EX_FILE=" if "%JS_EX_CHOICE%"=="1" set "JS_EX_FILE=examples\hello.zc" if "%JS_EX_CHOICE%"=="2" set "JS_EX_FILE=examples\fact.zc" if "%JS_EX_CHOICE%"=="3" set "JS_EX_FILE=examples\mandel.zc" if "%JS_EX_CHOICE%"=="4" set "JS_EX_FILE=examples\primes.zc" if "%JS_EX_CHOICE%"=="5" set "JS_EX_FILE=examples\life.zc" if "%JS_EX_CHOICE%"=="6" set "JS_EX_FILE=examples\lists.zc" if "%JS_EX_CHOICE%"=="7" set "JS_EX_FILE=examples\typed.zc" if "%JS_EX_CHOICE%"=="8" set "JS_EX_FILE=examples\wiring.zc" if "%JS_EX_CHOICE%"=="9" set "JS_EX_FILE=examples\bf.zc" if "%JS_EX_FILE%"=="" ( echo Invalid choice. timeout /t 2 >nul goto :menu_examples_js ) echo. echo =============================================================================== echo Running in JS: %JS_EX_FILE% echo =============================================================================== node src\js\tinyvm.js "%JS_EX_FILE%" echo. echo =============================================================================== pause goto :menu_examples_js REM ========================================================================= REM Build Routines REM ========================================================================= :build_core echo Compiling zy.exe (VM Core with JIT/Interpreter and Enhancements)... if not exist "bin" mkdir bin "%CC%" -O2 -w -fwrapv -DJTYPE=int src\core\core.c src\core\io_win.c -Isrc/core -o bin\zy.exe if errorlevel 1 (echo [ERROR] Failed to build bin\zy.exe.& exit /b 1) echo [OK] bin\zy.exe built successfully. exit /b 0 :build_micro echo Compiling zym.exe (Portable Microcore)... if not exist "bin" mkdir bin "%CC%" -O2 -w -fwrapv src\micro\micro.c src\micro\port_win.c -Isrc/core -Isrc/micro -o bin\zym.exe if errorlevel 1 (echo [ERROR] Failed to build bin\zym.exe.& exit /b 1) echo [OK] bin\zym.exe built successfully. exit /b 0 :build_tools if not exist "bin" mkdir bin echo Compiling zc0.exe (Bootstrap compiler)... "%CC%" -O1 -w -fwrapv src\tools\zc0.c -Isrc/core -o bin\zc0.exe if errorlevel 1 (echo [ERROR] Failed to build bin\zc0.exe.& exit /b 1) echo Compiling mkgenome.exe (Genome generator)... "%CC%" -O1 -w -fwrapv src\tools\mkgenome.c -Isrc/core -o bin\mkgenome.exe if errorlevel 1 (echo [ERROR] Failed to build bin\mkgenome.exe.& exit /b 1) echo Compiling genmap.exe (Memory map generator)... "%CC%" -O2 -w -fwrapv src\tools\genmap.c -Isrc/core -o bin\genmap.exe if errorlevel 1 (echo [ERROR] Failed to build bin\genmap.exe.& exit /b 1) echo [OK] Bootstrap tools built successfully in bin\. exit /b 0 :build_lsp echo Compiling zclsp.exe (LSP Server ^& Semantic Highlighter in zc)... if not exist "bin" mkdir bin if not exist "bin\zc0.exe" ( call :build_tools if errorlevel 1 exit /b 1 ) if not exist "bin\genmap.exe" ( call :build_tools if errorlevel 1 exit /b 1 ) if exist build\lsp rmdir /s /q build\lsp mkdir build\lsp\src if errorlevel 1 (echo [ERROR] Could not create build\lsp.& exit /b 1) bin\genmap.exe --preset lsp --grow -o build\lsp\map >nul 2>nul if errorlevel 1 (echo [ERROR] Could not generate the initial LSP map.& exit /b 1) "%CC%" -O1 -w -fwrapv src\tools\zc0.c -Ibuild\lsp\map -Isrc/core -o build\lsp\zc0.exe if errorlevel 1 (echo [ERROR] Could not build the LSP sizing compiler.& exit /b 1) (type build\lsp\map\rt.zc & type build\lsp\map\compiler.zc & type src\lsp\server.zc) | build\lsp\zc0.exe > build\lsp\plain.h if errorlevel 1 (echo [ERROR] Could not size the LSP genome.& exit /b 1) set "GLEN=" for /f "tokens=3" %%G in ('findstr /b /c:"#define GLEN" build\lsp\plain.h') do set "GLEN=%%G" if not defined GLEN (echo [ERROR] Could not read the LSP genome size.& exit /b 1) set /a SLOT=(GLEN+4095)/4096*4096 set /a DOCS_WORK=SLOT+65536 rmdir /s /q build\lsp\map bin\genmap.exe --preset lsp --grow --genome %DOCS_WORK% -o build\lsp\map >nul 2>nul if errorlevel 1 (echo [ERROR] Could not generate the documentation build map.& exit /b 1) "%CC%" -O1 -w -fwrapv -DZC0DOCS src\tools\zc0.c -Ibuild\lsp\map -Isrc/core -o build\lsp\zc0docs.exe if errorlevel 1 (echo [ERROR] Could not build the documentation compiler.& exit /b 1) (type build\lsp\map\rt.zc & type build\lsp\map\compiler.zc & type src\lsp\server.zc) | build\lsp\zc0docs.exe > build\lsp\docs-first.h if errorlevel 1 (echo [ERROR] Could not build the first documentation genome.& exit /b 1) set "DOCS_GLEN=" for /f "tokens=3" %%G in ('findstr /b /c:"#define GLEN" build\lsp\docs-first.h') do set "DOCS_GLEN=%%G" if not defined DOCS_GLEN (echo [ERROR] Could not read the documentation genome size.& exit /b 1) set /a DOCS_SLOT=(DOCS_GLEN+4095)/4096*4096 rmdir /s /q build\lsp\map bin\genmap.exe --preset lsp --grow --genome %DOCS_SLOT% -o build\lsp\map >nul 2>nul if errorlevel 1 (echo [ERROR] Could not generate the sized LSP map.& exit /b 1) "%CC%" -O1 -w -fwrapv -DZC0DOCS src\tools\zc0.c -Ibuild\lsp\map -Isrc/core -o build\lsp\zc0docs.exe if errorlevel 1 (echo [ERROR] Could not rebuild the documentation compiler.& exit /b 1) (type build\lsp\map\rt.zc & type build\lsp\map\compiler.zc & type src\lsp\server.zc) | build\lsp\zc0docs.exe > build\lsp\src\lsp_genome.h if errorlevel 1 (echo [ERROR] Could not build the sized documentation genome.& exit /b 1) set "FINAL_GLEN=" for /f "tokens=3" %%G in ('findstr /b /c:"#define GLEN" build\lsp\src\lsp_genome.h') do set "FINAL_GLEN=%%G" if not "!FINAL_GLEN!"=="!DOCS_GLEN!" (echo [ERROR] LSP genome changed length after map sizing.& exit /b 1) copy /y src\core\core.c build\lsp\src\ >nul if errorlevel 1 exit /b 1 copy /y src\core\io_win.c build\lsp\src\ >nul if errorlevel 1 exit /b 1 copy /y src\core\fops.h build\lsp\src\ >nul if errorlevel 1 exit /b 1 copy /y src\core\bops.h build\lsp\src\ >nul if errorlevel 1 exit /b 1 copy /y src\core\stack.h build\lsp\src\ >nul if errorlevel 1 exit /b 1 copy /y build\lsp\map\memmap.h build\lsp\src\ >nul if errorlevel 1 exit /b 1 "%CC%" -O2 -w -fwrapv -DJTYPE=int -DZY_SANDBOX -DUSE_LSP_GENOME -Ibuild\lsp\src build\lsp\src\core.c build\lsp\src\io_win.c -o bin\zclsp.exe if errorlevel 1 (echo [ERROR] Failed to build bin\zclsp.exe.& exit /b 1) echo [OK] bin\zclsp.exe built successfully with %FINAL_GLEN% words. exit /b 0 REM ========================================================================= REM CLI Command Handler REM ========================================================================= :handle_cli set "CMD=%~1" set "ARG2=%~2" if /i "%CMD%"=="build" ( if "%ARG2%"=="" goto :cli_build_all if /i "%ARG2%"=="all" goto :cli_build_all if /i "%ARG2%"=="core" ( call :build_core & exit /b !errorlevel! ) if /i "%ARG2%"=="micro" ( call :build_micro & exit /b !errorlevel! ) if /i "%ARG2%"=="tools" ( call :build_tools & exit /b !errorlevel! ) if /i "%ARG2%"=="lsp" ( call :build_lsp & exit /b !errorlevel! ) echo Unknown build target: %ARG2% exit /b 1 ) if /i "%CMD%"=="test" ( call :build_core if errorlevel 1 exit /b 1 call :build_micro if errorlevel 1 exit /b 1 powershell -NoProfile -ExecutionPolicy Bypass -File "tests\test_win.ps1" exit /b !errorlevel! ) if /i "%CMD%"=="run" ( if "%ARG2%"=="" ( echo Error: Missing .zc file to run. echo Usage: tinyvm.bat run path\to\program.zc exit /b 1 ) if not exist "bin\zy.exe" ( call :build_core if errorlevel 1 exit /b 1 ) bin\zy.exe < "%SOURCE_ARG%" exit /b !errorlevel! ) if /i "%CMD%"=="run-micro" ( if "%ARG2%"=="" ( echo Error: Missing .zc file to run. echo Usage: tinyvm.bat run-micro path\to\program.zc exit /b 1 ) if not exist "bin\zym.exe" ( call :build_micro if errorlevel 1 exit /b 1 ) bin\zym.exe < "%SOURCE_ARG%" exit /b !errorlevel! ) if /i "%CMD%"=="js" ( if "%ARG2%"=="" ( echo Error: Missing .zc file to run. echo Usage: tinyvm.bat js path\to\program.zc exit /b 1 ) node src\js\tinyvm.js "%SOURCE_ARG%" exit /b !errorlevel! ) if /i "%CMD%"=="lsp" ( if "%ARG2%"=="" ( echo Error: Missing .zc file to check. echo Usage: tinyvm.bat lsp path\to\program.zc exit /b 1 ) if not exist "bin\zclsp.exe" ( call :build_lsp if errorlevel 1 exit /b 1 ) bin\zclsp.exe < "%SOURCE_ARG%" exit /b !errorlevel! ) if /i "%CMD%"=="repl" ( if not exist "bin\zy.exe" ( call :build_core if errorlevel 1 exit /b 1 ) (type examples\repl.zc & echo ` & more) | bin\zy.exe exit /b !errorlevel! ) if /i "%CMD%"=="clean" ( rmdir /s /q build bin 2>nul echo [OK] Generated bin and build directories removed. exit /b 0 ) if /i "%CMD%"=="help" ( goto :show_help ) if /i "%CMD%"=="-h" ( goto :show_help ) if /i "%CMD%"=="--help" ( goto :show_help ) echo Unknown command: %CMD% echo. exit /b 1 :show_help echo usage: tinyvm.bat [command] echo tinyvm.bat launch interactive build ^& run menu echo tinyvm.bat build [all^|core^|micro^|tools^|lsp] echo compile TinyVM executables echo tinyvm.bat run ^ run a .zc program on VM core (zy.exe) echo tinyvm.bat run-micro ^ run a .zc program on microcore (zym.exe) echo tinyvm.bat js ^ run a .zc program on the JavaScript VM (node) echo tinyvm.bat lsp ^ check/highlight a .zc program with zclsp.exe echo tinyvm.bat test run the full Windows test suite echo tinyvm.bat repl launch the resident compiler REPL echo tinyvm.bat clean remove generated bin and build directories exit /b 0 :cli_build_all call :build_core if errorlevel 1 exit /b 1 call :build_micro if errorlevel 1 exit /b 1 call :build_tools if errorlevel 1 exit /b 1 call :build_lsp exit /b !errorlevel!