function bos/meta/class/isa-for-into() {
bos-namespaces/store-array-for-into "$1" isa "$2"
}
function bos/meta/class/set-superclasses-for() {
local isa_name; $self isa-for-into isa_name "$1"
local -n isa="$isa_name"
shift
isa=( "$@" )
return 0
}
function bos/meta/class/get-superclasses-for-into() {
local -n dest="$1"
local isa_name; $self isa-for-into isa_name "$2"
local -n isa="$isa_name"
dest=( "${isa[@]}" )
return 0
}
function bos/meta/class/mro-for-into() {
bos-namespaces/store-array-for-into "$1" mro "$2"
}
function bos/meta/class/make-mro-for() {
local class="$1"
local mro_name; $self mro-for-into mro_name "$class"
local -n mro="$mro_name"
mro=( "$class" )
local -a nextclasses
$self get-superclasses-for-into nextclasses "$class"
while [[ "${#nextclasses}" -gt 0 ]]; do
mro+=( "${nextclasses[0]}" )
class="${nextclasses[0]}"
$self get-superclasses-for-into nextclasses "$class"
done
mro+=( "bos/base" )
return 0
}
function bos/meta/class/find-method-into() {
local -n bos_meta_class_find_method_result="$1"
local class="$2"
local start_from_class="$3"
local method="$4"
local mro_store; $self mro-for-into mro_store "$class"
local -n mro="$mro_store"
if [[ "${#mro[@]}" -eq 0 ]]; then
mro=( "$class" )
fi
local idx=0
if [[ -n "$start_from_class" ]]; then
for (( ; idx < "${#mro[@]}" ; ++idx )); do
if [[ "${mro[$idx]}" == "$start_from_class" ]]; then
(( ++idx ))
break
fi
done
fi
for (( ; idx < "${#mro[@]}" ; ++idx )); do
local full_name="${mro[$idx]}/${method}"
if declare -F "$full_name" >/dev/null; then
bos_meta_class_find_method_result="${full_name}"
return 0
fi
done
>&2 echo "method $method not found via class $class"
return 1
}
function bos/meta/class/get-attribute-by-name-into() {
local -A bos_meta_class_attrs
local attribute_name='class-attributes'
local associated_class='bos/meta/class'
bos/meta/attribute/store-for-into bos_meta_class_attrs "$self"
return "${bos_meta_class_attrs[$1]}"
}
function bos/meta/class/find-attribute-into() {
local -n bos_meta_class_find_attribute_result="$1"
local class="$2"
local attribute_name="$4"
local mro_store; $self mro-for-into mro_store "$class"
local -n mro="$mro_store"
if [[ "${#mro[@]}" -eq 0 ]]; then
mro=( "$class" )
fi
local bos_meta_class_for_class
local bos_class_from_mro
for bos_class_from_mro in "${mro[@]}"; do
bos-meta/metaclass-instance-for-class-into bos_meta_class_for_class "$bos_class_from_mro"
$bos_meta_class_for_class get-attribute-by-name-into bos_meta_class_find_attribute_result "$attribute_name"
if [[ -n "$bos_meta_class_find_attribute_result" ]]; then
return 0
fi
done
>&2 echo "attribute $attribute_name not found via class $class"
return 1
}
function bos/meta/class/invoke() {
local class="$1";shift
local object_id="$1";shift
local method="$1";shift
local start_from_class=''
if [[ "$method" == 'next/method' ]]; then
local caller; bos-dispatch/caller-into caller
method="${caller##*/}"
start_from_class="${caller%/*}"
fi
local ffsname="to_invoke_${#FUNCNAME[*]}"
$self find-method-into "$ffsname" "$class" "$start_from_class" "$method"
local self
bos-object-id/pack-self-into self "$class" "$object_id"
eval "\"\$$ffsname\" \"\$@\""
return $?
}
function bos/meta/class/create-object-into() {
local -n bos_meta_class_create_object_result="$1";shift
local class="$1";shift
local object_id_store; bos-namespaces/store-scalar-for-into object_id_store object_id "$class"
local -n object_id="$object_id_store"
(( ++object_id ))
bos-object-id/pack-self-into bos_meta_class_create_object_result "$class" "$object_id"
return 0
}
function bos/meta/class() {
bos-dispatch/invoke bos/meta/class 0 "$@"
}
declare bos_meta_class_meta_class_instance
bos/meta/class/create-object-into bos_meta_class_meta_class_instance bos/meta/class
bos-meta/set-metaclass-instance-for bos/meta/class "$bos_meta_class_meta_class_instance"
$bos_meta_class_meta_class_instance make-mro-for bos/meta/class
unset bos_meta_class_meta_class_instance