diff options
Diffstat (limited to 'eshtrans/eshrt')
-rw-r--r-- | eshtrans/eshrt/eshrtbegin.esh | 250 | ||||
-rw-r--r-- | eshtrans/eshrt/eshrtend.esh | 27 |
2 files changed, 277 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}" +} diff --git a/eshtrans/eshrt/eshrtend.esh b/eshtrans/eshrt/eshrtend.esh new file mode 100644 index 0000000..34cb7e1 --- /dev/null +++ b/eshtrans/eshrt/eshrtend.esh @@ -0,0 +1,27 @@ +# 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 + +unset IFS +for __func in ${__init_funcs}; do + ${__func} +done +${__entry} "${@}" |