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