#!/bin/sh # # Step-2 test runner for M2c (scalars + MC64 backend). # Usage: ./run_tests.sh (from the m2c directory, after ./build.sh) # # Positive tests: compile with M2c, run the newest MC4/*.MC4 under mcint, # compare the printed ExitCode value with the expectation. # MGen emits .MC4 in the current directory; the helpers below # collect it into MC4/ and run it from there. # MCINT="${MCINT:-../m-code-64/mcint}" mkdir -p MC4 # MGen emits .MC4 in the current directory; collect_mcd gathers # strays (e.g. from parse-only checks) into MC4/. collect_mcd() { for f in *.MC4; do [ -f "$f" ] && mv -f "$f" MC4/ done } pass=0 fail=0 expect_ok() { # $1 = test file (no dir) — parse only name="$1" out=$(./M2c "tests/$name" 2>&1) case "$out" in *"Parsed correctly"*) echo "ok $name accepted" pass=$((pass+1)) ;; *) echo "FAIL $name: expected accept, got: $out" fail=$((fail+1)) ;; esac collect_mcd } expect_fail() { # $1 = test file, $2 = message text expected in the .LST name="$1" want="$2" out=$(./M2c "tests/$name" 2>&1) case "$out" in *"Incorrect source"*) ;; *) echo "FAIL $name: expected rejection, got: $out" collect_mcd fail=$((fail+1)); return ;; esac collect_mcd 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 } 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" out=$(./M2c "tests/$name" 2>&1) case "$out" in *"Parsed correctly"*) ;; *) echo "FAIL $name: M2c rejected it: $out" fail=$((fail+1)); return ;; esac [ -f "$mod.MC4" ] && mv -f "$mod.MC4" "$mcd" if [ ! -f "$mcd" ]; then echo "FAIL $name: no $mcd produced" fail=$((fail+1)); return fi got=$("$MCINT" "$mcd" 2>&1 | head -n 1 | tr -d '\r') if [ "$got" = "$want" ]; then echo "ok $name -> $got" pass=$((pass+1)) else echo "FAIL $name: printed [$got], expected [$want]" fail=$((fail+1)) fi } expect_run_none() { # $1 = test file — must compile and run with empty output name="$1" mod=$(head -n 1 "tests/$name" | cut -d' ' -f2 | cut -d';' -f1) mcd="MC4/$mod.MC4" rm -f "$mcd" "$mod.MC4" out=$(./M2c "tests/$name" 2>&1) case "$out" in *"Parsed correctly"*) ;; *) echo "FAIL $name: M2c rejected it: $out" fail=$((fail+1)); return ;; esac [ -f "$mod.MC4" ] && mv -f "$mod.MC4" "$mcd" if [ ! -f "$mcd" ]; then echo "FAIL $name: no $mcd produced" fail=$((fail+1)); return fi got=$("$MCINT" "$mcd" 2>&1 | head -n 1) if [ -z "$got" ]; then echo "ok $name runs silent" pass=$((pass+1)) else echo "FAIL $name: unexpected output [$got]" fail=$((fail+1)) fi } expect_run_files() { # $1 = program module (MC4 base), $2 = expected value, rest = sources prog="$1" want="$2" shift 2 mcd="MC4/$prog.MC4" rm -f "$mcd" "$prog.MC4" out=$(./M2c "$@" 2>&1) case "$out" in *"Parsed correctly"*) ;; *) echo "FAIL $prog: M2c rejected it: $out" fail=$((fail+1)); return ;; esac [ -f "$prog.MC4" ] && mv -f "$prog.MC4" "$mcd" if [ ! -f "$mcd" ]; then echo "FAIL $prog: no $mcd produced" fail=$((fail+1)); return fi got=$("$MCINT" "$mcd" 2>&1 | head -n 1 | tr -d '\r') if [ "$got" = "$want" ]; then echo "ok $prog -> $got" pass=$((pass+1)) else echo "FAIL $prog: printed [$got], expected [$want]" fail=$((fail+1)) fi } expect_fail_files() { # $1 = message in the failing file's .LST, rest = sources want="$1" shift out=$(./M2c "$@" 2>&1) case "$out" in *"Incorrect source"*) ;; *) echo "FAIL $*: expected rejection, got: $out" collect_mcd fail=$((fail+1)); return ;; esac 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 echo "ok $last rejected with [$want]" pass=$((pass+1)) else echo "FAIL $last: [$want] not found in $lst" fail=$((fail+1)) fi } echo "=== Phase-0 tests (still green) ===" expect_ok ok_minimal.mod expect_ok ok_nobegin.mod expect_fail bad_mismatch.mod "name mismatch" expect_fail bad_syntax.mod "expected" echo "=== Step-2 run tests (M2c -> mcint) ===" expect_run_none t_min.mod expect_run t_arith.mod 7 expect_run t_const.mod 15 expect_run t_bool.mod 42 expect_run t_if.mod 20 expect_run t_case.mod 103 expect_run t_while.mod 55 expect_run t_repeat.mod 55 expect_run t_loop.mod 7 expect_run t_for.mod 85 expect_run t_real.mod 31 expect_run t_rcmp.mod 31 expect_run t_char.mod 97 expect_run t_enum.mod 1 expect_run t_full.mod 74 expect_run t_set.mod 15 echo "=== Step-2 rejection tests ===" expect_fail t_bad_asn.mod "incompatible assignment" expect_fail t_bad_array.mod "not supported in this phase" expect_fail t_bad_with.mod "not a RECORD type" expect_fail t_bad_exit.mod "not supported in this phase" expect_fail t_bad_const.mod "not supported in this phase" expect_fail t_bad_deref.mod "not a POINTER type" echo "=== Step-3 run tests (procedures) ===" expect_run p_proc.mod 7 expect_run p_params.mod 21 expect_run p_func.mod 42 expect_run p_fact.mod 120 expect_run p_fib.mod 55 expect_run p_varpar.mod 3012 expect_run p_nested.mod 42 expect_run p_forward.mod 1 expect_run p_return.mod 40 expect_run p_local.mod 43 expect_run p_mixed.mod 52 expect_run p_chain.mod 9 expect_run p_empty.mod 3 expect_run p_realfn.mod 5 echo "=== Step-3 rejection tests ===" expect_fail p_bad_call.mod "invalid procedure call" expect_fail p_bad_arity.mod "invalid procedure call" expect_fail p_bad_actual.mod "invalid procedure call" expect_fail p_bad_proper.mod "invalid procedure call" expect_fail p_bad_return1.mod "bad RETURN" expect_fail p_bad_return2.mod "bad RETURN" expect_fail p_bad_return3.mod "bad RETURN" expect_fail p_bad_fwd.mod "forward mismatch" expect_fail p_bad_nobody.mod "forward mismatch" expect_fail p_bad_undecl.mod "undeclared identifier" echo "=== Step-4 run tests (composites) ===" expect_run t_arr.mod 39 expect_run a_mat.mod 134 expect_run a_sieve.mod 129 expect_run a_varpar.mod 150 expect_run a_enum.mod 21 expect_run t_rec.mod 30 expect_run r_nest.mod 135 expect_run t_with.mod 37 expect_run r_varpar.mod 303 expect_run t_ptr.mod 42 expect_run t_ptr0.mod 5 expect_run p_list.mod 21 expect_run t_setop.mod 22 expect_run s_range.mod 21 expect_run t_str.mod 11 echo "=== Step-4 rejection tests ===" expect_fail a_bad_idx.mod "array index must be integer" expect_fail a_bad_arr.mod "not an ARRAY type" expect_fail a_bad_asn.mod "incompatible assignment" expect_fail r_bad_field.mod "unknown field" expect_fail r_bad_rec.mod "not a RECORD type" expect_fail p_bad_new.mod "not a POINTER type" expect_fail s_bad_elem.mod "set operand mismatch" expect_fail a_bad_val.mod "not supported in this phase" expect_fail s_bad_long.mod "incompatible assignment" expect_fail r_bad_asn.mod "incompatible assignment" echo "=== Step-5 run tests (open arrays, copy, strings, I/O) ===" expect_run o_open.mod 150 expect_run c_copy.mod 18 expect_run s_streq.mod 21 expect_run o_val.mod 14 expect_run o_high.mod 14 expect_run c_rec.mod 17 expect_run w_io.mod hi42 expect_run o_open2.mod 286 expect_run c_copy2.mod 9 expect_run s_cmp2.mod 10 expect_run r_copy2.mod 15 expect_run a_subopen.mod 66 expect_run w_str2.mod ok8 expect_run p_newarr.mod 66 expect_run o_char.mod 4 echo "=== Step-5 rejection tests ===" expect_fail o_bad_open.mod "invalid procedure call" expect_fail o_bad_high.mod "not an ARRAY type" expect_fail c_bad_len.mod "incompatible assignment" expect_fail s_bad_cmp.mod "incompatible comparison" expect_fail v_bad_var.mod "invalid procedure call" expect_fail w_bad_int.mod "incompatible assignment" expect_fail w_bad_str.mod "incompatible assignment" expect_fail r_bad_open.mod "not supported in this phase" expect_fail p_bad_dispose.mod "not a POINTER type" expect_fail s_bad_op.mod "arithmetic operand must be numeric" echo "=== Step-6 run tests (local MODULEs) ===" expect_run m_mod.mod 12 expect_run m_multi.mod 7 expect_run m_arr.mod 42 expect_run m_outer.mod 11 expect_run m_const.mod 7 echo "=== Step-6 rejection tests ===" expect_fail m_bad_priv.mod "undeclared identifier" expect_fail m_bad_nest.mod "not supported in this phase" expect_fail m_bad_dup.mod "duplicate identifier" expect_fail m_bad_exp.mod "duplicate identifier" expect_fail m_bad_ghost.mod "undeclared identifier" expect_fail m_bad_end.mod "name mismatch" echo "=== Step-7 run tests (module procedures) ===" expect_run m_param.mod 15 expect_run m_varpar.mod 15 expect_run m_func.mod 45 expect_run m_open.mod 10 expect_run m_bare.mod 2 echo "=== Step-7 rejection tests ===" expect_fail m_bad_arity.mod "invalid procedure call" expect_fail m_bad_mactual.mod "invalid procedure call" expect_fail m_bad_mvar.mod "invalid procedure call" expect_fail m_bad_mfunc.mod "invalid procedure call" expect_fail m_bad_nope.mod "undeclared identifier" echo "=== Step-8 run tests (VAR tails) ===" expect_run v_idx.mod 35 expect_run v_deref.mod 105 expect_run v_field.mod 1031 expect_run v_rec.mod 16 expect_run v_row.mod 21 echo "=== Step-8 rejection tests ===" expect_fail v_bad_byte.mod "invalid procedure call" expect_fail v_bad_with.mod "invalid procedure call" echo "=== Step-9 run tests (type exports + tailed copy) ===" expect_run t_mint.mod 5 expect_run t_mrec.mod 30 expect_run t_marr.mod 18 expect_run t_mptr.mod 7 expect_run t_menum.mod 11 expect_run c_fcopy.mod 5 expect_run c_row.mod 15 echo "=== Step-9 rejection tests ===" expect_fail t_bad_mtype.mod "not a type name" expect_fail t_bad_mghost.mod "undeclared identifier" expect_fail t_bad_mmod.mod "not supported in this phase" echo "=== Step-10 run tests (module BEGIN bodies) ===" expect_run b_init.mod 42 expect_run b_order.mod 111 expect_run b_call.mod 15 expect_run b_mix.mod 110 echo "=== Step-10 rejection tests ===" expect_fail b_bad_ret.mod "bad RETURN" expect_fail b_bad_nest.mod "not supported in this phase" expect_fail b_bad_dup.mod "duplicate identifier" echo "=== Step-11 run tests (DEFINITION/IMPLEMENTATION/IMPORT) ===" expect_run_files DBasic 25 tests/d_lib.def tests/d_libimpl.mod tests/d_basic.mod expect_run_files DFrom 12 tests/d_lib2.def tests/d_lib2impl.mod tests/d_from.mod expect_run_files DMulti 82 tests/a_lib.def tests/a_libimpl.mod tests/b_lib.def tests/b_libimpl.mod tests/d_multi.mod expect_run_files DInit 510 tests/l1.def tests/l1impl.mod tests/l2.def tests/l2impl.mod tests/d_init.mod expect_run_files DFunc 55 tests/f_lib.def tests/f_libimpl.mod tests/d_func.mod expect_run_files DType 1122 tests/t_lib.def tests/t_libimpl.mod tests/d_type.mod expect_run_files DCase 25 tests/e_lib.def tests/e_libimpl.mod tests/d_case.mod echo "=== Step-11 rejection tests ===" expect_fail_files "undeclared identifier" tests/d_bad_nodef.mod expect_fail_files "procedure forward mismatch" tests/d_sglib.def tests/d_bad_sig.mod expect_fail_files "procedure forward mismatch" tests/d_nolib.def tests/d_bad_nobody.mod expect_fail_files "undeclared identifier" tests/d_bad_imp.mod expect_fail_files "undeclared identifier" tests/d_lib.def tests/d_libimpl.mod tests/d_bad_exp.mod expect_fail_files "duplicate identifier" tests/d_duplib.def tests/d_bad_dup.mod echo "=== $pass passed, $fail failed ===" test "$fail" = 0