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