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 67 languages:
14 * BASIC (C64 and QBasic)
28 * ES6 (ECMAScript 6 / ECMAScript 2015)
40 * JavaScript ([Online Demo](http://kanaka.github.io/mal))
49 * [miniMAL](https://github.com/kanaka/miniMAL)
80 Mal is a learning tool. See the [make-a-lisp process
81 guide](process/guide.md). Each implementation of mal is separated into
82 11 incremental, self-contained (and testable) steps that demonstrate
83 core concepts of Lisp. The last step is capable of self-hosting
84 (running the mal implementation of mal).
86 The mal (make a lisp) steps are:
88 * [step0_repl](process/guide.md#step0)
89 * [step1_read_print](process/guide.md#step1)
90 * [step2_eval](process/guide.md#step2)
91 * [step3_env](process/guide.md#step3)
92 * [step4_if_fn_do](process/guide.md#step4)
93 * [step5_tco](process/guide.md#step5)
94 * [step6_file](process/guide.md#step6)
95 * [step7_quote](process/guide.md#step7)
96 * [step8_macros](process/guide.md#step8)
97 * [step9_try](process/guide.md#step9)
98 * [stepA_mal](process/guide.md#stepA)
101 Mal was presented publicly for the first time in a lightning talk at
102 Clojure West 2014 (unfortunately there is no video). See
103 examples/clojurewest2014.mal for the presentation that was given at the
104 conference (yes the presentation is a mal program). At Midwest.io
105 2015, Joel Martin gave a presentation on Mal titled "Achievement
106 Unlocked: A Better Path to Language Learning".
107 [Video](https://www.youtube.com/watch?v=lgyOAiRtZGw),
108 [Slides](http://kanaka.github.io/midwest.io.mal/). More recently
109 Joel gave a presentation on "Make Your Own Lisp Interpreter in
110 10 Incremental Steps" at LambdaConf 2016: [Part
111 1](https://www.youtube.com/watch?v=jVhupfthTEk), [Part
112 2](https://www.youtube.com/watch?v=X5OQBMGpaTU),
113 [Slides](http://kanaka.github.io/lambdaconf/).
115 If you are interesting in creating a mal implementation (or just
116 interested in using mal for something), please drop by the #mal
117 channel on freenode. In addition to the [make-a-lisp process
118 guide](process/guide.md) there is also a [mal/make-a-lisp
119 FAQ](docs/FAQ.md) where I attempt to answer some common questions.
121 ## Building/running implementations
123 The simplest way to run any given implementation is to use docker.
124 Every implementation has a docker image pre-built with language
125 dependencies installed. You can launch the REPL using a convenience
126 target in the top level Makefile (where IMPL is the implementation
127 directory name and stepX is the step to run):
130 make DOCKERIZE=1 "repl^IMPL^stepX"
131 # OR stepA is the default step:
132 make DOCKERIZE=1 "repl^IMPL"
138 *The Ada implementation was created by [Chris Moore](https://github.com/zmower)*
140 The Ada implementation was developed with GNAT 4.9 on debian. It also
141 compiles unchanged on windows if you have windows versions of git,
142 GNAT and (optionally) make. There are no external dependencies
143 (readline not implemented).
153 *The GNU awk implementation was created by [Miutsuru kariya](https://github.com/kariya-mitsuru)*
155 The GNU awk implementation of mal has been tested with GNU awk 4.1.1.
159 gawk -O -f stepX_YYY.awk
169 ### BASIC (C64 and QBasic)
171 The BASIC implementation uses a preprocessor that can generate BASIC
172 code that is compatible with both C64 BASIC (CBM v2) and QBasic. The
173 C64 mode has been tested with
174 [cbmbasic](https://github.com/kanaka/cbmbasic) (the patched version is
175 currently required to fix issues with line input) and the QBasic mode
176 has been tested with [qb64](http://www.qb64.net/).
178 Generate C64 code and run it using cbmbasic:
186 Generate QBasic code and load it into qb64:
190 make MODE=qbasic stepX_YYY.bas
194 Thanks to [Steven Syrek](https://github.com/sjsyrek) for the original
195 inspiration for this implementation.
200 The C implementation of mal requires the following libraries (lib and
201 header packages): glib, libffi6, libgc, and either the libedit or GNU readline
212 *The C++ implementation was created by [Stephen Thirlwall (sdt)](https://github.com/sdt)*
214 The C++ implementation of mal requires g++-4.9 or clang++-3.5 and
215 a readline compatible library to build. See the `cpp/README.md` for
229 The C# implementation of mal has been tested on Linux using the Mono
230 C# compiler (mcs) and the Mono runtime (version 2.10.8.1). Both are
231 required to build and run the C# implementation.
241 *The ChucK implementation was created by [Vasilij Schneidermann](https://github.com/wasamasa)*
243 The ChucK implementation has been tested with ChucK 1.3.5.2.
252 *The Common Lisp implementation was created by [Iqbal Ansari](https://github.com/iqbalansari)*
254 The implementation has been tested with SBCL, CCL, CMUCL, GNU CLISP, ECL and
255 Allegro CL on Ubuntu 16.04 and Ubuntu 12.04, see
256 the [README][common-lisp/README.org] for more details. Provided you have the
257 dependencies mentioned installed, do the following to run the implementation
267 For the most part the Clojure implementation requires Clojure 1.5,
268 however, to pass all tests, Clojure 1.8.0-RC4 is required.
272 lein with-profile +stepX trampoline run
278 sudo npm install -g coffee-script
285 *The Crystal implementation of mal was created by [Linda_pp](https://github.com/rhysd)*
287 The Crystal implementation of mal has been tested with Crystal 0.18.4.
291 crystal run ./stepX_YYY.cr
293 make # needed to run tests
299 *The D implementation was created by [Dov Murik](https://github.com/dubek)*
301 The D implementation of mal was tested with GDC 4.8. It requires the GNU
312 *The Dart implementation was created by [Harry Terkelsen](https://github.com/hterkelsen)*
314 The Dart implementation has been tested with Dart 1.20.
323 *The Emacs Lisp implementation was created by [Vasilij Schneidermann](https://github.com/wasamasa)*
325 The Emacs Lisp implementation of mal has been tested with Emacs 24.3
326 and 24.5. While there is very basic readline editing (`<backspace>`
327 and `C-d` work, `C-c` cancels the process), it is recommended to use
332 emacs -Q --batch --load stepX_YYY.el
333 # with full readline support
334 rlwrap emacs -Q --batch --load stepX_YYY.el
339 *The Elixir implementation was created by [Martin Ek (ekmartin)](https://github.com/ekmartin)*
341 The Elixir implementation of mal has been tested with Elixir 1.0.5.
346 # Or with readline/line editing functionality:
352 *The Erlang implementation was created by [Nathan Fiedler (nlfiedler)](https://github.com/nlfiedler)*
354 The Erlang implementation of mal requires [Erlang/OTP R17](http://www.erlang.org/download.html)
355 and [rebar](https://github.com/rebar/rebar) to build.
361 MAL_STEP=stepX_YYY rebar compile escriptize # build individual step
365 ### ES6 (ECMAScript 6 / ECMAScript 2015)
367 The ES6 implementation uses the [babel](https://babeljs.io) compiler
368 to generate ES5 compatible JavaScript. The generated code has been
369 tested with Node 0.12.4.
374 node build/stepX_YYY.js
380 *The F# implementation was created by [Peter Stephens (pstephens)](https://github.com/pstephens)*
382 The F# implementation of mal has been tested on Linux using the Mono
383 F# compiler (fsharpc) and the Mono runtime (version 3.12.1). The mono C#
384 compiler (mcs) is also necessary to compile the readline dependency. All are
385 required to build and run the F# implementation.
395 *The Factor implementation was created by [Jordan Lewis (jordanlewis)](https://github.com/jordanlewis)*
397 The Factor implementation of mal has been tested with Factor 0.97
398 ([factorcode.org](http://factorcode.org)).
402 FACTOR_ROOTS=. factor -run=stepX_YYY
407 *The Forth implementation was created by [Chris Houser (chouser)](https://github.com/chouser)*
416 The Go implementation of mal requires that go is installed on on the
417 path. The implementation has been tested with Go 1.3.1.
428 The Groovy implementation of mal requires Groovy to run and has been
429 tested with Groovy 1.8.6.
434 groovy ./stepX_YYY.groovy
439 *The Guile implementation was created by [Mu Lei (NalaGinrut)](https://github.com/NalaGinrut).*
443 guile -L ./ stepX_YYY.scm
448 *The Smalltalk implementation was created by [Vasilij Schneidermann](https://github.com/wasamasa)*
450 The Smalltalk implementation of mal has been tested with GNU Smalltalk 3.2.91.
459 The Haskell implementation requires the ghc compiler version 7.10.1 or
460 later and also the Haskell parsec and readline (or editline) packages.
470 The Haxe implementation of mal requires Haxe version 3.2 to compile.
471 Four different Haxe targets are supported: Neko, Python, C++, and
481 python3 ./stepX_YYY.py
492 *The Io implementation was created by [Dov Murik](https://github.com/dubek)*
494 The Io implementation of mal has been tested with Io version 20110905.
503 The Java implementation of mal requires maven2 to build.
508 mvn -quiet exec:java -Dexec.mainClass=mal.stepX_YYY
510 mvn -quiet exec:java -Dexec.mainClass=mal.stepX_YYY -Dexec.args="CMDLINE_ARGS"
523 The Julia implementation of mal requires Julia 0.4.
532 *The Kotlin implementation was created by [Javier Fernandez-Ivern](https://github.com/ivern)*
534 The Kotlin implementation of mal has been tested with Kotlin 1.0.
539 java -jar stepX_YYY.jar
544 *The LiveScript implementation was created by [Jos van Bakel](https://github.com/c0deaddict)*
546 The LiveScript implementation of mal has been tested with LiveScript 1.5.
551 node_modules/.bin/lsc stepX_YYY.ls
556 *The Logo implementation was created by [Dov Murik](https://github.com/dubek)*
558 The Logo implementation of mal has been tested with UCBLogo 6.0.
567 Running the Lua implementation of mal requires lua 5.1 or later,
568 luarocks and the lua-rex-pcre library installed.
572 make # to build and link linenoise.so
578 Running the mal implementation of mal involves running stepA of one of
579 the other implementations and passing the mal step to run as a command
584 IMPL_STEPA_CMD ../mal/stepX_YYY.mal
597 *The Nim implementation was created by [Dennis Felsing (def-)](https://github.com/def-)*
599 The Nim implementation of mal has been tested with Nim 0.17.0.
611 The Object Pascal implementation of mal has been built and tested on
612 Linux using the Free Pascal compiler version 2.6.2 and 2.6.4.
622 The Objective C implementation of mal has been built and tested on
623 Linux using clang/LLVM 3.6. It has also been built and tested on OS
634 *The OCaml implementation was created by [Chris Houser (chouser)](https://github.com/chouser)*
644 The MATLAB implementation of mal has been tested with MATLAB version
645 R2014a on Linux. Note that MATLAB is a commercial product. It should
646 be fairly simple to support GNU Octave once it support classdef object
652 matlab -nodisplay -nosplash -nodesktop -nojvm -r "stepX_YYY();quit;"
653 # OR with command line arguments
654 matlab -nodisplay -nosplash -nodesktop -nojvm -r "stepX_YYY('arg1','arg2');quit;"
659 [miniMAL](https://github.com/kanaka/miniMAL) is small Lisp interpreter
660 implemented in less than 1024 bytes of JavaScript. To run the miniMAL
661 implementation of mal you need to download/install the miniMAL
662 interpreter (which requires Node.js).
665 # Download miniMAL and dependencies
667 export PATH=`pwd`/node_modules/minimal-lisp/:$PATH
668 # Now run mal implementation in miniMAL
674 For readline line editing support, install Term::ReadLine::Perl or
675 Term::ReadLine::Gnu from CPAN.
684 *The Perl 6 implementation was created by [Hinrik Örn Sigurðsson](https://github.com/hinrik)*
686 The Perl 6 implementation was tested on Rakudo Perl 6 2016.04.
695 The PHP implementation of mal requires the php command line interface
705 *The Picolisp implementation was created by [Vasilij Schneidermann](https://github.com/wasamasa)*
707 The Picolisp implementation requires libreadline and Picolisp 3.1.11
715 ### PL/pgSQL (Postgres SQL Procedural Language)
717 The PL/pgSQL implementation of mal requires a running Postgres server
718 (the "kanaka/mal-test-plpgsql" docker image automatically starts
719 a Postgres server). The implementation connects to the Postgres server
720 and create a database named "mal" to store tables and stored
721 procedures. The wrapper script uses the psql command to connect to the
722 server and defaults to the user "postgres" but this can be overridden
723 with the PSQL_USER environment variable. A password can be specified
724 using the PGPASSWORD environment variable. The implementation has been
725 tested with Postgres 9.4.
729 ./wrap.sh stepX_YYY.sql
731 PSQL_USER=myuser PGPASSWORD=mypass ./wrap.sh stepX_YYY.sql
734 ### PL/SQL (Oracle SQL Procedural Language)
736 The PL/pgSQL implementation of mal requires a running Oracle DB
737 server (the "kanaka/mal-test-plsql" docker image automatically
738 starts an Oracle Express server). The implementation connects to the
739 Oracle server to create types, tables and stored procedures. The
740 default SQL*Plus logon value (username/password@connect_identifier) is
741 "system/oracle" but this can be overridden with the ORACLE_LOGON
742 environment variable. The implementation has been tested with Oracle
743 Express Edition 11g Release 2. Note that any SQL*Plus connection
744 warnings (user password expiration, etc) will interfere with the
745 ability of the wrapper script to communicate with the DB.
749 ./wrap.sh stepX_YYY.sql
751 ORACLE_LOGON=myuser/mypass@ORCL ./wrap.sh stepX_YYY.sql
754 ### Postscript Level 2/3
756 The Postscript implementation of mal requires ghostscript to run. It
757 has been tested with ghostscript 9.10.
761 gs -q -dNODISPLAY -I./ stepX_YYY.ps
766 The PowerShell implementation of mal requires the PowerShell script
767 language. It has been tested with PowerShell 6.0.0 Alpha 9 on Linux.
771 powershell ./stepX_YYY.ps1
774 ### Python (2.X or 3.X)
783 You must have [rpython](https://rpython.readthedocs.org/) on your path
784 (included with [pypy](https://bitbucket.org/pypy/pypy/)).
788 make # this takes a very long time
794 The R implementation of mal requires R (r-base-core) to run.
798 make libs # to download and build rdyncall
804 The Racket implementation of mal requires the Racket
805 compiler/interpreter to run.
814 *The Rexx implementation was created by [Dov Murik](https://github.com/dubek)*
816 The Rexx implementation of mal has been tested with Regina Rexx 3.6.
821 rexx -a ./stepX_YYY.rexxpp
831 ### Rust (1.0.0 nightly)
833 The rust implementation of mal requires the rust compiler and build
834 tool (cargo) to build.
838 cargo run --release --bin stepX_YYY
843 Install scala and sbt (http://www.scala-sbt.org/0.13/tutorial/Installing-sbt-on-Linux.html):
847 sbt 'run-main stepX_YYY'
850 scala -classpath target/scala*/classes stepX_YYY
855 *The Skew implementation was created by [Dov Murik](https://github.com/dubek)*
857 The Skew implementation of mal has been tested with Skew 0.7.42.
868 *The Swift implementation was created by [Keith Rollin](https://github.com/keith-rollin)*
870 The Swift implementation of mal requires the Swift 2.0 compiler (XCode
871 7.0) to build. Older versions will not work due to changes in the
872 language and standard library.
882 The Swift 3 implementation of mal requires the Swift 3.0 compiler. It
883 has been tested with Swift 3 Preview 3.
893 *The Tcl implementation was created by [Dov Murik](https://github.com/dubek)*
895 The Tcl implementation of mal requires Tcl 8.6 to run. For readline line
896 editing support, install tclreadline.
900 tclsh ./stepX_YYY.tcl
905 *The TypeScript implementation was created by [vvakame](https://github.com/vvakame)*
907 The TypeScript implementation of mal requires the TypeScript 2.2 compiler.
908 It has been tested with Node.js v6.
918 *The VHDL implementation was created by [Dov Murik](https://github.com/dubek)*
920 The VHDL implementation of mal has been tested with GHDL 0.29.
925 ./run_vhdl.sh ./stepX_YYY
930 *The Vimscript implementation was created by [Dov Murik](https://github.com/dubek)*
932 The Vimscript implementation of mal requires Vim 8.0 to run.
936 ./run_vimscript.sh ./stepX_YYY.vim
939 ### Visual Basic.NET ###
941 The VB.NET implementation of mal has been tested on Linux using the Mono
942 VB compiler (vbnc) and the Mono runtime (version 2.10.8.1). Both are
943 required to build and run the VB.NET implementation.
957 The are over 600 generic functional tests (for all implementations)
958 in the `tests/` directory. Each step has a corresponding test file
959 containing tests specific to that step. The `runtest.py` test harness
960 launches a Mal step implementation and then feeds the tests one at
961 a time to the implementation and compares the output/return value to
962 the expected output/return value.
964 To simplify the process of running tests, a top level Makefile is
965 provided with convenient test targets.
967 * To run all the tests across all implementations (be prepared to wait):
973 * To run all tests against a single implementation:
983 * To run tests for a single step against all implementations:
993 * To run tests for a specific step against a single implementation:
996 make "test^IMPL^stepX"
999 make "test^ruby^step3"
1000 make "test^ps^step4"
1003 ### Self-hosted functional tests
1005 * To run the functional tests in self-hosted mode, you specify `mal`
1006 as the test implementation and use the `MAL_IMPL` make variable
1007 to change the underlying host language (default is JavaScript):
1009 make MAL_IMPL=IMPL "test^mal^step2"
1012 make "test^mal^step2" # js is default
1013 make MAL_IMPL=ruby "test^mal^step2"
1014 make MAL_IMPL=python "test^mal^step2"
1017 ### Starting the REPL
1019 * To start the REPL of an implementation in a specific step:
1022 make "repl^IMPL^stepX"
1025 make "repl^ruby^step3"
1026 make "repl^ps^step4"
1029 * If you omit the step, then `stepA` is used:
1039 * To start the REPL of the self-hosted implementation, specify `mal` as the
1040 REPL implementation and use the `MAL_IMPL` make variable to change the
1041 underlying host language (default is JavaScript):
1043 make MAL_IMPL=IMPL "repl^mal^stepX"
1046 make "repl^mal^step2" # js is default
1047 make MAL_IMPL=ruby "repl^mal^step2"
1048 make MAL_IMPL=python "repl^mal"
1051 ### Performance tests
1053 Warning: These performance tests are neither statistically valid nor
1054 comprehensive; runtime performance is a not a primary goal of mal. If
1055 you draw any serious conclusions from these performance tests, then
1056 please contact me about some amazing oceanfront property in Kansas
1057 that I'm willing to sell you for cheap.
1059 * To run performance tests against a single implementation:
1067 * To run performance tests against all implementations:
1072 ### Generating language statistics
1074 * To report line and byte statistics for a single implementation:
1082 * To report line and bytes statistics for general Lisp code (env, core
1085 make "stats-lisp^IMPL"
1088 make "stats-lisp^js"
1091 ## Dockerized testing
1093 Every implementation directory contains a Dockerfile to create
1094 a docker image containing all the dependencies for that
1095 implementation. In addition, the top-level Makefile contains support
1096 for running the tests target (and perf, stats, repl, etc) within
1097 a docker container for that implementation by passing *"DOCKERIZE=1"*
1098 on the make command line. For example:
1101 make DOCKERIZE=1 "test^js^step3"
1104 Existing implementations already have docker images built and pushed
1105 to the docker registry. However, if
1106 you wish to build or rebuild a docker image locally, the toplevel
1107 Makefile provides a rule for building docker images:
1110 make "docker-build^IMPL"
1115 * Docker images are named *"kanaka/mal-test-IMPL"*
1116 * JVM-based language implementations (Groovy, Java, Clojure, Scala):
1117 you will probably need to run these implementations once manually
1118 first (make DOCKERIZE=1 "repl^IMPL")before you can run tests because
1119 runtime dependencies need to be downloaded to avoid the tests timing
1120 out. These dependencies are download to dot-files in the /mal
1121 directory so they will persist between runs.
1126 Mal (make-a-lisp) is licensed under the MPL 2.0 (Mozilla Public
1127 License 2.0). See LICENSE.txt for more details.