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: