Made CASE treat symbol literals as strings, behave more like CL
[parenscript.git] / docs / reference.html
blob51a4eeda32919313cc21a2ea2eccf162b0b8b409
1 <!DOCTYPE html>
3 <html lang="en">
5 <head>
6 <meta charset="utf-8">
7 <meta name="viewport"
8 content="width=device-width, initial-scale=1"
11 <title>Parenscript Reference Manual</title>
13 <style type="text/css">
14 body {
15 max-width: 70ex;
16 margin: auto;
18 dl {
19 margin-left: 2em;
21 dt {
22 margin-top: 0.5ex;
23 border: 1px solid #d5d5d5;
24 background: #f9f9f9;
26 dd {
27 margin-top: 0.5ex;
29 p {
30 margin-left: 1em;
32 pre {
33 margin: 0;
35 samp {
36 color: #60a;
37 font-weight: bolder;
39 </style>
40 </head>
42 <body>
43 <h1 style="text-align:center;">Parenscript Reference Manual</h1>
45 <h2>Table of Contents</h2>
47 <ol>
48 <li><a href="#section-notation">Notation used in this manual</a></li>
49 <li><a href="#section-ps-compiler">The Parenscript compiler</a></li>
50 <li><a href="#section-symbolconv">Symbol conversion</a></li>
51 <li><a href="#section-namespace">The Parenscript namespace system</a>
52 <ul>
53 <li><a href="#section-obfuscation">Identifier obfuscation</a></li>
54 <li><a href="#section-minification">Minification</a></li>
55 </ul>
56 </li>
57 <li><a href="#reserved-symbols">Reserved symbols</a></li>
58 <li><a href="#section-statements-expressions">Statements, expressions, and return</a></li>
59 <li><a href="#section-types">Types and type predicates</a></li>
60 <li><a href="#section-literals">Literals</a>
61 <ul>
62 <li><a href="#ssection-numbers">Numbers</a></li>
63 <li><a href="#ssection-strings-chars">Strings and characters</a></li>
64 <li><a href="#ssection-regex">Regular expressions</a></li>
65 <li><a href="#ssection-booleans">Booleans and undefined</a></li>
66 </ul>
67 </li>
68 <li><a href="#section-objects">Objects</a></li>
69 <li><a href="#section-arrays">Arrays</a></li>
70 <li><a href="#section-arithmetic">Arithmetic and boolean operators</a></li>
71 <li><a href="#section-math">Mathematical functions and constants</a></li>
72 <li><a href="#section-blocks">Blocks</a></li>
73 <li><a href="#section-functions">Functions and multiple values</a></li>
74 <li><a href="#section-control-transfer">Control transfer and exceptions</a></li>
75 <li><a href="#section-conditionals">Conditionals</a></li>
76 <li><a href="#section-variables">Variable binding and declaration</a></li>
77 <li><a href="#section-assignment">Assignment</a></li>
78 <li><a href="#section-iteration">Iteration</a></li>
79 <li><a href="#section-macros">Macros</a>
80 <ul>
81 <li><a href="#ssection-defining-macros">Defining macros</a></li>
82 <li><a href="#ssection-symbol-macros">Symbol macros</a></li>
83 <li><a href="#ssection-gensym">Gensym</a></li>
84 </ul>
85 </li>
86 <li><a href="#section-utilities">Utilities</a>
87 <ul>
88 <li><a href="#ssection-dom">DOM</a></li>
89 <li><a href="#ssection-html-gen">HTML generation</a></li>
90 </ul>
91 </li>
92 <li><a href="#section-runtime-library">Run-time library</a></li>
93 <li><a href="#section-slime-integration">SLIME integration</a></li>
94 </ol>
96 <h2 id="section-notation">Notation used in this manual</h2>
97 <ul>
98 <li><code>Lisp form</code></li>
99 <li><var>Lisp variable</var></li>
100 <li>(<code>lisp-function-name</code> <var>lisp-function-argument</var>)</li>
101 <li><samp>JavaScript code</samp></li>
102 <li><dl><dt>Term</dt><dd>Definition of term</dd></dl></li>
103 <li><dl><dt><code>(Lisp forms)</code></dt><dd><samp>Lisp forms compiled to JavaScript;</samp></dd></dl></li>
104 </ul>
106 <h2 id="section-ps-compiler">The Parenscript compiler</h2>
108 <ul>
109 <li>(<code id="ps">PS</code> &amp;body <var>body</var>)</li>
110 <li>(<code id="ps-to-stream">PS-TO-STREAM</code> <var>stream</var> &amp;body <var>body</var>)</li>
111 <li>(<code id="ps*">PS*</code> &amp;rest <var>body</var>)</li>
112 <li>(<code id="ps-doc">PS-DOC</code> &amp;body <var>body</var>)</li>
113 <li>(<code id="ps-doc*">PS-DOC*</code> &amp;body <var>body</var>)</li>
114 <li>(<code id="ps-inline">PS-INLINE</code> <var>form</var> &amp;optional <var>*JS-STRING-DELIMITER*</var>)</li>
115 <li>(<code id="ps-inline*">PS-INLINE*</code> <var>form</var> &amp;optional <var>*JS-STRING-DELIMITER*</var>)</li>
116 <li>(<code id="ps-compile-stream">PS-COMPILE-STREAM</code> <var>stream</var>)</li>
117 <li>(<code id="ps-compile-file">PS-COMPILE-FILE</code> <var>file</var>)</li>
118 <li>(<code id="lisp">LISP</code> <var>lisp-form</var>)</li>
119 <li>(<code id="symbol-to-js-string">SYMBOL-TO-JS-STRING</code> <var>symbol</var>)</li>
121 <li><var id="*js-target-version*">*JS-TARGET-VERSION*</var></li>
122 <li><var id="*parenscript-stream*">*PARENSCRIPT-STREAM*</var></li>
123 <li><var id="*js-string-delimiter*">*JS-STRING-DELIMITER*</var></li>
124 <li><var id="*js-inline-string-delimiter*">*JS-INLINE-STRING-DELIMITER*</var></li>
125 <li><var id="*ps-read-function*">*PS-READ-FUNCTION*</var></li>
126 <li><var id="*version*">*VERSION*</var></li>
127 <li><var id="*defined-operators*">*DEFINED-OPERATORS*</var></li>
128 </ul>
130 <dl>
131 <dt><var>body</var></dt> <dd>implicit <code>PROGN</code></dd>
132 </dl>
134 <p>The difference between the regular and <code>*</code> versions
135 of the Parenscript compiler forms is roughly the difference
136 between <code>COMPILE</code>
137 and <code>EVAL</code>. The <code>*</code> forms are functions
138 that do all compilation when they are evaluated, while the
139 regular forms are macros that do almost all (except for the use
140 of the <code>LISP</code> special form, see below) compilation at
141 macro-expansion time.</p>
143 <p><code>PS</code> and <code>PS*</code> are the main interfaces to
144 the Parenscript compiler. They come with <code>PS-DOC</code>
145 and <code>PS-DOC*</code> counterparts which compile the given
146 code
147 with <a href="#*ps-gensym-counter*"><var>*PS-GENSYM-COUNTER*</var></a>
148 bound to <kbd>0</kbd>, and are useful for writing automated
149 tests.</p>
151 <p>By default, Parenscript writes output to a string. You can
152 output directly to a stream in one of two ways: either by
153 using <code>PS-TO-STREAM</code> instead of <code>PS</code>, or by
154 binding <var>*PARENSCRIPT-STREAM*</var> before
155 calling <code>PS*</code>.</p>
157 <p><code>PS-INLINE</code> and <code>PS-INLINE*</code> take a single
158 Parenscript form and output a string starting
159 with <samp>javascript:</samp> that can be used in HTML node
160 attributes. As well, they provide an argument to bind the value of
161 <var>*JS-STRING-DELIMITER*</var> to control the value of the
162 JavaScript string escape character to be compatible with
163 whatever the HTML generation mechanism is used (for example, if
164 HTML strings are delimited using <code>#\'</code>,
165 using <code>#\&quot;</code> will avoid conflicts without
166 requiring the output JavaScript code to be escaped). By default
167 the value is taken
168 from <var>*JS-INLINE-STRING-DELIMITER*</var>.</p>
170 <p>Parenscript code can be compiled from a stream or file
171 via <code>PS-COMPILE-STREAM</code>
172 and <code>PS-COMPILE-FILE</code>, respectively. The special
173 variable <var>*PS-READ-FUNCTION*</var> is bound to the function
174 used to read the forms from the file/stream (<code>READ</code> by
175 default), and can be used to provide completely customizable
176 syntax for Parenscript files.</p>
178 <p>Parenscript can also call out to arbitrary Common Lisp code at
179 <em>output time</em> (that is, every time an expression containing
180 a call to the Parenscript compiler is evaluated, compared
181 to <em>compile time</em>, where the effect is accomplished using
182 macros) using the special form <code>LISP</code>. The form
183 provided to <code>LISP</code> is evaluated, and its result is
184 compiled as though it were Parenscript code. For <code>PS</code>
185 and <code>PS-INLINE</code>, the Parenscript output code is
186 generated at macro-expansion time, and the <code>LISP</code>
187 statements are inserted inline into the output and have access
188 to the enclosing Common Lisp lexical
189 environment. <code>PS*</code> and <code>PS1*</code> evaluate the
190 <code>LISP</code> forms using <code>EVAL</code>, providing them
191 access to the current dynamic environment only
192 (using <code>LISP</code> when calling the <code>*</code> forms
193 is not strictly necessary, as the values can be inserted inline
194 into code).</p>
196 <p><var>*JS-TARGET-VERSION*</var> (<kbd>1.3</kbd> by default)
197 controls which version of JavaScript that Parenscript
198 targets. For newer versions of JS, some Parenscript special
199 forms may compile to more concise and/or efficient expressions
200 that are not present in earlier versions of JavaScript.</p>
202 <p><code>SYMBOL-TO-JS-STRING</code> is the Parenscript function
203 responsible for translating Common Lisp symbols to JavaScript
204 identifiers (see the section
205 on <a href="#section-symbolconv">symbol conversion</a> for the
206 translation rules). It is helpful for writing libraries or other
207 pieces of code that will interface with Parenscript-generated
208 JavaScript.</p>
210 <p>Newer versions of Parenscript may implement Common Lisp special
211 forms, functions or macros that were left unimplemented by earlier
212 versions. This can cause problems if your code provides
213 implementations for those forms itself. To help deal with
214 this, <var>*DEFINED-OPERATORS*</var> provides a list of special
215 forms, macros, and symbol macros defined by Parenscript
216 itself. <var>*VERSION*</var> is bound to the current release
217 version number of Parenscript.</p>
219 <h2 id="section-symbolconv">Symbol conversion</h2>
221 <p>Parenscript supports output for both case-sensitive and
222 case-insensitive symbols. By default the Lisp reader up-cases all
223 symbols. By setting <code>readtable-case</code>
224 to <a href="http://www.lispworks.com/documentation/lw50/CLHS/Body/23_ab.htm"><code>:invert</code></a>
225 (you can use
226 the <a href="https://common-lisp.net/project/named-readtables/">named-readtables</a>
227 library to make this more convenient) symbol case is preserved,
228 and Parenscript will output mixed-case symbols
229 (like <samp>encodeURIComponent</samp>) correctly.</p>
231 <p>Lisp symbols (other than keywords) that are all uppercase or
232 contain special characters are converted to JavaScript
233 identifiers by following a few simple rules. Special
234 characters <code>!, ?, #, @, %, /, *</code> and <code>+</code>
235 get replaced by their written-out equivalents "bang", "what",
236 "hash", "at", "percent", "slash", "start" and "plus"
237 respectively. The <code>$</code> character is untouched.</p>
239 <dl>
240 <dt><code>!?#@%</code></dt>
241 <dd><samp>bangwhathashatpercent;</samp></dd>
242 </dl>
244 <p>The <code>-</code> is an indication that the following
245 character should be converted to uppercase.</p>
247 <dl>
248 <dt><code>bla-foo-bar</code></dt>
249 <dd><samp>blaFooBar;</samp></dd>
250 </dl>
252 <p>JavaScript identifiers that begin with an uppercase letter can
253 be obtained with a leading <code>-</code> or <code>*</code>.</p>
255 <dl>
256 <dt><code>*array</code></dt>
257 <dd><samp>Array;</samp></dd>
258 </dl>
260 <p>A symbol starting and ending with <code>+</code>
261 or <code>*</code> is converted to all uppercase, to signify that
262 this is a constant or a global variable.</p>
264 <dl>
265 <dt><code>*global-array*</code></dt>
266 <dd><samp>GLOBALARRAY;</samp></dd>
267 </dl>
269 <p>Keywords are not translated to JavaScript identifiers, but are
270 printed in lower case without any character substitution as
271 strings. This is done because strings are the closest equivalent
272 to Common Lisp keywords (being self-evaluating objects in
273 JavaScript), and to permit keywords to be used for identifying
274 various symbols (for example, as tokens in a parser).</p>
276 <dl>
277 <dt><code>:+</code></dt>
278 <dd><samp>'+';</samp></dd>
280 <dt><code>:foo-Bar</code></dt>
281 <dd><samp>'foo-bar';</samp></dd>
282 </dl>
284 <h2 id="section-namespace">The Parenscript namespace system</h2>
285 <ul>
286 <li>
287 (<code id="in-package">in-package</code> <var>package-designator</var>)
288 </li>
289 <li>
290 (<code id="use-package">use-package</code> <var>package-designator</var>)
291 </li>
292 <li>
293 (setf (<code id="ps-package-prefix">PS-PACKAGE-PREFIX</code> <var>package-designator</var>) <var>string</var>)
294 </li>
295 </ul>
298 Although JavaScript does not offer namespacing or a package
299 system, Parenscript does provide a namespace mechanism for
300 generated JavaScript by integrating with the Common Lisp package
301 system. Since Parenscript code is normally read in by the Lisp
302 reader, all symbols (except for uninterned ones, i.e. - those
303 specified with the <code>#:</code> reader macro) have a Lisp
304 package. By default, no packages are prefixed. You can specify
305 that symbols in a particular package receive a prefix when
306 translated to JavaScript with the
307 <var>PS-PACKAGE-PREFIX</var> place.
308 </p>
310 <dl>
311 <dt>
312 <pre><code>(defpackage "PS-REF.MY-LIBRARY"
313 (:use "PARENSCRIPT"))
315 (setf (ps-package-prefix "PS-REF.MY-LIBRARY") "my_library_")
317 (ps (defun ps-ref.my-library::library-function (x y)
318 (+ x y)))</code></pre>
319 </dt>
321 <dd>
322 <pre><samp>function my_library_libraryFunction(x, y) {
323 return x + y;
324 };</samp></pre>
325 </dd>
326 </dl>
329 Parenscript provides <code>IN-PACKAGE</code>
330 and <code>USE-PACKAGE</code> special forms, primarily useful
331 with <a href="#ps-compile-file"><code>PS-COMPILE-FILE</code></a>
332 and <a href="#ps-compile-stream"><code>PS-COMPILE-STREAM</code></a>.
333 </p>
335 <h3 id="section-obfuscation">Identifier obfuscation</h3>
336 <ul>
337 <li>
338 (<code id="obfuscate-package">OBFUSCATE-PACKAGE</code> <var>package-designator</var> &amp;optional <var>symbol-map</var>)
339 </li>
340 <li>
341 (<code id="unobfuscate-package">UNOBFUSCATE-PACKAGE</code> <var>package-designator</var>)
342 </li>
343 </ul>
345 <p>Similar to the namespace mechanism, Parenscript provides a
346 facility to generate obfuscated identifiers in specified CL
347 packages. The function <code>OBFUSCATE-PACKAGE</code> may
348 optionally be passed a closure that maps symbols to their
349 obfuscated counterparts. By default, the mapping is done
350 using <code><a href="#ps-gensym">PS-GENSYM</a></code>.</p>
352 <dl>
353 <dt>
354 <pre><code>(defpackage "PS-REF.OBFUSCATE-ME")
356 (obfuscate-package "PS-REF.OBFUSCATE-ME"
357 (let ((code-pt-counter #x8CF6)
358 (symbol-map (make-hash-table)))
359 (lambda (symbol)
360 (or (gethash symbol symbol-map)
361 (setf (gethash symbol symbol-map)
362 (make-symbol (string (code-char (incf code-pt-counter)))))))))
364 (defun ps-ref.obfuscate-me::a-function (a b ps-ref.obfuscate-me::foo)
365 (+ a (ps-ref.my-library::library-function b ps-ref.obfuscate-me::foo)))</code></pre>
366 </dt>
368 <dd>
369 <pre><samp>function 賷(a, b, 賸) {
370 return a + libraryFunction(b, 賸);
371 };</samp></pre>
372 </dd>
373 </dl>
375 <p>The obfuscation and namespace facilities can be used on packages
376 at the same time.</p>
378 <p>Since Parenscript doesn't know anything about the DOM or other
379 JavaScript libraries, library function and property names might be
380 inadvertently obfuscated. To help prevent that, Parenscript comes
381 with
382 the <code>ps-dom1-symbols</code>, <code>ps-dom2-symbols</code>, <code>ps-window-wd-symbols</code>, <code>ps-dom-nonstandard-symbols</code>
383 and <code>ps-dhtml-symbols</code> symbol packages that define
384 various DOM property and function identifiers as exported symbols
385 (in both case-sensitive and insensitive variants), which you can
386 import into your packages to help prevent symbols
387 like <code>pageXOffset</code> from being
388 obfuscated. The <code>ps-dhtml-symbols</code> package contains the
389 broadest range of symbols and is most generally useful.</p>
391 <p>If you use obfuscation and external JavaScript libraries, you
392 can use the same technique to define your own packages with
393 symbols that will not be obfuscated.</p>
395 <h3 id="section-minification">Minification</h3>
396 <ul>
397 <li><var id="*ps-print-pretty*">*PS-PRINT-PRETTY*</var></li>
398 <li><var id="*indent-num-spaces*">*INDENT-NUM-SPACES*</var></li>
399 </ul>
401 <p><var>*PS-PRINT-PRETTY*</var> and <var>*INDENT-NUM-SPACES*</var>
402 control whether the resulting JavaScript code is pretty-printed,
403 and if so, how many spaces go into each indent level,
404 respectively. By default the code is pretty-printed
405 with <kbd>4</kbd> spaces per indent level.</p>
407 <p>Setting <var>*PS-PRINT-PRETTY*</var> to nil and turning
408 on <a href="#section-obfuscation">obfuscation</a> will minify the
409 generated JavaScript code.</p>
411 <h2 id="reserved-symbols">Reserved symbols</h2>
413 <p>The following symbols are reserved in Parenscript, and should not
414 be used as variable names.</p>
416 <code>
417 ! ~ ++ -- * / % + - &lt;&lt; &gt;&gt; &gt;&gt;&gt; &lt; &gt;
418 &lt;= &gt;= == != === !== & ^ | && || *= /= %= += -= &lt;&lt;=
419 &gt;&gt;= &gt;&gt;&gt;= &= ^= |= 1- 1+ @ ABSTRACT AND AREF ARRAY
420 BOOLEAN BREAK BYTE CASE CATCH CHAR CLASS COMMA CONST CONTINUE
421 CREATE DEBUGGER DECF DEFAULT DEFUN DEFVAR DELETE DO DO* DOEACH
422 DOLIST DOTIMES DOUBLE ELSE ENUM EQL EXPORT EXTENDS F FALSE FINAL
423 FINALLY FLOAT FLOOR FOR FOR-IN FUNCTION GOTO IF IMPLEMENTS
424 IMPORT IN INCF INSTANCEOF INT INTERFACE JS LABELED-FOR LAMBDA
425 LET LET* LISP LIST LONG MAKE-ARRAY NATIVE NEW NIL NOT OR PACKAGE
426 PRIVATE PROGN PROTECTED PUBLIC RANDOM REGEX RETURN SETF SHORT
427 GETPROP STATIC SUPER SWITCH SYMBOL-MACROLET SYNCHRONIZED T THIS
428 THROW THROWS TRANSIENT TRY TYPEOF UNDEFINED UNLESS VAR VOID
429 VOLATILE WHEN WHILE WITH WITH-SLOTS
430 </code>
432 <h2 id="section-statements-expressions">Statements, expressions, and return</h2>
435 In contrast to Lisp, where everything is an expression,
436 JavaScript makes an arbitrary distinction between expressions,
437 which yield a value and can be nested in other expressions, and
438 statements, which have no value and cannot occur in expressions.
439 </p>
442 Some Parenscript special forms compile to expressions, while
443 others can only compile to statements. Certain Parenscript
444 forms, like <code>IF</code> and <code>PROGN</code>, generate
445 different JavaScript depending on if they are used in an
446 expression context or a statement context. In such cases,
447 Parenscript tries to generate statement code if possible to
448 increase readability, only falling back to the expression code
449 if it is necessary.
450 </p>
452 <dl>
453 <dt>
454 <code>(+ i (if x (foo) (bar)))</code>
455 </dt>
457 <dd>
458 <samp>i + (x ? foo() : bar());</samp>
459 </dd>
461 <dt>
462 <code>(if x (foo) (bar))</code>
463 </dt>
465 <dd>
466 <pre><samp>if (x) {
467 foo();
468 } else {
469 bar();
470 };</samp></pre>
471 </dd>
472 </dl>
475 One important feature found in Lisp but absent from JavaScript
476 is implicit return from functions. Parenscript automatically
477 provides implicit return for JavaScript statements and
478 expressions:
479 </p>
481 <dl>
482 <dt>
483 <pre><code>(defun foo (x)
484 (1+ x))</code></pre>
485 </dt>
487 <dd>
488 <pre><samp>function foo(x) {
489 return x + 1;
490 };</samp></pre>
491 </dd>
493 <dt>
494 <pre><code>(lambda (x)
495 (case x
496 (1 (loop repeat 3 do (alert "foo")))
497 (:bar (alert "bar"))
498 (otherwise 4)))</code></pre>
499 </dt>
501 <dd>
502 <pre><samp>function (x) {
503 switch (x) {
504 case 1:
505 for (var _js1 = 0; _js1 < 3; _js1 += 1) {
506 alert('foo');
508 return null;
509 case 'bar':
510 return alert('bar');
511 default:
512 return 4;
514 };</samp></pre>
515 </dd>
516 </dl>
519 Parenscript generates code that works around the JavaScript
520 expression-statement dichotomy in an unobtrusive way:
521 </p>
523 <dl>
524 <dt>
525 <pre><code>(+ 1 (dotimes (x 3) (if (= x 2) (return (+ x x)))))</code></pre>
526 </dt>
528 <dd>
529 <pre><samp>(function () {
530 for (var x = 0; x < 3; x += 1) {
531 if (x === 2) {
532 return x + x;
535 })() + 1;</samp></pre>
536 </dd>
537 </dl>
539 <h2 id="section-types">Types and type predicates</h2>
540 <ul>
541 <li>(<code id="typeof">TYPEOF</code> <var>object</var>)</li>
542 <li>(<code id="instanceof">INSTANCEOF</code> <var>object</var> <var>type</var>)</li>
543 <li>(<code id="null">NULL</code> <var>object</var>)</li>
544 <li>(<code id="undefined_1">UNDEFINED</code> <var>object</var>)</li>
545 <li>(<code id="defined">DEFINED</code> <var>object</var>)</li>
546 <li>(<code id="stringp">STRINGP</code> <var>object</var>)</li>
547 <li>(<code id="numberp">NUMBERP</code> <var>object</var>)</li>
548 <li>(<code id="functionp">FUNCTIONP</code> <var>object</var>)</li>
549 <li>(<code id="objectp">OBJECTP</code> <var>object</var>)</li>
550 </ul>
552 <dl>
553 <dt><var>object</var></dt> <dd>an expression yielding an object</dd>
554 <dt><var>type</var></dt> <dd>a type designator</dd>
555 </dl>
557 <p>Parenscript is based around the JavaScript type system, and
558 does not introduce any new types or objects, nor does it attempt
559 to provide a Common Lisp-like interface to the type system.</p>
561 <h2 id="section-literals">Literals</h2>
563 <h3 id="ssection-numbers">Numbers</h3>
565 <p>Parenscript prints all integer literals as integers, and floats
566 and rationals as floats, in base 10.</p>
568 <dl>
569 <dt><code>1</code></dt>
570 <dd><samp>1;</samp></dd>
572 <dt><code>123.123</code></dt>
573 <dd><samp>123.123;</samp></dd>
575 <dt><code>3/4</code></dt>
576 <dd><samp>0.75;</samp></dd>
578 <dt><code>#x10</code></dt>
579 <dd><samp>16;</samp></dd>
580 </dl>
582 <h3 id="ssection-strings-chars">Strings and characters</h3>
584 <p>Lisp strings are converted to JavaScript strings.</p>
586 <dl>
587 <dt><code>"foobar"</code></dt>
588 <dd><samp>'foobar';</samp></dd>
589 </dl>
591 <p>Parenscript makes no effort to interpolate C-style escape
592 strings. Rather, non-printable characters in Lisp strings are
593 output using escape sequences:</p>
595 <dl>
596 <dt><code>#\Tab</code></dt>
597 <dd><samp>'\t';</samp></dd>
599 <dt><code>"\\n"</code></dt>
600 <dd><samp>'\\n';</samp></dd>
601 </dl>
603 <h3 id="ssection-regex">Regular expressions</h3>
604 <ul>
605 <li>(<code id="regex">REGEX</code> <var>regex</var>)</li>
606 </ul>
608 <dl>
609 <dt><var>regex</var></dt> <dd>a string</dd>
610 </dl>
612 <p>Regular expressions can be created by using
613 the <code>REGEX</code> form. If the argument does not start with
614 <code>/</code>, it is surrounded by <code>/</code>, otherwise it
615 is left as it is.</p>
617 <dl>
618 <dt><code>(regex "foobar")</code></dt>
619 <dd><samp>/foobar/;</samp></dd>
621 <dt><code>(regex "/foobar/i")</code></dt>
622 <dd><samp>/foobar/i;</samp></dd>
623 </dl>
625 <p><a href="https://edicl.github.io/cl-interpol/">CL-INTERPOL</a> is
626 convenient for writing regular expressions:</p>
628 <dl>
629 <dt><code>(regex #?r"/([^\s]+)foobar/i")</code></dt>
630 <dd><samp>/([^\s]+)foobar/i;</samp></dd>
631 </dl>
633 <h3 id="ssection-booleans">Booleans and undefined</h3>
634 <ul>
635 <li><code id="t">T</code></li>
636 <li><code id="f">F</code></li>
637 <li><code id="false">FALSE</code></li>
638 <li><code id="nil">NIL</code></li>
639 <li><code id="undefined">UNDEFINED</code></li>
640 </ul>
642 <p><code>T</code> and <code>FALSE</code> (or <code>F</code>) are
643 converted to their JavaScript boolean
644 equivalents <samp>true</samp> and <samp>false</samp>.</p>
646 <p><code>NIL</code> is converted to the JavaScript keyword
647 <samp>null</samp>.</p>
649 <p><code>UNDEFINED</code> is converted to the JavaScript global
650 variable <a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Properties/undefined"><samp>undefined</samp></a>.</p>
652 <h2 id="section-objects">Objects</h2>
653 <ul>
654 <li>(<code id="new">NEW</code> <var>constructor</var>)</li>
655 <li>(<code id="create">CREATE</code> {<var>name</var> <var>value</var>}*)</li>
656 <li>(<code id="getprop">GETPROP</code> <var>object</var> {<var>slot-specifier</var>}*)</li>
657 <li>(<code id="@">@</code> {<var>slot-specifier</var>}*)</li>
658 <li>(<code id="chain">CHAIN</code> {<var>slot-specifier</var> | <var>function-call</var>}*)</li>
659 <li>(<code id="with-slots">WITH-SLOTS</code> ({<var>slot-name</var>}*) <var>object</var> <var>body</var>)</li>
660 <li>(<code id="delete">DELETE</code> <var>object</var>)</li>
661 </ul>
663 <dl>
664 <dt><var>constructor</var></dt> <dd>a function call to an object constructor</dd>
665 <dt><var>name</var></dt> <dd>symbol, string or keyword</dd>
666 <dt><var>value</var></dt> <dd>an expression</dd>
667 <dt><var>object</var></dt> <dd>an expression yielding an object</dd>
668 <dt><var>slot-specifier</var></dt> <dd>a quoted symbol, a string, a number, or an expression yielding a string or number</dd>
669 <dt><var>body</var></dt> <dd>implicit <code>PROGN</code></dd>
670 </dl>
672 <p>The <code>NEW</code> operator maps to JavaScript like:</p>
674 <dl>
675 <dt><code>(new (-Person age shoe-size))</code></dt>
676 <dd><samp>new Person(age, shoeSize);</samp></dd>
677 </dl>
679 <p>Object literals are created
680 with <code>CREATE</code>. <code>CREATE</code> takes a property
681 list of property names and values.</p>
683 <dl>
684 <dt>
685 <code>(create foo "bar" :blorg 1)</code>
686 </dt>
688 <dd>
689 <samp>{ foo : 'bar', 'blorg' : 1 };</samp>
690 </dd>
692 <dt>
693 <pre><code>(create foo "hihi"
694 blorg (array 1 2 3)
695 another-object (create :schtrunz 1))</code></pre>
696 </dt>
698 <dd>
699 <pre><samp>{ foo : 'hihi',
700 blorg : [ 1, 2, 3 ],
701 anotherObject : { 'schtrunz' : 1 } };</samp></pre>
702 </dd>
703 </dl>
705 <p>Object properties can be accessed using
706 <code>GETPROP</code>, which takes an object and a list of
707 properties.</p>
709 <dl>
710 <dt><code>(getprop obj 'foo)</code></dt>
711 <dd><samp>obj.foo;</samp></dd>
713 <dt><code>(getprop obj foo)</code></dt>
714 <dd><samp>obj[foo];</samp></dd>
716 <dt><code>(getprop element i 'child-node 0 'node-value)</code></dt>
717 <dd><samp>element[i].childNode[0].nodeValue;</samp></dd>
718 </dl>
720 <p>The convenience macro <code>@</code> quotes all its given
721 symbol slot-specifiers to save typing:</p>
723 <dl>
724 <dt><code>(@ an-object foo bar)</code></dt>
725 <dd><samp>anObject.foo.bar;</samp></dd>
727 <dt><code>(@ foo bar child-node 0 node-value)</code></dt>
728 <dd><samp>foo.bar.childNode[0].nodeValue;</samp></dd>
729 </dl>
731 <p><code>CHAIN</code> can be used to conveniently chain together
732 accessors and function calls:</p>
734 <dl>
735 <dt><code>(chain foo (bar x y) 0 baz)</code></dt>
736 <dd><samp>foo.bar(x, y)[0].baz;</samp></dd>
737 </dl>
739 <p><code>WITH-SLOTS</code> can be used to bind the given
740 slot-names to a symbol macro that will expand into
741 a <code>GETPROP</code> form at expansion time:</p>
743 <dl>
744 <dt>
745 <pre><code>(with-slots (a b c) this
746 (+ a b c))</code></pre>
747 </dt>
749 <dd>
750 <samp>this.a + this.b + this.c;</samp>
751 </dd>
752 </dl>
754 <h2 id="section-arrays">Arrays</h2>
755 <ul>
756 <li>(<code id="array">ARRAY</code> {<var>value</var>}*)</li>
757 <li>(<code id="list">LIST</code> {<var>value</var>}*)</li>
758 <li>(<code id="[]">[]</code> {<var>value</var>}*)</li>
759 <li>(<code id="make-array">MAKE-ARRAY</code> {<var>value</var>}*)</li>
760 <li>(<code id="length">LENGTH</code> <var>array</var>)</li>
761 <li>(<code id="aref">AREF</code> <var>array</var> <var>index</var>)</li>
762 <li>(<code id="elt">ELT</code> <var>array</var> <var>index</var>)</li>
763 <li>(<code id="destructuring-bind">DESTRUCTURING-BIND</code> <var>bindings</var> <var>array</var> <var>body</var>)</li>
764 <li>(<code id="concatenate">CONCATENATE 'STRING</code> {<var>value</var>}*)</li>
765 <li>(<code id="append">APPEND</code> {<var>value</var>}*)</li>
766 </ul>
768 <dl>
769 <dt><var>value</var></dt> <dd>an expression</dd>
770 <dt><var>array</var></dt> <dd>an expression</dd>
771 <dt><var>index</var></dt> <dd>an expression</dd>
772 </dl>
774 <p>Array literals can be created using the <code>ARRAY</code>
775 or <code>LIST</code> forms.</p>
777 <dl>
778 <dt><code>(array)</code></dt>
779 <dd><samp>[];</samp></dd>
781 <dt><code>(array 1 2 3)</code></dt>
782 <dd><samp>[1, 2, 3];</samp></dd>
784 <dt><code>(list (foo) (bar) 3)</code></dt>
785 <dd><samp>[foo(), bar(), 3];</samp></dd>
787 <dt>
788 <pre><code>(array (array 2 3)
789 (array "foo" "bar"))</code></pre>
790 </dt>
792 <dd>
793 <samp>[[ 2, 3 ], ['foo', 'bar']];</samp>
794 </dd>
795 </dl>
797 <p>The <code>[]</code> macro treats list arguments as quoted,
798 making it easy to write nested array literals:</p>
800 <dl>
801 <dt><code>([] 1 2 (3 4) 5 6)</code></dt>
802 <dd><samp>[1, 2, [3, 4], 5, 6];</samp></dd>
803 </dl>
805 <p>Arrays can also be created with a call to the <code>Array</code>
806 function using <code>MAKE-ARRAY</code>.</p>
808 <dl>
809 <dt><code>(make-array)</code></dt>
810 <dd><samp>new Array();</samp></dd>
812 <dt><code>(make-array 1 2 3)</code></dt>
813 <dd><samp>new Array(1, 2, 3);</samp></dd>
815 <dt>
816 <pre><code>(make-array
817 (make-array 2 3)
818 (make-array "foobar" "bratzel bub"))</code></pre>
819 </dt>
821 <dd>
822 <samp>new Array(new Array(2, 3), new Array('foobar', 'bratzel bub'));</samp>
823 </dd>
824 </dl>
826 <p>Array elements can be accessed using <code>AREF</code> or <code>ELT</code>.</p>
828 <h2 id="section-arithmetic">Arithmetic and boolean operators</h2>
829 <ul>
830 <li>(&lt;operator&gt; {<var>argument</var>}*)</li>
831 <li>(&lt;single-operator&gt; <var>argument</var>)</li>
832 </ul>
834 <dl>
835 <dt>&lt;operator&gt;</dt>
836 <dd>one of <code>*, /, +, -, <, >, <=, >=, =, AND, ASH, EQ, EQL, EQUAL, LOGAND, LOGIOR, LOGXOR, MOD, OR, REM, SETF</code>
837 </dd>
838 <dt>&lt;single-operator&gt;</dt>
839 <dd>one of <code>DECF, INCF, LOGNOT, NOT</code></dd>
841 <dt><var>argument</var></dt> <dd>an expression</dd>
842 </dl>
844 <p>Operator forms are similar to function call forms, but have an
845 operator as function name.</p>
847 <p>Please note that <code>=</code> is converted to <samp>===</samp> in
848 JavaScript. The <code>=</code> Parenscript operator is not the
849 assignment operator.</p>
851 <dl>
852 <dt><code>(* 1 2)</code></dt>
853 <dd><samp>1 * 2;</samp></dd>
855 <dt><code>(= 1 2)</code></dt>
856 <dd><samp>1 === 2;</samp></dd>
857 </dl>
859 <p>The negation of equality operators are obtained by through <code>NOT</code>. For example:</p>
861 <dl>
862 <dt><code>(not (eql 1 2))</code></dt>
863 <dd><samp>1 !== 2</samp></dd>
864 </dl>
866 <p>The operators that in CL have variable arity convert into multiple calls
867 to the equivalent operators in JavaScript</p>
869 <dl>
870 <dt><code>(logxor 1 3 7 15)</code></dt>
871 <dd><samp>1 ^ 3 ^ 7 ^ 15 </samp></dd>
872 </dl>
874 <h2 id="section-math">Mathematical functions and constants</h2>
875 <ul>
876 <li>(<code id="max">MAX</code> {<var>number</var>}*)</li>
877 <li>(<code id="min">MIN</code> {<var>number</var>}*)</li>
878 <li>(<code id="floor">FLOOR</code> <var>number</var> &amp;optional <var>divisor</var>)</li>
879 <li>(<code id="ceiling">CEILING</code> <var>number</var> &amp;optional <var>divisor</var>)</li>
880 <li>(<code id="round">ROUND</code> <var>number</var> &amp;optional <var>divisor</var>)</li>
881 <li>(<code id="sin">SIN</code> <var>number</var>)</li>
882 <li>(<code id="cos">COS</code> <var>number</var>)</li>
883 <li>(<code id="tan">TAN</code> <var>number</var>)</li>
884 <li>(<code id="asin">ASIN</code> <var>number</var>)</li>
885 <li>(<code id="acos">ACOS</code> <var>number</var>)</li>
886 <li>(<code id="atan">ATAN</code> <var>number1</var> &amp;optional <var>number2</var>)</li>
887 <li>(<code id="sinh">SINH</code> <var>number</var>)</li>
888 <li>(<code id="cosh">COSH</code> <var>number</var>)</li>
889 <li>(<code id="tanh">TANH</code> <var>number</var>)</li>
890 <li>(<code id="asinh">ASINH</code> <var>number</var>)</li>
891 <li>(<code id="acosh">ACOSH</code> <var>number</var>)</li>
892 <li>(<code id="atanh">ATANH</code> <var>number</var>)</li>
893 <li>(<code id="1+">1+</code> <var>number</var>)</li>
894 <li>(<code id="1-">1-</code> <var>number</var>)</li>
895 <li>(<code id="abs">ABS</code> <var>number</var>)</li>
896 <li>(<code id="evenp">EVENP</code> <var>number</var>)</li>
897 <li>(<code id="oddp">ODDP</code> <var>number</var>)</li>
898 <li>(<code id="exp">EXP</code> <var>number</var>)</li>
899 <li>(<code id="expt">EXPT</code> <var>base</var> <var>power</var>)</li>
900 <li>(<code id="log">LOG</code> <var>number</var> &amp;optional <var>base</var>)</li>
901 <li>(<code id="sqrt">SQRT</code> <var>number</var>)</li>
902 <li>(<code id="random">RANDOM</code> &amp;optional <var>limit</var>)</li>
904 <li><var id="pi">PI</var></li>
905 </ul>
908 The mathematical functions listed above work mostly like their
909 Common Lisp counterparts when called directly, with the
910 exception that complex numbers are not supported. However, most
911 of them are implemented as macros, and as such cannot be treated
912 as first-class functions.
913 </p>
915 <h2 id="section-blocks">Blocks</h2>
916 <ul>
917 <li>
918 (<code id="block">BLOCK</code> <var>name</var> {<var>expression</var> | <var>statement</var>}*)
919 </li>
920 <li>
921 (<code id="progn">PROGN</code> {<var>statement</var>}*) in statement context
922 </li>
923 <li>
924 (<code>PROGN</code> {<var>expression</var>}*) in expression context
925 </li>
926 <li>
927 (<code id="prog1">PROG1</code> {<var>expression</var> | <var>statement</var>}*)
928 </li>
929 <li>
930 (<code id="prog2">PROG2</code> {<var>expression</var> | <var>statement</var>}*)
931 </li>
932 <li>
933 (<code id="eval-when">EVAL-WHEN</code> {<var>expression</var> | <var>statement</var>}*)
934 </li>
935 </ul>
937 <dl>
938 <dt><var>name</var></dt> <dd>Name/tag of the block. A symbol or nil.</dd>
939 <dt><var>statement</var></dt> <dd>a form that compiles to a statement</dd>
940 <dt><var>expression</var></dt> <dd>a form that compiles to an expression</dd>
941 </dl>
944 The translation of <code>PROGN</code> depends on whether it is
945 found in a statement or expression context:
946 </p>
948 <dl>
949 <dt><code>(progn (blorg i) (blafoo i))</code></dt>
950 <dd>
951 <pre><samp>blorg(i);
952 blafoo(i);</samp></pre>
953 </dd>
955 <dt><code>(+ i (progn (blorg i) (blafoo i)))</code></dt>
956 <dd><samp>i + (blorg(i), blafoo(i));</samp></dd>
957 </dl>
960 The Parenscript <code>EVAL-WHEN</code> special operator has a
961 slightly different meaning from the Common Lisp one. The code in
962 the <code>EVAL-WHEN</code> special form is assumed to be Common
963 Lisp code in <code>:compile-toplevel</code>
964 and <code>:load-toplevel</code> situations, and is executed by
965 the Parenscript compiler, and is assumed to be Parenscript code
966 in the <code>:execute</code> situation, when it is run as
967 JavaScript.
968 </p>
970 <h2 id="section-functions">Functions and multiple values</h2>
971 <ul>
972 <li>(<code id="defun">DEFUN</code> <var>name</var> <var>lambda-list</var> <var>body</var>)</li>
973 <li>(<code id="lambda">LAMBDA</code> <var>lambda-list</var> <var>body</var>)</li>
974 <li>(<code id="flet">FLET</code> ({(<var>name</var> <var>lambda-list</var> <var>body</var>)}*) <var>body</var>)</li>
975 <li>(<code id="labels">LABELS</code> ({(<var>name</var> <var>lambda-list</var> <var>body</var>)}*) <var>body</var>)</li>
976 <li>(<code id="values">VALUES</code> {<var>expression</var>}*)</li>
977 <li>(<code id="multiple-value-bind">MULTIPLE-VALUE-BIND</code> ({<var>var</var>}*) <var>expression</var> <var>body</var>)</li>
978 <li>(<code id="apply">APPLY</code> <var>function</var> {<var>expression</var>}*)</li>
979 <li>(<code id="funcall">FUNCALL</code> <var>function</var> {<var>expression</var>}*)</li>
980 <li><var id="this">THIS</var></li>
981 </ul>
983 <dl>
984 <dt><var>expression</var></dt> <dd>a form that compiles to an expression</dd>
985 <dt><var>name</var></dt> <dd>a symbol</dd>
986 <dt><var>lambda-list</var></dt> <dd>a lambda list</dd>
987 <dt><var>body</var></dt> <dd>implicit <code>PROGN</code></dd>
988 <dt><var>var</var></dt> <dd>a symbol naming a variable</dd>
989 <dt><var>function</var></dt> <dd>an expression that yields a function</dd>
990 </dl>
993 New function definitions can be introduced using all the regular
994 Lisp forms
995 - <code>DEFUN</code>, <code>LAMBDA</code>, <code>FLET</code>,
996 and <code>LABELS</code>. Function lambda lists
997 support <code>&amp;optional</code>, <code>&amp;rest</code> and
998 <code>&amp;key</code> arguments.
999 </p>
1002 The Parenscript multiple value facility passes the first return
1003 value using the regular JavaScript convention, therefore
1004 functions returning multiple values can be called by regular
1005 JavaScript code and <code>MULTIPLE-VALUE-BIND</code> works with
1006 regular JavaScript functions.
1007 </p>
1010 <code>APPLY</code> is a macro that expands into a call to the
1011 JavaScript <code>apply</code> method.
1012 </p>
1014 <h2 id="section-control-transfer">Control transfer and exceptions</h2>
1015 <ul>
1016 <li>
1017 (<code id="return">RETURN</code> {<var>value</var>}?)
1018 </li>
1019 <li>
1020 (<code id="return-from">RETURN-FROM</code> <var>name</var> {<var>value</var>}?)
1021 </li>
1022 <li>
1023 (<code id="throw">THROW</code> {<var>exp</var>}?)
1024 </li>
1025 <li>
1026 (<code id="try">TRY</code> <var>form</var>
1027 {(<code id="catch">:CATCH</code> (<var>var</var>) <var>body</var>)}?
1028 {(<code id="finally">:FINALLY</code> <var>body</var>)}?)
1029 </li>
1030 <li>
1031 (<code id="unwind-protect">UNWIND-PROTECT</code> <var>protected-form</var> <var>cleanup-form</var>)
1032 </li>
1033 <li>
1034 (<code id="ignore-errors">IGNORE-ERRORS</code> <var>body</var>)
1035 </li>
1036 </ul>
1038 <dl>
1039 <dt><var>value</var></dt> <dd>a statement or expression</dd>
1040 <dt><var>name</var></dt> <dd>name of block to return from</dd>
1041 <dt><var>exp</var></dt> <dd>an expression</dd>
1042 <dt><var>var</var></dt> <dd>variable to which the value of the caught <code>THROW</code> is bound</dd>
1043 <dt><var>body</var></dt> <dd>implicit <code>PROGN</code></dd>
1044 </dl>
1047 Parenscript support nested blocks and the <code>RETURN</code>
1048 and <code>RETURN-FROM</code> special forms.
1049 </p>
1051 <dl>
1052 <dt>
1053 <pre><code>(defun foo (x)
1054 (progn
1055 (abc)
1056 (return-from foo
1057 (case x
1058 (1 :a)
1059 (2 :b)))
1060 (xyz)))</code></pre>
1061 </dt>
1063 <dd>
1064 <pre><samp>function foo(x) {
1065 abc();
1066 switch (x) {
1067 case 1:
1068 return 'a';
1069 case 2:
1070 return 'b';
1072 return xyz();
1073 };</samp></pre>
1074 </dd>
1075 </dl>
1078 Currently, <code>THROW</code> translates directly into the
1079 JavaScript <samp>throw</samp>, to be used with <code>TRY</code>,
1080 which is translated to the JavaScript <samp>try</samp>.
1081 </p>
1083 <dl>
1084 <dt>
1085 <pre><code>(try (throw "i")
1086 (:catch (error)
1087 (alert (+ "an error happened: " error)))
1088 (:finally
1089 (alert "Leaving the try form")))</code></pre>
1090 </dt>
1092 <dd>
1093 <pre><samp>try {
1094 throw 'i';
1095 } catch (error) {
1096 alert('an error happened: ' + error);
1097 } finally {
1098 alert('Leaving the try form');
1099 };</samp></pre>
1100 </dd>
1101 </dl>
1103 <h2 id="section-conditionals">Conditionals</h2>
1104 <ul>
1105 <li>(<code id="if">IF</code> <var>condition</var> <var>then</var> {<var>else</var>})</li>
1106 <li>(<code id="when">WHEN</code> <var>condition</var> <var>then</var>)</li>
1107 <li>(<code id="unless">UNLESS</code> <var>condition</var> <var>then</var>)</li>
1108 <li>(<code id="cond">COND</code> {<var>clause</var>}*)</li>
1109 <li>(<code id="case">CASE</code> <var>case-value</var> <var>clause</var>*)</li>
1110 <li>(<code id="switch">SWITCH</code> <var>case-value</var> <var>clause</var>*)</li>
1111 <li><code id="break">BREAK</code></li>
1112 </ul>
1114 <dl>
1115 <dt><var>condition</var></dt> <dd>an expression</dd>
1116 <dt><var>then</var></dt> <dd>a statement in statement context, or an expression in expression context</dd>
1117 <dt><var>else</var></dt> <dd>a statement in statement context, or an expression in expression context</dd>
1118 <dt><var>clause</var></dt> <dd>(&lt;<var>value</var>&gt; <var>body</var>) | (<var>default</var> <var>body</var>)</dd>
1119 </dl>
1121 <p><code>IF, WHEN, UNLESS</code> and <code>COND</code> work like
1122 their Lisp counterparts, and are compiled either into statements
1123 or expressions, depending on the context:</p>
1125 <dl>
1126 <dt>
1127 <code>(cond ((= x 1) (+ x (if (foo y) 2 3))))</code>
1128 </dt>
1130 <dd>
1131 <pre><samp>if (x == 1) {
1132 x + (foo(y) ? 2 : 3);
1133 };</samp></pre>
1134 </dd>
1135 </dl>
1138 <code>CASE</code> works similar to its Common Lisp equivalent.
1139 </p>
1142 An additional form, <code>SWITCH</code>, takes the same syntax
1143 as <code>CASE</code>, but the individual branches must be
1144 terminated with the
1145 symbol <a href="#break"><code>BREAK</code></a>. This allows
1146 C-style case "fall-throughs" in <code>switch</code> statements:
1147 </p>
1149 <dl>
1150 <dt>
1151 <pre><code>(switch (aref blorg i)
1152 (1 (alert "If I get here"))
1153 (2 (alert "I also get here")
1154 break)
1155 (default (alert "I always get here")))</code></pre>
1156 </dt>
1158 <dd>
1159 <pre><samp>switch (blorg[i]) {
1160 case 1:
1161 alert('If I get here');
1162 case 2:
1163 alert('I also get here');
1164 break;
1165 default:
1166 alert('I always get here');
1167 };</samp></pre>
1168 </dd>
1169 </dl>
1171 <p>Note that the default case in a <code>SWITCH</code> statement
1172 must be named <code id="default">DEFAULT</code>.</p>
1174 <h2 id="section-variables">Variable binding and declaration</h2>
1175 <ul>
1176 <li>(<code id="let">LET</code> ({<var>var</var> | (<var>var</var> <var>value</var>)}*) <var>body</var>)</li>
1177 <li>(<code id="let*">LET*</code> ({<var>var</var> | (<var>var</var> <var>value</var>)}*) <var>body</var>)</li>
1178 <li>(<code id="defvar">DEFVAR</code> <var>var</var> {<var>value</var>}?)</li>
1179 <li>(<code id="var">VAR</code> <var>var</var> {<var>value</var>}?)</li>
1180 </ul>
1182 <dl>
1183 <dt><var>var</var></dt> <dd>a symbol</dd>
1184 <dt><var>value</var></dt> <dd>an expression</dd>
1185 <dt><var>body</var></dt> <dd>implicit <code>PROGN</code></dd>
1186 <dt><var>object</var></dt> <dd>an expression evaluating to an object</dd>
1187 </dl>
1189 <p>Parenscript provides the <code>LET</code> and <code>LET*</code>
1190 special forms for creating new variable bindings. Both special
1191 forms implement lexical scope by renaming the provided variables
1192 via <a href="#ps-gensym"><code>GENSYM</code></a>, and implement
1193 dynamic binding
1194 using <a href="#try"><code>TRY-FINALLY</code></a>.</p>
1196 <p>Special variables can be declared using
1197 <code>DEFVAR</code>. Note that the result is undefined
1198 if <code>DEFVAR</code> does not occur as a top-level form.</p>
1200 <p>One Parenscript feature that is not part of Common Lisp is the
1201 lexically-scoped global variable, which is declared using
1202 the <code>VAR</code> special form. The result is undefined
1203 if <code>VAR</code> does not occur as a top-level form.</p>
1205 <p>An example of variable declaration and binding:</p>
1207 <dl>
1208 <dt>
1209 <pre><code>(defvar *a* 4)
1210 (var *b* 3)
1211 (lambda ()
1212 (let ((x 1)
1213 (*a* 2)
1214 (*b* 6))
1215 (let* ((y (+ x 1))
1216 (x (+ x y)))
1217 (+ *a* *b* x y))))</code></pre>
1218 </dt>
1220 <dd>
1221 <pre><samp>var A = 4;
1222 var B = 3;
1223 function () {
1224 var x = 1;
1225 var B = 6;
1226 var A_TMPSTACK1;
1227 try {
1228 A_TMPSTACK1 = A;
1229 A = 2;
1230 var y = x + 1;
1231 var x2 = x + y;
1232 return A + B + x2 + y;
1233 } finally {
1234 A = A_TMPSTACK1;
1236 };</samp></pre>
1237 </dd>
1238 </dl>
1240 <h2 id="section-assignment">Assignment</h2>
1242 <p>Parenscript assignment is done via the
1243 standard <code id="setf">SETF</code>, <code id="SETQ">SETQ</code>,
1244 <code id="PSETF">PSETF</code>, and <code id="PSETQ">PSETQ</code>
1245 Lisp special forms. Parenscript supports the Common Lisp
1246 protocol of <code>SETF</code>able places.</p>
1248 <p>New places can be defined in one of two ways: using
1249 <code>DEFSETF</code> or using <code>DEFUN</code> with a setf
1250 function name; both are analogous to their Common Lisp
1251 counterparts. <code>DEFSETF</code> supports both long and short
1252 forms, while <code>DEFUN</code> of a setf place generates a
1253 JavaScript function name with the <samp>__setf_</samp>
1254 prefix:</p>
1256 <dl>
1257 <dt>
1258 <pre><code>(defun (setf color) (new-color el)
1259 (setf (@ el style color) new-color))</code></pre>
1260 </dt>
1262 <dd>
1263 <pre><samp>function __setf_color(newColor, el) {
1264 return el.style.color = newColor;
1265 };</samp></pre>
1266 </dd>
1268 <dt>
1269 <code>(setf (color some-div) (+ 23 "em"))</code>
1270 </dt>
1272 <dd>
1273 <pre><samp>var _js2 = someDiv;
1274 var _js1 = 23 + 'em';
1275 __setf_color(_js1, _js2);</samp></pre>
1276 </dd>
1277 </dl>
1279 <p>The following example illustrates how setf places can be used
1280 to provide a uniform protocol for positioning elements in HTML
1281 pages:</p>
1283 <dl>
1284 <dt>
1285 <pre><code>(defsetf left (el) (offset)
1286 `(setf (@ ,el style left) ,offset))
1288 (defmacro left (el)
1289 `(@ ,el offset-left))
1291 (setf (left some-div) (+ 123 "px"))
1292 (left some-div)</code></pre>
1293 </dt>
1295 <dd>
1296 <pre><samp>var _js2 = someDiv;
1297 var _js1 = 123 + 'px';
1298 _js2.style.left = _js1;
1299 someDiv.offsetLeft;</samp></pre>
1300 </dd>
1301 </dl>
1303 <h2 id="section-iteration">Iteration</h2>
1304 <ul>
1305 <li>(<code id="do">DO</code> ({<var>var</var> | (<var>var</var> {<var>init</var>}? {<var>step</var>}?)}*) (<var>end-test</var> {<var>result</var>}?) <var>body</var>)</li>
1306 <li>(<code id="do*">DO*</code> ({<var>var</var> | (<var>var</var> {<var>init</var>}? {<var>step</var>}?)}*) (<var>end-test</var> {<var>result</var>}?) <var>body</var>)</li>
1307 <li>(<code id="dotimes">DOTIMES</code> (<var>var</var> <var>numeric-form</var> {<var>result</var>}?) <var>body</var>)</li>
1308 <li>(<code id="dolist">DOLIST</code> (<var>var</var> <var>list-form</var> {<var>result</var>}?) <var>body</var>)</li>
1309 <li>(<code id="for-in">FOR-IN</code> (<var>var</var> <var>object</var>) <var>body</var>)</li>
1310 <li>(<code id="while">WHILE</code> <var>end-test</var> <var>body</var>)</li>
1311 <li>(<code id="loop">LOOP</code> {&lt;loop clauses&gt;}*)</li>
1312 </ul>
1314 <dl>
1315 <dt><var>var</var></dt> <dd>a symbol</dd>
1316 <dt><var>numeric-form</var></dt> <dd>a number yielding expression</dd>
1317 <dt><var>list-form</var></dt> <dd>an array yielding expression</dd>
1318 <dt><var>object-form</var></dt> <dd>an object yielding expression</dd>
1319 <dt><var>init</var></dt> <dd>an expression</dd>
1320 <dt><var>step</var></dt> <dd>an expression</dd>
1321 <dt><var>end-test</var></dt> <dd>an expression</dd>
1322 <dt><var>result</var></dt> <dd>an expression</dd>
1323 <dt><var>body</var></dt> <dd>implicit <code>PROGN</code></dd>
1324 </dl>
1326 <p>Parenscript comes with a wide array of Common Lisp iteration
1327 constructs that compile to efficient JavaScript code,
1328 including a partial implementation of <code>LOOP</code>.</p>
1330 <h2 id="section-macros">Macros</h2>
1331 <h3 id="ssection-defining-macros">Defining macros</h3>
1332 <ul>
1333 <li>(<code id="defmacro">DEFMACRO</code> <var>name</var> <var>lambda-list</var> <var>macro-body</var>)</li>
1334 <li>(<code id="defpsmacro">DEFPSMACRO</code> <var>name</var> <var>lambda-list</var> <var>macro-body</var>)</li>
1335 <li>(<code id="defmacro+ps">DEFMACRO+PS</code> <var>name</var> <var>lambda-list</var> <var>macro-body</var>)</li>
1336 <li>(<code id="import-macros-from-lisp">IMPORT-MACROS-FROM-LISP</code> {<var>symbol</var>}*)</li>
1337 <li>(<code id="macrolet">MACROLET</code> ({<var>name</var> <var>lambda-list</var> <var>macro-body</var>}*) <var>body</var>)</li>
1338 </ul>
1340 <dl>
1341 <dt><var>name</var></dt> <dd>a symbol</dd>
1342 <dt><var>lambda-list</var></dt> <dd>a lambda list</dd>
1343 <dt><var>macro-body</var></dt> <dd>Lisp code evaluating to Parenscript code</dd>
1344 <dt><var>body</var></dt> <dd>implicit <code>PROGN</code></dd>
1345 <dt><var>symbol</var></dt> <dd>symbol with a Lisp macro function definition</dd>
1346 </dl>
1348 <p>Parenscript macros are like Lisp macros in that they have
1349 access to the full Lisp language, but different in that they must
1350 produce Parenscript code. Since Parenscript provides a large
1351 subset of Common Lisp, many Lisp macros already produce valid
1352 Parenscript code, and vice-versa. Parenscript provides several
1353 different ways to define new macros, and to use already existing
1354 Common Lisp macros.</p>
1356 <p><code>DEFMACRO</code> and <code>MACROLET</code> can be used to
1357 define new macros in Parenscript code. Note that macros defined
1358 this way are defined in a null lexical environment (ex
1359 - <code>(let ((x 1)) (defmacro baz (y) `(+ ,y ,x)))</code> will
1360 not work), since the surrounding Parenscript code is just
1361 translated to JavaScript and not actually evaluated.</p>
1363 <p><code>DEFPSMACRO</code> is a Lisp form (not a Parenscript one!)
1364 that can be used by Lisp code to define Parenscript macros without
1365 calling the Parenscript compiler.</p>
1367 <p>The representation of Parenscript macro functions is the same
1368 as that of Common Lisp, and in fact Parenscript can use already
1369 defined macros this way.
1371 <p><code>DEFMACRO+PS</code> defines two macros with the same name
1372 and expansion, one in Parenscript and one in
1373 Lisp. <code>DEFMACRO+PS</code> is used when the full
1374 macro-expansion of the Lisp macro yields code that cannot be used
1375 by Parenscript.</p>
1377 <p>Parenscript also supports the use of macros defined in the
1378 underlying Lisp environment. Existing Lisp macros can be
1379 imported into the Parenscript macro environment
1380 by <code>IMPORT-MACROS-FROM-LISP</code>. This functionality
1381 enables code sharing between Parenscript and Lisp, and is useful
1382 in debugging since the full power of Lisp macro-expanders,
1383 editors and other supporting facilities can be used. However, it
1384 is important to note that the macro-expansion of Lisp macros and
1385 Parenscript macros takes place in their own respective
1386 environments, and many Lisp macros (especially those provided by
1387 the Lisp implementation) expand into code that is not usable by
1388 Parenscript. To make it easy for users to take advantage of
1389 these features, two additional macro definition facilities are
1390 provided by Parenscript: </p>
1392 <h3 id="ssection-symbol-macros">Symbol macros</h3>
1394 <ul>
1395 <li>(<code id="define-ps-symbol-macro">DEFINE-PS-SYMBOL-MACRO</code> <var>symbol</var> <var>expansion</var>)</li>
1396 <li>(<code id="symbol-macrolet">SYMBOL-MACROLET</code> ({<var>name</var> <var>macro-body</var>}*) <var>body</var>)</li>
1397 </ul>
1399 <p>Symbol macros can be introduced
1400 using <code>SYMBOL-MACROLET</code> or defined in Lisp
1401 with <code>DEFINE-PS-SYMBOL-MACRO</code>. For example, the
1402 Parenscript
1403 <code>WITH-SLOTS</code> is implemented using symbol macros:</p>
1405 <dl>
1406 <dt>
1407 <pre><code>(defpsmacro with-slots (slots object &amp;rest body)
1408 `(symbol-macrolet ,(mapcar #'(lambda (slot)
1409 `(,slot '(getprop ,object ',slot)))
1410 slots)
1411 ,@body))</code></pre>
1412 </dt>
1413 </dl>
1415 <h3 id="ssection-gensym">Gensym</h3>
1416 <ul>
1417 <li>(<code id="ps-gensym">PS-GENSYM</code> {<var>string</var>})</li>
1418 <li>(<code id="with-ps-gensyms">WITH-PS-GENSYMS</code> <var>symbols</var> &amp;body <var>body</var>)</li>
1419 <li>(<code id="ps-once-only">PS-ONCE-ONLY</code> (&amp;rest <var>vars</var>) &amp;body <var>body</var>)</li>
1421 <li><var id="*ps-gensym-counter*">*PS-GENSYM-COUNTER*</var></li>
1422 </ul>
1424 <p>JavaScript identifier equality is based on string
1425 representations, as opposed to Common Lisp, where two uninterned
1426 symbols with the same name are different objects. Therefore
1427 Parenscript <code>GENSYM</code> depends
1428 on <var>*PS-GENSYM-COUNTER*</var> values only for generating
1429 unique identifiers. <var>*PS-GENSYM-COUNTER*</var> does not
1430 persist and is not guaranteed to be thread-safe, so care should be
1431 taken to avoid writing var where gensymed identifiers may clash
1432 (for example, this could happen if you concatenate JS var from PS
1433 compilers running in two different Lisp images, where the values
1434 of <var>*PS-GENSYM-COUNTER*</var> overlap).
1436 <h2 id="section-utilities">Utilities</h2>
1438 <h3 id="ssection-dom">DOM</h3>
1439 <ul>
1440 <li>(<code>INNER-HTML</code> <var>el</var>)</li>
1441 <li>(<code>URI-ENCODE</code> <var>el</var>)</li>
1442 <li>(<code>ATTRIBUTE</code> <var>el</var>)</li>
1443 <li>(<code>OFFSET</code> <var>compass</var> <var>el</var>)</li>
1444 <li>(<code>SCROLL</code> <var>compass</var> <var>el</var>)</li>
1445 <li>(<code>INNER</code> <var>wh</var> <var>el</var>)</li>
1446 <li>(<code>CLIENT</code> <var>wh</var> <var>el</var>)</li>
1447 </ul>
1449 <dl>
1450 <dt><var>el</var></dt> <dd>an expression that yields a DOM element</dd>
1451 <dt><var>compass</var></dt> <dd>one of <code>:TOP, :LEFT, :HEIGHT, :WIDTH, :BOTTOM, :RIGHT</code></dd>
1452 <dt><var>wh</var></dt> <dd>one of <code>:WIDTH, :HEIGHT</code></dd>
1453 </dl>
1455 <h3 id="ssection-html-gen">HTML generation</h3>
1456 <ul>
1457 <li>(<code id="ps-html">PS-HTML</code> <var>html-expression</var>)</li>
1458 <li>(<code id="who-ps-html">WHO-PS-HTML</code> <var>html-expression</var>)</li>
1459 <li><var id="*ps-html-empty-tag-aware-p*">*PS-HTML-EMPTY-TAG-AWARE-P*</var></li>
1460 <li><var id="*ps-html-mode*">*PS-HTML-MODE*</var></li>
1461 </ul>
1463 <p>Parenscript comes with two HTML markup generation facilities
1464 that produce Parenscript code - <code>PS-HTML</code>
1465 and <code>WHO-PS-HTML</code>. The former
1466 accepts <a href="https://franz.com/support/documentation/current/doc/aserve/htmlgen.html">LHTML</a>
1467 style markup; the latter
1468 accepts <a href="https://edicl.github.io/cl-who/">CL-WHO</a>
1469 style markup.</p>
1471 <p><var>*PS-HTML-EMPTY-TAG-AWARE-P*</var>
1472 and <var>*PS-HTML-MODE*</var> control how tags are closed when an
1473 HTML element has no
1474 content. When <var>*PS-HTML-EMPTY-TAG-AWARE-P*</var> is <code>nil</code>, all
1475 tags are fully closed (ex - <code>:BR</code> is translated
1476 as <samp>&lt;BR&gt;&lt;/BR&gt;</samp>). When <var>*PS-HTML-EMPTY-TAG-AWARE-P*</var>
1477 has a non-nil value and <var>*PS-HTML-MODE*</var>
1478 is <code>:SGML</code>, tags such as <code>BR</code> are output without
1479 being closed. When <var>*PS-HTML-MODE*</var> is <code>:XML</code>,
1480 XML-style closing tags are used (ex - <code>:BR</code> is
1481 translated as <samp>&lt;BR /&gt;</samp>).</p>
1483 <dl>
1484 <dt><code>(ps-html ((:a :href "foobar") "blorg"))</code></dt>
1485 <dd><samp>'&lt;A HREF=\"foobar\"&gt;blorg&lt;/A&gt;';</samp></dd>
1487 <dt><code>(who-ps-html (:a :href (generate-a-link) "blorg"))</code></dt>
1488 <dd><samp>'&lt;A HREF=\"' + generateALink() + '\"&gt;blorg&lt;/A&gt;';</samp></dd>
1489 </dl>
1491 <p>The Parenscript compiler can be recursively called in an HTML
1492 expression:</p>
1494 <dl>
1495 <dt>
1496 <pre><code>((@ document write)
1497 (ps-html ((:a :href "#"
1498 :onclick (ps-inline (transport))) "link")))</code></pre>
1499 </dt>
1501 <dd><samp>document.write('&lt;A HREF=\"#\" ONCLICK=\"' + ('javascript:' + 'transport()') + '\"&gt;link&lt;/A&gt;');</samp></dd>
1502 </dl>
1504 <p>Forms may be used in attribute lists to conditionally generate
1505 the next attribute. In this example the textarea is sometimes
1506 disabled.</p>
1508 <dl>
1509 <dt>
1510 <pre><code>(let ((disabled nil)
1511 (authorized t))
1512 (setf (@ element inner-h-t-m-l)
1513 (ps-html ((:textarea (or disabled (not authorized)) :disabled "disabled")
1514 "Edit me"))))</code></pre>
1515 </dt>
1517 <dd>
1518 <pre><samp>var disabled = null;
1519 var authorized = true;
1520 element.innerHTML =
1521 '&lt;TEXTAREA'
1522 + (disabled || !authorized ? ' DISABLED=\"' + 'disabled' + '\"' : '')
1523 + '&gt;Edit me&lt;/TEXTAREA&gt;';</samp></pre>
1524 </dd>
1525 </dl>
1527 <h2 id="section-runtime-library">Run-time library</h2>
1528 <ul>
1529 <li>(<code id="member">MEMBER</code> <var>object</var> <var>array</var>)</li>
1530 <li>(<code id="map">MAP</code> <var>function</var> <var>array</var>)</li>
1531 <li>(<code id="mapcar">MAPCAR</code> <var>function</var> {<var>array</var>}*)</li>
1532 <li>(<code id="reduce">REDUCE</code> <var>function</var> <var>array</var> <var>object</var>)</li>
1533 <li>(<code id="map-into">MAP-INTO</code> <var>function</var> <var>array</var>)</li>
1534 <li>(<code id="set-difference">SET-DIFFERENCE</code> <var>array1</var> <var>array2</var>)</li>
1535 <li><var id="*ps-lisp-library*">*PS-LISP-LIBRARY*</var></li>
1536 </ul>
1538 <p>All the Parenscript constructs presented so far have been free
1539 of any run-time dependencies. Parenscript also comes with a library
1540 of useful predefined functions that can be added to your
1541 project. These functions are kept as Parenscript code in
1542 the <var>*PS-LISP-LIBRARY*</var> special variable.</p>
1544 <p><code>MAP</code> differs from its Common Lisp counterpart by
1545 virtue of being a <code>MAPCAR</code> that only accepts a single
1546 sequence to map over. <code>MAP-UNTIL</code> is
1547 like <code>MAP</code> but replaces the contents of the given
1548 array in-place.</p>
1550 <h2 id="section-slime-integration">SLIME integration</h2>
1552 <p>The <kbd>extras</kbd> folder in the Parenscript distribution
1553 contains <kbd>js-expander.el</kbd>, which when loaded in Emacs
1554 with SLIME adds the ability to quickly see the translation of
1555 any Lisp form in JavaScript, and works much like the Slime '<kbd>C-c
1556 M-m</kbd>' macro-expansion feature.</p>
1558 <p>'<kbd>C-c j</kbd>' (<a href="#ps"><code>PS</code></a>) or
1559 '<kbd>C-c d</kbd>' (<a href="#ps-doc"><code>PS-DOC</code></a>)
1560 at a Parenscript expression in a <code>slime-mode</code> buffer
1561 will bring up a buffer with the resulting JavaScript code. Note
1562 that the extension does not work
1563 in <code>slime-repl-mode</code>, which is intentional.</p>
1565 <p><kbd>extras/swank-parenscript.lisp</kbd> shows how to add support
1566 to SLIME for printing hints about Parenscript-defined macro and
1567 function argument lists to the Emacs minibuffer, like SLIME
1568 already does for Common Lisp functions and macros.</p>
1570 <p style="font-size:xx-small;float:right;">Last updated: 2018-10-20</p>
1571 </body>
1572 </html>