Annotation of parser3/src/types/pa_vclass.C, revision 1.37
1.7 paf 1: /** @file
2: Parser: @b class parser class impl.
1.1 paf 3:
1.37 ! misha 4: Copyright (c) 2001-2009 ArtLebedev Group (http://www.artlebedev.com)
1.7 paf 5: Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
1.1 paf 6: */
7:
1.37 ! misha 8: static const char * const IDENT_VCLASS_C="$Date: 2008-06-16 12:42:20 $";
1.7 paf 9:
1.1 paf 10: #include "pa_vclass.h"
11:
1.24 paf 12: Property& VClass::add_property(const String& aname) {
13: String prop_name=aname.mid(4, aname.length());
14:
15: Property* result;
16: if(Value* value=ffields.get(prop_name)) {
17: result=value->get_property();
18: if(!result) // can occur in ^process
19: throw Exception("parser.compile",
20: &prop_name,
21: "property can not be created, already exists field (%s) with that name", value->get_class()->name_cstr());
22: } else {
23: VProperty* vproperty=new VProperty();
24: ffields.put(prop_name, vproperty);
25: result=&vproperty->get();
26: }
27: return *result;
28: }
29:
1.22 paf 30: /// preparing property accessors to fields
1.35 misha 31: void VClass::add_method(const String& aname, Method& amethod) {
32: if(aname.starts_with("GET_")){
1.36 misha 33: if(aname=="GET_DEFAULT")
1.35 misha 34: set_default_getter(&amethod);
35: else
36: add_property(aname).getter=&amethod;
1.36 misha 37: } else if(aname.starts_with("SET_")){
1.24 paf 38: add_property(aname).setter=&amethod;
1.36 misha 39: } else if(aname=="GET"){
40: set_scalar(&amethod);
41: }
42:
43:
1.25 paf 44: // NOT under 'else' for backward compatiblilty:
45: // if someone used get_xxx names to name regular methods
1.24 paf 46: // still register method:
47: VStateless_class::add_method(aname, amethod);
1.22 paf 48: }
49:
1.17 paf 50: Value* VClass::as(const char* atype, bool looking_up) {
51: if(Value* result=Value::as(atype, looking_up))
1.12 paf 52: return result;
1.11 paf 53: else
1.12 paf 54: return fbase?fbase->as(atype, looking_up):0;
1.11 paf 55: }
56:
1.22 paf 57: /// VClass: $CLASS, (field/property)=STATIC value;(method)=method_ref with self=object_class
1.28 paf 58: Value* VClass::get_element(const String& aname, Value& aself, bool alooking_up) {
1.30 paf 59: bool property_but_no_getter_in_self=false;
60:
1.22 paf 61: // simple things first: $field=static field/property
62: if(Value* result=ffields.get(aname)) {
1.35 misha 63: Property* prop=result->get_property();
64:
65: if(!prop) // just field, not a property
66: return result;
67:
68: if(Method* method=prop->getter) // has getter
69: return new VJunction(aself, method, true /*is_getter*/);
70:
71: property_but_no_getter_in_self=true;
1.21 paf 72: }
73:
1.14 paf 74: // $CLASS, $method, or other base element
1.35 misha 75: if(Value* result=VStateless_class::get_element(aname, aself, false))
1.37 ! misha 76: return result; // @TODO: this can be SIGNIFICANTLY sped up by caching in ffields! [THOUGH decide about different aself] // what REALLY would speed up things is to join storage of properties/methods/fields of all vobject parents into last descenant [sort of vmt + all fields as in other langs]
1.30 paf 77:
78: if(property_but_no_getter_in_self)
1.34 misha 79: throw Exception(PARSER_RUNTIME,
1.31 paf 80: 0,
81: "this property has no getter method (@GET_%s[])", aname.cstr());
1.7 paf 82:
1.35 misha 83: // no field or method found: looking for default getter
84: if(alooking_up)
85: if(Value* result=get_default_getter(aself, aname))
86: return result;
87:
1.7 paf 88: return 0;
89: }
90:
1.32 paf 91: #define PROPERTY_BUT_NO_SETTER_IN_SELF reinterpret_cast<const VJunction*>(2)
92: const VJunction* VClass::prevent_overwrite_property(Value* value, Prevent_info* info) {
1.25 paf 93: if(Property* property=value->get_property()) {
1.28 paf 94: if(Method* setter=property->setter)
1.32 paf 95: return new VJunction(*info->self, setter);
1.29 paf 96:
97: return PROPERTY_BUT_NO_SETTER_IN_SELF;
1.25 paf 98: }
99:
100: return 0;
101: }
1.32 paf 102: const VJunction* VClass::prevent_append_if_exists_in_base(Value* value, Prevent_info* info) {
1.28 paf 103: if(VStateless_class* cbase=info->_this->fbase) {
1.29 paf 104: if(Value* obase=info->self->base()) // MXdoc has fbase but does not have object_base[ base() ]
1.32 paf 105: if(const VJunction* result=cbase->put_element(*obase, *info->name, value, true/*try to replace! NEVER overwrite*/))
1.29 paf 106: return result; // replaced in base
1.28 paf 107: }
1.25 paf 108:
1.28 paf 109: return 0;
110: }
1.25 paf 111: /// VClass: (field/property)=value - static values only
1.32 paf 112: const VJunction* VClass::put_element(Value& aself, const String& aname, Value* avalue, bool areplace) {
1.28 paf 113: Prevent_info info={this, &aself, &aname};
1.29 paf 114: if(areplace) {
115: bool property_but_no_setter_in_self=false;
116: // trying to replace it in fields/properties
1.32 paf 117: if(const VJunction* result=ffields.maybe_replace_never_append<const VJunction*>(aname, avalue,
1.28 paf 118: prevent_overwrite_property,
1.29 paf 119: &info))
120: if(result==PROPERTY_BUT_NO_SETTER_IN_SELF)
121: property_but_no_setter_in_self=true; // continue to find setter up the tree
122: else
123: return result; // replaced locally
124:
125: // if not found locally, going up the tree
126: if(fbase)
127: if(Value* obase=aself.base()) // MXdoc has fbase but does not have object_base[ base() ]
1.32 paf 128: if(const VJunction* result=fbase->put_element(*obase, aname, avalue, true/*try to replace! NEVER overwrite*/))
1.29 paf 129: return result; // replaced in base
130:
131: if(property_but_no_setter_in_self)
1.34 misha 132: throw Exception(PARSER_RUNTIME,
1.29 paf 133: 0,
1.31 paf 134: "this property has no setter method (@SET_%s[value])", aname.cstr());
1.29 paf 135:
136: return 0;
137: } else // append if not existed neither in fields nor in base classes
1.32 paf 138: return ffields.maybe_replace_maybe_append<const VJunction*>(aname, avalue,
1.28 paf 139: prevent_overwrite_property,
140: prevent_append_if_exists_in_base,
141: &info);
1.7 paf 142: }
143:
144: /// @returns object of this class
1.28 paf 145: Value* VClass::create_new_value(Pool& apool, HashStringValue& afields) {
146: return new VObject(apool, *this, afields);
1.1 paf 147: }
E-mail: