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 63 languages:
14 * BASIC (C64 and QBasic)
28 * ES6 (ECMAScript 6 / ECMAScript 2015)
39 * JavaScript ([Online Demo](http://kanaka.github.io/mal))
47 * [miniMAL](https://github.com/kanaka/miniMAL)
76 Mal is a learning tool. See the [make-a-lisp process
77 guide](process/guide.md). Each implementation of mal is separated into
78 11 incremental, self-contained (and testable) steps that demonstrate
79 core concepts of Lisp. The last step is capable of self-hosting
80 (running the mal implementation of mal).
82 The mal (make a lisp) steps are:
84 * [step0_repl](process/guide.md#step0)
85 * [step1_read_print](process/guide.md#step1)
86 * [step2_eval](process/guide.md#step2)
87 * [step3_env](process/guide.md#step3)
88 * [step4_if_fn_do](process/guide.md#step4)
89 * [step5_tco](process/guide.md#step5)
90 * [step6_file](process/guide.md#step6)
91 * [step7_quote](process/guide.md#step7)
92 * [step8_macros](process/guide.md#step8)
93 * [step9_try](process/guide.md#step9)
94 * [stepA_mal](process/guide.md#stepA)
97 Mal was presented publicly for the first time in a lightning talk at
98 Clojure West 2014 (unfortunately there is no video). See
99 examples/clojurewest2014.mal for the presentation that was given at the
100 conference (yes the presentation is a mal program). At Midwest.io
101 2015, Joel Martin gave a presentation on Mal titled "Achievement
102 Unlocked: A Better Path to Language Learning".
103 [Video](https://www.youtube.com/watch?v=lgyOAiRtZGw),
104 [Slides](http://kanaka.github.io/midwest.io.mal/).
106 If you are interesting in creating a mal implementation (or just
107 interested in using mal for something), please drop by the #mal
108 channel on freenode. In addition to the [make-a-lisp process
109 guide](process/guide.md) there is also a [mal/make-a-lisp
110 FAQ](docs/FAQ.md) where I attempt to answer some common questions.
112 ## Building/running implementations
114 The simplest way to run any given implementation is to use docker.
115 Every implementation has a docker image pre-built with language
116 dependencies installed. You can launch the REPL using a convenience
117 target in the top level Makefile (where IMPL is the implementation
118 directory name and stepX is the step to run):
121 make DOCKERIZE=1 "repl^IMPL^stepX"
122 # OR stepA is the default step:
123 make DOCKERIZE=1 "repl^IMPL"
129 *The Ada implementation was created by [Chris Moore](https://github.com/zmower)*
131 The Ada implementation was developed with GNAT 4.9 on debian. It also
132 compiles unchanged on windows if you have windows versions of git,
133 GNAT and (optionally) make. There are no external dependencies
134 (readline not implemented).
144 *The GNU awk implementation was created by [Miutsuru kariya](https://github.com/kariya-mitsuru)*
146 The GNU awk implementation of mal has been tested with GNU awk 4.1.1.
150 gawk -O -f stepX_YYY.awk
160 ### BASIC (C64 and QBasic)
162 The BASIC implementation uses a preprocessor that can generate BASIC
163 code that is compatible with both C64 BASIC (CBM v2) and QBasic. The
164 C64 mode has been tested with
165 [cbmbasic](https://github.com/kanaka/cbmbasic) (the patched version is
166 currently required to fix issues with line input) and the QBasic mode
167 has been tested with [qb64](http://www.qb64.net/).
169 Generate C64 code and run it using cbmbasic:
177 Generate QBasic code and load it into qb64:
181 make MODE=qbasic stepX_YYY.bas
185 Thanks to [Steven Syrek](https://github.com/sjsyrek) for the original
186 inspiration for this implementation.
191 The C implementation of mal requires the following libraries (lib and
192 header packages): glib, libffi6, libgc, and either the libedit or GNU readline
203 *The C++ implementation was created by [Stephen Thirlwall (sdt)](https://github.com/sdt)*
205 The C++ implementation of mal requires g++-4.9 or clang++-3.5 and
206 a readline compatible library to build. See the `cpp/README.md` for
220 The C# implementation of mal has been tested on Linux using the Mono
221 C# compiler (mcs) and the Mono runtime (version 2.10.8.1). Both are
222 required to build and run the C# implementation.
232 *The ChucK implementation was created by [Vasilij Schneidermann](https://github.com/wasamasa)*
234 The ChucK implementation has been tested with ChucK 1.3.5.2.
243 *The Common Lisp implementation was created by [Iqbal Ansari](https://github.com/iqbalansari)*
245 The implementation has been tested with SBCL, CCL, CMUCL, GNU CLISP, ECL and
246 Allegro CL on Ubuntu 16.04 and Ubuntu 12.04, see
247 the [README][common-lisp/README.org] for more details. Provided you have the
248 dependencies mentioned installed, do the following to run the implementation
258 For the most part the Clojure implementation requires Clojure 1.5,
259 however, to pass all tests, Clojure 1.8.0-RC4 is required.
263 lein with-profile +stepX trampoline run
269 sudo npm install -g coffee-script
276 *The Crystal implementation of mal was created by [Linda_pp](https://github.com/rhysd)*
278 The Crystal implementation of mal has been tested with Crystal 0.18.4.
282 crystal run ./stepX_YYY.cr
284 make # needed to run tests
290 *The D implementation was created by [Dov Murik](https://github.com/dubek)*
292 The D implementation of mal was tested with GDC 4.8. It requires the GNU
303 *The Dart implementation was created by [Harry Terkelsen](https://github.com/hterkelsen)*
305 The Dart implementation has been tested with Dart 1.20.
314 *The Emacs Lisp implementation was created by [Vasilij Schneidermann](https://github.com/wasamasa)*
316 The Emacs Lisp implementation of mal has been tested with Emacs 24.3
317 and 24.5. While there is very basic readline editing (`<backspace>`
318 and `C-d` work, `C-c` cancels the process), it is recommended to use
323 emacs -Q --batch --load stepX_YYY.el
324 # with full readline support
325 rlwrap emacs -Q --batch --load stepX_YYY.el
330 *The Elixir implementation was created by [Martin Ek (ekmartin)](https://github.com/ekmartin)*
332 The Elixir implementation of mal has been tested with Elixir 1.0.5.
337 # Or with readline/line editing functionality:
343 *The Erlang implementation was created by [Nathan Fiedler (nlfiedler)](https://github.com/nlfiedler)*
345 The Erlang implementation of mal requires [Erlang/OTP R17](http://www.erlang.org/download.html)
346 and [rebar](https://github.com/rebar/rebar) to build.
352 MAL_STEP=stepX_YYY rebar compile escriptize # build individual step
356 ### ES6 (ECMAScript 6 / ECMAScript 2015)
358 The ES6 implementation uses the [babel](https://babeljs.io) compiler
359 to generate ES5 compatible JavaScript. The generated code has been
360 tested with Node 0.12.4.
365 node build/stepX_YYY.js
371 *The F# implementation was created by [Peter Stephens (pstephens)](https://github.com/pstephens)*
373 The F# implementation of mal has been tested on Linux using the Mono
374 F# compiler (fsharpc) and the Mono runtime (version 3.12.1). The mono C#
375 compiler (mcs) is also necessary to compile the readline dependency. All are
376 required to build and run the F# implementation.
386 *The Factor implementation was created by [Jordan Lewis (jordanlewis)](https://github.com/jordanlewis)*
388 The Factor implementation of mal has been tested with Factor 0.97
389 ([factorcode.org](http://factorcode.org)).
393 FACTOR_ROOTS=. factor -run=stepX_YYY
398 *The Forth implementation was created by [Chris Houser (chouser)](https://github.com/chouser)*
407 The Go implementation of mal requires that go is installed on on the
408 path. The implementation has been tested with Go 1.3.1.
419 The Groovy implementation of mal requires Groovy to run and has been
420 tested with Groovy 1.8.6.
425 groovy ./stepX_YYY.groovy
430 *The Guile implementation was created by [Mu Lei (NalaGinrut)](https://github.com/NalaGinrut).*
434 guile -L ./ stepX_YYY.scm
439 The Haskell implementation requires the ghc compiler version 7.10.1 or
440 later and also the Haskell parsec and readline (or editline) packages.
450 The Haxe implementation of mal requires Haxe version 3.2 to compile.
451 Four different Haxe targets are supported: Neko, Python, C++, and
461 python3 ./stepX_YYY.py
472 *The Io implementation was created by [Dov Murik](https://github.com/dubek)*
474 The Io implementation of mal has been tested with Io version 20110905.
483 The Java implementation of mal requires maven2 to build.
488 mvn -quiet exec:java -Dexec.mainClass=mal.stepX_YYY
490 mvn -quiet exec:java -Dexec.mainClass=mal.stepX_YYY -Dexec.args="CMDLINE_ARGS"
503 The Julia implementation of mal requires Julia 0.4.
512 *The Kotlin implementation was created by [Javier Fernandez-Ivern](https://github.com/ivern)*
514 The Kotlin implementation of mal has been tested with Kotlin 1.0.
519 java -jar stepX_YYY.jar
524 *The Logo implementation was created by [Dov Murik](https://github.com/dubek)*
526 The Logo implementation of mal has been tested with UCBLogo 6.0.
535 Running the Lua implementation of mal requires lua 5.1 or later,
536 luarocks and the lua-rex-pcre library installed.
540 make # to build and link linenoise.so
546 Running the mal implementation of mal involves running stepA of one of
547 the other implementations and passing the mal step to run as a command
552 IMPL_STEPA_CMD ../mal/stepX_YYY.mal
565 *The Nim implementation was created by [Dennis Felsing (def-)](https://github.com/def-)*
567 The Nim implementation of mal has been tested with Nim 0.15.2.
579 The Object Pascal implementation of mal has been built and tested on
580 Linux using the Free Pascal compiler version 2.6.2 and 2.6.4.
590 The Objective C implementation of mal has been built and tested on
591 Linux using clang/LLVM 3.6. It has also been built and tested on OS
602 *The OCaml implementation was created by [Chris Houser (chouser)](https://github.com/chouser)*
612 The MATLAB implementation of mal has been tested with MATLAB version
613 R2014a on Linux. Note that MATLAB is a commercial product. It should
614 be fairly simple to support GNU Octave once it support classdef object
620 matlab -nodisplay -nosplash -nodesktop -nojvm -r "stepX_YYY();quit;"
621 # OR with command line arguments
622 matlab -nodisplay -nosplash -nodesktop -nojvm -r "stepX_YYY('arg1','arg2');quit;"
627 [miniMAL](https://github.com/kanaka/miniMAL) is small Lisp interpreter
628 implemented in less than 1024 bytes of JavaScript. To run the miniMAL
629 implementation of mal you need to download/install the miniMAL
630 interpreter (which requires Node.js).
633 # Download miniMAL and dependencies
635 export PATH=`pwd`/node_modules/minimal-lisp/:$PATH
636 # Now run mal implementation in miniMAL
642 For readline line editing support, install Term::ReadLine::Perl or
643 Term::ReadLine::Gnu from CPAN.
652 *The Perl 6 implementation was created by [Hinrik Örn Sigurðsson](https://github.com/hinrik)*
654 The Perl 6 implementation was tested on Rakudo Perl 6 2016.04.
663 The PHP implementation of mal requires the php command line interface
673 *The Picolisp implementation was created by [Vasilij Schneidermann](https://github.com/wasamasa)*
675 The Picolisp implementation requires libreadline and Picolisp 3.1.11
683 ### PL/pgSQL (Postgres SQL Procedural Language)
685 The PL/pgSQL implementation of mal requires a running Postgres server
686 (the "kanaka/mal-test-plpgsql" docker image automatically starts
687 a Postgres server). The implementation connects to the Postgres server
688 and create a database named "mal" to store tables and stored
689 procedures. The wrapper script uses the psql command to connect to the
690 server and defaults to the user "postgres" but this can be overridden
691 with the PSQL_USER environment variable. A password can be specified
692 using the PGPASSWORD environment variable. The implementation has been
693 tested with Postgres 9.4.
697 ./wrap.sh stepX_YYY.sql
699 PSQL_USER=myuser PGPASSWORD=mypass ./wrap.sh stepX_YYY.sql
702 ### PL/SQL (Oracle SQL Procedural Language)
704 The PL/pgSQL implementation of mal requires a running Oracle DB
705 server (the "kanaka/mal-test-plsql" docker image automatically
706 starts an Oracle Express server). The implementation connects to the
707 Oracle server to create types, tables and stored procedures. The
708 default SQL*Plus logon value (username/password@connect_identifier) is
709 "system/oracle" but this can be overridden with the ORACLE_LOGON
710 environment variable. The implementation has been tested with Oracle
711 Express Edition 11g Release 2. Note that any SQL*Plus connection
712 warnings (user password expiration, etc) will interfere with the
713 ability of the wrapper script to communicate with the DB.
717 ./wrap.sh stepX_YYY.sql
719 ORACLE_LOGON=myuser/mypass@ORCL ./wrap.sh stepX_YYY.sql
722 ### Postscript Level 2/3
724 The Postscript implementation of mal requires ghostscript to run. It
725 has been tested with ghostscript 9.10.
729 gs -q -dNODISPLAY -I./ stepX_YYY.ps
734 The PowerShell implementation of mal requires the PowerShell script
735 language. It has been tested with PowerShell 6.0.0 Alpha 9 on Linux.
739 powershell ./stepX_YYY.ps1
742 ### Python (2.X or 3.X)
751 You must have [rpython](https://rpython.readthedocs.org/) on your path
752 (included with [pypy](https://bitbucket.org/pypy/pypy/)).
756 make # this takes a very long time
762 The R implementation of mal requires R (r-base-core) to run.
766 make libs # to download and build rdyncall
772 The Racket implementation of mal requires the Racket
773 compiler/interpreter to run.
787 ### Rust (1.0.0 nightly)
789 The rust implementation of mal requires the rust compiler and build
790 tool (cargo) to build.
794 cargo run --release --bin stepX_YYY
799 Install scala and sbt (http://www.scala-sbt.org/0.13/tutorial/Installing-sbt-on-Linux.html):
803 sbt 'run-main stepX_YYY'
806 scala -classpath target/scala*/classes stepX_YYY
811 *The Skew implementation was created by [Dov Murik](https://github.com/dubek)*
813 The Skew implementation of mal has been tested with Skew 0.7.42.
824 *The Swift implementation was created by [Keith Rollin](https://github.com/keith-rollin)*
826 The Swift implementation of mal requires the Swift 2.0 compiler (XCode
827 7.0) to build. Older versions will not work due to changes in the
828 language and standard library.
838 The Swift 3 implementation of mal requires the Swift 3.0 compiler. It
839 has been tested with Swift 3 Preview 3.
849 *The Tcl implementation was created by [Dov Murik](https://github.com/dubek)*
851 The Tcl implementation of mal requires Tcl 8.6 to run. For readline line
852 editing support, install tclreadline.
856 tclsh ./stepX_YYY.tcl
861 The TypeScript implementation of mal requires the TypeScript 2.2 compiler.
862 It has been tested with Node.js v7.6.0.
872 *The VHDL implementation was created by [Dov Murik](https://github.com/dubek)*
874 The VHDL implementation of mal has been tested with GHDL 0.29.
879 ./run_vhdl.sh ./stepX_YYY
884 *The Vimscript implementation was created by [Dov Murik](https://github.com/dubek)*
886 The Vimscript implementation of mal requires Vim 8.0 to run.
890 ./run_vimscript.sh ./stepX_YYY.vim
893 ### Visual Basic.NET ###
895 The VB.NET implementation of mal has been tested on Linux using the Mono
896 VB compiler (vbnc) and the Mono runtime (version 2.10.8.1). Both are
897 required to build and run the VB.NET implementation.
911 The are over 600 generic functional tests (for all implementations)
912 in the `tests/` directory. Each step has a corresponding test file
913 containing tests specific to that step. The `runtest.py` test harness
914 launches a Mal step implementation and then feeds the tests one at
915 a time to the implementation and compares the output/return value to
916 the expected output/return value.
918 To simplify the process of running tests, a top level Makefile is
919 provided with convenient test targets.
921 * To run all the tests across all implementations (be prepared to wait):
927 * To run all tests against a single implementation:
937 * To run tests for a single step against all implementations:
947 * To run tests for a specific step against a single implementation:
950 make "test^IMPL^stepX"
953 make "test^ruby^step3"
957 ### Self-hosted functional tests
959 * To run the functional tests in self-hosted mode, you specify `mal`
960 as the test implementation and use the `MAL_IMPL` make variable
961 to change the underlying host language (default is JavaScript):
963 make MAL_IMPL=IMPL "test^mal^step2"
966 make "test^mal^step2" # js is default
967 make MAL_IMPL=ruby "test^mal^step2"
968 make MAL_IMPL=python "test^mal^step2"
971 ### Starting the REPL
973 * To start the REPL of an implementation in a specific step:
976 make "repl^IMPL^stepX"
979 make "repl^ruby^step3"
983 * If you omit the step, then `stepA` is used:
993 * To start the REPL of the self-hosted implementation, specify `mal` as the
994 REPL implementation and use the `MAL_IMPL` make variable to change the
995 underlying host language (default is JavaScript):
997 make MAL_IMPL=IMPL "repl^mal^stepX"
1000 make "repl^mal^step2" # js is default
1001 make MAL_IMPL=ruby "repl^mal^step2"
1002 make MAL_IMPL=python "repl^mal"
1005 ### Performance tests
1007 Warning: These performance tests are neither statistically valid nor
1008 comprehensive; runtime performance is a not a primary goal of mal. If
1009 you draw any serious conclusions from these performance tests, then
1010 please contact me about some amazing oceanfront property in Kansas
1011 that I'm willing to sell you for cheap.
1013 * To run performance tests against a single implementation:
1021 * To run performance tests against all implementations:
1026 ### Generating language statistics
1028 * To report line and byte statistics for a single implementation:
1036 * To report line and bytes statistics for general Lisp code (env, core
1039 make "stats-lisp^IMPL"
1042 make "stats-lisp^js"
1045 ## Dockerized testing
1047 Every implementation directory contains a Dockerfile to create
1048 a docker image containing all the dependencies for that
1049 implementation. In addition, the top-level Makefile contains support
1050 for running the tests target (and perf, stats, repl, etc) within
1051 a docker container for that implementation by passing *"DOCKERIZE=1"*
1052 on the make command line. For example:
1055 make DOCKERIZE=1 "test^js^step3"
1058 Existing implementations already have docker images built and pushed
1059 to the docker registry. However, if
1060 you wish to build or rebuild a docker image locally, the toplevel
1061 Makefile provides a rule for building docker images:
1064 make "docker-build^IMPL"
1069 * Docker images are named *"kanaka/mal-test-IMPL"*
1070 * JVM-based language implementations (Groovy, Java, Clojure, Scala):
1071 you will probably need to run these implementations once manually
1072 first (make DOCKERIZE=1 "repl^IMPL")before you can run tests because
1073 runtime dependencies need to be downloaded to avoid the tests timing
1074 out. These dependencies are download to dot-files in the /mal
1075 directory so they will persist between runs.
1080 Mal (make-a-lisp) is licensed under the MPL 2.0 (Mozilla Public
1081 License 2.0). See LICENSE.txt for more details.