diff options
-rw-r--r-- | bos-meta-attribute.sh | 81 | ||||
-rw-r--r-- | bos-meta-bootstrap.sh | 22 | ||||
-rw-r--r-- | bos-meta-class.sh | 64 |
3 files changed, 134 insertions, 33 deletions
diff --git a/bos-meta-attribute.sh b/bos-meta-attribute.sh index b5155ad..0d65dce 100644 --- a/bos-meta-attribute.sh +++ b/bos-meta-attribute.sh @@ -9,7 +9,61 @@ function bos/meta/attribute/store-for-into() { "bos-namespaces/store-${attribute_type}-for-into" "$1" attribute "$attribute_name" "$associated_class" "$bos_meta_attribute_class" "$bos_meta_attribute_objid" } +function bos/meta/attribute/get-attribute-name-into() { + local attribute_type='scalar' + local associated_class='bos/meta/attribute' + + local bos_meta_attribute_name_store + local attribute_name='attribute_name' + bos/meta/attribute/store-for-into bos_meta_attribute_name_store "$self" + + local -n bos_meta_attribute_name="$bos_meta_attribute_name_store" + + >&2 echo "get-attribute-name-into($1)<-$bos_meta_attribute_name_store" + local -n bos_meta_attribute_name_dest="$1" + bos_meta_attribute_name_dest="$bos_meta_attribute_name" +} + +function bos/meta/attribute/get-attribute-type-into() { + local attribute_type='scalar' + local associated_class='bos/meta/attribute' + + local bos_meta_attribute_type_store + local attribute_name='attribute_type' + bos/meta/attribute/store-for-into bos_meta_attribute_type_store "$self" + + local -n bos_meta_attribute_type="$bos_meta_attribute_type_store" + + local -n bos_meta_attribute_type_dest="$1" + bos_meta_attribute_type_dest="$bos_meta_attribute_type" +} + +function bos/meta/attribute/get-associated-class-into() { + local attribute_type='scalar' + local associated_class='bos/meta/attribute' + + local bos_meta_attribute_class_store + local attribute_name='associated_class' + bos/meta/attribute/store-for-into bos_meta_attribute_class_store "$self" + + local -n bos_meta_attribute_class="$bos_meta_attribute_class_store" + + local -n bos_meta_attribute_class_dest="$1" + bos_meta_attribute_class_dest="$bos_meta_attribute_class" +} + function bos/meta/attribute/set-value() { + # the `if` is there because bos-meta-bootstrap.sh sets these manually + if [[ -z "$attribute_name" ]]; then + local bos_meta_attribute_set_name; $self get-attribute-name-into bos_meta_attribute_set_name + local bos_meta_attribute_set_type; $self get-attribute-type-into bos_meta_attribute_set_type + local bos_meta_attribute_set_class; $self get-associated-class-into bos_meta_attribute_set_class + + local attribute_name="$bos_meta_attribute_set_name" + local attribute_type="$bos_meta_attribute_set_type" + local associated_class="$bos_meta_attribute_set_class" + fi + local bos_meta_attribute_store_name; $self store-for-into bos_meta_attribute_store_name "$1" shift local -n bos_meta_attribute_store="$bos_meta_attribute_store_name" @@ -17,23 +71,46 @@ function bos/meta/attribute/set-value() { case "$attribute_type" in scalar) bos_meta_attribute_store="$1" ;; array) bos_meta_attribute_store=( "$@" ) ;; - assoc) >&2 echo "NYI"; return 1 ;; + assoc) eval "bos_meta_attribute_store=( ${@@Q} )" ;; esac + >&2 declare -p "$bos_meta_attribute_store_name" + return 0 } function bos/meta/attribute/get-value-into() { + local bos_meta_attribute_result_name="$1" local -n bos_meta_attribute_result="$1"; shift; + # meta-look! we can't depend on bos-dispatch/invoke or + # bos/meta/class/invoke to set these up + + local bos_meta_attribute_get_name; $self get-attribute-name-into bos_meta_attribute_get_name + local bos_meta_attribute_get_type; $self get-attribute-type-into bos_meta_attribute_get_type + local bos_meta_attribute_get_class; $self get-associated-class-into bos_meta_attribute_get_class + + local attribute_name="$bos_meta_attribute_get_name" + local attribute_type="$bos_meta_attribute_get_type" + local associated_class="$bos_meta_attribute_get_class" + + >&2 echo "getting ($self) ($attribute_name) ($attribute_type) ($associated_class)" + local bos_meta_attribute_store_name; $self store-for-into bos_meta_attribute_store_name "$1" local -n bos_meta_attribute_store="$bos_meta_attribute_store_name" + local bos_meta_attribute_value_expr + 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 ;; + assoc) + bos_meta_attribute_value_expr="$(declare -p "$bos_meta_attribute_store_name")" + eval "bos_meta_attribute_result=${bos_meta_attribute_value_expr#*=}" + ;; esac + >&2 declare -p "$bos_meta_attribute_result_name" + return 0 } diff --git a/bos-meta-bootstrap.sh b/bos-meta-bootstrap.sh index f301812..b476f38 100644 --- a/bos-meta-bootstrap.sh +++ b/bos-meta-bootstrap.sh @@ -76,14 +76,14 @@ $bos_meta_attribute_meta_class_instance set-attribute-by-name 'associated_class' # now we set the attributes for bos/meta/class! -## this is the `class-attributes` meta-attribute +## this is the `class_attributes` meta-attribute bos/meta/class/create-object-into bos_meta_attribute_instance bos/meta/attribute attribute_type='scalar' -associated_class='bos/meta/class' +associated_class='bos/meta/attribute' attribute_name='attribute_name' -$bos_meta_attribute_instance set-value "$bos_meta_attribute_instance" 'class-attributes' +$bos_meta_attribute_instance set-value "$bos_meta_attribute_instance" 'class_attributes' attribute_name='attribute_type' $bos_meta_attribute_instance set-value "$bos_meta_attribute_instance" assoc @@ -91,16 +91,16 @@ $bos_meta_attribute_instance set-value "$bos_meta_attribute_instance" assoc attribute_name='associated_class' $bos_meta_attribute_instance set-value "$bos_meta_attribute_instance" bos/meta/class -$bos_meta_class_meta_class_instance set-attribute-by-name 'class-attributes' "$bos_meta_attribute_instance" +$bos_meta_class_meta_class_instance set-attribute-by-name 'class_attributes' "$bos_meta_attribute_instance" -## this is the `class-name` meta-attribute +## this is the `class_name` meta-attribute bos/meta/class/create-object-into bos_meta_attribute_instance bos/meta/attribute attribute_type='scalar' -associated_class='bos/meta/class' +associated_class='bos/meta/attribute' attribute_name='attribute_name' -$bos_meta_attribute_instance set-value "$bos_meta_attribute_instance" 'class-name' +$bos_meta_attribute_instance set-value "$bos_meta_attribute_instance" 'class_name' attribute_name='attribute_type' $bos_meta_attribute_instance set-value "$bos_meta_attribute_instance" scalar @@ -108,19 +108,19 @@ $bos_meta_attribute_instance set-value "$bos_meta_attribute_instance" scalar attribute_name='associated_class' $bos_meta_attribute_instance set-value "$bos_meta_attribute_instance" bos/meta/class -$bos_meta_class_meta_class_instance set-attribute-by-name 'class-name' "$bos_meta_attribute_instance" +$bos_meta_class_meta_class_instance set-attribute-by-name 'class_name' "$bos_meta_attribute_instance" ## this is the `isa` meta-attribute bos/meta/class/create-object-into bos_meta_attribute_instance bos/meta/attribute attribute_type='scalar' -associated_class='bos/meta/class' +associated_class='bos/meta/attribute' attribute_name='attribute_name' $bos_meta_attribute_instance set-value "$bos_meta_attribute_instance" 'isa' attribute_name='attribute_type' -$bos_meta_attribute_instance set-value "$bos_meta_attribute_instance" arary +$bos_meta_attribute_instance set-value "$bos_meta_attribute_instance" array attribute_name='associated_class' $bos_meta_attribute_instance set-value "$bos_meta_attribute_instance" bos/meta/class @@ -137,7 +137,7 @@ attribute_name='attribute_name' $bos_meta_attribute_instance set-value "$bos_meta_attribute_instance" 'mro' attribute_name='attribute_type' -$bos_meta_attribute_instance set-value "$bos_meta_attribute_instance" arary +$bos_meta_attribute_instance set-value "$bos_meta_attribute_instance" array attribute_name='associated_class' $bos_meta_attribute_instance set-value "$bos_meta_attribute_instance" bos/meta/class diff --git a/bos-meta-class.sh b/bos-meta-class.sh index ec3c03e..9e25b90 100644 --- a/bos-meta-class.sh +++ b/bos-meta-class.sh @@ -103,21 +103,23 @@ function bos/meta/class/find-method-into() { # that the class that this metaclass describe, actuall has that # attribute function bos/meta/class/get-attribute-by-name-into() { - local -n bos_meta_class_get_attribute_result="$1" + >&2 echo "get-attribute-by-name-into($*)" + local -n bos_meta_class_get_attribute_result="$1"; shift + local bos_meta_class_get_attribute_name="$1" local bos_meta_class_attrs_name - + # very manual method call, because I'm not sure I can make this # work otherwise local attribute_type='assoc' - local attribute_name='class-attributes' + local attribute_name='class_attributes' local associated_class='bos/meta/class' bos/meta/attribute/store-for-into bos_meta_class_attrs_name "$self" local -n bos_meta_class_attrs="$bos_meta_class_attrs_name" - bos_meta_class_get_attribute_result="${bos_meta_class_attrs[$1]}" + bos_meta_class_get_attribute_result="${bos_meta_class_attrs[$bos_meta_class_get_attribute_name]}" return 0 } @@ -129,7 +131,7 @@ function bos/meta/class/set-attribute-by-name() { # work otherwise local attribute_type='assoc' - local attribute_name='class-attributes' + local attribute_name='class_attributes' local associated_class='bos/meta/class' bos/meta/attribute/store-for-into bos_meta_class_attrs_name "$self" @@ -144,10 +146,10 @@ function bos/meta/class/set-attribute-by-name() { function bos/meta/class/find-attribute-into() { local -n bos_meta_class_find_attribute_result="$1" - local class="$2" - local attribute_name="$4" + local bos_meta_class_find_attribute_class="$2" + local bos_meta_class_find_attribute_attribute_name="$3" - local mro_store; $self mro-for-into mro_store "$class" + local mro_store; $self mro-for-into mro_store "$bos_meta_class_find_attribute_class" local -n mro="$mro_store" # minimal MRO: the class itself @@ -161,7 +163,7 @@ function bos/meta/class/find-attribute-into() { 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" + $bos_meta_class_for_class get-attribute-by-name-into bos_meta_class_find_attribute_result "$bos_meta_class_find_attribute_attribute_name" if [[ -n "$bos_meta_class_find_attribute_result" ]]; then return 0 @@ -175,19 +177,19 @@ function bos/meta/class/find-attribute-into() { # the method dispatcher function bos/meta/class/invoke() { - local class="$1";shift - local object_id="$1";shift - local method="$1";shift + local bos_invoke_class="$1";shift + local bos_invoke_object_id="$1";shift + local bos_invoke_method="$1";shift - local start_from_class='' + local bos_invoke_start_from_class='' - if [[ "$method" == 'next/method' ]]; then + if [[ "$bos_invoke_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-dispatch/caller-into caller - method="${caller##*/}" - start_from_class="${caller%/*}" + local bos_invoke_caller; bos-dispatch/caller-into bos_invoke_caller + bos_invoke_method="${bos_invoke_caller##*/}" + bos_invoke_start_from_class="${bos_invoke_caller%/*}" fi # get the first class that defines the method @@ -196,12 +198,34 @@ function bos/meta/class/invoke() { # 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 "$ffsname" "$class" "$start_from_class" "$method" + $self find-method-into "$ffsname" "$bos_invoke_class" "$bos_invoke_start_from_class" "$bos_invoke_method" + + local bos_invoke_attrs_attr + $self find-attribute-into bos_invoke_attrs_attr "$bos_invoke_class" 'class_attributes' + + if [[ -n "$bos_invoke_attrs_attr" ]]; then + local -A bos_invoke_attrs + $bos_invoke_attrs_attr get-value-into bos_invoke_attrs "$self" - # TODO: make the fields accessible! + local bos_invoke_attr_name bos_invoke_attr_obj bos_invoke_attr_type + for bos_invoke_attr_name in "${!bos_invoke_attrs[@]}"; do + bos_invoke_attr_obj="${bos_invoke_attrs[$bos_invoke_attr_name]}" + + >&2 echo "getting attribute type from $bos_invoke_attr_name=($bos_invoke_attr_obj)" + $bos_invoke_attr_obj get-attribute-type-into bos_invoke_attr_type + + case "$bos_invoke_attr_type" in + scalar) local "$bos_invoke_attr_name" ;; + array) local -a "$bos_invoke_attr_name" ;; + assoc) local -A "$bos_invoke_attr_name" ;; + esac + + $bos_invoke_attr_obj get-value-into "$bos_invoke_attr_name" + done + fi local self - bos-object-id/pack-self-into self "$class" "$object_id" + bos-object-id/pack-self-into self "$bos_invoke_class" "$bos_invoke_object_id" # call it eval "\"\$$ffsname\" \"\$@\"" |