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