diff options
-rw-r--r-- | bos-namespaces.sh | 29 | ||||
-rw-r--r-- | bos-sugar.sh | 91 | ||||
-rw-r--r-- | t/namespace.t | 17 |
3 files changed, 104 insertions, 33 deletions
diff --git a/bos-namespaces.sh b/bos-namespaces.sh index 0cb794a..02f3df2 100644 --- a/bos-namespaces.sh +++ b/bos-namespaces.sh @@ -38,9 +38,25 @@ function bos-namespaces/store-dict-for-into() { result="$name" } +declare -a bos_namespace_stack + +function bos-namespaces/current-namespace-into() { + local -n bos_namespace_current_namespace_result="$1" + local IFS=/ + bos_namespace_current_namespace_result="${bos_namespace_stack[*]}" +} + +function bos-namespaces/push() { + bos_namespace_stack+=( "$1" ) +} + +function bos-namespaces/pop() { + unset "bos_namespace_stack[-1]" +} + # save all currently-visible functions in an associative array -function bos-namespaces/start() { - local namespace="$1";shift +function bos-namespaces/save-funcs() { + local namespace; bos-namespaces/current-namespace-into namespace local ns_store; bos-namespaces/store-dict-for-into ns_store saved_funcs "$namespace" local -n saved_funcs="$ns_store" local _ funcname @@ -56,12 +72,17 @@ function bos-namespaces/start() { # ones that differ function bos-namespaces/list-new-funcs-into() { local -n result="$1" - local namespace="$2" + local namespace; bos-namespaces/current-namespace-into namespace local ns_store; bos-namespaces/store-dict-for-into ns_store saved_funcs "$namespace" local -n saved_funcs="$ns_store" local _ funcname new_function while read -r _ _ funcname; do + # if a function already belong to this namespace, it's not new + if [[ "$funcname" == "$namespace"/* ]]; then + continue + fi + new_function="$(declare -pf "$funcname")" if [[ "$new_function" != "${saved_funcs["$funcname"]}" ]]; then result+=( "${funcname}" ) @@ -74,7 +95,7 @@ function bos-namespaces/list-new-funcs-into() { # rename a bunch of functions by prepending a prefix; restore the # saved function of the same name, if it exists function bos-namespaces/qualify-funcs() { - local namespace="$1";shift + local namespace; bos-namespaces/current-namespace-into namespace local ns_store; bos-namespaces/store-dict-for-into ns_store saved_funcs "$namespace" local -n saved_funcs="$ns_store" local _ funcname new_function diff --git a/bos-sugar.sh b/bos-sugar.sh index 2da789a..1322b36 100644 --- a/bos-sugar.sh +++ b/bos-sugar.sh @@ -1,47 +1,58 @@ #!bash -declare -a bos_sugar_block_toggle +declare -a bos_sugar_block_stack -function bos-sugar/block() { +function bos-sugar/push() { + bos_sugar_block_stack+=( 0 ) +} + +function bos-sugar/block-and-pop() { local on_open="$1"; shift local on_close="$1"; shift - local depth="${#FUNCNAME[*]}" - if [[ -z "${bos_sugar_block_toggle[$depth]}" ]]; then - bos_sugar_block_toggle=( ["$depth"]=1 ) - "$on_open" "$@" + + if [[ "${bos_sugar_block_stack[-1]}" == 0 ]]; then + bos_sugar_block_stack[-1]=1 + "$on_open" "$@" && return 0 else - unset "bos_sugar_block_toggle[$depth]" - "$on_close" "$@" + unset "bos_sugar_block_toggle[-1]" + "$on_close" "$@" && return 1 fi } -declare -a bos_sugar_class_stack +function bos-sugar/declare-block() { + local block_name="$1" + local open_func="$2" + local close_func="$3" -function bos-sugar/current-class-into() { - local -n bos_sugar_current_class_result="$1" - local IFS=/ - bos_sugar_current_class_result="${bos_sugar_class_stack[*]}" + shopt -s expand_aliases + + eval "alias $1='bos-sugar/push; while bos-sugar/block-and-pop $open_func $close_func'" } -function bos-sugar/set-metaclass-for-current-class() { - local class; bos-sugar/current-class-into class +# ---- + +function bos-sugar/set-metaclass-for() { + local class="$1" local metaclass_ref; bos-namespaces/store-scalar-for-into metaclass_ref meta "$class" local -n metaclass_object="$metaclass_ref" metaclass_object='bos-dispatch/invoke bos/mop/inheritance 0' } function bos-sugar/class-open() { - if [[ "${#*}" -gt 1 ]]; then + if [[ "${#*}" -ne 1 ]]; then >&2 echo "'class \$class_name; do …; done', not 'class $*'" return 1 fi + local class="$1" - bos_sugar_class_stack+=( "$class" ) - bos-sugar/set-metaclass-for-current-class - local fq_class; bos-sugar/current-class-into fq_class + bos-namespaces/push "$class" + + local fq_class; bos-namespaces/current-namespace-into fq_class + + bos-sugar/set-metaclass-for "$fq_class" function extends() { - local fq_class; bos-sugar/current-class-into fq_class + local fq_class; bos-namespaces/current-namespace-into fq_class local metaclass_ref; bos-namespaces/store-scalar-for-into metaclass_ref meta "$fq_class" local -n metaclass_object="$metaclass_ref" $metaclass_object set-superclasses-for "$fq_class" "$@" @@ -49,7 +60,7 @@ function bos-sugar/class-open() { eval "function $fq_class { bos-dispatch/invoke \"$fq_class\" 0 \"\$@\"; }" - bos-namespaces/start "$fq_class" + bos-namespaces/save-funcs # this will get renamed into the class function new-into() { @@ -68,22 +79,44 @@ function bos-sugar/class-open() { } function bos-sugar/class-close() { - local class="$1" + local class="$1"; - local fq_class; bos-sugar/current-class-into fq_class + local fq_class; bos-namespaces/current-namespace-into fq_class local metaclass_ref; bos-namespaces/store-scalar-for-into metaclass_ref meta "$fq_class" local -n metaclass_object="$metaclass_ref" - local -a methods_list; bos-namespaces/list-new-funcs-into methods_list "$fq_class" - bos-namespaces/qualify-funcs "$fq_class" "${methods_list[@]}" + local -a methods_list; bos-namespaces/list-new-funcs-into methods_list + bos-namespaces/qualify-funcs "${methods_list[@]}" $metaclass_object make-mro-for "$fq_class" - unset "bos_sugar_class_stack[-1]" + bos-namespaces/pop + + return 0 +} + +bos-sugar/declare-block class bos-sugar/class-open bos-sugar/class-close + +function bos-sugar/namespace-open() { + if [[ "${#*}" -ne 1 ]]; then + >&2 echo "'namespace \$namespace_name; do …; done', not 'namespace $*'" + return 1 + fi + + bos-namespaces/push "$1" + bos-namespaces/save-funcs - return 1 + return 0 +} + +function bos-sugar/namespace-close() { + local -a methods_list; bos-namespaces/list-new-funcs-into methods_list + bos-namespaces/qualify-funcs "${methods_list[@]}" + + bos-namespaces/pop + + return 0 } -shopt -s expand_aliases +bos-sugar/declare-block namespace bos-sugar/namespace-open bos-sugar/namespace-close -alias class='while bos-sugar/block bos-sugar/class-open bos-sugar/class-close' diff --git a/t/namespace.t b/t/namespace.t new file mode 100644 index 0000000..e367720 --- /dev/null +++ b/t/namespace.t @@ -0,0 +1,17 @@ +#!/bin/bash + +. t/testlib.sh + +namespace One; do + function test() { echo One/test; } + + class Two; do + function test() { echo One/Two/test; } + done + +done + +is "$(One/test)" One/test 'function should be moved to namespace' +is "$(One/Two/test)" One/Two/test 'class should be moved to namespace' + +done-testing |