2 # Command line settings
9 # Extra options to pass to runtest.py
12 # Extra implementation specific options to pass to runtest.py
13 mal_TEST_OPTS
= --start-timeout
60 --test-timeout
120
19 IMPLS
= awk bash c clojure coffee
cpp crystal cs erlang elixir es6 factor forth fsharp go groovy \
20 guile haskell java julia js kotlin lua make mal ocaml matlab miniMAL nim \
21 perl php ps python r racket rpython ruby rust scala swift tcl vb vimscript
24 step1
= step1_read_print
27 step4
= step4_if_fn_do
35 EXCLUDE_TESTS
+= test^awk^step5
# completes at 10,000
36 EXCLUDE_TESTS
+= test^bash^step5
# no stack exhaustion or completion
37 EXCLUDE_TESTS
+= test^c^step5
# segfault
38 EXCLUDE_TESTS
+= test^
cpp^step5
# completes at 10,000
39 EXCLUDE_TESTS
+= test^cs^step5
# fatal stack overflow fault
40 EXCLUDE_TESTS
+= test^erlang^step5
# erlang is TCO, test passes
41 EXCLUDE_TESTS
+= test^elixir^step5
# elixir is TCO, test passes
42 EXCLUDE_TESTS
+= test^fsharp^step5
# completes at 10,000, fatal stack overflow at 100,000
43 EXCLUDE_TESTS
+= test^haskell^step5
# test completes
44 EXCLUDE_TESTS
+= test^make^step5
# no TCO capability/step
45 EXCLUDE_TESTS
+= test^mal^step5
# no TCO capability/step
46 EXCLUDE_TESTS
+= test^miniMAL^step5
# strange error with runtest.py
47 EXCLUDE_TESTS
+= test^nim^step5
# test completes, even at 100,000
48 EXCLUDE_TESTS
+= test^go^step5
# test completes, even at 100,000
49 EXCLUDE_TESTS
+= test^php^step5
# test completes, even at 100,000
50 EXCLUDE_TESTS
+= test^racket^step5
# test completes
51 EXCLUDE_TESTS
+= test^ruby^step5
# test completes, even at 100,000
52 EXCLUDE_TESTS
+= test^rust^step5
# no catching stack overflows
53 EXCLUDE_TESTS
+= test^ocaml^step5
# test completes, even at 1,000,000
54 EXCLUDE_TESTS
+= test^vb^step5
# completes at 10,000
55 EXCLUDE_TESTS
+= test^crystal^step5
# test completes, even at 1,000,000
57 EXCLUDE_PERFS
= perf^mal
# TODO: fix this
63 STEP_TEST_FILES
= $(strip $(wildcard $(1)/tests
/$($(2)).mal
) $(wildcard tests
/$($(2)).mal
))
65 awk_STEP_TO_PROG
= awk
/$($(1)).awk
66 bash_STEP_TO_PROG
= bash
/$($(1)).sh
67 c_STEP_TO_PROG
= c
/$($(1))
68 clojure_STEP_TO_PROG
= clojure
/src
/$($(1)).clj
69 coffee_STEP_TO_PROG
= coffee
/$($(1)).coffee
70 cpp_STEP_TO_PROG
= cpp/$($(1))
71 crystal_STEP_TO_PROG
= crystal
/$($(1))
72 cs_STEP_TO_PROG
= cs
/$($(1)).exe
73 elixir_STEP_TO_PROG
= elixir
/lib
/mix
/tasks
/$($(1)).ex
74 erlang_STEP_TO_PROG
= erlang
/$($(1))
75 es6_STEP_TO_PROG
= es6
/build
/$($(1)).js
76 factor_STEP_TO_PROG
= factor
/$($(1))/$($(1)).factor
77 forth_STEP_TO_PROG
= forth
/$($(1)).fs
78 fsharp_STEP_TO_PROG
= fsharp
/$($(1)).exe
79 go_STEP_TO_PROG
= go
/$($(1))
80 groovy_STEP_TO_PROG
= groovy
/$($(1)).groovy
81 java_STEP_TO_PROG
= java
/src
/main
/java
/mal
/$($(1)).java
82 haskell_STEP_TO_PROG
= haskell
/$($(1))
83 julia_STEP_TO_PROG
= julia
/$($(1)).jl
84 js_STEP_TO_PROG
= js
/$($(1)).js
85 kotlin_STEP_TO_PROG
= kotlin
/$($(1)).jar
86 lua_STEP_TO_PROG
= lua
/$($(1)).lua
87 make_STEP_TO_PROG
= make
/$($(1)).mk
88 mal_STEP_TO_PROG
= mal
/$($(1)).mal
89 ocaml_STEP_TO_PROG
= ocaml
/$($(1))
90 matlab_STEP_TO_PROG
= matlab
/$($(1)).m
91 miniMAL_STEP_TO_PROG
= miniMAL
/$($(1)).json
92 nim_STEP_TO_PROG
= nim
/$($(1))
93 perl_STEP_TO_PROG
= perl
/$($(1)).pl
94 php_STEP_TO_PROG
= php
/$($(1)).php
95 ps_STEP_TO_PROG
= ps
/$($(1)).ps
96 python_STEP_TO_PROG
= python
/$($(1)).py
97 r_STEP_TO_PROG
= r
/$($(1)).r
98 racket_STEP_TO_PROG
= racket
/$($(1)).rkt
99 rpython_STEP_TO_PROG
= rpython
/$($(1))
100 ruby_STEP_TO_PROG
= ruby
/$($(1)).rb
101 rust_STEP_TO_PROG
= rust
/target
/release
/$($(1))
102 scala_STEP_TO_PROG
= scala
/$($(1)).scala
103 swift_STEP_TO_PROG
= swift
/$($(1))
104 tcl_STEP_TO_PROG
= tcl
/$($(1)).tcl
105 vb_STEP_TO_PROG
= vb
/$($(1)).exe
106 vimscript_STEP_TO_PROG
= vimscript
/$($(1)).vim
107 guile_STEP_TO_PROG
= guile
/$($(1)).scm
109 # Needed some argument munging
112 SPACE
= $(noop
) $(noop
)
113 export FACTOR_ROOTS
:= .
115 awk_RUNSTEP
= awk
-O
-f ..
/$(2) $(3)
116 bash_RUNSTEP
= bash ..
/$(2) $(3)
117 c_RUNSTEP
= ..
/$(2) $(3)
118 clojure_RUNSTEP
= lein with-profile
+$(1) trampoline run
$(3)
119 coffee_RUNSTEP
= coffee ..
/$(2) $(3)
120 cpp_RUNSTEP
= ..
/$(2) $(3)
121 crystal_RUNSTEP
= ..
/$(2) $(3)
122 cs_RUNSTEP
= mono ..
/$(2) --raw
$(3)
123 elixir_RUNSTEP
= mix
$(notdir $(basename $(2))) $(3)
124 erlang_RUNSTEP
= ..
/$(2) $(3)
125 es6_RUNSTEP
= node ..
/$(2) $(3)
126 factor_RUNSTEP
= factor ..
/$(2) $(3)
127 forth_RUNSTEP
= gforth ..
/$(2) $(3)
128 fsharp_RUNSTEP
= mono ..
/$(2) --raw
$(3)
129 go_RUNSTEP
= ..
/$(2) $(3)
130 groovy_RUNSTEP
= groovy ..
/$(2) $(3)
131 haskell_RUNSTEP
= ..
/$(2) $(3)
132 java_RUNSTEP
= mvn
-quiet exec
:java
-Dexec.mainClass
="mal.$($(1))" $(if
$(3), -Dexec.args
="$(3)",)
133 julia_RUNSTEP
= ..
/$(2) $(3)
134 js_RUNSTEP
= node ..
/$(2) $(3)
135 kotlin_RUNSTEP
= java
-jar ..
/$(2) $(3)
136 lua_RUNSTEP
= ..
/$(2) $(3)
137 make_RUNSTEP
= make
-f ..
/$(2) $(3)
138 mal_RUNSTEP
= $(call
$(MAL_IMPL
)_RUNSTEP
,stepA
,$(call
$(MAL_IMPL
)_STEP_TO_PROG
,stepA
),..
/$(2),") #"
139 ocaml_RUNSTEP
= ..
/$(2) $(3)
140 matlab_args
= $(subst $(SPACE
),$(COMMA
),$(foreach x
,$(strip $(1)),'$(x)'))
141 matlab_RUNSTEP
= matlab
-nodisplay
-nosplash
-nodesktop
-nojvm
-r
"$($(1))($(call matlab_args,$(3)));quit;"
142 miniMAL_RUNSTEP
= miniMAL ..
/$(2) $(3)
143 nim_RUNSTEP
= ..
/$(2) $(3)
144 perl_RUNSTEP
= perl ..
/$(2) $(3)
145 php_RUNSTEP
= php ..
/$(2) $(3)
146 ps_RUNSTEP
= gs
-q
-I.
/ -dNODISPLAY
-- ..
/$(2) $(3)
147 python_RUNSTEP
= $(PYTHON
) ..
/$(2) $(3)
148 r_RUNSTEP
= Rscript ..
/$(2) $(3)
149 racket_RUNSTEP
= ..
/$(2) $(3)
150 rpython_RUNSTEP
= ..
/$(2) $(3)
151 ruby_RUNSTEP
= ruby ..
/$(2) $(3)
152 rust_RUNSTEP
= ..
/$(2) $(3)
153 scala_RUNSTEP
= sbt
'run-main $($(1))$(if $(3), $(3),)'
154 swift_RUNSTEP
= ..
/$(2) $(3)
155 tcl_RUNSTEP
= tclsh ..
/$(2) --raw
$(3)
156 vb_RUNSTEP
= mono ..
/$(2) --raw
$(3)
157 vimscript_RUNSTEP
= .
/run_vimscript.sh ..
/$(2) $(3)
158 # needs TERM=dumb to work with readline
159 guile_RUNSTEP
= guile
--no-auto-compile
-L ..
/guile ..
/$(2) $(3)
162 vimscript_TEST_OPTS
= --test-timeout
30
163 ifeq ($(MAL_IMPL
),vimscript
)
164 mal_TEST_OPTS
= --start-timeout
60 --test-timeout
180
168 STEPS
= $(sort $(filter step
%,$(.VARIABLES
)))
169 DO_IMPLS
= $(filter-out $(SKIP_IMPLS
),$(IMPLS
))
170 IMPL_TESTS
= $(foreach impl
,$(DO_IMPLS
),test^
$(impl
))
171 STEP_TESTS
= $(foreach step
,$(STEPS
),test^
$(step
))
172 ALL_TESTS
= $(filter-out $(EXCLUDE_TESTS
),\
174 $(foreach impl
,$(DO_IMPLS
),\
175 $(foreach step
,$(STEPS
),test^
$(impl
)^
$(step
))))))
177 IMPL_STATS
= $(foreach impl
,$(DO_IMPLS
),stats^
$(impl
))
178 IMPL_STATS_LISP
= $(foreach impl
,$(DO_IMPLS
),stats-lisp^
$(impl
))
180 DOCKER_BUILD
= $(foreach impl
,$(DO_IMPLS
),docker-build^
$(impl
))
182 IMPL_PERF
= $(filter-out $(EXCLUDE_PERFS
),$(foreach impl
,$(DO_IMPLS
),perf^
$(impl
)))
188 # Build a program in an implementation directory
189 # Make sure we always try and build first because the dependencies are
190 # encoded in the implementation Makefile not here
191 .PHONY
: $(foreach i
,$(DO_IMPLS
),$(foreach s
,$(STEPS
),$(call
$(i
)_STEP_TO_PROG
,$(s
))))
192 $(foreach i
,$(DO_IMPLS
),$(foreach s
,$(STEPS
),$(call
$(i
)_STEP_TO_PROG
,$(s
)))):
193 $(foreach impl
,$(word 1,$(subst /, ,$(@
))),\
194 $(MAKE
) -C
$(impl
) $(subst $(impl
)/,,$(@
)))
196 # Allow test, test^STEP, test^IMPL, and test^IMPL^STEP
198 $(IMPL_TESTS
): $$(filter $$@^
%,$$(ALL_TESTS
))
201 $(STEP_TESTS
): $$(foreach step
,$$(subst test^
,,$$@
),$$(filter %^
$$(step
),$$(ALL_TESTS
)))
204 $(ALL_TESTS
): $$(call
$$(word 2,$$(subst ^
, ,$$(@
)))_STEP_TO_PROG
,$$(word 3,$$(subst ^
, ,$$(@
))))
205 @
$(foreach impl
,$(word 2,$(subst ^
, ,$(@
))),\
206 $(foreach step
,$(word 3,$(subst ^
, ,$(@
))),\
207 cd
$(if
$(filter mal
,$(impl
)),$(MAL_IMPL
),$(impl
)); \
208 $(foreach test,$(call STEP_TEST_FILES
,$(impl
),$(step
)),\
209 echo
'----------------------------------------------'; \
210 echo
'Testing $@, step file: $+, test file: $(test)'; \
211 echo
'Running: ../runtest.py $(TEST_OPTS) $(call $(impl)_TEST_OPTS) ../$(test) -- $(call $(impl)_RUNSTEP,$(step),$(+))'; \
212 ..
/runtest.py
$(TEST_OPTS
) $(call
$(impl
)_TEST_OPTS
) ..
/$(test) -- $(call
$(impl
)_RUNSTEP
,$(step
),$(+));)))
221 stats-lisp
: $(IMPL_STATS_LISP
)
225 @echo
"----------------------------------------------"; \
226 $(foreach impl
,$(word 2,$(subst ^
, ,$(@
))),\
227 echo
"Stats for $(impl):"; \
228 $(MAKE
) --no-print-directory
-C
$(impl
) stats
)
232 @echo
"----------------------------------------------"; \
233 $(foreach impl
,$(word 2,$(subst ^
, ,$(@
))),\
234 echo
"Stats (lisp only) for $(impl):"; \
235 $(MAKE
) --no-print-directory
-C
$(impl
) stats-lisp
)
239 docker-build
: $(DOCKER_BUILD
)
243 echo
"----------------------------------------------"; \
244 $(foreach impl
,$(word 2,$(subst ^
, ,$(@
))),\
245 echo
"Running: docker build -t kanaka/mal-test-$(impl) .:"; \
246 cd
$(impl
) && docker build
-t kanaka
/mal-test-
$(impl
) .
)
248 # Performance test rules
254 @echo
"----------------------------------------------"; \
255 $(foreach impl
,$(word 2,$(subst ^
, ,$(@
))),\
256 cd
$(if
$(filter mal
,$(impl
)),$(MAL_IMPL
),$(impl
)); \
257 echo
"Performance test for $(impl):"; \
258 echo
'Running: $(call $(impl)_RUNSTEP,stepA,$(call $(impl)_STEP_TO_PROG,stepA),../tests/perf1.mal)'; \
259 $(call
$(impl
)_RUNSTEP
,stepA
,$(call
$(impl
)_STEP_TO_PROG
,stepA
),..
/tests
/perf1.mal
); \
260 echo
'Running: $(call $(impl)_RUNSTEP,stepA,$(call $(impl)_STEP_TO_PROG,stepA),../tests/perf2.mal)'; \
261 $(call
$(impl
)_RUNSTEP
,stepA
,$(call
$(impl
)_STEP_TO_PROG
,stepA
),..
/tests
/perf2.mal
); \
262 echo
'Running: $(call $(impl)_RUNSTEP,stepA,$(call $(impl)_STEP_TO_PROG,stepA),../tests/perf3.mal)'; \
263 $(call
$(impl
)_RUNSTEP
,stepA
,$(call
$(impl
)_STEP_TO_PROG
,stepA
),..
/tests
/perf3.mal
))