This commit is contained in:
2026-06-08 13:21:57 +02:00
parent 823130e3ac
commit 8bee76328b
23 changed files with 734 additions and 382 deletions
+59 -6
View File
@@ -1,13 +1,66 @@
# js-maker
js-maker is a deliberately small syntax-driven Racket-to-JavaScript string
maker. The public API is intentionally one macro:
`js-maker` is a deliberately small Racket macro for generating JavaScript text
from a compact Racket/Scheme-like surface syntax.
The public API is intentionally small:
```racket
(require js-maker)
(js (define (square x) (return (* x x))))
(js form ...)
```
js-maker 3 keeps the implementation compact and supports ordinary `let`,
`let*`, and tail-recursive named `let` loops while preserving Racket binding
semantics. Demos are in `demo/`; regression tests are in `testing/`.
There is no public `js1` and no `js/expression`. Expression-oriented examples
should be written as normal JavaScript-producing programs, usually by placing an
explicit `(return ...)` in a generated function.
## Supported core forms
The js-maker 3 restart supports the following core forms:
- `(define (name arg ...) body ...)`
- `(define name expr)`
- `(lambda (arg ...) body ...)` and `(λ (arg ...) body ...)`
- `(if condition then else)`
- `(begin body ...)`
- `(return expr)`
- `(set! target expr)`
- ordinary `let` with parallel binding semantics
- `let*` with sequential binding semantics
- named `let`, compiled to `while (true)` with parallel loop-variable updates
- quote/eval for simple datum insertion
- calls, infix arithmetic/comparison operators, `and`, `or`, `not`
- `(send obj method arg ...)`
- `(new Class arg ...)`
- `(js-dot obj field ...)` / `(dot obj field ...)`
- `(js-ref obj key ...)` for JavaScript bracket/index access
- `(list ...)` and `(cons a b)`
`js-ref` is a DSL form inside `(js ...)`, not a separately exported binding.
For example, `(js-ref xs i)` generates `xs[i]`, `(js-ref obj "name")`
generates `obj["name"]`, and `(set! (js-ref xs i) value)` generates an
indexed assignment.
Named `let` is statement-oriented. A tail call to the loop name continues the
loop. The branch that leaves the loop should use an explicit `(return ...)`.
## Running tests
From the package root:
```sh
raco test -p js-maker
```
If Node is available, several generated JavaScript programs are executed. If no
Node executable is found, those runtime checks are skipped and the string-level
checks still run.
## What was removed from the old test set
The previous larger branch contained tests and demos for a broader language and
runtime shim. Those are not part of the compact js-maker 3 restart. The old
hash, regexp, `with-handlers`, `for/list`, `for/fold`, `while`, `when`, `cond`,
`case`, object/class/destructuring and runtime helper tests were removed or
replaced by tests for the supported core forms above.