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