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

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

E-mail: