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