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

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

E-mail: