declare -a bos_sugar_block_stack
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
if [[ "${bos_sugar_block_stack[-1]}" == 0 ]]; then
bos_sugar_block_stack[-1]=1
"$on_open" "$@" && return 0
else
unset "bos_sugar_block_toggle[-1]"
"$on_close" "$@" && return 1
fi
}
function bos-sugar/declare-block() {
local block_name="$1"
local open_func="$2"
local close_func="$3"
shopt -s expand_aliases
eval "alias $1='bos-sugar/push; while bos-sugar/block-and-pop $open_func $close_func'"
}
function bos-sugar/declare-helpers() {
function extends() {
local fq_class; bos-namespaces/current-namespace-into fq_class
local metaclass_instance; bos-meta/metaclass-instance-for-class-into metaclass_instance "$fq_class"
$metaclass_instance set-superclasses-for "$fq_class" "$@"
}
}
function bos-sugar/remove-helpers() {
unset extends
}
function bos-sugar/class-open() {
if [[ "${#*}" -lt 1 || "${#*}" -gt 2 ]]; then
>&2 echo "'class \$class_name [\$metaclass]; do …; done', not 'class $*'"
return 1
fi
local class="$1"
local metaclass="${2:-bos/meta/class}"
bos-sugar/declare-helpers
bos-namespaces/namespace-open "$1"
local fq_class; bos-namespaces/current-namespace-into fq_class
local class_open_metaclass_instance; $metaclass new-into class_open_metaclass_instance
bos-meta/set-metaclass-instance-for "$fq_class" "$class_open_metaclass_instance"
return 0
}
function bos-sugar/class-close() {
local class="$1";
local fq_class; bos-namespaces/current-namespace-into fq_class
bos-namespaces/namespace-close
local class_close_metaclass_instance; bos-meta/metaclass-instance-for-class-into class_close_metaclass_instance "$fq_class"
$class_close_metaclass_instance make-mro-for "$fq_class"
# TODO this should probably be done by the metaclass?
eval "function $fq_class { bos-dispatch/invoke \"$fq_class\" 0 \"\$@\"; }"
bos-sugar/remove-helpers
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/namespace-open "$1"
return 0
}
function bos-sugar/namespace-close() {
bos-namespaces/namespace-close
return 0
}
bos-sugar/declare-block namespace bos-sugar/namespace-open bos-sugar/namespace-close