mirror of
https://github.com/kanaka/mal.git
synced 2024-09-11 13:55:55 +03:00
Add step5/9 tests for impls that support it.
- Also remove broken make/tests/*.mk tests. Not used any more.
This commit is contained in:
parent
b58698b257
commit
cc021efe10
14
Makefile
14
Makefile
@ -24,7 +24,19 @@ step8 = step8_macros
|
||||
step9 = step9_interop
|
||||
stepA = stepA_more
|
||||
|
||||
EXCLUDE_TESTS = test^make^step5 test^mal^step0 test^mal^step5 test^mal^step9 test^java^step9 test^cs^step9
|
||||
EXCLUDE_TESTS += test^bash^step5 # no stack exhaustion or completion
|
||||
EXCLUDE_TESTS += test^c^step5 # segfault
|
||||
EXCLUDE_TESTS += test^cs^step5 # fatal stack overflow fault
|
||||
EXCLUDE_TESTS += test^make^step5 # no TCO capability/step
|
||||
EXCLUDE_TESTS += test^mal^step5 # no TCO capability/step
|
||||
EXCLUDE_TESTS += test^php^step5 # test completes, even at 100,000
|
||||
EXCLUDE_TESTS += test^ruby^step5 # test completes, even at 100,000
|
||||
|
||||
# interop tests now implemented yet
|
||||
EXCLUDE_TESTS += test^cs^step9 test^java^step9 test^mal^step9 \
|
||||
test^php^step9 test^ps^step9 test^python^step9 \
|
||||
test^ruby^step9
|
||||
|
||||
EXCLUDE_PERFS = perf^mal # TODO: fix this
|
||||
|
||||
#
|
||||
|
@ -1,5 +1,3 @@
|
||||
TESTS = tests/types.sh tests/reader.sh
|
||||
|
||||
SOURCES_BASE = types.sh reader.sh printer.sh
|
||||
SOURCES_LISP = env.sh core.sh stepA_more.sh
|
||||
SOURCES = $(SOURCES_BASE) $(SOURCES_LISP)
|
||||
@ -15,15 +13,9 @@ mal.sh: $(SOURCES)
|
||||
clean:
|
||||
rm -f mal.sh
|
||||
|
||||
.PHONY: stats tests $(TESTS)
|
||||
.PHONY: stats
|
||||
|
||||
stats: $(SOURCES)
|
||||
@wc $^
|
||||
stats-lisp: $(SOURCES_LISP)
|
||||
@wc $^
|
||||
|
||||
tests: $(TESTS)
|
||||
|
||||
$(TESTS):
|
||||
@echo "Running $@"; \
|
||||
bash $@ || exit 1; \
|
||||
|
@ -164,7 +164,7 @@ EVAL () {
|
||||
while read line; do
|
||||
output="${output}${line}\n"
|
||||
done < <(eval ${ANON["${r}"]})
|
||||
_string "${output}"
|
||||
_string "${output%\\n}"
|
||||
return ;;
|
||||
do) _count "${ast}"
|
||||
_slice "${ast}" 1 $(( ${r} - 2 ))
|
||||
|
@ -164,7 +164,7 @@ EVAL () {
|
||||
while read line; do
|
||||
output="${output}${line}\n"
|
||||
done < <(eval ${ANON["${r}"]})
|
||||
_string "${output}"
|
||||
_string "${output%\\n}"
|
||||
return ;;
|
||||
try*) MACROEXPAND "${a1}" "${env}"
|
||||
EVAL "${r}" "${env}"
|
||||
|
@ -1,25 +0,0 @@
|
||||
|
||||
assert () {
|
||||
if ! eval "${2}"; then
|
||||
echo "assert failure line ${1}"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
assert_eq () {
|
||||
if eval "${3}"; then
|
||||
if [[ "${2}" != "${r}" ]]; then
|
||||
echo "assert_eq failure line ${1}: '${2}' != '${r}'"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "assert_eq failure line ${1}: could not evaluate '${3}'"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
TEST_RE () {
|
||||
r=
|
||||
READ_STR "${1}"
|
||||
EVAL "${r}" ${REPL_ENV}
|
||||
}
|
@ -1,88 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
INTERACTIVE=
|
||||
|
||||
source tests/common.sh
|
||||
source reader.sh
|
||||
|
||||
echo "Testing read of constants/strings"
|
||||
assert_eq $LINENO 2 "READ_STR '2'; number_pr_str \$r"
|
||||
assert_eq $LINENO 12345 "READ_STR '12345'; number_pr_str \$r"
|
||||
assert_eq $LINENO 12345 "READ_STR '12345 \"abc\"'; number_pr_str \$r"
|
||||
assert_eq $LINENO 'abc' "READ_STR '\"abc\"'; number_pr_str \$r"
|
||||
assert_eq $LINENO 'a string (with parens)' "READ_STR '\"a string (with parens)\"'; number_pr_str \$r"
|
||||
|
||||
echo "Testing read of symbols"
|
||||
assert $LINENO "READ_STR 'abc'; _symbol? \$r"
|
||||
assert_eq $LINENO 'abc' "READ_STR 'abc'; symbol_pr_str \$r"
|
||||
assert_eq $LINENO '.' "READ_STR '.'; symbol_pr_str \$r"
|
||||
|
||||
raw_val () {
|
||||
r="${ANON["${1}"]}"
|
||||
}
|
||||
|
||||
echo "Testing READ_STR of strings"
|
||||
assert_eq $LINENO 'a string' "READ_STR '\"a string\"'; raw_val \$r"
|
||||
assert_eq $LINENO 'a string (with parens)' "READ_STR '\"a string (with parens)\"'; raw_val \$r"
|
||||
assert_eq $LINENO 'a string' "READ_STR '\"a string\"()'; raw_val \$r"
|
||||
assert_eq $LINENO 'a string' "READ_STR '\"a string\"123'; raw_val \$r"
|
||||
assert_eq $LINENO 'a string' "READ_STR '\"a string\"abc'; raw_val \$r"
|
||||
assert_eq $LINENO '' "READ_STR '\"\"'; raw_val \$r"
|
||||
assert_eq $LINENO 'abc ' "READ_STR '\"abc \"'; raw_val \$r"
|
||||
assert_eq $LINENO ' abc' "READ_STR '\" abc\"'; raw_val \$r"
|
||||
assert_eq $LINENO '$abc' "READ_STR '\"\$abc\"'; raw_val \$r"
|
||||
assert_eq $LINENO 'abc$()' "READ_STR '\"abc\$()\"'; raw_val \$r"
|
||||
# TODO: fix parsing of escaped characters
|
||||
#assert_eq $LINENO '"xyz"' "READ_STR '\"\\\"xyz\\\"\"'; raw_val \$r"
|
||||
|
||||
echo "Testing READ_STR of lists"
|
||||
assert_eq $LINENO 2 "READ_STR '(2 3)'; _count \$r"
|
||||
assert_eq $LINENO 2 "READ_STR '(2 3)'; first \$r; number_pr_str \$r"
|
||||
assert_eq $LINENO 3 "READ_STR '(2 3)'; rest \$r; first \$r; number_pr_str \$r"
|
||||
|
||||
READ_STR "(+ 1 2 \"str1\" \"string (with parens) and 'single quotes'\")"
|
||||
L="${r}"
|
||||
assert_eq $LINENO 5 "_count \$r"
|
||||
assert_eq $LINENO 'str1' "_nth ${L} 3; raw_val \$r"
|
||||
assert_eq $LINENO "string (with parens) and 'single quotes'" "_nth ${L} 4; raw_val \$r"
|
||||
assert_eq $LINENO '(2 3)' "READ_STR '(2 3)'; list_pr_str \$r"
|
||||
assert_eq $LINENO '(2 3 "string (with parens)")' "READ_STR '(2 3 \"string (with parens)\")'; list_pr_str \$r yes"
|
||||
|
||||
|
||||
echo "Testing READ_STR of vectors"
|
||||
assert_eq $LINENO 2 "READ_STR '[2 3]'; _count \$r"
|
||||
assert_eq $LINENO 2 "READ_STR '[2 3]'; first \$r; number_pr_str \$r"
|
||||
assert_eq $LINENO 3 "READ_STR '[2 3]'; rest \$r; first \$r; number_pr_str \$r"
|
||||
|
||||
READ_STR "[+ 1 2 \"str1\" \"string (with parens) and 'single quotes'\"]"
|
||||
L="${r}"
|
||||
assert_eq $LINENO 5 "_count \$r"
|
||||
assert_eq $LINENO 'str1' "_nth ${L} 3; raw_val \$r"
|
||||
assert_eq $LINENO "string (with parens) and 'single quotes'" "_nth ${L} 4; raw_val \$r"
|
||||
assert_eq $LINENO '[2 3]' "READ_STR '[2 3]'; vector_pr_str \$r yes"
|
||||
assert_eq $LINENO '[2 3 "string (with parens)"]' "READ_STR '[2 3 \"string (with parens)\"]'; vector_pr_str \$r yes"
|
||||
|
||||
|
||||
echo "Testing READ_STR of quote/quasiquote"
|
||||
assert_eq $LINENO 'quote' "READ_STR \"'1\"; _nth \$r 0; raw_val \$r"
|
||||
assert_eq $LINENO 1 "READ_STR \"'1\"; _nth \$r 1; raw_val \$r"
|
||||
assert_eq $LINENO 'quote' "READ_STR \"'(1 2 3)\"; _nth \$r 0; raw_val \$r"
|
||||
assert_eq $LINENO 3 "READ_STR \"'(1 2 3)\"; _nth \$r 1; _nth \$r 2; raw_val \$r"
|
||||
|
||||
assert_eq $LINENO 'quasiquote' "READ_STR \"\\\`1\"; _nth \$r 0; raw_val \$r"
|
||||
assert_eq $LINENO 1 "READ_STR \"\\\`1\"; _nth \$r 1; raw_val \$r"
|
||||
assert_eq $LINENO 'quasiquote' "READ_STR \"\\\`(1 2 3)\"; _nth \$r 0; raw_val \$r"
|
||||
assert_eq $LINENO 3 "READ_STR \"\\\`(1 2 3)\"; _nth \$r 1; _nth \$r 2; raw_val \$r"
|
||||
|
||||
assert_eq $LINENO 'unquote' "READ_STR \"~1\"; _nth \$r 0; raw_val \$r"
|
||||
assert_eq $LINENO 1 "READ_STR \"~1\"; _nth \$r 1; raw_val \$r"
|
||||
assert_eq $LINENO 'unquote' "READ_STR \"~(1 2 3)\"; _nth \$r 0; raw_val \$r"
|
||||
assert_eq $LINENO 3 "READ_STR \"~(1 2 3)\"; _nth \$r 1; _nth \$r 2; raw_val \$r"
|
||||
|
||||
assert_eq $LINENO 'splice-unquote' "READ_STR \"~@1\"; _nth \$r 0; raw_val \$r"
|
||||
assert_eq $LINENO 1 "READ_STR \"~@1\"; _nth \$r 1; raw_val \$r"
|
||||
assert_eq $LINENO 'splice-unquote' "READ_STR \"~@(1 2 3)\"; _nth \$r 0; raw_val \$r"
|
||||
assert_eq $LINENO 3 "READ_STR \"~@(1 2 3)\"; _nth \$r 1; _nth \$r 2; raw_val \$r"
|
||||
|
||||
|
||||
echo "All tests completed"
|
17
bash/tests/step9_interop.mal
Normal file
17
bash/tests/step9_interop.mal
Normal file
@ -0,0 +1,17 @@
|
||||
;; Testing basic bash interop
|
||||
|
||||
(sh* "echo 7")
|
||||
;=>"7"
|
||||
|
||||
(sh* "echo >&2 hello")
|
||||
; hello
|
||||
;=>""
|
||||
|
||||
(sh* "foo=8; echo ${foo}")
|
||||
;=>"8"
|
||||
|
||||
(sh* "for x in a b c; do echo -n \"X${x}Y \"; done; echo")
|
||||
;=>"XaY XbY XcY"
|
||||
|
||||
(sh* "for x in 1 2 3; do echo -n \"$((1+$x)) \"; done; echo")
|
||||
;=>"2 3 4"
|
@ -1,161 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
source tests/common.sh
|
||||
source types.sh
|
||||
|
||||
echo "Testing type function"
|
||||
assert_eq $LINENO bash "_obj_type xyz"
|
||||
assert_eq $LINENO nil "_obj_type ${__nil}"
|
||||
assert_eq $LINENO true "_obj_type ${__true}"
|
||||
assert_eq $LINENO false "_obj_type ${__false}"
|
||||
|
||||
|
||||
echo "Testing number? function"
|
||||
assert_eq $LINENO number "number 1; _obj_type \$r"
|
||||
assert_eq $LINENO number "number 10; _obj_type \$r"
|
||||
assert_eq $LINENO number "number 12345; _obj_type \$r"
|
||||
|
||||
|
||||
echo "Testing symbols"
|
||||
assert_eq $LINENO symbol "symbol abc; _obj_type \$r"
|
||||
symbol "a sym value"; SYM1="${r}"
|
||||
assert_eq $LINENO "a sym value" "symbol_pr_str ${SYM1} yes"
|
||||
assert_eq $LINENO ${__true} "symbol? ${SYM1}"
|
||||
|
||||
|
||||
echo "Testing strings"
|
||||
assert_eq $LINENO string "string abc; _obj_type \$r"
|
||||
string "a string value"; STR1="${r}"
|
||||
assert_eq $LINENO "\"a string value\"" "string_pr_str ${STR1} yes"
|
||||
assert_eq $LINENO ${__true} "string? ${STR1}"
|
||||
# TODO: fix to count characters instead of words
|
||||
#assert_eq $LINENO 14 "_count ${STR1}"
|
||||
|
||||
string "a string (with parens)"; STR2="${r}"
|
||||
assert_eq $LINENO "\"a string (with parens)\"" "string_pr_str ${STR2} yes"
|
||||
assert_eq $LINENO ${__true} "string? ${STR2}"
|
||||
|
||||
# TODO: test str and subs
|
||||
|
||||
|
||||
echo "Testing function objects"
|
||||
assert_eq $LINENO "function" "_function \"echo hello\"; _obj_type \$r"
|
||||
_function "r=\"arg1:'\$1' arg2:'\$2'\""; FN1="${r}"
|
||||
assert_eq $LINENO ${__true} "function? ${FN1}"
|
||||
assert_eq $LINENO "arg1:'A' arg2:'B'" "${ANON["${FN1}"]} A B"
|
||||
|
||||
|
||||
|
||||
echo "Testing lists"
|
||||
list; LE="${r}"
|
||||
assert_eq $LINENO list "_obj_type ${LE}"
|
||||
|
||||
echo "Testing lists (cons)"
|
||||
list; cons P ${r}; L1="${r}"
|
||||
cons Q ${L1}; L2="${r}"
|
||||
assert_eq $LINENO ${__true} "list? ${L1}"
|
||||
assert_eq $LINENO ${__true} "list? ${L2}"
|
||||
assert_eq $LINENO P "first ${L1}"
|
||||
assert_eq $LINENO 2 "_count ${L2}"
|
||||
assert_eq $LINENO Q "first ${L2}"
|
||||
assert_eq $LINENO P "_nth ${L2} 1"
|
||||
rest ${L2}; L2R="${r}"
|
||||
|
||||
echo "Testing lists (concat)"
|
||||
concat ${L1} ${L2}; L1_2="${r}"
|
||||
assert_eq $LINENO 3 "_count ${L1_2}"
|
||||
assert_eq $LINENO P "first ${L1_2}"
|
||||
assert_eq $LINENO Q "_nth ${L1_2} 1"
|
||||
assert_eq $LINENO P "_nth ${L1_2} 2"
|
||||
rest ${L1_2}; L1_2R="${r}"
|
||||
|
||||
echo "Testing lists (conj)"
|
||||
list; conj ${r} A B; L3="${r}"
|
||||
list; conj ${r} X ${L3}; L4="${r}"
|
||||
assert_eq $LINENO ${__true} "list? ${L3}"
|
||||
assert_eq $LINENO ${__true} "list? ${L4}"
|
||||
assert_eq $LINENO A "first ${L3}"
|
||||
assert_eq $LINENO X "first ${L4}"
|
||||
_nth ${L4} 1; L4_1="${r}"
|
||||
assert_eq $LINENO ${__true} "list? ${L4_1}"
|
||||
assert_eq $LINENO A "first ${L4_1}"
|
||||
|
||||
|
||||
echo "Testing hash maps"
|
||||
hash_map; X="${r}"
|
||||
hash_map; Y="${r}"
|
||||
assert_eq $LINENO ${__true} "hash_map? ${X}"
|
||||
assert_eq $LINENO ${__true} "hash_map? ${Y}"
|
||||
|
||||
string "a"
|
||||
mykey="${r}"
|
||||
assert_eq $LINENO "" "_get ${X} a"
|
||||
assert_eq $LINENO ${__false} "contains? ${X} ${mykey}"
|
||||
assoc! ${X} a 'value of X a'
|
||||
assert_eq $LINENO "value of X a" "_get ${X} a"
|
||||
assert_eq $LINENO ${__true} "contains? ${X} ${mykey}"
|
||||
|
||||
# TODO: more testing of Y, assoc!, dissoc!
|
||||
|
||||
|
||||
# TODO: vectors
|
||||
|
||||
|
||||
echo "Testing _map/map function"
|
||||
list; conj "${r}" 1 2 3; L5="${r}"
|
||||
inc () { r=$(( ${1} + 1)); }
|
||||
assert_eq $LINENO "2 3 4" "_map inc ${L5}; r=\${ANON[\$r]}"
|
||||
_function "r=\$(( \$1 + 1 ));"; inc_func="${r}"
|
||||
assert_eq $LINENO "2 3 4" "map ${inc_func} ${L5}; r=\${ANON[\$r]}"
|
||||
|
||||
|
||||
echo "Testing equal? function"
|
||||
assert_eq $LINENO ${__true} "equal? 2 2"
|
||||
assert_eq $LINENO ${__false} "equal? 2 3"
|
||||
assert_eq $LINENO ${__false} "equal? 2 3"
|
||||
assert_eq $LINENO ${__true} "equal? abc abc"
|
||||
assert_eq $LINENO ${__false} "equal? abc abz"
|
||||
assert_eq $LINENO ${__false} "equal? zbc abc"
|
||||
assert_eq $LINENO ${__true} "string abc; A=\$r; string abc; B=\$r; equal? \$A \$B"
|
||||
assert_eq $LINENO ${__false} "string abc; A=\$r; string abz; B=\$r; equal? \$A \$B"
|
||||
assert_eq $LINENO ${__false} "string zbc; A=\$r; string abc; B=\$r; equal? \$A \$B"
|
||||
assert_eq $LINENO ${__true} "symbol abc; A=\$r; symbol abc; B=\$r; equal? \$A \$B"
|
||||
assert_eq $LINENO ${__false} "symbol abc; A=\$r; symbol abz; B=\$r; equal? \$A \$B"
|
||||
assert_eq $LINENO ${__false} "symbol zbc; A=\$r; symbol abc; B=\$r; equal? \$A \$B"
|
||||
list; conj "${r}" 1 2 3; L6="${r}"
|
||||
list; conj "${r}" 1 2 3; L7="${r}"
|
||||
list; conj "${r}" 1 2 Z; L8="${r}"
|
||||
list; conj "${r}" Z 2 3; L9="${r}"
|
||||
list; conj "${r}" 1 2; L10="${r}"
|
||||
assert_eq $LINENO ${__true} "equal? ${L6} ${L7}"
|
||||
assert_eq $LINENO ${__false} "equal? ${L6} ${L8}"
|
||||
assert_eq $LINENO ${__false} "equal? ${L6} ${L9}"
|
||||
assert_eq $LINENO ${__false} "equal? ${L6} ${L10}"
|
||||
assert_eq $LINENO ${__false} "equal? ${L10} ${L6}"
|
||||
|
||||
# TODO: empty? function tests
|
||||
|
||||
echo "Testing ENV environment (1 level)"
|
||||
ENV; env1="${r}"
|
||||
assert_eq $LINENO "" "ENV_GET \"${env1}\" a"
|
||||
ENV_SET "${env1}" a "val_a"
|
||||
ENV_SET "${env1}" b "val_b"
|
||||
ENV_SET "${env1}" = "val_eq"
|
||||
assert_eq $LINENO "val_a" "ENV_GET \"${env1}\" a"
|
||||
assert_eq $LINENO "val_b" "ENV_GET \"${env1}\" b"
|
||||
assert_eq $LINENO "val_eq" "ENV_GET \"${env1}\" ="
|
||||
assert_eq $LINENO "${env1}" "ENV_FIND \"${env1}\" ="
|
||||
|
||||
echo "Testing ENV environment (2 levels)"
|
||||
ENV "${env1}"; env2="${r}"
|
||||
ENV_SET "${env2}" b "val_b2"
|
||||
ENV_SET "${env2}" c "val_c"
|
||||
assert_eq $LINENO "${env1}" "ENV_FIND \"${env2}\" a"
|
||||
assert_eq $LINENO "${env2}" "ENV_FIND \"${env2}\" b"
|
||||
assert_eq $LINENO "${env2}" "ENV_FIND \"${env2}\" c"
|
||||
assert_eq $LINENO "val_a" "ENV_GET \"${env2}\" a"
|
||||
assert_eq $LINENO "val_b2" "ENV_GET \"${env2}\" b"
|
||||
assert_eq $LINENO "val_c" "ENV_GET \"${env2}\" c"
|
||||
|
||||
|
||||
echo "All tests completed"
|
@ -1,21 +1,12 @@
|
||||
|
||||
TESTS =
|
||||
|
||||
SOURCES_BASE = src/readline.clj src/reader.clj src/printer.clj
|
||||
SOURCES_LISP = src/env.clj src/core.clj src/stepA_more.clj
|
||||
SOURCES = $(SOURCES_BASE) $(SOURCES_LISP)
|
||||
|
||||
all:
|
||||
|
||||
.PHONY: stats tests $(TESTS)
|
||||
.PHONY: stats
|
||||
|
||||
stats: $(SOURCES)
|
||||
@wc $^
|
||||
stats-lisp: $(SOURCES_LISP)
|
||||
@wc $^
|
||||
|
||||
tests: $(TESTS)
|
||||
|
||||
$(TESTS):
|
||||
@echo "Running $@"; \
|
||||
lein with-profile XXX$@XXX trampoline run || exit 1; \
|
||||
|
17
clojure/tests/step9_interop.mal
Normal file
17
clojure/tests/step9_interop.mal
Normal file
@ -0,0 +1,17 @@
|
||||
;; Testing basic clojure interop
|
||||
|
||||
(clj* "7")
|
||||
;=>7
|
||||
|
||||
(clj* "\"abc\"")
|
||||
;=>"abc"
|
||||
|
||||
(clj* "{\"abc\" 123}")
|
||||
;=>{"abc" 123}
|
||||
|
||||
(clj* "(prn \"foo\")")
|
||||
; "foo"
|
||||
;=>nil
|
||||
|
||||
(clj* "(for [x [1 2 3]] (+ 1 x))")
|
||||
;=>(2 3 4)
|
@ -49,11 +49,11 @@ public class step1_read_print {
|
||||
System.out.println(PRINT(RE(null, line)));
|
||||
} catch (MalContinue e) {
|
||||
continue;
|
||||
} catch (MalError e) {
|
||||
System.out.println("Error: " + e.getMessage());
|
||||
} catch (MalThrowable t) {
|
||||
System.out.println("Error: " + t.getMessage());
|
||||
continue;
|
||||
} catch (reader.ParseError e) {
|
||||
System.out.println(e.getMessage());
|
||||
} catch (Throwable t) {
|
||||
System.out.println("Uncaught " + t + ": " + t.getMessage());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -126,11 +126,11 @@ public class step2_eval {
|
||||
System.out.println(PRINT(RE(repl_env, line)));
|
||||
} catch (MalContinue e) {
|
||||
continue;
|
||||
} catch (reader.ParseError e) {
|
||||
System.out.println(e.getMessage());
|
||||
} catch (MalThrowable t) {
|
||||
System.out.println("Error: " + t.getMessage());
|
||||
continue;
|
||||
} catch (MalError e) {
|
||||
System.out.println("Error: " + e.getMessage());
|
||||
} catch (Throwable t) {
|
||||
System.out.println("Uncaught " + t + ": " + t.getMessage());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -146,11 +146,11 @@ public class step3_env {
|
||||
System.out.println(PRINT(RE(repl_env, line)));
|
||||
} catch (MalContinue e) {
|
||||
continue;
|
||||
} catch (reader.ParseError e) {
|
||||
System.out.println(e.getMessage());
|
||||
} catch (MalThrowable t) {
|
||||
System.out.println("Error: " + t.getMessage());
|
||||
continue;
|
||||
} catch (MalError e) {
|
||||
System.out.println("Error: " + e.getMessage());
|
||||
} catch (Throwable t) {
|
||||
System.out.println("Uncaught " + t + ": " + t.getMessage());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -154,12 +154,12 @@ public class step4_if_fn_do {
|
||||
System.out.println(PRINT(RE(repl_env, line)));
|
||||
} catch (MalContinue e) {
|
||||
continue;
|
||||
} catch (reader.ParseError e) {
|
||||
System.out.println(e.getMessage());
|
||||
continue;
|
||||
} catch (MalThrowable t) {
|
||||
System.out.println("Error: " + t.getMessage());
|
||||
continue;
|
||||
} catch (Throwable t) {
|
||||
System.out.println("Uncaught " + t + ": " + t.getMessage());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -167,12 +167,12 @@ public class step5_tco {
|
||||
System.out.println(PRINT(RE(repl_env, line)));
|
||||
} catch (MalContinue e) {
|
||||
continue;
|
||||
} catch (reader.ParseError e) {
|
||||
System.out.println(e.getMessage());
|
||||
continue;
|
||||
} catch (MalThrowable t) {
|
||||
System.out.println("Error: " + t.getMessage());
|
||||
continue;
|
||||
} catch (Throwable t) {
|
||||
System.out.println("Uncaught " + t + ": " + t.getMessage());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -185,12 +185,12 @@ public class step6_file {
|
||||
System.out.println(PRINT(RE(repl_env, line)));
|
||||
} catch (MalContinue e) {
|
||||
continue;
|
||||
} catch (reader.ParseError e) {
|
||||
System.out.println(e.getMessage());
|
||||
continue;
|
||||
} catch (MalThrowable t) {
|
||||
System.out.println("Error: " + t.getMessage());
|
||||
continue;
|
||||
} catch (Throwable t) {
|
||||
System.out.println("Uncaught " + t + ": " + t.getMessage());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -217,12 +217,12 @@ public class step7_quote {
|
||||
System.out.println(PRINT(RE(repl_env, line)));
|
||||
} catch (MalContinue e) {
|
||||
continue;
|
||||
} catch (reader.ParseError e) {
|
||||
System.out.println(e.getMessage());
|
||||
continue;
|
||||
} catch (MalThrowable t) {
|
||||
System.out.println("Error: " + t.getMessage());
|
||||
continue;
|
||||
} catch (Throwable t) {
|
||||
System.out.println("Uncaught " + t + ": " + t.getMessage());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -257,12 +257,12 @@ public class step8_macros {
|
||||
System.out.println(PRINT(RE(repl_env, line)));
|
||||
} catch (MalContinue e) {
|
||||
continue;
|
||||
} catch (reader.ParseError e) {
|
||||
System.out.println(e.getMessage());
|
||||
continue;
|
||||
} catch (MalThrowable t) {
|
||||
System.out.println("Error: " + t.getMessage());
|
||||
continue;
|
||||
} catch (Throwable t) {
|
||||
System.out.println("Uncaught " + t + ": " + t.getMessage());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -287,15 +287,15 @@ public class stepA_more {
|
||||
System.out.println(PRINT(RE(repl_env, line)));
|
||||
} catch (MalContinue e) {
|
||||
continue;
|
||||
} catch (reader.ParseError e) {
|
||||
System.out.println(e.getMessage());
|
||||
continue;
|
||||
} catch (MalException e) {
|
||||
System.out.println("Error: " + printer._pr_str(e.getValue(), false));
|
||||
continue;
|
||||
} catch (MalThrowable t) {
|
||||
System.out.println("Error: " + t.getMessage());
|
||||
continue;
|
||||
} catch (Throwable t) {
|
||||
System.out.println("Uncaught " + t + ": " + t.getMessage());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
TESTS = tests/types.js tests/reader.js tests/step5_tco.js
|
||||
TESTS = tests/types.js tests/reader.js
|
||||
|
||||
SOURCES_BASE = node_readline.js types.js reader.js printer.js
|
||||
SOURCES_LISP = env.js core.js stepA_more.js
|
||||
|
@ -1,22 +0,0 @@
|
||||
common = require('./common.js');
|
||||
var assert_eq = common.assert_eq;
|
||||
var rep = require('../step5_tco.js').rep;
|
||||
|
||||
console.log("Testing Stack Exhaustion Function");
|
||||
rep('(def! sum-to (fn* (n) (if (= n 0) 0 (+ n (sum-to (- n 1))))))');
|
||||
try {
|
||||
rep('(sum-to 10000)');
|
||||
throw new Error("Did not get expected stack exhaustion");
|
||||
} catch (e) {
|
||||
if (e.toString().match(/RangeError/)) {
|
||||
console.log("Got expected stack exhaustion");
|
||||
} else {
|
||||
throw new Error("Unexpected error: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
console.log("Testing Tail Call Optimization/Elimination");
|
||||
rep('(def! sum2 (fn* (n acc) (if (= n 0) acc (sum2 (- n 1) (+ n acc)))))');
|
||||
rep('(sum2 10000 0)');
|
||||
|
||||
console.log("All tests completed");
|
24
js/tests/step9_interop.mal
Normal file
24
js/tests/step9_interop.mal
Normal file
@ -0,0 +1,24 @@
|
||||
;; Testing basic bash interop
|
||||
|
||||
(js* "7")
|
||||
;=>7
|
||||
|
||||
(js* "'7'")
|
||||
;=>"7"
|
||||
|
||||
(js* "[7,8,9]")
|
||||
;=>(7 8 9)
|
||||
|
||||
(js* "console.log('hello');")
|
||||
; hello
|
||||
;=>nil
|
||||
|
||||
(js* "foo=8;")
|
||||
(js* "foo;")
|
||||
;=>8
|
||||
|
||||
(js* "['a','b','c'].map(function(x){return 'X'+x+'Y'}).join(' ')")
|
||||
;=>"XaY XbY XcY"
|
||||
|
||||
(js* "[1,2,3].map(function(x){return 1+x})")
|
||||
;=>(2 3 4)
|
34
make/rules.mk
Normal file
34
make/rules.mk
Normal file
@ -0,0 +1,34 @@
|
||||
# To load this file:
|
||||
# $(eval include rules.mk)
|
||||
|
||||
# Usage:
|
||||
# (make* "$(eval $(call PRINT_RULE,abc,,@echo \"building $$@\"))")
|
||||
define PRINT_RULE
|
||||
$(1): $(2)
|
||||
$(3)
|
||||
endef
|
||||
|
||||
# Usage:
|
||||
# (make* "$(eval $(call PRINT_LINES,abc:, @echo \"shell command\"))")
|
||||
define PRINT_LINES
|
||||
$(1)
|
||||
$(2)
|
||||
$(3)
|
||||
$(4)
|
||||
$(5)
|
||||
$(6)
|
||||
$(7)
|
||||
$(8)
|
||||
$(9)
|
||||
$(10)
|
||||
$(11)
|
||||
$(12)
|
||||
$(13)
|
||||
$(14)
|
||||
$(15)
|
||||
$(16)
|
||||
$(17)
|
||||
$(18)
|
||||
$(19)
|
||||
$(20)
|
||||
endef
|
@ -119,9 +119,10 @@ $(if $(MAKECMDGOALS),\
|
||||
$(call do,$(call _conj!,$(_argv),$(call _string,$(arg)))))\
|
||||
$(call do,$(call REP, (load-file "$(word 1,$(MAKECMDGOALS))") )) \
|
||||
$(eval INTERACTIVE :=),)
|
||||
.PHONY: none $(MAKECMDGOALS)
|
||||
none $(MAKECMDGOALS):
|
||||
@true
|
||||
|
||||
# repl loop
|
||||
$(if $(strip $(INTERACTIVE)),$(call REPL))
|
||||
|
||||
.PHONY: none $(MAKECMDGOALS)
|
||||
none $(MAKECMDGOALS):
|
||||
@true
|
||||
|
@ -136,9 +136,10 @@ $(if $(MAKECMDGOALS),\
|
||||
$(call do,$(call _conj!,$(_argv),$(call _string,$(arg)))))\
|
||||
$(call do,$(call REP, (load-file "$(word 1,$(MAKECMDGOALS))") )) \
|
||||
$(eval INTERACTIVE :=),)
|
||||
.PHONY: none $(MAKECMDGOALS)
|
||||
none $(MAKECMDGOALS):
|
||||
@true
|
||||
|
||||
# repl loop
|
||||
$(if $(strip $(INTERACTIVE)),$(call REPL))
|
||||
|
||||
.PHONY: none $(MAKECMDGOALS)
|
||||
none $(MAKECMDGOALS):
|
||||
@true
|
||||
|
@ -161,9 +161,10 @@ $(if $(MAKECMDGOALS),\
|
||||
$(call do,$(call _conj!,$(_argv),$(call _string,$(arg)))))\
|
||||
$(call do,$(call REP, (load-file "$(word 1,$(MAKECMDGOALS))") )) \
|
||||
$(eval INTERACTIVE :=),)
|
||||
.PHONY: none $(MAKECMDGOALS)
|
||||
none $(MAKECMDGOALS):
|
||||
@true
|
||||
|
||||
# repl loop
|
||||
$(if $(strip $(INTERACTIVE)),$(call REPL))
|
||||
|
||||
.PHONY: none $(MAKECMDGOALS)
|
||||
none $(MAKECMDGOALS):
|
||||
@true
|
||||
|
@ -102,7 +102,7 @@ $(if $(__ERROR),,\
|
||||
$(if $(call _EQ,make*,$($(a0)_value)),\
|
||||
$(foreach a1,$(call _nth,$(1),1),\
|
||||
$(and $(EVAL_DEBUG),$(info make*: $$(eval __result := $(call str_decode,$(value $(a1)_value)))))\
|
||||
$(eval __result := $(call str_decode,$(value $(a1)_value)))$(call READ_STR,$(__result))),\
|
||||
$(eval __result := $(call str_decode,$(value $(a1)_value)))$(call _string,$(__result))),\
|
||||
$(if $(call _EQ,do,$($(a0)_value)),\
|
||||
$(call slast,$(call EVAL_AST,$(call srest,$(1)),$(2))),\
|
||||
$(if $(call _EQ,if,$($(a0)_value)),\
|
||||
@ -165,9 +165,10 @@ $(if $(MAKECMDGOALS),\
|
||||
$(call do,$(call _conj!,$(_argv),$(call _string,$(arg)))))\
|
||||
$(call do,$(call REP, (load-file "$(word 1,$(MAKECMDGOALS))") )) \
|
||||
$(eval INTERACTIVE :=),)
|
||||
.PHONY: none $(MAKECMDGOALS)
|
||||
none $(MAKECMDGOALS):
|
||||
@true
|
||||
|
||||
# repl loop
|
||||
$(if $(strip $(INTERACTIVE)),$(call REPL))
|
||||
|
||||
.PHONY: none $(MAKECMDGOALS)
|
||||
none $(MAKECMDGOALS):
|
||||
@true
|
||||
|
@ -102,7 +102,7 @@ $(if $(__ERROR),,\
|
||||
$(if $(call _EQ,make*,$($(a0)_value)),\
|
||||
$(foreach a1,$(call _nth,$(1),1),\
|
||||
$(and $(EVAL_DEBUG),$(info make*: $$(eval __result := $(call str_decode,$(value $(a1)_value)))))\
|
||||
$(eval __result := $(call str_decode,$(value $(a1)_value)))$(call READ_STR,$(__result))),\
|
||||
$(eval __result := $(call str_decode,$(value $(a1)_value)))$(call _string,$(__result))),\
|
||||
$(if $(call _EQ,try*,$($(a0)_value)),\
|
||||
$(foreach a1,$(call _nth,$(1),1),\
|
||||
$(foreach res,$(call EVAL,$(a1),$(2)),\
|
||||
@ -181,11 +181,12 @@ $(if $(MAKECMDGOALS),\
|
||||
$(call do,$(call _conj!,$(_argv),$(call _string,$(arg)))))\
|
||||
$(call do,$(call REP, (load-file "$(word 1,$(MAKECMDGOALS))") )) \
|
||||
$(eval INTERACTIVE :=),)
|
||||
.PHONY: none $(MAKECMDGOALS)
|
||||
none $(MAKECMDGOALS):
|
||||
@true
|
||||
|
||||
# repl loop
|
||||
$(if $(strip $(INTERACTIVE)),\
|
||||
$(call do,$(call REP, (println (str "Mal [" *host-language* "]")) )) \
|
||||
$(call REPL))
|
||||
|
||||
.PHONY: none $(MAKECMDGOALS)
|
||||
none $(MAKECMDGOALS):
|
||||
@true
|
||||
|
@ -1,18 +0,0 @@
|
||||
|
||||
# assert macros
|
||||
assert = $(if $1,,$(error assert failure: $2))
|
||||
assert_not = $(if $1,$(error assert_not: $2),)
|
||||
assert_eq = $(if $(call _EQ,$(1),$(2)),,$(error assert_eq failure: $(1) != $(2): $(3)))
|
||||
# With debug:
|
||||
#assert_eq = $(info 1: $(1))$(info 2: $(2))$(info 3: $(3))$(if $(call _EQ,$(1),$(2)),,$(error assert_eq failure: $(3)))
|
||||
|
||||
|
||||
# REPL related wrappers
|
||||
test_read = $(call READ_STR,$(1))
|
||||
ifndef MACROEXPAND
|
||||
define MACROEXPAND
|
||||
$(1)
|
||||
endef
|
||||
endif
|
||||
test_re = $(strip $(call EVAL,$(call MACROEXPAND,$(strip $(call test_read,$(1))),$(REPL_ENV)),$(REPL_ENV)))
|
||||
test_rep = $(call PRINT,$(strip $(call EVAL,$(call MACROEXPAND,$(strip $(call test_read,$(1))),$(REPL_ENV)),$(REPL_ENV))))
|
@ -1,76 +0,0 @@
|
||||
INTERACTIVE = no
|
||||
|
||||
include tests/common.mk
|
||||
include reader.mk
|
||||
|
||||
_tonum = $(call int_decode,$($(1)_value))
|
||||
|
||||
$(info Testing READ_STR of numbers)
|
||||
$(call assert_eq,2,$(call _tonum,$(call READ_STR,2)))
|
||||
$(call assert_eq,12345,$(call _tonum,$(call READ_STR,12345)))
|
||||
$(call assert_eq,12345,$(call _tonum,$(call READ_STR,12345 "abc")))
|
||||
$(call assert_eq,12345,$(call _tonum,$(call READ_STR,12345"abc")))
|
||||
$(call assert_eq,12345,$(call _tonum,$(call READ_STR,12345(1))))
|
||||
|
||||
$(info Testing READ_STR of symbols)
|
||||
$(call assert_eq,abc,$($(call READ_STR,abc)_value))
|
||||
$(call assert_eq,abc,$($(call READ_STR,abc )_value))
|
||||
$(call assert_eq,abc,$($(call READ_STR,abc"a str")_value))
|
||||
$(call assert_eq,abc,$($(call READ_STR,abc(2 3))_value))
|
||||
|
||||
$(info Testing READ_STR of strings)
|
||||
$(call assert_eq,a string,$(call str_decode,$($(call READ_STR,"a string")_value)))
|
||||
$(call assert_eq,a string (with parens),$(call str_decode,$($(call READ_STR,"a string (with parens)")_value)))
|
||||
$(call assert_eq,a string,$(call str_decode,$($(call READ_STR,"a string"())_value)))
|
||||
$(call assert_eq,a string,$(call str_decode,$($(call READ_STR,"a string"123)_value)))
|
||||
$(call assert_eq,a string,$(call str_decode,$($(call READ_STR,"a string"abc)_value)))
|
||||
$(call assert_eq,,$(call str_decode,$($(call READ_STR,"")_value)))
|
||||
$(call assert_eq,abc ,$(call str_decode,$($(call READ_STR,"abc ")_value)))
|
||||
$(call assert_eq, abc,$(call str_decode,$($(call READ_STR," abc")_value)))
|
||||
$(call assert_eq,$$abc,$(call str_decode,$($(call READ_STR,"$$abc")_value)))
|
||||
$(call assert_eq,abc$$(),$(call str_decode,$($(call READ_STR,"abc$$()")_value)))
|
||||
$(call assert_eq,"xyz",$(call str_decode,$($(call READ_STR,"\"xyz\"")_value)))
|
||||
|
||||
$(info Testing READ_STR of lists)
|
||||
$(call assert_eq,2,$(call _count,$(call READ_STR,(2 3))))
|
||||
$(call assert_eq,2,$(call _tonum,$(call sfirst,$(call READ_STR,(2 3)))))
|
||||
$(call assert_eq,3,$(call _tonum,$(call sfirst,$(call srest,$(call READ_STR,(2 3))))))
|
||||
L := $(strip $(call READ_STR,(+ 1 2 "str1" "string (with parens) and 'single quotes'")))
|
||||
$(call assert_eq,5,$(call _count,$(L)))
|
||||
$(call assert_eq,str1,$(call str_decode,$($(call _nth,$(L),3)_value)))
|
||||
$(call assert_eq,string (with parens) and 'single quotes',$(call str_decode,$($(call _nth,$(L),4)_value)))
|
||||
|
||||
$(info Testing READ_STR of vectors)
|
||||
$(call assert_eq,2,$(call _count,$(call READ_STR,[2 3])))
|
||||
$(call assert_eq,2,$(call _tonum,$(call sfirst,$(call READ_STR,[2 3]))))
|
||||
$(call assert_eq,3,$(call _tonum,$(call sfirst,$(call srest,$(call READ_STR,[2 3])))))
|
||||
L := $(strip $(call READ_STR,[+ 1 2 "str1" "string (with parens) and 'single quotes'"]))
|
||||
$(call assert_eq,5,$(call _count,$(L)))
|
||||
$(call assert_eq,str1,$(call str_decode,$($(call _nth,$(L),3)_value)))
|
||||
$(call assert_eq,string (with parens) and 'single quotes',$(call str_decode,$($(call _nth,$(L),4)_value)))
|
||||
|
||||
$(info Testing READ_STR of quote/quasiquote)
|
||||
$(call assert_eq,quote,$($(call _nth,$(call READ_STR,'1),0)_value)) #'
|
||||
$(call assert_eq,1,$(call _tonum,$(call _nth,$(call READ_STR,'1),1))) #'
|
||||
$(call assert_eq,quote,$($(call _nth,$(call READ_STR,'(1 2 3)),0)_value)) #'
|
||||
$(call assert_eq,3,$(call _tonum,$(call _nth,$(call _nth,$(call READ_STR,'(1 2 3)),1),2))) #'
|
||||
|
||||
$(call assert_eq,quasiquote,$($(call _nth,$(call READ_STR,`1),0)_value))
|
||||
$(call assert_eq,1,$(call _tonum,$(call _nth,$(call READ_STR,`1),1)))
|
||||
$(call assert_eq,quasiquote,$($(call _nth,$(call READ_STR,`(1 2 3)),0)_value))
|
||||
$(call assert_eq,3,$(call _tonum,$(call _nth,$(call _nth,$(call READ_STR,`(1 2 3)),1),2)))
|
||||
|
||||
$(call assert_eq,unquote,$($(call _nth,$(call READ_STR,~1),0)_value))
|
||||
$(call assert_eq,1,$(call _tonum,$(call _nth,$(call READ_STR,~1),1)))
|
||||
$(call assert_eq,unquote,$($(call _nth,$(call READ_STR,~(1 2 3)),0)_value))
|
||||
$(call assert_eq,3,$(call _tonum,$(call _nth,$(call _nth,$(call READ_STR,~(1 2 3)),1),2)))
|
||||
|
||||
$(call assert_eq,splice-unquote,$($(call _nth,$(call READ_STR,~@1),0)_value))
|
||||
$(call assert_eq,1,$(call _tonum,$(call _nth,$(call READ_STR,~@1),1)))
|
||||
$(call assert_eq,splice-unquote,$($(call _nth,$(call READ_STR,~@(1 2 3)),0)_value))
|
||||
$(call assert_eq,3,$(call _tonum,$(call _nth,$(call _nth,$(call READ_STR,~@(1 2 3)),1),2)))
|
||||
|
||||
|
||||
.PHONY: all
|
||||
all:
|
||||
@echo "All tests completed"
|
19
make/tests/step9_interop.mal
Normal file
19
make/tests/step9_interop.mal
Normal file
@ -0,0 +1,19 @@
|
||||
;; Testing basic make interop
|
||||
|
||||
(make* "7")
|
||||
;=>"7"
|
||||
|
||||
(make* "$(info foo)")
|
||||
; foo
|
||||
;=>""
|
||||
|
||||
(make* "$(eval foo := 8)")
|
||||
(make* "$(foo)")
|
||||
;=>"8"
|
||||
|
||||
(make* "$(foreach v,a b c,X$(v)Y)")
|
||||
;=>"XaY XbY XcY"
|
||||
|
||||
(read-string (make* "($(foreach v,1 2 3,$(call gmsl_plus,1,$(v))))"))
|
||||
;=>(2 3 4)
|
||||
|
@ -1,14 +0,0 @@
|
||||
INTERACTIVE =
|
||||
|
||||
include tests/common.mk
|
||||
include step9_interop.mk
|
||||
|
||||
$(info Testing trivial macros)
|
||||
$(call assert_eq,7,$(call test_rep, (make* "7") ))
|
||||
$(call assert_eq,"XaY XbY XcY",$(call test_rep, (make* "\"$(foreach v,a b c,X$(v)Y)\"") ))
|
||||
$(call assert_eq,(2 3 4),$(call test_rep, (make* "($(foreach v,1 2 3,$(call gmsl_plus,1,$(v))))") ))
|
||||
|
||||
|
||||
.PHONY: all
|
||||
all:
|
||||
@echo "All tests completed"
|
@ -1,304 +0,0 @@
|
||||
include tests/common.mk
|
||||
include types.mk
|
||||
|
||||
# treat an expression as a statement
|
||||
do = $(eval __tmp := $(1))
|
||||
|
||||
|
||||
$(info Testing foreach as a let form)
|
||||
|
||||
$(call assert_eq,XbX,$(foreach local_var,b,X$(local_var)X),\
|
||||
Using foreach as 'let' failed)
|
||||
|
||||
|
||||
$(info Testing type function)
|
||||
$(call assert_eq,make,$(call _obj_type,xyz),\
|
||||
(type xyz) is not 'make')
|
||||
$(call assert_eq,nil,$(call _obj_type,$(__nil)),\
|
||||
(type $$(__nil)) is not 'nil')
|
||||
$(call assert_eq,true,$(call _obj_type,$(__true)),\
|
||||
(type $$(__true)) is not 'true')
|
||||
$(call assert_eq,false,$(call _obj_type,$(__false)),\
|
||||
(type $$(__false)) is not 'false')
|
||||
|
||||
|
||||
$(info Testing number? function)
|
||||
|
||||
$(call assert_eq,number,$(call _obj_type,$(call number,1)))
|
||||
$(call assert_eq,number,$(call _obj_type,$(call number,10)))
|
||||
$(call assert_eq,number,$(call _obj_type,$(call number,12345)))
|
||||
|
||||
|
||||
$(info Testing symbols)
|
||||
|
||||
$(call assert_eq,symbol,$(call _obj_type,$(call symbol,abc)),\
|
||||
(type (symbol abc)) is not 'symbol')
|
||||
SYM1 := $(call symbol,a sym value)
|
||||
$(call assert_eq,a sym value,$($(SYM1)_value))
|
||||
$(call assert_eq,$(__true),$(call symbol?,$(SYM1)))
|
||||
|
||||
|
||||
$(info Testing strings)
|
||||
|
||||
$(call assert_eq,string,$(call _obj_type,$(call string,abc)),\
|
||||
(type (string abc)) is not string)
|
||||
|
||||
STR1 := $(call string,a string value)
|
||||
$(call assert_eq,a string value,$(call str_decode,$($(STR1)_value)))
|
||||
$(call assert_eq,$(__true),$(call string?,$(STR1)))
|
||||
$(call assert_eq,14,$(call _count,$(STR1)))
|
||||
|
||||
STR2 := $(call string,a string (with parens))
|
||||
$(call assert_eq,a string (with parens),$(call str_decode,$($(STR2)_value)))
|
||||
$(call assert_eq,$(__true),$(call string?,$(STR2)))
|
||||
$(call assert_eq,22,$(call _count,$(STR2)))
|
||||
|
||||
$(info Testing strings (subs))
|
||||
$(call assert_eq,a string (with parens),$(call str_decode,$($(call subs,$(STR2),$(call number,2))_value)))
|
||||
$(call assert_eq,a string,$(call str_decode,$($(call subs,$(STR2),$(call number,0),$(call number,8))_value)))
|
||||
|
||||
$(info Testing strings (str))
|
||||
$(call assert_eq,a string value - a string (with parens),$(call str_decode,$($(call str,$(STR1) $(call string, - ) $(STR2))_value)))
|
||||
|
||||
|
||||
$(info Testing function objects)
|
||||
|
||||
$(call assert_eq,function,$(call _obj_type,$(call _function,abc)),\
|
||||
(type (function abc)) is not 'function')
|
||||
FN1 := $(call _function,arg1:'$$(word 1,$$(1))' arg2:'$$(word 2,$$(1))')
|
||||
$(call assert_eq,$(__true),$(call function?,$(FN1)))
|
||||
$(call assert_eq,arg1:'A' arg2:'B',$(call apply,$(FN1),$(call list,A B)))
|
||||
|
||||
|
||||
$(info Testing lists)
|
||||
|
||||
$(call assert_eq,list,$(call _obj_type,$(call list)),\
|
||||
(type (list)) is not 'list')
|
||||
|
||||
$(info Testing lists (cons))
|
||||
L1 := $(call cons,P $(call list))
|
||||
L2 := $(call cons,Q $(L1))
|
||||
$(call assert_eq,$(__true),$(call list?,$(L1)))
|
||||
$(call assert_eq,$(__true),$(call list?,$(L2)))
|
||||
$(call assert_eq,P,$(call sfirst,$(L1)))
|
||||
$(call assert_eq,2,$(call _count,$(L2)))
|
||||
$(call assert_eq,Q,$(call sfirst,$(L2)))
|
||||
$(call assert_eq,P,$(call _nth,$(L2),1))
|
||||
$(call assert_eq,$(__true),$(call equal?,$(L1) $(call srest,$(L2))))
|
||||
|
||||
$(info Testing lists (concat))
|
||||
L1_2 := $(call concat,$(L1) $(L2))
|
||||
$(call assert_eq,3,$(call _count,$(L1_2)))
|
||||
$(call assert_eq,P,$(call sfirst,$(L1_2)))
|
||||
$(call assert_eq,Q,$(call _nth,$(L1_2),1))
|
||||
$(call assert_eq,P,$(call _nth,$(L1_2),2))
|
||||
$(call assert_eq,$(__true),$(call equal?,$(L2) $(call srest,$(L1_2))))
|
||||
|
||||
$(info Testing lists (conj))
|
||||
L3 := $(call _conj!,$(call list),A B)
|
||||
L4 := $(call _conj!,$(call list),X $(L3))
|
||||
$(call assert_eq,$(__true),$(call list?,$(L3)),\
|
||||
(list? $$(L3)))
|
||||
$(call assert_eq,$(__true),$(call list?,$(L4)),\
|
||||
(list? $$(L3)))
|
||||
$(call assert_eq,A,$(call sfirst,$(L3)),\
|
||||
(sfirst $$(L3)) is not 'A')
|
||||
$(call assert_eq,X,$(call sfirst,$(L4)),\
|
||||
(sfirst $$(L4)) is not 'X')
|
||||
$(call assert_eq,$(__true),$(call list?,$(call _nth,$(L4),1)),\
|
||||
(_nth $$(L4),1) is not a list)
|
||||
$(call assert_eq,A,$(call sfirst,$(call _nth,$(L4),1)),\
|
||||
(first (_nth $$(L4),1)) is not 'A')
|
||||
|
||||
|
||||
$(info Testing hash_maps)
|
||||
|
||||
X := $(call _hash_map)
|
||||
$(call assert_eq,$(__true),$(call hash_map?,$(X)),\
|
||||
(hash_map? $$(X)))
|
||||
$(call assert_eq,$(__false),$(call vector?,$(X)),\
|
||||
(vector? $$(X)))
|
||||
|
||||
mykey := $(call _string,a)
|
||||
$(call assert_not,$(call _get,$(X),a),\
|
||||
(get $$(X),a))
|
||||
$(call assert_eq,$(__false),$(call contains?,$(X),$(mykey)),\
|
||||
(contains? $$(X),a))
|
||||
$(call do,$(call _assoc!,$(X),a,value of X a))
|
||||
$(call assert_eq,value of X a,$(call _get,$(X),a),\
|
||||
(get $$(X),a) is not 'value of Xa')
|
||||
$(call assert_eq,$(__true),$(call contains?,$(X) $(mykey)),\
|
||||
(contains? $$(X),a))
|
||||
|
||||
Y := $(call _hash_map)
|
||||
$(call assert_eq,0,$(call _count,$(Y)),\
|
||||
(_count $$(Y)))
|
||||
$(call do,$(call _assoc!,$(Y),a,value of Y a))
|
||||
$(call assert_eq,1,$(call _count,$(Y)),\
|
||||
(_count $$(Y)))
|
||||
$(call do,$(call _assoc!,$(Y),b,value of Y b))
|
||||
$(call assert_eq,2,$(call _count,$(Y)),\
|
||||
(_count $$(Y)))
|
||||
$(call assert_eq,value of Y a,$(call _get,$(Y),a),\
|
||||
(get $$(Y),a) is not 'value of Y a')
|
||||
$(call assert_eq,value of Y b,$(call _get,$(Y),b),\
|
||||
(get $$(Y),b) is not 'value of Y b')
|
||||
$(call assert_eq,value of Y a value of Y b,$(call raw_flat,$(Y),b),\
|
||||
(raw_flat $(Y)) is not 'value of Y a value of Y b')
|
||||
|
||||
$(call do,$(call _assoc!,$(X),b,$(Y)))
|
||||
$(call assert_eq,2,$(call _count,$(Y),a),\
|
||||
(_count $$(Y)) should still be 2)
|
||||
|
||||
$(call assert_eq,$(__true),$(call hash_map?,$(call _get,$(X),b)),\
|
||||
(hash_map? (get $$(X),b)))
|
||||
|
||||
$(call assert_eq,$(call _get,$(call _get,$(X),b),a),value of Y a,\
|
||||
(get (get $(X),b),a) is not 'value of Y a')
|
||||
$(call assert_eq,$(call _get,$(call _get,$(X),b),b),value of Y b,\
|
||||
(get (get $(X),b),b) is not 'value of Y b')
|
||||
|
||||
$(call do,$(call _dissoc!,$(Y),a))
|
||||
$(call assert_eq,1,$(call _count,$(Y)),\
|
||||
(_count $$(Y)) should now be 1)
|
||||
$(call assert_not,$(call _get,$(Y),a),\
|
||||
(get $$(Y),a))
|
||||
$(call do,$(call _dissoc!,$(Y),b))
|
||||
$(call assert_eq,0,$(call _count,$(Y)),\
|
||||
(_count $$(Y)) should now be 0)
|
||||
$(call assert_not,$(call _get,$(Y),b),\
|
||||
(get $$(Y),b))
|
||||
|
||||
|
||||
$(info Testing vectors)
|
||||
|
||||
V1 := $(call _conj!,$(call vector),first.vector.value second.vector.value third.vector.value)
|
||||
$(call assert_eq,$(__true),$(call vector?,$(V1)),\
|
||||
(vector? $$(V1)))
|
||||
$(call assert_eq,first.vector.value,$(call _nth,$(V1),0))
|
||||
$(call assert_eq,second.vector.value,$(call _nth,$(V1),1))
|
||||
$(call assert_eq,third.vector.value,$(call _nth,$(V1),2))
|
||||
$(call assert_eq,third.vector.value,$(call slast,$(V1)))
|
||||
$(call assert_eq,3,$(call _count,$(V1)))
|
||||
|
||||
V2 := $(call _conj!,$(call vector),A B C)
|
||||
$(call assert_eq,3,$(call _count,$(V2)),\
|
||||
(_count $$(V2)) is not 3)
|
||||
$(call assert_eq,A B C,$($(V2)_value))
|
||||
$(call assert_eq,A,$(call sfirst,$(V2)),\
|
||||
(first $$(V2)) is not 'A')
|
||||
$(call assert_eq,$(__true),$(call list?,$(call srest,$(V2))),\
|
||||
(rest $$(V2)) is not a vector)
|
||||
$(call assert_eq,B C,$($(call srest,$(V2))_value))
|
||||
$(call assert_eq,B,$(call sfirst,$(call srest,$(V2))),\
|
||||
(first (rest $$(V2))) is not 'B')
|
||||
$(call assert_eq,C,$(call sfirst,$(call srest,$(call srest,$(V2)))),\
|
||||
(first (rest (rest $$(V2)))) is not 'C')
|
||||
$(call assert_eq,C,$(call _nth,$(V2),2),\
|
||||
(_nth $$(V2),2) is not 'C')
|
||||
|
||||
V2_1 := $(call _conj!,$(V2),$(V1))
|
||||
$(call assert_eq,4,$(call _count,$(V2_1)),\
|
||||
(_count $$(V2_1)) is not 4)
|
||||
$(call assert_eq,C,$(call _nth,$(V2_1),2),\
|
||||
(_nth $$(V2_1),2) is no longer 'C')
|
||||
$(call assert_eq,$(__true),$(call vector?,$(call _nth,$(V2_1),3)),\
|
||||
(_nth $$(V2_1),3) is not a vector)
|
||||
$(call assert_eq,second.vector.value,$(call _nth,$(call _nth,$(V2_1),3),1),\
|
||||
(_nth (_nth $$(V2_1),3),1) is not 'second.vector.value')
|
||||
|
||||
$(info Testing vectors (rest))
|
||||
|
||||
V3 := $(call srest,$(V2_1))
|
||||
$(call assert_eq,3,$(call _count,$(V3)),\
|
||||
(_count $$(V3)) is not 3)
|
||||
$(call assert_eq,B,$(call sfirst,$(V3)),\
|
||||
(first $$(V3)) is not 'B')
|
||||
$(call assert_eq,$(__true),$(call vector?,$(call _nth,$(V3),2)),\
|
||||
(_nth $$(V3),2) is not a vector)
|
||||
$(call assert_eq,second.vector.value,$(call _nth,$(call _nth,$(V3),2),1),\
|
||||
(_nth (_nth $$(V3),2),1) is not 'second.vector.value')
|
||||
|
||||
$(info Testing vectors (contains?))
|
||||
|
||||
$(call assert_eq,$(__true),$(call _contains?,$(V2_1),0),\
|
||||
(contains? $$(V2_1),0))
|
||||
$(call assert_eq,,$(call _contains?,$(V2_1),7),\
|
||||
(contains? $$(V2_1),7))
|
||||
|
||||
|
||||
$(info Testing _apply function)
|
||||
|
||||
label_args = $(word 1,$(1))$(word 2,$(1))$(word 3,$(1))$(word 4,$(1))
|
||||
$(call assert_eq,,$(call _apply,label_args,$(call list)))
|
||||
$(call assert_eq,A,$(call _apply,label_args,$(call list,A)))
|
||||
$(call assert_eq,AB,$(call _apply,label_args,$(call list,A B)))
|
||||
$(call assert_eq,ABCD,$(call _apply,label_args,$(call list,A B C D)))
|
||||
|
||||
|
||||
$(info Testing smap function)
|
||||
|
||||
L5 := $(call _conj!,$(call list),$(call number,1) $(call number,2) $(call number,3))
|
||||
inc = $(call number_plus,$(call number,1) $(1))
|
||||
$(call assert_eq,(2 3 4),$(call _pr_str,$(call _smap,inc,$(L5))))
|
||||
inc_func := $(call _function,$$(call number_plus,$$(call number,1) $$(1)))
|
||||
$(call assert_eq,(2 3 4),$(call _pr_str,$(call smap,$(inc_func) $(L5))))
|
||||
|
||||
|
||||
$(info Testing equal? function)
|
||||
$(call assert_eq,$(__true),$(call equal?,2 2))
|
||||
$(call assert_eq,$(__false),$(call equal?,2 3))
|
||||
$(call assert_eq,$(__false),$(call equal?,2 3))
|
||||
$(call assert_eq,$(__true),$(call equal?,abc abc))
|
||||
$(call assert_eq,$(__false),$(call equal?,abc abz))
|
||||
$(call assert_eq,$(__false),$(call equal?,zbc abc))
|
||||
$(call assert_eq,$(__true),$(call equal?,$(call string,abc) $(call string,abc)))
|
||||
$(call assert_eq,$(__false),$(call equal?,$(call string,abc) $(call string,abz)))
|
||||
$(call assert_eq,$(__false),$(call equal?,$(call string,zbc) $(call string,abc)))
|
||||
$(call assert_eq,$(__true),$(call equal?,$(call symbol,abc) $(call symbol,abc)))
|
||||
$(call assert_eq,$(__false),$(call equal?,$(call symbol,abc) $(call symbol,abz)))
|
||||
$(call assert_eq,$(__false),$(call equal?,$(call symbol,zbc) $(call symbol,abc)))
|
||||
L6 := $(call _conj!,$(call list),1 2 3)
|
||||
L7 := $(call _conj!,$(call list),1 2 3)
|
||||
L8 := $(call _conj!,$(call list),1 2 Z)
|
||||
L9 := $(call _conj!,$(call list),Z 2 3)
|
||||
L10 := $(call _conj!,$(call list),1 2)
|
||||
$(call assert_eq,$(__true),$(call equal?,$(L6) $(L7)))
|
||||
$(call assert_eq,$(__false),$(call equal?,$(L6) $(L8)))
|
||||
$(call assert_eq,$(__false),$(call equal?,$(L6) $(L9)))
|
||||
$(call assert_eq,$(__false),$(call equal?,$(L6) $(L10)))
|
||||
$(call assert_eq,$(__false),$(call equal?,$(L10) $(L6)))
|
||||
|
||||
|
||||
$(info Testing empty? function)
|
||||
$(call assert_eq,$(__true),$(call empty?,$(call list)))
|
||||
$(call assert_eq,$(__false),$(call empty?,$(call list,1)))
|
||||
|
||||
|
||||
$(info Testing ENV (1 level))
|
||||
env1 := $(call ENV)
|
||||
$(call assert_eq,,$(call ENV_GET,$(env1),a))
|
||||
$(call assert_eq,$(env1),$(call ENV_SET,$(env1),a,val_a))
|
||||
$(call assert_eq,$(env1),$(call ENV_SET,$(env1),b,val_b))
|
||||
$(call assert_eq,$(env1),$(call ENV_SET,$(env1),=,val_eq))
|
||||
$(call assert_eq,val_a,$(call ENV_GET,$(env1),a))
|
||||
$(call assert_eq,val_b,$(call ENV_GET,$(env1),b))
|
||||
$(call assert_eq,val_eq,$(call ENV_GET,$(env1),=))
|
||||
$(call assert_eq,hash_map,$(call _obj_type,$(call ENV_FIND,$(env1),a)))
|
||||
$(call assert_eq,val_a,$(call _get,$(call ENV_FIND,$(env1),a),a))
|
||||
|
||||
$(info Testing ENV (2 levels))
|
||||
env2 := $(call ENV,$(env1))
|
||||
$(call assert_eq,$(env2),$(call ENV_SET,$(env2),b,val_b2))
|
||||
$(call assert_eq,$(env2),$(call ENV_SET,$(env2),c,val_c))
|
||||
$(call assert_eq,$(env1),$(call ENV_FIND,$(env2),a))
|
||||
$(call assert_eq,$(env2),$(call ENV_FIND,$(env2),b))
|
||||
$(call assert_eq,$(env2),$(call ENV_FIND,$(env2),c))
|
||||
$(call assert_eq,val_a,$(call ENV_GET,$(env2),a))
|
||||
$(call assert_eq,val_b2,$(call ENV_GET,$(env2),b))
|
||||
$(call assert_eq,val_c,$(call ENV_GET,$(env2),c))
|
||||
|
||||
|
||||
.PHONY: all
|
||||
all:
|
||||
@echo "All tests completed"
|
24
runtest.py
24
runtest.py
@ -18,6 +18,8 @@ parser.add_argument('--start-timeout', default=10, type=int,
|
||||
help="default timeout for initial prompt")
|
||||
parser.add_argument('--test-timeout', default=20, type=int,
|
||||
help="default timeout for each individual test action")
|
||||
parser.add_argument('--pre-eval', default=None, type=str,
|
||||
help="Mal code to evaluate prior to running the test")
|
||||
parser.add_argument('--redirect', action='store_true',
|
||||
help="Run implementation in bash and redirect output to /dev/null")
|
||||
|
||||
@ -77,14 +79,24 @@ def read_test(data):
|
||||
|
||||
return form, output, ret, test_idx
|
||||
|
||||
def assert_prompt(timeout):
|
||||
# Wait for the initial prompt
|
||||
idx = p.expect(['user> ', 'mal-user> ', EOF, TIMEOUT],
|
||||
timeout=timeout)
|
||||
if idx not in [0,1]:
|
||||
print "Did not get 'user> ' or 'mal-user> ' prompt"
|
||||
print " Got : %s" % repr(p.before)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
# Wait for the initial prompt
|
||||
idx = p.expect(['user> ', 'mal-user> ', EOF, TIMEOUT],
|
||||
timeout=args.start_timeout)
|
||||
if idx not in [0,1]:
|
||||
print "Never got 'user> ' prompt"
|
||||
print " Got : %s" % repr(p.before)
|
||||
sys.exit(1)
|
||||
assert_prompt(args.start_timeout)
|
||||
|
||||
# Send the pre-eval code if any
|
||||
if args.pre_eval:
|
||||
sys.stdout.write("RUNNING pre-eval: %s" % args.pre_eval)
|
||||
p.sendline(args.pre_eval)
|
||||
assert_prompt(args.test_timeout)
|
||||
|
||||
fail_cnt = 0
|
||||
|
||||
|
27
tests/step5_tco.mal
Normal file
27
tests/step5_tco.mal
Normal file
@ -0,0 +1,27 @@
|
||||
;; Test recursive non-tail call function
|
||||
|
||||
(def! sum-to (fn* (n) (if (= n 0) 0 (+ n (sum-to (- n 1))))))
|
||||
|
||||
(sum-to 10)
|
||||
;=>55
|
||||
|
||||
;;; no try* yet, so test completion of side-effects
|
||||
(def! res1 nil)
|
||||
;=>nil
|
||||
(def! res1 (sum-to 10000)))
|
||||
res1
|
||||
;=>nil
|
||||
|
||||
;; Testing recursive tail-call function
|
||||
|
||||
(def! sum2 (fn* (n acc) (if (= n 0) acc (sum2 (- n 1) (+ n acc)))))
|
||||
|
||||
(sum2 10 0)
|
||||
;=>55
|
||||
|
||||
(def! res2 nil)
|
||||
;=>nil
|
||||
(def! res2 (sum2 10000 0))
|
||||
res2
|
||||
;=>50005000
|
||||
|
Loading…
Reference in New Issue
Block a user