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