#!/bin/sh # Regression for M2comp step 2 (Coco/R + SymTab semantic analysis). # Usage: ./run_tests.sh (from the m2comp directory) pass=0; fail=0 expect_ok() { if ./M2comp "$1" 2>&1 | grep -q "Parsed correctly"; then pass=$((pass+1)); echo "PASS(ok): $1" else fail=$((fail+1)); echo "FAIL(ok, rejected): $1" fi collect_mcd } expect_fail() { if ./M2comp "$1" 2>&1 | grep -q "Incorrect source"; then pass=$((pass+1)); echo "PASS(fail): $1" else fail=$((fail+1)); echo "FAIL(fail, accepted): $1" fi collect_mcd } expect_dump() { if ./M2comp "$1" 2>&1 | grep -q "$2"; then pass=$((pass+1)); echo "PASS(ast): $1 [$2]" else fail=$((fail+1)); echo "FAIL(ast): $1 [$2]" fi collect_mcd } MCINT="${MCINT:-../m-code-64/mcint}" mkdir -p MC4 MCTIMEOUT="${MCTIMEOUT:-10}" # MGen emits .MC4 in the current directory; the run helpers # below collect it into MC4/ and run it from there. collect_mcd() { for f in *.MC4; do [ -f "$f" ] && mv -f "$f" MC4/ done } expect_run() { # $1 = test file, $2 = expected printed ExitCode value name="$1" want="$2" mod=$(head -n 1 "tests/$name" | cut -d' ' -f2 | cut -d';' -f1) mcd="MC4/$mod.MC4" rm -f "$mcd" "$mod.MC4" if ./M2comp "tests/$name" 2>&1 | grep -q "Incorrect source"; then fail=$((fail+1)); echo "FAIL(run): $name rejected"; return fi [ -f "$mod.MC4" ] && mv -f "$mod.MC4" "$mcd" if [ ! -f "$mcd" ]; then fail=$((fail+1)); echo "FAIL(run): $name no $mcd"; return fi timeout "$MCTIMEOUT" "$MCINT" "$mcd" > /tmp/m2comp_out.txt 2>&1; rc=$? if [ "$rc" -ne 0 ]; then fail=$((fail+1)); echo "FAIL(run): $name vm rc=$rc (diverges?)"; return fi got=$(head -n 1 /tmp/m2comp_out.txt | tr -d '\r') if [ "$got" = "$want" ]; then pass=$((pass+1)); echo "PASS(run): $name -> $got" else fail=$((fail+1)); echo "FAIL(run): $name printed [$got], want [$want]" fi } expect_run_none() { # $1 = test file — must compile and run silent (terminating) name="$1" mod=$(head -n 1 "tests/$name" | cut -d' ' -f2 | cut -d';' -f1) mcd="MC4/$mod.MC4" rm -f "$mcd" "$mod.MC4" if ./M2comp "tests/$name" 2>&1 | grep -q "Incorrect source"; then fail=$((fail+1)); echo "FAIL(silent): $name rejected"; return fi [ -f "$mod.MC4" ] && mv -f "$mod.MC4" "$mcd" if [ ! -f "$mcd" ]; then fail=$((fail+1)); echo "FAIL(silent): $name no $mcd"; return fi timeout "$MCTIMEOUT" "$MCINT" "$mcd" > /tmp/m2comp_out.txt 2>&1; rc=$? if [ "$rc" -ne 0 ]; then fail=$((fail+1)); echo "FAIL(silent): $name vm rc=$rc (diverges?)"; return fi got=$(head -n 1 /tmp/m2comp_out.txt) if [ -z "$got" ]; then pass=$((pass+1)); echo "PASS(silent): $name runs silent" else fail=$((fail+1)); echo "FAIL(silent): $name output [$got]" fi } expect_run_files() { # $1 = program module (MC4 base), $2 = expected value, rest = sources # (definitions, then implementations, then the program). prog="$1" want="$2" shift 2 mcd="MC4/$prog.MC4" rm -f "$mcd" "$prog.MC4" if ./M2comp "$@" 2>&1 | grep -q "Incorrect source"; then fail=$((fail+1)); echo "FAIL(run): $prog rejected"; return fi [ -f "$prog.MC4" ] && mv -f "$prog.MC4" "$mcd" collect_mcd if [ ! -f "$mcd" ]; then fail=$((fail+1)); echo "FAIL(run): $prog no $mcd"; return fi timeout "$MCTIMEOUT" "$MCINT" "$mcd" > /tmp/m2comp_out.txt 2>&1; rc=$? if [ "$rc" -ne 0 ]; then fail=$((fail+1)); echo "FAIL(run): $prog vm rc=$rc (diverges?)"; return fi got=$(head -n 1 /tmp/m2comp_out.txt | tr -d '\r') if [ "$got" = "$want" ]; then pass=$((pass+1)); echo "PASS(run): $prog -> $got" else fail=$((fail+1)); echo "FAIL(run): $prog printed [$got], want [$want]" fi } expect_fail_files() { # $1 = message in the failing file's .LST, rest = sources. want="$1" shift if ./M2comp "$@" 2>&1 | grep -q "Incorrect source"; then : else fail=$((fail+1)); echo "FAIL(fail, accepted): $*"; return fi collect_mcd last="" for f in "$@"; do last="$f"; done lst=$(echo "$last" | sed 's/\.[^.]*$/.LST/') if grep -q "$want" "$lst" 2>/dev/null; then pass=$((pass+1)); echo "PASS(fail): $last [$want]" else fail=$((fail+1)); echo "FAIL(fail): [$want] not found in $lst" fi } expect_fail_multi() { # stdout-only rejection (driver stage errors leave no .LST mark). if ./M2comp "$@" 2>&1 | grep -q "Incorrect source"; then pass=$((pass+1)); echo "PASS(fail): $*" else fail=$((fail+1)); echo "FAIL(fail, accepted): $*" fi collect_mcd } expect_ok tests/ok_minimal.mod expect_ok tests/ok_proc.mod expect_ok tests/showcase.mod expect_fail tests/bad_mismatch.mod expect_fail tests/t_dup.mod expect_fail tests/t_undecl.mod expect_fail tests/t_assign.mod expect_fail tests/t_arith.mod expect_fail tests/t_bool.mod expect_fail tests/t_rel.mod expect_fail tests/t_cond.mod expect_fail tests/t_field.mod expect_fail tests/t_index.mod expect_fail tests/t_ptr.mod expect_fail tests/t_for.mod expect_fail tests/t_call.mod expect_fail tests/t_call2.mod expect_fail tests/t_return.mod expect_fail tests/t_exit.mod expect_dump tests/showcase.mod "Module Showcase" expect_dump tests/showcase.mod "Proc Work" expect_dump tests/showcase.mod "CallExpr" expect_dump tests/showcase.mod "Field q" expect_dump tests/showcase.mod "Int 255" expect_dump tests/ok_proc.mod "Proc P" expect_run_none ok_minimal.mod expect_run_none ok_proc.mod expect_run r_arith.mod 8 expect_run r_flow.mod 69 expect_run r_bool.mod 11 expect_run r_real.mod 1111 expect_run r_proc.mod 162 expect_run r_varpar.mod 48 expect_run r_nested.mod 213 expect_run r_array.mod 39 expect_run r_record.mod 15 expect_run r_set.mod 12 expect_run r_string.mod 111 expect_run r_ptr.mod 111 expect_run r_module.mod 83 expect_run r_const.mod 1102 echo "=== Step-5 run tests (DEFINITION/IMPLEMENTATION/IMPORT) ===" expect_run_files DBasic 60 tests/d_lib.def tests/d_libimpl.mod tests/d_basic.mod expect_run_files DFrom 35 tests/d_lib.def tests/d_libimpl.mod tests/d_lib2.def tests/d_lib2impl.mod tests/d_from.mod expect_run_files DMulti 68 tests/d_lib.def tests/d_libimpl.mod tests/d_lib2.def tests/d_lib2impl.mod tests/d_multi.mod expect_run_files DInit 7 tests/d_lib.def tests/d_libimpl.mod tests/d_init.mod expect_run_files DFunc 81 tests/d_lib.def tests/d_libimpl.mod tests/d_func.mod expect_run_files DType 40 tests/d_lib.def tests/d_libimpl.mod tests/d_type.mod echo "=== Step-5 rejection tests ===" expect_fail_files "undeclared identifier" tests/d_bad_nodef.mod expect_fail_files "procedure forward mismatch" tests/d_lib.def tests/d_bad_sig.mod expect_fail_files "procedure forward mismatch" tests/d_lib.def tests/d_bad_nobody.mod expect_fail_files "undeclared identifier" tests/d_lib.def tests/d_bad_noimpl.mod expect_fail_files "duplicate identifier" tests/d_lib.def tests/d_bad_dup.def expect_fail_files "undeclared identifier" tests/d_lib.def tests/d_libimpl.mod tests/d_bad_priv.mod expect_fail_multi tests/d_lib.def tests/d_libimpl.mod tests/d_basic.mod tests/d_basic.mod echo "--- $pass passed, $fail failed ---" [ "$fail" -eq 0 ]