Chris@70: #!/bin/bash Chris@70: Chris@70: # Disable shellcheck warnings for useless-use-of-cat. UUOC is good Chris@70: # practice, not bad: clearer, safer, less error-prone. Chris@70: # shellcheck disable=SC2002 Chris@70: Chris@70: sml="$VEXT_SML" Chris@70: Chris@70: set -eu Chris@70: Chris@70: mydir=$(dirname "$0") Chris@70: program="$mydir/vext.sml" Chris@70: Chris@70: hasher= Chris@70: local_install= Chris@70: if [ -w "$mydir" ]; then Chris@70: if echo | sha256sum >/dev/null 2>&1 ; then Chris@70: hasher=sha256sum Chris@70: local_install=true Chris@70: elif echo | shasum >/dev/null 2>&1 ; then Chris@70: hasher=shasum Chris@70: local_install=true Chris@70: else Chris@70: echo "WARNING: sha256sum or shasum program not found" 1>&2 Chris@70: fi Chris@70: fi Chris@70: Chris@70: if [ -n "$local_install" ]; then Chris@70: hash=$(echo "$sml" | cat "$program" - | $hasher | cut -c1-16) Chris@70: gen_sml=$mydir/.vext-$hash.sml Chris@70: gen_out=$mydir/.vext-$hash.bin Chris@70: trap 'rm -f $gen_sml' 0 Chris@70: else Chris@70: gen_sml=$(mktemp /tmp/vext-XXXXXXXX.sml) Chris@70: gen_out=$(mktemp /tmp/vext-XXXXXXXX.bin) Chris@70: trap 'rm -f $gen_sml $gen_out' 0 Chris@70: fi Chris@70: Chris@70: if [ -x "$gen_out" ]; then Chris@70: exec "$gen_out" "$@" Chris@70: fi Chris@70: Chris@70: # We need one of Poly/ML, SML/NJ, or MLton. Since we're running a Chris@70: # single-file SML program as if it were a script, our order of Chris@70: # preference is based on startup speed, except in the local_install Chris@70: # case where we retain a persistent binary. Chris@70: Chris@70: if [ -z "$sml" ]; then Chris@70: if [ -n "$local_install" ] && mlton 2>&1 | grep -q 'MLton'; then Chris@70: sml="mlton" Chris@70: elif sml -h 2>&1 | grep -q 'Standard ML of New Jersey'; then Chris@70: sml="smlnj" Chris@70: # We would prefer Poly/ML to SML/NJ, except that Poly v5.7 has a Chris@70: # nasty bug that occasionally causes it to deadlock on startup. Chris@70: # That appears to be fixed in their repo, so we could promote it Chris@70: # up the order again at some point in future Chris@70: elif echo | poly -v 2>/dev/null | grep -q 'Poly/ML'; then Chris@70: sml="poly" Chris@70: elif mlton 2>&1 | grep -q 'MLton'; then Chris@70: sml="mlton" Chris@70: else cat 1>&2 <&2 </dev/null 2>&1 ; then Chris@70: if [ ! -x "$gen_out" ]; then Chris@70: polyc -o "$gen_out" "$program" Chris@70: fi Chris@70: "$gen_out" "$@" Chris@70: else Chris@70: echo 'use "'"$program"'"; vext ['"$arglist"'];' | Chris@70: poly -q --error-exit Chris@70: fi ;; Chris@70: mlton) Chris@70: if [ ! -x "$gen_out" ]; then Chris@70: echo "[Precompiling Vext binary...]" 1>&2 Chris@70: echo "val _ = main ()" | cat "$program" - > "$gen_sml" Chris@70: mlton -output "$gen_out" "$gen_sml" Chris@70: fi Chris@70: "$gen_out" "$@" ;; Chris@70: smlnj) Chris@70: cat "$program" | ( Chris@70: cat < (), flush = fn () => () }; Chris@70: x Chris@70: end; Chris@70: val smlrun__prev = ref ""; Chris@70: Control.Print.out := { Chris@70: say = fn s => Chris@70: (if String.isSubstring " Error" s Chris@70: then (Control.Print.out := smlrun__cp; Chris@70: (#say smlrun__cp) (!smlrun__prev); Chris@70: (#say smlrun__cp) s) Chris@70: else (smlrun__prev := s; ())), Chris@70: flush = fn s => () Chris@70: }; Chris@70: EOF Chris@70: cat - Chris@70: cat < "$gen_sml" Chris@70: CM_VERBOSE=false sml "$gen_sml" ;; Chris@70: *) Chris@70: echo "ERROR: Unknown SML implementation name: $sml" 1>&2; Chris@70: exit 2 ;; Chris@70: esac Chris@70: