diff options
author | Gianni Ceccarelli <gianni.ceccarelli@broadbean.com> | 2023-07-06 16:57:08 +0100 |
---|---|---|
committer | Gianni Ceccarelli <gianni.ceccarelli@broadbean.com> | 2023-07-06 16:57:08 +0100 |
commit | ef445704a404a335663292214564cf5ce62622a3 (patch) | |
tree | 48c142c02e14927cde575057ff855929848c96fa /defs.sh | |
parent | might work? (diff) | |
download | bash-object-system-ef445704a404a335663292214564cf5ce62622a3.tar.gz bash-object-system-ef445704a404a335663292214564cf5ce62622a3.tar.bz2 bash-object-system-ef445704a404a335663292214564cf5ce62622a3.zip |
some docs
Diffstat (limited to 'defs.sh')
-rw-r--r-- | defs.sh | 105 |
1 files changed, 61 insertions, 44 deletions
@@ -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")" |