4 ;;; ParenScript is a simple language that looks a lot like Lisp, but
5 ;;; actually is JavaScript in disguise. Actually, it is JavaScript
6 ;;; embedded in a host Lisp. This way, JavaScript programs can be
7 ;;; seamlessly integrated in a Lisp web application. The programmer
8 ;;; doesn't have to resort to a different syntax, and JavaScript code
9 ;;; can easily be generated without having to resort to complicated
10 ;;; string generation or `FORMAT' expressions.
12 ;;; An example is worth more than a thousand words. The following Lisp
13 ;;; expression is a call to the ParenScript "compiler". The
14 ;;; ParenScript "compiler" transforms the expression in ParenScript
15 ;;; into an equivalent, human-readable expression in JavaScript.
21 ;;; The resulting javascript is:
23 function foobar(a, b) {
27 ;;; Great care has been given to the indentation and overall
28 ;;; readability of the generated JavaScript code.
32 ;;; ParenScript supports all the statements and expressions defined by
33 ;;; the EcmaScript 262 standard. Lisp symbols are converted to
34 ;;; camelcase, javascript-compliant syntax. This idea is taken from
35 ;;; Linj by Antonio Menezes Leitao. Here are a few examples of Lisp
36 ;;; symbol to JavaScript name conversion:
38 (js-to-string 'foobar
) => "foobar"
39 (js-to-string 'foo-bar
) => "fooBar"
40 (js-to-string 'foo-b-
@-r
) => "fooBAtR"
41 (js-to-string 'foo-b
@r
) => "fooBatr"
42 (js-to-string '*array
) => "Array"
43 (js-to-string '*math.floor
) => "Math.floor"
45 ;;; It also supports additional iteration constructs, relieving the
46 ;;; programmer of the burden of iterating over arrays.
47 ;;; `for' loops can be written using the customary `DO' syntax.
51 (j (aref arr i
) (aref arr i
)))
53 (alert (+ "i is " i
" and j is " j
))))
57 for (var i = 0, j = arr[i]; i < 10; i = ++i, j = arr[i]) {
58 alert('i is ' + i + ' and j is ' + j);
61 ;;; ParenScript uses the Lisp reader, allowing for reader macros. It
62 ;;; also comes with its own macro environment, allowing host Lisp
63 ;;; macros and ParenScript macros to coexist without interfering with
64 ;;; each other. For example, the `1+' construct is implemented using
65 ;;; a ParenScript macro:
70 ;;; ParenScript allows the creation of JavaScript objects in a Lispy
71 ;;; way, using keyword arguments.
82 ;;; ParenScript features a HTML generator. Using the same syntax as
83 ;;; the HTMLGEN package of Franz, Inc., it can generate JavaScript
84 ;;; string expressions. This allows for a clean integration of HTML in
85 ;;; ParenScript code, instead of writing the tedious and error-prone
86 ;;; string generation code generally found in JavaScript.
89 (defun add-div (name href link-text
)
91 (ps-html ((:div
:id name
)
93 ((:a
:href href
) link-text
))))))
97 function addDiv(name, href, linkText) {
98 document.write('<div id=\"' + name + '\">The link is: <a href=\"'
100 + linkText + '</a></div>');
103 ;;; In order to have a complete web application framework available in
104 ;;; Lisp, ParenScript also provides a sexp-based syntax for CSS
105 ;;; stylesheets. Thus, a complete web application featuring HTML, CSS
106 ;;; and JavaScript documents can be generated using Lisp syntax,
107 ;;; allowing the programmer to use Lisp macros to factor out the
108 ;;; redundancies and complexities of Web syntax. For example, to
109 ;;; generate a CSS inline node in a HTML document using the
110 ;;; AllegroServe HTMLGEN library:
112 (html-stream *standard-output
*
116 (css (* :border
"1px solid black")
117 (div.bl0rg
:font-family
"serif")
118 (("a:active" "a:hoover") :color
"black" :size
"200%"))))))
122 <html
><head
><style type
="text/css">
125 border
:1px solid black
;