#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].