diff options
Diffstat (limited to 'bos-mop.sh')
-rw-r--r-- | bos-mop.sh | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/bos-mop.sh b/bos-mop.sh new file mode 100644 index 0000000..f9faef2 --- /dev/null +++ b/bos-mop.sh @@ -0,0 +1,81 @@ +#!bash + +bos_class__bos__mop__base__meta="bos-dipatch/invoke bos/mop/base 0" + +# these are instance methods of the base metaclass + +function bos/mop/base/mro-for-into() { + local name="bos_mop__mro__${1//\//__}" + local -n result="$2" + declare -ga "$name" + result="$name" +} + +# find the first class (in MRO) that defines a given method +function bos/mop/base/find-method-into() { + # the class that started the method dispatch (the class of $self, + # usually) + local class="$1" + # what class invoked next/method (if we're doing next/method) + local start_from_class="$2" + # the method to look for + local method="$3" + local -n result="$4" + + local mro_store; $self mro-for-into mro_store + local -n mro="$mro_store" + local idx=0 + + # if we don't have a $start_from_class, it means we're doing the + # initial method resolution, so don't skip any class in $mro + 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 + result="${full_name}" + return 0 + fi + done + + # TODO: better error / failure + >&2 echo "method $method not found" + return 1 +} + +# the method dispatcher +function bos/mop/base/invoke() { + local class="$1";shift + local object_id="$1";shift + local method="$1";shift + + local start_from_class='' + + if [[ "$method" == 'next/method' ]]; then + # get the method and the calling class, so + # bos_find_class_for_method will return the *next* class to + # use + local caller; bos-dispatch/caller-into caller + method="${caller##*/}" + start_from_class="${caller%/*}" + fi + + # get the first class that defines the method + local to_invoke + $self find-method-into "$class" "$start_from_class" "$method" to_invoke + + # TODO: make the fields accessible! + + local self + bos-object-id/pack-self-into "$class" "$object_id" self + + # call it + "$to_invoke" "$@" +} |