aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Moon Flower <moonflower@elhenney.local> 2026-10-14 08:45:35 +0330
committerGravatar Moon Flower <moonflower@elhenney.local> 2026-10-14 08:45:35 +0330
commitd981870038c3ffa531f5c1d07e4aec855e061491 (patch)
tree9b88cc64668a54a7b240bd180a12c5f2779bd081
parentfeat: grow memory limits, add icon/actor libraries, overhaul LSP diagnostics (diff)
build: generate everything into build/, keep src/ free of generated files
src/ carried 8.4 MB of build output: the genome header, the javascript vm and its layout, and the language-server image, plus a second copy of the extension server under editors/vscode/server/. none of it is source. - move the genome from src/core/genome.h to build/core/genome.h and compile with -Ibuild/core; `make all` bootstraps one when it is missing - write genome.json, layout.ts, layout.js and lsp.json to build/js/ - compile tinyvm.ts to build/js/, typed by a tracked src/js/layout.d.ts so the vm needs no generated file beside its source - build the wasm server into build/editors/vscode/server/ and stage the whole server into editors/vscode/server/ only while mkvsix.sh packages it - redirect the test suite, image_run.js, tinyvm.sh, tinyvm.bat, test_win.ps1 and the baremetal build at the new paths, and add make lspimage and make vsix - stop tracking every generated file also fix a build blocker: lookup_raw compared skind against K_VAR, which was never declared, so `make genome` could not run at all. the guard is about emitted program globals, which are K_GVAR and K_GARR. tests/test.sh -q reports 159 passed and 21 failed both before and after this change; every failure is pre-existing and comes from the checked-in genome being stale relative to src/, plus the bootstrap above.
-rw-r--r--.gitignore6
-rw-r--r--Makefile70
-rw-r--r--README.md16
-rw-r--r--TODO.md1
-rwxr-xr-xsrc/baremetal/run.sh2
-rw-r--r--src/compiler/compiler.zc2
-rw-r--r--src/js/extract_genome.js84
-rw-r--r--src/js/extract_lsp.js55
-rw-r--r--src/js/layout.d.ts17
-rw-r--r--src/js/tinyvm.ts6
-rwxr-xr-xsrc/tools/mklspwasm.sh9
-rwxr-xr-xsrc/tools/mkvsix.sh34
-rw-r--r--tests/drivers/image_run.js2
-rw-r--r--tests/drivers/lsp_vm.js2
-rwxr-xr-xtests/test.sh36
-rw-r--r--tests/test_win.ps114
-rwxr-xr-xtinyvm.bat2
-rwxr-xr-xtinyvm.sh2
18 files changed, 246 insertions, 114 deletions
diff --git a/.gitignore b/.gitignore
index 6c1dc32..d79798a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,9 +3,13 @@ bin/
*.o
*.obj
*.exe
-!editors/vscode/bin/*.exe
# built programs
/bin/
/build/
/src/web/zc.wasm
+
+# the editor's packaged server: layout, vm and language-server image, plus the
+# wasm server. `make vsix` stages it into editors/vscode/server/ only while it
+# packages, so nothing built is kept in the tree.
+/editors/vscode/server/
diff --git a/Makefile b/Makefile
index b0e0df1..6a3898d 100644
--- a/Makefile
+++ b/Makefile
@@ -5,15 +5,20 @@
# make test the whole suite (tests/test.sh)
# make check the minimal suite, for iterating (tests/test.sh -q)
# make test JOBS=4 the same, four sections at a time
-# make genome rebuild src/core/genome.h from src/ and check the fixpoint
+# make genome rebuild build/core/genome.h from src/ and check the fixpoint
# make lsp bin/zclsp, the language server
# make web src/web/zc.wasm (needs clang with the wasm32 target)
-# make js src/js/genome.json, for the javascript vm
+# make js build/js/genome.json and the vm, for the javascript vm
# make run PROG=examples/hello.zc
# compile one program into a run-only image on a memory
# map sized to it (src/tools/automap.sh) -> build/run/zymr
+# make vsix the vscode extension, server and all
# make clean remove bin/ and build/ and the web build
#
+# nothing built is kept in the tree: the genome, the javascript vm and its
+# layout, and the packed editor server all land in build/ (the web build keeps
+# its historical src/web/zc.wasm path because the page loads it by name).
+#
# CC picks the compiler (cc by default; clang works too).
CC ?= cc
@@ -32,6 +37,11 @@ endif
BIN := bin
B := build
+JS := $(B)/js
+# the hand-written core headers, then the generated genome beside them
+COREINC := -Isrc/core -I$(B)/core
+# the sources the compiler genome is built from
+ZC_SRC := src/runtime/rt.zc src/core/core.zc src/compiler/compiler.zc
TOOLS := $(BIN)/zc0$(EXE) $(BIN)/mkgenome$(EXE) $(BIN)/genmap$(EXE)
PROGS := $(BIN)/zy$(EXE) $(BIN)/zym$(EXE) $(BIN)/zclsp$(EXE)
@@ -49,11 +59,11 @@ $(BIN)/genmap$(EXE): src/tools/genmap.c | $(BIN)
$(CC) $(CFLAGS) src/tools/genmap.c -Isrc/core -o $@
# the interpreter: the vm core with the compiler genome inside
-$(BIN)/zy$(EXE): src/core/core.c $(IO) src/core/genome.h src/core/memmap.h src/core/fops.h src/core/bops.h src/core/stack.h | $(BIN)
- $(CC) $(CFLAGS) -DJTYPE=int src/core/core.c $(IO) -Isrc/core -o $@
+$(BIN)/zy$(EXE): src/core/core.c $(IO) $(B)/core/genome.h src/core/memmap.h src/core/fops.h src/core/bops.h src/core/stack.h | $(BIN)
+ $(CC) $(CFLAGS) -DJTYPE=int src/core/core.c $(IO) $(COREINC) -o $@
# the portable microcore
-$(BIN)/zym$(EXE): src/micro/micro.c src/micro/micro_port.h $(PORT) src/core/genome.h src/core/memmap.h src/core/fops.h src/core/bops.h src/core/stack.h | $(BIN)
- $(CC) $(CFLAGS) $(MICRO_THREADS) src/micro/micro.c $(PORT) -Isrc/core -Isrc/micro -o $@
+$(BIN)/zym$(EXE): src/micro/micro.c src/micro/micro_port.h $(PORT) $(B)/core/genome.h src/core/memmap.h src/core/fops.h src/core/bops.h src/core/stack.h | $(BIN)
+ $(CC) $(CFLAGS) $(MICRO_THREADS) src/micro/micro.c $(PORT) $(COREINC) -Isrc/micro -o $@
# the language server is the compiler in check mode plus src/lsp/server.zc, on a map
# sized to it
@@ -66,33 +76,49 @@ src/compiler/compiler.zc: src/lib/std.zc src/lib/icon.zc src/tools/embed.sh
bash src/tools/embed.sh all
# bootstrap: zc0 compiles the compiler to g0, g0 compiles it to g1, g1 to g2.
-# g1 and g2 must be identical (the fixpoint), and g1 becomes src/core/genome.h.
+# g1 and g2 must be identical (the fixpoint), and g1 becomes build/core/genome.h.
+# run this by hand after editing a .zc source; `make check` reports a stale genome.
genome: $(BIN)/zc0$(EXE) $(BIN)/mkgenome$(EXE) src/compiler/compiler.zc | $(B)
- mkdir -p $(B)/s0 $(B)/s1
+ mkdir -p $(B)/s0 $(B)/s1 $(B)/core
cp src/core/core.c $(IO) src/core/memmap.h src/core/fops.h src/core/bops.h src/core/stack.h $(B)/s0/
cp src/core/core.c $(IO) src/core/memmap.h src/core/fops.h src/core/bops.h src/core/stack.h $(B)/s1/
- cat src/runtime/rt.zc src/core/core.zc src/compiler/compiler.zc | $(BIN)/zc0$(EXE) > $(B)/s0/genome.h
+ cat $(ZC_SRC) | $(BIN)/zc0$(EXE) > $(B)/s0/genome.h
$(CC) $(CFLAGS) -DJTYPE=int $(B)/s0/core.c $(B)/s0/$(notdir $(IO)) -o $(B)/zy0$(EXE)
- (cat src/tools/build.zc; printf '`'; cat src/runtime/rt.zc src/core/core.zc src/compiler/compiler.zc) | $(B)/zy0$(EXE) > $(B)/g1.bin
+ (cat src/tools/build.zc; printf '`'; cat $(ZC_SRC)) | $(B)/zy0$(EXE) > $(B)/g1.bin
$(BIN)/mkgenome$(EXE) < $(B)/g1.bin > $(B)/s1/genome.h
$(CC) $(CFLAGS) -DJTYPE=int $(B)/s1/core.c $(B)/s1/$(notdir $(IO)) -o $(B)/zy1$(EXE)
- (cat src/tools/build.zc; printf '`'; cat src/runtime/rt.zc src/core/core.zc src/compiler/compiler.zc) | $(B)/zy1$(EXE) > $(B)/g2.bin
+ (cat src/tools/build.zc; printf '`'; cat $(ZC_SRC)) | $(B)/zy1$(EXE) > $(B)/g2.bin
cmp $(B)/g1.bin $(B)/g2.bin
- cp $(B)/s1/genome.h src/core/genome.h
- @echo "fixpoint: $$(( $$(wc -c < $(B)/g1.bin) / 8 )) words, src/core/genome.h updated"
+ cp $(B)/s1/genome.h $(B)/core/genome.h
+ @echo "fixpoint: $$(( $$(wc -c < $(B)/g1.bin) / 8 )) words, $(B)/core/genome.h updated"
+
+# a fresh clone has no genome, so bootstrap one on demand. it is deliberately
+# not rebuilt from source dependencies: the fixpoint run is expensive, and
+# `make genome` is the explicit way to refresh it after editing a .zc file.
+$(B)/core/genome.h:
+ $(MAKE) genome
-js: src/js/genome.json src/js/layout.ts src/js/layout.js src/js/tinyvm.js
-src/js/genome.json: src/core/genome.h src/core/memmap.h src/js/extract_genome.js src/js/mapvalues.js
+js: $(JS)/genome.json $(JS)/layout.js $(JS)/tinyvm.js
+$(JS):
+ mkdir -p $@
+$(JS)/genome.json: $(B)/core/genome.h src/core/memmap.h src/js/extract_genome.js src/js/mapvalues.js | $(JS)
node src/js/extract_genome.js
-src/js/layout.ts: src/js/genome.json
+$(JS)/layout.ts $(JS)/layout.js: $(JS)/genome.json
@test -f $@ || node src/js/extract_genome.js
-src/js/layout.js: src/js/layout.ts
- @test -f $@ || node src/js/extract_genome.js
-src/js/tinyvm.js: src/js/tinyvm.ts src/js/layout.ts
- tsc src/js/tinyvm.ts --target es2020 --lib es2020,dom --module commonjs --outDir src/js
+$(JS)/tinyvm.js: src/js/tinyvm.ts src/js/layout.d.ts | $(JS)
+ tsc src/js/tinyvm.ts --target es2020 --lib es2020,dom --module commonjs --outDir $(JS)
+
+# the language server image for the javascript vm, and the wasm server
+lspimage: $(JS)/lsp.json
+$(JS)/lsp.json: $(BIN)/zclsp$(EXE) src/js/extract_lsp.js src/js/mapvalues.js | $(JS)
+ node src/js/extract_lsp.js
+
+# the vscode extension, with the server and its image inside it
+vsix: | $(B)
+ bash src/tools/mkvsix.sh
web: src/web/zc.wasm
-src/web/zc.wasm: src/micro/micro.c src/micro/micro_port.h src/web/port_wasm.c src/web/build.sh src/core/genome.h src/core/memmap.h src/core/fops.h src/core/bops.h src/core/stack.h
+src/web/zc.wasm: src/micro/micro.c src/micro/micro_port.h src/web/port_wasm.c src/web/build.sh $(B)/core/genome.h src/core/memmap.h src/core/fops.h src/core/bops.h src/core/stack.h
bash src/web/build.sh $@
# one program as a run-only image: the runtime, the program, and a map exactly
@@ -115,4 +141,4 @@ check:
clean:
rm -rf $(BIN) $(B) src/web/zc.wasm
-.PHONY: all lsp genome js web run test check clean
+.PHONY: all lsp genome js lspimage vsix web run test check clean
diff --git a/README.md b/README.md
index bcad133..904bd0a 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@ this folder has the latest code. `docs/LEARN.md` is a tour of the language. `doc
## files
-`src/core/core.c` is the native core. it contains the arm64 jit, the llvm backend (behind `-DZYLLVM`), the portable interpreter, the enhancement unit (recipe parser, vm-code lifter, optimizer and lowering), and the o3 region compiler. `src/runtime/rt.zc` provides i/o, native division enhancements, the heap, and the collector; `src/compiler/compiler.zc` is the compiler. both are written in zc and begin with an overview. together they make up the genome. `src/tools/zc0.c` is stage 0 of the bootstrap, a c compiler for the subset of zc used by `src/compiler/compiler.zc`. `src/tools/build.zc` has the resident compiler compile its own source into a fresh image, and `src/tools/mkgenome.c` turns that image into the generated, checked-in `src/core/genome.h`. `examples/` contains small programs (hello, factorial, echo, self-patching code, an owning list, a repl, a typed program, and an enhancement demo) and larger proofs of concept:
+`src/core/core.c` is the native core. it contains the arm64 jit, the llvm backend (behind `-DZYLLVM`), the portable interpreter, the enhancement unit (recipe parser, vm-code lifter, optimizer and lowering), and the o3 region compiler. `src/runtime/rt.zc` provides i/o, native division enhancements, the heap, and the collector; `src/compiler/compiler.zc` is the compiler. both are written in zc and begin with an overview. together they make up the genome. `src/tools/zc0.c` is stage 0 of the bootstrap, a c compiler for the subset of zc used by `src/compiler/compiler.zc`. `src/tools/build.zc` has the resident compiler compile its own source into a fresh image, and `src/tools/mkgenome.c` turns that image into the generated `build/core/genome.h`. `examples/` contains small programs (hello, factorial, echo, self-patching code, an owning list, a repl, a typed program, and an enhancement demo) and larger proofs of concept:
- `mandel.zc`: the mandelbrot set in 16.16 fixed point, with the fixed-point multiply wired in as a custom opcode.
- `bf.zc`: a brainfuck compiler. it turns brainfuck into zc source, has the resident compiler compile it, and runs it (native code on the jit). it takes a program after a backtick, or runs hello world.
@@ -37,7 +37,7 @@ make js
make run PROG=examples/hello.zc
```
-`make genome` bootstraps the compiler, compares two self-compiled images, and updates `src/core/genome.h` only after they agree. rebuild the native, javascript, and web runtimes after changing the genome. `make check` runs the smaller suite while iterating.
+`make genome` bootstraps the compiler, compares two self-compiled images, and updates `build/core/genome.h` only after they agree. rebuild the native, javascript, and web runtimes after changing the genome. `make check` runs the smaller suite while iterating.
### command-line help
@@ -45,7 +45,7 @@ the native vm, portable vm, language server, bootstrap compiler, image converter
the same early help option is available in `tinyvm.sh`, `tinyvm.bat`, `src/tools/zcc`, the public `src/tools/*.sh` build scripts, and the javascript vm and extraction utilities. `src/tools/zcc [-o OUT] [-k] FILE.zc` builds a standalone run-only binary. `src/tools/automap.sh run|small|default|lsp OUTDIR FILE...` generates a sized map and image; `src/tools/embed.sh std|icon|all [--check]` refreshes embedded modules, while its `lsp OUT` form writes source providers. `src/tools/mklsp.sh [OUTDIR]`, `src/tools/mklspwasm.sh [OUTFILE.wasm]` and `src/tools/mkvsix.sh [OUTFILE.vsix]` build the language server and extension. the javascript vm accepts an optional source file; without one it reads source from stdin. the extraction utilities take no input arguments and read the generated headers from their documented paths. `python3 tests/drivers/cli_help_test.py` checks the native, micro, LSP, bootstrap and image tools, shell scripts, and javascript utilities with open stdin and invalid memory settings, rejects unknown options, and confirms the language server source options still work.
-`make js` regenerates the JavaScript bundle and needs Node.js and the TypeScript compiler (`tsc`). running the committed `src/js/tinyvm.js` directly needs Node.js only.
+`make js` regenerates the JavaScript bundle into `build/js/` and needs Node.js and the TypeScript compiler (`tsc`). running the built `build/js/tinyvm.js` directly needs Node.js only.
### interactive runners
@@ -125,14 +125,14 @@ build a package with `bash src/tools/mkvsix.sh`, then use "extensions: install f
a complete, self-contained 64-bit TinyVM core implemented in JavaScript and TypeScript is provided in `src/js/`:
-- `src/js/tinyvm.ts` and `src/js/tinyvm.js`: Implements the 64-bit word machine on `BigInt64Array` with byte addressing (`Uint8Array` / `DataView`), dual stacks, all 22 base opcodes, byte/float opcodes (612–619), system calls, and custom virtual enhancement execution (`xrun`).
-- `src/js/genome.json`: the compiler genome loaded into VM memory. `node src/js/extract_genome.js` rebuilds it from `src/core/genome.h`, and `tests/test.sh` checks it is current.
+- `src/js/tinyvm.ts` (compiled to `build/js/tinyvm.js`): Implements the 64-bit word machine on `BigInt64Array` with byte addressing (`Uint8Array` / `DataView`), dual stacks, all 22 base opcodes, byte/float opcodes (612–619), system calls, and custom virtual enhancement execution (`xrun`).
+- `build/js/genome.json`: the compiler genome loaded into VM memory, generated. `node src/js/extract_genome.js` rebuilds it from `build/core/genome.h`, and `tests/test.sh` checks it is current.
run any `.zc` program in Node.js:
```cmd
-node src/js/tinyvm.js examples/hello.zc
-node src/js/tinyvm.js examples/fact.zc
-node src/js/tinyvm.js examples/mandel.zc
+node build/js/tinyvm.js examples/hello.zc
+node build/js/tinyvm.js examples/fact.zc
+node build/js/tinyvm.js examples/mandel.zc
# or via the Windows runner:
tinyvm.bat js examples/primes.zc
```
diff --git a/TODO.md b/TODO.md
index ae2c746..d0634fc 100644
--- a/TODO.md
+++ b/TODO.md
@@ -141,3 +141,4 @@
- [ ] document the public standard-library APIs with concise descriptions of behavior, parameters, ownership and return values where applicable; update reference and learning entries, add executable examples and record implemented changes in history; keep prose lowercase and verify docs appear in hovers.
- [ ] revise diagnostics, comments and learning/reference prose using professional compiler documentation guidance, preserving lowercase and adding message regressions.
- [ ] implement and integrate `src/lib/icon.zc` with structured runtime syntax transformations, template matching, execution inspection and stepping, with explicit contracts and comprehensive tests.
+- [ ] change the producer of the genome header (`build/core/genome.h`) to emit a c translation unit that embeds the compiler, core and runtime zc sources with a `#embed` directive instead of concatenating them into a 1.5 mb generated header; keep the `.zc` sources as the single source of truth and extend the fixpoint check in `make genome` so it still verifies the emitted genome without materializing a header at all.
diff --git a/src/baremetal/run.sh b/src/baremetal/run.sh
index aec9d20..467e86e 100755
--- a/src/baremetal/run.sh
+++ b/src/baremetal/run.sh
@@ -78,7 +78,7 @@ if [ "$mode" = run ] || [ "$mode" = io ]; then
timeout=120
fi
elif [ "$mode" = compile ]; then
- cp src/micro/micro.c src/micro/micro_port.h src/core/memmap.h src/core/genome.h src/core/fops.h src/core/bops.h src/core/stack.h "$D/"
+ cp src/micro/micro.c src/micro/micro_port.h src/core/memmap.h build/core/genome.h src/core/fops.h src/core/bops.h src/core/stack.h "$D/"
"$cc" $common $def -I"$D" -c "$D/micro.c" -o "$D/micro.o"
"$cc" $common $def -DBARE_INPUT=1 -I"$D" -c src/baremetal/port.c -o "$D/port.o"
timeout=90
diff --git a/src/compiler/compiler.zc b/src/compiler/compiler.zc
index d274eff..2a05c58 100644
--- a/src/compiler/compiler.zc
+++ b/src/compiler/compiler.zc
@@ -1019,7 +1019,7 @@ int lookup_raw(char* name) {
resident = i;
while (resident >= syntax_host_floor) resident = snext[resident] - 1;
if (resident >= 0) return resident;
- if (skind[i] == K_VAR) serr("a syntax handler cannot access emitted program globals");
+ if (skind[i] == K_GVAR || skind[i] == K_GARR) serr("a syntax handler cannot access emitted program globals");
}
while (i >= 0) {
if (i >= vislo || skind[i] == K_KW || skind[i] == K_TYPE) return i;
diff --git a/src/js/extract_genome.js b/src/js/extract_genome.js
index 89bebe3..4ef2c43 100644
--- a/src/js/extract_genome.js
+++ b/src/js/extract_genome.js
@@ -1,18 +1,52 @@
+// converts the compiler genome and the memory map into the javascript vm's
+// layout files. everything it writes is generated, so it goes to build/js/ and
+// nothing is left in the tree.
+//
+// node src/js/extract_genome.js [--genome PATH] [--map PATH] [--out DIR]
+//
+// the genome is the one make genome produced in build/core/genome.h, and the
+// map is src/core/memmap.h. outputs, in the out directory:
+// genome.json the genome words, for the vm that has no compiler inside it
+// layout.ts the map as typescript constants
+// layout.js the map as commonjs constants
const fs = require('fs');
const path = require('path');
-if (process.argv.length > 2) {
- if (process.argv.length === 3 && ['--help', '-h'].includes(process.argv[2])) {
- console.log('usage: node src/js/extract_genome.js [--help|-h]\nconverts src/core/genome.h and memmap.h into the javascript genome and layout files.');
- process.exit(0);
- }
- console.error('extract_genome: unexpected arguments; use --help for usage');
+const root = path.join(__dirname, '..', '..');
+
+const args = process.argv.slice(2);
+const opt = (name) => {
+ const i = args.indexOf(name);
+ return i >= 0 && args[i + 1] ? args[i + 1] : null;
+};
+if (args.includes('--help') || args.includes('-h')) {
+ console.log([
+ 'usage: node src/js/extract_genome.js [--genome PATH] [--map PATH] [--out DIR]',
+ 'converts the compiler genome and memory map into the javascript layout files.',
+ 'options:',
+ ' --genome PATH the genome header to read; defaults to build/core/genome.h',
+ ' --map PATH the memory map header to read; defaults to src/core/memmap.h',
+ ' --out DIR where to write; defaults to build/js',
+ ' --help, -h show this help and exit',
+ ].join('\n'));
+ process.exit(0);
+}
+const unknown = args.filter((a) => !['--genome', '--map', '--out'].includes(a));
+if (unknown.length) {
+ console.error('extract_genome: unexpected arguments: ' + unknown.join(' ') + '; use --help for usage');
process.exit(2);
}
-const srcPath = path.join(__dirname, '..', 'core', 'genome.h');
-const outPath = path.join(__dirname, 'genome.json');
+const genomePath = opt('--genome') || path.join(root, 'build', 'core', 'genome.h');
+const mapPath = opt('--map') || path.join(__dirname, '..', 'core', 'memmap.h');
+const outDir = opt('--out') || path.join(root, 'build', 'js');
+
+if (!fs.existsSync(genomePath)) {
+ console.error('extract_genome: no genome at ' + genomePath + '; run `make genome` first');
+ process.exit(1);
+}
+fs.mkdirSync(outDir, { recursive: true });
-const text = fs.readFileSync(srcPath, 'utf8');
+const text = fs.readFileSync(genomePath, 'utf8');
const gorgMatch = text.match(/#define\s+GORG\s+(\d+)/);
const glenMatch = text.match(/#define\s+GLEN\s+(\d+)/);
@@ -21,33 +55,39 @@ const glen = parseInt(glenMatch[1], 10);
const arrMatch = text.match(/genome\[\]\s*=\s*\{([\s\S]*?)\};/);
if (!arrMatch) {
- console.error('Could not find genome array in genome.h');
+ console.error('extract_genome: could not find the genome array in ' + genomePath);
process.exit(1);
}
const words = arrMatch[1]
.split(',')
.map(s => s.trim())
- .filter(s => s.length > 0)
- .map(s => s); // keep as string numbers
+ .filter(s => s.length > 0);
console.log(`Parsed genome: GORG=${gorg}, GLEN=${words.length}`);
if (words.length !== glen) throw new Error('genome length does not match GLEN');
-// the compiler's map, from src/core/memmap.h, as typescript constants: the js vm reads
-// them instead of its own copies. the values are computed here, from the map.
+// the compiler's map, as typescript constants: the js vm reads them instead of
+// its own copies. the values are computed here, from the map.
const { mapValues } = require('./mapvalues.js');
const names = ['MW', 'PW', 'ZFP', 'GORG', 'DS0', 'DSLIM', 'RS0', 'RSLIM', 'SYSGATE', 'HEAP_LO', 'HEAP_HI'];
-const map = mapValues(path.join(__dirname, '..', 'core', 'memmap.h'), names);
+const map = mapValues(mapPath, names);
if (map.GORG !== gorg) throw new Error('genome GORG ' + gorg + ' is not the map GORG ' + map.GORG);
-fs.writeFileSync(outPath, JSON.stringify({ gorg, glen, words }));
-console.log(`saved genome to ${outPath}`);
+
+const genomeJson = path.join(outDir, 'genome.json');
+fs.writeFileSync(genomeJson, JSON.stringify({ gorg, glen, words }));
+console.log('saved genome to ' + genomeJson);
+
const lines = names.map(k => ` ${k}: ${map[k]},`).join('\n');
-fs.writeFileSync(path.join(__dirname, 'layout.ts'),
- '// generated by src/js/extract_genome.js from src/core/memmap.h. do not edit.\n' +
+const layoutTs = path.join(outDir, 'layout.ts');
+fs.writeFileSync(layoutTs,
+ '// generated by src/js/extract_genome.js from ' + path.relative(root, mapPath) + '. do not edit.\n' +
'export const MAP = {\n' + lines + '\n} as const;\n');
-console.log(`Saved the map to ${path.join(__dirname, 'layout.ts')}`);
-fs.writeFileSync(path.join(__dirname, 'layout.js'),
- '// generated by src/js/extract_genome.js from src/core/memmap.h. do not edit.\n' +
+console.log('saved the map to ' + layoutTs);
+
+const layoutJs = path.join(outDir, 'layout.js');
+fs.writeFileSync(layoutJs,
+ '// generated by src/js/extract_genome.js from ' + path.relative(root, mapPath) + '. do not edit.\n' +
'exports.MAP = ' + JSON.stringify(map, null, 4) + ';\n');
+console.log('saved the map to ' + layoutJs); \ No newline at end of file
diff --git a/src/js/extract_lsp.js b/src/js/extract_lsp.js
index 358d404..14ee279 100644
--- a/src/js/extract_lsp.js
+++ b/src/js/extract_lsp.js
@@ -1,22 +1,47 @@
-// writes src/js/lsp.json: the language server's image (build/lsp/genome.h, made by
-// src/tools/mklsp.sh) and the map it was built for, read from build/lsp/map/memmap.h.
-// the vm needs the layout, because the server's map is not the compiler's.
+// writes the language server's javascript image: the genome build/lsp/genome.h,
+// made by src/tools/mklsp.sh, and the map it was built for, read from
+// build/lsp/map/memmap.h. the vm needs the layout, because the server's map is
+// not the compiler's. the image is generated, so it goes to build/js/ and
+// nothing is left in the tree.
+//
+// node src/js/extract_lsp.js [--out PATH]
+//
+// build the lsp first (`make lsp`, or src/tools/mklsp.sh); it needs
+// build/lsp/genome.h.
const fs = require('fs');
const path = require('path');
-if (process.argv.length > 2) {
- if (process.argv.length === 3 && ['--help', '-h'].includes(process.argv[2])) {
- console.log('usage: node src/js/extract_lsp.js [--help|-h]\nconverts build/lsp/genome.h and its memory map into src/js/lsp.json; build the lsp first.');
- process.exit(0);
+const root = path.join(__dirname, '..', '..');
+
+const args = process.argv.slice(2);
+if (args.includes('--help') || args.includes('-h')) {
+ console.log([
+ 'usage: node src/js/extract_lsp.js [--out PATH]',
+ 'converts the language server genome and its memory map into a javascript image.',
+ 'options:',
+ ' --out PATH where to write; defaults to build/js/lsp.json',
+ ' --help, -h show this help and exit',
+ ].join('\n'));
+ process.exit(0);
+}
+let out = path.join(root, 'build', 'js', 'lsp.json');
+for (let i = 0; i < args.length; i++) {
+ if (args[i] === '--out' && args[i + 1]) out = args[i + 1];
+ else {
+ console.error('extract_lsp: unexpected arguments; use --help for usage');
+ process.exit(2);
}
- console.error('extract_lsp: unexpected arguments; use --help for usage');
- process.exit(2);
}
-const root = path.join(__dirname, '..', '..');
-const genome = fs.readFileSync(path.join(root, 'build', 'lsp', 'genome.h'), 'utf8');
+const genomePath = path.join(root, 'build', 'lsp', 'genome.h');
+const mapPath = path.join(root, 'build', 'lsp', 'map', 'memmap.h');
+if (!fs.existsSync(genomePath)) {
+ console.error('extract_lsp: no language server image at ' + genomePath + '; run `make lsp` first');
+ process.exit(1);
+}
+const genome = fs.readFileSync(genomePath, 'utf8');
const { mapValues } = require('./mapvalues.js');
-const layout = mapValues(path.join(root, 'build', 'lsp', 'map', 'memmap.h'), ['GORG', 'DS0', 'DSLIM', 'RS0', 'RSLIM', 'SYSGATE', 'ZFP', 'HEAP_LO', 'HEAP_HI']);
+const layout = mapValues(mapPath, ['GORG', 'DS0', 'DSLIM', 'RS0', 'RSLIM', 'SYSGATE', 'ZFP', 'HEAP_LO', 'HEAP_HI']);
const gorg = parseInt(genome.match(/#define\s+GORG\s+(\d+)/)[1], 10);
const glen = parseInt(genome.match(/#define\s+GLEN\s+(\d+)/)[1], 10);
@@ -25,5 +50,7 @@ const words = arr[1].split(',').map(s => s.trim()).filter(s => s.length > 0);
if (words.length !== glen) throw new Error('genome has ' + words.length + ' words, GLEN says ' + glen);
if (gorg !== layout.GORG) throw new Error('genome GORG ' + gorg + ' is not the map GORG ' + layout.GORG);
-fs.writeFileSync(path.join(__dirname, 'lsp.json'), JSON.stringify({ gorg, glen, layout, words }));
-console.log('wrote src/js/lsp.json: genome ' + glen + ' words at ' + gorg + ', heap ' + layout.HEAP_LO + '..' + layout.HEAP_HI);
+fs.mkdirSync(path.dirname(out), { recursive: true });
+fs.writeFileSync(out, JSON.stringify({ gorg, glen, layout, words }));
+console.log('wrote ' + path.relative(root, out) + ': genome ' + glen + ' words at ' + gorg +
+ ', heap ' + layout.HEAP_LO + '..' + layout.HEAP_HI); \ No newline at end of file
diff --git a/src/js/layout.d.ts b/src/js/layout.d.ts
new file mode 100644
index 0000000..1e8c004
--- /dev/null
+++ b/src/js/layout.d.ts
@@ -0,0 +1,17 @@
+// types for the map the javascript vm reads at runtime. the values are
+// generated by src/js/extract_genome.js into build/js/layout.js, which sits
+// beside the compiled vm; this declaration is here so tinyvm.ts typechecks
+// without a generated file in the tree.
+export declare const MAP: {
+ readonly MW: number;
+ readonly PW: number;
+ readonly ZFP: number;
+ readonly GORG: number;
+ readonly DS0: number;
+ readonly DSLIM: number;
+ readonly RS0: number;
+ readonly RSLIM: number;
+ readonly SYSGATE: number;
+ readonly HEAP_LO: number;
+ readonly HEAP_HI: number;
+}; \ No newline at end of file
diff --git a/src/js/tinyvm.ts b/src/js/tinyvm.ts
index b6146fb..4b4bc39 100644
--- a/src/js/tinyvm.ts
+++ b/src/js/tinyvm.ts
@@ -10,7 +10,7 @@ declare const process: any, require: any, module: any, __dirname: string, Buffer
const fs: any = typeof require === 'function' ? require('fs') : undefined;
const path: any = typeof require === 'function' ? require('path') : undefined;
-// the compiler's map, computed from src/core/memmap.h at build time (src/js/layout.ts)
+// the compiler's map, computed from src/core/memmap.h at build time (build/js/layout.js)
import { MAP } from './layout';
// float bits stay in vm words; arithmetic uses javascript's binary64 numbers.
@@ -915,11 +915,11 @@ export class TinyVM {
}
}
-// command line runner: node src/js/tinyvm.js <file.zc>, or the source on stdin
+// command line runner: node build/js/tinyvm.js <file.zc>, or the source on stdin
if (typeof require === 'function' && typeof module !== 'undefined' && require.main === module) {
const option = process.argv[2];
if (option === '--help' || option === '-h') {
- process.stdout.write('usage: node src/js/tinyvm.js [file.zc]\n' +
+ process.stdout.write('usage: node build/js/tinyvm.js [file.zc]\n' +
'compiles and runs the file, or reads source from stdin when no file is supplied.\n' +
'input after a backtick is program input.\n' +
'options:\n --help, -h show this help and exit\n' +
diff --git a/src/tools/mklspwasm.sh b/src/tools/mklspwasm.sh
index 86a902e..4789eab 100755
--- a/src/tools/mklspwasm.sh
+++ b/src/tools/mklspwasm.sh
@@ -1,20 +1,21 @@
#!/bin/bash
-# builds the language server as WebAssembly: editors/vscode/server/lsp.wasm by
-# default, or the path given as the first argument. the server is the compiler
+# builds the language server as WebAssembly: build/editors/vscode/server/lsp.wasm
+# by default, or the path given as the first argument. the server is the compiler
# and src/lsp/server.zc on the map and genome that src/tools/mklsp.sh made in build/lsp,
# and the microcore (src/micro/micro.c) runs them. the host is client/wasmproc.js.
# needs clang with the wasm32 target and wasm-ld; run src/tools/mklsp.sh first.
# src/tools/mklspwasm.sh [outfile.wasm]
set -e
case "${1:-}" in
- --help|-h) printf '%s\n' 'usage: src/tools/mklspwasm.sh [OUTFILE.wasm]' 'builds the wasm language server; defaults to editors/vscode/server/lsp.wasm.' 'requires clang with wasm32 support and wasm-ld.' 'environment: LSP_BUILD_DIR selects the native lsp build; LSP_REUSE_BUILD=1 reuses its image.'; exit 0 ;;
+ --help|-h) printf '%s\n' 'usage: src/tools/mklspwasm.sh [OUTFILE.wasm]' 'builds the wasm language server; defaults to build/editors/vscode/server/lsp.wasm.' 'requires clang with wasm32 support and wasm-ld.' 'environment: LSP_BUILD_DIR selects the native lsp build; LSP_REUSE_BUILD=1 reuses its image.'; exit 0 ;;
-*) echo "mklspwasm: unknown option $1; use --help for usage" >&2; exit 2 ;;
esac
cd "$(dirname "$0")/../.."
-OUT=${1:-editors/vscode/server/lsp.wasm}
+OUT=${1:-build/editors/vscode/server/lsp.wasm}
LSP_BUILD_DIR=${LSP_BUILD_DIR:-build/lsp}
if [ "${LSP_REUSE_BUILD:-0}" != 1 ]; then bash src/tools/mklsp.sh "$LSP_BUILD_DIR" >/dev/null; fi
[ -f "$LSP_BUILD_DIR/src/lsp_genome.h" ] || { echo "mklspwasm: no language server image in $LSP_BUILD_DIR" >&2; exit 1; }
+mkdir -p "$(dirname "$OUT")"
clang --target=wasm32 -O2 -w -fwrapv -nostdlib -fno-builtin -mbulk-memory -DJTYPE=int -DUSE_LSP_GENOME \
-I"$LSP_BUILD_DIR/src" -Isrc/micro src/micro/micro.c src/micro/port_wasm_stream.c \
-Wl,--no-entry -Wl,--export=wasm_chunk -Wl,--export=wasm_chunk_cap -Wl,--export=wasm_feed \
diff --git a/src/tools/mkvsix.sh b/src/tools/mkvsix.sh
index 39fb9c4..df9e703 100755
--- a/src/tools/mkvsix.sh
+++ b/src/tools/mkvsix.sh
@@ -1,9 +1,13 @@
#!/bin/bash
# builds the vs code extension, with the language server inside it: the tinyvm
-# javascript vm (src/js/tinyvm.js, compiled from src/js/tinyvm.ts) and the server's image
-# (src/js/lsp.json, from build/lsp/genome.h and its map), and the wasm server
+# javascript vm (built from src/js/tinyvm.ts) and the server's image
+# (build/js/lsp.json, from build/lsp/genome.h and its map), and the wasm server
# (src/tools/mklspwasm.sh) when clang can build it. needs node and tsc; the
# server build (src/tools/mklsp.sh) runs first if build/lsp is missing.
+#
+# everything generated lands in build/. the packaged files are staged into
+# editors/vscode/server/ only for as long as vsce is packing, then removed, so a
+# fresh clone has no extension until it is built.
# src/tools/mkvsix.sh [outfile.vsix]
set -e
case "${1:-}" in
@@ -14,20 +18,32 @@ cd "$(dirname "$0")/../.."
OUT=${1:-$PWD/build/zc-language-support.vsix}
case "$OUT" in /*) ;; *) OUT="$PWD/$OUT" ;; esac
mkdir -p "$(dirname "$OUT")"
+JS=build/js
+STAGE=build/editors/vscode/server
+PACKDIR=editors/vscode/server
+
bash src/tools/mklsp.sh build/lsp >/dev/null
# typescript errors stop packaging, so broken generated code is never shipped.
command -v tsc >/dev/null || { echo "mkvsix: tsc is not installed" >&2; exit 1; }
-tsc src/js/tinyvm.ts --target es2020 --lib es2020,dom --module commonjs --outDir src/js
+tsc src/js/tinyvm.ts --target es2020 --lib es2020,dom --module commonjs --outDir "$JS"
node src/js/extract_lsp.js
-mkdir -p editors/vscode/server
-cp src/js/tinyvm.js src/js/layout.js src/js/lsp.json editors/vscode/server/
-# the wasm server runs when it is there; without clang the vm server is packed alone
+mkdir -p "$STAGE"
+cp "$JS/tinyvm.js" "$JS/layout.js" "$JS/lsp.json" "$STAGE/"
+# the wasm server runs when there is one; without clang the vm server is packed alone
if command -v clang >/dev/null && clang --print-targets | grep -q wasm32; then
- LSP_BUILD_DIR=build/lsp LSP_REUSE_BUILD=1 bash src/tools/mklspwasm.sh editors/vscode/server/lsp.wasm
+ LSP_BUILD_DIR=build/lsp LSP_REUSE_BUILD=1 bash src/tools/mklspwasm.sh "$STAGE/lsp.wasm"
else
- rm -f editors/vscode/server/lsp.wasm
+ rm -f "$STAGE/lsp.wasm"
echo "no clang with wasm32: packing the javascript vm server only" >&2
fi
+
+# vsce packs the extension directory, so the server has to sit inside it while
+# it runs. stage it, package, and leave the tree as it was.
+cleanup() { rm -rf "$PACKDIR"; }
+trap cleanup EXIT INT TERM
+rm -rf "$PACKDIR"
+mkdir -p "$PACKDIR"
+cp "$STAGE"/* "$PACKDIR"/
cd editors/vscode
if [ -n "${VSCE:-}" ]; then
"$VSCE" package --allow-missing-repository --skip-license -o "$OUT" >/dev/null
@@ -36,4 +52,4 @@ elif command -v vsce >/dev/null; then
else
npx -y @vscode/vsce package --allow-missing-repository --skip-license -o "$OUT" >/dev/null
fi
-echo "$OUT"
+echo "$OUT" \ No newline at end of file
diff --git a/tests/drivers/image_run.js b/tests/drivers/image_run.js
index 6d0b949..f657916 100644
--- a/tests/drivers/image_run.js
+++ b/tests/drivers/image_run.js
@@ -1,6 +1,6 @@
// run a generated image directly, avoiding compiler time in vm execution tests.
const fs = require('fs');
-const { TinyVM } = require('../../src/js/tinyvm.js');
+const { TinyVM } = require('../../build/js/tinyvm.js');
const { mapValues } = require('../../src/js/mapvalues.js');
const header = fs.readFileSync(process.argv[2], 'utf8');
const org = Number(header.match(/#define\s+GORG\s+(\d+)/)[1]);
diff --git a/tests/drivers/lsp_vm.js b/tests/drivers/lsp_vm.js
index e1f5d7a..2cb7abb 100644
--- a/tests/drivers/lsp_vm.js
+++ b/tests/drivers/lsp_vm.js
@@ -1,4 +1,4 @@
-// tests for the language server run by the javascript vm (src/js/tinyvm.js), through
+// tests for the language server run by the javascript vm (build/js/tinyvm.js), through
// the extension's own host (editors/vscode/client/vmproc.js): the same checks as
// tests/drivers/lsp_wasm.js. the vm starts at the image's heap and grows as the server asks.
// usage: node tests/drivers/lsp_vm.js path/to/server/dir (tinyvm.js, lsp.json, layout.js)
diff --git a/tests/test.sh b/tests/test.sh
index e7f8f7c..b80f548 100755
--- a/tests/test.sh
+++ b/tests/test.sh
@@ -45,15 +45,15 @@ ROOT=$T
# built here rather than inside a section: interp runs the program list on
# it, and the run-only and bare-metal sections read it as the reference.
-gcc -pthread -O2 -w -fwrapv -DJTYPE=int src/core/core.c src/core/io_linux.c -Isrc/core -o $T/zy || exit 1
-gcc -O2 -w -fwrapv src/tools/genmap.c -Isrc/core -o $T/genmap || exit 1
+gcc -pthread -O2 -w -fwrapv -DJTYPE=int src/core/core.c src/core/io_linux.c -Isrc/core -Ibuild/core -o $T/zy || exit 1
+gcc -O2 -w -fwrapv src/tools/genmap.c -Isrc/core -Ibuild/core -o $T/genmap || exit 1
# the c helper for tests/programs/structval.zc: structs by value, loaded with cload
mkdir -p build && gcc -shared -fPIC -w tests/data/sbv.c -o build/sbv.so || exit 1
selfc(){ (cat src/tools/build.zc; printf '`'; src) | $1 > $2; }
# bootstrap: zc0 (c) -> g0, g0 compiles compiler.zc -> g1, g1 compiles it -> g2
-gcc -O1 -w -fwrapv src/tools/zc0.c -Isrc/core -o $T/zc0 && gcc -O1 -w -fwrapv src/tools/mkgenome.c -Isrc/core -o $T/mkg || exit 1
+gcc -O1 -w -fwrapv src/tools/zc0.c -Isrc/core -Ibuild/core -o $T/zc0 && gcc -O1 -w -fwrapv src/tools/mkgenome.c -Isrc/core -Ibuild/core -o $T/mkg || exit 1
mkdir $T/s0 $T/s1
cp src/core/core.c src/core/io_linux.c src/core/memmap.h src/core/fops.h src/core/bops.h src/core/stack.h $T/s0/; cp src/core/core.c src/core/io_linux.c src/core/memmap.h src/core/fops.h src/core/bops.h src/core/stack.h $T/s1/
src | $T/zc0 > $T/s0/genome.h || exit 1
@@ -62,7 +62,7 @@ selfc $T/zy0 $T/g1.bin; $T/mkg < $T/g1.bin > $T/s1/genome.h
gcc -pthread -O2 -w -fwrapv -DJTYPE=int $T/s1/core.c $T/s1/io_linux.c -o $T/zy1
selfc $T/zy1 $T/g2.bin
cmp -s $T/g1.bin $T/g2.bin && chk 1 1 "fixpoint: the compiler compiles itself to the same $(($(wc -c < $T/g1.bin) / 8)) words" || chk 0 1 "fixpoint"
-cmp -s $T/s1/genome.h src/core/genome.h && chk 1 1 "genome.h is up to date" || chk 0 1 "genome.h is stale (cp the bootstrap output over it)"
+cmp -s $T/s1/genome.h build/core/genome.h && chk 1 1 "genome.h is up to date" || chk 0 1 "genome.h is stale (run make genome)"
chk "$($T/zc0 < tests/programs/zc0typed.zc | md5sum)" "$($T/zc0 < tests/programs/zc0plain.zc | md5sum)" "zc0 reads types and throws them away: typed and plain sources give one image"
for n in $SECS; do
@@ -199,7 +199,7 @@ ABC" "$l o3 lifts byte loads and stores"
}
s_interp() {
T=$ROOT/interp
- gcc -pthread -O2 -w -fwrapv -DJTYPE=int src/core/core.c src/core/io_linux.c -Isrc/core -o $T/zy
+ gcc -pthread -O2 -w -fwrapv -DJTYPE=int src/core/core.c src/core/io_linux.c -Isrc/core -Ibuild/core -o $T/zy
run $T/zy "interp"
python3 tests/drivers/array_methods_test.py $T/zy > $T/arrays.out 2>&1; r=$?
grep -v '^ok' $T/arrays.out
@@ -245,7 +245,7 @@ s_micro() {
selfc $T/zym $T/gm.bin
cmp -s $T/g1.bin $T/gm.bin && chk 1 1 "microcore self-compile matches" || chk 0 1 "microcore self-compile matches"
gcc -ffreestanding -w -c src/micro/micro.c -Isrc/core -Isrc/micro -o $T/micro.o && gcc -ffreestanding -w -c src/micro/port_stub.c -Isrc/core -Isrc/micro -o $T/stub.o && chk 1 1 "microcore and the stub port compile freestanding" || chk 0 1 "microcore and the stub port compile freestanding"
- gcc -pthread -O2 -w -fwrapv -DJTYPE=int -DZY_SOFTFLOAT -DZYINTERP src/core/core.c src/core/io_linux.c -Isrc/core -o $T/zysoft || exit 1
+ gcc -pthread -O2 -w -fwrapv -DJTYPE=int -DZY_SOFTFLOAT -DZYINTERP src/core/core.c src/core/io_linux.c -Isrc/core -Ibuild/core -o $T/zysoft || exit 1
chk "$($T/zysoft < tests/programs/float.zc)" "4.000000 4.500000 3.000000 2.500000 2.500000 0.001500 0.100000 -0.125000 inf -inf nan 1 1 1 0 0 3 -3 3.000000 -2.000000 2" "soft-float fallback matches the hardware line"
chk "$($T/zysoft < tests/programs/ftruth.zc)" "00111000110107" "soft-float negative zero is false"
chk "$($T/zysoft < tests/programs/fo3.zc)" "5997 5997 4.000000 nan 0 3.250000 1 0 0" "soft-float o3 float ops match"
@@ -255,7 +255,7 @@ s_micro() {
s_small() {
T=$ROOT/small
# smaller machines. addresses are literals, so each size is its own genome.
- gcc -O2 -w -fwrapv src/tools/genmap.c -Isrc/core -o $T/genmap || exit 1
+ gcc -O2 -w -fwrapv src/tools/genmap.c -Isrc/core -Ibuild/core -o $T/genmap || exit 1
$T/genmap --preset default --check >/dev/null && chk 1 1 "default map matches the checked-in sources" || chk 0 1 "default map matches the checked-in sources"
$T/genmap --preset small -o $T/small || exit 1
$T/genmap --mode compiler --name small --heap-lo 8192 --heap 20480 --types 8192 \
@@ -426,13 +426,13 @@ s_bare() {
s_jit() {
T=$ROOT/jit
if command -v aarch64-linux-gnu-gcc >/dev/null && command -v qemu-aarch64 >/dev/null; then
- aarch64-linux-gnu-gcc -pthread -O2 -w -fwrapv -DJTYPE=int -static src/core/core.c src/core/io_linux.c -Isrc/core -o $T/zyj || exit 1
+ aarch64-linux-gnu-gcc -pthread -O2 -w -fwrapv -DJTYPE=int -static src/core/core.c src/core/io_linux.c -Isrc/core -Ibuild/core -o $T/zyj || exit 1
printf '#!/bin/sh\nexec qemu-aarch64 %s "$@"\n' $T/zyj > $T/jit; chmod +x $T/jit
run $T/jit "jit"
chk "$(ZYTRACE=1 $T/jit < tests/programs/o3.zc 2>&1 | grep -c 'bytes of arm64')" "8" "jit compiles every o3 region to arm64"
selfc $T/jit $T/gj.bin; cmp -s $T/g1.bin $T/gj.bin && chk 1 1 "jit self-compile matches" || chk 0 1 "jit self-compile matches"
# native calls need a dynamic binary (a static one has no dlsym), run against the aarch64 libc
- if [ -d /usr/aarch64-linux-gnu/lib ] && aarch64-linux-gnu-gcc -pthread -O2 -w -fwrapv -DJTYPE=int src/core/core.c src/core/io_linux.c -Isrc/core -o $T/zyjd -ldl 2>/dev/null; then
+ if [ -d /usr/aarch64-linux-gnu/lib ] && aarch64-linux-gnu-gcc -pthread -O2 -w -fwrapv -DJTYPE=int src/core/core.c src/core/io_linux.c -Isrc/core -Ibuild/core -o $T/zyjd -ldl 2>/dev/null; then
chk "$(qemu-aarch64 -L /usr/aarch64-linux-gnu $T/zyjd < tests/programs/cabi.zc | md5sum)" "$(md5sum < tests/programs/cabi.expected)" "jit native calls and callbacks (extern, cfunc)"
chk "$(qemu-aarch64 -L /usr/aarch64-linux-gnu $T/zyjd < tests/programs/cabi_o3.zc | md5sum)" "$(md5sum < tests/programs/cabi_o3.expected)" "jit native calls from o3 code, stack arguments"
chk "$(qemu-aarch64 -L /usr/aarch64-linux-gnu $T/zyjd < tests/programs/cabi_sized.zc | md5sum)" "$(md5sum < tests/programs/cabi_sized.expected)" "jit native calls with f32 and the sized integers"
@@ -448,7 +448,7 @@ s_llvm() {
T=$ROOT/llvm
# llvm-config can exist without the headers and static libs (a runtime-only install), so the gate is a real build
llvm_ok=0
- if command -v llvm-config >/dev/null && gcc -pthread -O2 -w -fwrapv -DJTYPE=int -DZYLLVM $(llvm-config --cflags) src/core/core.c src/core/io_linux.c -Isrc/core -o $T/zyl $(llvm-config --ldflags --libs) 2>/dev/null; then llvm_ok=1; fi
+ if command -v llvm-config >/dev/null && gcc -pthread -O2 -w -fwrapv -DJTYPE=int -DZYLLVM $(llvm-config --cflags) src/core/core.c src/core/io_linux.c -Isrc/core -Ibuild/core -o $T/zyl $(llvm-config --ldflags --libs) 2>/dev/null; then llvm_ok=1; fi
if [ $llvm_ok = 1 ]; then
run $T/zyl "llvm"
chk "$(ZYTRACE=1 $T/zyl < tests/programs/o3.zc 2>&1 | grep -c 'compiled by llvm')" "8" "llvm compiles every o3 region"
@@ -574,7 +574,7 @@ s_lsp() {
else echo "skip lsp wasm tests (no clang with wasm32)"; fi
# the same server run by the javascript vm, the extension's fallback when wasm is not there.
# the vm starts at the image's heap and grows on the heap's request, so a long document is the test
- node src/js/extract_lsp.js >/dev/null && mkdir -p $T/vmserver && cp src/js/tinyvm.js src/js/layout.js src/js/lsp.json $T/vmserver/
+ node src/js/extract_lsp.js >/dev/null && mkdir -p $T/vmserver && cp build/js/tinyvm.js build/js/layout.js build/js/lsp.json $T/vmserver/
node tests/drivers/hover_surface_test.js --vm $T/vmserver > $T/hoversurfacevm.out 2>&1; r=$?
grep -v '^ok' $T/hoversurfacevm.out
chk $r 0 "lsp: embedded and asm hovers through the javascript host"
@@ -597,12 +597,12 @@ s_js() {
T=$ROOT/js
# the javascript vm, and the microcore as webassembly. both run the same genome
if command -v node >/dev/null; then
- chk "$(node -e "console.log(require('./src/js/genome.json').glen)")" "$(grep -m1 '#define GLEN' src/core/genome.h | awk '{print $3}')" "src/js/genome.json is up to date"
- chk "$(node src/js/tinyvm.js examples/hello.zc)" "hello, world!" "js vm: hello"
- chk "$(node src/js/tinyvm.js examples/fact.zc | tail -1)" "3628800" "js vm: factorial"
- chk "$(node src/js/tinyvm.js examples/primes.zc | tail -1)" "widest gap: 72, after 31397" "js vm: primes"
- chk "$(node src/js/tinyvm.js tests/programs/growone.zc)" "12 1" "js vm: a block past the initial heap grows the machine"
- chk "$(node src/js/tinyvm.js tests/programs/replace_owner.zc)" "$(cat tests/programs/replace_owner.expected)" "js vm: replacement ownership and cleanup"
+ chk "$(node -e "console.log(require('./build/js/genome.json').glen)")" "$(grep -m1 '#define GLEN' build/core/genome.h | awk '{print $3}')" "build/js/genome.json is up to date"
+ chk "$(node build/js/tinyvm.js examples/hello.zc)" "hello, world!" "js vm: hello"
+ chk "$(node build/js/tinyvm.js examples/fact.zc | tail -1)" "3628800" "js vm: factorial"
+ chk "$(node build/js/tinyvm.js examples/primes.zc | tail -1)" "widest gap: 72, after 31397" "js vm: primes"
+ chk "$(node build/js/tinyvm.js tests/programs/growone.zc)" "12 1" "js vm: a block past the initial heap grows the machine"
+ chk "$(node build/js/tinyvm.js tests/programs/replace_owner.zc)" "$(cat tests/programs/replace_owner.expected)" "js vm: replacement ownership and cleanup"
if command -v clang >/dev/null && command -v wasm-ld >/dev/null && clang --print-targets 2>/dev/null | grep -q wasm32; then
bash src/web/build.sh $T/zc.wasm >/dev/null && node tests/drivers/wasm_test.js $T/zc.wasm > $T/wasm.out 2>&1; r=$?
grep -v '^ok' $T/wasm.out
@@ -633,7 +633,7 @@ s_make() {
# every block in it is one of those examples (tests/drivers/learn.py)
s_learn() {
T=$ROOT/learn
- gcc -pthread -O2 -w -fwrapv -DJTYPE=int src/core/core.c src/core/io_linux.c -Isrc/core -o $T/zy
+ gcc -pthread -O2 -w -fwrapv -DJTYPE=int src/core/core.c src/core/io_linux.c -Isrc/core -Ibuild/core -o $T/zy
# learn.py prints its own ok and FAIL lines, which the tally below counts
python3 tests/drivers/learn.py $T/zy; true
}
diff --git a/tests/test_win.ps1 b/tests/test_win.ps1
index 0a18728..0edc86c 100644
--- a/tests/test_win.ps1
+++ b/tests/test_win.ps1
@@ -66,7 +66,7 @@ try {
$isFixpoint = [System.Linq.Enumerable]::SequenceEqual($g1, $g2)
Report-Result $isFixpoint "Fixpoint: compiler compiles itself to identical $($g1.Length / 8) words"
- $ghRepo = (Get-FileHash "src\core\genome.h").Hash
+ $ghRepo = (Get-FileHash "build\core\genome.h").Hash
$ghGen = (Get-FileHash "$tempDir\s1\genome.h").Hash
Report-Result ($ghRepo -eq $ghGen) "genome.h is up to date"
@@ -226,20 +226,20 @@ try {
Write-Host " [SKIP] Node.js not detected in PATH, skipping lsp protocol tests." -ForegroundColor DarkYellow
}
- # --- 8. JavaScript / TypeScript vm runtime (src/js/tinyvm.js) ---
- Write-Host "`n=== 8. JavaScript VM Runtime (node src/js/tinyvm.js) ===" -ForegroundColor Yellow
+ # --- 8. JavaScript / TypeScript vm runtime (build/js/tinyvm.js) ---
+ Write-Host "`n=== 8. JavaScript VM Runtime (node build/js/tinyvm.js) ===" -ForegroundColor Yellow
$nodeCmd = Get-Command node -ErrorAction SilentlyContinue
if ($nodeCmd) {
- $jsHello = (node src\js\tinyvm.js examples\hello.zc 2>&1) -join "`n"
+ $jsHello = (node build\js\tinyvm.js examples\hello.zc 2>&1) -join "`n"
Report-Result ($jsHello.Trim() -eq "hello, world!") "JS VM: hello.zc"
- $jsFact = (node src\js\tinyvm.js examples\fact.zc 2>&1) -join "`n"
+ $jsFact = (node build\js\tinyvm.js examples\fact.zc 2>&1) -join "`n"
Report-Result ($jsFact.Contains("3628800")) "JS VM: fact.zc"
- $jsPrimes = (node src\js\tinyvm.js examples\primes.zc 2>&1) -join "`n"
+ $jsPrimes = (node build\js\tinyvm.js examples\primes.zc 2>&1) -join "`n"
Report-Result ($jsPrimes.Contains("widest gap: 72")) "JS VM: primes.zc"
- $jsMandel = (node src\js\tinyvm.js examples\mandel.zc 2>&1) -join "`n"
+ $jsMandel = (node build\js\tinyvm.js examples\mandel.zc 2>&1) -join "`n"
Report-Result ($jsMandel.Contains("*") -or $jsMandel.Contains(".")) "JS VM: mandel.zc (custom fmul enhancement)"
} else {
Write-Host " [SKIP] Node.js not detected in PATH, skipping JS tests." -ForegroundColor DarkYellow
diff --git a/tinyvm.bat b/tinyvm.bat
index 4a3f725..9a457eb 100755
--- a/tinyvm.bat
+++ b/tinyvm.bat
@@ -106,7 +106,7 @@ 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 src/js/tinyvm.js)
+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)
diff --git a/tinyvm.sh b/tinyvm.sh
index 12e3a15..7c5ce39 100755
--- a/tinyvm.sh
+++ b/tinyvm.sh
@@ -50,7 +50,7 @@ run_file() {
run) exe=bin/zy ;;
run-micro) exe=bin/zym ;;
lsp) exe=bin/zclsp ;;
- js) command -v node >/dev/null || { echo 'node.js is required.' >&2; return 1; }; make js || return; node src/js/tinyvm.js "$input"; return ;;
+ js) command -v node >/dev/null || { echo 'node.js is required.' >&2; return 1; }; make js || return; node build/js/tinyvm.js "$input"; return ;;
esac
make "$exe" || return
"$exe" < "$input"