diff --git a/f.sh b/f.sh deleted file mode 100644 index 6986105..0000000 --- a/f.sh +++ /dev/null @@ -1,118 +0,0 @@ -#!/bin/sh - -alias :=_newword -alias ']=_execbody' -alias xshift='shift 2>/dev/null || printf "Stack underflow\n"' - -_stack="" # top is -_builtin_dictionary="swap dup rot over drop add sub div mod mul put" # + - / * . - -_newword() { - name="$1" - shift - eval "${name}_definition=\"$*\"" -} - -_execword() { - eval "def=\"\$$1_definition\"" - eval "def=\"\$$1_definition\"" - [ "$def" ] || { - printf '%s\n' "Error: no word $1" - return - } - _execbody $def -} - -_execbody() { - for word in "$@"; do - [ "$_debug" ] && { - printf 'word %s\nstack %s\n' "$word" "$_stack" - read - } - case "$_builtin_dictionary" in - *"$word"*) "_$word" $_stack ;; - *) case "$word" in - *[0-9]*) _stack="$word $_stack" ;; - *) _execword "$word" ;; - esac - ;; - esac - done -} - -_swap() { - one="$1" - two="$2" - xshift - _stack="$2 $1 $*" -} - -_dup() { - _stack="$1 $*" -} - -_rot() { - one="$1" - two="$2" - thr="$3" - xshift - xshift - xshift - _stack="$3 $1 $2 $*" -} - -_over() { - _stack="$2 $*" -} - -_drop() { - xshift - _stack="$*" -} - -_add() { - one="$1" - two="$2" - xshift - xshift - _stack="$(( one + two )) $*" -} - -_sub() { - one="$1" - two="$2" - xshift - xshift - _stack="$(( two - one )) $*" -} - -_div() { - one="$1" - two="$2" - xshift - xshift - _stack="$(( two / one )) $*" -} - -_mod() { - one="$1" - two="$2" - xshift - xshift - _stack="$(( two % one )) $*" -} - -_mul() { - one="$1" - two="$2" - xshift - xshift - _stack="$(( one * two )) $*" -} - -_put() { - one="$1" - xshift - printf '%s \n' "$one" - _stack="$*" -} diff --git a/for.sh b/for.sh new file mode 100755 index 0000000..a678edd --- /dev/null +++ b/for.sh @@ -0,0 +1,232 @@ +#!/bin/sh + +# Weird shell stack based forth "lookalike" +# recursion can be done by repeating the +# word. Words cannot have multiple defs +# in a dictionary. +# todo: +# implement conditionals in _execword :^) + +ignore() : +alias :=_newword +alias ']=_execbody' + +_stack="" # top is +_builtin_dictionary="swap dup rot over drop add sub div mod mul put not or and xor eq lt gt ne" # + - / * . + +_newword() { + name="$1" + shift + [ "$_debug" ] && { + printf '_newword %s: %s\n' "$name" "$*" + read + } + eval "${name}_definition=\"$*\"" +} + +_execword() { + [ "$_debug" ] && { + printf '_execword %s\n' "$1" + read + } + eval "def=\"\$$1_definition\"" + [ "$def" ] || { + printf '%s\n' "Error: no word $1" + return + } + _execbody $def +} + +_execbody() { + while [ "$1" ]; do + word="$1" + + [ "$_debug" ] && { + printf 'word %s\nstack %s\n' "$word" "$_stack" + read + } + case "$_builtin_dictionary" in + *"$word"*) "_$word" $_stack ;; + *) case "$word" in + then) ignore ;; + if) + [ "${_stack%% *}" = 0 ] && { + [ "$_debug" ] && { + printf 'failed if, jumping ahead\n' + read + } + _ifcnt=1 + _thencnt=0 + while [ "$_ifcnt" != "$_thencnt" ]; do + [ "$_debug" ] && { + printf '$1 %s\n' "$1" + printf '$* %s\n' "$*" + printf 'ifcnt: %s thencnt: %s\n' "$_ifcnt" "$_thencnt" + read + } + shift + case "$1" in + if) ignore $(( _ifcnt += 1 )) ;; + then) ignore $(( _thencnt += 1 )) ;; + "") printf 'Unmatched if\n'; return ;; + esac + done + } + _drop $_stack + shift + continue + ;; + *[0-9]*) _stack="$word $_stack" ;; + *) _execword "$word" ;; + esac + ;; + esac + + shift + done +} + +_swap() { + one="$1" + two="$2" + shift 2 + _stack="$two $one $*" +} + +_dup() { + _stack="$1 $*" +} + +_rot() { + one="$1" + two="$2" + thr="$3" + shift 3 + _stack="$thr $one $two $*" +} + +_over() { + _stack="$2 $*" +} + +_drop() { + shift + _stack="$*" +} + +_add() { + one="$1" + two="$2" + shift 2 + _stack="$(( one + two )) $*" +} + +_sub() { + one="$1" + two="$2" + shift 2 + _stack="$(( two - one )) $*" +} + +_div() { + one="$1" + two="$2" + shift 2 + _stack="$(( two / one )) $*" +} + +_mod() { + one="$1" + two="$2" + shift 2 + _stack="$(( two % one )) $*" +} + +_mul() { + one="$1" + two="$2" + shift 2 + _stack="$(( one * two )) $*" +} + +_put() { + one="$1" + shift + printf '%s \n' "$one" + _stack="$*" +} + +_not() { + one="$1" + shift + _stack="$(( ~ one )) $*" +} + +_or() { + one="$1" + two="$2" + shift 2 + _stack="$(( one | two )) $*" +} + +_and() { + one="$1" + two="$2" + shift 2 + _stack="$(( one & two )) $*" +} + +_xor() { + one="$1" + two="$2" + shift 2 + _stack="$(( one ^ two )) $*" +} + +_eq() { + one="$1" + two="$2" + shift 2 + if [ "$one" -eq "$two" ]; then + _stack="$(( ~ 0 )) $*" + else + _stack="$(( 0 )) $*" + fi +} + +_lt() { + one="$1" + two="$2" + shift 2 + if [ "$two" -lt "$one" ]; then + _stack="$(( ~ 0 )) $*" + else + _stack="$(( 0 )) $*" + fi +} + +_gt() { + one="$1" + two="$2" + shift 2 + if [ "$two" -gt "$one" ]; then + _stack="$(( ~ 0 )) $*" + else + _stack="$(( 0 )) $*" + fi +} + +_ne() { + one="$1" + two="$2" + shift 2 + if [ "$two" -ne "$one" ]; then + _stack="$(( ~ 0 )) $*" + else + _stack="$(( 0 )) $*" + fi +} + +# definitions in forsh +: true not false ; +: false 0 ; diff --git a/t.sh b/t.sh new file mode 100755 index 0000000..070bd7d --- /dev/null +++ b/t.sh @@ -0,0 +1,8 @@ +#!/bin/sh +. ./for.sh + +# _debug=y + +: pow dup 1 gt if 1 sub over swap pow mul then dup 1 gt not if drop then ; # b e -- x + +] 2 8 pow put