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

1.7       paf         1: /**    @file
                      2:        Parser: @b class parser class impl.
1.1       paf         3: 
1.56      moko        4:        Copyright (c) 2001-2017 Art. Lebedev Studio (http://www.artlebedev.com)
1.7       paf         5:        Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
1.1       paf         6: */
                      7: 
1.45      moko        8: #include "pa_vclass.h"
1.48      moko        9: #include "pa_vobject.h"
1.7       paf        10: 
1.59    ! moko       11: volatile const char * IDENT_PA_VCLASS_C="$Id: pa_vclass.C,v 1.58 2018/01/18 23:06:51 moko Exp $" IDENT_PA_VCLASS_H;
1.55      moko       12: 
                     13: #ifdef OBJECT_PROTOTYPE
                     14:        bool VClass::prototype = true;
                     15: #endif
1.1       paf        16: 
1.39      misha      17: Property& VClass::get_property(const String& aname) {
1.40      misha      18:        Property* result=ffields.get(aname);
                     19:        if (result) {
1.39      misha      20:                if (!result->getter && !result->setter) {
1.59    ! moko       21:                        // replacing field with property
        !            22:                        result=new Property();
        !            23:                } else {
        !            24:                        // cloning existing property to avoid ancestor modification
        !            25:                        result=new Property(*result);
1.39      misha      26:                }
1.24      paf        27:        } else {
1.59    ! moko       28:                // creating new property
1.39      misha      29:                result=new Property();
1.24      paf        30:        }
1.40      misha      31:        ffields.put(aname, result);
1.24      paf        32:        return *result;
                     33: }
                     34: 
1.41      misha      35: void VClass::real_set_method(const String& aname, Method* amethod) {
1.35      misha      36:        if(aname.starts_with("GET_")){
1.36      misha      37:                if(aname=="GET_DEFAULT")
1.40      misha      38:                        set_default_getter(amethod);
1.35      misha      39:                else
1.40      misha      40:                        get_property(aname.mid(4, aname.length())).getter=amethod;
1.36      misha      41:        } else if(aname.starts_with("SET_")){
1.44      moko       42:                if(aname=="SET_DEFAULT")
                     43:                        set_default_setter(amethod);
                     44:                else
                     45:                        get_property(aname.mid(4, aname.length())).setter=amethod;
1.36      misha      46:        } else if(aname=="GET"){
1.40      misha      47:                set_scalar(amethod);
1.36      misha      48:        }
                     49: 
1.41      misha      50:        // NOT under 'else' for backward compatiblilty: 
1.25      paf        51:        // if someone used get_xxx names to name regular methods
1.24      paf        52:        // still register method:
1.41      misha      53:        VStateless_class::real_set_method(aname, amethod);
1.39      misha      54: }
                     55: 
                     56: void VClass::set_base(VStateless_class* abase){
                     57:        VStateless_class::set_base(abase);
1.51      moko       58:        if(abase) {
1.42      misha      59:                if(HashStringProperty *props=abase->get_properties())
1.39      misha      60:                        ffields.merge_dont_replace(*props);
1.51      moko       61:                else
1.42      misha      62:                        throw Exception("parser.compile",
                     63:                                0,
1.54      moko       64:                                "Class %s base class (%s) is not user-defined", type(), abase->type());
1.51      moko       65:        }
1.39      misha      66: }
                     67: 
                     68: Value* VClass::as(const char* atype) {
                     69:        Value* result=Value::as(atype);
                     70:        return result!=0 ? result : fbase ? fbase->as(atype) : 0;
1.11      paf        71: }
                     72: 
1.22      paf        73: /// VClass: $CLASS, (field/property)=STATIC value;(method)=method_ref with self=object_class
1.39      misha      74: Value* VClass::get_element(Value& aself, const String& aname) {
1.22      paf        75:        // simple things first: $field=static field/property
1.43      misha      76:        if(Property* prop=ffields.get(aname)) {
                     77:                if(prop->getter)
1.39      misha      78:                        return new VJunction(aself, prop->getter, true /*is_getter*/);
1.35      misha      79: 
1.46      moko       80:                if(prop->setter){
                     81:                        if(Value *result=get_default_getter(aself, aname))
                     82:                                return result;
                     83:                        throw Exception(PARSER_RUNTIME, 0, "this property has no getter method (@GET_%s[])", aname.cstr());
                     84:                }
1.39      misha      85:                 
                     86:                // just field, can be 0 as we don't remove 
                     87:                return prop->value;
1.21      paf        88:        }
                     89: 
1.14      paf        90:        // $CLASS, $method, or other base element
1.43      misha      91:        if(Value* result=VStateless_class::get_element(aself, aname))
1.39      misha      92:                return result;
1.7       paf        93: 
1.35      misha      94:        // no field or method found: looking for default getter
1.44      moko       95:        return get_default_getter(aself, aname);
1.7       paf        96: }
                     97: 
1.43      misha      98: static void add_field(
                     99:                HashStringProperty::key_type key, 
                    100:                HashStringProperty::value_type prop,
                    101:                HashStringValue* result
                    102: ){
                    103:        if(prop->value)
                    104:                result->put(key, prop->value);
                    105: }
                    106: 
1.47      misha     107: HashStringValue* VClass::get_hash() {
1.43      misha     108:        HashStringValue* result=new HashStringValue();
                    109:        ffields.for_each(add_field, result);
                    110:        return result;
                    111: }
                    112: 
1.25      paf       113: /// VClass: (field/property)=value - static values only
1.48      moko      114: const VJunction* VClass::put_element(Value& aself, const String& aname, Value* avalue) {
1.40      misha     115:        if(Property* prop=ffields.get(aname)) {
1.39      misha     116:                if (prop->setter)
                    117:                        return new VJunction(aself, prop->setter);
1.29      paf       118: 
1.46      moko      119:                if(prop->getter){
                    120:                        if(VJunction *result=get_default_setter(aself, aname))
                    121:                                return result;
1.58      moko      122: #ifdef CLASS_GETTER_UNPROTECTED
                    123:                        prop->getter=0;
                    124: #else
1.46      moko      125:                        throw Exception(PARSER_RUNTIME, 0, "this property has no setter method (@SET_%s[value])", aname.cstr());
1.58      moko      126: #endif
1.46      moko      127:                }
1.39      misha     128:                
                    129:                // just field, value can be 0 and unlike usual we don't remove it
                    130:                prop->value=avalue;
1.49      moko      131:                return PUT_ELEMENT_REPLACED_ELEMENT;
1.39      misha     132:        } else {
1.49      moko      133:                if(VJunction *result=get_default_setter(aself, aname))
                    134:                        return result;
                    135: 
1.40      misha     136:                prop=new Property();
                    137:                prop->value=avalue;
                    138:                ffields.put(aname, prop);
                    139: 
                    140:                Array_iterator<VStateless_class *> i(fderived);
                    141:                while(i.has_next()) {
                    142:                        HashStringProperty *props=i.next()->get_properties();
                    143:                        if(props)
                    144:                                props->put_dont_replace(aname, prop);
                    145:                }
1.39      misha     146:        }
1.49      moko      147:        return 0;
1.7       paf       148: }
                    149: 
1.48      moko      150: /// part of put_element
                    151: const VJunction* VClass::put_element_replace_only(Value& aself, const String& aname, Value* avalue) {
                    152:        if(Property* prop=ffields.get(aname)) {
                    153:                if (prop->setter)
                    154:                        return new VJunction(aself, prop->setter);
1.55      moko      155: #ifdef OBJECT_PROTOTYPE
                    156:                if(!prototype)
                    157: #endif
                    158:                {
1.57      moko      159:                        if(prop->getter){
                    160:                                if(VJunction *result=get_default_setter(aself, aname))
                    161:                                        return result;
                    162:                                throw Exception(PARSER_RUNTIME, 0, "this property has no setter method (@SET_%s[value])", aname.cstr());
                    163:                        }
1.55      moko      164:                        // just field, value can be 0 and unlike usual we don't remove it
                    165:                        prop->value=avalue;
                    166:                        return PUT_ELEMENT_REPLACED_ELEMENT;
                    167:                }
1.48      moko      168:        }
                    169:        return 0;
                    170: }
                    171: 
1.7       paf       172: /// @returns object of this class
1.39      misha     173: Value* VClass::create_new_value(Pool&) { 
                    174:        return new VObject(*this);
1.1       paf       175: }
1.50      misha     176: 
                    177: const String* VClass::get_json_string(Json_options& options){
                    178:        if(options.default_method){
                    179:                return default_method_2_json_string(*options.default_method, options);
                    180:        }
1.52      moko      181:        return options.hash_json_string(get_hash());
1.50      misha     182: }

E-mail: