factor: step 3
[jackhill/mal.git] / README.md
CommitLineData
60154d24
JM
1# mal - Make a Lisp
2
bcddc3e4
JM
3## Description
4
27696157 5Mal is a Clojure inspired Lisp interpreter.
b76aa73b 6
39381792 7Mal is implemented in 30 different languages:
bcddc3e4 8
edc3b064 9* Bash shell
bcddc3e4 10* C
73fc9366 11* C++
edc3b064
JM
12* C#
13* Clojure
891c3f3b 14* CoffeeScript
96032890 15* Forth
1771ab50 16* Go
b76aa73b 17* Haskell
bcddc3e4 18* Java
39381792
JM
19* JavaScript ([Online Demo](http://kanaka.github.io/mal))
20* Julia
9d42904e 21* Lua
bcddc3e4
JM
22* GNU Make
23* mal itself
8a9d0a8a 24* MATLAB
1218ce98 25* [miniMAL](https://github.com/kanaka/miniMAL)
a2cd0a3a 26* Nim
bc6448bc 27* OCaml
6301e0b6 28* Perl
edc3b064
JM
29* PHP
30* Postscript
31* Python
9b3362e8 32* R
f5223195 33* Racket
8adb0827 34* Ruby
abdd56eb 35* Rust
821930db 36* Scala
8b142f08 37* Swift
ee7cd585 38* Visual Basic.NET
bcddc3e4
JM
39
40
bd08422d
JM
41Mal is a learning tool. See the [make-a-lisp process
42guide](process/guide.md). Each implementation of mal is separated into
4311 incremental, self-contained (and testable) steps that demonstrate
44core concepts of Lisp. The last step is capable of self-hosting
45(running the mal implementation of mal).
bcddc3e4
JM
46
47The mal (make a lisp) steps are:
48
0f4ca9d1
JM
49* [step0_repl](process/guide.md#step0)
50* [step1_read_print](process/guide.md#step1)
51* [step2_eval](process/guide.md#step2)
52* [step3_env](process/guide.md#step3)
53* [step4_if_fn_do](process/guide.md#step4)
54* [step5_tco](process/guide.md#step5)
55* [step6_file](process/guide.md#step6)
56* [step7_quote](process/guide.md#step7)
57* [step8_macros](process/guide.md#step8)
58* [step9_try](process/guide.md#step9)
90f618cb 59* [stepA_mal](process/guide.md#stepA)
bcddc3e4
JM
60
61
62Mal was presented publicly for the first time in a lightning talk at
63Clojure West 2014 (unfortunately there is no video). See
64mal/clojurewest2014.mal for the presentation that was given at the
65conference (yes the presentation is a mal program).
60154d24 66
144f2b6a 67If you are interesting in creating a mal implementation (or just
bd62ff74 68interested in using mal for something), please drop by the #mal
144f2b6a
JM
69channel on freenode. In addition to the [make-a-lisp process
70guide](process/guide.md) there is also a [mal/make-a-lisp
71FAQ](docs/FAQ.md) where I attempt to answer some common questions.
72
60154d24
JM
73## Building/running implementations
74
bcddc3e4 75### Bash 4
60154d24
JM
76
77```
78cd bash
79bash stepX_YYY.sh
80```
81
bcddc3e4 82### C
60154d24 83
01c97316
JM
84The C implementation of mal requires the following libraries (lib and
85header packages): glib, libffi6 and either the libedit or GNU readline library.
54c75382 86
60154d24
JM
87```
88cd c
89make
90./stepX_YYY
91```
92
73fc9366
JM
93### C++
94
a848d783
JM
95*The C++ implementation was created by [Stephen Thirlwall (sdt)](https://github.com/sdt)*
96
73fc9366
JM
97The C++ implementation of mal requires g++-4.9 or clang++-3.5 and
98a readline compatible library to build. See the `cpp/README.md` for
99more details:
100
101```
102cd cpp
103make
104 # OR
105make CXX=clang++-3.5
106./stepX_YYY
107```
108
109
9b1563a3 110### C# ###
edc3b064
JM
111
112The C# implementation of mal has been tested on Linux using the Mono
113C# compiler (mcs) and the Mono runtime (version 2.10.8.1). Both are
114required to build and run the C# implementation.
115
116```
117cd cs
118make
ee7cd585 119mono ./stepX_YYY.exe
edc3b064
JM
120```
121
122
bcddc3e4 123### Clojure
60154d24
JM
124
125```
126cd clojure
127lein with-profile +stepX trampoline run
128```
129
891c3f3b
JM
130### CoffeeScript
131
132```
133sudo npm install -g coffee-script
134cd coffee
135coffee ./stepX_YYY
136```
137
96032890
C
138### Forth
139
a848d783
JM
140*The Forth implementation was created by [Chris Houser (chouser)](https://github.com/chouser)*
141
96032890
C
142```
143cd forth
144gforth stepX_YYY.fs
145```
146
1771ab50
JM
147### Go
148
fd888612
JM
149You Go implementation of mal requires that go is installed on on the
150path. The implementation has been tested with Go 1.3.1.
151
1771ab50
JM
152```
153cd go
154make
155./stepX_YYY
156```
157
158
b76aa73b
JM
159### Haskell
160
2988d38e 161Install the Haskell compiler (ghc/ghci), the Haskell platform and
5400d4bf
JM
162either the editline package (BSD) or the readline package (GPL). On
163Ubuntu these packages are: ghc, haskell-platform,
164libghc-readline-dev/libghc-editline-dev
b76aa73b
JM
165
166```
167cd haskell
168make
169./stepX_YYY
170```
171
172
bcddc3e4 173### Java 1.7
60154d24 174
01c97316
JM
175The Java implementation of mal requires maven2 to build.
176
60154d24
JM
177```
178cd java
179mvn compile
180mvn -quiet exec:java -Dexec.mainClass=mal.stepX_YYY
181 # OR
182mvn -quiet exec:java -Dexec.mainClass=mal.stepX_YYY -Dexec.args="CMDLINE_ARGS"
183```
184
39381792 185### JavaScript/Node
60154d24
JM
186
187```
188cd js
54c75382 189npm update
60154d24
JM
190node stepX_YYY.js
191```
192
39381792
JM
193### Julia
194
195The Julia implementation of mal has been tested with Julia 0.3.7.
196
197```
198cd julia
199julia stepX_YYY.jl
200```
201
9d42904e
JM
202### Lua
203
8a9d0a8a 204Running the Lua implementation of mal requires lua 5.1 or later,
9d42904e
JM
205luarocks and the lua-rex-pcre library installed.
206
207```
208cd lua
209make # to build and link linenoise.so
210./stepX_YYY.lua
211```
212
bcddc3e4 213### Mal
60154d24
JM
214
215Running the mal implementation of mal involves running stepA of one of
216the other implementations and passing the mal step to run as a command
5d446bd8 217line argument.
60154d24
JM
218
219```
220cd IMPL
221IMPL_STEPA_CMD ../mal/stepX_YYY.mal
222
223```
224
bcddc3e4 225### GNU Make 3.81
60154d24
JM
226
227```
228cd make
229make -f stepX_YYY.mk
230```
231
a2cd0a3a 232### Nim 0.10.3
233
a848d783
JM
234*The Nim implementation was created by [Dennis Felsing (def-)](https://github.com/def-)*
235
a2cd0a3a 236Running the Nim implementation of mal requires Nim's current devel branch
237(0.10.3) or later, and the nre library installed.
238
239```
240cd nim
241make
242 # OR
243nimble build
244./stepX_YYY
245```
246
bc6448bc
C
247### OCaml 4.01.0
248
a848d783
JM
249*The OCaml implementation was created by [Chris Houser (chouser)](https://github.com/chouser)*
250
bc6448bc
C
251```
252cd ocaml
253make
254./stepX_YYY
255```
256
8a9d0a8a
JM
257### MATLAB
258
259The MATLAB implementation of mal has been tested with MATLAB version
260R2014a on Linux. Note that MATLAB is a commercial product. It should
261be fairly simple to support GNU Octave once it support classdef object
262syntax.
263
264```
265cd matlab
266./stepX_YYY
267matlab -nodisplay -nosplash -nodesktop -nojvm -r "stepX_YYY();quit;"
268 # OR with command line arguments
269matlab -nodisplay -nosplash -nodesktop -nojvm -r "stepX_YYY('arg1','arg2');quit;"
270```
271
1218ce98
JM
272### miniMAL
273
274[miniMAL](https://github.com/kanaka/miniMAL) is small Lisp interpreter
275implemented in less than 1024 bytes of JavaScript. To run the miniMAL
276implementation of mal you need to download/install the miniMAL
277interpreter (which requires Node.js).
278```
1218ce98 279cd miniMAL
478fd9ce
JM
280# Download miniMAL and dependencies
281npm install
282export PATH=`pwd`/node_modules/minimal-lisp/:$PATH
283# Now run mal implementation in miniMAL
1218ce98
JM
284miniMAL ./stepX_YYY
285```
286
9b1563a3 287### Perl 5.8
9e5b2151
JM
288
289For readline line editing support, install Term::ReadLine::Perl or
290Term::ReadLine::Gnu from CPAN.
291
292```
293cd perl
294perl stepX_YYY.pl
295```
296
297
bcddc3e4 298### PHP 5.3
60154d24 299
01c97316
JM
300The PHP implementation of mal requires the php command line interface
301to run.
302
60154d24
JM
303```
304cd php
305php stepX_YYY.php
306```
307
bcddc3e4 308### Postscript Level 2/3
60154d24 309
01c97316
JM
310The Postscript implementation of mal requires ghostscript to run. It
311has been tested with ghostscript 9.10.
312
60154d24
JM
313```
314cd ps
fa64b741 315gs -q -dNODISPLAY -I./ stepX_YYY.ps
60154d24
JM
316```
317
a05f7822 318### Python (2 or 3)
60154d24
JM
319
320```
321cd python
322python stepX_YYY.py
323```
8adb0827 324
9b3362e8
JM
325### R
326
327The R implementation of mal requires R (r-base-core) to run.
328
329```
330cd r
9d42904e 331make libs # to download and build rdyncall
f5223195
JM
332Rscript stepX_YYY.r
333```
334
335### Racket (5.3)
336
337The Racket implementation of mal requires the Racket
338compiler/interpreter to run.
339
340```
341cd racket
3796240a 342./stepX_YYY.rkt
9b3362e8
JM
343```
344
107d9694 345### Ruby (1.9+)
8adb0827
JM
346
347```
348cd ruby
349ruby stepX_YYY.rb
350```
592eb5cf 351
9106a221 352### Rust (1.0.0 nightly)
abdd56eb
JM
353
354The rust implementation of mal requires the rust compiler and build
355tool (cargo) to build.
356
357```
358cd rust
bbeb1b87 359cargo run --release --bin stepX_YYY
abdd56eb
JM
360```
361
821930db
JM
362### Scala ###
363
364Install scala and sbt (http://www.scala-sbt.org/0.13/tutorial/Installing-sbt-on-Linux.html):
365
366```
367cd scala
368sbt 'run-main stepX_YYY'
369 # OR
370sbt compile
371scala -classpath target/scala*/classes stepX_YYY
372```
373
2539e6af
KR
374### Swift
375
a848d783
JM
376*The Swift implementation was created by [Keith Rollin](https://github.com/keith-rollin)*
377
8b142f08
JM
378The Swift implemenation of mal requires the Swift compiler (XCode) to
379build.
380
2539e6af
KR
381```
382cd swift
383make
384./stepX_YYY
385```
386
ee7cd585
JM
387### Visual Basic.NET ###
388
389The VB.NET implementation of mal has been tested on Linux using the Mono
390VB compiler (vbnc) and the Mono runtime (version 2.10.8.1). Both are
391required to build and run the VB.NET implementation.
392
393```
394cd vb
395make
396mono ./stepX_YYY.exe
397```
398
399
400
592eb5cf
JM
401## Running tests
402
294aba2c
JM
403### Functional tests
404
405The are nearly 500 generic functional tests (for all implementations)
406in the `tests/` directory. Each step has a corresponding test file
407containing tests specific to that step. The `runtest.py` test harness
bd62ff74
JM
408launches a Mal step implementation and then feeds the tests one at
409a time to the implementation and compares the output/return value to
410the expected output/return value.
592eb5cf
JM
411
412To simplify the process of running tests, a top level Makefile is
413provided with convenient test targets.
414
415* To run all the tests across all implementations (be prepared to wait):
416
417```
418make test
419```
420
421* To run all tests against a single implementation:
422
423```
424make test^IMPL
425
426# e.g.
427make test^clojure
428make test^js
429```
430
431* To run tests for a single step against all implementations:
432
433```
434make test^stepX
435
436# e.g.
437make test^step2
438make test^step7
439```
440
294aba2c 441* To run tests for a specifc step against a single implementation:
592eb5cf
JM
442
443```
444make test^IMPL^stepX
445
446# e.g
447make test^ruby^step3
448make test^ps^step4
449```
fd888612 450
294aba2c
JM
451### Self-hosted functional tests
452
453* To run the functional tests in self-hosted mode, you specify `mal`
454 as the test implementation and use the `MAL_IMPL` make variable
455 to change the underlying host language (default is JavaScript):
456```
457make MAL_IMPL=IMPL test^mal^step2
458
459# e.g.
460make test^mal^step2 # js is default
461make MAL_IMPL=ruby test^mal^step2
462make MAL_IMPL=python test^mal^step2
463```
464
465
466### Performance tests
467
8569b2af
JM
468Warning: These performance tests are neither statistically valid nor
469comprehensive; runtime performance is a not a primary goal of mal. If
470you draw any serious conclusions from these performance tests, then
471please contact me about some amazing oceanfront property in Kansas
472that I'm willing to sell you for cheap.
473
294aba2c
JM
474* To run performance tests against a single implementation:
475```
476make perf^IMPL
477
478# e.g.
479make perf^js
480```
481
482* To run performance tests against all implementations:
483```
484make perf
485```
486
487### Generating language statistics
488
489* To report line and byte stastics for a single implementation:
490```
491make stats^IMPL
492
493# e.g.
494make stats^js
495```
496
497* To report line and bytes stastics for general Lisp code (env, core
498 and stepA):
499```
500make stats-lisp^IMPL
501
502# e.g.
503make stats-lisp^js
504```
505
75363567
JM
506## Docker test environment
507
508There is a Dockerfile included in the `tests/docker` directory that
509builds a docker image based on Ubuntu Utopic that contains everything
510needed to run tests against all the implementations (except for MATLAB
511which is proprietary/licensed).
512
513Build the the docker image using a provided script. WARNING: this will
514likely take over an hour to build from scratch and use more 3 GB of disk:
515```bash
516./tests/docker-build.sh
517```
518
519Launch a docker container from that image built above. This will
520volume mount the mal directory to `/mal` and then give you a bash
521prompt in the container. You can then run individual mal
522implementations and tests:
523```bash
524./tests/docker-run.sh
525```
526
527You can also specify a command to run within the container. For
528example, to run step2 tests for every implementation (except MATLAB):
529```bash
530./tests/docker-run.sh make SKIP_IMPLS="matlab" test^step2
531```
532
533**Notes**:
534* JVM-based language implementations (Java, Clojure, Scala): you will
535 need to run these implementations once manually first before you can
536 run tests because runtime dependencies need to be downloaded to
537 avoid the tests timing out. These dependencies are download to
538 dot-files in the /mal directory so they will persist between runs.
bd62ff74 539* Compiled languages: if your host system is different enough from
75363567
JM
540 Ubuntu Utopic then you may need to re-compile your compiled
541 languages from within the container to avoid linker version
542 mismatches.
543
294aba2c 544
fd888612
JM
545## License
546
547Mal (make-a-lisp) is licensed under the MPL 2.0 (Mozilla Public
548License 2.0). See LICENSE.txt for more details.
549