aboutsummaryrefslogtreecommitdiff
path: root/tinyvm.bat
diff options
context:
space:
mode:
authorGravatar zinc <zinc@downsta.ir> 2026-10-14 07:28:39 +0000
committerGravatar zinc <zinc@downsta.ir> 2026-10-14 07:28:39 +0000
commit7451eb090d890fb5ea5e4d40627a1b4df15a49de (patch)
tree357bdf4b528e860bffa688865306f656b788d2c2 /tinyvm.bat
parentanalyzer: close the ownership gaps that stopped the compiler compiling itself (diff)
build: embed images with #embed, keep everything generated in build/
the cores take their genome in with c23 #embed through src/core/genome.h, so images are plain little-endian word files (genome.bin) instead of generated c headers. zc0 writes that format, mkgenome checks an image against its map and shows a compiler's diagnostics when it gets them, and the javascript vm and the editor's vm host read the same files. src/tools/findcc.sh picks a compiler with #embed (clang 19 or gcc 15). zc gets an embed declaration, embed "file" as [type] name, for globals and locals: a byte string by default, char*, numbers read little-endian, and arrays of numbers. the compiler and language server carry their library and source texts through it, so embed.sh and the text it spliced into compiler.zc are gone. make writes executables to build/bin, the default map to build/core/map, the web page to build/web and the extension staging to build/vsix, and the genome now rebuilds when its sources change. the test suite lays out its own map and bootstrap and reads nothing from build/. also: rt.put_s of a byte string in zc0 images, retained function sources no longer count as live objects, a missing include no longer cascades into undefined-name errors, consecutive comment lines join into one hover paragraph, and stale test fixtures follow the include format.
Diffstat (limited to 'tinyvm.bat')
-rwxr-xr-xtinyvm.bat569
1 files changed, 297 insertions, 272 deletions
diff --git a/tinyvm.bat b/tinyvm.bat
index 9a457eb..7d0676d 100755
--- a/tinyvm.bat
+++ b/tinyvm.bat
@@ -7,65 +7,83 @@ if /i "%~1"=="help" goto :show_help
if /i "%~1"=="--help" goto :show_help
if /i "%~1"=="-h" goto :show_help
+REM everything built or generated goes under build\ (executables in build\bin);
+REM the tree holds sources only. the cores take their genome in with c23 #embed,
+REM so the compiler has to be clang 19 or gcc 15 or later.
+
REM =========================================================================
REM Compiler Detection & Environment Setup
REM =========================================================================
set "CC_NAME="
-
-REM preserve a compiler selected by the caller.
+if not exist "build\probe" mkdir "build\probe"
+> "build\probe\probe.bin" echo ab
+> "build\probe\probe.c" echo static const unsigned char probe[] = {
+>> "build\probe\probe.c" echo #embed "probe.bin"
+>> "build\probe\probe.c" echo };
+>> "build\probe\probe.c" echo int main(void) { return sizeof probe ^> 0 ? 0 : 1; }
+
+REM preserve a compiler selected by the caller, if it can #embed.
if defined CC (
- set "CC_NAME=Configured [%CC%]"
- goto :has_compiler
+ call :probe_cc "%CC%"
+ if not errorlevel 1 (
+ set "CC_NAME=Configured [%CC%]"
+ goto :has_compiler
+ )
+ echo [ERROR] CC=%CC% does not support #embed; clang 19 or gcc 15 is needed.
+ exit /b 1
)
-REM 1. Search WinGet LLVM-MinGW portable packages first (self-contained with CRT headers)
+REM 1. WinGet LLVM-MinGW portable packages (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
+ call :probe_cc "%%B\bin\clang.exe"
+ if not errorlevel 1 (
+ set "PATH=%%B\bin;!PATH!"
+ set "CC=clang"
+ set "CC_NAME=LLVM-MinGW Clang [WinGet]"
+ goto :has_compiler
+ )
)
)
)
-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 2. clang or gcc already in PATH
+for %%C in (clang gcc) do (
+ where %%C >nul 2>nul
+ if !errorlevel! equ 0 (
+ call :probe_cc %%C
+ if not errorlevel 1 (
+ set "CC=%%C"
+ set "CC_NAME=%%C [in PATH]"
+ goto :has_compiler
+ )
+ )
)
-REM 3. Search C:\Program Files\LLVM\bin
+REM 3. C:\Program Files\LLVM\bin and the x86 variant
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
+ call :probe_cc "%ProgramFiles%\LLVM\bin\clang.exe"
+ if not errorlevel 1 (
+ set "PATH=%ProgramFiles%\LLVM\bin;%PATH%"
+ set "CC=clang"
+ set "CC_NAME=LLVM Clang [Program Files]"
+ goto :has_compiler
+ )
)
-
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
+ call :probe_cc "!PFX86!\LLVM\bin\clang.exe"
+ if not errorlevel 1 (
+ set "PATH=!PFX86!\LLVM\bin;%PATH%"
+ set "CC=clang"
+ set "CC_NAME=LLVM Clang [Program Files x86]"
+ goto :has_compiler
+ )
)
-:compiler_found
-if not "%CC%"=="" goto :has_compiler
-
-echo [ERROR] No suitable C compiler [clang or gcc] found on this system.
+echo [ERROR] No C compiler with #embed support [clang 19 or gcc 15 and later] was found.
echo.
echo Please install LLVM / Clang:
echo winget install MartinStorsjo.LLVM-MinGW.UCRT
@@ -74,7 +92,14 @@ echo.
pause
exit /b 1
+REM :probe_cc compiler - errorlevel 0 when it compiles a file that uses #embed
+:probe_cc
+%1 -w --embed-dir=build\probe build\probe\probe.c -o build\probe\probe.exe >nul 2>nul
+exit /b %errorlevel%
+
:has_compiler
+REM the include and embed paths of a core that carries the compiler genome
+set "COREINC=-Isrc/core -Ibuild/core/map --embed-dir=build/core"
REM Handle CLI Arguments if provided
if not "%~1"=="" goto :handle_cli
@@ -92,29 +117,29 @@ 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 )
+if exist "build\bin\zy.exe" ( echo [X] build\bin\zy.exe - VM core interpreter ) else ( echo [ ] build\bin\zy.exe - not built )
+if exist "build\bin\zym.exe" ( echo [X] build\bin\zym.exe - portable microcore ) else ( echo [ ] build\bin\zym.exe - not built )
+if exist "build\bin\zc0.exe" ( echo [X] build\bin\zc0.exe - stage 0 bootstrap compiler ) else ( echo [ ] build\bin\zc0.exe - not built )
+if exist "build\bin\mkgenome.exe" ( echo [X] build\bin\mkgenome.exe - genome image checker ) else ( echo [ ] build\bin\mkgenome.exe - not built )
+if exist "build\bin\genmap.exe" ( echo [X] build\bin\genmap.exe - memory map generator ) else ( echo [ ] build\bin\genmap.exe - not built )
+if exist "build\bin\zclsp.exe" ( echo [X] build\bin\zclsp.exe - language server protocol ^& highlighter ) else ( echo [ ] build\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 [1] build VM core (build\bin\zy.exe)
+echo [2] build microcore (build\bin\zym.exe)
+echo [3] build bootstrap tools (zc0.exe, mkgenome.exe, genmap.exe)
+echo [4] build LSP server ^& highlighter (build\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 [7] run an example on the native VM (build\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 [L] check/highlight .zc with LSP (build\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 [G] rebuild the compiler genome and check the fixpoint
+echo [C] clean generated output (build)
echo [Q] quit
echo ===============================================================================
-set /p "CHOICE=select an option [1-9, L, R, B, C, Q]: "
+set /p "CHOICE=select an option [1-9, L, R, G, C, Q]: "
if /i "%CHOICE%"=="1" goto :menu_build_core
if /i "%CHOICE%"=="2" goto :menu_build_micro
@@ -127,7 +152,7 @@ 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%"=="g" goto :menu_genome
if /i "%CHOICE%"=="c" goto :menu_clean
if /i "%CHOICE%"=="q" exit /b 0
@@ -141,7 +166,6 @@ REM =========================================================================
:menu_build_core
echo.
-echo [Building zy.exe]...
call :build_core
echo.
pause
@@ -149,7 +173,6 @@ goto :main_menu
:menu_build_micro
echo.
-echo [Building zym.exe]...
call :build_micro
echo.
pause
@@ -157,7 +180,6 @@ goto :main_menu
:menu_build_tools
echo.
-echo [Building tools: zc0.exe, mkgenome.exe, genmap.exe]...
call :build_tools
echo.
pause
@@ -165,7 +187,6 @@ goto :main_menu
:menu_build_lsp
echo.
-echo [Building zclsp.exe (LSP Server ^& Highlighter)]...
call :build_lsp
echo.
pause
@@ -173,14 +194,7 @@ 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
+call :build_all
if errorlevel 1 goto :build_failed
echo.
echo [OK] Build complete.
@@ -195,41 +209,23 @@ 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"
+call :run_tests
if errorlevel 1 echo [ERROR] Test suite failed.
echo.
pause
goto :main_menu
-:menu_bootstrap
+:menu_genome
echo.
-echo [Running Bootstrap and Full Test Verification]...
-call :build_tools
+call :build_genome
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.
+call :clean
echo.
pause
goto :main_menu
@@ -245,18 +241,15 @@ if not exist "%CUSTOM_FILE%" (
pause
goto :main_menu
)
-
-if not exist "bin\zy.exe" (
- echo bin\zy.exe not found, building first...
+if not exist "build\bin\zy.exe" (
call :build_core
if errorlevel 1 goto :build_failed
)
-
echo.
echo ===============================================================================
echo Running: %CUSTOM_FILE%
echo ===============================================================================
-bin\zy.exe < "%CUSTOM_FILE%"
+build\bin\zy.exe < "%CUSTOM_FILE%"
echo.
echo ===============================================================================
pause
@@ -272,18 +265,15 @@ if not exist "%LSP_FILE%" (
pause
goto :main_menu
)
-
-if not exist "bin\zclsp.exe" (
- echo bin\zclsp.exe not found, building first...
+if not exist "build\bin\zclsp.exe" (
call :build_lsp
if errorlevel 1 goto :build_failed
)
-
echo.
echo ===============================================================================
-echo Analyzing with bin\zclsp.exe: %LSP_FILE%
+echo Analyzing with build\bin\zclsp.exe: %LSP_FILE%
echo ===============================================================================
-bin\zclsp.exe < "%LSP_FILE%"
+build\bin\zclsp.exe < "%LSP_FILE%"
echo.
echo ===============================================================================
pause
@@ -291,8 +281,7 @@ goto :main_menu
:menu_repl
echo.
-if not exist "bin\zy.exe" (
- echo bin\zy.exe not found, building first...
+if not exist "build\bin\zy.exe" (
call :build_core
if errorlevel 1 goto :build_failed
)
@@ -302,7 +291,7 @@ 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
+(type examples\repl.zc & echo ` & more) | build\bin\zy.exe
echo.
pause
goto :main_menu
@@ -316,47 +305,24 @@ 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 ===============================================================================
+call :example_list
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"
-
+call :example_file "%EX_CHOICE%"
if "%EX_FILE%"=="" (
echo Invalid choice.
timeout /t 2 >nul
goto :menu_examples
)
-
-if not exist "bin\zy.exe" (
+if not exist "build\bin\zy.exe" (
call :build_core
if errorlevel 1 goto :build_failed
)
-
echo.
echo ===============================================================================
echo Running: %EX_FILE%
echo ===============================================================================
-bin\zy.exe < "%EX_FILE%"
+build\bin\zy.exe < "%EX_FILE%"
echo.
echo ===============================================================================
pause
@@ -367,142 +333,216 @@ 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%"=="" (
+call :example_list
+set /p "EX_CHOICE=Select an example [1-9, B]: "
+if /i "%EX_CHOICE%"=="b" goto :main_menu
+call :example_file "%EX_CHOICE%"
+if "%EX_FILE%"=="" (
echo Invalid choice.
timeout /t 2 >nul
goto :menu_examples_js
)
-
+call :build_js
+if errorlevel 1 goto :build_failed
echo.
echo ===============================================================================
-echo Running in JS: %JS_EX_FILE%
+echo Running in JS: %EX_FILE%
echo ===============================================================================
-node src\js\tinyvm.js "%JS_EX_FILE%"
+node build\js\tinyvm.js "%EX_FILE%"
echo.
echo ===============================================================================
pause
goto :menu_examples_js
+:example_list
+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 compiler running inside TinyVM
+echo [B] Back to main menu
+echo ===============================================================================
+exit /b 0
+
+:example_file
+set "EX_FILE="
+if "%~1"=="1" set "EX_FILE=examples\hello.zc"
+if "%~1"=="2" set "EX_FILE=examples\fact.zc"
+if "%~1"=="3" set "EX_FILE=examples\mandel.zc"
+if "%~1"=="4" set "EX_FILE=examples\primes.zc"
+if "%~1"=="5" set "EX_FILE=examples\life.zc"
+if "%~1"=="6" set "EX_FILE=examples\lists.zc"
+if "%~1"=="7" set "EX_FILE=examples\typed.zc"
+if "%~1"=="8" set "EX_FILE=examples\wiring.zc"
+if "%~1"=="9" set "EX_FILE=examples\bf.zc"
+exit /b 0
+
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.
+REM genmap needs no map; the default map comes from it and the zc sources' const blocks
+:build_tools
+if not exist "build\bin" mkdir build\bin
+echo Compiling genmap.exe (memory map generator)...
+"%CC%" -O2 -w -fwrapv src\tools\genmap.c -o build\bin\genmap.exe
+if errorlevel 1 (echo [ERROR] Failed to build build\bin\genmap.exe.& exit /b 1)
+if exist build\core\map rmdir /s /q build\core\map
+if not exist build\core mkdir build\core
+build\bin\genmap.exe --preset default --check -o build\core\map >nul
+if errorlevel 1 (echo [ERROR] The default memory map does not match the sources.& exit /b 1)
+echo Compiling zc0.exe (bootstrap compiler)...
+"%CC%" -O1 -w -fwrapv src\tools\zc0.c -Isrc/core -Ibuild/core/map -o build\bin\zc0.exe
+if errorlevel 1 (echo [ERROR] Failed to build build\bin\zc0.exe.& exit /b 1)
+echo Compiling mkgenome.exe (genome image checker)...
+"%CC%" -O1 -w -fwrapv src\tools\mkgenome.c -Ibuild/core/map -o build\bin\mkgenome.exe
+if errorlevel 1 (echo [ERROR] Failed to build build\bin\mkgenome.exe.& exit /b 1)
+echo [OK] Bootstrap tools built in build\bin.
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.
+REM zc0 compiles the compiler to g0, g0 compiles it to g1, g1 to g2. g1 and g2
+REM must be identical, and g1 becomes build\core\genome.bin.
+:build_genome
+call :build_tools
+if errorlevel 1 exit /b 1
+echo Bootstrapping the compiler genome...
+if not exist build\s0 mkdir build\s0
+if not exist build\s1 mkdir build\s1
+(type src\runtime\rt.zc & type src\core\core.zc & type src\compiler\compiler.zc) | build\bin\zc0.exe > build\s0\g0.bin
+if errorlevel 1 (echo [ERROR] Stage 0 failed.& exit /b 1)
+build\bin\mkgenome.exe < build\s0\g0.bin > build\s0\genome.bin
+if errorlevel 1 (echo [ERROR] Stage 0 did not produce a genome.& exit /b 1)
+"%CC%" -O2 -w -fwrapv -DJTYPE=int src\core\core.c src\core\io_win.c -Isrc/core -Ibuild/core/map --embed-dir=build/s0 -o build\s0\zy0.exe
+if errorlevel 1 (echo [ERROR] Failed to build the stage 0 core.& exit /b 1)
+(type src\tools\build.zc & echo ` & type src\runtime\rt.zc & type src\core\core.zc & type src\compiler\compiler.zc) | build\s0\zy0.exe > build\s1\g1.bin
+build\bin\mkgenome.exe < build\s1\g1.bin > build\s1\genome.bin
+if errorlevel 1 (echo [ERROR] The compiler did not compile itself; its diagnostics are above.& exit /b 1)
+"%CC%" -O2 -w -fwrapv -DJTYPE=int src\core\core.c src\core\io_win.c -Isrc/core -Ibuild/core/map --embed-dir=build/s1 -o build\s1\zy1.exe
+if errorlevel 1 (echo [ERROR] Failed to build the stage 1 core.& exit /b 1)
+(type src\tools\build.zc & echo ` & type src\runtime\rt.zc & type src\core\core.zc & type src\compiler\compiler.zc) | build\s1\zy1.exe > build\s1\g2.bin
+fc /b build\s1\g1.bin build\s1\g2.bin >nul
+if errorlevel 1 (echo [ERROR] Fixpoint failed: the compiler does not compile itself to the same image.& exit /b 1)
+copy /y build\s1\genome.bin build\core\genome.bin >nul
+echo [OK] Fixpoint reached; build\core\genome.bin updated.
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\.
+:need_genome
+if exist build\core\genome.bin if exist build\core\map\memmap.h exit /b 0
+call :build_genome
+exit /b %errorlevel%
+
+:build_core
+call :need_genome
+if errorlevel 1 exit /b 1
+echo Compiling zy.exe (VM core with the compiler genome)...
+"%CC%" -O2 -w -fwrapv -DJTYPE=int src\core\core.c src\core\io_win.c %COREINC% -o build\bin\zy.exe
+if errorlevel 1 (echo [ERROR] Failed to build build\bin\zy.exe.& exit /b 1)
+echo [OK] build\bin\zy.exe built.
+exit /b 0
+
+:build_micro
+call :need_genome
+if errorlevel 1 exit /b 1
+echo Compiling zym.exe (portable microcore)...
+"%CC%" -O2 -w -fwrapv src\micro\micro.c src\micro\port_win.c %COREINC% -Isrc/micro -o build\bin\zym.exe
+if errorlevel 1 (echo [ERROR] Failed to build build\bin\zym.exe.& exit /b 1)
+echo [OK] build\bin\zym.exe built.
exit /b 0
+REM the language server: the compiler in check mode plus src\lsp\server.zc, on a
+REM map sized to the image (the steps of src/tools/automap.sh lsp with DOCS=1)
: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" (
+if not exist "build\bin\genmap.exe" (
call :build_tools
if errorlevel 1 exit /b 1
)
+echo Compiling zclsp.exe (language server ^& semantic highlighter)...
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
+mkdir build\lsp
+call :lsp_pass "" "" image.bin
+if errorlevel 1 exit /b 1
+call :words build\lsp\image.bin
+set /a SLOT=(WORDS+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
+call :lsp_pass %DOCS_WORK% -DZC0DOCS image.bin
+if errorlevel 1 exit /b 1
+call :words build\lsp\image.bin
+set /a DOCS_SLOT=(WORDS+4095)/4096*4096
+set "DOCS_WORDS=!WORDS!"
+call :lsp_pass %DOCS_SLOT% -DZC0DOCS lsp_genome.bin
+if errorlevel 1 exit /b 1
+call :words build\lsp\lsp_genome.bin
+if not "!WORDS!"=="!DOCS_WORDS!" (echo [ERROR] LSP genome changed length after map sizing.& exit /b 1)
+copy /y build\lsp\map\memmap.h build\lsp\memmap.h >nul
+"%CC%" -O2 -w -fwrapv -DJTYPE=int -DZY_SANDBOX -DUSE_LSP_GENOME src\core\core.c src\core\io_win.c -Isrc/core -Ibuild/lsp --embed-dir=build/lsp -o build\lsp\zclsp.exe
+if errorlevel 1 (echo [ERROR] Failed to build zclsp.exe.& exit /b 1)
+if not exist "build\bin" mkdir build\bin
+copy /y build\lsp\zclsp.exe build\bin\zclsp.exe >nul
+echo [OK] build\bin\zclsp.exe built with !WORDS! words.
+exit /b 0
+
+REM :lsp_pass genome-slot zc0-define output - lay out the lsp map (with that genome
+REM slot, or the preset's own when it is empty) and compile the server image into it
+:lsp_pass
+if exist build\lsp\map rmdir /s /q build\lsp\map
+if "%~1"=="" (
+ build\bin\genmap.exe --preset lsp --grow -o build\lsp\map >nul 2>nul
+) else (
+ build\bin\genmap.exe --preset lsp --grow --genome %~1 -o build\lsp\map >nul 2>nul
+)
+if errorlevel 1 (echo [ERROR] Could not generate the LSP map.& exit /b 1)
+"%CC%" -O1 -w -fwrapv %~2 src\tools\zc0.c -Ibuild/lsp/map -Isrc/core -o build\lsp\zc0.exe
+if errorlevel 1 (echo [ERROR] Could not build the LSP stage 0 compiler.& exit /b 1)
+"%CC%" -O1 -w -fwrapv src\tools\mkgenome.c -Ibuild/lsp/map -o build\lsp\mkgenome.exe
+if errorlevel 1 (echo [ERROR] Could not build the LSP image checker.& exit /b 1)
+(type build\lsp\map\rt.zc & type src\core\core.zc & type build\lsp\map\compiler.zc & type src\lsp\server.zc) | build\lsp\zc0.exe > build\lsp\raw.bin
+if errorlevel 1 (echo [ERROR] Could not compile the LSP image.& exit /b 1)
+build\lsp\mkgenome.exe < build\lsp\raw.bin > build\lsp\%~3
+if errorlevel 1 (echo [ERROR] The LSP image does not match its map.& exit /b 1)
+exit /b 0
+
+REM :words file - WORDS is the file's length in 64-bit words
+:words
+set /a WORDS=%~z1/8
+exit /b 0
+
+REM the javascript vm: layout, genome and the compiled vm in build\js (needs node and tsc)
+:build_js
+call :need_genome
if errorlevel 1 exit /b 1
-copy /y src\core\io_win.c build\lsp\src\ >nul
+if not exist build\js mkdir build\js
+node src\js\mklayout.js --map build\core\map\memmap.h --out build\js >nul
+if errorlevel 1 (echo [ERROR] Could not write the javascript layout.& exit /b 1)
+copy /y build\core\genome.bin build\js\genome.bin >nul
+call tsc src\js\tinyvm.ts --target es2020 --lib es2020,dom --module commonjs --outDir build\js
+if errorlevel 1 (echo [ERROR] Could not compile the javascript vm; tsc is needed.& exit /b 1)
+exit /b 0
+
+:build_all
+call :build_genome
if errorlevel 1 exit /b 1
-copy /y src\core\fops.h build\lsp\src\ >nul
+call :build_core
if errorlevel 1 exit /b 1
-copy /y src\core\bops.h build\lsp\src\ >nul
+call :build_micro
if errorlevel 1 exit /b 1
-copy /y src\core\stack.h build\lsp\src\ >nul
+call :build_lsp
+exit /b %errorlevel%
+
+:run_tests
+call :build_core
if errorlevel 1 exit /b 1
-copy /y build\lsp\map\memmap.h build\lsp\src\ >nul
+call :build_micro
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.
+powershell -NoProfile -ExecutionPolicy Bypass -File "tests\test_win.ps1"
+exit /b %errorlevel%
+
+:clean
+rmdir /s /q build 2>nul
+echo [OK] Generated build directory removed.
exit /b 0
REM =========================================================================
@@ -514,22 +554,24 @@ 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 "%ARG2%"=="" ( call :build_all & exit /b !errorlevel! )
+ if /i "%ARG2%"=="all" ( call :build_all & exit /b !errorlevel! )
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! )
+ if /i "%ARG2%"=="js" ( call :build_js & exit /b !errorlevel! )
echo Unknown build target: %ARG2%
exit /b 1
)
+if /i "%CMD%"=="genome" (
+ call :build_genome
+ exit /b !errorlevel!
+)
+
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"
+ call :run_tests
exit /b !errorlevel!
)
@@ -539,11 +581,11 @@ if /i "%CMD%"=="run" (
echo Usage: tinyvm.bat run path\to\program.zc
exit /b 1
)
- if not exist "bin\zy.exe" (
+ if not exist "build\bin\zy.exe" (
call :build_core
if errorlevel 1 exit /b 1
)
- bin\zy.exe < "%SOURCE_ARG%"
+ build\bin\zy.exe < "%SOURCE_ARG%"
exit /b !errorlevel!
)
@@ -553,11 +595,11 @@ if /i "%CMD%"=="run-micro" (
echo Usage: tinyvm.bat run-micro path\to\program.zc
exit /b 1
)
- if not exist "bin\zym.exe" (
+ if not exist "build\bin\zym.exe" (
call :build_micro
if errorlevel 1 exit /b 1
)
- bin\zym.exe < "%SOURCE_ARG%"
+ build\bin\zym.exe < "%SOURCE_ARG%"
exit /b !errorlevel!
)
@@ -567,7 +609,9 @@ if /i "%CMD%"=="js" (
echo Usage: tinyvm.bat js path\to\program.zc
exit /b 1
)
- node src\js\tinyvm.js "%SOURCE_ARG%"
+ call :build_js
+ if errorlevel 1 exit /b 1
+ node build\js\tinyvm.js "%SOURCE_ARG%"
exit /b !errorlevel!
)
@@ -577,62 +621,43 @@ if /i "%CMD%"=="lsp" (
echo Usage: tinyvm.bat lsp path\to\program.zc
exit /b 1
)
- if not exist "bin\zclsp.exe" (
+ if not exist "build\bin\zclsp.exe" (
call :build_lsp
if errorlevel 1 exit /b 1
)
- bin\zclsp.exe < "%SOURCE_ARG%"
+ build\bin\zclsp.exe < "%SOURCE_ARG%"
exit /b !errorlevel!
)
if /i "%CMD%"=="repl" (
- if not exist "bin\zy.exe" (
+ if not exist "build\bin\zy.exe" (
call :build_core
if errorlevel 1 exit /b 1
)
- (type examples\repl.zc & echo ` & more) | bin\zy.exe
+ (type examples\repl.zc & echo ` & more) | build\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.
+ call :clean
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 build [all^|core^|micro^|tools^|lsp^|js]
+echo compile TinyVM executables into build\bin
+echo tinyvm.bat genome rebuild build\core\genome.bin and check the fixpoint
echo tinyvm.bat run ^<file.zc^> run a .zc program on VM core (zy.exe)
echo tinyvm.bat run-micro ^<file.zc^> run a .zc program on microcore (zym.exe)
echo tinyvm.bat js ^<file.zc^> run a .zc program on the JavaScript VM (node)
echo tinyvm.bat lsp ^<file.zc^> check/highlight a .zc program with zclsp.exe
-echo tinyvm.bat test run the full Windows test suite
+echo tinyvm.bat test run the Windows test suite
echo tinyvm.bat repl launch the resident compiler REPL
-echo tinyvm.bat clean remove generated bin and build directories
+echo tinyvm.bat clean remove the generated build directory
+echo the compiler must support c23 #embed: clang 19 or gcc 15 and later.
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!