Annotation of parser3/src/types/pa_vclass.C, revision 1.65
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.65 ! moko 11: volatile const char * IDENT_PA_VCLASS_C="$Id: pa_vclass.C,v 1.64 2024/09/07 15:01:38 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.65 ! moko 143: for(ArrayClass::Iterator i(fderived); i; ) {
1.40 misha 144: HashStringProperty *props=i.next()->get_properties();
145: if(props)
146: props->put_dont_replace(aname, prop);
147: }
1.39 misha 148: }
1.49 moko 149: return 0;
1.7 paf 150: }
151:
1.48 moko 152: /// part of put_element
153: const VJunction* VClass::put_element_replace_only(Value& aself, const String& aname, Value* avalue) {
154: if(Property* prop=ffields.get(aname)) {
155: if (prop->setter)
156: return new VJunction(aself, prop->setter);
1.55 moko 157: #ifdef OBJECT_PROTOTYPE
158: if(!prototype)
159: #endif
160: {
1.57 moko 161: if(prop->getter){
162: if(VJunction *result=get_default_setter(aself, aname))
163: return result;
164: throw Exception(PARSER_RUNTIME, 0, "this property has no setter method (@SET_%s[value])", aname.cstr());
165: }
1.55 moko 166: // just field, value can be 0 and unlike usual we don't remove it
167: prop->value=avalue;
1.60 moko 168: return PUT_ELEMENT_REPLACED_FIELD;
1.55 moko 169: }
1.48 moko 170: }
171: return 0;
172: }
173:
1.7 paf 174: /// @returns object of this class
1.39 misha 175: Value* VClass::create_new_value(Pool&) {
176: return new VObject(*this);
1.1 paf 177: }
1.50 misha 178:
179: const String* VClass::get_json_string(Json_options& options){
180: if(options.default_method){
181: return default_method_2_json_string(*options.default_method, options);
182: }
1.52 moko 183: return options.hash_json_string(get_hash());
1.50 misha 184: }
E-mail: