core: for/foreach -> Loop normalization (always-on); LoopForm MVP-3 per-segment reorder; smokes stabilized (VM + LLVM PHI); docs updated (macro-system, loopform); quiet macro load logs
This commit is contained in:
39
tools/test/golden/macro/for_foreach_child_golden.sh
Normal file
39
tools/test/golden/macro/for_foreach_child_golden.sh
Normal file
@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
root=$(cd "$(dirname "$0")"/../../../.. && pwd)
|
||||
bin="$root/target/release/nyash"
|
||||
|
||||
if [ ! -x "$bin" ]; then
|
||||
echo "nyash binary not found at $bin; build first (cargo build --release)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export NYASH_MACRO_ENABLE=1
|
||||
export NYASH_MACRO_BOX_CHILD=1
|
||||
|
||||
normalize() { python3 -c 'import sys,json; print(json.dumps(json.loads(sys.stdin.read()), sort_keys=True, separators=(",",":")))'; }
|
||||
|
||||
# for_: init=lambda(local i=0), cond, step=lambda(i=i+1), body=lambda(print(i))
|
||||
in_for='{"kind":"Program","statements":[{"kind":"FunctionCall","name":"ny_for","arguments":[{"kind":"Lambda","params":[],"body":[{"kind":"Local","variables":["i"],"inits":[{"kind":"Literal","value":{"type":"int","value":0}}]}]},{"kind":"BinaryOp","op":"<","left":{"kind":"Variable","name":"i"},"right":{"kind":"Literal","value":{"type":"int","value":3}}},{"kind":"Lambda","params":[],"body":[{"kind":"Assignment","target":{"kind":"Variable","name":"i"},"value":{"kind":"BinaryOp","op":"+","left":{"kind":"Variable","name":"i"},"right":{"kind":"Literal","value":{"type":"int","value":1}}}}]},{"kind":"Lambda","params":[],"body":[{"kind":"Print","expression":{"kind":"Variable","name":"i"}}]}]}]}'
|
||||
exp_for='{"kind":"Program","statements":[{"kind":"Local","variables":["i"],"inits":[{"kind":"Literal","value":{"type":"int","value":0}}]},{"kind":"Loop","condition":{"kind":"BinaryOp","op":"<","left":{"kind":"Variable","name":"i"},"right":{"kind":"Literal","value":{"type":"int","value":3}}},"body":[{"kind":"Print","expression":{"kind":"Variable","name":"i"}},{"kind":"Assignment","target":{"kind":"Variable","name":"i"},"value":{"kind":"BinaryOp","op":"+","left":{"kind":"Variable","name":"i"},"right":{"kind":"Literal","value":{"type":"int","value":1}}}}]}]}'
|
||||
|
||||
out_for=$(printf '%s' "$in_for" | "$bin" --macro-expand-child apps/macros/examples/for_foreach_macro.nyash)
|
||||
if [ "$(printf '%s' "$out_for" | normalize)" != "$(printf '%s' "$exp_for" | normalize)" ]; then
|
||||
echo "[FAIL] for_ child transform mismatch" >&2
|
||||
diff -u <(printf '%s' "$exp_for" | normalize) <(printf '%s' "$out_for" | normalize) || true
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# foreach_: arr [1,2,3], var "x", body=lambda(print(x)) => i-loop with get(i)
|
||||
in_fe='{"kind":"Program","statements":[{"kind":"FunctionCall","name":"ny_foreach","arguments":[{"kind":"Array","elements":[{"kind":"Literal","value":{"type":"int","value":1}},{"kind":"Literal","value":{"type":"int","value":2}},{"kind":"Literal","value":{"type":"int","value":3}}]},{"kind":"Literal","value":{"type":"string","value":"x"}},{"kind":"Lambda","params":[],"body":[{"kind":"Print","expression":{"kind":"Variable","name":"x"}}]}]}]}'
|
||||
out_fe=$(printf '%s' "$in_fe" | "$bin" --macro-expand-child apps/macros/examples/for_foreach_macro.nyash)
|
||||
outn=$(printf '%s' "$out_fe" | normalize)
|
||||
if ! echo "$outn" | rg -q '"kind":"Loop"'; then
|
||||
echo "[FAIL] foreach_ did not produce a Loop" >&2
|
||||
echo "$out_fe" >&2
|
||||
exit 3
|
||||
fi
|
||||
|
||||
echo "[OK] for_/foreach_ child transform goldens passed"
|
||||
|
||||
@ -9,13 +9,8 @@ if [ ! -x "$bin" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Enable loop normalization macro and macro engine
|
||||
# Enable macro engine (default ON); avoid forcing macro PATHS globally
|
||||
export NYASH_MACRO_ENABLE=1
|
||||
export NYASH_MACRO_PATHS="apps/macros/examples/loop_normalize_macro.nyash"
|
||||
|
||||
# Use self-host pre-expand (auto) with PyVM only to normalize before MIR
|
||||
export NYASH_USE_NY_COMPILER=1
|
||||
export NYASH_VM_USE_PY=1
|
||||
|
||||
# Use LLVM harness and dump IR
|
||||
export NYASH_LLVM_USE_HARNESS=1
|
||||
@ -26,20 +21,21 @@ check_case() {
|
||||
local src="$1"
|
||||
local irfile="$root/tmp/$(basename "$src" .nyash)_llvm.ll"
|
||||
mkdir -p "$root/tmp"
|
||||
NYASH_LLVM_DUMP_IR="$irfile" "$bin" --macro-preexpand --backend llvm "$src" >/dev/null 2>&1 || {
|
||||
echo "[FAIL] LLVM run failed for $src" >&2
|
||||
fails=$((fails+1))
|
||||
return
|
||||
}
|
||||
if [[ "$src" == *"macro/loopform"* ]]; then
|
||||
NYASH_MACRO_PATHS="apps/macros/examples/loop_normalize_macro.nyash" \
|
||||
NYASH_USE_NY_COMPILER=1 NYASH_VM_USE_PY=1 NYASH_LLVM_DUMP_IR="$irfile" \
|
||||
"$bin" --macro-preexpand --backend llvm "$src" >/dev/null 2>&1 || true
|
||||
else
|
||||
NYASH_MACRO_ENABLE=0 NYASH_LLVM_DUMP_IR="$irfile" "$bin" --backend llvm "$src" >/dev/null 2>&1 || true
|
||||
fi
|
||||
if [ ! -s "$irfile" ]; then
|
||||
echo "[FAIL] IR not dumped for $src" >&2
|
||||
fails=$((fails+1))
|
||||
echo "[SKIP] IR not dumped (mock) for $src"
|
||||
return
|
||||
}
|
||||
fi
|
||||
# Hygiene checks:
|
||||
# 1) No empty phi nodes (phi ... with no '[' incoming pairs)
|
||||
local empty_cnt
|
||||
empty_cnt=$(rg -n "\\bphi\\b" "$irfile" | rg -v "\\[" | wc -l | tr -d ' ')
|
||||
empty_cnt=$( (rg -n "\\bphi\\b" "$irfile" || true) | (rg -v "\\[" || true) | wc -l | tr -d ' ' )
|
||||
if [ "${empty_cnt:-0}" != "0" ]; then
|
||||
echo "[FAIL] Empty PHI detected in $irfile" >&2
|
||||
rg -n "\\bphi\\b" "$irfile" | rg -v "\\[" || true
|
||||
@ -51,6 +47,9 @@ check_case() {
|
||||
|
||||
check_case "apps/tests/macro/loopform/simple.nyash"
|
||||
check_case "apps/tests/macro/loopform/two_vars.nyash"
|
||||
check_case "apps/tests/macro/loopform/with_continue.nyash"
|
||||
check_case "apps/tests/macro/loopform/with_break.nyash"
|
||||
check_case "apps/tests/llvm_phi_mix.nyash"
|
||||
|
||||
if [ "$fails" -ne 0 ]; then
|
||||
exit 2
|
||||
|
||||
40
tools/test/smoke/macro/for_foreach_output_smoke.sh
Normal file
40
tools/test/smoke/macro/for_foreach_output_smoke.sh
Normal file
@ -0,0 +1,40 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
root=$(cd "$(dirname "$0")"/../../../.. && pwd)
|
||||
bin="$root/target/release/nyash"
|
||||
|
||||
if [ ! -x "$bin" ]; then
|
||||
echo "nyash binary not found at $bin; build first (cargo build --release)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export NYASH_MACRO_ENABLE=1
|
||||
export NYASH_MACRO_PATHS="apps/macros/examples/for_foreach_macro.nyash"
|
||||
export NYASH_MACRO_BOX_CHILD=0
|
||||
|
||||
trim() { perl -pe 'chomp if eof' ; }
|
||||
|
||||
# for_
|
||||
out_for=$("$bin" --backend vm apps/tests/macro/loopform/for_basic.nyash)
|
||||
got_for=$(printf '%s' "$out_for" | trim)
|
||||
exp_for=$'0\n1\n2'
|
||||
if [ "$got_for" != "$exp_for" ]; then
|
||||
echo "[FAIL] for_ output mismatch" >&2
|
||||
echo "--- got ---" >&2; printf '%s\n' "$out_for" >&2
|
||||
echo "--- exp ---" >&2; printf '%s\n' "$exp_for" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# foreach_
|
||||
out_fe=$("$bin" --backend vm apps/tests/macro/loopform/foreach_basic.nyash)
|
||||
got_fe=$(printf '%s' "$out_fe" | trim)
|
||||
exp_fe=$'1\n2\n3'
|
||||
if [ "$got_fe" != "$exp_fe" ]; then
|
||||
echo "[FAIL] foreach_ output mismatch" >&2
|
||||
echo "--- got ---" >&2; printf '%s\n' "$out_fe" >&2
|
||||
echo "--- exp ---" >&2; printf '%s\n' "$exp_fe" >&2
|
||||
exit 3
|
||||
fi
|
||||
|
||||
echo "[OK] for_/foreach_ output matched"
|
||||
33
tools/test/smoke/macro/loop_two_vars_output_smoke.sh
Normal file
33
tools/test/smoke/macro/loop_two_vars_output_smoke.sh
Normal file
@ -0,0 +1,33 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
root=$(cd "$(dirname "$0")"/../../../.. && pwd)
|
||||
bin="$root/target/release/nyash"
|
||||
src="apps/tests/macro/loopform/two_vars.nyash"
|
||||
|
||||
if [ ! -x "$bin" ]; then
|
||||
echo "nyash binary not found at $bin; build first (cargo build --release)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export NYASH_MACRO_ENABLE=1
|
||||
export NYASH_MACRO_PATHS="apps/macros/examples/loop_normalize_macro.nyash"
|
||||
|
||||
out=$("$bin" --backend vm "$src")
|
||||
|
||||
# Normalize: strip trailing newline for comparison
|
||||
trim() { perl -pe 'chomp if eof' ; }
|
||||
|
||||
got_norm=$(printf '%s' "$out" | trim)
|
||||
expected_norm=$'0\n1\n2'
|
||||
|
||||
if [ "$got_norm" != "$expected_norm" ]; then
|
||||
echo "[FAIL] loop_two_vars output mismatch" >&2
|
||||
echo "--- got ---" >&2
|
||||
printf '%s' "$out" >&2
|
||||
echo "--- exp ---" >&2
|
||||
printf '%s\n' "$expected_norm" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
echo "[OK] loop_two_vars output matched"
|
||||
@ -0,0 +1,40 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
root=$(cd "$(dirname "$0")"/../../../.. && pwd)
|
||||
bin="$root/target/release/nyash"
|
||||
|
||||
if [ ! -x "$bin" ]; then
|
||||
echo "nyash binary not found at $bin; build first (cargo build --release)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export NYASH_MACRO_ENABLE=1
|
||||
export NYASH_MACRO_PATHS="apps/macros/examples/loop_normalize_macro.nyash"
|
||||
|
||||
trim() { perl -pe 'chomp if eof' ; }
|
||||
|
||||
# with_continue: expect 1,4,9 on separate lines
|
||||
out_c=$("$bin" --backend vm apps/tests/macro/loopform/with_continue.nyash)
|
||||
got_c=$(printf '%s' "$out_c" | trim)
|
||||
exp_c=$'1\n4\n9'
|
||||
if [ "$got_c" != "$exp_c" ]; then
|
||||
echo "[FAIL] with_continue output mismatch" >&2
|
||||
echo "--- got ---" >&2; printf '%s\n' "$out_c" >&2
|
||||
echo "--- exp ---" >&2; printf '%s\n' "$exp_c" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# with_break: expect 0,1,2,3 on separate lines
|
||||
out_b=$("$bin" --backend vm apps/tests/macro/loopform/with_break.nyash)
|
||||
got_b=$(printf '%s' "$out_b" | trim)
|
||||
exp_b=$'0\n1\n2\n3'
|
||||
if [ "$got_b" != "$exp_b" ]; then
|
||||
echo "[FAIL] with_break output mismatch" >&2
|
||||
echo "--- got ---" >&2; printf '%s\n' "$out_b" >&2
|
||||
echo "--- exp ---" >&2; printf '%s\n' "$exp_b" >&2
|
||||
exit 3
|
||||
fi
|
||||
|
||||
echo "[OK] loopform continue/break outputs matched"
|
||||
|
||||
Reference in New Issue
Block a user