Annotation of parser3/src/main/core.C, revision 1.11

1.10      paf         1: enum Prefix {
                      2:        NO_PREFIX,
                      3:        ROOT_PREFIX,
                      4:        SELF_PREFIX
                      5: };
                      6: 
                      7: enum CHAR_TYPE {
                      8:        NO_TYPE=0, // these got skipped by String::skip_to
1.11    ! paf         9:        VAR_START_TYPE,
        !            10:        METHOD_START_TYPE,
        !            11:        STOP_TYPE,///=-1 // same as EOF type(-1), see String::skip_to
        !            12:        DOT_TYPE,
        !            13:        COLON_TYPE,
        !            14:        CONSTRUCTOR_BODY_START_TYPE,
        !            15:        CONSTRUCTOR_BODY_FINISH_TYPE,
        !            16:        BLOCK_START_TYPE,
        !            17:        BLOCK_FINISH_TYPE,
        !            18:        
        !            19:        Z_TYPE
1.10      paf        20: };
                     21: 
1.11    ! paf        22: Char_types var_or_method_start;
        !            23: Char_types var_or_method_start_or_constructor_stop;
        !            24: Char_types var_or_method_start_or_block_stop;
        !            25: Char_types common_names_breaks, var_names_breaks, method_names_breaks;
1.10      paf        26: 
                     27: void prepare() {
1.11    ! paf        28:        var_or_method_start.set('$', VAR_START_TYPE);
        !            29:        var_or_method_start.set('^', METHOD_START_TYPE);
        !            30: 
        !            31:        var_or_method_start_or_constructor_stop=var_or_method_start;
        !            32:        var_or_method_start_or_constructor_stop.set(')', STOP_TYPE);
        !            33: 
        !            34:        var_or_method_start_or_block_stop=var_or_method_start;
        !            35:        var_or_method_start_or_block_stop.set(']', STOP_TYPE);
        !            36: 
        !            37:        common_names_breaks.set(0, ' ', STOP_TYPE);
        !            38:        common_names_breaks.set('.', DOT_TYPE);
        !            39:        common_names_breaks.set(':', COLON_TYPE);
        !            40:        common_names_breaks.set(')', STOP_TYPE); // var_or_method_start_or_constructor_stop
        !            41:        common_names_breaks.set(']', STOP_TYPE); // var_or_method_start_or_block_stop
        !            42: 
        !            43:        var_names_breaks=common_names_breaks;
        !            44:        var_names_breaks.set('(', CONSTRUCTOR_BODY_START_TYPE);
        !            45: 
        !            46:        method_names_breaks=common_names_breaks;
        !            47:        method_names_breaks.set('[', BLOCK_START_TYPE);
1.10      paf        48: }
                     49: 
1.7       paf        50: void process(method_self_n_params_n_locals& root, Value& self,
                     51:                         arcontext& arcontext, WContext& awcontext, 
1.10      paf        52:                         String_iterator& iter, Char_types& breaks) {
                     53:        while(!iter.eof()) {
                     54:                String_iterator start(iter);
                     55:                CHAR_TYPE type=iter.skip_to(breaks);
                     56:                awcontext.write(start, iter);
                     57: 
                     58:                switch(type) {
1.11    ! paf        59:                case VAR_START_TYPE: 
        !            60:                        process_var(root, self, arcontext, awcontext, iter, breaks);
1.10      paf        61:                        break;
1.11    ! paf        62:                case METHOD_START_TYPE:
        !            63:                        process_method(root, self, arcontext, awcontext, iter, breaks);
1.10      paf        64:                        break;
                     65:                case STOP_TYPE:
                     66:                        return;
                     67:                }
                     68:        }
1.1       paf        69: }
                     70: 
1.11    ! paf        71: void process_var(method_self_n_params_n_locals& root, Value& self,
        !            72:                                 arcontext& arcontext, WContext& awcontext, 
        !            73:                                 String_iterator& iter, Char_types& breaks) {
1.1       paf        74: 
                     75:        // $name.field.subfield -- read
                     76:        // $name.field.subfield(constructor code) -- construct
                     77:        // $name.field.subfield[usage code & if none existed autoconstructed as VHash] -- use OR auto-VHash construct
                     78:        
1.11    ! paf        79:        Prefix prefix;
1.1       paf        80:        Array/*<String&>*/ names(pool);  // what.they.refer.to left-to-right list
1.11    ! paf        81:        CHAR_TYPE names_ended_before; // the char type after long name
1.1       paf        82:        get_names(
1.11    ! paf        83:                iter, var_names_breaks,
1.6       paf        84:                &prefix, &names, &names_ended_before); // can return count()=0 when $self alone
1.1       paf        85: 
                     86:        bool read_mode=name_ended_before==' ';
1.6       paf        87:        Value *context=
                     88:                prefix?
1.8       paf        89:                        prefix==ROOT_PREFIX?root:self:
1.7       paf        90:                read_mode?arcontext:awcontext;
1.1       paf        91:        
                     92:        if(read_mode) {
1.3       paf        93:                // 'context' dive into dotted path
1.1       paf        94:                for(int i=0; i<names.count(); i++) {
                     95:                        context=context->get_element(static_cast<Value *>(names.get[i]));
                     96:                        if(!context) // no such object field, nothing bad, just ignore that
                     97:                                return;
                     98:                }
1.7       paf        99:                awcontext.write(context);
1.1       paf       100:        } else { // write mode
                    101:                iter++; // skip '(' '['
                    102: 
                    103:                bool construct_mode=names_ended_before=='(';
                    104: 
1.4       paf       105:                // 'context' dive into dotted path, 
1.1       paf       106:                int steps=names.count();
1.4       paf       107:                // if constructing then "excluding last .name"
1.1       paf       108:                if(construct_mode)
1.6       paf       109:                        if(!steps--) // bad: "$self("; now we can safely do ".get[steps]" below
                    110:                                pool.exception().raise("self re-construction prohibited");
1.1       paf       111:                for(int i=0; i<steps; i++) {
                    112:                        String& name=static_cast<String&>(names.get[i]);
                    113:                        Value *next_current=context->get_element(name);
                    114:                        if(next_current)
                    115:                                next_current=context->put_element(name, new(pool) VHash(pool));
                    116:                        context=new_current;
                    117:                }
                    118: 
                    119:                if(construct_mode) {  
1.7       paf       120:                        // .name(construct-code), processing on arcontext in empty temp awcontext
                    121:                        // pure side effect, no awcontext.write here
1.3       paf       122:                        // last .name
1.1       paf       123:                        String& name=static_cast<String&>(names.get[steps]);
                    124:                        WContext local_wcontext(pool /* empty */);
1.7       paf       125:                        process(root, self, arcontext, local_wcontext, iter, ')');
1.1       paf       126:                        context->put_element(name, local_wcontext.value());
                    127:                } else { // =='['
1.3       paf       128:                        // .name[with-code], processing on 'context'
1.1       paf       129:                        WContext local_context(pool, context);
1.6       paf       130:                        process(root, self, local_context, local_context, iter, ']');
1.7       paf       131:                        awcontext.write(local_context);
1.1       paf       132:                }
                    133:                
                    134:                iter++; // skip ')' ']'
                    135:        }
                    136: }
                    137: 
1.11    ! paf       138: void process_method(method_self_n_params_n_locals& root, Value& self,
        !           139:                                        arcontext& arcontext, WContext& awcontext, 
        !           140:                                        String_iterator& iter, char char_to_stop_before) {
1.1       paf       141:        
                    142:        // ^name.field.subfield.method[..] -- plain call
                    143:        // ^name.field.subfield.method_ref[..] -- method ref call, when .get_method()!=0
1.8       paf       144:        // ^class:method[..]  -- no dotted path allowed before/after
                    145:        //  1: wcontext.object_class == 0?  -- constructor
                    146:        //  2: wcontext.object_class.has_parent('class')? -- dynamic call
                    147:        //  3: not -------------------------------------? -- static call
1.1       paf       148:        
1.11    ! paf       149:        Prefix prefix;
1.1       paf       150:        Array/*<String&>*/ names(pool);  // what.they.refer.to left-to-right list
1.11    ! paf       151:        CHAR_TYPE names_ended_before; // the char type after long name
1.1       paf       152:        get_names(
1.11    ! paf       153:                iter, method_names_breaks,
1.6       paf       154:                &prefix, &names, &names_ended_before); // can return count()=0 when ^self alone
1.1       paf       155: 
1.6       paf       156:        Value *context=
                    157:                prefix?
1.8       paf       158:                        prefix==ROOT_PREFIX?root:self:
1.7       paf       159:                arcontext;
1.1       paf       160:        iter++; // skip '['
                    161: 
1.3       paf       162:        // 'context' dive into dotted path, excluding last .name
1.1       paf       163:        int steps=names.count()-1;
1.6       paf       164:        if(steps<0) // bad: "^self["; now we can safely do ".get[steps]" below
                    165:                pool.exception().raise("call: calling method named 'self'");
1.1       paf       166:        for(int i=0; i<steps; i++) {
                    167:                String& name=static_cast<String&>(names.get[i]);
1.6       paf       168:                context=context->get_element(name);
1.1       paf       169:                if(!context) // no such object field, sad story: can't call method of void
                    170:                        pool.exception().raise(name, "call: to void.method");
                    171:        }
                    172:        
1.3       paf       173:        // last .name
1.1       paf       174:        String& name=static_cast<String&>(names.get[steps]);
1.8       paf       175:        if(steps==0) { // the sole name on path, maybe ^class:method[ call
                    176:                String_iterator ni(name);
                    177:                if(ni.skip_to(':')) { // it is
                    178:                        ni++; // skip ':'
                    179:                        String method_name(pool); method_name.append(ni, 0);
                    180:                        name=method_name; // trim "class:" prefix from the name
                    181: 
                    182:                        String cn(pool);  cn.append(0, ni);
                    183:                        Class *right_class=classes.get(cn);
1.9       paf       184:                        if(!right_class) // bad: no such class
1.8       paf       185:                                pool.exception().raise(cn, "call: undefined class");
                    186:                        Class *left_class=awcontext.get_class();
                    187:                        if(left_class) {
                    188:                                if(left_class.has_parent(right_class)) // dynamic call
1.10      paf       189:                                        context=awcontext.value(); // it's 'self' instance
1.8       paf       190:                                else // static call
1.9       paf       191:                                        context=right_class; // 'self' := class, not instance
1.8       paf       192:                        } else { // constructor: $some(^class:method[..]) call
1.10      paf       193:                                context=new(pool) VClass(pool, right_class); // 'self' := new instance of 'class:'
1.8       paf       194:                                awcontext.write(context);
                    195:                        }
                    196:                }
                    197:        }
1.1       paf       198:        // first we're trying to locate method with that 'name'
                    199:        Method *method=context.get_method(name);
                    200:        if(!method) { // no such method: try to locate method ref field
                    201:                Value *value=context.get_element(name);
1.6       paf       202:                if(value) { // good: we have some element of that 'name'
                    203:                        Method_ref *method_ref=value->get_method_ref();
                    204:                        if(!method_ref) // bad: that field wasn't method_ref
                    205:                                pool.exception().raise(name, "call: this field is not a method reference");
1.11    ! paf       206:                        context=method_ref->self;
1.6       paf       207:                        method=method_ref->method;
                    208:                } else { // no element of that 'name', that must be operator then
1.11    ! paf       209:                        Operator *op=operators.get(name);
        !           210:                        if(!op) // bad: that 'name' is neither method nor field nor operator
1.6       paf       211:                                pool.exception().raise(name, "call: neither method nor field nor operator");
1.11    ! paf       212:                        context=op->self;
        !           213:                        method=op;
1.6       paf       214:                }
1.1       paf       215:        }
                    216: 
                    217: 
1.11    ! paf       218:        // evaluating param values
1.10      paf       219:        Array/*<Value&>*/ param_values(pool);
1.1       paf       220:        get_params(
1.6       paf       221:                iter,
1.9       paf       222:                arcontext,
1.1       paf       223:                &param_values);
                    224:        iter++; // skip ']'
                    225: 
1.11    ! paf       226:        // preparing contexts
1.7       paf       227:        method_self_n_params_n_locals local_rcontext(pool, 
1.6       paf       228:                context,
1.7       paf       229:                method->param_names, param_values,
                    230:                method->local_names);
1.9       paf       231:        WContext local_wcontext(pool, context);
1.10      paf       232:        String_iterator local_iter(method->code);
1.11    ! paf       233:        // calling method/operator
1.6       paf       234:        process(
1.9       paf       235:                local_rcontext/* $:vars */, context /* $self.vars */,
1.6       paf       236:                local_rcontext, local_wcontext, 
1.10      paf       237:                local_iter, 0);
1.7       paf       238:        awcontext.write(local_wcontext);
1.10      paf       239: }
                    240: 
                    241: 
1.11    ! paf       242: enum Prefix {
        !           243:        NO_PREFIX,
        !           244:        ROOT_PREFIX,
        !           245:        SELF_PREFIX
        !           246: };
1.10      paf       247: void get_names(
1.11    ! paf       248:                String_iterator& iter, Char_types& breaks,
        !           249:                Prefix prefix, Array& names, CHAR_TYPE& names_ended_before) {
1.10      paf       250: 
                    251:        // can return count()=0 when $self alone
                    252: }
                    253: 
                    254: void get_params(
                    255:                String_iterator& iter,
                    256:                Value *arcontext,
                    257:                Array/*<Values&>*/& param_values) {
                    258: }

E-mail: