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