merge upstream
[jackhill/mal.git] / README.md
1 # mal - Make a Lisp
2
3 ## Description
4
5 Mal is a Clojure inspired Lisp interpreter.
6
7 Mal is implemented in 31 different languages:
8
9 * Bash shell
10 * C
11 * C++
12 * C#
13 * Clojure
14 * CoffeeScript
15 * Factor
16 * Forth
17 * Go
18 * Haskell
19 * Java
20 * JavaScript ([Online Demo](http://kanaka.github.io/mal))
21 * Julia
22 * Lua
23 * GNU Make
24 * mal itself
25 * MATLAB
26 * [miniMAL](https://github.com/kanaka/miniMAL)
27 * Nim
28 * OCaml
29 * Perl
30 * PHP
31 * Postscript
32 * Python
33 * R
34 * Racket
35 * Ruby
36 * Rust
37 * Scala
38 * Swift
39 * Visual Basic.NET
40
41
42 Mal is a learning tool. See the [make-a-lisp process
43 guide](process/guide.md). Each implementation of mal is separated into
44 11 incremental, self-contained (and testable) steps that demonstrate
45 core concepts of Lisp. The last step is capable of self-hosting
46 (running the mal implementation of mal).
47
48 The mal (make a lisp) steps are:
49
50 * [step0_repl](process/guide.md#step0)
51 * [step1_read_print](process/guide.md#step1)
52 * [step2_eval](process/guide.md#step2)
53 * [step3_env](process/guide.md#step3)
54 * [step4_if_fn_do](process/guide.md#step4)
55 * [step5_tco](process/guide.md#step5)
56 * [step6_file](process/guide.md#step6)
57 * [step7_quote](process/guide.md#step7)
58 * [step8_macros](process/guide.md#step8)
59 * [step9_try](process/guide.md#step9)
60 * [stepA_mal](process/guide.md#stepA)
61
62
63 Mal was presented publicly for the first time in a lightning talk at
64 Clojure West 2014 (unfortunately there is no video). See
65 mal/clojurewest2014.mal for the presentation that was given at the
66 conference (yes the presentation is a mal program).
67
68 If you are interesting in creating a mal implementation (or just
69 interested in using mal for something), please drop by the #mal
70 channel on freenode. In addition to the [make-a-lisp process
71 guide](process/guide.md) there is also a [mal/make-a-lisp
72 FAQ](docs/FAQ.md) where I attempt to answer some common questions.
73
74 ## Building/running implementations
75
76 ### Bash 4
77
78 ```
79 cd bash
80 bash stepX_YYY.sh
81 ```
82
83 ### C
84
85 The C implementation of mal requires the following libraries (lib and
86 header packages): glib, libffi6 and either the libedit or GNU readline library.
87
88 ```
89 cd c
90 make
91 ./stepX_YYY
92 ```
93
94 ### C++
95
96 *The C++ implementation was created by [Stephen Thirlwall (sdt)](https://github.com/sdt)*
97
98 The C++ implementation of mal requires g++-4.9 or clang++-3.5 and
99 a readline compatible library to build. See the `cpp/README.md` for
100 more details:
101
102 ```
103 cd cpp
104 make
105 # OR
106 make CXX=clang++-3.5
107 ./stepX_YYY
108 ```
109
110
111 ### C# ###
112
113 The C# implementation of mal has been tested on Linux using the Mono
114 C# compiler (mcs) and the Mono runtime (version 2.10.8.1). Both are
115 required to build and run the C# implementation.
116
117 ```
118 cd cs
119 make
120 mono ./stepX_YYY.exe
121 ```
122
123
124 ### Clojure
125
126 ```
127 cd clojure
128 lein with-profile +stepX trampoline run
129 ```
130
131 ### CoffeeScript
132
133 ```
134 sudo npm install -g coffee-script
135 cd coffee
136 coffee ./stepX_YYY
137 ```
138
139 ### Factor
140
141 *The Factor implementation was created by [Jordan Lewis (jordanlewis)](https://github.com/jordanlewis)*
142
143 The Factor implementation of mal has been tested with Factor 0.97
144 ([factorcode.org](factorcode.org)).
145
146 ```
147 cd factor
148 FACTOR_ROOTS=src factor -run=stepX_YYY
149 ```
150
151 ### Forth
152
153 *The Forth implementation was created by [Chris Houser (chouser)](https://github.com/chouser)*
154
155 ```
156 cd forth
157 gforth stepX_YYY.fs
158 ```
159
160 ### Go
161
162 The Go implementation of mal requires that go is installed on on the
163 path. The implementation has been tested with Go 1.3.1.
164
165 ```
166 cd go
167 make
168 ./stepX_YYY
169 ```
170
171
172 ### Haskell
173
174 Install the Haskell compiler (ghc/ghci), the Haskell platform and
175 either the editline package (BSD) or the readline package (GPL). On
176 Ubuntu these packages are: ghc, haskell-platform,
177 libghc-readline-dev/libghc-editline-dev
178
179 ```
180 cd haskell
181 make
182 ./stepX_YYY
183 ```
184
185
186 ### Java 1.7
187
188 The Java implementation of mal requires maven2 to build.
189
190 ```
191 cd java
192 mvn compile
193 mvn -quiet exec:java -Dexec.mainClass=mal.stepX_YYY
194 # OR
195 mvn -quiet exec:java -Dexec.mainClass=mal.stepX_YYY -Dexec.args="CMDLINE_ARGS"
196 ```
197
198 ### JavaScript/Node
199
200 ```
201 cd js
202 npm update
203 node stepX_YYY.js
204 ```
205
206 ### Julia
207
208 The Julia implementation of mal has been tested with Julia 0.3.7.
209
210 ```
211 cd julia
212 julia stepX_YYY.jl
213 ```
214
215 ### Lua
216
217 Running the Lua implementation of mal requires lua 5.1 or later,
218 luarocks and the lua-rex-pcre library installed.
219
220 ```
221 cd lua
222 make # to build and link linenoise.so
223 ./stepX_YYY.lua
224 ```
225
226 ### Mal
227
228 Running the mal implementation of mal involves running stepA of one of
229 the other implementations and passing the mal step to run as a command
230 line argument.
231
232 ```
233 cd IMPL
234 IMPL_STEPA_CMD ../mal/stepX_YYY.mal
235
236 ```
237
238 ### GNU Make 3.81
239
240 ```
241 cd make
242 make -f stepX_YYY.mk
243 ```
244
245 ### Nim 0.10.3
246
247 *The Nim implementation was created by [Dennis Felsing (def-)](https://github.com/def-)*
248
249 Running the Nim implementation of mal requires Nim's current devel branch
250 (0.10.3) or later, and the nre library installed.
251
252 ```
253 cd nim
254 make
255 # OR
256 nimble build
257 ./stepX_YYY
258 ```
259
260 ### OCaml 4.01.0
261
262 *The OCaml implementation was created by [Chris Houser (chouser)](https://github.com/chouser)*
263
264 ```
265 cd ocaml
266 make
267 ./stepX_YYY
268 ```
269
270 ### MATLAB
271
272 The MATLAB implementation of mal has been tested with MATLAB version
273 R2014a on Linux. Note that MATLAB is a commercial product. It should
274 be fairly simple to support GNU Octave once it support classdef object
275 syntax.
276
277 ```
278 cd matlab
279 ./stepX_YYY
280 matlab -nodisplay -nosplash -nodesktop -nojvm -r "stepX_YYY();quit;"
281 # OR with command line arguments
282 matlab -nodisplay -nosplash -nodesktop -nojvm -r "stepX_YYY('arg1','arg2');quit;"
283 ```
284
285 ### miniMAL
286
287 [miniMAL](https://github.com/kanaka/miniMAL) is small Lisp interpreter
288 implemented in less than 1024 bytes of JavaScript. To run the miniMAL
289 implementation of mal you need to download/install the miniMAL
290 interpreter (which requires Node.js).
291 ```
292 cd miniMAL
293 # Download miniMAL and dependencies
294 npm install
295 export PATH=`pwd`/node_modules/minimal-lisp/:$PATH
296 # Now run mal implementation in miniMAL
297 miniMAL ./stepX_YYY
298 ```
299
300 ### Perl 5.8
301
302 For readline line editing support, install Term::ReadLine::Perl or
303 Term::ReadLine::Gnu from CPAN.
304
305 ```
306 cd perl
307 perl stepX_YYY.pl
308 ```
309
310
311 ### PHP 5.3
312
313 The PHP implementation of mal requires the php command line interface
314 to run.
315
316 ```
317 cd php
318 php stepX_YYY.php
319 ```
320
321 ### Postscript Level 2/3
322
323 The Postscript implementation of mal requires ghostscript to run. It
324 has been tested with ghostscript 9.10.
325
326 ```
327 cd ps
328 gs -q -dNODISPLAY -I./ stepX_YYY.ps
329 ```
330
331 ### Python (2 or 3)
332
333 ```
334 cd python
335 python stepX_YYY.py
336 ```
337
338 ### R
339
340 The R implementation of mal requires R (r-base-core) to run.
341
342 ```
343 cd r
344 make libs # to download and build rdyncall
345 Rscript stepX_YYY.r
346 ```
347
348 ### Racket (5.3)
349
350 The Racket implementation of mal requires the Racket
351 compiler/interpreter to run.
352
353 ```
354 cd racket
355 ./stepX_YYY.rkt
356 ```
357
358 ### Ruby (1.9+)
359
360 ```
361 cd ruby
362 ruby stepX_YYY.rb
363 ```
364
365 ### Rust (1.0.0 nightly)
366
367 The rust implementation of mal requires the rust compiler and build
368 tool (cargo) to build.
369
370 ```
371 cd rust
372 cargo run --release --bin stepX_YYY
373 ```
374
375 ### Scala ###
376
377 Install scala and sbt (http://www.scala-sbt.org/0.13/tutorial/Installing-sbt-on-Linux.html):
378
379 ```
380 cd scala
381 sbt 'run-main stepX_YYY'
382 # OR
383 sbt compile
384 scala -classpath target/scala*/classes stepX_YYY
385 ```
386
387 ### Swift
388
389 *The Swift implementation was created by [Keith Rollin](https://github.com/keith-rollin)*
390
391 The Swift implemenation of mal requires the Swift compiler (XCode) to
392 build.
393
394 ```
395 cd swift
396 make
397 ./stepX_YYY
398 ```
399
400 ### Visual Basic.NET ###
401
402 The VB.NET implementation of mal has been tested on Linux using the Mono
403 VB compiler (vbnc) and the Mono runtime (version 2.10.8.1). Both are
404 required to build and run the VB.NET implementation.
405
406 ```
407 cd vb
408 make
409 mono ./stepX_YYY.exe
410 ```
411
412
413
414 ## Running tests
415
416 ### Functional tests
417
418 The are nearly 500 generic functional tests (for all implementations)
419 in the `tests/` directory. Each step has a corresponding test file
420 containing tests specific to that step. The `runtest.py` test harness
421 launches a Mal step implementation and then feeds the tests one at
422 a time to the implementation and compares the output/return value to
423 the expected output/return value.
424
425 To simplify the process of running tests, a top level Makefile is
426 provided with convenient test targets.
427
428 * To run all the tests across all implementations (be prepared to wait):
429
430 ```
431 make test
432 ```
433
434 * To run all tests against a single implementation:
435
436 ```
437 make test^IMPL
438
439 # e.g.
440 make test^clojure
441 make test^js
442 ```
443
444 * To run tests for a single step against all implementations:
445
446 ```
447 make test^stepX
448
449 # e.g.
450 make test^step2
451 make test^step7
452 ```
453
454 * To run tests for a specifc step against a single implementation:
455
456 ```
457 make test^IMPL^stepX
458
459 # e.g
460 make test^ruby^step3
461 make test^ps^step4
462 ```
463
464 ### Self-hosted functional tests
465
466 * To run the functional tests in self-hosted mode, you specify `mal`
467 as the test implementation and use the `MAL_IMPL` make variable
468 to change the underlying host language (default is JavaScript):
469 ```
470 make MAL_IMPL=IMPL test^mal^step2
471
472 # e.g.
473 make test^mal^step2 # js is default
474 make MAL_IMPL=ruby test^mal^step2
475 make MAL_IMPL=python test^mal^step2
476 ```
477
478
479 ### Performance tests
480
481 Warning: These performance tests are neither statistically valid nor
482 comprehensive; runtime performance is a not a primary goal of mal. If
483 you draw any serious conclusions from these performance tests, then
484 please contact me about some amazing oceanfront property in Kansas
485 that I'm willing to sell you for cheap.
486
487 * To run performance tests against a single implementation:
488 ```
489 make perf^IMPL
490
491 # e.g.
492 make perf^js
493 ```
494
495 * To run performance tests against all implementations:
496 ```
497 make perf
498 ```
499
500 ### Generating language statistics
501
502 * To report line and byte stastics for a single implementation:
503 ```
504 make stats^IMPL
505
506 # e.g.
507 make stats^js
508 ```
509
510 * To report line and bytes stastics for general Lisp code (env, core
511 and stepA):
512 ```
513 make stats-lisp^IMPL
514
515 # e.g.
516 make stats-lisp^js
517 ```
518
519 ## Docker test environment
520
521 There is a Dockerfile included in the `tests/docker` directory that
522 builds a docker image based on Ubuntu Utopic that contains everything
523 needed to run tests against all the implementations (except for MATLAB
524 which is proprietary/licensed).
525
526 Build the the docker image using a provided script. WARNING: this will
527 likely take over an hour to build from scratch and use more 3 GB of disk:
528 ```bash
529 ./tests/docker-build.sh
530 ```
531
532 Launch a docker container from that image built above. This will
533 volume mount the mal directory to `/mal` and then give you a bash
534 prompt in the container. You can then run individual mal
535 implementations and tests:
536 ```bash
537 ./tests/docker-run.sh
538 ```
539
540 You can also specify a command to run within the container. For
541 example, to run step2 tests for every implementation (except MATLAB):
542 ```bash
543 ./tests/docker-run.sh make SKIP_IMPLS="matlab" test^step2
544 ```
545
546 **Notes**:
547 * JVM-based language implementations (Java, Clojure, Scala): you will
548 need to run these implementations once manually first before you can
549 run tests because runtime dependencies need to be downloaded to
550 avoid the tests timing out. These dependencies are download to
551 dot-files in the /mal directory so they will persist between runs.
552 * Compiled languages: if your host system is different enough from
553 Ubuntu Utopic then you may need to re-compile your compiled
554 languages from within the container to avoid linker version
555 mismatches.
556
557
558 ## License
559
560 Mal (make-a-lisp) is licensed under the MPL 2.0 (Mozilla Public
561 License 2.0). See LICENSE.txt for more details.
562