summaryrefslogtreecommitdiffstats
path: root/eshtrans/eshrt/eshrtbegin.esh
diff options
context:
space:
mode:
Diffstat (limited to 'eshtrans/eshrt/eshrtbegin.esh')
-rw-r--r--eshtrans/eshrt/eshrtbegin.esh250
1 files changed, 250 insertions, 0 deletions
diff --git a/eshtrans/eshrt/eshrtbegin.esh b/eshtrans/eshrt/eshrtbegin.esh
new file mode 100644
index 0000000..9f7e59e
--- /dev/null
+++ b/eshtrans/eshrt/eshrtbegin.esh
@@ -0,0 +1,250 @@
+# Eggshell runtime library
+#
+# Copyright (C) 2016 Patrick "P. J." McDermott
+#
+# This file is part of the Eggshell Compiler.
+#
+# The Eggshell Compiler is free software: you can redistribute it
+# and/or modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation, either version 3 of
+# the License, or (at your option) any later version.
+#
+# The Eggshell Compiler is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with the Eggshell Compiler If not, see
+# <http://www.gnu.org/licenses/>.
+
+use nostack
+
+__ESC="$(printf '\033.')"; __ESC="${__ESC%.}"
+ __RS="$(printf '\036.')"; __RS="${__RS%.}"
+ __US="$(printf '\037.')"; __US="${__US%.}"
+__sp=0
+__fn_name=''
+__fn_tu=''
+__fn_vars=''
+__fn_var_vals=''
+__fn=''
+__prev_tu=''
+__prev_vars=''
+__var=''
+__val=''
+__fn_frame=0
+__fn_begin_hooks=''
+__fn_end_hooks=''
+__init_funcs=''
+
+__sp_inc()
+{
+ __sp=$((${__sp} + 1))
+}
+
+__sp_dec()
+{
+ __sp=$((${__sp} - 1))
+}
+
+__frame_set()
+{
+ eval "__frame_${__sp}_name=\${__fn_name}"
+ eval "__frame_${__sp}_tu=\${__fn_tu}"
+ eval "__frame_${__sp}_vars=\${__fn_vars}"
+ eval "__frame_${__sp}_var_vals=\${__fn_var_vals}"
+}
+
+__frame_get()
+{
+ eval "__fn_name=\${__frame_${__sp}_name}"
+ eval "__fn_tu=\${__frame_${__sp}_tu}"
+ eval "__fn_vars=\${__frame_${__sp}_vars}"
+ eval "__fn_var_vals=\${__frame_${__sp}_var_vals}"
+}
+
+__fn_ctxsw()
+{
+ unset IFS
+ case "${__prev_tu}" in
+ ${__fn_tu});;
+ ?*)
+ # Unset static variables and functions from previous TU.
+ eval "__val=\${__${__prev_tu}_static_vars}"
+ case "${__val}" in ?*)
+ eval "unset \${__${__prev_tu}_static_vars}"
+ ;; esac
+ eval "__val=\${__${__prev_tu}_static_fns}"
+ for __fn in ${__val}; do
+ unset -f "${__fn%:*}"
+ done
+ ;; esac
+ case "${__fn_tu}" in
+ ${__prev_tu});;
+ ?*)
+ # Set static variables and function for the current TU.
+ eval "__val=\${__${__fn_tu}_static_var_vals}"
+ eval "${__val}"
+ eval "__val=\${__${__fn_tu}_static_fns}"
+ for __fn in ${__val}; do
+ eval "${__fn%:*}() { ${__fn#*:}; }"
+ done
+ ;; esac
+ case "${__prev_vars}" in ?*)
+ unset ${__prev_vars}
+ ;; esac
+ eval "${__fn_var_vals}"
+}
+
+__fn_update_vars()
+{
+ unset IFS
+ for __var in ${__fn_vars}; do
+ __val="$(eval "printf '%s' \"\${${__var}}\"" | \
+ sed "s|'|'\\\\''|g;")"
+ __fn_var_vals="${__fn_var_vals} ${__var}='${__val}'"
+ done
+}
+
+__fn_start()
+{
+ # Hooks.
+ unset IFS
+ for __fn in ${__fn_begin_hooks}; do
+ ${__fn} ${2}
+ done
+
+ # Old state.
+ __prev_tu="${__fn_tu}"
+ __prev_vars="${__fn_vars}"
+
+ # Update local vars in stack.
+ __fn_update_vars
+ __frame_set
+
+ # Set stack pointer.
+ __sp_inc
+
+ # New state.
+ __fn_name="${2}"
+ __fn_tu="${1}"
+ __fn_vars=
+ __fn_var_vals=
+ __frame_set
+
+ # Switch.
+ __fn_ctxsw
+}
+
+__fn_end()
+{
+ # Hooks.
+ unset IFS
+ for __fn in ${__fn_end_hooks}; do
+ ${__fn} ${__fn_name}
+ done
+
+ # Old state.
+ __prev_tu="${__fn_tu}"
+ __prev_vars="${__fn_vars}"
+
+ # Set stack pointer.
+ __sp_dec
+
+ # New state.
+ __frame_get
+
+ # Switch.
+ __fn_ctxsw
+}
+
+__tu_end()
+{
+ # Save TU static vars.
+ unset IFS
+ for __var in $(eval "printf '%s' \"\${__${__tu}_static_vars}\""); do
+ __val="$(eval "printf '%s' \"\${${__var}}\"" | \
+ sed "s|'|'\\\\''|g")"
+ eval "__${__tu}_static_var_vals=\"\${__${__tu}_static_var_vals}\
+ ${__var}='\${__val}'\""
+ unset ${__var}
+ done
+
+ __tu=''
+}
+
+__stack_trace()
+{
+ __fn_frame=0
+ while [ ${__fn_frame} -le ${__sp} ]; do
+ eval "printf '%s\n' \"\${__frame_${__fn_frame}_name}\""
+ __fn_frame=$((${__fn_frame} + 1))
+ done
+}
+
+__local()
+{
+ unset IFS
+ for __var in "${@}"; do
+ case "${__var}" in
+ *=*)
+ __val="${__var#*=}"
+ __var="${__var%%=*}"
+ ;;
+ *)
+ __val=''
+ ;;
+ esac
+ case "${__var}" in [!A-Za-z_]* | *[!0-9A-Za-z_]*)
+ printf 'Syntax error: %s %s\n' \
+ 'illegal static variable name:' "${__var}" >&2
+ exit 1
+ ;; esac
+ eval "${__var}=\${__val}"
+ __fn_vars="${__fn_vars} ${__var}"
+ done
+}
+
+__static()
+{
+ case "${__tu}" in '')
+ printf 'Error: Cannot declare static variables in functions' >&2
+ exit 1
+ ;; esac
+ unset IFS
+ for __var in "${@}"; do
+ case "${__var}" in
+ *=*)
+ __val="${__var#*=}"
+ __var="${__var%%=*}"
+ ;;
+ *)
+ __val=''
+ ;;
+ esac
+ case "${__var}" in [!A-Za-z_]* | *[!0-9A-Za-z_]*)
+ printf 'Syntax error: %s %s\n' \
+ 'illegal static variable name:' "${__var}" >&2
+ exit 1
+ ;; esac
+ eval "${__var}=\${__val}"
+ eval "__${__tu}_static_vars=\"\${__${__tu}_static_vars} \
+ ${__var}\""
+ done
+}
+
+__fn_begin_hook()
+{
+ __fn_begin_hooks="${__fn_begin_hooks} ${1}"
+}
+
+__fn_end_hook()
+{
+ __fn_end_hooks="${__fn_end_hooks} ${1}"
+}
+
+__init()
+{
+ __init_funcs="${__init_funcs} ${1}"
+}