-
Notifications
You must be signed in to change notification settings - Fork 3
/
index.html
548 lines (421 loc) · 23.2 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/transitional.dtd">
<html>
<head>
<title>CL-JavaScript</title>
<style type="text/css">
body {margin: 0; padding: 0; max-width: 55em; background-color: #f5f5f5;}
#wrap {margin: 0 3em; padding: 3em 5em; border-left: 1px solid #400; border-right: 1px solid #400;
background-color: white;}
h1, h2, h3 {font-family: tahoma, sans-serif;}
p.news {padding-left: 2em; text-indent: -2em;}
p.news span {font-weight: bold;}
p.def {font-family: monospace; font-weight: bold;}
p.def span {color: #555; font-weight: normal}
.desc {padding-left: 1em;}
a {text-decoration: none; color: #600;}
ul {padding: 0; margin: 0; margin-left: 1.5em;}
</style>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
</head>
<body>
<div id="wrap">
<h1><a style="color: black" href="http://marijnhaverbeke.nl/cl-javascript">CL-JavaScript</a></h1>
<p>JavaScript is the new BASIC—a universal scripting language.
CL-JavaScript allows you to add user scripting to your Common Lisp
application without requiring your poor users to learn Common Lisp.
It is a JavaScript to Common Lisp translator, runtime, and standard
library. We are <a href="http://bclary.com/2004/11/07/">ECMAScript
3</a> compatible, with some of the ECMAScript 5 extensions.</p>
<p>By using the Lisp compiler to compile JavaScript (and by using
some clever tricks for the things that Lisp normally isn't good at),
this implementation manages to be faster than most of the 2009
generation of JavaScript engines. The new generation (V8,
Jägermonkey) beats it by, depending on the benchmark, a factor 4 or
so.</p>
<h2>Contents</h2>
<ul>
<li><a href="#news">News</a></li>
<li><a href="#code">Code</a></li>
<li><a href="#dependencies">Dependencies</a></li>
<li><a href="#support">Support</a></li>
<li><a href="#quickstart">Quickstart</a></li>
<li><a href="#reference">Reference</a>
<ul>
<li><a href="#running">Running Code</a></li>
<li><a href="#values">JavaScript Values</a></li>
<li><a href="#exceptions">Exceptions</a></li>
<li><a href="#environment">The Environment</a></li>
<li><a href="#utilities">Utilities</a></li>
<li><a href="#deflib">Library Definition</a></li>
<li><a href="#provided">Provided Libraries</a></li>
</ul>
</li>
</ul>
<h2 id="news">News</h2>
<p class="news"><span>14-03-2012</span>: <strong><a href="http://marijnhaverbeke.nl/cl-javascript/cl-javascript-0.12.03.tgz">Version
0.12.03</a></strong>: Fix CLISP incompatibility.</p>
<p class="news"><span>09-01-2012</span>: <strong><a href="http://marijnhaverbeke.nl/cl-javascript/cl-javascript-0.12.01.tgz">Version
0.12.01</a></strong>: Follow changes
in <a href="http://marijnhaverbeke.nl/parse-js">parse-js</a>,
add <code>Function.prototype.bind</code>, getter/setter support,
small fixes.</p>
<p class="news"><span>08-12-2010</span>: <strong><a
href="http://marijnhaverbeke.nl/cl-javascript/cl-javascript-0.10.12.tgz">Version
0.10.12</a></strong>: Implements <a
href="http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf">ECMA5-style</a>
array, string, and <code>Object</code> constructor methods, as well
as a <code>JSON</code> object. Rough <a
href="#requirelib">support</a> for <a
href="http://www.commonjs.org/specs/modules/1.0/">CommonJS
modules</a>. Adds correct <code>length</code> (arity) properties to
function objects.</p>
<p class="news"><span>15-11-2010</span>: <strong><a
href="http://marijnhaverbeke.nl/cl-javascript/cl-javascript-0.10.11.tgz">Version
0.10.11</a></strong>: The first release on the new project page. Our
API can be considered more or less stable now, and there are no
serious gaps left in our ECMAScript 3 support.</p>
<p class="news"><span>15-11-2010</span>: It seems I have finally
documented this library.</p>
<h2 id="code">Code</h2>
<p>CL-JavaScript was created by Alan Pavičić, Iva Jurišić, and
Marijn Haverbeke. It is released under a <a href="LICENSE">MIT-style
licence</a>.</p>
<p>Development takes place on <a
href="http://github.com/akapav/js">github</a>. Any releases we make
are listed under <a href="#news">News</a>. The latest release is
always linked from <a
href="http://marijnhaverbeke.nl/cl-javascript/cl-javascript.tgz">cl-javascript.tgz</a>.</p>
<h2 id="dependencies">Dependencies</h2>
<p>CL-JavaScript depends on <a
href="http://marijnhaverbeke.nl/parse-js">parse-js</a>, <a
href="http://weitz.de/cl-ppcre/">CL-PPCRE</a>, and optionally <a
href="http://common-lisp.net/project/local-time/">local-time</a>
(you won't have a <code>Date</code> object if your ASDF can not find
local-time).</p>
<p>Because <em>emulating</em> IEEE 754 floating point special values
(NaN, Infinity) in software is painfully inefficient, CL-JavaScript
includes some non-portable code to directly use machine floats in
SBCL and Allegro Common Lisp. There is fallback code present for
other implementations, but since the developers don't develop on
those, that might not be very well tested. It is recommended, if you
really want to use the system on another implementation, to try and
add native float support for that implementation.</p>
<h2 id="support">Support</h2>
<p>When you have a problem, please either open an issue on <a
href="https://github.com/akapav/js/issues">github</a>, or send <a
href="mailto:marijnh@gmail.com">the maintainer</a> an e-mail.</p>
<h2 id="quickstart">Quickstart</h2>
<p>First, load the system:</p>
<pre>cl-user> (asdf:oos 'asdf:load-op :cl-js)
cl-user> (use-package :cl-js)</pre>
<p>We can start a JavaScript REPL to convince ourselves that yes, we
really do have JavaScript in our Common Lisp.</p>
<pre>cl-user> (js-repl)
JS repl (#q to quit)
> 1 + 1
2
> function fac(x) { return x <= 1 ? x : x * fac(x - 1); }
[object Object]
> fac(10)
3628800
> #q
cl-user></pre>
<p>Well, that seems to work. Next up: defining our own library.</p>
<pre>cl-user> (defparameter *mylib* (empty-lib))
cl-user> (add-to-lib *mylib*
(.func "plusOne" (x) (1+ (to-number x)))
(.object "numbers"
(.value "one" 1)
(.value "two" "2")))
cl-user> (with-js-env (*mylib*)
(run-js "plusOne(numbers.two)"))
3</pre>
<p>Note the <code>to-number</code> call. This will invoke
JavaScripts number-conversion. For a library like this, you are, of
course, better off just doing something like this:</p>
<pre>cl-user> (run-js "
function plusOne(x){return x + 1;}
var numbers = {one: 1, two: '2'};")</pre>
<p>But, in general, what you want to do is write <em>glue</em> code,
providing a JavaScript API for your application. For this, the
library does its best to provide a practical interface for defining
JavaScript environments.</p>
<h2 id="reference">Reference</h2>
<h3 id="running">Running Code</h3>
<p class="def" id="run-js"><span>function</span> run-js (code &key (compile t) wrap-parse-errors optimize)</p>
<p class="desc">Runs the given code. <code>code</code> can be a
string or a stream. <code>compile</code> and <code>optimize</code>
determine whether the code should be compiled, and if, whether it
should be optimized, before it is run. When
<code>wrap-parse-errors</code> is given, parse errors are wrapped in
<a href="#js-condition"><code>js-condition</code></a> objects, and
can be caught by JavaScript <code>catch</code> forms.</p>
<p class="def" id="run-js-file"><span>function</span> run-js-file (file &key (compile t) wrap-parse-errors optimize external-format)</p>
<p class="desc">Runs the code from the given file. The keyword
arguments are passed through to <a
href="#run-js"><code>run-js</code></a>, except for
<code>external-format</code>, which is passed to
<code>open</code>.</p>
<p class="def" id="js-repl"><span>function</span> js-repl (&key (handle-errors t))</p>
<p class="desc">Starts an interactive JavaScript REPL. If
<code>handle-errors</code> is <code>t</code>, all errors will be
caught and printed. If it is <code>nil</code>, all errors are let
through. If it has any other value, only errors of type <a
href="#js-condition"><code>js-condition</code></a> are handled and
printed.</p>
<h3 id="values">JavaScript Values</h3>
<p>Values in a JavaScript environment are represented as
follows:</p>
<p><code>null</code> and <code>undefined</code> are the Lisp
keywords <code>:null</code> and <code>:undefined</code>. The type
<code>js-null</code> is provided, which includes both these values.
<code>js-null</code> is also a predicate function (shortcut for
<code>(typep x 'js-null)</code>).</p>
<p>Booleans are Lisp booleans (<code>nil</code> and <code>t</code>).</p>
<p>Numbers are represented as Lisp numbers (integers and
double-floats). On implementations where no support for representing
NaN and Infinity as floats has been added, these are represented by
the values <code>:NaN</code>, <code>:Inf</code>, and
<code>:-Inf</code>. The <code>js-number</code> type helps abstract
this—matching only numbers on those implementations where no
keywords are needed, and both numbers and these three keywords on
others.</p>
<p>The macros <code>nan</code>, <code>infinity</code>, and
<code>-infinity</code> are provided to create special number values.
The predicate <code>is-nan</code> can be used to check whether a
value is NaN.</p>
<p>Strings are plain Lisp strings.</p>
<p>Objects are a custom struct type—<code>js-obj</code>. The
<code>js-func</code> and <code>js-array</code> types are subtypes of
this.</p>
<p class="def" id="js-obj"><span>function</span> js-obj (&optional prototype type)</p>
<p class="desc">Creates a JavaScript object. Optionally, a prototype
id (more about that <a href="#prototype">later</a>) or prototype
object, and a type (as
in <a href="#define-js-obj"><code>define-js-obj</code></a>) can be
given.</p>
<p class="def" id="js-prop"><span>function</span> js-prop (obj propname)</p>
<p class="desc">Retrieves a property from an object. A
<code>setf</code> variant is provided for setting properties.</p>
<p class="def" id="js-array"><span>function</span> js-array (vector)</p>
<p class="desc">Creates a new JavaScript array. <code>vector</code>
must be an adjustable vector with a fill pointer.</p>
<p class="def" id="js-array-length"><span>function</span> js-array-length (array)</p>
<p class="desc">Retrieve the length of a JavaScript array.</p>
<p class="def" id="js-aref"><span>function</span> js-aref (array index)</p>
<p class="desc">Access an element in an array. There is a
<code>setf</code> variant as well.</p>
<p class="def" id="js-call"><span>macro</span> js-call (func this &rest args)</p>
<p class="desc">Call a JavaScript function value.</p>
<p class="def" id="js-method"><span>macro</span> js-method (object name &rest args)</p>
<p class="desc">Call a method in a JavaScript object.</p>
<p class="def" id="js-func"><span>macro</span> js-func (args &body body)</p>
<p class="desc">Creates a JavaScript function object from a
<code>lambda</code>-like specification. Inside the body
<code>this</code> will be bound, in addition to the specified
arguments. The argument list is mangled to conform to JavaScript
calling conventions—each paramter will become optional, with an
implicit default of <code>:undefined</code>, unless you specify your
own default. A <code>&rest</code> clause is allowed, but
<code>&key</code> and <code>&optional</code> can't be
used.</p>
<h3 id="exceptions">Exceptions</h3>
<p>JavaScript exceptions are raised as Lisp conditions of the
<code>js-condition</code> type. A JavaScript <code>catch</code>
block will catch these (and only these).</p>
<p class="def" id="js-condition-value"><span>method</span> js-condition-value (condition)</p>
<p class="desc">Returns the JavaScript value associated with the
given condition.</p>
<p class="def" id="js-error"><span>function</span> js-error (type message &rest args)</p>
<p class="desc">Raises a JavaScript error (value of type
<code>Error</code>) . <code>type</code> must be prototype id
(<code>:error</code>, <code>:type-error</code>,
<code>:syntax-error</code>, <code>:range-error</code>,
<code>:uri-error</code>, and <code>:eval-error</code> are provided
by the standard lib). <code>message</code> can be a format string
into which <code>args</code> will be interpolated.</p>
<h3 id="environment">The Environment</h3>
<p class="def" id="env"><span>variable</span> *env*</p>
<p class="desc">The variable that holds the current environment.
Starts out unbound (though <a href="#run-js"><code>run-js</code></a>
and <a href="#js-repl"><code>js-repl</code></a> will give it a
default value automatically when they find it unbound).</p>
<p class="def" id="with-js-env"><span>macro</span> with-js-env ((&rest libraries) &body body)</p>
<p class="desc">Runs <code>body</code> with <a
href="#env"><code>*env*</code></a> bound to a fresh environment,
which was created by loading the standard library plus the given
libraries.</p>
<p class="def" id="create-env"><span>function</span> create-env (&rest libraries)</p>
<p class="desc">Creates a new environment, loading the given libraries.</p>
<p class="def" id="add-to-env"><span>function</span> add-to-env (env &rest libraries)</p>
<p class="desc">Extends <code>env</code> with the given libraries,
then returns it.</p>
<h3 id="utilities">Utilities</h3>
<p class="def" id="void"><span>macro</span> void (&body body)</p>
<p class="desc">Executes the body, returns
<code>:undefined</code>.</p>
<p class="def" id="to-string">
<span>function</span> to-string (value)<br/>
<span>function</span> to-number (value)<br/>
<span>function</span> to-integer (value)<br/>
<span>function</span> to-boolean (value)</p>
<p class="desc">Invokes the standard JavaScript type conversion
algorithm on the given value.</p>
<h3 id="deflib">Library Definition</h3>
<p>CL-JavaScript works with first-class libraries. These are
specifications of a set of variables, prototypes, and constructors
that can be instantiated into an environment to make their
definitions available there.</p>
<p class="def" id="empty-lib"><span>function</span> empty-lib (&optional name)</p>
<p class="desc">Returns a fresh, empty library specification object.
The name is only used for the printed representation of the object.</p>
<p class="def" id="add-to-lib"><span>macro</span> add-to-lib (lib &body body)</p>
<p class="desc">Add the definitions found in <code>body</code> to
the given library.</p>
<p>Defining the content of a library is done with a family of macros
starting with a period. These all take a <code>&body</code> in
which lists starting with a keyword can be used to set options. For
example:</p>
<pre>(.object "Math"
(:slot-default :noenum)
(.value "E" (exp 1)))</pre>
<p>Here, the <code>:slot-default</code> option is given, causing all
slots defined in the <code>Math</code> object to not be enumerable.</p>
<p>All defining forms that allow slots to be defined inside of them
accept the <code>:slot-default</code> option. All forms that define
slots accept the <code>:slot</code> option. Both of these expect a
list of keywords (<code>:enum</code>, <code>:noenum</code>,
<code>:ro</code>, <code>:rw</code>, <code>:del</code>,
<code>:nodel</code>) which specify slot properties (enumerabe,
read-only, and deletable). Properties that are not specified are
inherited from the context (as an under-the-covers special
variable). By default, properties are enumerable, read-write, and
deletable, except in prototypes, where they are not enumerable.</p>
<p class="def" id="prototype"><span>macro</span> .prototype (id &body body)</p>
<p class="desc">Creates a new prototype and associates it with the
given ID. All non-option forms appearing in the body are evaluated,
and can add properties to the prototpe. A <code>:parent</code>
option (which should hold a prototype-id) can be used to make this
prototype inherit from another prototype.</p>
<p class="def" id="constructor"><span>macro</span> .constructor (name args &body body)</p>
<p class="desc">Declares a constructor with the given argument list
(interpreted as in <a href="#js-func"><code>js-func</code></a>) and
body. A <code>:prototype</code> option may appear in the body, and
is used to determine what prototype objects created with this
constructor should get. If it holds a keyword, that is the ID of the
prototype to use, if it holds a list of slot definitions, a new prototype
object is created and given those slots.</p>
<p class="desc">If this constructor should not create regular
objects, you can give it a <code>:type</code> option containing the
name of a type defined with <a
href="#define-js-obj"><code>define-js-obj</code></a>. When the
constructor is invoked with <code>new</code>, you will then get an
object of that type as <code>this</code> variable, rather than a
plain object.</p>
<p class="desc">Finally, a <code>:properties</code> option can be
passed, within which properties for the constructor itself can be
defined (as in <code>String.fromCharCode</code>).</p>
<p class="def" id="value"><span>macro</span> .value (name &body value)</p>
<p class="desc">Defines a simple value property. When this appears
at the top level, it defines a global variable. When it appears
inside another form, it adds a property to that definition.</p>
<p class="def" id="object"><span>macro</span> .object (name &body body)</p>
<p class="desc">This defines an object property. The
<code>body</code> contains property definitons for this object, and
optionally a <code>:parent</code> option, as in <a
href="#prototype"><code>.prototype</code></a>, to give the object a
specific prototype.</p>
<p class="def" id="func"><span>macro</span> .func (name args &body body)</p>
<p class="desc">Adds a function (top-level) or method.
<code>args</code> is an argument list as in <a
href="#js-func"><code>js-func</code></a>. The given body becomes the
body of the function. A <code>:properties</code> option can be used
to give the function object itself properties.</p>
<p class="def" id="active"><span>macro</span> .active (name &body body)</p>
<p class="desc">This macro is used to add 'active' properties to
objects. Active properties are things that can be approached like
regular properties, but execute some function when read or written.
The <code>:read</code> and <code>:write</code> options can be used
to specify the bodies of the functions, like this:</p>
<pre class="desc">(.active "preciousProperty"
(:read () "my precious!")
(:write (value) (js-error :error "How dare you touch my precious!")))</pre>
<p class="desc">(The argument lists are compulsory, even though they are always
the same.)</p>
<p class="def" id="active-r"><span>macro</span> .active-r (name &body body)</p>
<p class="desc">This is a shortcut for an <a
href="#active"><code>.active</code></a> property with only a
<code>:read</code> entry (meaning writes to the slot will be
ignored).</p>
<p>The following two macros should not be used inside library
definitions, but at the top level (they are global in their
effect).</p>
<p class="def" id="define-js-obj"><span>macro</span> define-js-obj (name &body slots)</p>
<p class="desc">Defines a struct type fit for holding JavaScript
object values. The way to use this is to specify the type name you
use here as the <code>:type</code> option of a <a
href="#constructor"><code>.constructor</code></a> form, and then
fill in your custom slots in this constructor.</p>
<p class="def" id="integrate-type"><span>macro</span> integrate-type (specializer &body options)</p>
<p class="desc">A type defined by <a
href="#define-js-obj"><code>define-js-obj</code></a> is a 'real'
JavaScript object, to which clients can add properties. Sometimes,
it is preferable to use Lisp objects 'as they are', because wrapping
is too expensive. This macro allows you to do that.</p>
<p class="desc">To be able to use a value as a JavaScript value, a
bunch of methods have to specialized on it, so that JavaScript
operations (<code>typeof</code>, <code>String(x)</code>) will know
what to do with it.</p>
<p class="desc"><code>specializer</code> should be a valid method
specializer that can be used to recognize the type you want to
integrate.</p>
<p class="desc">All options appearing under this macro can take
either the form of a single value, or an argument list (of a single
symbol) and then a body. The <code>:string</code> option determines
how the type is converted to string (default is <code>"[object
Object]"</code>). The <code>:number</code> option converts to
numbers (default <code>NaN</code>). The <code>:boolean</code> option
to booleans (default <code>true</code>). <code>typeof</code> is used
to determine the string returned by the <code>typeof</code> operator
(default <code>"foreign"</code>). When a <code>:proto-id</code> form
is given, it is used to locate a prototype in which properties for
these values are looked up.</p>
<p class="desc">An example:</p>
<pre class="desc">(integrate-type complex
(:number (val) (realpart val))
(:string (val) (format nil "~a+~ai" (realpart val) (imagpart val)))
(:typeof "complex")
(:proto-id :number)) ;; or add a custom prototype
/* ... and in your library ... */
(.func "complex" (real imag)
(complex (to-number real) (to-number imag)))</pre>
<h3 id="provided">Provided Libraries</h3>
<p class="def" id="printlib"><span>variable</span> *printlib*</p>
<p class="desc">A tiny library value containing only a
<code>print</code> function, which will write its arguments to
<code>*standard-output*</code>.</p>
<p class="def" id="requirelib"><span>function</span> requirelib (hook)</p>
<p class="desc">When called, returns a library object that
implements the CommonJS-style <code>require</code> operator.
<code>hook</code> should be a funcallable object which, given a
string, verifies that string as a module specifier, and returns a
pathname under which the module text can be found. Or, if you need
modules that aren't simply files, it can return two values—a
canonical module identifier (must be comparable with
<code>equal</code>) and a function that, given this identifier,
returns either a stream or a string containing the module's
text.</p>
<p class="desc">A trivial hook (without error-checking or safety)
could simply do <code>(merge-pathnames spec
"/my/script/dir/x.js")</code>. If you do want to do error-checking,
use <a href="#js-error"><code>js-error</code></a> to complain when a
specifier is not acceptable.</p>
<p class="desc">Note that CL-JavaScript's implementation of CommonJS
modules does not sandbox the modules in any serious way—it simply
wraps them in a function. This means that direct,
<code>var</code>-less assignments <em>will</em> create top-level
variables, and the module can mangle existing values (say,
<code>Object.prototype</code>) all it wants. For well-behaved
modules, this shouldn't be an issue.</p>
</div>
</body></html>