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