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 62 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)
75 Mal is a learning tool. See the [make-a-lisp process
76 guide](process/guide.md). Each implementation of mal is separated into
77 11 incremental, self-contained (and testable) steps that demonstrate
78 core concepts of Lisp. The last step is capable of self-hosting
79 (running the mal implementation of mal).
81 The mal (make a lisp) steps are:
83 * [step0_repl](process/guide.md#step0)
84 * [step1_read_print](process/guide.md#step1)
85 * [step2_eval](process/guide.md#step2)
86 * [step3_env](process/guide.md#step3)
87 * [step4_if_fn_do](process/guide.md#step4)
88 * [step5_tco](process/guide.md#step5)
89 * [step6_file](process/guide.md#step6)
90 * [step7_quote](process/guide.md#step7)
91 * [step8_macros](process/guide.md#step8)
92 * [step9_try](process/guide.md#step9)
93 * [stepA_mal](process/guide.md#stepA)
96 Mal was presented publicly for the first time in a lightning talk at
97 Clojure West 2014 (unfortunately there is no video). See
98 examples/clojurewest2014.mal for the presentation that was given at the
99 conference (yes the presentation is a mal program). At Midwest.io
100 2015, Joel Martin gave a presentation on Mal titled "Achievement
101 Unlocked: A Better Path to Language Learning".
102 [Video](https://www.youtube.com/watch?v=lgyOAiRtZGw),
103 [Slides](http://kanaka.github.io/midwest.io.mal/).
105 If you are interesting in creating a mal implementation (or just
106 interested in using mal for something), please drop by the #mal
107 channel on freenode. In addition to the [make-a-lisp process
108 guide](process/guide.md) there is also a [mal/make-a-lisp
109 FAQ](docs/FAQ.md) where I attempt to answer some common questions.
111 ## Building/running implementations
113 The simplest way to run any given implementation is to use docker.
114 Every implementation has a docker image pre-built with language
115 dependencies installed. You can launch the REPL using a convenience
116 target in the top level Makefile (where IMPL is the implementation
117 directory name and stepX is the step to run):
120 make DOCKERIZE=1 "repl^IMPL^stepX"
121 # OR stepA is the default step:
122 make DOCKERIZE=1 "repl^IMPL"
128 *The Ada implementation was created by [Chris Moore](https://github.com/zmower)*
130 The Ada implementation was developed with GNAT 4.9 on debian. It also
131 compiles unchanged on windows if you have windows versions of git,
132 GNAT and (optionally) make. There are no external dependencies
133 (readline not implemented).
143 *The GNU awk implementation was created by [Miutsuru kariya](https://github.com/kariya-mitsuru)*
145 The GNU awk implementation of mal has been tested with GNU awk 4.1.1.
149 gawk -O -f stepX_YYY.awk
159 ### BASIC (C64 and QBasic)
161 The BASIC implementation uses a preprocessor that can generate BASIC
162 code that is compatible with both C64 BASIC (CBM v2) and QBasic. The
163 C64 mode has been tested with
164 [cbmbasic](https://github.com/kanaka/cbmbasic) (the patched version is
165 currently required to fix issues with line input) and the QBasic mode
166 has been tested with [qb64](http://www.qb64.net/).
168 Generate C64 code and run it using cbmbasic:
176 Generate QBasic code and load it into qb64:
180 make MODE=qbasic stepX_YYY.bas
184 Thanks to [Steven Syrek](https://github.com/sjsyrek) for the original
185 inspiration for this implementation.
190 The C implementation of mal requires the following libraries (lib and
191 header packages): glib, libffi6, libgc, and either the libedit or GNU readline
202 *The C++ implementation was created by [Stephen Thirlwall (sdt)](https://github.com/sdt)*
204 The C++ implementation of mal requires g++-4.9 or clang++-3.5 and
205 a readline compatible library to build. See the `cpp/README.md` for
219 The C# implementation of mal has been tested on Linux using the Mono
220 C# compiler (mcs) and the Mono runtime (version 2.10.8.1). Both are
221 required to build and run the C# implementation.
231 *The ChucK implementation was created by [Vasilij Schneidermann](https://github.com/wasamasa)*
233 The ChucK implementation has been tested with ChucK 1.3.5.2.
242 *The Common Lisp implementation was created by [Iqbal Ansari](https://github.com/iqbalansari)*
244 The implementation has been tested with SBCL, CCL, CMUCL, GNU CLISP, ECL and
245 Allegro CL on Ubuntu 16.04 and Ubuntu 12.04, see
246 the [README][common-lisp/README.org] for more details. Provided you have the
247 dependencies mentioned installed, do the following to run the implementation
257 For the most part the Clojure implementation requires Clojure 1.5,
258 however, to pass all tests, Clojure 1.8.0-RC4 is required.
262 lein with-profile +stepX trampoline run
268 sudo npm install -g coffee-script
275 *The Crystal implementation of mal was created by [Linda_pp](https://github.com/rhysd)*
277 The Crystal implementation of mal has been tested with Crystal 0.18.4.
281 crystal run ./stepX_YYY.cr
283 make # needed to run tests
289 *The D implementation was created by [Dov Murik](https://github.com/dubek)*
291 The D implementation of mal was tested with GDC 4.8. It requires the GNU
302 *The Dart implementation was created by [Harry Terkelsen](https://github.com/hterkelsen)*
304 The Dart implementation has been tested with Dart 1.20.
313 *The Emacs Lisp implementation was created by [Vasilij Schneidermann](https://github.com/wasamasa)*
315 The Emacs Lisp implementation of mal has been tested with Emacs 24.3
316 and 24.5. While there is very basic readline editing (`<backspace>`
317 and `C-d` work, `C-c` cancels the process), it is recommended to use
322 emacs -Q --batch --load stepX_YYY.el
323 # with full readline support
324 rlwrap emacs -Q --batch --load stepX_YYY.el
329 *The Elixir implementation was created by [Martin Ek (ekmartin)](https://github.com/ekmartin)*
331 The Elixir implementation of mal has been tested with Elixir 1.0.5.
336 # Or with readline/line editing functionality:
342 *The Erlang implementation was created by [Nathan Fiedler (nlfiedler)](https://github.com/nlfiedler)*
344 The Erlang implementation of mal requires [Erlang/OTP R17](http://www.erlang.org/download.html)
345 and [rebar](https://github.com/rebar/rebar) to build.
351 MAL_STEP=stepX_YYY rebar compile escriptize # build individual step
355 ### ES6 (ECMAScript 6 / ECMAScript 2015)
357 The ES6 implementation uses the [babel](https://babeljs.io) compiler
358 to generate ES5 compatible JavaScript. The generated code has been
359 tested with Node 0.12.4.
364 node build/stepX_YYY.js
370 *The F# implementation was created by [Peter Stephens (pstephens)](https://github.com/pstephens)*
372 The F# implementation of mal has been tested on Linux using the Mono
373 F# compiler (fsharpc) and the Mono runtime (version 3.12.1). The mono C#
374 compiler (mcs) is also necessary to compile the readline dependency. All are
375 required to build and run the F# implementation.
385 *The Factor implementation was created by [Jordan Lewis (jordanlewis)](https://github.com/jordanlewis)*
387 The Factor implementation of mal has been tested with Factor 0.97
388 ([factorcode.org](http://factorcode.org)).
392 FACTOR_ROOTS=. factor -run=stepX_YYY
397 *The Forth implementation was created by [Chris Houser (chouser)](https://github.com/chouser)*
406 The Go implementation of mal requires that go is installed on on the
407 path. The implementation has been tested with Go 1.3.1.
418 The Groovy implementation of mal requires Groovy to run and has been
419 tested with Groovy 1.8.6.
424 groovy ./stepX_YYY.groovy
429 *The Guile implementation was created by [Mu Lei (NalaGinrut)](https://github.com/NalaGinrut).*
433 guile -L ./ stepX_YYY.scm
438 The Haskell implementation requires the ghc compiler version 7.10.1 or
439 later and also the Haskell parsec and readline (or editline) packages.
449 The Haxe implementation of mal requires Haxe version 3.2 to compile.
450 Four different Haxe targets are supported: Neko, Python, C++, and
460 python3 ./stepX_YYY.py
471 *The Io implementation was created by [Dov Murik](https://github.com/dubek)*
473 The Io implementation of mal has been tested with Io version 20110905.
482 The Java implementation of mal requires maven2 to build.
487 mvn -quiet exec:java -Dexec.mainClass=mal.stepX_YYY
489 mvn -quiet exec:java -Dexec.mainClass=mal.stepX_YYY -Dexec.args="CMDLINE_ARGS"
502 The Julia implementation of mal requires Julia 0.4.
511 *The Kotlin implementation was created by [Javier Fernandez-Ivern](https://github.com/ivern)*
513 The Kotlin implementation of mal has been tested with Kotlin 1.0.
518 java -jar stepX_YYY.jar
523 *The Logo implementation was created by [Dov Murik](https://github.com/dubek)*
525 The Logo implementation of mal has been tested with UCBLogo 6.0.
534 Running the Lua implementation of mal requires lua 5.1 or later,
535 luarocks and the lua-rex-pcre library installed.
539 make # to build and link linenoise.so
545 Running the mal implementation of mal involves running stepA of one of
546 the other implementations and passing the mal step to run as a command
551 IMPL_STEPA_CMD ../mal/stepX_YYY.mal
564 *The Nim implementation was created by [Dennis Felsing (def-)](https://github.com/def-)*
566 The Nim implementation of mal has been tested with Nim 0.15.2.
578 The Object Pascal implementation of mal has been built and tested on
579 Linux using the Free Pascal compiler version 2.6.2 and 2.6.4.
589 The Objective C implementation of mal has been built and tested on
590 Linux using clang/LLVM 3.6. It has also been built and tested on OS
601 *The OCaml implementation was created by [Chris Houser (chouser)](https://github.com/chouser)*
611 The MATLAB implementation of mal has been tested with MATLAB version
612 R2014a on Linux. Note that MATLAB is a commercial product. It should
613 be fairly simple to support GNU Octave once it support classdef object
619 matlab -nodisplay -nosplash -nodesktop -nojvm -r "stepX_YYY();quit;"
620 # OR with command line arguments
621 matlab -nodisplay -nosplash -nodesktop -nojvm -r "stepX_YYY('arg1','arg2');quit;"
626 [miniMAL](https://github.com/kanaka/miniMAL) is small Lisp interpreter
627 implemented in less than 1024 bytes of JavaScript. To run the miniMAL
628 implementation of mal you need to download/install the miniMAL
629 interpreter (which requires Node.js).
632 # Download miniMAL and dependencies
634 export PATH=`pwd`/node_modules/minimal-lisp/:$PATH
635 # Now run mal implementation in miniMAL
641 For readline line editing support, install Term::ReadLine::Perl or
642 Term::ReadLine::Gnu from CPAN.
651 *The Perl 6 implementation was created by [Hinrik Örn Sigurðsson](https://github.com/hinrik)*
653 The Perl 6 implementation was tested on Rakudo Perl 6 2016.04.
662 The PHP implementation of mal requires the php command line interface
672 *The Picolisp implementation was created by [Vasilij Schneidermann](https://github.com/wasamasa)*
674 The Picolisp implementation requires libreadline and Picolisp 3.1.11
682 ### PL/pgSQL (Postgres SQL Procedural Language)
684 The PL/pgSQL implementation of mal requires a running Postgres server
685 (the "kanaka/mal-test-plpgsql" docker image automatically starts
686 a Postgres server). The implementation connects to the Postgres server
687 and create a database named "mal" to store tables and stored
688 procedures. The wrapper script uses the psql command to connect to the
689 server and defaults to the user "postgres" but this can be overridden
690 with the PSQL_USER environment variable. A password can be specified
691 using the PGPASSWORD environment variable. The implementation has been
692 tested with Postgres 9.4.
696 ./wrap.sh stepX_YYY.sql
698 PSQL_USER=myuser PGPASSWORD=mypass ./wrap.sh stepX_YYY.sql
701 ### PL/SQL (Oracle SQL Procedural Language)
703 The PL/pgSQL implementation of mal requires a running Oracle DB
704 server (the "kanaka/mal-test-plsql" docker image automatically
705 starts an Oracle Express server). The implementation connects to the
706 Oracle server to create types, tables and stored procedures. The
707 default SQL*Plus logon value (username/password@connect_identifier) is
708 "system/oracle" but this can be overridden with the ORACLE_LOGON
709 environment variable. The implementation has been tested with Oracle
710 Express Edition 11g Release 2. Note that any SQL*Plus connection
711 warnings (user password expiration, etc) will interfere with the
712 ability of the wrapper script to communicate with the DB.
716 ./wrap.sh stepX_YYY.sql
718 ORACLE_LOGON=myuser/mypass@ORCL ./wrap.sh stepX_YYY.sql
721 ### Postscript Level 2/3
723 The Postscript implementation of mal requires ghostscript to run. It
724 has been tested with ghostscript 9.10.
728 gs -q -dNODISPLAY -I./ stepX_YYY.ps
733 The PowerShell implementation of mal requires the PowerShell script
734 language. It has been tested with PowerShell 6.0.0 Alpha 9 on Linux.
738 powershell ./stepX_YYY.ps1
741 ### Python (2.X or 3.X)
750 You must have [rpython](https://rpython.readthedocs.org/) on your path
751 (included with [pypy](https://bitbucket.org/pypy/pypy/)).
755 make # this takes a very long time
761 The R implementation of mal requires R (r-base-core) to run.
765 make libs # to download and build rdyncall
771 The Racket implementation of mal requires the Racket
772 compiler/interpreter to run.
786 ### Rust (1.0.0 nightly)
788 The rust implementation of mal requires the rust compiler and build
789 tool (cargo) to build.
793 cargo run --release --bin stepX_YYY
798 Install scala and sbt (http://www.scala-sbt.org/0.13/tutorial/Installing-sbt-on-Linux.html):
802 sbt 'run-main stepX_YYY'
805 scala -classpath target/scala*/classes stepX_YYY
810 *The Swift implementation was created by [Keith Rollin](https://github.com/keith-rollin)*
812 The Swift implementation of mal requires the Swift 2.0 compiler (XCode
813 7.0) to build. Older versions will not work due to changes in the
814 language and standard library.
824 The Swift 3 implementation of mal requires the Swift 3.0 compiler. It
825 has been tested with Swift 3 Preview 3.
835 *The Tcl implementation was created by [Dov Murik](https://github.com/dubek)*
837 The Tcl implementation of mal requires Tcl 8.6 to run. For readline line
838 editing support, install tclreadline.
842 tclsh ./stepX_YYY.tcl
847 *The VHDL implementation was created by [Dov Murik](https://github.com/dubek)*
849 The VHDL implementation of mal has been tested with GHDL 0.29.
854 ./run_vhdl.sh ./stepX_YYY
859 *The Vimscript implementation was created by [Dov Murik](https://github.com/dubek)*
861 The Vimscript implementation of mal requires Vim 8.0 to run.
865 ./run_vimscript.sh ./stepX_YYY.vim
868 ### Visual Basic.NET ###
870 The VB.NET implementation of mal has been tested on Linux using the Mono
871 VB compiler (vbnc) and the Mono runtime (version 2.10.8.1). Both are
872 required to build and run the VB.NET implementation.
886 The are over 600 generic functional tests (for all implementations)
887 in the `tests/` directory. Each step has a corresponding test file
888 containing tests specific to that step. The `runtest.py` test harness
889 launches a Mal step implementation and then feeds the tests one at
890 a time to the implementation and compares the output/return value to
891 the expected output/return value.
893 To simplify the process of running tests, a top level Makefile is
894 provided with convenient test targets.
896 * To run all the tests across all implementations (be prepared to wait):
902 * To run all tests against a single implementation:
912 * To run tests for a single step against all implementations:
922 * To run tests for a specific step against a single implementation:
925 make "test^IMPL^stepX"
928 make "test^ruby^step3"
932 ### Self-hosted functional tests
934 * To run the functional tests in self-hosted mode, you specify `mal`
935 as the test implementation and use the `MAL_IMPL` make variable
936 to change the underlying host language (default is JavaScript):
938 make MAL_IMPL=IMPL "test^mal^step2"
941 make "test^mal^step2" # js is default
942 make MAL_IMPL=ruby "test^mal^step2"
943 make MAL_IMPL=python "test^mal^step2"
946 ### Starting the REPL
948 * To start the REPL of an implementation in a specific step:
951 make "repl^IMPL^stepX"
954 make "repl^ruby^step3"
958 * If you omit the step, then `stepA` is used:
968 * To start the REPL of the self-hosted implementation, specify `mal` as the
969 REPL implementation and use the `MAL_IMPL` make variable to change the
970 underlying host language (default is JavaScript):
972 make MAL_IMPL=IMPL "repl^mal^stepX"
975 make "repl^mal^step2" # js is default
976 make MAL_IMPL=ruby "repl^mal^step2"
977 make MAL_IMPL=python "repl^mal"
980 ### Performance tests
982 Warning: These performance tests are neither statistically valid nor
983 comprehensive; runtime performance is a not a primary goal of mal. If
984 you draw any serious conclusions from these performance tests, then
985 please contact me about some amazing oceanfront property in Kansas
986 that I'm willing to sell you for cheap.
988 * To run performance tests against a single implementation:
996 * To run performance tests against all implementations:
1001 ### Generating language statistics
1003 * To report line and byte statistics for a single implementation:
1011 * To report line and bytes statistics for general Lisp code (env, core
1014 make "stats-lisp^IMPL"
1017 make "stats-lisp^js"
1020 ## Dockerized testing
1022 Every implementation directory contains a Dockerfile to create
1023 a docker image containing all the dependencies for that
1024 implementation. In addition, the top-level Makefile contains support
1025 for running the tests target (and perf, stats, repl, etc) within
1026 a docker container for that implementation by passing *"DOCKERIZE=1"*
1027 on the make command line. For example:
1030 make DOCKERIZE=1 "test^js^step3"
1033 Existing implementations already have docker images built and pushed
1034 to the docker registry. However, if
1035 you wish to build or rebuild a docker image locally, the toplevel
1036 Makefile provides a rule for building docker images:
1039 make "docker-build^IMPL"
1044 * Docker images are named *"kanaka/mal-test-IMPL"*
1045 * JVM-based language implementations (Groovy, Java, Clojure, Scala):
1046 you will probably need to run these implementations once manually
1047 first (make DOCKERIZE=1 "repl^IMPL")before you can run tests because
1048 runtime dependencies need to be downloaded to avoid the tests timing
1049 out. These dependencies are download to dot-files in the /mal
1050 directory so they will persist between runs.
1055 Mal (make-a-lisp) is licensed under the MPL 2.0 (Mozilla Public
1056 License 2.0). See LICENSE.txt for more details.