Alles aangepast.

This commit is contained in:
2026-06-08 12:55:08 +02:00
parent a9610e6e0c
commit 823130e3ac
24 changed files with 418 additions and 2621 deletions
+66 -35
View File
@@ -1,53 +1,84 @@
#lang scribble/manual
@(require (for-label racket/base
js-maker))
@(require (for-label racket/base js-maker))
@title{js-maker}
@author{Hans Dijkema}
@defmodule[js-maker]
@racketmodname[js-maker] provides a deliberately small syntax-driven macro for
making JavaScript strings from a limited Racket-like surface syntax. This is a
clean js-maker 3 restart based on the compact @filepath{js-transform.rkt}
implementation.
@emph{js-maker} is a deliberately small syntax-driven JavaScript string maker.
It provides one public macro, @racket[js]. The helper machinery used to render
subexpressions is private to the package.
@section{Public API}
@defform[(js form ...)]{
Generates JavaScript statements for each @racket[form] and concatenates them.
The generated JavaScript is returned as a string.
Produces a JavaScript string for the supplied forms. Each top-level form is
rendered as a JavaScript statement. The macro is intended for small generated
snippets, demos, and controlled code generation; it is not a complete Racket to
JavaScript compiler.
Examples:
@racketblock[
(js
(define (sum-to n)
(let loop ([i 0] [acc 0])
(if (> i n)
(return acc)
(loop (+ i 1) (+ acc i))))))]
}
@defform[(js1 form)]{
Generates JavaScript for a single expression or syntactic form and returns it as
a string. Use this when you want the expression-level generator directly.
@racketblock[
(js1 (+ 1 2))]
(js (+ 1 2))
(js (define answer 42))
(js (define (square x)
(return (* x x))))
]
}
@section{Supported core forms}
The compact branch supports identifiers, quoted data, primitive literals,
function calls, infix arithmetic and comparison operators, @racket[if],
@racket[begin], @racket[return], @racket[set!], @racket[lambda],
@racket[define], ordinary @racket[let], @racket[let*], and named
@racket[let].
The compact js-maker 3 implementation supports:
Ordinary @racket[let] keeps Racket's parallel binding semantics. All right-hand
sides are generated before the bound names are introduced, and the actual
JavaScript bindings are placed in an inner block so JavaScript temporal dead zone
rules cannot accidentally shadow the initializers.
@itemlist[
@item{@racket[define] for values and functions.}
@item{@racket[lambda] and @racket[lambda]-style generated JavaScript functions.}
@item{@racket[if], @racket[begin], @racket[set!], and explicit @racket[return].}
@item{Ordinary @racket[let] with parallel binding semantics.}
@item{@racket[let*] with sequential binding semantics.}
@item{Named @racket[let] in tail-recursive loop style.}
@item{Common infix operators such as @racket[+], @racket[-], @racket[*],
@racket[/], comparisons, @racket[and], @racket[or], and @racket[not].}
@item{@racket[list], @racket[cons], @racket[send], @racket[js-dot], and
@racket[new].}
]
Named @racket[let] is compiled to a JavaScript @tt{while (true)} loop. A tail
call to the loop name is rewritten to parallel assignment of the loop variables
followed by @tt{continue}. This keeps the important loop semantics without
reintroducing the large js-maker 2 implementation.
@section{Let semantics}
Ordinary @racket[let] evaluates all right-hand sides before introducing the new
bindings. js-maker preserves that behavior by emitting temporary JavaScript
constants and then opening a nested block for the real @tt{let} bindings.
This avoids JavaScript temporal-dead-zone shadowing when a bound name is also
used by a right-hand side.
@racketblock[
(js (define (ordinary-let x)
(let ([x 1] [y x])
(return y))))
]
The generated JavaScript returns the original argument as the value of
@tt{y}, matching Racket's ordinary @racket[let] semantics.
@section{Named let}
Named @racket[let] is emitted as a @tt{while (true)} loop. A tail call to the
loop name is translated to parallel update assignments followed by
@tt{continue}. The intended style is statement-oriented and uses explicit
@racket[return] for terminating branches.
@racketblock[
(js (define (sum-to n)
(let loop ([i 0] [acc 0])
(if (> i n)
(return acc)
(loop (+ i 1) (+ acc i))))))
]
@section{Package layout}
The package includes small demos under @filepath{demo/} and a regression suite
under @filepath{testing/}. The public API remains just @racket[js].