#!/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 }" [ -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"