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

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

E-mail: