54 lines
1.8 KiB
Racket
54 lines
1.8 KiB
Racket
#lang scribble/manual
|
|
|
|
@(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.
|
|
|
|
@defform[(js form ...)]{
|
|
Generates JavaScript statements for each @racket[form] and concatenates them.
|
|
The generated JavaScript is returned as a string.
|
|
|
|
@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))]
|
|
}
|
|
|
|
@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].
|
|
|
|
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.
|
|
|
|
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.
|