Created
August 19, 2022 10:41
-
-
Save alganet/c4647a6de06d5edc5c81803e5c6e0ef5 to your computer and use it in GitHub Desktop.
Portable shell script cargo typing and runtime expression parsing experiment
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
set -euf | |
PATH= | |
IFS= | |
_r= | |
_v=0 # variable counter | |
_f=1 # scopedion namespace | |
_x=0 # parser namespace | |
! command -v emulate >/dev/null 2>&1 || emulate ksh >/dev/null 2>&1 | |
command -v local >/dev/null 2>&1 || alias local=typeset | |
xp () { | |
test -n "${1:-}" || return 1 | |
test "$1" = '[' || set -- [ "$@" ] | |
while test $# -gt 0 | |
do | |
if test "$1" = '[' | |
then _x=$(($_x + 1)) | |
elif test "$1" = ']' | |
then | |
test "$_x" -gt 0 || return 1 | |
eval "eval \"\$_x_$_x\"; _x=$(($_x - 1))" | |
eval "_x_$_x=\"$_r\"" | |
unset "_x_"$((_x + 1)) | |
else | |
case "$1" in | |
'@'*) val "${1#"@"}";; | |
'n'*) num "${1#"n"}";; | |
*) _r="$1";; | |
esac | |
eval "_x_$_x=\"\${_x_$_x:-}$_r \"" | |
fi | |
shift | |
done | |
if test "$_x" = 0 | |
then unset _x_0 | |
elif test "$_x" = 1 && test "$_r" = $((_x_$_x)) | |
then unset _x_1 | |
else return 1 | |
fi | |
} | |
## FLOW CONTROL | |
_shift_xp () { | |
shift $1; | |
xp "$@" | |
} | |
var () { | |
_r= | |
_shift_xp 3 "$@" | |
val_usage "$_r" +1 | |
eval "_f$_f=\"\${_f$_f:- }$1 \"" | |
eval "$1='$_r'" | |
} | |
scoped () { | |
_f="$((_f + 1))" | |
eval "_f$_f=;_f${_f}l=${_v:-0}" | |
} | |
result () { | |
_r=${1:-$_r} | |
_gc_uvars | |
_gc_scope $_r | |
_f="$((_f - 1))" | |
} | |
## GARBAGE COLLECTION | |
_gc_val () { | |
if eval test \"\${_${1}r:-0}\" = 0 | |
then val_invoke "$1" destroy | |
fi | |
} | |
_gc_uvars () { | |
IFS=' ' | |
eval "set -- \$_f$_f" | |
IFS='' | |
while test $# -gt 0 | |
do eval val_usage "\$$1" -1; shift | |
done | |
unset "_f$_f" | |
} | |
_gc_scope () { | |
local _vlow _vhigh | |
eval "_vlow=\${_f${_f}l:-0}; _vhigh=\$((_v - _vlow))" | |
while test $_vhigh -gt $_vlow | |
do | |
test "$_vhigh" = "$1" || _gc_val "$_vhigh" | |
_vhigh=$((_vhigh - 2)) | |
done | |
unset "_f${_f}l" | |
} | |
## TYPES | |
val_invoke () { | |
local method="$2" vid="$1" | |
shift 2 | |
eval "eval \"\\\${_\$(($vid - 1)):-seq}_$method $vid \\\"\\\$@\\\"\"" | |
} | |
val_usage () { | |
eval "_${1}r=\$((\${_${1}r:-} + $2))" | |
} | |
val_destroy () { | |
unset "_${1}" "_${1}r" "_$(($1 - 1))" | |
} | |
val () { | |
_v=$((_v + 1)) | |
eval "_$_v='val'" | |
_v=$((_v + 1)) | |
eval "_$_v='$1'" | |
_r="$_v" | |
} | |
num () { | |
_v=$((_v + 1)) | |
eval "_$_v='num'" | |
_v=$((_v + 1)) | |
eval "_$_v='$1'" | |
_r="$_v" | |
} | |
num_destroy () { | |
val_destroy "$@" | |
} | |
seq () { | |
_v=$((_v + 2)) | |
eval "_$_v=''" | |
_r="$_v" | |
while test $# -gt 0 | |
do seq_push $_v $1; shift | |
done | |
} | |
seq_destroy () { | |
local _name="$1" | |
IFS=' ' | |
eval "set -- \$_$1" | |
IFS='' | |
while test $# -gt 0 | |
do val_usage "$1" -1; shift | |
done | |
val_destroy $_name | |
} | |
seq_push () { | |
val_usage "$2" +1 | |
eval "_$1=\"\${_$1:- }$2 \"" | |
} | |
hello () { | |
scoped | |
local greetings greetings2 | |
var greetings = seq @"Hello " n10 $1 | |
var greetings2 = seq @"Hello " n15 $1 | |
result $greetings | |
return | |
} | |
var zoid = hello @"Alexandre" | |
result $zoid | |
set | |
eval : $_r \$_$_r |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment