Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 43s
lib/guest/reflective/env.sx — added refl-env-find-frame-with (returns
the scope where NAME is bound, or nil). Needed by consumers like
Smalltalk that mutate variables at the source frame rather than
shadowing at the current one. Also added refl-env-find-frame for
the canonical shape.
lib/smalltalk/eval.sx — new st-frame-cfg adapter for the kit.
st-lookup-local now delegates parent-walk to refl-env-find-frame-with
while preserving its Smalltalk-flavoured {:found :value :frame}
return shape (which is used to mutate at the binding's source
frame, not the current one).
lib/smalltalk/test.sh + compare.sh — load lib/guest/reflective/env.sx
before lib/smalltalk/eval.sx.
Three genuinely different wire shapes now share the parent-walk:
- Kernel: {:refl-tag :env :bindings :parent} mutable bindings
- Tcl: {:level :locals :parent} functional update
- Smalltalk: {:self :method-class :locals :parent mutable bindings,
:return-k :active-cell} rich metadata
All three consumers' full test suites unchanged: Smalltalk 847/847,
Kernel 322/322, Tcl 427/427. The cfg adapter pattern (modelled after
lib/guest/match.sx) cleanly handles all three.
148 lines
3.9 KiB
Bash
Executable File
148 lines
3.9 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Fast Smalltalk-on-SX test runner — pipes directly to sx_server.exe.
|
|
# Mirrors lib/haskell/test.sh.
|
|
#
|
|
# Usage:
|
|
# bash lib/smalltalk/test.sh # run all tests
|
|
# bash lib/smalltalk/test.sh -v # verbose
|
|
# bash lib/smalltalk/test.sh tests/tokenize.sx # run one file
|
|
|
|
set -uo pipefail
|
|
cd "$(git rev-parse --show-toplevel)"
|
|
|
|
SX_SERVER="hosts/ocaml/_build/default/bin/sx_server.exe"
|
|
if [ ! -x "$SX_SERVER" ]; then
|
|
MAIN_ROOT=$(git worktree list | head -1 | awk '{print $1}')
|
|
if [ -x "$MAIN_ROOT/$SX_SERVER" ]; then
|
|
SX_SERVER="$MAIN_ROOT/$SX_SERVER"
|
|
else
|
|
echo "ERROR: sx_server.exe not found. Run: cd hosts/ocaml && dune build"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
VERBOSE=""
|
|
FILES=()
|
|
for arg in "$@"; do
|
|
case "$arg" in
|
|
-v|--verbose) VERBOSE=1 ;;
|
|
*) FILES+=("$arg") ;;
|
|
esac
|
|
done
|
|
|
|
if [ ${#FILES[@]} -eq 0 ]; then
|
|
# tokenize.sx must load first — it defines the st-test helpers reused by
|
|
# subsequent test files. Sort enforces this lexicographically.
|
|
mapfile -t FILES < <(find lib/smalltalk/tests -maxdepth 2 -name '*.sx' | sort)
|
|
fi
|
|
|
|
TOTAL_PASS=0
|
|
TOTAL_FAIL=0
|
|
FAILED_FILES=()
|
|
|
|
for FILE in "${FILES[@]}"; do
|
|
[ -f "$FILE" ] || { echo "skip $FILE (not found)"; continue; }
|
|
TMPFILE=$(mktemp)
|
|
if [ "$(basename "$FILE")" = "tokenize.sx" ]; then
|
|
cat > "$TMPFILE" <<EPOCHS
|
|
(epoch 1)
|
|
(load "lib/smalltalk/tokenizer.sx")
|
|
(epoch 2)
|
|
(load "$FILE")
|
|
(epoch 3)
|
|
(eval "(list st-test-pass st-test-fail)")
|
|
EPOCHS
|
|
else
|
|
cat > "$TMPFILE" <<EPOCHS
|
|
(epoch 1)
|
|
(load "lib/smalltalk/tokenizer.sx")
|
|
(epoch 2)
|
|
(load "lib/smalltalk/parser.sx")
|
|
(epoch 3)
|
|
(load "lib/smalltalk/runtime.sx")
|
|
(epoch 4)
|
|
(load "lib/guest/reflective/env.sx")
|
|
(load "lib/smalltalk/eval.sx")
|
|
(epoch 5)
|
|
(load "lib/smalltalk/sunit.sx")
|
|
(epoch 6)
|
|
(load "lib/smalltalk/tests/tokenize.sx")
|
|
(epoch 7)
|
|
(load "$FILE")
|
|
(epoch 8)
|
|
(eval "(list st-test-pass st-test-fail)")
|
|
EPOCHS
|
|
fi
|
|
|
|
OUTPUT=$(timeout 180 "$SX_SERVER" < "$TMPFILE" 2>&1 || true)
|
|
rm -f "$TMPFILE"
|
|
|
|
# Final epoch's value: either (ok N (P F)) on one line or
|
|
# (ok-len N M)\n(P F) where the value is on the following line.
|
|
LINE=$(echo "$OUTPUT" | awk '/^\(ok-len [0-9]+ / {getline; print}' | tail -1)
|
|
if [ -z "$LINE" ]; then
|
|
LINE=$(echo "$OUTPUT" | grep -E '^\(ok [0-9]+ \([0-9]+ [0-9]+\)\)' | tail -1 \
|
|
| sed -E 's/^\(ok [0-9]+ //; s/\)$//')
|
|
fi
|
|
if [ -z "$LINE" ]; then
|
|
echo "X $FILE: could not extract summary"
|
|
echo "$OUTPUT" | tail -30
|
|
TOTAL_FAIL=$((TOTAL_FAIL + 1))
|
|
FAILED_FILES+=("$FILE")
|
|
continue
|
|
fi
|
|
P=$(echo "$LINE" | sed -E 's/^\(([0-9]+) ([0-9]+)\).*/\1/')
|
|
F=$(echo "$LINE" | sed -E 's/^\(([0-9]+) ([0-9]+)\).*/\2/')
|
|
TOTAL_PASS=$((TOTAL_PASS + P))
|
|
TOTAL_FAIL=$((TOTAL_FAIL + F))
|
|
if [ "$F" -gt 0 ]; then
|
|
FAILED_FILES+=("$FILE")
|
|
printf 'X %-40s %d/%d\n' "$FILE" "$P" "$((P+F))"
|
|
TMPFILE2=$(mktemp)
|
|
if [ "$(basename "$FILE")" = "tokenize.sx" ]; then
|
|
cat > "$TMPFILE2" <<EPOCHS
|
|
(epoch 1)
|
|
(load "lib/smalltalk/tokenizer.sx")
|
|
(epoch 2)
|
|
(load "$FILE")
|
|
(epoch 3)
|
|
(eval "(map (fn (f) (get f :name)) st-test-fails)")
|
|
EPOCHS
|
|
else
|
|
cat > "$TMPFILE2" <<EPOCHS
|
|
(epoch 1)
|
|
(load "lib/smalltalk/tokenizer.sx")
|
|
(epoch 2)
|
|
(load "lib/smalltalk/parser.sx")
|
|
(epoch 3)
|
|
(load "lib/smalltalk/runtime.sx")
|
|
(epoch 4)
|
|
(load "lib/guest/reflective/env.sx")
|
|
(load "lib/smalltalk/eval.sx")
|
|
(epoch 5)
|
|
(load "lib/smalltalk/sunit.sx")
|
|
(epoch 6)
|
|
(load "lib/smalltalk/tests/tokenize.sx")
|
|
(epoch 7)
|
|
(load "$FILE")
|
|
(epoch 8)
|
|
(eval "(map (fn (f) (get f :name)) st-test-fails)")
|
|
EPOCHS
|
|
fi
|
|
FAILS=$(timeout 180 "$SX_SERVER" < "$TMPFILE2" 2>&1 | grep -E '^\(ok [0-9]+ \(' | tail -1 || true)
|
|
rm -f "$TMPFILE2"
|
|
echo " $FAILS"
|
|
elif [ "$VERBOSE" = "1" ]; then
|
|
printf 'OK %-40s %d passed\n' "$FILE" "$P"
|
|
fi
|
|
done
|
|
|
|
TOTAL=$((TOTAL_PASS + TOTAL_FAIL))
|
|
if [ $TOTAL_FAIL -eq 0 ]; then
|
|
echo "OK $TOTAL_PASS/$TOTAL smalltalk-on-sx tests passed"
|
|
else
|
|
echo "FAIL $TOTAL_PASS/$TOTAL passed, $TOTAL_FAIL failed in: ${FAILED_FILES[*]}"
|
|
fi
|
|
|
|
[ $TOTAL_FAIL -eq 0 ]
|