3 [![Build Status](https://travis-ci.org/kanaka/mal.svg?branch=master)](https://travis-ci.org/kanaka/mal)
7 Mal is a Clojure inspired Lisp interpreter.
9 Mal is implemented in 48 languages:
23 * ES6 (ECMAScript 6 / ECMAScript 2015)
33 * JavaScript ([Online Demo](http://kanaka.github.io/mal))
40 * [miniMAL](https://github.com/kanaka/miniMAL)
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).
67 The mal (make a lisp) steps are:
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)
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).
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.
93 ## Building/running implementations
97 *The GNU awk implementation was created by [Miutsuru kariya](https://github.com/kariya-mitsuru)*
99 The GNU awk implementation of mal has been tested with GNU awk 4.1.1.
103 gawk -O -f stepX_YYY.awk
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.
126 *The C++ implementation was created by [Stephen Thirlwall (sdt)](https://github.com/sdt)*
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
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.
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.
161 lein with-profile +stepX trampoline run
167 sudo npm install -g coffee-script
174 *The Crystal implementation of mal was created by [Linda_pp](https://github.com/rhysd)*
176 The Crystal implementation of mal has been tested with Crystal 0.10.0.
180 crystal run ./stepX_YYY.cr
182 make # needed to run tests
188 *The D implementation was created by [Dov Murik](https://github.com/dubek)*
190 The D implementation of mal was tested with GDC 4.8. It requires the GNU
201 *The Emacs Lisp implementation was created by [Vasilij Schneidermann](https://github.com/wasamasa)*
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
210 emacs -Q --batch --load stepX_YYY.el
211 # with full readline support
212 rlwrap emacs -Q --batch --load stepX_YYY.el
217 *The Elixir implementation was created by [Martin Ek (ekmartin)](https://github.com/ekmartin)*
219 The Elixir implementation of mal has been tested with Elixir 1.0.5.
224 # Or with readline/line editing functionality:
230 *The Erlang implementation was created by [Nathan Fiedler (nlfiedler)](https://github.com/nlfiedler)*
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.
239 MAL_STEP=stepX_YYY rebar compile escriptize # build individual step
243 ### ES6 (ECMAScript 6 / ECMAScript 2015)
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.
252 node build/stepX_YYY.js
258 *The F# implementation was created by [Peter Stephens (pstephens)](https://github.com/pstephens)*
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.
273 *The Factor implementation was created by [Jordan Lewis (jordanlewis)](https://github.com/jordanlewis)*
275 The Factor implementation of mal has been tested with Factor 0.97
276 ([factorcode.org](factorcode.org)).
280 FACTOR_ROOTS=. factor -run=stepX_YYY
285 *The Forth implementation was created by [Chris Houser (chouser)](https://github.com/chouser)*
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.
306 The Groovy implementation of mal requires Groovy to run and has been
307 tested with Groovy 1.8.6.
312 groovy ./stepX_YYY.groovy
317 *The Guile implementation was created by [Mu Lei (NalaGinrut)](https://github.com/NalaGinrut).*
321 guile -L ./ stepX_YYY.scm
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
339 The Haxe implementation of mal requires Haxe version 3.2 to compile.
340 Four different Haxe targets are supported: Neko, Python, C++, and
350 python3 ./stepX_YYY.py
362 The Java implementation of mal requires maven2 to build.
367 mvn -quiet exec:java -Dexec.mainClass=mal.stepX_YYY
369 mvn -quiet exec:java -Dexec.mainClass=mal.stepX_YYY -Dexec.args="CMDLINE_ARGS"
382 The Julia implementation of mal requires Julia 0.4.
391 *The Kotlin implementation was created by [Javier Fernandez-Ivern](https://github.com/ivern)*
393 The Kotlin implementation of mal has been tested with Kotlin 1.0.
398 java -jar stepX_YYY.jar
403 Running the Lua implementation of mal requires lua 5.1 or later,
404 luarocks and the lua-rex-pcre library installed.
408 make # to build and link linenoise.so
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
420 IMPL_STEPA_CMD ../mal/stepX_YYY.mal
433 *The Nim implementation was created by [Dennis Felsing (def-)](https://github.com/def-)*
435 Running the Nim implementation of mal requires Nim 0.11.0 or later.
447 The Objective C implementation of mal has been built and tested on
448 Linux using clang/LLVM 3.6.
458 *The OCaml implementation was created by [Chris Houser (chouser)](https://github.com/chouser)*
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
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;"
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).
489 # Download miniMAL and dependencies
491 export PATH=`pwd`/node_modules/minimal-lisp/:$PATH
492 # Now run mal implementation in miniMAL
498 For readline line editing support, install Term::ReadLine::Perl or
499 Term::ReadLine::Gnu from CPAN.
509 The PHP implementation of mal requires the php command line interface
517 ### Postscript Level 2/3
519 The Postscript implementation of mal requires ghostscript to run. It
520 has been tested with ghostscript 9.10.
524 gs -q -dNODISPLAY -I./ stepX_YYY.ps
527 ### Python (2.X or 3.X)
536 You must have [rpython](https://rpython.readthedocs.org/) on your path
537 (included with [pypy](https://bitbucket.org/pypy/pypy/)).
541 make # this takes a very long time
547 The R implementation of mal requires R (r-base-core) to run.
551 make libs # to download and build rdyncall
557 The Racket implementation of mal requires the Racket
558 compiler/interpreter to run.
572 ### Rust (1.0.0 nightly)
574 The rust implementation of mal requires the rust compiler and build
575 tool (cargo) to build.
579 cargo run --release --bin stepX_YYY
584 Install scala and sbt (http://www.scala-sbt.org/0.13/tutorial/Installing-sbt-on-Linux.html):
588 sbt 'run-main stepX_YYY'
591 scala -classpath target/scala*/classes stepX_YYY
596 *The Swift implementation was created by [Keith Rollin](https://github.com/keith-rollin)*
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.
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
622 *The Tcl implementation was created by [Dov Murik](https://github.com/dubek)*
624 The Tcl implementation of mal requires Tcl 8.6 to run. For readline line
625 editing support, install tclreadline.
629 tclsh ./stepX_YYY.tcl
634 *The Vimscript implementation was created by [Dov Murik](https://github.com/dubek)*
636 The Vimscript implementation of mal requires Vim to run. It has been tested
641 ./run_vimscript.sh ./stepX_YYY.vim
644 ### Visual Basic.NET ###
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.
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.
669 To simplify the process of running tests, a top level Makefile is
670 provided with convenient test targets.
672 * To run all the tests across all implementations (be prepared to wait):
678 * To run all tests against a single implementation:
688 * To run tests for a single step against all implementations:
698 * To run tests for a specific step against a single implementation:
701 make "test^IMPL^stepX"
704 make "test^ruby^step3"
708 ### Self-hosted functional tests
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):
714 make MAL_IMPL=IMPL "test^mal^step2"
717 make "test^mal^step2" # js is default
718 make MAL_IMPL=ruby "test^mal^step2"
719 make MAL_IMPL=python "test^mal^step2"
722 ### Starting the REPL
724 * To start the REPL of an implementation in a specific step:
727 make "repl^IMPL^stepX"
730 make "repl^ruby^step3"
734 * If you omit the step, then `stepA` is used:
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):
748 make MAL_IMPL=IMPL "repl^mal^stepX"
751 make "repl^mal^step2" # js is default
752 make MAL_IMPL=ruby "repl^mal^step2"
753 make MAL_IMPL=python "repl^mal"
756 ### Performance tests
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.
764 * To run performance tests against a single implementation:
772 * To run performance tests against all implementations:
777 ### Generating language statistics
779 * To report line and byte statistics for a single implementation:
787 * To report line and bytes statistics for general Lisp code (env, core
790 make "stats-lisp^IMPL"
796 ## Docker test environment
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).
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:
806 ./tests/docker-build.sh
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:
814 ./tests/docker-run.sh
817 You can also specify a command to run within the container. For
818 example, to run step2 tests for every implementation (except MATLAB):
820 ./tests/docker-run.sh make SKIP_IMPLS="matlab" "test^step2"
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
837 Mal (make-a-lisp) is licensed under the MPL 2.0 (Mozilla Public
838 License 2.0). See LICENSE.txt for more details.