summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGianni Ceccarelli <gianni.ceccarelli@broadbean.com>2023-07-14 15:22:38 +0100
committerGianni Ceccarelli <gianni.ceccarelli@broadbean.com>2023-07-14 15:22:38 +0100
commit6297ec2ae4263c346a9f7cf036055ca8cdb72c78 (patch)
tree77263057ecc8c925315cd6cd10939a0cf0942413
parentmuch better encoding (diff)
downloadbash-object-system-6297ec2ae4263c346a9f7cf036055ca8cdb72c78.tar.gz
bash-object-system-6297ec2ae4263c346a9f7cf036055ca8cdb72c78.tar.bz2
bash-object-system-6297ec2ae4263c346a9f7cf036055ca8cdb72c78.zip
inheritance via MOP
*probably*, I'm still not completely certain I've found all the weirdness
-rw-r--r--bos-dispatch.sh6
-rw-r--r--bos-mop-inheritance.sh51
-rw-r--r--bos-mop.sh18
-rw-r--r--test.sh12
4 files changed, 76 insertions, 11 deletions
diff --git a/bos-dispatch.sh b/bos-dispatch.sh
index cb883d8..afefb5e 100644
--- a/bos-dispatch.sh
+++ b/bos-dispatch.sh
@@ -6,10 +6,9 @@ function bos-dispatch/invoke() {
local self_id="$1";shift
local method="$1";shift
- local self
- bos-object-id/pack-self-into "$class" "$self_id" self
-
if declare -F "$class/$method" >/dev/null; then
+ local self
+ bos-object-id/pack-self-into "$class" "$self_id" self
"$class/$method" "$@"
return $?
fi
@@ -19,4 +18,5 @@ function bos-dispatch/invoke() {
local -n metaclass_object="$metaclass_ref"
$metaclass_object invoke "$class" "$self_id" "$method" "$@"
+ return $?
}
diff --git a/bos-mop-inheritance.sh b/bos-mop-inheritance.sh
new file mode 100644
index 0000000..551dd18
--- /dev/null
+++ b/bos-mop-inheritance.sh
@@ -0,0 +1,51 @@
+#!bash
+
+# this encoding must match bos-namespaces/encode-into
+bos_5fbos_2fmop_2finheritance_5fmeta="bos-dispatch/invoke bos/mop/base 0"
+declare -a bos_5fbos_2fmop_2finheritance_5fmro=( "bos/mop/inheritance" "bos/mop/base" )
+
+function bos/mop/inheritance/isa-for-into() {
+ bos-namespaces/store-array-for-into isa "$1" "$2"
+}
+
+function bos/mop/inheritance/set-superclasses-for() {
+ local isa_name; $self isa-for-into "$1" isa_name
+ local -n isa="$isa_name"
+ shift
+
+ isa=( "$@" )
+
+ return 0
+}
+
+function bos/mop/inheritance/get-superclasses-for-into() {
+ local isa_name; $self isa-for-into "$1" isa_name
+ local -n isa="$isa_name"
+ local -n dest="$2"
+
+ dest=( "${isa[@]}" )
+
+ return 0
+}
+
+# given a class and an array, sets the array to the list of clasess to
+# look into when resolving a method call for the given class, in order
+function bos/mop/inheritance/make-mro-for() {
+ local class="$1"
+ local mro_name; $self mro-for-into "$class" mro_name
+ local -n mro="$mro_name"
+
+ # TODO: use C3 and support multiple inheritance
+
+ mro=( "$class" )
+ local -a nextclasses
+ $self get-superclasses-for-into "$class" nextclasses
+
+ while [[ "${#nextclasses}" -gt 0 ]]; do
+ mro+=( "${nextclasses[0]}" )
+ class="${nextclasses[0]}"
+ $self get-superclasses-for-into "$class" nextclasses
+ done
+
+ return 0
+}
diff --git a/bos-mop.sh b/bos-mop.sh
index 3b06216..b3b03f0 100644
--- a/bos-mop.sh
+++ b/bos-mop.sh
@@ -23,6 +23,12 @@ function bos/mop/base/find-method-into() {
local mro_store; $self mro-for-into "$class" mro_store
local -n mro="$mro_store"
+
+ # minimal MRO: the class itself
+ if [[ "${#mro[@]}" -eq 0 ]]; then
+ mro=( "$class" )
+ fi
+
local idx=0
# if we don't have a $start_from_class, it means we're doing the
@@ -67,14 +73,18 @@ function bos/mop/base/invoke() {
fi
# get the first class that defines the method
- local to_invoke
- $self find-method-into "$class" "$start_from_class" "$method" to_invoke
+
+ # there is some fuckery going on with namerefs, recursion, and
+ # local; this is a probably-bad-but-works workaround: use a
+ # different variable name in different recursive calls
+ local ffsname="to_invoke_${#FUNCNAME[*]}"
+ $self find-method-into "$class" "$start_from_class" "$method" "$ffsname"
# TODO: make the fields accessible!
- local self
bos-object-id/pack-self-into "$class" "$object_id" self
# call it
- "$to_invoke" "$@"
+ eval "\"\$$ffsname\" \"\$@\""
+ return $?
}
diff --git a/test.sh b/test.sh
index 1a4ed6d..4a3e02c 100644
--- a/test.sh
+++ b/test.sh
@@ -1,19 +1,23 @@
#!/bin/bash
+PS4='[${#FUNCNAME[*]}] ${BASH_SOURCE[0]}:${LINENO} (${FUNCNAME[0]}) +'
+
. bos-namespaces.sh
. bos-object-id.sh
. bos-mop.sh
. bos-dispatch.sh
+. bos-mop-inheritance.sh
-bos_5fA_5fmeta="bos-dispatch/invoke bos/mop/base 0"
-bos_5fA_5fmro=( "A" )
+bos_5fA_5fmeta="bos-dispatch/invoke bos/mop/inheritance 0"
function A/thing() {
echo "<$self> A/thing ($*)"
}
-bos_5fB_5fmeta="bos-dispatch/invoke bos/mop/base 0"
-bos_5fB_5fmro=( "B" "A" )
+
+bos_5fB_5fmeta="bos-dispatch/invoke bos/mop/inheritance 0"
+$bos_5fB_5fmeta set-superclasses-for B A
+$bos_5fB_5fmeta make-mro-for B
function B/other() {
echo "<$self> B/other ($*)"