Commit | Line | Data |
---|---|---|
8e198a08 MB |
1 | ;;;# Introduction |
2 | ;;; | |
3 | ;;; ParenScript is a simple language that looks a lot like Lisp, but | |
4 | ;;; actually is JavaScript in disguise. Actually, it is JavaScript | |
5 | ;;; embedded in a host Lisp. This way, JavaScript programs can be | |
6 | ;;; seamlessly integrated in a Lisp web application. The programmer | |
7 | ;;; doesn't have to resort to a different syntax, and JavaScript code | |
8 | ;;; can easily be generated without having to resort to complicated | |
9 | ;;; string generation or `FORMAT' expressions. | |
10 | ;;; | |
11 | ;;; An example is worth more than a thousand words. The following Lisp | |
12 | ;;; expression is a call to the ParenScript "compiler". The | |
13 | ;;; ParenScript "compiler" transforms the expression in ParenScript | |
14 | ;;; into an equivalent, human-readable expression in JavaScript. | |
15 | ||
16 | (js | |
17 | (defun foobar (a b) | |
18 | (return (+ a b)))) | |
19 | ||
20 | ;;; The resulting javascript is: | |
21 | ||
22 | function foobar(a, b) { | |
23 | return a + b; | |
24 | } | |
25 | ||
26 | ;;; Great care has been given to the indentation and overall | |
27 | ;;; readability of the generated JavaScript code. | |
28 | ||
29 | ;;;# Features | |
30 | ;;; | |
31 | ;;; ParenScript supports all the statements and expressions defined by | |
32 | ;;; the EcmaScript 262 standard. Lisp symbols are converted to | |
33 | ;;; camelcase, javascript-compliant syntax. This idea is taken from | |
34 | ;;; Linj by Antonio Menezes Leitao. Here are a few examples of Lisp | |
35 | ;;; symbol to JavaScript name conversion: | |
36 | ||
37 | (js-to-string 'foobar) => "foobar" | |
38 | (js-to-string 'foo-bar) => "fooBar" | |
39 | (js-to-string 'foo-b-@-r) => "fooBAtR" | |
40 | (js-to-string 'foo-b@r) => "fooBatr" | |
41 | (js-to-string '*array) => "Array" | |
42 | (js-to-string '*math.floor) => "Math.floor" | |
43 | ||
44 | ;;; It also supports additional iteration constructs, relieving the | |
45 | ;;; programmer of the burden of iterating over arrays. | |
46 | ;;; `for' loops can be written using the customary `DO' syntax. | |
47 | ||
48 | (js | |
49 | (do ((i 0 (incf i)) | |
50 | (j (aref arr i) (aref arr i))) | |
51 | ((>= i 10)) | |
52 | (alert (+ "i is " i " and j is " j)))) | |
53 | ||
54 | ; compiles to | |
55 | ||
56 | for (var i = 0, j = arr[i]; i < 10; i = ++i, j = arr[i]) { | |
57 | alert("i is " + i + " and j is " + j); | |
58 | } | |
59 | ||
60 | ;;; ParenScript uses the Lisp reader, allowing for reader macros. It | |
61 | ;;; also comes with its own macro environment, allowing host macros | |
62 | ;;; and ParenScript to coexist without interfering with each other. | |
63 | ;;; Furthermore, ParenScript uses its own compiler macro system, | |
64 | ;;; allowing for an even further customization of the generation of | |
65 | ;;; JavaScript. For example, the `1+' construct is implemented using a | |
66 | ;;; ParenScript macro: | |
67 | ||
68 | (defjsmacro 1+ (form) | |
69 | `(+ ,form 1)) | |
70 | ||
71 | ;;; ParenScript allows the creation of JavaScript objects in a Lispy | |
72 | ;;; way, using keyword arguments. | |
73 | ||
74 | (js | |
75 | (create :foo "foo" | |
76 | :bla "bla")) | |
77 | ||
78 | ; compiles to | |
79 | ||
80 | { foo : "foo", | |
81 | bla : "bla" } | |
82 | ||
83 | ;;; ParenScript features a HTML generator. Using the same syntax as | |
84 | ;;; the `HTMLGEN' package of Franz, Inc., it can generate JavaScript | |
85 | ;;; string expressions. This allows for a clean integration of HTML in | |
86 | ;;; ParenScript code, instead of writing the tedious and error-prone | |
87 | ;;; string generation code generally found in JavaScript. | |
88 | ||
89 | (js | |
90 | (defun add-div (name href link-text) | |
91 | (document.write | |
92 | (html ((:div :id name) | |
93 | "The link is: " | |
94 | ((:a :href href) link-text)))))) | |
95 | ||
96 | ; compiles to | |
97 | ||
98 | function addDiv(name, href, linkText) { | |
99 | document.write("<div id=\"" + name + "\">The link is: <a href=\"" | |
100 | + href + "\">" | |
101 | + linkText + "</a></div>"); | |
102 | } | |
103 | ||
104 | ;;; In order to have a complete web application framework available in | |
105 | ;;; Lisp, ParenScript also provides a sexp-based syntax for CSS | |
106 | ;;; files. Thus, a complete web application featuring HTML, CSS and | |
107 | ;;; JavaScript documents can be generated using Lisp syntax, allowing | |
108 | ;;; the programmer to use Lisp macros to factor out the redundancies | |
109 | ;;; and complexities of Web syntax. For example, to generate a CSS | |
110 | ;;; inline node in a HTML document: | |
111 | ||
112 | (html-stream *standard-output* | |
113 | (html | |
114 | (:html | |
115 | (:head | |
116 | (css (* :border "1px solid black") | |
117 | (div.bl0rg :font-family "serif") | |
118 | (("a:active" "a:hoover") :color "black" :size "200%")))))) | |
119 | ||
120 | ; which produces | |
121 | ||
122 | <html><head><style type="text/css"> | |
123 | <!-- | |
124 | * { | |
125 | border:1px solid black; | |
126 | } | |
127 | ||
128 | div.bl0rg { | |
129 | font-family:serif; | |
130 | } | |
131 | ||
132 | a:active,a:hoover { | |
133 | color:black; | |
134 | size:200%; | |
135 | } | |
136 | ||
137 | --> | |
138 | </style> | |
139 | </head> | |
140 | </html> | |
141 | ||
142 | ;;;# Getting ParenScript | |
143 | ;;; | |
144 | ;;; ParenScript can be obtained from the BKNR subversion repository at | |
145 | ||
146 | svn://bknr.net/trunk/bknr/src/js | |
147 | ||
148 | ;;; ParenScript does not depend on any part of BKNR though. You can | |
149 | ;;; download snapshots of ParenScript at the webpage | |
150 | ||
151 | http://bknr.net/parenscript | |
152 | ||
153 | ;;; or using asdf-install. | |
154 | ||
155 | (asdf-install:install 'parenscript) | |
156 | ||
157 | ;;; | |
158 | ;;; After downloading the ParenScript sourcecode, set up the ASDF | |
159 | ;;; central registry by adding a symlink to "parenscript.asd". Then | |
160 | ;;; use ASDF to load ParenScript. You may want to edit the ASDF file | |
161 | ;;; to remove the dependency on the Allegroserve HTMLGEN facility. | |
162 | ||
163 | (asdf:oos 'asdf:load-op :parenscript) | |
164 | ||
165 | ;;; ParenScript was written by Manuel Odendahl. He can be reached at | |
166 | ||
167 | manuel@bknr.net | |
168 |