summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGianni Ceccarelli <gianni.ceccarelli@broadbean.com>2023-07-06 16:57:08 +0100
committerGianni Ceccarelli <gianni.ceccarelli@broadbean.com>2023-07-06 16:57:08 +0100
commitef445704a404a335663292214564cf5ce62622a3 (patch)
tree48c142c02e14927cde575057ff855929848c96fa
parentmight work? (diff)
downloadbash-object-system-ef445704a404a335663292214564cf5ce62622a3.tar.gz
bash-object-system-ef445704a404a335663292214564cf5ce62622a3.tar.bz2
bash-object-system-ef445704a404a335663292214564cf5ce62622a3.zip
some docs
-rw-r--r--defs.sh105
1 files changed, 61 insertions, 44 deletions
diff --git a/defs.sh b/defs.sh
index dc711ec..1ab6fbe 100644
--- a/defs.sh
+++ b/defs.sh
@@ -1,7 +1,12 @@
#!bash
+### Bash Object System
+
+## namespace handling
+
declare -A bos_saved_funcs
+# save all currently-visible functions in an associative array
function bos_save_funcs() {
local _ name
@@ -12,6 +17,8 @@ function bos_save_funcs() {
return 0
}
+# diff all currently-visible function against the saved ones, list the
+# ones that differ
function bos_list_new_funcs() {
local _ name new_function
@@ -25,6 +32,8 @@ function bos_list_new_funcs() {
return 0
}
+# rename a bunch of functions by prepending a prefix; restore the
+# saved function of the same name, if it exists
function bos_qualify_funcs() {
local prefix="$1"
shift
@@ -43,7 +52,21 @@ function bos_qualify_funcs() {
return 0
}
+## the MOP
+
+bos_current_class=''
+
+# begin the definition of a class (not really MOP, is it?)
+function bos_begin_class() {
+ bos_current_class="$1"
+
+ bos_save_funcs
+
+ return 0
+}
+# set the superclasses of the current class
+# TODO: split this into MOP + helper
function bos_set_superclasses() {
local isa_name="${bos_current_class}__bos_isa"
declare -ga "$isa_name"
@@ -54,6 +77,7 @@ function bos_set_superclasses() {
return 0
}
+# get the superclasses of the given class
function bos_get_superclasses_for() {
local class="$1"
local -n dest="$2"
@@ -65,8 +89,9 @@ function bos_get_superclasses_for() {
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_linearised_isa() {
-
local class="$1"
local -n _linearised_isa="$2"
@@ -85,16 +110,10 @@ function bos_linearised_isa() {
return 0
}
-bos_current_class=''
-
-function bos_begin_class() {
- bos_current_class="$1"
-
- bos_save_funcs
-
- return 0
-}
-
+# ends the definition of a class, moving its functions into the class
+# namespace and calculating the MRO
+# TODO: split this into MOP + helper
+# TODO: delay MRO computation until first method call?
function bos_end_class() {
local mro_name="${bos_current_class}__bos_mro"
declare -ga "$mro_name"
@@ -106,21 +125,21 @@ function bos_end_class() {
return 0
}
+# find the first class (in MRO) that defines a given method
function bos_find_class_for_method() {
- # we need to know:
- #
- # - what class started the method dispatch (we need a class name
- # or an object instance)
+ # the class that started the method dispatch (the class of $self,
+ # usually)
local class="$1"
- # - what class invoked us
+ # what class invoked next.method (if we're doing next.method)
local start_from_class="$2"
- # - what method invoked us (same)
+ # the method to look for
local method="$3"
local -n mro="${class}__bos_mro"
- local next_class
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
@@ -138,18 +157,14 @@ function bos_find_class_for_method() {
fi
done
+ # TODO: better error / failure
>&2 echo "method $method not found"
}
-function bos_id_from_self() {
- local -a parts=( $1 )
- echo "${parts[2]}"
-}
-
# objects are values, so they're stored in variables!
#
-# the shape of that value is… a call to _invoke curry-ed on class and
-# id, so that `$my_obj the-method 1 2` is equivalent to `_invoke
+# the shape of that value is… a call to bos_invoke curry-ed on class and
+# id, so that `$my_obj the-method 1 2` is equivalent to `bos_invoke
# TheClass $the_obj_id the-method 1 2`
function bos_self_from_class_id() {
local class="$1"
@@ -157,6 +172,12 @@ function bos_self_from_class_id() {
echo "bos_invoke $class $self_id"
}
+# get object id from a $self string
+function bos_id_from_self() {
+ local -a parts=( $1 )
+ echo "${parts[2]}"
+}
+
function bos_storage_var_for_object() {
local self_id="$(bos_id_from_self "$1")"
local var="bos_obj_storage_${self_id}"
@@ -177,6 +198,11 @@ function bos_get_attribute_value() {
echo "${storage[$field]}"
}
+# declare getter / setter for an attribute in the current class
+#
+# TODO: maybe split? bos_add_attribute just declares the attribute,
+# then have MOP functions to create getter and/or setter, then join
+# the two in bos_end_class
function bos_add_attribute() {
local name="$1"
@@ -190,25 +216,7 @@ function set_${name}() {
"
}
-function bos_find_methods() {
- local class="$1"
- local method="$2"
- local -n dest="$3"
-
- local -n mro="${class}__bos_mro"
-
- dest=()
-
- for class in "${mro[@]}"; do
- local full_name="${class}.${method}"
- if declare -F "$full_name" >/dev/null; then
- dest+=( "$full_name" )
- fi
- done
-
- return 0
-}
-
+# return the closest non-BOS function name from the call stack
function bos_caller() {
local idx
for caller in "${FUNCNAME[@]}"; do
@@ -229,21 +237,30 @@ function bos_invoke() {
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_caller)"
method="${caller##*.}"
start_from_class="${caller%.*}"
fi
+ # get the first class that defines the method
class="$(bos_find_class_for_method "$class" "$start_from_class" "$method")"
+ # call it
"${class}.${method}" "$@"
}
bos_object_id=0
+# constructor: given a variable name and a class, create an object of
+# that class, build it, and assign it to the variable
function bos_create_object() {
local -n dest="$1";shift
local class="$1";shift
+
(( ++bos_object_id ))
+
local self="$(bos_self_from_class_id $class $bos_object_id)"
declare -gA "$(bos_storage_var_for_object "$self")"