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