Logo implementation
[jackhill/mal.git] / README.md
1 # mal - Make a Lisp
2
3 [![Build Status](https://travis-ci.org/kanaka/mal.svg?branch=master)](https://travis-ci.org/kanaka/mal)
4
5 ## Description
6
7 Mal is a Clojure inspired Lisp interpreter.
8
9 Mal is implemented in 56 languages:
10
11 * Ada
12 * GNU awk
13 * Bash shell
14 * C
15 * C++
16 * C#
17 * Clojure
18 * CoffeeScript
19 * Crystal
20 * D
21 * Elixir
22 * Emacs Lisp
23 * Erlang
24 * ES6 (ECMAScript 6 / ECMAScript 2015)
25 * F#
26 * Factor
27 * Forth
28 * Go
29 * Groovy
30 * GNU Guile
31 * Haskell
32 * Haxe
33 * Io
34 * Java
35 * JavaScript ([Online Demo](http://kanaka.github.io/mal))
36 * Julia
37 * Kotlin
38 * Logo
39 * Lua
40 * GNU Make
41 * mal itself
42 * MATLAB
43 * [miniMAL](https://github.com/kanaka/miniMAL)
44 * Nim
45 * Object Pascal
46 * Objective C
47 * OCaml
48 * Perl
49 * Perl 6
50 * PHP
51 * PL/pgSQL (Postgres)
52 * PL/SQL (Oracle)
53 * Postscript
54 * Python
55 * RPython
56 * R
57 * Racket
58 * Ruby
59 * Rust
60 * Scala
61 * Swift
62 * Swift 3
63 * Tcl
64 * VHDL
65 * Vimscript
66 * Visual Basic.NET
67
68
69 Mal is a learning tool. See the [make-a-lisp process
70 guide](process/guide.md). Each implementation of mal is separated into
71 11 incremental, self-contained (and testable) steps that demonstrate
72 core concepts of Lisp. The last step is capable of self-hosting
73 (running the mal implementation of mal).
74
75 The mal (make a lisp) steps are:
76
77 * [step0_repl](process/guide.md#step0)
78 * [step1_read_print](process/guide.md#step1)
79 * [step2_eval](process/guide.md#step2)
80 * [step3_env](process/guide.md#step3)
81 * [step4_if_fn_do](process/guide.md#step4)
82 * [step5_tco](process/guide.md#step5)
83 * [step6_file](process/guide.md#step6)
84 * [step7_quote](process/guide.md#step7)
85 * [step8_macros](process/guide.md#step8)
86 * [step9_try](process/guide.md#step9)
87 * [stepA_mal](process/guide.md#stepA)
88
89
90 Mal was presented publicly for the first time in a lightning talk at
91 Clojure West 2014 (unfortunately there is no video). See
92 examples/clojurewest2014.mal for the presentation that was given at the
93 conference (yes the presentation is a mal program). At Midwest.io
94 2015, Joel Martin gave a presentation on Mal titled "Achievement
95 Unlocked: A Better Path to Language Learning".
96 [Video](https://www.youtube.com/watch?v=lgyOAiRtZGw),
97 [Slides](http://kanaka.github.io/midwest.io.mal/).
98
99 If you are interesting in creating a mal implementation (or just
100 interested in using mal for something), please drop by the #mal
101 channel on freenode. In addition to the [make-a-lisp process
102 guide](process/guide.md) there is also a [mal/make-a-lisp
103 FAQ](docs/FAQ.md) where I attempt to answer some common questions.
104
105 ## Building/running implementations
106
107 The simplest way to run any given implementation is to use docker.
108 Every implementation has a docker image pre-built with language
109 dependencies installed. You can launch the REPL using a convenience
110 target in the top level Makefile (where IMPL is the implementation
111 directory name and stepX is the step to run):
112
113 ```
114 make DOCKERIZE=1 "repl^IMPL^stepX"
115 # OR stepA is the default step:
116 make DOCKERIZE=1 "repl^IMPL"
117 ```
118
119
120 ### Ada
121
122 *The Ada implementation was created by [Chris Moore](https://github.com/zmower)*
123
124 The Ada implementation was developed with GNAT 4.9 on debian. It also
125 compiles unchanged on windows if you have windows versions of git,
126 GNAT and (optionally) make. There are no external dependencies
127 (readline not implemented).
128
129 ```
130 cd ada
131 make
132 ./stepX_YYY
133 ```
134
135 ### GNU awk
136
137 *The GNU awk implementation was created by [Miutsuru kariya](https://github.com/kariya-mitsuru)*
138
139 The GNU awk implementation of mal has been tested with GNU awk 4.1.1.
140
141 ```
142 cd gawk
143 gawk -O -f stepX_YYY.awk
144 ```
145
146 ### Bash 4
147
148 ```
149 cd bash
150 bash stepX_YYY.sh
151 ```
152
153 ### C
154
155 The C implementation of mal requires the following libraries (lib and
156 header packages): glib, libffi6, libgc, and either the libedit or GNU readline
157 library.
158
159 ```
160 cd c
161 make
162 ./stepX_YYY
163 ```
164
165 ### C++
166
167 *The C++ implementation was created by [Stephen Thirlwall (sdt)](https://github.com/sdt)*
168
169 The C++ implementation of mal requires g++-4.9 or clang++-3.5 and
170 a readline compatible library to build. See the `cpp/README.md` for
171 more details:
172
173 ```
174 cd cpp
175 make
176 # OR
177 make CXX=clang++-3.5
178 ./stepX_YYY
179 ```
180
181
182 ### C# ###
183
184 The C# implementation of mal has been tested on Linux using the Mono
185 C# compiler (mcs) and the Mono runtime (version 2.10.8.1). Both are
186 required to build and run the C# implementation.
187
188 ```
189 cd cs
190 make
191 mono ./stepX_YYY.exe
192 ```
193
194
195 ### Clojure
196
197 For the most part the Clojure implementation requires Clojure 1.5,
198 however, to pass all tests, Clojure 1.8.0-RC4 is required.
199
200 ```
201 cd clojure
202 lein with-profile +stepX trampoline run
203 ```
204
205 ### CoffeeScript
206
207 ```
208 sudo npm install -g coffee-script
209 cd coffee
210 coffee ./stepX_YYY
211 ```
212
213 ### Crystal
214
215 *The Crystal implementation of mal was created by [Linda_pp](https://github.com/rhysd)*
216
217 The Crystal implementation of mal has been tested with Crystal 0.17.4.
218
219 ```
220 cd crystal
221 crystal run ./stepX_YYY.cr
222 # OR
223 make # needed to run tests
224 ./stepX_YYY
225 ```
226
227 ### D
228
229 *The D implementation was created by [Dov Murik](https://github.com/dubek)*
230
231 The D implementation of mal was tested with GDC 4.8. It requires the GNU
232 readline library.
233
234 ```
235 cd d
236 make
237 ./stepX_YYY
238 ```
239
240 ### Emacs Lisp
241
242 *The Emacs Lisp implementation was created by [Vasilij Schneidermann](https://github.com/wasamasa)*
243
244 The Emacs Lisp implementation of mal has been tested with Emacs 24.3
245 and 24.5. While there is very basic readline editing (`<backspace>`
246 and `C-d` work, `C-c` cancels the process), it is recommended to use
247 `rlwrap`.
248
249 ```
250 cd elisp
251 emacs -Q --batch --load stepX_YYY.el
252 # with full readline support
253 rlwrap emacs -Q --batch --load stepX_YYY.el
254 ```
255
256 ### Elixir
257
258 *The Elixir implementation was created by [Martin Ek (ekmartin)](https://github.com/ekmartin)*
259
260 The Elixir implementation of mal has been tested with Elixir 1.0.5.
261
262 ```
263 cd elixir
264 mix stepX_YYY
265 # Or with readline/line editing functionality:
266 iex -S mix stepX_YYY
267 ```
268
269 ### Erlang
270
271 *The Erlang implementation was created by [Nathan Fiedler (nlfiedler)](https://github.com/nlfiedler)*
272
273 The Erlang implementation of mal requires [Erlang/OTP R17](http://www.erlang.org/download.html)
274 and [rebar](https://github.com/rebar/rebar) to build.
275
276 ```
277 cd erlang
278 make
279 # OR
280 MAL_STEP=stepX_YYY rebar compile escriptize # build individual step
281 ./stepX_YYY
282 ```
283
284 ### ES6 (ECMAScript 6 / ECMAScript 2015)
285
286 The ES6 implementation uses the [babel](https://babeljs.io) compiler
287 to generate ES5 compatible JavaScript. The generated code has been
288 tested with Node 0.12.4.
289
290 ```
291 cd es6
292 make
293 node build/stepX_YYY.js
294 ```
295
296
297 ### F# ###
298
299 *The F# implementation was created by [Peter Stephens (pstephens)](https://github.com/pstephens)*
300
301 The F# implementation of mal has been tested on Linux using the Mono
302 F# compiler (fsharpc) and the Mono runtime (version 3.12.1). The mono C#
303 compiler (mcs) is also necessary to compile the readline dependency. All are
304 required to build and run the F# implementation.
305
306 ```
307 cd fsharp
308 make
309 mono ./stepX_YYY.exe
310 ```
311
312 ### Factor
313
314 *The Factor implementation was created by [Jordan Lewis (jordanlewis)](https://github.com/jordanlewis)*
315
316 The Factor implementation of mal has been tested with Factor 0.97
317 ([factorcode.org](http://factorcode.org)).
318
319 ```
320 cd factor
321 FACTOR_ROOTS=. factor -run=stepX_YYY
322 ```
323
324 ### Forth
325
326 *The Forth implementation was created by [Chris Houser (chouser)](https://github.com/chouser)*
327
328 ```
329 cd forth
330 gforth stepX_YYY.fs
331 ```
332
333 ### Go
334
335 The Go implementation of mal requires that go is installed on on the
336 path. The implementation has been tested with Go 1.3.1.
337
338 ```
339 cd go
340 make
341 ./stepX_YYY
342 ```
343
344
345 ### Groovy
346
347 The Groovy implementation of mal requires Groovy to run and has been
348 tested with Groovy 1.8.6.
349
350 ```
351 cd groovy
352 make
353 groovy ./stepX_YYY.groovy
354 ```
355
356 ### GNU Guile 2.1+
357
358 *The Guile implementation was created by [Mu Lei (NalaGinrut)](https://github.com/NalaGinrut).*
359
360 ```
361 cd guile
362 guile -L ./ stepX_YYY.scm
363 ```
364
365 ### Haskell
366
367 Install the Haskell compiler (ghc/ghci), the Haskell platform and
368 either the editline package (BSD) or the readline package (GPL). On
369 Ubuntu these packages are: ghc, haskell-platform,
370 libghc-readline-dev/libghc-editline-dev
371
372 ```
373 cd haskell
374 make
375 ./stepX_YYY
376 ```
377
378 ### Haxe
379
380 The Haxe implementation of mal requires Haxe version 3.2 to compile.
381 Four different Haxe targets are supported: Neko, Python, C++, and
382 JavaScript.
383
384 ```
385 cd haxe
386 # Neko
387 make all-neko
388 neko ./stepX_YYY.n
389 # Python
390 make all-python
391 python3 ./stepX_YYY.py
392 # C++
393 make all-cpp
394 ./cpp/stepX_YYY
395 # JavaScript
396 make all-js
397 node ./stepX_YYY.js
398 ```
399
400 ### Io
401
402 *The Io implementation was created by [Dov Murik](https://github.com/dubek)*
403
404 The Io implementation of mal has been tested with Io version 20110905.
405
406 ```
407 cd io
408 io ./stepX_YYY.io
409 ```
410
411 ### Java 1.7
412
413 The Java implementation of mal requires maven2 to build.
414
415 ```
416 cd java
417 mvn compile
418 mvn -quiet exec:java -Dexec.mainClass=mal.stepX_YYY
419 # OR
420 mvn -quiet exec:java -Dexec.mainClass=mal.stepX_YYY -Dexec.args="CMDLINE_ARGS"
421 ```
422
423 ### JavaScript/Node
424
425 ```
426 cd js
427 npm update
428 node stepX_YYY.js
429 ```
430
431 ### Julia
432
433 The Julia implementation of mal requires Julia 0.4.
434
435 ```
436 cd julia
437 julia stepX_YYY.jl
438 ```
439
440 ### Kotlin
441
442 *The Kotlin implementation was created by [Javier Fernandez-Ivern](https://github.com/ivern)*
443
444 The Kotlin implementation of mal has been tested with Kotlin 1.0.
445
446 ```
447 cd kotlin
448 make
449 java -jar stepX_YYY.jar
450 ```
451
452 ### Logo
453
454 *The Logo implementation was created by [Dov Murik](https://github.com/dubek)*
455
456 The Logo implementation of mal has been tested with UCBLogo 6.0.
457
458 ```
459 cd logo
460 logo stepX_YYY.lg
461 ```
462
463 ### Lua
464
465 Running the Lua implementation of mal requires lua 5.1 or later,
466 luarocks and the lua-rex-pcre library installed.
467
468 ```
469 cd lua
470 make # to build and link linenoise.so
471 ./stepX_YYY.lua
472 ```
473
474 ### Mal
475
476 Running the mal implementation of mal involves running stepA of one of
477 the other implementations and passing the mal step to run as a command
478 line argument.
479
480 ```
481 cd IMPL
482 IMPL_STEPA_CMD ../mal/stepX_YYY.mal
483
484 ```
485
486 ### GNU Make 3.81
487
488 ```
489 cd make
490 make -f stepX_YYY.mk
491 ```
492
493 ### Nim 0.11.0
494
495 *The Nim implementation was created by [Dennis Felsing (def-)](https://github.com/def-)*
496
497 Running the Nim implementation of mal requires Nim 0.11.0 or later.
498
499 ```
500 cd nim
501 make
502 # OR
503 nimble build
504 ./stepX_YYY
505 ```
506
507 ### Object Pascal
508
509 The Object Pascal implementation of mal has been built and tested on
510 Linux using the Free Pascal compiler version 2.6.2 and 2.6.4.
511
512 ```
513 cd objpascal
514 make
515 ./stepX_YYY
516 ```
517
518 ### Objective C
519
520 The Objective C implementation of mal has been built and tested on
521 Linux using clang/LLVM 3.6. It has also been built and tested on OS
522 X using XCode 7.
523
524 ```
525 cd objc
526 make
527 ./stepX_YYY
528 ```
529
530 ### OCaml 4.01.0
531
532 *The OCaml implementation was created by [Chris Houser (chouser)](https://github.com/chouser)*
533
534 ```
535 cd ocaml
536 make
537 ./stepX_YYY
538 ```
539
540 ### MATLAB
541
542 The MATLAB implementation of mal has been tested with MATLAB version
543 R2014a on Linux. Note that MATLAB is a commercial product. It should
544 be fairly simple to support GNU Octave once it support classdef object
545 syntax.
546
547 ```
548 cd matlab
549 ./stepX_YYY
550 matlab -nodisplay -nosplash -nodesktop -nojvm -r "stepX_YYY();quit;"
551 # OR with command line arguments
552 matlab -nodisplay -nosplash -nodesktop -nojvm -r "stepX_YYY('arg1','arg2');quit;"
553 ```
554
555 ### miniMAL
556
557 [miniMAL](https://github.com/kanaka/miniMAL) is small Lisp interpreter
558 implemented in less than 1024 bytes of JavaScript. To run the miniMAL
559 implementation of mal you need to download/install the miniMAL
560 interpreter (which requires Node.js).
561 ```
562 cd miniMAL
563 # Download miniMAL and dependencies
564 npm install
565 export PATH=`pwd`/node_modules/minimal-lisp/:$PATH
566 # Now run mal implementation in miniMAL
567 miniMAL ./stepX_YYY
568 ```
569
570 ### Perl 5.8
571
572 For readline line editing support, install Term::ReadLine::Perl or
573 Term::ReadLine::Gnu from CPAN.
574
575 ```
576 cd perl
577 perl stepX_YYY.pl
578 ```
579
580 ### Perl 6
581
582 *The Perl 6 implementation was created by [Hinrik Örn Sigurðsson](https://github.com/hinrik)*
583
584 The Perl 6 implementation was tested on Rakudo Perl 6 2016.04.
585
586 ```
587 cd perl6
588 perl6 stepX_YYY.pl
589 ```
590
591 ### PHP 5.3
592
593 The PHP implementation of mal requires the php command line interface
594 to run.
595
596 ```
597 cd php
598 php stepX_YYY.php
599 ```
600
601 ### Postscript Level 2/3
602
603 The Postscript implementation of mal requires ghostscript to run. It
604 has been tested with ghostscript 9.10.
605
606 ```
607 cd ps
608 gs -q -dNODISPLAY -I./ stepX_YYY.ps
609 ```
610
611 ### PL/pgSQL (Postgres SQL Procedural Language)
612
613 The PL/pgSQL implementation of mal requires a running Postgres server
614 (the "kanaka/mal-test-plpgsql" docker image automatically starts
615 a Postgres server). The implementation connects to the Postgres server
616 and create a database named "mal" to store tables and stored
617 procedures. The wrapper script uses the psql command to connect to the
618 server and defaults to the user "postgres" but this can be overridden
619 with the PSQL_USER environment variable. A password can be specified
620 using the PGPASSWORD environment variable. The implementation has been
621 tested with Postgres 9.4.
622
623 ```
624 cd plpgsql
625 ./wrap.sh stepX_YYY.sql
626 # OR
627 PSQL_USER=myuser PGPASSWORD=mypass ./wrap.sh stepX_YYY.sql
628 ```
629
630 ### PL/SQL (Oracle SQL Procedural Language)
631
632 The PL/pgSQL implementation of mal requires a running Oracle DB
633 server (the "kanaka/mal-test-plsql" docker image automatically
634 starts an Oracle Express server). The implementation connects to the
635 Oracle server to create types, tables and stored procedures. The
636 default SQL*Plus logon value (username/password@connect_identifier) is
637 "system/oracle" but this can be overridden with the ORACLE_LOGON
638 environment variable. The implementation has been tested with Oracle
639 Express Edition 11g Release 2. Note that any SQL*Plus connection
640 warnings (user password expiration, etc) will interfere with the
641 ability of the wrapper script to communicate with the DB.
642
643 ```
644 cd plsql
645 ./wrap.sh stepX_YYY.sql
646 # OR
647 ORACLE_LOGON=myuser/mypass@ORCL ./wrap.sh stepX_YYY.sql
648 ```
649
650 ### Python (2.X or 3.X)
651
652 ```
653 cd python
654 python stepX_YYY.py
655 ```
656
657 ### RPython
658
659 You must have [rpython](https://rpython.readthedocs.org/) on your path
660 (included with [pypy](https://bitbucket.org/pypy/pypy/)).
661
662 ```
663 cd rpython
664 make # this takes a very long time
665 ./stepX_YYY
666 ```
667
668 ### R
669
670 The R implementation of mal requires R (r-base-core) to run.
671
672 ```
673 cd r
674 make libs # to download and build rdyncall
675 Rscript stepX_YYY.r
676 ```
677
678 ### Racket (5.3)
679
680 The Racket implementation of mal requires the Racket
681 compiler/interpreter to run.
682
683 ```
684 cd racket
685 ./stepX_YYY.rkt
686 ```
687
688 ### Ruby (1.9+)
689
690 ```
691 cd ruby
692 ruby stepX_YYY.rb
693 ```
694
695 ### Rust (1.0.0 nightly)
696
697 The rust implementation of mal requires the rust compiler and build
698 tool (cargo) to build.
699
700 ```
701 cd rust
702 cargo run --release --bin stepX_YYY
703 ```
704
705 ### Scala ###
706
707 Install scala and sbt (http://www.scala-sbt.org/0.13/tutorial/Installing-sbt-on-Linux.html):
708
709 ```
710 cd scala
711 sbt 'run-main stepX_YYY'
712 # OR
713 sbt compile
714 scala -classpath target/scala*/classes stepX_YYY
715 ```
716
717 ### Swift
718
719 *The Swift implementation was created by [Keith Rollin](https://github.com/keith-rollin)*
720
721 The Swift implementation of mal requires the Swift 2.0 compiler (XCode
722 7.0) to build. Older versions will not work due to changes in the
723 language and standard library.
724
725 ```
726 cd swift
727 make
728 ./stepX_YYY
729 ```
730
731 ### Swift 3
732
733 The Swift 3 implementation of mal requires the Swift 3.0 compiler. It
734 has been tested with the development version of the Swift 3 from
735 2016-02-08.
736
737 ```
738 cd swift3
739 make
740 ./stepX_YYY
741 ```
742
743 ### Tcl 8.6
744
745 *The Tcl implementation was created by [Dov Murik](https://github.com/dubek)*
746
747 The Tcl implementation of mal requires Tcl 8.6 to run. For readline line
748 editing support, install tclreadline.
749
750 ```
751 cd tcl
752 tclsh ./stepX_YYY.tcl
753 ```
754
755 ### VHDL
756
757 *The VHDL implementation was created by [Dov Murik](https://github.com/dubek)*
758
759 The VHDL implementation of mal has been tested with GHDL 0.29.
760
761 ```
762 cd vhdl
763 make
764 ./run_vhdl.sh ./stepX_YYY
765 ```
766
767 ### Vimscript
768
769 *The Vimscript implementation was created by [Dov Murik](https://github.com/dubek)*
770
771 The Vimscript implementation of mal requires Vim to run. It has been tested
772 with Vim 7.4.
773
774 ```
775 cd vimscript
776 ./run_vimscript.sh ./stepX_YYY.vim
777 ```
778
779 ### Visual Basic.NET ###
780
781 The VB.NET implementation of mal has been tested on Linux using the Mono
782 VB compiler (vbnc) and the Mono runtime (version 2.10.8.1). Both are
783 required to build and run the VB.NET implementation.
784
785 ```
786 cd vb
787 make
788 mono ./stepX_YYY.exe
789 ```
790
791
792
793 ## Running tests
794
795 ### Functional tests
796
797 The are over 600 generic functional tests (for all implementations)
798 in the `tests/` directory. Each step has a corresponding test file
799 containing tests specific to that step. The `runtest.py` test harness
800 launches a Mal step implementation and then feeds the tests one at
801 a time to the implementation and compares the output/return value to
802 the expected output/return value.
803
804 To simplify the process of running tests, a top level Makefile is
805 provided with convenient test targets.
806
807 * To run all the tests across all implementations (be prepared to wait):
808
809 ```
810 make test
811 ```
812
813 * To run all tests against a single implementation:
814
815 ```
816 make "test^IMPL"
817
818 # e.g.
819 make "test^clojure"
820 make "test^js"
821 ```
822
823 * To run tests for a single step against all implementations:
824
825 ```
826 make "test^stepX"
827
828 # e.g.
829 make "test^step2"
830 make "test^step7"
831 ```
832
833 * To run tests for a specific step against a single implementation:
834
835 ```
836 make "test^IMPL^stepX"
837
838 # e.g
839 make "test^ruby^step3"
840 make "test^ps^step4"
841 ```
842
843 ### Self-hosted functional tests
844
845 * To run the functional tests in self-hosted mode, you specify `mal`
846 as the test implementation and use the `MAL_IMPL` make variable
847 to change the underlying host language (default is JavaScript):
848 ```
849 make MAL_IMPL=IMPL "test^mal^step2"
850
851 # e.g.
852 make "test^mal^step2" # js is default
853 make MAL_IMPL=ruby "test^mal^step2"
854 make MAL_IMPL=python "test^mal^step2"
855 ```
856
857 ### Starting the REPL
858
859 * To start the REPL of an implementation in a specific step:
860
861 ```
862 make "repl^IMPL^stepX"
863
864 # e.g
865 make "repl^ruby^step3"
866 make "repl^ps^step4"
867 ```
868
869 * If you omit the step, then `stepA` is used:
870
871 ```
872 make "repl^IMPL"
873
874 # e.g
875 make "repl^ruby"
876 make "repl^ps"
877 ```
878
879 * To start the REPL of the self-hosted implementation, specify `mal` as the
880 REPL implementation and use the `MAL_IMPL` make variable to change the
881 underlying host language (default is JavaScript):
882 ```
883 make MAL_IMPL=IMPL "repl^mal^stepX"
884
885 # e.g.
886 make "repl^mal^step2" # js is default
887 make MAL_IMPL=ruby "repl^mal^step2"
888 make MAL_IMPL=python "repl^mal"
889 ```
890
891 ### Performance tests
892
893 Warning: These performance tests are neither statistically valid nor
894 comprehensive; runtime performance is a not a primary goal of mal. If
895 you draw any serious conclusions from these performance tests, then
896 please contact me about some amazing oceanfront property in Kansas
897 that I'm willing to sell you for cheap.
898
899 * To run performance tests against a single implementation:
900 ```
901 make "perf^IMPL"
902
903 # e.g.
904 make "perf^js"
905 ```
906
907 * To run performance tests against all implementations:
908 ```
909 make "perf"
910 ```
911
912 ### Generating language statistics
913
914 * To report line and byte statistics for a single implementation:
915 ```
916 make "stats^IMPL"
917
918 # e.g.
919 make "stats^js"
920 ```
921
922 * To report line and bytes statistics for general Lisp code (env, core
923 and stepA):
924 ```
925 make "stats-lisp^IMPL"
926
927 # e.g.
928 make "stats-lisp^js"
929 ```
930
931 ## Dockerized testing
932
933 Every implementation directory contains a Dockerfile to create
934 a docker image containing all the dependencies for that
935 implementation. In addition, the top-level Makefile contains support
936 for running the tests target (and perf, stats, repl, etc) within
937 a docker container for that implementation by passing *"DOCKERIZE=1"*
938 on the make command line. For example:
939
940 ```
941 make DOCKERIZE=1 "test^js^step3"
942 ```
943
944 Existing implementations already have docker images built and pushed
945 to the docker registry. However, if
946 you wish to build or rebuild a docker image locally, the toplevel
947 Makefile provides a rule for building docker images:
948
949 ```
950 make "docker-build^IMPL"
951 ```
952
953
954 **Notes**:
955 * Docker images are named *"kanaka/mal-test-IMPL"*
956 * JVM-based language implementations (Groovy, Java, Clojure, Scala):
957 you will probably need to run these implementations once manually
958 first (make DOCKERIZE=1 "repl^IMPL")before you can run tests because
959 runtime dependencies need to be downloaded to avoid the tests timing
960 out. These dependencies are download to dot-files in the /mal
961 directory so they will persist between runs.
962
963
964 ## License
965
966 Mal (make-a-lisp) is licensed under the MPL 2.0 (Mozilla Public
967 License 2.0). See LICENSE.txt for more details.