Annotation of parser3/src/types/pa_vclass.C, revision 1.35
1.7 paf 1: /** @file
2: Parser: @b class parser class impl.
1.1 paf 3:
1.33 paf 4: Copyright (c) 2001-2005 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.35 ! misha 8: static const char * const IDENT_VCLASS_C="$Date: 2007/04/23 10:30:49 $";
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_")){
! 33: if(aname == "GET_DEFAULT")
! 34: set_default_getter(&amethod);
! 35: else
! 36: add_property(aname).getter=&amethod;
! 37: } else if(aname.starts_with("SET_") )
1.24 paf 38: add_property(aname).setter=&amethod;
1.25 paf 39:
40: // NOT under 'else' for backward compatiblilty:
41: // if someone used get_xxx names to name regular methods
1.24 paf 42: // still register method:
43: VStateless_class::add_method(aname, amethod);
1.22 paf 44: }
45:
1.17 paf 46: Value* VClass::as(const char* atype, bool looking_up) {
47: if(Value* result=Value::as(atype, looking_up))
1.12 paf 48: return result;
1.11 paf 49: else
1.12 paf 50: return fbase?fbase->as(atype, looking_up):0;
1.11 paf 51: }
52:
1.22 paf 53: /// VClass: $CLASS, (field/property)=STATIC value;(method)=method_ref with self=object_class
1.28 paf 54: Value* VClass::get_element(const String& aname, Value& aself, bool alooking_up) {
1.30 paf 55: bool property_but_no_getter_in_self=false;
56:
1.22 paf 57: // simple things first: $field=static field/property
58: if(Value* result=ffields.get(aname)) {
1.35 ! misha 59: Property* prop=result->get_property();
! 60:
! 61: if(!prop) // just field, not a property
! 62: return result;
! 63:
! 64: if(Method* method=prop->getter) // has getter
! 65: return new VJunction(aself, method, true /*is_getter*/);
! 66:
! 67: property_but_no_getter_in_self=true;
1.21 paf 68: }
69:
1.14 paf 70: // $CLASS, $method, or other base element
1.35 ! misha 71: if(Value* result=VStateless_class::get_element(aname, aself, false))
1.22 paf 72: 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 73:
74: if(property_but_no_getter_in_self)
1.34 misha 75: throw Exception(PARSER_RUNTIME,
1.31 paf 76: 0,
77: "this property has no getter method (@GET_%s[])", aname.cstr());
1.7 paf 78:
1.35 ! misha 79: // no field or method found: looking for default getter
! 80: if(alooking_up)
! 81: if(Value* result=get_default_getter(aself, aname))
! 82: return result;
! 83:
1.7 paf 84: return 0;
85: }
86:
1.32 paf 87: #define PROPERTY_BUT_NO_SETTER_IN_SELF reinterpret_cast<const VJunction*>(2)
88: const VJunction* VClass::prevent_overwrite_property(Value* value, Prevent_info* info) {
1.25 paf 89: if(Property* property=value->get_property()) {
1.28 paf 90: if(Method* setter=property->setter)
1.32 paf 91: return new VJunction(*info->self, setter);
1.29 paf 92:
93: return PROPERTY_BUT_NO_SETTER_IN_SELF;
1.25 paf 94: }
95:
96: return 0;
97: }
1.32 paf 98: const VJunction* VClass::prevent_append_if_exists_in_base(Value* value, Prevent_info* info) {
1.28 paf 99: if(VStateless_class* cbase=info->_this->fbase) {
1.29 paf 100: if(Value* obase=info->self->base()) // MXdoc has fbase but does not have object_base[ base() ]
1.32 paf 101: if(const VJunction* result=cbase->put_element(*obase, *info->name, value, true/*try to replace! NEVER overwrite*/))
1.29 paf 102: return result; // replaced in base
1.28 paf 103: }
1.25 paf 104:
1.28 paf 105: return 0;
106: }
1.25 paf 107: /// VClass: (field/property)=value - static values only
1.32 paf 108: const VJunction* VClass::put_element(Value& aself, const String& aname, Value* avalue, bool areplace) {
1.28 paf 109: Prevent_info info={this, &aself, &aname};
1.29 paf 110: if(areplace) {
111: bool property_but_no_setter_in_self=false;
112: // trying to replace it in fields/properties
1.32 paf 113: if(const VJunction* result=ffields.maybe_replace_never_append<const VJunction*>(aname, avalue,
1.28 paf 114: prevent_overwrite_property,
1.29 paf 115: &info))
116: if(result==PROPERTY_BUT_NO_SETTER_IN_SELF)
117: property_but_no_setter_in_self=true; // continue to find setter up the tree
118: else
119: return result; // replaced locally
120:
121: // if not found locally, going up the tree
122: if(fbase)
123: if(Value* obase=aself.base()) // MXdoc has fbase but does not have object_base[ base() ]
1.32 paf 124: if(const VJunction* result=fbase->put_element(*obase, aname, avalue, true/*try to replace! NEVER overwrite*/))
1.29 paf 125: return result; // replaced in base
126:
127: if(property_but_no_setter_in_self)
1.34 misha 128: throw Exception(PARSER_RUNTIME,
1.29 paf 129: 0,
1.31 paf 130: "this property has no setter method (@SET_%s[value])", aname.cstr());
1.29 paf 131:
132: return 0;
133: } else // append if not existed neither in fields nor in base classes
1.32 paf 134: return ffields.maybe_replace_maybe_append<const VJunction*>(aname, avalue,
1.28 paf 135: prevent_overwrite_property,
136: prevent_append_if_exists_in_base,
137: &info);
1.7 paf 138: }
139:
140: /// @returns object of this class
1.28 paf 141: Value* VClass::create_new_value(Pool& apool, HashStringValue& afields) {
142: return new VObject(apool, *this, afields);
1.1 paf 143: }
E-mail: