| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 |
- #
- # Builds the Test2 compiler (SimpleMod2 scalar subset -> QBE backend)
- # and runs the end-to-end tests.
- # Requires GNU Modula-2 (gm2), the CR binary, qbe and cc.
- #
- # Usage: ./build_qbe.sh (from the Test2 directory)
- #
- # Pipeline per test: SimpleQ tests/<f>.mod -> gen_qbe/<F>.ssa
- # -> qbe -> cc -> ./<F> ; exit code must match the expectation below.
- # Test convention: a global VAR ExitCode : INTEGER selects the process
- # exit code; without it the program returns 0.
- #
- pass=0
- fail=0
- expect_run() {
- # $1 = test file (no dir), $2 = expected exit code
- name="$1"
- want="$2"
- mod="$(basename "$name" .mod)"
- # The backend names the .ssa after the MODULE name; the newest .ssa
- # is the one just produced (tests run sequentially, names unique).
- out=$(./SimpleQ "tests/$name" 2>&1)
- case "$out" in
- *"Parsed correctly"*) ;;
- *) echo "FAIL $name: SimpleQ rejected it: $out"; fail=$((fail+1)); return ;;
- esac
- ssa=$(ls -t gen_qbe/*.ssa 2>/dev/null | head -n 1)
- if [ -z "$ssa" ]; then
- echo "FAIL $name: no .ssa produced"; fail=$((fail+1)); return
- fi
- base=$(basename "$ssa" .ssa)
- if ! qbe -o "gen_qbe/$base.s" "$ssa" 2> "gen_qbe/$base.qbeerr"; then
- echo "FAIL $name: qbe rejected $ssa:"; cat "gen_qbe/$base.qbeerr"; fail=$((fail+1)); return
- fi
- if ! cc "gen_qbe/$base.s" -o "gen_qbe/$base" 2> "gen_qbe/$base.ccerr"; then
- echo "FAIL $name: cc failed:"; cat "gen_qbe/$base.ccerr"; fail=$((fail+1)); return
- fi
- "gen_qbe/$base" > /dev/null 2>&1
- got=$?
- if [ "$got" = "$want" ]; then
- echo "ok $name -> exit $got"
- pass=$((pass+1))
- else
- echo "FAIL $name: exit $got, expected $want"
- fail=$((fail+1))
- fi
- }
- expect_fail() {
- # $1 = test file, $2 = message text that must appear in the .LST
- # (listings show messages, not numeric codes)
- name="$1"
- want="$2"
- out=$(./SimpleQ "tests/$name" 2>&1)
- case "$out" in
- *"Incorrect source"*) ;;
- *) echo "FAIL $name: expected rejection, got: $out"; fail=$((fail+1)); return ;;
- esac
- lst="tests/$(basename "$name" .mod).LST"
- if grep -q "$want" "$lst" 2>/dev/null; then
- echo "ok $name rejected with $want"
- pass=$((pass+1))
- else
- echo "FAIL $name: $want not found in $lst"
- fail=$((fail+1))
- fi
- }
- echo "=== Regenerating SimpleQS / SimpleQP / SimpleQ from SimpleQ.atg ==="
- CRFRAMES="$(pwd)" ../CR -m -C SimpleQ.atg || exit 1
- echo "=== Deleting all o files ==="
- rm -f ./*.o
- echo "=== Compiling the needed modules ==="
- for m in FileIO SymTab QbeGen SimpleQS SimpleQP SimpleQ; do
- gm2 -fiso -c "$m.mod" || exit 1
- done
- echo "=== Phase 1: generating the module list ==="
- gm2 -fiso -fgen-module-list=modules.lst -o /dev/null \
- SimpleQS.o SimpleQP.o FileIO.o SymTab.o QbeGen.o SimpleQ.mod || exit 1
- echo "=== Phase 2: compiling main module and linking using the module list ==="
- gm2 -fiso -fuse-list=modules.lst -o SimpleQ \
- SimpleQS.o SimpleQP.o FileIO.o SymTab.o QbeGen.o SimpleQ.mod || exit 1
- echo "=== SimpleQ built ==="
- mkdir -p gen_qbe tests
- echo "=== Positive tests (compile + qbe + cc + run) ==="
- expect_run q_minimal.mod 0
- expect_run q_arith.mod 7
- expect_run q_const.mod 15
- expect_run q_bool.mod 42
- expect_run q_if.mod 20
- expect_run q_case.mod 103
- expect_run q_while.mod 55
- expect_run q_repeat.mod 55
- expect_run q_loop.mod 7
- expect_run q_for.mod 85
- expect_run q_real.mod 31
- expect_run q_char.mod 97
- expect_run q_enum.mod 1
- expect_run q_full.mod 74
- echo "=== Negative tests (must be rejected) ==="
- expect_fail q_bad_array.mod "qbe backend"
- expect_fail q_bad_with.mod "qbe backend"
- expect_fail q_bad_set.mod "qbe backend"
- expect_fail q_bad_exit.mod "qbe backend"
- expect_fail q_bad_const.mod "qbe backend"
- expect_fail q_bad_asn.mod "incompatible assignment"
- echo "=== $pass passed, $fail failed ==="
- test "$fail" = 0
|