#!/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="$*" }