1. Mal 是受 Clojure 启发的 Lisp 解释器
2.Mal是一个学习工具
mal 的每个实现都分为 11 个增量的、独立的(且可测试的)步骤,展示了 Lisp 的核心概念。最后一步是能够自托管(运行 mal 的 mal 实现)。请参阅 make-a-lisp 流程指南。
make-a-lisp的步骤是:
每个 make-a-lisp 步骤都有一个相关的架构图。该步骤中的新元素以红色突出显示。这是步骤 A 完成后的最终架构:
如果您有兴趣创建 mal 实现(或者只是对使用 mal 进行某些操作感兴趣),欢迎加入我们的 Discord。除了 make-a-lisp 流程指南之外,还有 mal/make-a-lisp 常见问题解答,我尝试在其中回答一些常见问题。
3. Mal以88种语言实现(94种不同的实现和117种运行时模式)
语言 | 创作者 |
---|---|
艾达 | 克里斯·摩尔 |
艾达#2 | 尼古拉斯·布伦格斯 |
GNU awk | 刈谷满 |
重击4 | 乔尔·马丁 |
BASIC(C64 和 QBasic) | 乔尔·马丁 |
英国广播公司基本五 | 本·哈里斯 |
C | 乔尔·马丁 |
C#2 | 邓肯·瓦茨 |
C++ | 史蒂芬·瑟尔沃尔 |
C# | 乔尔·马丁 |
查克 | 瓦西里·施奈德曼 |
Clojure(Clojure 和 ClojureScript) | 乔尔·马丁 |
咖啡脚本 | 乔尔·马丁 |
通用语言 | 伊克巴尔·安萨里 |
水晶 | 琳达_pp |
D | 多夫·穆里克 |
镖 | 哈里·特克尔森 |
灵丹妙药 | 马丁·埃克 |
榆树 | 乔斯·范·巴克尔 |
Emacs Lisp | 瓦西里·施奈德曼 |
埃尔兰 | 内森·费德勒 |
ES6(ECMAScript 2015) | 乔尔·马丁 |
F# | 彼得·斯蒂芬斯 |
因素 | 乔丹·刘易斯 |
幻影 | 多夫·穆里克 |
茴香 | 索盖尤 |
福斯 | 克里斯·豪瑟 |
GNU 诡计 | 穆蕾 |
GNU Smalltalk | 瓦西里·施奈德曼 |
去 | 乔尔·马丁 |
格罗维 | 乔尔·马丁 |
哈斯克尔 | 乔尔·马丁 |
Haxe(Neko、Python、C++ 和 JS) | 乔尔·马丁 |
海伊 | 乔尔·马丁 |
木卫一 | 多夫·穆里克 |
珍妮特 | 索盖尤 |
爪哇 | 乔尔·马丁 |
Java Truffle (Truffle/GraalVM) | 马特·麦吉尔 |
JavaScript(演示) | 乔尔·马丁 |
杰克 | 阿里·穆罕默德·普尔 |
朱莉娅 | 乔尔·马丁 |
科特林 | 哈维尔·费尔南德斯-伊文 |
乳胶3 | 尼古拉斯·布伦格斯 |
实时脚本 | 乔斯·范·巴克尔 |
标识 | 多夫·穆里克 |
卢阿 | 乔尔·马丁 |
GNU 使 | 乔尔·马丁 |
马尔本身 | 乔尔·马丁 |
MATLAB(GNU Octave 和 MATLAB) | 乔尔·马丁 |
miniMAL(存储库、演示) | 乔尔·马丁 |
NASM | 本·达德森 |
尼姆 | 丹尼斯·费尔辛 |
对象帕斯卡 | 乔尔·马丁 |
目标C | 乔尔·马丁 |
奥卡米尔 | 克里斯·豪瑟 |
珀尔 | 乔尔·马丁 |
珀尔6 | 欣里克·奥恩·西于尔松 |
PHP | 乔尔·马丁 |
皮科利斯普 | 瓦西里·施奈德曼 |
派克 | 多夫·穆里克 |
PL/pgSQL (PostgreSQL) | 乔尔·马丁 |
PL/SQL(Oracle) | 乔尔·马丁 |
后记 | 乔尔·马丁 |
电源外壳 | 乔尔·马丁 |
序言 | 尼古拉斯·布伦格斯 |
纯脚本 | 姆塞库特 |
Python2 | 乔尔·马丁 |
Python3 | 加文·刘易斯 |
RPython | 乔尔·马丁 |
右 | 乔尔·马丁 |
球拍 | 乔尔·马丁 |
雷克斯 | 多夫·穆里克 |
红宝石 | 乔尔·马丁 |
红宝石 #2 | 瑞安·库克 |
锈 | 乔尔·马丁 |
斯卡拉 | 乔尔·马丁 |
方案(R7RS) | 瓦西里·施奈德曼 |
倾斜 | 多夫·穆里克 |
标准机器学习 | 法比安·伯格斯特罗姆 |
雨燕3 | 乔尔·马丁 |
雨燕4 | 陆遥 |
雨燕6 | 奥列格·蒙塔克 |
铊 | 多夫·穆里克 |
打字稿 | 裙带菜正宏 |
瓦拉 | 西蒙·泰瑟姆 |
超高清描述语言 | 多夫·穆里克 |
Vim脚本 | 多夫·穆里克 |
Visual Basic.NET | 乔尔·马丁 |
视觉基本脚本 | 刘百超 |
WebAssembly(wasm) | 乔尔·马丁 |
鹪 | 多夫·穆里克 |
XSLT | 阿里·穆罕默德·普尔 |
约里克 | 多夫·穆里克 |
之字形 | 乔什·托宾 |
Mal 在 2014 年 Clojure West 的闪电演讲中首次公开亮相(遗憾的是没有视频)。请参阅示例/clojurewest2014.mal,了解会议上的演示文稿(是的,该演示文稿是一个 mal 程序)。
在 Midwest.io 2015 上,Joel Martin 就 Mal 做了题为“解锁成就:更好的语言学习之路”的演讲。视频、幻灯片。
最近,Joel 在 LambdaConf 2016 上发表了题为“用 10 个增量步骤创建自己的 Lisp 解释器”的演讲:第 1 部分、第 2 部分、第 3 部分、第 4 部分,幻灯片。
运行任何给定实现的最简单方法是使用 docker。每个实现都有一个预先构建的 docker 镜像,并安装了语言依赖项。您可以使用顶层 Makefile 中的方便目标来启动 REPL(其中 IMPL 是实现目录名称,stepX 是要运行的步骤):
make DOCKERIZE=1 "repl^IMPL^stepX"
# OR stepA is the default step:
make DOCKERIZE=1 "repl^IMPL"
以下实现作为单独的项目进行维护:
Ada 实现是在 debian 上使用 GNAT 4.9 开发的。如果您有 Windows 版本的 git、GNAT 和(可选)make,它也可以在 Windows 上编译,无需更改。没有外部依赖项(readline 未实现)。
cd impls/ada
make
./stepX_YYY
第二个 Ada 实现是使用 GNAT 8 开发的,并与 GNU readline 库链接。
cd impls/ada
make
./stepX_YYY
mal 的 GNU awk 实现已使用 GNU awk 4.1.1 进行了测试。
cd impls/gawk
gawk -O -f stepX_YYY.awk
cd impls/bash
bash stepX_YYY.sh
BASIC 实现使用可以生成与 C64 BASIC (CBM v2) 或 QBasic 兼容的 BASIC 代码的预处理器。 C64 模式已使用 cbmbasic 进行了测试(当前需要修补版本来修复线路输入问题),而 QBasic 模式已使用 FreeBASIC 进行了测试。
生成 C64 代码并使用 cbmbasic 运行它:
cd impls/basic
make MODE=cbm stepX_YYY.bas
STEP=stepX_YYY basic_MODE=cbm ./run
生成QBasic代码,使用FreeBASIC编译并执行:
cd impls/basic
make MODE=qbasic stepX_YYY.bas
make MODE=qbasic stepX_YYY
./stepX_YYY
感谢 Steven Syrek 为本实施提供的最初灵感。
BBC BASIC V 实现可以在 Brandy 解释器中运行:
cd impls/bbc-basic
brandy -quit stepX_YYY.bbc
或者在 RISC OS 3 或更高版本下的 ARM BBC BASIC V 中:
*Dir bbc-basic.riscos
*Run setup
*Run stepX_YYY
mal 的 C 实现需要以下库(lib 和头包):glib、libffi6、libgc 以及 libedit 或 GNU readline 库。
cd impls/c
make
./stepX_YYY
mal 的第二个 C 实现需要以下库(lib 和头包):libedit、libgc、libdl 和 libffi。
cd impls/c.2
make
./stepX_YYY
mal 的 C++ 实现需要 g++-4.9 或 clang++-3.5 以及 readline 兼容库来构建。有关更多详细信息,请参阅cpp/README.md
:
cd impls/cpp
make
# OR
make CXX=clang++-3.5
./stepX_YYY
mal 的 C# 实现已在 Linux 上使用 Mono C# 编译器 (mcs) 和 Mono 运行时(版本 2.10.8.1)进行了测试。构建和运行 C# 实现都需要两者。
cd impls/cs
make
mono ./stepX_YYY.exe
ChucK 实现已使用 ChucK 1.3.5.2 进行了测试。
cd impls/chuck
./run
大多数情况下,Clojure 实现需要 Clojure 1.5,但是,为了通过所有测试,需要 Clojure 1.8.0-RC4。
cd impls/clojure
lein with-profile +stepX trampoline run
sudo npm install -g coffee-script
cd impls/coffee
coffee ./stepX_YYY
该实现已在 Ubuntu 16.04 和 Ubuntu 12.04 上使用 SBCL、CCL、CMUCL、GNU CLISP、ECL 和 Allegro CL 进行了测试,请参阅 README 了解更多详细信息。如果您安装了提到的依赖项,请执行以下操作来运行实施
cd impls/common-lisp
make
./run
mal 的 Crystal 实现已使用 Crystal 0.26.1 进行了测试。
cd impls/crystal
crystal run ./stepX_YYY.cr
# OR
make # needed to run tests
./stepX_YYY
mal 的 D 实现已使用 GDC 4.8 进行了测试。它需要 GNU readline 库。
cd impls/d
make
./stepX_YYY
Dart 实现已使用 Dart 1.20 进行了测试。
cd impls/dart
dart ./stepX_YYY
mal 的 Emacs Lisp 实现已在 Emacs 24.3 和 24.5 上进行了测试。虽然有非常基本的读行编辑( <backspace>
和Cd
工作, Cc
取消该过程),但建议使用rlwrap
。
cd impls/elisp
emacs -Q --batch --load stepX_YYY.el
# with full readline support
rlwrap emacs -Q --batch --load stepX_YYY.el
Mal 的 Elixir 实现已使用 Elixir 1.0.5 进行了测试。
cd impls/elixir
mix stepX_YYY
# Or with readline/line editing functionality:
iex -S mix stepX_YYY
mal 的 Elm 实现已使用 Elm 0.18.0 进行了测试
cd impls/elm
make stepX_YYY.js
STEP=stepX_YYY ./run
mal 的 Erlang 实现需要 Erlang/OTP R17 和 rebar 来构建。
cd impls/erlang
make
# OR
MAL_STEP=stepX_YYY rebar compile escriptize # build individual step
./stepX_YYY
ES6 / ECMAScript 2015 实现使用 babel 编译器生成 ES5 兼容的 JavaScript。生成的代码已使用 Node 0.12.4 进行了测试。
cd impls/es6
make
node build/stepX_YYY.js
mal 的 F# 实现已在 Linux 上使用 Mono F# 编译器 (fsharpc) 和 Mono 运行时(版本 3.12.1)进行了测试。 Mono C# 编译器 (mcs) 也是编译 readline 依赖项所必需的。构建和运行 F# 实现需要所有这些。
cd impls/fsharp
make
mono ./stepX_YYY.exe
mal 的 Factor 实现已使用 Factor 0.97 (factorcode.org) 进行了测试。
cd impls/factor
FACTOR_ROOTS=. factor -run=stepX_YYY
mal 的 Fantom 实现已使用 Fantom 1.0.70 进行了测试。
cd impls/fantom
make lib/fan/stepX_YYY.pod
STEP=stepX_YYY ./run
mal 的 Fennel 实现已在 Lua 5.4 上使用 Fennel 版本 0.9.1 进行了测试。
cd impls/fennel
fennel ./stepX_YYY.fnl
cd impls/forth
gforth stepX_YYY.fs
cd impls/guile
guile -L ./ stepX_YYY.scm
mal 的 Smalltalk 实现已使用 GNU Smalltalk 3.2.91 进行了测试。
cd impls/gnu-smalltalk
./run
mal 的 Go 实现需要在路径上安装 go。该实现已使用 Go 1.3.1 进行了测试。
cd impls/go
make
./stepX_YYY
mal 的 Groovy 实现需要 Groovy 才能运行,并已使用 Groovy 1.8.6 进行了测试。
cd impls/groovy
make
groovy ./stepX_YYY.groovy
Haskell 实现需要 ghc 编译器版本 7.10.1 或更高版本,以及 Haskell parsec 和 readline(或 editline)包。
cd impls/haskell
make
./stepX_YYY
mal 的 Haxe 实现需要 Haxe 3.2 版本才能编译。支持四种不同的 Haxe 目标:Neko、Python、C++ 和 JavaScript。
cd impls/haxe
# Neko
make all-neko
neko ./stepX_YYY.n
# Python
make all-python
python3 ./stepX_YYY.py
# C++
make all-cpp
./cpp/stepX_YYY
# JavaScript
make all-js
node ./stepX_YYY.js
mal 的 Hy 实现已使用 Hy 0.13.0 进行了测试。
cd impls/hy
./stepX_YYY.hy
mal 的 Io 实现已使用 Io 版本 20110905 进行了测试。
cd impls/io
io ./stepX_YYY.io
mal 的 Janet 实现已使用 Janet 版本 1.12.2 进行了测试。
cd impls/janet
janet ./stepX_YYY.janet
mal的Java实现需要maven2来构建。
cd impls/java
mvn compile
mvn -quiet exec:java -Dexec.mainClass=mal.stepX_YYY
# OR
mvn -quiet exec:java -Dexec.mainClass=mal.stepX_YYY -Dexec.args="CMDLINE_ARGS"
该 Java 实现将在 OpenJDK 上运行,但由于 Truffle 框架,在 GraalVM 上的运行速度可以提高 30 倍。它已使用 OpenJDK 11、GraalVM CE 20.1.0 和 GraalVM CE 21.1.0 进行了测试。
cd impls/java-truffle
./gradlew build
STEP=stepX_YYY ./run
cd impls/js
npm install
node stepX_YYY.js
mal 的 Julia 实现需要 Julia 0.4。
cd impls/julia
julia stepX_YYY.jl
针对1.6版本进行测试,IO部门有很多作弊行为
cd impls/jq
STEP=stepA_YYY ./run
# with Debug
DEBUG=true STEP=stepA_YYY ./run
mal 的 Kotlin 实现已使用 Kotlin 1.0 进行了测试。
cd impls/kotlin
make
java -jar stepX_YYY.jar
mal 的 LaTeX3 实现已使用 pdfTeX 3.141592653-2.6-1.40.24 进行了测试。
自托管对于任何合理的超时来说都太慢,并且在第 4 步中崩溃,显然是由于硬编码的限制。
任何从事此工作的人都应该取消注释步骤文件中的两行(慢速)调试选项,并导出 DEBUG=1 (以获得比测试接受的更多输出)。
mal 的 LiveScript 实现已使用 LiveScript 1.5 进行了测试。
cd impls/livescript
make
node_modules/.bin/lsc stepX_YYY.ls
mal 的 Logo 实现已使用 UCBLogo 6.0 进行了测试。
cd impls/logo
logo stepX_YYY.lg
mal 的 Lua 实现已经在 Lua 5.3.5 上进行了测试,该实现需要安装 luarocks。
cd impls/lua
make # to build and link linenoise.so and rex_pcre.so
./stepX_YYY.lua
运行 mal 的 mal 实现涉及运行其他实现之一的 stepA 并将 mal 步骤作为命令行参数传递给运行。
cd impls/IMPL
IMPL_STEPA_CMD ../mal/stepX_YYY.mal
cd impls/make
make -f stepX_YYY.mk
mal 的 NASM 实现是为 x86-64 Linux 编写的,并已在 Linux 3.16.0-4-amd64 和 NASM 版本 2.11.05 上进行了测试。
cd impls/nasm
make
./stepX_YYY
mal 的 Nim 实现已使用 Nim 1.0.4 进行了测试。
cd impls/nim
make
# OR
nimble build
./stepX_YYY
mal 的 Object Pascal 实现已在 Linux 上使用 Free Pascal 编译器版本 2.6.2 和 2.6.4 进行了构建和测试。
cd impls/objpascal
make
./stepX_YYY
mal 的 Objective C 实现已使用 clang/LLVM 3.6 在 Linux 上构建和测试。它还使用 Xcode 7 在 OS X 上构建和测试。
cd impls/objc
make
./stepX_YYY
cd impls/ocaml
make
./stepX_YYY
MatLab 实现已使用 GNU Octave 4.2.1 进行了测试。它还在 Linux 上使用 MATLAB R2014a 版本进行了测试。请注意,MATLAB 是商业产品。
cd impls/matlab
./stepX_YYY
octave -q --no-gui --no-history --eval "stepX_YYY();quit;"
matlab -nodisplay -nosplash -nodesktop -nojvm -r "stepX_YYY();quit;"
# OR with command line arguments
octave -q --no-gui --no-history --eval "stepX_YYY('arg1','arg2');quit;"
matlab -nodisplay -nosplash -nodesktop -nojvm -r "stepX_YYY('arg1','arg2');quit;"
miniMAL 是用不到 1024 字节的 JavaScript 实现的小型 Lisp 解释器。要运行 mal 的 miniMAL 实现,您需要下载/安装 miniMAL 解释器(需要 Node.js)。
cd impls/miniMAL
# Download miniMAL and dependencies
npm install
export PATH=`pwd`/node_modules/minimal-lisp/:$PATH
# Now run mal implementation in miniMAL
miniMAL ./stepX_YYY
Perl 5 实现应该与 perl 5.19.3 及更高版本一起使用。
要获得 readline 行编辑支持,请从 CPAN 安装 Term::ReadLine::Perl 或 Term::ReadLine::Gnu。
cd impls/perl
perl stepX_YYY.pl
Perl 6 实现在 Rakudo Perl 6 2016.04 上进行了测试。
cd impls/perl6
perl6 stepX_YYY.pl
mal 的 PHP 实现需要 php 命令行界面才能运行。
cd impls/php
php stepX_YYY.php
Picolisp 实现需要 libreadline 和 Picolisp 3.1.11 或更高版本。
cd impls/picolisp
./run
Pike 实现在 Pike 8.0 上进行了测试。
cd impls/pike
pike stepX_YYY.pike
mal 的 PL/pgSQL 实现需要一个正在运行的 PostgreSQL 服务器(“kanaka/mal-test-plpgsql”docker 镜像会自动启动 PostgreSQL 服务器)。该实现连接到 PostgreSQL 服务器并创建一个名为“mal”的数据库来存储表和存储过程。包装器脚本使用 psql 命令连接到服务器,并默认为用户“postgres”,但这可以使用 PSQL_USER 环境变量覆盖。可以使用 PGPASSWORD 环境变量指定密码。该实现已使用 PostgreSQL 9.4 进行了测试。
cd impls/plpgsql
./wrap.sh stepX_YYY.sql
# OR
PSQL_USER=myuser PGPASSWORD=mypass ./wrap.sh stepX_YYY.sql
mal 的 PL/SQL 实现需要一个正在运行的 Oracle DB 服务器(“kanaka/mal-test-plsql”docker 映像会自动启动 Oracle Express 服务器)。该实现连接到 Oracle 服务器以创建类型、表和存储过程。默认的 SQL*Plus 登录值(用户名/密码@connect_identifier)是“system/oracle”,但这可以使用 ORACLE_LOGON 环境变量覆盖。该实现已使用 Oracle Express Edition 11g 第 2 版进行了测试。请注意,任何 SQL*Plus 连接警告(用户密码过期等)都会干扰包装器脚本与数据库通信的能力。
cd impls/plsql
./wrap.sh stepX_YYY.sql
# OR
ORACLE_LOGON=myuser/mypass@ORCL ./wrap.sh stepX_YYY.sql
mal 的 PostScript 实现需要 Ghostscript 才能运行。它已经使用 Ghostscript 9.10 进行了测试。
cd impls/ps
gs -q -dNODISPLAY -I./ stepX_YYY.ps
mal 的 PowerShell 实现需要 PowerShell 脚本语言。它已在 Linux 上使用 PowerShell 6.0.0 Alpha 9 进行了测试。
cd impls/powershell
powershell ./stepX_YYY.ps1
Prolog 实现使用一些特定于 SWI-Prolog 的结构,包括 readline 支持,并已在 Debian GNU/Linux 版本 8.2.1 上进行了测试。
cd impls/prolog
swipl stepX_YYY
PureScript 实现需要 spago 编译器版本 0.20.2。
cd impls/purs
make
node ./stepX_YYY.js
该实现仅使用了python2的特性,但避免了与python3的不兼容。
此实现会检查样式和类型(flake8、pylint、mypy)。它报告所有错误并附有详细信息。它演示了迭代器、装饰器、功能工具、链映射、数据类、内省、匹配语句、赋值表达式。
您的路径上必须有 rpython(包含在 pypy 中)。
cd impls/rpython
make # this takes a very long time
./stepX_YYY
mal 的 R 实现需要 R (r-base-core) 才能运行。
cd impls/r
make libs # to download and build rdyncall
Rscript stepX_YYY.r
mal 的 Racket 实现需要 Racket 编译器/解释器才能运行。
cd impls/racket
./stepX_YYY.rkt
mal 的 Rexx 实现已使用 Regina Rexx 3.6 进行了测试。
cd impls/rexx
make
rexx -a ./stepX_YYY.rexxpp
cd impls/ruby
ruby stepX_YYY.rb
第二个 Ruby 实现具有以下目标:
Mal
模块命名空间中 cd impls/ruby.2
ruby stepX_YYY.rb
mal 的 Rust 实现需要 rust 编译器和构建工具(cargo)来构建。
cd impls/rust
cargo run --release --bin stepX_YYY
安装 scala 和 sbt (http://www.scala-sbt.org/0.13/tutorial/Installing-sbt-on-Linux.html):
cd impls/scala
sbt 'run-main stepX_YYY'
# OR
sbt compile
scala -classpath target/scala*/classes stepX_YYY
MAL 的方案实施已使用 Chibi-Scheme 0.10、Kawa 3.1.1、Gauche 0.9.6、CHICKEN 5.1.0、Sagittarius 0.9.7、Cyclone 0.32.0(Git 版本)和 Foment 0.4(Git 版本)进行了测试。在弄清楚如何加载库并相应地调整Makefile
和run
脚本后,您应该能够在其他符合 R7RS 的实现上运行它。
cd impls/scheme
# chibi
scheme_MODE=chibi ./run
# kawa
make kawa
scheme_MODE=kawa ./run
# gauche
scheme_MODE=gauche ./run
# chicken
make chicken
scheme_MODE=chicken ./run
# sagittarius
scheme_MODE=sagittarius ./run
# cyclone
make cyclone
scheme_MODE=cyclone ./run
# foment
scheme_MODE=foment ./run
mal 的 Skew 实现已使用 Skew 0.7.42 进行了测试。
cd impls/skew
make
node stepX_YYY.js
mal 的标准 ML 实现需要 SML97 实现。 Makefile 支持 Poly/ML、MLton、Moscow ML,并已通过 Poly/ML 5.8.1、MLton 20210117 和Moscow ML 版本 2.10 进行测试。
cd impls/sml
# Poly/ML
make sml_MODE=polyml
./stepX_YYY
# MLton
make sml_MODE=mlton
./stepX_YYY
# Moscow ML
make sml_MODE=mosml
./stepX_YYY
mal 的 Swift 3 实现需要 Swift 3.0 编译器。它已经使用 Swift 3 Preview 3 进行了测试。
cd impls/swift3
make
./stepX_YYY
mal 的 Swift 4 实现需要 Swift 4.0 编译器。它已经使用 Swift 4.2.3 版本进行了测试。
cd impls/swift4
make
./stepX_YYY
mal 的 Swift 5 实现需要 Swift 5.0 编译器。它已经通过 Swift 5.1.1 版本进行了测试。
cd impls/swift6
swift run stepX_YYY
mal 的 Tcl 实现需要 Tcl 8.6 才能运行。要获得 readline 行编辑支持,请安装 tclreadline。
cd impls/tcl
tclsh ./stepX_YYY.tcl
mal 的 TypeScript 实现需要 TypeScript 2.2 编译器。它已经使用 Node.js v6 进行了测试。
cd impls/ts
make
node ./stepX_YYY.js
mal 的 Vala 实现已经使用 Vala 0.40.8 编译器进行了测试。您将需要安装valac
和libreadline-dev
或同等软件。
cd impls/vala
make
./stepX_YYY
mal 的 VHDL 实现已使用 GHDL 0.29 进行了测试。
cd impls/vhdl
make
./run_vhdl.sh ./stepX_YYY
mal 的 Vimscript 实现需要 Vim 8.0 才能运行。
cd impls/vimscript
./run_vimscript.sh ./stepX_YYY.vim
mal 的 VB.NET 实现已在 Linux 上使用 Mono VB 编译器 (vbnc) 和 Mono 运行时(版本 2.10.8.1)进行了测试。构建和运行 VB.NET 实现都需要两者。
cd impls/vb
make
mono ./stepX_YYY.exe
mal 的 VBScript 实现已在 Windows 10 1909 上进行了测试install.vbs
可以帮助您安装要求(.NET 2.0 3.0 3.5)。如果您尚未安装.NET 2.0 3.0 3.5
,则会弹出安装窗口。如果您已经安装了它,它将不会执行任何操作。
cd implsvbs
install.vbs
cscript -nologo stepX_YYY.vbs
WebAssembly 实现是用 Wam(WebAssembly 宏语言)编写的,并在几种不同的非 Web 嵌入(运行时)下运行:node、wasmtime、wasmer、wax、wace、warpy。
cd impls/wasm
# node
make wasm_MODE=node
./run.js ./stepX_YYY.wasm
# wasmtime
make wasm_MODE=wasmtime
wasmtime --dir=./ --dir=../ --dir=/ ./stepX_YYY.wasm
# wasmer
make wasm_MODE=wasmer
wasmer run --dir=./ --dir=../ --dir=/ ./stepX_YYY.wasm
# wax
make wasm_MODE=wax
wax ./stepX_YYY.wasm
# wace
make wasm_MODE=wace_libc
wace ./stepX_YYY.wasm
# warpy
make wasm_MODE=warpy
warpy --argv --memory-pages 256 ./stepX_YYY.wasm
mal 的 XSLT 实现是用 XSLT 3 编写的,并在 Saxon 9.9.1.6 Home Edition 上进行了测试。
cd impls/xslt
STEP=stepX_YY ./run
mal 的 Wren 实现在 Wren 0.2.0 上进行了测试。
cd impls/wren
wren ./stepX_YYY.wren
Mal 的 Yorick 实现在 Yorick 2.2.04 上进行了测试。
cd impls/yorick
yorick -batch ./stepX_YYY.i
mal 的 Zig 实现在 Zig 0.5 上进行了测试。
cd impls/zig
zig build stepX_YYY
顶层 Makefile 有许多有用的目标来协助实现开发和测试。 help
目标提供了目标和选项的列表:
make help
tests/
目录中有近 800 个通用功能测试(针对所有实现)。每个步骤都有一个相应的测试文件,其中包含特定于该步骤的测试。 runtest.py
测试工具启动 Mal 步骤实现,然后一次将一个测试提供给实现,并将输出/返回值与预期输出/返回值进行比较。
make test
make "test^IMPL"
# e.g.
make "test^clojure"
make "test^js"
make "test^stepX"
# e.g.
make "test^step2"
make "test^step7"
make "test^IMPL^stepX"
# e.g
make "test^ruby^step3"
make "test^ps^step4"
mal
作为测试实现,并使用MAL_IMPL
make 变量来更改底层主机语言(默认为 JavaScript): make MAL_IMPL=IMPL "test^mal^step2"
# e.g.
make "test^mal^step2" # js is default
make MAL_IMPL=ruby "test^mal^step2"
make MAL_IMPL=python3 "test^mal^step2"
make "repl^IMPL^stepX"
# e.g
make "repl^ruby^step3"
make "repl^ps^step4"
stepA
: make "repl^IMPL"
# e.g
make "repl^ruby"
make "repl^ps"
mal
作为 REPL 实现,并使用MAL_IMPL
make 变量来更改底层主机语言(默认为 JavaScript): make MAL_IMPL=IMPL "repl^mal^stepX"
# e.g.
make "repl^mal^step2" # js is default
make MAL_IMPL=ruby "repl^mal^step2"
make MAL_IMPL=python3 "repl^mal"
警告:这些性能测试在统计上既不有效也不全面;运行时性能并不是 mal 的主要目标。如果您从这些性能测试中得出任何严肃的结论,那么请与我联系,了解堪萨斯州一些令人惊叹的海滨房产,我愿意以便宜的价格卖给您。
make "perf^IMPL"
# e.g.
make "perf^js"
make "perf"
make "stats^IMPL"
# e.g.
make "stats^js"
每个实现目录都包含一个 Dockerfile,用于创建包含该实现的所有依赖项的 docker 映像。此外,顶级 Makefile 还支持通过在 make 命令行上传递“DOCKERIZE=1”来在 docker 容器内运行测试目标(以及 perf、stats、repl 等)以实现该实现。例如:
make DOCKERIZE=1 "test^js^step3"
现有的实现已经构建了 docker 镜像并将其推送到 docker 注册表。但是,如果您希望在本地构建或重建 docker 镜像,顶层 Makefile 提供了构建 docker 镜像的规则:
make "docker-build^IMPL"
注意事项:
make DOCKERIZE=1 "repl^IMPL"
才能运行测试,因为需要下载运行时依赖项以避免测试超时。这些依赖项被下载到 /mal 目录中的点文件中,因此它们将在运行之间持续存在。 Mal (make-a-lisp) 根据 MPL 2.0(Mozilla 公共许可证 2.0)获得许可。有关详细信息,请参阅 LICENSE.txt。