summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordakkar <dakkar@thenautilus.net>2023-07-22 16:53:18 +0100
committerdakkar <dakkar@thenautilus.net>2023-07-22 16:53:18 +0100
commit0f575edf3c393c81ee690beea9416dea89b8085f (patch)
tree9e3abddcf97ffaf1a8034e5e8013fc5ac6e1e04c
parentmetaclass instances (diff)
downloadbash-object-system-0f575edf3c393c81ee690beea9416dea89b8085f.tar.gz
bash-object-system-0f575edf3c393c81ee690beea9416dea89b8085f.tar.bz2
bash-object-system-0f575edf3c393c81ee690beea9416dea89b8085f.zip
remove old implementation
-rw-r--r--defs.sh311
1 files changed, 0 insertions, 311 deletions
diff --git a/defs.sh b/defs.sh
deleted file mode 100644
index 1ab6fbe..0000000
--- a/defs.sh
+++ /dev/null
@@ -1,311 +0,0 @@
-#!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
-
- while read -r _ _ name; do
- bos_saved_funcs+=( ["$name"]="$(declare -pf "$name")" )
- done < <( declare -pF )
-
- 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
-
- while read -r _ _ name; do
- new_function="$(declare -pf "$name")"
- if [[ "$new_function" != "${bos_saved_funcs["$name"]}" ]]; then
- echo "${name}"
- fi
- done < <( declare -pF )
-
- 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
- local _ name new_function
-
- for name in "$@"; do
- new_function="$(declare -pf "$name")"
- eval "${prefix}.${new_function}"
- if [[ -n "${bos_saved_funcs["$name"]}" ]]; then
- eval "${bos_saved_funcs["$name"]}"
- else
- unset -f "$name"
- fi
- done
-
- 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"
- local -n isa="$isa_name"
-
- isa=( "$@" )
-
- return 0
-}
-
-# get the superclasses of the given class
-function bos_get_superclasses_for() {
- local class="$1"
- local -n dest="$2"
- local isa_name="${class}__bos_isa"
- local -n isa="$isa_name"
-
- 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_linearised_isa() {
- local class="$1"
- local -n _linearised_isa="$2"
-
- # TODO: use C3 and support multiple inheritance
-
- _linearised_isa=( "$class" )
- local -a nextclasses
- bos_get_superclasses_for "$class" nextclasses
-
- while [[ "${#nextclasses}" -gt 0 ]]; do
- _linearised_isa+=( "${nextclasses[0]}" )
- class="${nextclasses[0]}"
- bos_get_superclasses_for "$class" nextclasses
- done
-
- 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"
-
- readarray -t method_names < <(bos_list_new_funcs)
- bos_qualify_funcs "$bos_current_class" "${method_names[@]}"
- bos_linearised_isa "$bos_current_class" "$mro_name"
-
- return 0
-}
-
-# find the first class (in MRO) that defines a given method
-function bos_find_class_for_method() {
- # 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 mro="${class}__bos_mro"
- 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
- echo "${mro[$idx]}"
- return 0
- fi
- done
-
- # TODO: better error / failure
- >&2 echo "method $method not found"
-}
-
-# objects are values, so they're stored in variables!
-#
-# 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"
- local self_id="$2"
- 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}"
- echo "$var"
-}
-
-function bos_set_attribute_value() {
- local self="$1";shift
- local field="$1";shift
- local -n storage="$(bos_storage_var_for_object "$self")"
- storage[$field]="$*"
-}
-
-function bos_get_attribute_value() {
- local self="$1";shift
- local field="$1";shift
- local -n storage="$(bos_storage_var_for_object "$self")"
- 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"
-
- eval "
-function get_${name}() {
- bos_get_attribute_value \"\$self\" $name
-}
-function set_${name}() {
- bos_set_attribute_value \"\$self\" $name \"\$@\"
-}
-"
-}
-
-# return the closest non-BOS function name from the call stack
-function bos_caller() {
- local idx
- for caller in "${FUNCNAME[@]}"; do
- if [[ ! $caller =~ ^bos_ ]]; then
- echo "$caller"
- return 0
- fi
- done
-}
-
-# the method dispatcher
-function bos_invoke() {
- local class="$1";shift
- local self_id="$1";shift
- local method="$1";shift
- local self="$(bos_self_from_class_id $class $self_id)"
-
- 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")"
-
- $self BUILD "$@"
-
- dest="$self"
-}
-
-# ---- test ----
-
-bos_begin_class one
-
-bos_add_attribute first
-
-BUILD() {
- echo "building one"
- $self set_first "$1"
-}
-
-function doit() {
- echo "one method ($*) first=$( $self get_first )"
-}
-
-bos_end_class
-
-bos_begin_class two
-
-bos_set_superclasses one
-
-bos_add_attribute second
-
-BUILD() {
- echo "building two"
- $self set_second "$1"
- $self next.method "$2"
-}
-
-function doit() {
- echo "two method ($*) second=$( $self get_second )"
-
- $self next.method "$@"
-}
-
-bos_end_class
-
-bos_create_object A two 16 23
-
-$A doit 1 2 3