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: ¶m_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: