Annotation of parser3/src/types/pa_vclass.C, revision 1.27.2.7
1.7 paf 1: /** @file
2: Parser: @b class parser class impl.
1.1 paf 3:
1.20 paf 4: Copyright (c) 2001-2004 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.27.2.7! paf 8: static const char * const IDENT_VCLASS_C="$Date: 2005/07/27 14:25:27 $";
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.24 paf 31: void VClass::add_method(const String& aname, Method& amethod)
1.22 paf 32: {
1.27.2.6 paf 33: if(aname.starts_with("GET_"))
1.24 paf 34: add_property(aname).getter=&amethod;
1.27.2.6 paf 35: else if(aname.starts_with("SET_") )
1.24 paf 36: add_property(aname).setter=&amethod;
1.25 paf 37:
38: // NOT under 'else' for backward compatiblilty:
39: // if someone used get_xxx names to name regular methods
1.24 paf 40: // still register method:
41: VStateless_class::add_method(aname, amethod);
1.22 paf 42: }
43:
1.17 paf 44: Value* VClass::as(const char* atype, bool looking_up) {
45: if(Value* result=Value::as(atype, looking_up))
1.12 paf 46: return result;
1.11 paf 47: else
1.12 paf 48: return fbase?fbase->as(atype, looking_up):0;
1.11 paf 49: }
50:
1.22 paf 51: /// VClass: $CLASS, (field/property)=STATIC value;(method)=method_ref with self=object_class
1.27.2.2 paf 52: Value* VClass::get_element(const String& aname, Value& aself, bool alooking_up) {
1.22 paf 53: // simple things first: $field=static field/property
54: if(Value* result=ffields.get(aname)) {
1.25 paf 55: if(Property* prop=result->get_property()) { // it is property?
1.22 paf 56: Method* method=prop->getter;
57: if(!method)
58: throw Exception("parser.runtime",
59: &aname,
1.27.2.7! paf 60: "this property has no getter method (GET_%s)", aname.cstr());
1.21 paf 61:
1.22 paf 62: return new VJunction(new Junction(aself, method, true /*is_getter*/));
63: }
1.21 paf 64: return result;
65: }
66:
1.14 paf 67: // $CLASS, $method, or other base element
1.27.2.2 paf 68: if(Value* result=VStateless_class::get_element(aname, aself, alooking_up))
1.22 paf 69: 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.7 paf 70:
71: return 0;
72: }
73:
1.27.2.4 paf 74: const Junction* VClass::prevent_overwrite_property(Value* value, Prevent_info* info) {
1.25 paf 75: if(Property* property=value->get_property()) {
1.27.2.4 paf 76: if(Method* setter=property->setter)
77: return new Junction(*info->self, setter);
1.25 paf 78:
79: throw Exception("parser.runtime",
80: 0,
81: "this property has no setter method (is read-only)");
82: }
83:
84: return 0;
85: }
1.27.2.4 paf 86: const Junction* VClass::prevent_append_if_exists_in_base(Value* value, Prevent_info* info) {
87: if(VStateless_class* cbase=info->_this->fbase) {
88: // VObject must have .base()!=0 of type VObject [contains parent OBJECT (not class)]
89: Value* obase=info->self->base();
1.27.2.2 paf 90: assert(obase);
1.27.2.7! paf 91: if(const Junction* result=cbase->put_element(*obase, *info->name, value, true/*try to replace! NEVER overwrite*/))
1.27.2.2 paf 92: return result; // replaced in base
1.7 paf 93: }
1.27.2.3 paf 94:
95: return 0;
1.27.2.4 paf 96: }
97: /// VClass: (field/property)=value - static values only
1.27.2.7! paf 98: const Junction* VClass::put_element(Value& aself, const String& aname, Value* avalue, bool areplace) {
1.27.2.4 paf 99: Prevent_info info={this, &aself, &aname};
1.27.2.7! paf 100: if(areplace)
! 101: return ffields.maybe_replace_never_append<const Junction*>(aname, avalue,
! 102: prevent_overwrite_property,
! 103: &info);
! 104: else // append if not existed neither in fields nor in base classes
! 105: return ffields.maybe_replace_maybe_append<const Junction*>(aname, avalue,
! 106: prevent_overwrite_property,
! 107: prevent_append_if_exists_in_base,
! 108: &info);
1.7 paf 109: }
110:
111: /// @returns object of this class
1.27.2.1 paf 112: Value* VClass::create_new_value(Pool& apool, HashStringValue& afields) {
113: return new VObject(apool, *this, afields);
1.1 paf 114: }
E-mail: