Annotation of parser3/src/types/pa_vclass.C, revision 1.35

1.7       paf         1: /**    @file
                      2:        Parser: @b class parser class impl.
1.1       paf         3: 
1.33      paf         4:        Copyright (c) 2001-2005 ArtLebedev Group (http://www.artlebedev.com)
1.7       paf         5:        Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
1.1       paf         6: */
                      7: 
1.35    ! misha       8: static const char * const IDENT_VCLASS_C="$Date: 2007/04/23 10:30:49 $";
1.7       paf         9: 
1.1       paf        10: #include "pa_vclass.h"
                     11: 
1.24      paf        12: Property& VClass::add_property(const String& aname) {
                     13:        String prop_name=aname.mid(4, aname.length());
                     14:        
                     15:        Property* result;
                     16:        if(Value* value=ffields.get(prop_name)) {
                     17:                result=value->get_property();
                     18:                if(!result) // can occur in ^process
                     19:                        throw Exception("parser.compile",
                     20:                                &prop_name,
                     21:                                "property can not be created, already exists field (%s) with that name", value->get_class()->name_cstr());
                     22:        } else {
                     23:                VProperty* vproperty=new VProperty();
                     24:                ffields.put(prop_name, vproperty);
                     25:                result=&vproperty->get();
                     26:        }
                     27:        return *result;
                     28: }
                     29: 
1.22      paf        30: /// preparing property accessors to fields
1.35    ! misha      31: void VClass::add_method(const String& aname, Method& amethod) {
        !            32:        if(aname.starts_with("GET_")){
        !            33:                if(aname == "GET_DEFAULT")
        !            34:                        set_default_getter(&amethod);
        !            35:                else
        !            36:                        add_property(aname).getter=&amethod;
        !            37:        } else if(aname.starts_with("SET_") )
1.24      paf        38:                add_property(aname).setter=&amethod;
1.25      paf        39:        
                     40:        // NOT under 'else' for backward compatiblilty: 
                     41:        // if someone used get_xxx names to name regular methods
1.24      paf        42:        // still register method:
                     43:        VStateless_class::add_method(aname, amethod);
1.22      paf        44: }
                     45: 
1.17      paf        46: Value* VClass::as(const char* atype, bool looking_up) {
                     47:        if(Value* result=Value::as(atype, looking_up))
1.12      paf        48:                return result;
1.11      paf        49:        else
1.12      paf        50:                return fbase?fbase->as(atype, looking_up):0;
1.11      paf        51: }
                     52: 
1.22      paf        53: /// VClass: $CLASS, (field/property)=STATIC value;(method)=method_ref with self=object_class
1.28      paf        54: Value* VClass::get_element(const String& aname, Value& aself, bool alooking_up) {
1.30      paf        55:        bool property_but_no_getter_in_self=false;
                     56: 
1.22      paf        57:        // simple things first: $field=static field/property
                     58:        if(Value* result=ffields.get(aname)) {
1.35    ! misha      59:                Property* prop=result->get_property();
        !            60: 
        !            61:                if(!prop) // just field, not a property
        !            62:                        return result;
        !            63: 
        !            64:                if(Method* method=prop->getter) // has getter
        !            65:                        return new VJunction(aself, method, true /*is_getter*/);
        !            66: 
        !            67:                property_but_no_getter_in_self=true;
1.21      paf        68:        }
                     69: 
1.14      paf        70:        // $CLASS, $method, or other base element
1.35    ! misha      71:        if(Value* result=VStateless_class::get_element(aname, aself, false))
1.22      paf        72:                return result; // TODO: this can be SIGNIFICANTLY sped up by caching in ffields! [THOUGH decide about different aself] // what REALLY would speed up things is to join storage of properties/methods/fields of all vobject parents into last descenant [sort of vmt + all fields as in other langs]
1.30      paf        73: 
                     74:        if(property_but_no_getter_in_self)
1.34      misha      75:                throw Exception(PARSER_RUNTIME,
1.31      paf        76:                        0,
                     77:                        "this property has no getter method (@GET_%s[])", aname.cstr());
1.7       paf        78: 
1.35    ! misha      79:        // no field or method found: looking for default getter
        !            80:        if(alooking_up)
        !            81:                if(Value* result=get_default_getter(aself, aname))
        !            82:                        return result;
        !            83: 
1.7       paf        84:        return 0;
                     85: }
                     86: 
1.32      paf        87: #define PROPERTY_BUT_NO_SETTER_IN_SELF reinterpret_cast<const VJunction*>(2)
                     88: const VJunction* VClass::prevent_overwrite_property(Value* value, Prevent_info* info) {
1.25      paf        89:        if(Property* property=value->get_property()) {
1.28      paf        90:                if(Method* setter=property->setter)
1.32      paf        91:                        return new VJunction(*info->self, setter);
1.29      paf        92: 
                     93:                return PROPERTY_BUT_NO_SETTER_IN_SELF;
1.25      paf        94:        }
                     95: 
                     96:        return 0;
                     97: }
1.32      paf        98: const VJunction* VClass::prevent_append_if_exists_in_base(Value* value, Prevent_info* info)  {
1.28      paf        99:        if(VStateless_class* cbase=info->_this->fbase) {
1.29      paf       100:                if(Value* obase=info->self->base()) // MXdoc has fbase but does not have object_base[ base() ]
1.32      paf       101:                        if(const VJunction* result=cbase->put_element(*obase, *info->name, value, true/*try to replace! NEVER overwrite*/))
1.29      paf       102:                                return result; // replaced in base
1.28      paf       103:        }
1.25      paf       104: 
1.28      paf       105:        return 0;
                    106: }
1.25      paf       107: /// VClass: (field/property)=value - static values only
1.32      paf       108: const VJunction* VClass::put_element(Value& aself, const String& aname, Value* avalue, bool areplace) {
1.28      paf       109:        Prevent_info info={this, &aself, &aname};
1.29      paf       110:        if(areplace) {
                    111:                bool property_but_no_setter_in_self=false;
                    112:                // trying to replace it in fields/properties
1.32      paf       113:                if(const VJunction* result=ffields.maybe_replace_never_append<const VJunction*>(aname, avalue, 
1.28      paf       114:                        prevent_overwrite_property,
1.29      paf       115:                        &info))
                    116:                        if(result==PROPERTY_BUT_NO_SETTER_IN_SELF)
                    117:                                property_but_no_setter_in_self=true; // continue to find setter up the tree
                    118:                        else
                    119:                                return result; // replaced locally
                    120: 
                    121:                // if not found locally, going up the tree
                    122:                if(fbase)
                    123:                        if(Value* obase=aself.base()) // MXdoc has fbase but does not have object_base[ base() ]
1.32      paf       124:                                if(const VJunction* result=fbase->put_element(*obase, aname, avalue, true/*try to replace! NEVER overwrite*/))
1.29      paf       125:                                        return result; // replaced in base
                    126: 
                    127:                if(property_but_no_setter_in_self)
1.34      misha     128:                        throw Exception(PARSER_RUNTIME,
1.29      paf       129:                                0,
1.31      paf       130:                                "this property has no setter method (@SET_%s[value])", aname.cstr());
1.29      paf       131: 
                    132:                return 0;
                    133:        } else // append if not existed neither in fields nor in base classes
1.32      paf       134:                return ffields.maybe_replace_maybe_append<const VJunction*>(aname, avalue, 
1.28      paf       135:                        prevent_overwrite_property,
                    136:                        prevent_append_if_exists_in_base, 
                    137:                        &info);
1.7       paf       138: }
                    139: 
                    140: /// @returns object of this class
1.28      paf       141: Value* VClass::create_new_value(Pool& apool, HashStringValue& afields) { 
                    142:        return new VObject(apool, *this, afields);
1.1       paf       143: }

E-mail: