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