Files
gemigreerd-js-maker/scrbl/js-maker.scrbl
T
2026-06-08 12:55:08 +02:00

85 lines
2.6 KiB
Racket

#lang scribble/manual
@(require (for-label racket/base js-maker))
@title{js-maker}
@author{Hans Dijkema}
@defmodule[js-maker]
@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 ...)]{
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 (+ 1 2))
(js (define answer 42))
(js (define (square x)
(return (* x x))))
]
}
@section{Supported core forms}
The compact js-maker 3 implementation supports:
@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].}
]
@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].