Merge pull request #106 from dubek/tcl-impl
[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 43 different languages:
10
11 * GNU awk
12 * Bash shell
13 * C
14 * C++
15 * C#
16 * Clojure
17 * CoffeeScript
18 * Crystal
19 * Elixir
20 * Erlang
21 * ES6 (ECMAScript 6 / ECMAScript 2015)
22 * F#
23 * Factor
24 * Forth
25 * Go
26 * Groovy
27 * GNU Guile
28 * Haskell
29 * Java
30 * JavaScript ([Online Demo](http://kanaka.github.io/mal))
31 * Julia
32 * Kotlin
33 * Lua
34 * GNU Make
35 * mal itself
36 * MATLAB
37 * [miniMAL](https://github.com/kanaka/miniMAL)
38 * Nim
39 * OCaml
40 * Perl
41 * PHP
42 * Postscript
43 * Python
44 * RPython
45 * R
46 * Racket
47 * Ruby
48 * Rust
49 * Scala
50 * Swift
51 * Tcl
52 * Vimscript
53 * Visual Basic.NET
54
55
56 Mal is a learning tool. See the [make-a-lisp process
57 guide](process/guide.md). Each implementation of mal is separated into
58 11 incremental, self-contained (and testable) steps that demonstrate
59 core concepts of Lisp. The last step is capable of self-hosting
60 (running the mal implementation of mal).
61
62 The mal (make a lisp) steps are:
63
64 * [step0_repl](process/guide.md#step0)
65 * [step1_read_print](process/guide.md#step1)
66 * [step2_eval](process/guide.md#step2)
67 * [step3_env](process/guide.md#step3)
68 * [step4_if_fn_do](process/guide.md#step4)
69 * [step5_tco](process/guide.md#step5)
70 * [step6_file](process/guide.md#step6)
71 * [step7_quote](process/guide.md#step7)
72 * [step8_macros](process/guide.md#step8)
73 * [step9_try](process/guide.md#step9)
74 * [stepA_mal](process/guide.md#stepA)
75
76
77 Mal was presented publicly for the first time in a lightning talk at
78 Clojure West 2014 (unfortunately there is no video). See
79 mal/clojurewest2014.mal for the presentation that was given at the
80 conference (yes the presentation is a mal program).
81
82 If you are interesting in creating a mal implementation (or just
83 interested in using mal for something), please drop by the #mal
84 channel on freenode. In addition to the [make-a-lisp process
85 guide](process/guide.md) there is also a [mal/make-a-lisp
86 FAQ](docs/FAQ.md) where I attempt to answer some common questions.
87
88 ## Building/running implementations
89
90 ### GNU awk
91
92 *The GNU awk implementation was created by [Miutsuru kariya](https://github.com/kariya-mitsuru)*
93
94 The GNU awk implementation of mal has been tested with GNU awk 4.1.1.
95
96 ```
97 cd gawk
98 gawk -O -f stepX_YYY.awk
99 ```
100
101 ### Bash 4
102
103 ```
104 cd bash
105 bash stepX_YYY.sh
106 ```
107
108 ### C
109
110 The C implementation of mal requires the following libraries (lib and
111 header packages): glib, libffi6 and either the libedit or GNU readline library.
112
113 ```
114 cd c
115 make
116 ./stepX_YYY
117 ```
118
119 ### C++
120
121 *The C++ implementation was created by [Stephen Thirlwall (sdt)](https://github.com/sdt)*
122
123 The C++ implementation of mal requires g++-4.9 or clang++-3.5 and
124 a readline compatible library to build. See the `cpp/README.md` for
125 more details:
126
127 ```
128 cd cpp
129 make
130 # OR
131 make CXX=clang++-3.5
132 ./stepX_YYY
133 ```
134
135
136 ### C# ###
137
138 The C# implementation of mal has been tested on Linux using the Mono
139 C# compiler (mcs) and the Mono runtime (version 2.10.8.1). Both are
140 required to build and run the C# implementation.
141
142 ```
143 cd cs
144 make
145 mono ./stepX_YYY.exe
146 ```
147
148
149 ### Clojure
150
151 ```
152 cd clojure
153 lein with-profile +stepX trampoline run
154 ```
155
156 ### CoffeeScript
157
158 ```
159 sudo npm install -g coffee-script
160 cd coffee
161 coffee ./stepX_YYY
162 ```
163
164 ### Crystal
165
166 *The Crystal implementation of mal was created by [Linda_pp](https://github.com/rhysd)*
167
168 The Crystal implementation of mal has been tested with Crystal 0.8.0.
169
170 ```
171 cd crystal
172 crystal run ./stepX_YYY.cr
173 # OR
174 make # needed to run tests
175 ./stepX_YYY
176 ```
177
178 ### Elixir
179
180 *The Elixir implementation was created by [Martin Ek (ekmartin)](https://github.com/ekmartin)*
181
182 The Elixir implementation of mal has been tested with Elixir 1.0.5.
183
184 ```
185 cd elixir
186 mix stepX_YYY
187 # Or with readline/line editing functionality:
188 iex -S mix stepX_YYY
189 ```
190
191 ### Erlang
192
193 *The Erlang implementation was created by [Nathan Fiedler (nlfiedler)](https://github.com/nlfiedler)*
194
195 The Erlang implementation of mal requires [Erlang/OTP R17](http://www.erlang.org/download.html)
196 and [rebar](https://github.com/rebar/rebar) to build.
197
198 ```
199 cd erlang
200 make
201 # OR
202 MAL_STEP=stepX_YYY rebar compile escriptize # build individual step
203 ./stepX_YYY
204 ```
205
206 ### ES6 (ECMAScript 6 / ECMAScript 2015)
207
208 The ES6 implementation uses the [babel](https://babeljs.io) compiler
209 to generate ES5 compatible JavaScript. The generated code has been
210 tested with Node 0.12.4.
211
212 ```
213 cd es6
214 make
215 node build/stepX_YYY.js
216 ```
217
218
219 ### F# ###
220
221 *The F# implementation was created by [Peter Stephens (pstephens)](https://github.com/pstephens)*
222
223 The F# implementation of mal has been tested on Linux using the Mono
224 F# compiler (fsharpc) and the Mono runtime (version 3.12.1). The mono C#
225 compiler (mcs) is also necessary to compile the readline dependency. All are
226 required to build and run the F# implementation.
227
228 ```
229 cd fsharp
230 make
231 mono ./stepX_YYY.exe
232 ```
233
234 ### Factor
235
236 *The Factor implementation was created by [Jordan Lewis (jordanlewis)](https://github.com/jordanlewis)*
237
238 The Factor implementation of mal has been tested with Factor 0.97
239 ([factorcode.org](factorcode.org)).
240
241 ```
242 cd factor
243 FACTOR_ROOTS=. factor -run=stepX_YYY
244 ```
245
246 ### Forth
247
248 *The Forth implementation was created by [Chris Houser (chouser)](https://github.com/chouser)*
249
250 ```
251 cd forth
252 gforth stepX_YYY.fs
253 ```
254
255 ### Go
256
257 The Go implementation of mal requires that go is installed on on the
258 path. The implementation has been tested with Go 1.3.1.
259
260 ```
261 cd go
262 make
263 ./stepX_YYY
264 ```
265
266
267 ### Groovy
268
269 The Groovy implementation of mal requires Groovy to run and has been
270 tested with Groovy 1.8.6.
271
272 ```
273 cd groovy
274 make
275 groovy ./stepX_YYY.groovy
276 ```
277
278 ### GNU Guile 2.1+
279
280 *The Guile implementation was created by [Mu Lei (NalaGinrut)](https://github.com/NalaGinrut).*
281
282 ```
283 cd guile
284 guile -L ./ stepX_YYY.scm
285 ```
286
287 ### Haskell
288
289 Install the Haskell compiler (ghc/ghci), the Haskell platform and
290 either the editline package (BSD) or the readline package (GPL). On
291 Ubuntu these packages are: ghc, haskell-platform,
292 libghc-readline-dev/libghc-editline-dev
293
294 ```
295 cd haskell
296 make
297 ./stepX_YYY
298 ```
299
300
301 ### Java 1.7
302
303 The Java implementation of mal requires maven2 to build.
304
305 ```
306 cd java
307 mvn compile
308 mvn -quiet exec:java -Dexec.mainClass=mal.stepX_YYY
309 # OR
310 mvn -quiet exec:java -Dexec.mainClass=mal.stepX_YYY -Dexec.args="CMDLINE_ARGS"
311 ```
312
313 ### JavaScript/Node
314
315 ```
316 cd js
317 npm update
318 node stepX_YYY.js
319 ```
320
321 ### Julia
322
323 The Julia implementation of mal requires Julia 0.4.
324
325 ```
326 cd julia
327 julia stepX_YYY.jl
328 ```
329
330 ### Kotlin
331
332 *The Kotlin implementation was created by [Javier Fernandez-Ivern](https://github.com/ivern)*
333
334 The Kotlin implementation of mal has been tested with Kotlin 1.0.0-beta.
335
336 ```
337 cd kotlin
338 make
339 java -jar stepX_YYY.jar
340 ```
341
342 ### Lua
343
344 Running the Lua implementation of mal requires lua 5.1 or later,
345 luarocks and the lua-rex-pcre library installed.
346
347 ```
348 cd lua
349 make # to build and link linenoise.so
350 ./stepX_YYY.lua
351 ```
352
353 ### Mal
354
355 Running the mal implementation of mal involves running stepA of one of
356 the other implementations and passing the mal step to run as a command
357 line argument.
358
359 ```
360 cd IMPL
361 IMPL_STEPA_CMD ../mal/stepX_YYY.mal
362
363 ```
364
365 ### GNU Make 3.81
366
367 ```
368 cd make
369 make -f stepX_YYY.mk
370 ```
371
372 ### Nim 0.11.0
373
374 *The Nim implementation was created by [Dennis Felsing (def-)](https://github.com/def-)*
375
376 Running the Nim implementation of mal requires Nim 0.11.0 or later.
377
378 ```
379 cd nim
380 make
381 # OR
382 nimble build
383 ./stepX_YYY
384 ```
385
386 ### OCaml 4.01.0
387
388 *The OCaml implementation was created by [Chris Houser (chouser)](https://github.com/chouser)*
389
390 ```
391 cd ocaml
392 make
393 ./stepX_YYY
394 ```
395
396 ### MATLAB
397
398 The MATLAB implementation of mal has been tested with MATLAB version
399 R2014a on Linux. Note that MATLAB is a commercial product. It should
400 be fairly simple to support GNU Octave once it support classdef object
401 syntax.
402
403 ```
404 cd matlab
405 ./stepX_YYY
406 matlab -nodisplay -nosplash -nodesktop -nojvm -r "stepX_YYY();quit;"
407 # OR with command line arguments
408 matlab -nodisplay -nosplash -nodesktop -nojvm -r "stepX_YYY('arg1','arg2');quit;"
409 ```
410
411 ### miniMAL
412
413 [miniMAL](https://github.com/kanaka/miniMAL) is small Lisp interpreter
414 implemented in less than 1024 bytes of JavaScript. To run the miniMAL
415 implementation of mal you need to download/install the miniMAL
416 interpreter (which requires Node.js).
417 ```
418 cd miniMAL
419 # Download miniMAL and dependencies
420 npm install
421 export PATH=`pwd`/node_modules/minimal-lisp/:$PATH
422 # Now run mal implementation in miniMAL
423 miniMAL ./stepX_YYY
424 ```
425
426 ### Perl 5.8
427
428 For readline line editing support, install Term::ReadLine::Perl or
429 Term::ReadLine::Gnu from CPAN.
430
431 ```
432 cd perl
433 perl stepX_YYY.pl
434 ```
435
436
437 ### PHP 5.3
438
439 The PHP implementation of mal requires the php command line interface
440 to run.
441
442 ```
443 cd php
444 php stepX_YYY.php
445 ```
446
447 ### Postscript Level 2/3
448
449 The Postscript implementation of mal requires ghostscript to run. It
450 has been tested with ghostscript 9.10.
451
452 ```
453 cd ps
454 gs -q -dNODISPLAY -I./ stepX_YYY.ps
455 ```
456
457 ### Python (2.X or 3.X)
458
459 ```
460 cd python
461 python stepX_YYY.py
462 ```
463
464 ### RPython
465
466 You must have [rpython](https://rpython.readthedocs.org/) on your path
467 (included with [pypy](https://bitbucket.org/pypy/pypy/)).
468
469 ```
470 cd rpython
471 make # this takes a very long time
472 ./stepX_YYY
473 ```
474
475 ### R
476
477 The R implementation of mal requires R (r-base-core) to run.
478
479 ```
480 cd r
481 make libs # to download and build rdyncall
482 Rscript stepX_YYY.r
483 ```
484
485 ### Racket (5.3)
486
487 The Racket implementation of mal requires the Racket
488 compiler/interpreter to run.
489
490 ```
491 cd racket
492 ./stepX_YYY.rkt
493 ```
494
495 ### Ruby (1.9+)
496
497 ```
498 cd ruby
499 ruby stepX_YYY.rb
500 ```
501
502 ### Rust (1.0.0 nightly)
503
504 The rust implementation of mal requires the rust compiler and build
505 tool (cargo) to build.
506
507 ```
508 cd rust
509 cargo run --release --bin stepX_YYY
510 ```
511
512 ### Scala ###
513
514 Install scala and sbt (http://www.scala-sbt.org/0.13/tutorial/Installing-sbt-on-Linux.html):
515
516 ```
517 cd scala
518 sbt 'run-main stepX_YYY'
519 # OR
520 sbt compile
521 scala -classpath target/scala*/classes stepX_YYY
522 ```
523
524 ### Swift
525
526 *The Swift implementation was created by [Keith Rollin](https://github.com/keith-rollin)*
527
528 The Swift implementation of mal requires the Swift 2.0 compiler (XCode
529 7.0) to build. Older versions will not work due to changes in the
530 language and standard library.
531
532 ```
533 cd swift
534 make
535 ./stepX_YYY
536 ```
537
538 ### Tcl 8.6
539
540 *The Tcl implementation was created by [Dov Murik](https://github.com/dubek)*
541
542 The Tcl implementation of mal requires Tcl 8.6 to run. For readline line
543 editing support, install tclreadline.
544
545 ```
546 cd tcl
547 tclsh ./stepX_YYY.tcl
548 ```
549
550 ### Vimscript
551
552 *The Vimscript implementation was created by [Dov Murik](https://github.com/dubek)*
553
554 The Vimscript implementation of mal requires Vim to run. It has been tested
555 with Vim 7.4.
556
557 ```
558 cd vimscript
559 ./run_vimscript.sh ./stepX_YYY.vim
560 ```
561
562 ### Visual Basic.NET ###
563
564 The VB.NET implementation of mal has been tested on Linux using the Mono
565 VB compiler (vbnc) and the Mono runtime (version 2.10.8.1). Both are
566 required to build and run the VB.NET implementation.
567
568 ```
569 cd vb
570 make
571 mono ./stepX_YYY.exe
572 ```
573
574
575
576 ## Running tests
577
578 ### Functional tests
579
580 The are nearly 500 generic functional tests (for all implementations)
581 in the `tests/` directory. Each step has a corresponding test file
582 containing tests specific to that step. The `runtest.py` test harness
583 launches a Mal step implementation and then feeds the tests one at
584 a time to the implementation and compares the output/return value to
585 the expected output/return value.
586
587 To simplify the process of running tests, a top level Makefile is
588 provided with convenient test targets.
589
590 * To run all the tests across all implementations (be prepared to wait):
591
592 ```
593 make test
594 ```
595
596 * To run all tests against a single implementation:
597
598 ```
599 make test^IMPL
600
601 # e.g.
602 make test^clojure
603 make test^js
604 ```
605
606 * To run tests for a single step against all implementations:
607
608 ```
609 make test^stepX
610
611 # e.g.
612 make test^step2
613 make test^step7
614 ```
615
616 * To run tests for a specific step against a single implementation:
617
618 ```
619 make test^IMPL^stepX
620
621 # e.g
622 make test^ruby^step3
623 make test^ps^step4
624 ```
625
626 ### Self-hosted functional tests
627
628 * To run the functional tests in self-hosted mode, you specify `mal`
629 as the test implementation and use the `MAL_IMPL` make variable
630 to change the underlying host language (default is JavaScript):
631 ```
632 make MAL_IMPL=IMPL test^mal^step2
633
634 # e.g.
635 make test^mal^step2 # js is default
636 make MAL_IMPL=ruby test^mal^step2
637 make MAL_IMPL=python test^mal^step2
638 ```
639
640
641 ### Performance tests
642
643 Warning: These performance tests are neither statistically valid nor
644 comprehensive; runtime performance is a not a primary goal of mal. If
645 you draw any serious conclusions from these performance tests, then
646 please contact me about some amazing oceanfront property in Kansas
647 that I'm willing to sell you for cheap.
648
649 * To run performance tests against a single implementation:
650 ```
651 make perf^IMPL
652
653 # e.g.
654 make perf^js
655 ```
656
657 * To run performance tests against all implementations:
658 ```
659 make perf
660 ```
661
662 ### Generating language statistics
663
664 * To report line and byte statistics for a single implementation:
665 ```
666 make stats^IMPL
667
668 # e.g.
669 make stats^js
670 ```
671
672 * To report line and bytes statistics for general Lisp code (env, core
673 and stepA):
674 ```
675 make stats-lisp^IMPL
676
677 # e.g.
678 make stats-lisp^js
679 ```
680
681 ## Docker test environment
682
683 There is a Dockerfile included in the `tests/docker` directory that
684 builds a docker image based on Ubuntu Utopic that contains everything
685 needed to run tests against all the implementations (except for MATLAB
686 which is proprietary/licensed).
687
688 Build the docker image using a provided script. WARNING: this will
689 likely take over an hour to build from scratch and use more 3 GB of disk:
690 ```bash
691 ./tests/docker-build.sh
692 ```
693
694 Launch a docker container from that image built above. This will
695 volume mount the mal directory to `/mal` and then give you a bash
696 prompt in the container. You can then run individual mal
697 implementations and tests:
698 ```bash
699 ./tests/docker-run.sh
700 ```
701
702 You can also specify a command to run within the container. For
703 example, to run step2 tests for every implementation (except MATLAB):
704 ```bash
705 ./tests/docker-run.sh make SKIP_IMPLS="matlab" test^step2
706 ```
707
708 **Notes**:
709 * JVM-based language implementations (Java, Clojure, Scala): you will
710 need to run these implementations once manually first before you can
711 run tests because runtime dependencies need to be downloaded to
712 avoid the tests timing out. These dependencies are download to
713 dot-files in the /mal directory so they will persist between runs.
714 * Compiled languages: if your host system is different enough from
715 Ubuntu Utopic then you may need to re-compile your compiled
716 languages from within the container to avoid linker version
717 mismatches.
718
719
720 ## License
721
722 Mal (make-a-lisp) is licensed under the MPL 2.0 (Mozilla Public
723 License 2.0). See LICENSE.txt for more details.