Annotation of parser3/src/types/pa_vclass.C, revision 1.25

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.25    ! paf         8: static const char * const IDENT_VCLASS_C="$Date: 2005/07/25 09:39:54 $";
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.24      paf        33:        if(aname.starts_with("get_"))
                     34:                add_property(aname).getter=&amethod;
1.25    ! 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.17      paf        52: Value* VClass::get_element(const String& aname, Value& aself, bool looking_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,
                     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.17      paf        68:        if(Value* result=VStateless_class::get_element(aname, aself, looking_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.25    ! paf        74: static const Method* prevent_overwrite_property(Value* value) {
        !            75:        if(Property* property=value->get_property()) {
        !            76:                if(Method* result=property->setter)
        !            77:                        return result;
        !            78:                
        !            79:                throw Exception("parser.runtime",
        !            80:                        0,
        !            81:                        "this property has no setter method (is read-only)");
        !            82:        }
        !            83: 
        !            84:        return 0;
        !            85: }
        !            86: 
        !            87: /// VClass: (field/property)=value - static values only
        !            88: const Junction* VClass::put_element(const String& aname, Value* avalue, bool /*replace TODO: maybe remove?*/) {
1.7       paf        89:        try {
1.25    ! paf        90:                if(fbase)
        !            91:                        if(const Junction* result=fbase->put_element(aname, avalue, true))
        !            92:                                return result; // replaced in base
1.10      paf        93:        } catch(Exception) {  /* allow override parent variables, useful for form descendants */ }
1.7       paf        94: 
1.25    ! paf        95:        if(const Method* method=ffields.maybe_put<const Method*>(aname, avalue, prevent_overwrite_property) ) {
        !            96:                if(method==reinterpret_cast<Method*>(1)) // existed, but not were not property?
        !            97:                        return PUT_ELEMENT_REPLACED_ELEMENT;
        !            98:                return new Junction(*this, method, true /*is_setter*/);
1.7       paf        99:        }
1.25    ! paf       100: 
        !           101:        return 0; // were simply added [not existed before]
1.7       paf       102: }
                    103: 
                    104: /// @returns object of this class
1.18      paf       105: Value* VClass::create_new_value(Pool& apool) { 
                    106:        return new VObject(apool, *this);
1.1       paf       107: }

E-mail: