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