diff options
-rw-r--r-- | bos-meta-attribute.sh | 38 | ||||
-rw-r--r-- | bos-meta-class.sh | 49 |
2 files changed, 87 insertions, 0 deletions
diff --git a/bos-meta-attribute.sh b/bos-meta-attribute.sh new file mode 100644 index 0000000..78c573e --- /dev/null +++ b/bos-meta-attribute.sh @@ -0,0 +1,38 @@ +#!bash + +# this must be callable without a `self`, see +# bos/meta/class/get-attribute-by-name-into +function bos/meta/attribute/store-for-into() { + local bos_meta_attribute_class bos_meta_attribute_objid + bos-object/unpack-self-into bos_meta_attribute_class bos_meta_attribute_objid "$2" + + "bos-namespaces/${attribute_type}-store-for-into" "$1" attribute "$attribute_name" "$associated_class" "$bos_meta_attribute_class" "$bos_meta_attribute_objid" +} + +function bos/meta/attribute/set-value() { + local bos_meta_attribute_store; $self store-for-into bos_meta_attribute_store "$1" + shift + + case "$attribute_type" in + scalar) bos_meta_attribute_store="$1" ;; + array) bos_meta_attribute_store=( "$@" ) ;; + assoc) >&2 echo "NYI"; return 1 ;; + esac + + return 0 +} + +function bos/meta/attribute/get-value-into() { + local -n bos_meta_attribute_result="$1"; shift; + + local bos_meta_attribute_store; $self store-for-into bos_meta_attribute_store "$1" + + case "$attribute_type" in + scalar) bos_meta_attribute_result="$bos_meta_attribute_store" ;; + array) bos_meta_attribute_result=( "${bos_meta_attribute_store[@]}" ) ;; + assoc) >&2 echo "NYI"; return 1 ;; + esac + + return 0 +} + diff --git a/bos-meta-class.sh b/bos-meta-class.sh index 1fedb45..4884d40 100644 --- a/bos-meta-class.sh +++ b/bos-meta-class.sh @@ -99,6 +99,55 @@ function bos/meta/class/find-method-into() { return 1 } +# get the attribute meta-object for the given attribute name, assuming +# that the class that this metaclass describe, actuall has that +# attribute +function bos/meta/class/get-attribute-by-name-into() { + local -A bos_meta_class_attrs + + # very manual method call, because I'm not sure I can make this + # work otherwise + + local attribute_name='class-attributes' + local associated_class='bos/meta/class' + + bos/meta/attribute/store-for-into bos_meta_class_attrs "$self" + + return "${bos_meta_class_attrs[$1]}" +} + + +function bos/meta/class/find-attribute-into() { + local -n bos_meta_class_find_attribute_result="$1" + local class="$2" + local attribute_name="$4" + + local mro_store; $self mro-for-into mro_store "$class" + local -n mro="$mro_store" + + # minimal MRO: the class itself + if [[ "${#mro[@]}" -eq 0 ]]; then + mro=( "$class" ) + fi + + local bos_meta_class_for_class + local bos_class_from_mro + + for bos_class_from_mro in "${mro[@]}"; do + bos-meta/metaclass-instance-for-class-into bos_meta_class_for_class "$bos_class_from_mro" + + $bos_meta_class_for_class get-attribute-by-name-into bos_meta_class_find_attribute_result "$attribute_name" + + if [[ -n "$bos_meta_class_find_attribute_result" ]]; then + return 0 + fi + done + + # TODO: better error / failure + >&2 echo "attribute $attribute_name not found via class $class" + return 1 +} + # the method dispatcher function bos/meta/class/invoke() { local class="$1";shift |