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 68 languages:
14 * BASIC (C64 and QBasic)
29 * ES6 (ECMAScript 6 / ECMAScript 2015)
41 * JavaScript ([Online Demo](http://kanaka.github.io/mal))
50 * [miniMAL](https://github.com/kanaka/miniMAL)
81 Mal is a learning tool. See the [make-a-lisp process
82 guide](process/guide.md). Each implementation of mal is separated into
83 11 incremental, self-contained (and testable) steps that demonstrate
84 core concepts of Lisp. The last step is capable of self-hosting
85 (running the mal implementation of mal).
87 The mal (make a lisp) steps are:
89 * [step0_repl](process/guide.md#step0)
90 * [step1_read_print](process/guide.md#step1)
91 * [step2_eval](process/guide.md#step2)
92 * [step3_env](process/guide.md#step3)
93 * [step4_if_fn_do](process/guide.md#step4)
94 * [step5_tco](process/guide.md#step5)
95 * [step6_file](process/guide.md#step6)
96 * [step7_quote](process/guide.md#step7)
97 * [step8_macros](process/guide.md#step8)
98 * [step9_try](process/guide.md#step9)
99 * [stepA_mal](process/guide.md#stepA)
102 Mal was presented publicly for the first time in a lightning talk at
103 Clojure West 2014 (unfortunately there is no video). See
104 examples/clojurewest2014.mal for the presentation that was given at the
105 conference (yes the presentation is a mal program). At Midwest.io
106 2015, Joel Martin gave a presentation on Mal titled "Achievement
107 Unlocked: A Better Path to Language Learning".
108 [Video](https://www.youtube.com/watch?v=lgyOAiRtZGw),
109 [Slides](http://kanaka.github.io/midwest.io.mal/). More recently
110 Joel gave a presentation on "Make Your Own Lisp Interpreter in
111 10 Incremental Steps" at LambdaConf 2016: [Part
112 1](https://www.youtube.com/watch?v=jVhupfthTEk), [Part
113 2](https://www.youtube.com/watch?v=X5OQBMGpaTU),
114 [Slides](http://kanaka.github.io/lambdaconf/).
116 If you are interesting in creating a mal implementation (or just
117 interested in using mal for something), please drop by the #mal
118 channel on freenode. In addition to the [make-a-lisp process
119 guide](process/guide.md) there is also a [mal/make-a-lisp
120 FAQ](docs/FAQ.md) where I attempt to answer some common questions.
122 ## Building/running implementations
124 The simplest way to run any given implementation is to use docker.
125 Every implementation has a docker image pre-built with language
126 dependencies installed. You can launch the REPL using a convenience
127 target in the top level Makefile (where IMPL is the implementation
128 directory name and stepX is the step to run):
131 make DOCKERIZE=1 "repl^IMPL^stepX"
132 # OR stepA is the default step:
133 make DOCKERIZE=1 "repl^IMPL"
139 *The Ada implementation was created by [Chris Moore](https://github.com/zmower)*
141 The Ada implementation was developed with GNAT 4.9 on debian. It also
142 compiles unchanged on windows if you have windows versions of git,
143 GNAT and (optionally) make. There are no external dependencies
144 (readline not implemented).
154 *The GNU awk implementation was created by [Miutsuru kariya](https://github.com/kariya-mitsuru)*
156 The GNU awk implementation of mal has been tested with GNU awk 4.1.1.
160 gawk -O -f stepX_YYY.awk
170 ### BASIC (C64 and QBasic)
172 The BASIC implementation uses a preprocessor that can generate BASIC
173 code that is compatible with both C64 BASIC (CBM v2) and QBasic. The
174 C64 mode has been tested with
175 [cbmbasic](https://github.com/kanaka/cbmbasic) (the patched version is
176 currently required to fix issues with line input) and the QBasic mode
177 has been tested with [qb64](http://www.qb64.net/).
179 Generate C64 code and run it using cbmbasic:
187 Generate QBasic code and load it into qb64:
191 make MODE=qbasic stepX_YYY.bas
195 Thanks to [Steven Syrek](https://github.com/sjsyrek) for the original
196 inspiration for this implementation.
201 The C implementation of mal requires the following libraries (lib and
202 header packages): glib, libffi6, libgc, and either the libedit or GNU readline
213 *The C++ implementation was created by [Stephen Thirlwall (sdt)](https://github.com/sdt)*
215 The C++ implementation of mal requires g++-4.9 or clang++-3.5 and
216 a readline compatible library to build. See the `cpp/README.md` for
230 The C# implementation of mal has been tested on Linux using the Mono
231 C# compiler (mcs) and the Mono runtime (version 2.10.8.1). Both are
232 required to build and run the C# implementation.
242 *The ChucK implementation was created by [Vasilij Schneidermann](https://github.com/wasamasa)*
244 The ChucK implementation has been tested with ChucK 1.3.5.2.
253 *The Common Lisp implementation was created by [Iqbal Ansari](https://github.com/iqbalansari)*
255 The implementation has been tested with SBCL, CCL, CMUCL, GNU CLISP, ECL and
256 Allegro CL on Ubuntu 16.04 and Ubuntu 12.04, see
257 the [README][common-lisp/README.org] for more details. Provided you have the
258 dependencies mentioned installed, do the following to run the implementation
268 For the most part the Clojure implementation requires Clojure 1.5,
269 however, to pass all tests, Clojure 1.8.0-RC4 is required.
273 lein with-profile +stepX trampoline run
279 sudo npm install -g coffee-script
286 *The Crystal implementation of mal was created by [Linda_pp](https://github.com/rhysd)*
288 The Crystal implementation of mal has been tested with Crystal 0.18.4.
292 crystal run ./stepX_YYY.cr
294 make # needed to run tests
300 *The D implementation was created by [Dov Murik](https://github.com/dubek)*
302 The D implementation of mal was tested with GDC 4.8. It requires the GNU
313 *The Dart implementation was created by [Harry Terkelsen](https://github.com/hterkelsen)*
315 The Dart implementation has been tested with Dart 1.20.
324 *The Emacs Lisp implementation was created by [Vasilij Schneidermann](https://github.com/wasamasa)*
326 The Emacs Lisp implementation of mal has been tested with Emacs 24.3
327 and 24.5. While there is very basic readline editing (`<backspace>`
328 and `C-d` work, `C-c` cancels the process), it is recommended to use
333 emacs -Q --batch --load stepX_YYY.el
334 # with full readline support
335 rlwrap emacs -Q --batch --load stepX_YYY.el
340 *The Elixir implementation was created by [Martin Ek (ekmartin)](https://github.com/ekmartin)*
342 The Elixir implementation of mal has been tested with Elixir 1.0.5.
347 # Or with readline/line editing functionality:
353 *The Elm implementation was created by [Jos van Bakel](https://github.com/c0deaddict)*
355 The Elm implementation of mal has been tested with Elm 0.18.0
365 *The Erlang implementation was created by [Nathan Fiedler (nlfiedler)](https://github.com/nlfiedler)*
367 The Erlang implementation of mal requires [Erlang/OTP R17](http://www.erlang.org/download.html)
368 and [rebar](https://github.com/rebar/rebar) to build.
374 MAL_STEP=stepX_YYY rebar compile escriptize # build individual step
378 ### ES6 (ECMAScript 6 / ECMAScript 2015)
380 The ES6 implementation uses the [babel](https://babeljs.io) compiler
381 to generate ES5 compatible JavaScript. The generated code has been
382 tested with Node 0.12.4.
387 node build/stepX_YYY.js
393 *The F# implementation was created by [Peter Stephens (pstephens)](https://github.com/pstephens)*
395 The F# implementation of mal has been tested on Linux using the Mono
396 F# compiler (fsharpc) and the Mono runtime (version 3.12.1). The mono C#
397 compiler (mcs) is also necessary to compile the readline dependency. All are
398 required to build and run the F# implementation.
408 *The Factor implementation was created by [Jordan Lewis (jordanlewis)](https://github.com/jordanlewis)*
410 The Factor implementation of mal has been tested with Factor 0.97
411 ([factorcode.org](http://factorcode.org)).
415 FACTOR_ROOTS=. factor -run=stepX_YYY
420 *The Forth implementation was created by [Chris Houser (chouser)](https://github.com/chouser)*
429 The Go implementation of mal requires that go is installed on on the
430 path. The implementation has been tested with Go 1.3.1.
441 The Groovy implementation of mal requires Groovy to run and has been
442 tested with Groovy 1.8.6.
447 groovy ./stepX_YYY.groovy
452 *The Guile implementation was created by [Mu Lei (NalaGinrut)](https://github.com/NalaGinrut).*
456 guile -L ./ stepX_YYY.scm
461 *The Smalltalk implementation was created by [Vasilij Schneidermann](https://github.com/wasamasa)*
463 The Smalltalk implementation of mal has been tested with GNU Smalltalk 3.2.91.
472 The Haskell implementation requires the ghc compiler version 7.10.1 or
473 later and also the Haskell parsec and readline (or editline) packages.
483 The Haxe implementation of mal requires Haxe version 3.2 to compile.
484 Four different Haxe targets are supported: Neko, Python, C++, and
494 python3 ./stepX_YYY.py
505 *The Io implementation was created by [Dov Murik](https://github.com/dubek)*
507 The Io implementation of mal has been tested with Io version 20110905.
516 The Java implementation of mal requires maven2 to build.
521 mvn -quiet exec:java -Dexec.mainClass=mal.stepX_YYY
523 mvn -quiet exec:java -Dexec.mainClass=mal.stepX_YYY -Dexec.args="CMDLINE_ARGS"
536 The Julia implementation of mal requires Julia 0.4.
545 *The Kotlin implementation was created by [Javier Fernandez-Ivern](https://github.com/ivern)*
547 The Kotlin implementation of mal has been tested with Kotlin 1.0.
552 java -jar stepX_YYY.jar
557 *The LiveScript implementation was created by [Jos van Bakel](https://github.com/c0deaddict)*
559 The LiveScript implementation of mal has been tested with LiveScript 1.5.
564 node_modules/.bin/lsc stepX_YYY.ls
569 *The Logo implementation was created by [Dov Murik](https://github.com/dubek)*
571 The Logo implementation of mal has been tested with UCBLogo 6.0.
580 Running the Lua implementation of mal requires lua 5.1 or later,
581 luarocks and the lua-rex-pcre library installed.
585 make # to build and link linenoise.so
591 Running the mal implementation of mal involves running stepA of one of
592 the other implementations and passing the mal step to run as a command
597 IMPL_STEPA_CMD ../mal/stepX_YYY.mal
610 *The Nim implementation was created by [Dennis Felsing (def-)](https://github.com/def-)*
612 The Nim implementation of mal has been tested with Nim 0.17.0.
624 The Object Pascal implementation of mal has been built and tested on
625 Linux using the Free Pascal compiler version 2.6.2 and 2.6.4.
635 The Objective C implementation of mal has been built and tested on
636 Linux using clang/LLVM 3.6. It has also been built and tested on OS
647 *The OCaml implementation was created by [Chris Houser (chouser)](https://github.com/chouser)*
657 The MATLAB implementation of mal has been tested with MATLAB version
658 R2014a on Linux. Note that MATLAB is a commercial product. It should
659 be fairly simple to support GNU Octave once it support classdef object
665 matlab -nodisplay -nosplash -nodesktop -nojvm -r "stepX_YYY();quit;"
666 # OR with command line arguments
667 matlab -nodisplay -nosplash -nodesktop -nojvm -r "stepX_YYY('arg1','arg2');quit;"
672 [miniMAL](https://github.com/kanaka/miniMAL) is small Lisp interpreter
673 implemented in less than 1024 bytes of JavaScript. To run the miniMAL
674 implementation of mal you need to download/install the miniMAL
675 interpreter (which requires Node.js).
678 # Download miniMAL and dependencies
680 export PATH=`pwd`/node_modules/minimal-lisp/:$PATH
681 # Now run mal implementation in miniMAL
687 For readline line editing support, install Term::ReadLine::Perl or
688 Term::ReadLine::Gnu from CPAN.
697 *The Perl 6 implementation was created by [Hinrik Örn Sigurðsson](https://github.com/hinrik)*
699 The Perl 6 implementation was tested on Rakudo Perl 6 2016.04.
708 The PHP implementation of mal requires the php command line interface
718 *The Picolisp implementation was created by [Vasilij Schneidermann](https://github.com/wasamasa)*
720 The Picolisp implementation requires libreadline and Picolisp 3.1.11
728 ### PL/pgSQL (Postgres SQL Procedural Language)
730 The PL/pgSQL implementation of mal requires a running Postgres server
731 (the "kanaka/mal-test-plpgsql" docker image automatically starts
732 a Postgres server). The implementation connects to the Postgres server
733 and create a database named "mal" to store tables and stored
734 procedures. The wrapper script uses the psql command to connect to the
735 server and defaults to the user "postgres" but this can be overridden
736 with the PSQL_USER environment variable. A password can be specified
737 using the PGPASSWORD environment variable. The implementation has been
738 tested with Postgres 9.4.
742 ./wrap.sh stepX_YYY.sql
744 PSQL_USER=myuser PGPASSWORD=mypass ./wrap.sh stepX_YYY.sql
747 ### PL/SQL (Oracle SQL Procedural Language)
749 The PL/pgSQL implementation of mal requires a running Oracle DB
750 server (the "kanaka/mal-test-plsql" docker image automatically
751 starts an Oracle Express server). The implementation connects to the
752 Oracle server to create types, tables and stored procedures. The
753 default SQL*Plus logon value (username/password@connect_identifier) is
754 "system/oracle" but this can be overridden with the ORACLE_LOGON
755 environment variable. The implementation has been tested with Oracle
756 Express Edition 11g Release 2. Note that any SQL*Plus connection
757 warnings (user password expiration, etc) will interfere with the
758 ability of the wrapper script to communicate with the DB.
762 ./wrap.sh stepX_YYY.sql
764 ORACLE_LOGON=myuser/mypass@ORCL ./wrap.sh stepX_YYY.sql
767 ### Postscript Level 2/3
769 The Postscript implementation of mal requires ghostscript to run. It
770 has been tested with ghostscript 9.10.
774 gs -q -dNODISPLAY -I./ stepX_YYY.ps
779 The PowerShell implementation of mal requires the PowerShell script
780 language. It has been tested with PowerShell 6.0.0 Alpha 9 on Linux.
784 powershell ./stepX_YYY.ps1
787 ### Python (2.X or 3.X)
796 You must have [rpython](https://rpython.readthedocs.org/) on your path
797 (included with [pypy](https://bitbucket.org/pypy/pypy/)).
801 make # this takes a very long time
807 The R implementation of mal requires R (r-base-core) to run.
811 make libs # to download and build rdyncall
817 The Racket implementation of mal requires the Racket
818 compiler/interpreter to run.
827 *The Rexx implementation was created by [Dov Murik](https://github.com/dubek)*
829 The Rexx implementation of mal has been tested with Regina Rexx 3.6.
834 rexx -a ./stepX_YYY.rexxpp
844 ### Rust (1.0.0 nightly)
846 The rust implementation of mal requires the rust compiler and build
847 tool (cargo) to build.
851 cargo run --release --bin stepX_YYY
856 Install scala and sbt (http://www.scala-sbt.org/0.13/tutorial/Installing-sbt-on-Linux.html):
860 sbt 'run-main stepX_YYY'
863 scala -classpath target/scala*/classes stepX_YYY
868 *The Skew implementation was created by [Dov Murik](https://github.com/dubek)*
870 The Skew implementation of mal has been tested with Skew 0.7.42.
881 *The Swift implementation was created by [Keith Rollin](https://github.com/keith-rollin)*
883 The Swift implementation of mal requires the Swift 2.0 compiler (XCode
884 7.0) to build. Older versions will not work due to changes in the
885 language and standard library.
895 The Swift 3 implementation of mal requires the Swift 3.0 compiler. It
896 has been tested with Swift 3 Preview 3.
906 *The Tcl implementation was created by [Dov Murik](https://github.com/dubek)*
908 The Tcl implementation of mal requires Tcl 8.6 to run. For readline line
909 editing support, install tclreadline.
913 tclsh ./stepX_YYY.tcl
918 *The TypeScript implementation was created by [vvakame](https://github.com/vvakame)*
920 The TypeScript implementation of mal requires the TypeScript 2.2 compiler.
921 It has been tested with Node.js v6.
931 *The VHDL implementation was created by [Dov Murik](https://github.com/dubek)*
933 The VHDL implementation of mal has been tested with GHDL 0.29.
938 ./run_vhdl.sh ./stepX_YYY
943 *The Vimscript implementation was created by [Dov Murik](https://github.com/dubek)*
945 The Vimscript implementation of mal requires Vim 8.0 to run.
949 ./run_vimscript.sh ./stepX_YYY.vim
952 ### Visual Basic.NET ###
954 The VB.NET implementation of mal has been tested on Linux using the Mono
955 VB compiler (vbnc) and the Mono runtime (version 2.10.8.1). Both are
956 required to build and run the VB.NET implementation.
970 The are over 600 generic functional tests (for all implementations)
971 in the `tests/` directory. Each step has a corresponding test file
972 containing tests specific to that step. The `runtest.py` test harness
973 launches a Mal step implementation and then feeds the tests one at
974 a time to the implementation and compares the output/return value to
975 the expected output/return value.
977 To simplify the process of running tests, a top level Makefile is
978 provided with convenient test targets.
980 * To run all the tests across all implementations (be prepared to wait):
986 * To run all tests against a single implementation:
996 * To run tests for a single step against all implementations:
1006 * To run tests for a specific step against a single implementation:
1009 make "test^IMPL^stepX"
1012 make "test^ruby^step3"
1013 make "test^ps^step4"
1016 ### Self-hosted functional tests
1018 * To run the functional tests in self-hosted mode, you specify `mal`
1019 as the test implementation and use the `MAL_IMPL` make variable
1020 to change the underlying host language (default is JavaScript):
1022 make MAL_IMPL=IMPL "test^mal^step2"
1025 make "test^mal^step2" # js is default
1026 make MAL_IMPL=ruby "test^mal^step2"
1027 make MAL_IMPL=python "test^mal^step2"
1030 ### Starting the REPL
1032 * To start the REPL of an implementation in a specific step:
1035 make "repl^IMPL^stepX"
1038 make "repl^ruby^step3"
1039 make "repl^ps^step4"
1042 * If you omit the step, then `stepA` is used:
1052 * To start the REPL of the self-hosted implementation, specify `mal` as the
1053 REPL implementation and use the `MAL_IMPL` make variable to change the
1054 underlying host language (default is JavaScript):
1056 make MAL_IMPL=IMPL "repl^mal^stepX"
1059 make "repl^mal^step2" # js is default
1060 make MAL_IMPL=ruby "repl^mal^step2"
1061 make MAL_IMPL=python "repl^mal"
1064 ### Performance tests
1066 Warning: These performance tests are neither statistically valid nor
1067 comprehensive; runtime performance is a not a primary goal of mal. If
1068 you draw any serious conclusions from these performance tests, then
1069 please contact me about some amazing oceanfront property in Kansas
1070 that I'm willing to sell you for cheap.
1072 * To run performance tests against a single implementation:
1080 * To run performance tests against all implementations:
1085 ### Generating language statistics
1087 * To report line and byte statistics for a single implementation:
1095 * To report line and bytes statistics for general Lisp code (env, core
1098 make "stats-lisp^IMPL"
1101 make "stats-lisp^js"
1104 ## Dockerized testing
1106 Every implementation directory contains a Dockerfile to create
1107 a docker image containing all the dependencies for that
1108 implementation. In addition, the top-level Makefile contains support
1109 for running the tests target (and perf, stats, repl, etc) within
1110 a docker container for that implementation by passing *"DOCKERIZE=1"*
1111 on the make command line. For example:
1114 make DOCKERIZE=1 "test^js^step3"
1117 Existing implementations already have docker images built and pushed
1118 to the docker registry. However, if
1119 you wish to build or rebuild a docker image locally, the toplevel
1120 Makefile provides a rule for building docker images:
1123 make "docker-build^IMPL"
1128 * Docker images are named *"kanaka/mal-test-IMPL"*
1129 * JVM-based language implementations (Groovy, Java, Clojure, Scala):
1130 you will probably need to run these implementations once manually
1131 first (make DOCKERIZE=1 "repl^IMPL")before you can run tests because
1132 runtime dependencies need to be downloaded to avoid the tests timing
1133 out. These dependencies are download to dot-files in the /mal
1134 directory so they will persist between runs.
1139 Mal (make-a-lisp) is licensed under the MPL 2.0 (Mozilla Public
1140 License 2.0). See LICENSE.txt for more details.