blob: d732e498bc658c50b477f7a36471696ae90fd4e5 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
#!/usr/bin/env bash
set -u
root="$(cd "$(dirname "$0")/.." && pwd)"
cd "$root"
if [ -z "${NO_COLOR:-}" ]; then
bold=$'\033[1m'; dim=$'\033[2m'; red=$'\033[31m'; green=$'\033[32m'; reset=$'\033[0m'
else
bold=; dim=; red=; green=; reset=
fi
hdass="${HDASS:-./bin/debug-linux/hdass}"
if [ ! -x "$hdass" ]; then
echo "${red}error:${reset} '$hdass' not found; build it first with:" >&2
echo " premake5 gmake && make config=debug" >&2
exit 1
fi
for tool in nasm ld; do
if ! command -v "$tool" >/dev/null 2>&1; then
echo "${red}error:${reset} '$tool' not found; run this inside the Docker environment" >&2
exit 1
fi
done
work="$(mktemp -d)"
trap 'rm -rf "$work"' EXIT
pass=0
fail=0
check()
{
local name="$1" desc="$2" source="$3" expected_exit="$4" expected_stdout="$5"
local asm="$work/$name.asm" obj="$work/$name.o" bin="$work/$name" stage=""
if ! "$hdass" "$source" -o "$asm" 2>"$work/err"; then
stage="transpile"
elif ! nasm -f elf64 "$asm" -o "$obj" 2>"$work/err"; then
stage="assemble"
elif ! ld -e main "$obj" -o "$bin" 2>"$work/err"; then
stage="link"
fi
if [ -n "$stage" ]; then
printf ' %s✘%s %-12s %s%s%s\n' "$red" "$reset" "$name" "$dim" "$desc" "$reset"
printf ' %sfailed to %s%s\n' "$red" "$stage" "$reset"
sed 's/^/ /' "$work/err"
fail=$((fail + 1))
return
fi
local actual_stdout actual_exit
actual_stdout="$(timeout 10 "$bin")"
actual_exit=$?
if [ "$actual_exit" != "$expected_exit" ] || [ "$actual_stdout" != "$expected_stdout" ]; then
printf ' %s✘%s %-12s %s%s%s\n' "$red" "$reset" "$name" "$dim" "$desc" "$reset"
if [ "$actual_exit" = 124 ]; then
printf ' %stimed out (likely an infinite loop)%s\n' "$red" "$reset"
fi
printf ' expected: exit %s stdout=%s\n' "$expected_exit" "$(printf '%q' "$expected_stdout")"
printf ' actual: exit %s stdout=%s\n' "$actual_exit" "$(printf '%q' "$actual_stdout")"
fail=$((fail + 1))
return
fi
printf ' %s✔%s %-12s %s%-42s%s %sexit %s%s\n' \
"$green" "$reset" "$name" "$dim" "$desc" "$reset" "$dim" "$expected_exit" "$reset"
pass=$((pass + 1))
}
printf '%s━━ example programs ━━%s\n' "$bold" "$reset"
check hello_world "writes a greeting to stdout" examples/hello_world.hdass 0 "Hello, World!"
check greet "writes a fixed string" examples/greet.hdass 0 "hdass works!"
check exit_code "exits with a status code" examples/exit_code.hdass 42 ""
check arithmetic "integer compound-assignment math" examples/arithmetic.hdass 15 ""
check loop_sum "sums 1..5 with a countdown loop" examples/loop_sum.hdass 15 ""
check branch "selects the larger of two values" examples/branch.hdass 8 ""
check call "passes an argument through a proc" examples/call.hdass 21 ""
check logical "logical register names (r1..r14)" examples/logical.hdass 21 ""
check mul_div "multiply and non-rax division" examples/mul_div.hdass 8 ""
check fibonacci "prints the first ten Fibonacci numbers" examples/fibonacci.hdass 0 "0
1
1
2
3
5
8
13
21
34"
printf '\n'
if [ "$fail" -eq 0 ]; then
printf ' %s✔ all %d examples passed%s\n' "$green" "$pass" "$reset"
else
printf ' %s✘ %d of %d examples failed%s\n' "$red" "$fail" "$((pass + fail))" "$reset"
fi
[ "$fail" -eq 0 ]
|