#!/usr/bin/env bash
# annotations.sh — verify that a declared type matches what it annotates.
#
# El had annotations and no checking. The annotation fed dispatch (deciding
# whether `a + b` is arithmetic or concatenation) and was never verified against
# the value, so a mismatch did not fail -- it reinterpreted memory:
#
#   let x: Int = "hello"    a string pointer used as an integer
#   let s: String = 42      address 42 dereferenced as a string
#
# The second is an arbitrary-read primitive if the integer is influenced.
set -uo pipefail
REL="${1:?usage: annotations.sh <relations-file>}"
[ -f "$REL" ] || exit 0
locate() {
    awk -v L="$1" '$2=="spans" && $3<=L && $4>=L {printf "%s:%d", $1, L-$3+1; exit}' "$REL" 2>/dev/null
}
V=0
while read -r caller _ rest; do
    [ "${rest#typemismatch:}" = "$rest" ] && continue
    body="${rest#typemismatch:}"
    declared="${body%%:*}"; body="${body#*:}"
    actual="${body%%:*}";   var="${body#*:}"
    printf "type error in %s: '%s' is declared %s but assigned a %s literal — the annotation drives dispatch, so the value will be reinterpreted rather than rejected\n" \
           "$caller" "$var" "$declared" "$actual"
    V=$((V+1))
done < <(sort -u "$REL")
[ "$V" -eq 0 ] && echo "annotations: clean"
exit "$V"
