|
|
| version 1.10, 2001/02/14 13:40:55 | version 1.36, 2001/02/24 15:35:28 |
|---|---|
| Line 1 | Line 1 |
| enum Prefix { | /* |
| NO_PREFIX, | $Id$ |
| ROOT_PREFIX, | */ |
| SELF_PREFIX | |
| }; | #include "pa_request.h" |
| #include "pa_wwrapper.h" | |
| enum CHAR_TYPE { | #include "pa_common.h" |
| NO_TYPE=0, // these got skipped by String::skip_to | #include "pa_vclass.h" |
| DOLLAR_TYPE, | |
| BIRD_TYPE, | #include <stdio.h> |
| STOP_TYPE///=-1 // same as EOF type(-1), see String::skip_to | |
| }; | void core() { |
| Pool pool; | |
| Char_types dollar_or_bird; | Request request(pool); |
| Char_types dollar_or_bird_or_close_round_bracket; | request.core(); |
| Char_types dollar_or_bird_or_close_square_bracket; | } |
| void prepare() { | void Request::core() { |
| dollar_or_bird.set('$', DOLLAR_TYPE); | TRY { |
| dollar_or_bird.set('^', BIRD_TYPE); | char *file="Y:\\parser3\\src\\test.p"; |
| dollar_or_bird_or_close_round_bracket=dollar_or_bird; | String RUN(pool()); RUN.APPEND_CONST(NAME_RUN); |
| dollar_or_bird_or_close_round_bracket.set(')', STOP_TYPE); | use(file, &RUN); |
| dollar_or_bird_or_close_square_bracket=dollar_or_bird; | |
| dollar_or_bird_or_close_square_bracket.set(']', STOP_TYPE); | char *result=execute_MAIN(); |
| } | printf("result-----------------\n%sEOF----------------\n", result); |
| } | |
| void process(method_self_n_params_n_locals& root, Value& self, | CATCH(e) { |
| arcontext& arcontext, WContext& awcontext, | printf("\nERROR: "); |
| String_iterator& iter, Char_types& breaks) { | const String *problem_source=e.problem_source(); |
| while(!iter.eof()) { | if(problem_source) { |
| String_iterator start(iter); | const Origin& origin=problem_source->origin(); |
| CHAR_TYPE type=iter.skip_to(breaks); | if(origin.file) |
| awcontext.write(start, iter); | printf("%s(%d): ", |
| origin.file, 1+origin.line); | |
| switch(type) { | printf("'%s' ", |
| case DOLLAR_TYPE: | problem_source->cstr()); |
| process_dollar(root, self, arcontext, awcontext, iter, breaks); | } |
| break; | printf("%s", e.comment()); |
| case BIRD_TYPE: | const String *type=e.type(); |
| process_bird(root, self, arcontext, awcontext, iter, breaks); | if(type) { |
| break; | printf(" type: %s", type->cstr()); |
| case STOP_TYPE: | const String *code=e.code(); |
| return; | if(code) |
| printf(", code: %s", code->cstr()); | |
| } | } |
| printf("\n"); | |
| } | } |
| END_CATCH | |
| } | } |
| void process_dollar(method_self_n_params_n_locals& root, Value& self, | void Request::use(char *file, String *name) { |
| arcontext& arcontext, WContext& awcontext, | char *source=file_read(pool(), file); |
| String_iterator& iter, Char_types& breaks) { | VClass& vclass=COMPILE(source, file); |
| if(name) // they forced some name? | |
| // $name.field.subfield -- read | vclass.set_name(*name); |
| // $name.field.subfield(constructor code) -- construct | name=vclass.name(); |
| // $name.field.subfield[usage code & if none existed autoconstructed as VHash] -- use OR auto-VHash construct | if(!name) |
| return; //TODO: add operators | |
| Array/*<String&>*/ names(pool); // what.they.refer.to left-to-right list | classes_array()+=&vclass; |
| char names_ended_before; // the char after long name | classes().put(*name, &vclass); |
| Prefix prefix; | } |
| get_names( | |
| iter, " ([", | char *Request::execute_MAIN() { |
| &prefix, &names, &names_ended_before); // can return count()=0 when $self alone | // locate class with @main & it's code |
| String name_main(pool()); | |
| bool read_mode=name_ended_before==' '; | name_main.APPEND_CONST(MAIN_METHOD_NAME); |
| Value *context= | |
| prefix? | // looking for latest known @main |
| prefix==ROOT_PREFIX?root:self: | for(int i=classes_array().size(); --i>=0;) { |
| read_mode?arcontext:awcontext; | VClass *vclass=static_cast<VClass *>(classes_array().get(i)); |
| Value *main=vclass->get_element(name_main); | |
| if(read_mode) { | if(main) { // found some 'main' element |
| // 'context' dive into dotted path | Junction *junction=main->get_junction(); |
| for(int i=0; i<names.count(); i++) { | if(junction) {// it even has junction! |
| context=context->get_element(static_cast<Value *>(names.get[i])); | const Method *method=junction->method; |
| if(!context) // no such object field, nothing bad, just ignore that | if(method) { // and junction is method-junction! call it |
| return; | // initialize contexts |
| } | self=root=rcontext=vclass; |
| awcontext.write(context); | wcontext=NEW WWrapper(pool(), vclass); |
| } else { // write mode | |
| iter++; // skip '(' '[' | // execute! |
| execute(method->code); | |
| bool construct_mode=names_ended_before=='('; | |
| // return chars | |
| // 'context' dive into dotted path, | return wcontext->get_string()->cstr(); |
| int steps=names.count(); | } |
| // if constructing then "excluding last .name" | |
| if(construct_mode) | |
| if(!steps--) // bad: "$self("; now we can safely do ".get[steps]" below | |
| pool.exception().raise("self re-construction prohibited"); | |
| for(int i=0; i<steps; i++) { | |
| String& name=static_cast<String&>(names.get[i]); | |
| Value *next_current=context->get_element(name); | |
| if(next_current) | |
| next_current=context->put_element(name, new(pool) VHash(pool)); | |
| context=new_current; | |
| } | |
| if(construct_mode) { | |
| // .name(construct-code), processing on arcontext in empty temp awcontext | |
| // pure side effect, no awcontext.write here | |
| // last .name | |
| String& name=static_cast<String&>(names.get[steps]); | |
| WContext local_wcontext(pool /* empty */); | |
| process(root, self, arcontext, local_wcontext, iter, ')'); | |
| context->put_element(name, local_wcontext.value()); | |
| } else { // =='[' | |
| // .name[with-code], processing on 'context' | |
| WContext local_context(pool, context); | |
| process(root, self, local_context, local_context, iter, ']'); | |
| awcontext.write(local_context); | |
| } | |
| iter++; // skip ')' ']' | |
| } | |
| } | |
| void process_bird(method_self_n_params_n_locals& root, Value& self, | |
| arcontext& arcontext, WContext& awcontext, | |
| String_iterator& iter, char char_to_stop_before) { | |
| // ^name.field.subfield.method[..] -- plain call | |
| // ^name.field.subfield.method_ref[..] -- method ref call, when .get_method()!=0 | |
| // ^class:method[..] -- no dotted path allowed before/after | |
| // 1: wcontext.object_class == 0? -- constructor | |
| // 2: wcontext.object_class.has_parent('class')? -- dynamic call | |
| // 3: not -------------------------------------? -- static call | |
| Array/*<String&>*/ names(pool); // what.they.refer.to left-to-right list | |
| char names_ended_before; // the char after long name | |
| Prefix prefix; | |
| get_names( | |
| iter, "[", | |
| &prefix, &names, &names_ended_before); // can return count()=0 when ^self alone | |
| Value *context= | |
| prefix? | |
| prefix==ROOT_PREFIX?root:self: | |
| arcontext; | |
| iter++; // skip '[' | |
| // 'context' dive into dotted path, excluding last .name | |
| int steps=names.count()-1; | |
| if(steps<0) // bad: "^self["; now we can safely do ".get[steps]" below | |
| pool.exception().raise("call: calling method named 'self'"); | |
| for(int i=0; i<steps; i++) { | |
| String& name=static_cast<String&>(names.get[i]); | |
| context=context->get_element(name); | |
| if(!context) // no such object field, sad story: can't call method of void | |
| pool.exception().raise(name, "call: to void.method"); | |
| } | |
| // last .name | |
| String& name=static_cast<String&>(names.get[steps]); | |
| if(steps==0) { // the sole name on path, maybe ^class:method[ call | |
| String_iterator ni(name); | |
| if(ni.skip_to(':')) { // it is | |
| ni++; // skip ':' | |
| String method_name(pool); method_name.append(ni, 0); | |
| name=method_name; // trim "class:" prefix from the name | |
| String cn(pool); cn.append(0, ni); | |
| Class *right_class=classes.get(cn); | |
| if(!right_class) // bad: no such class | |
| pool.exception().raise(cn, "call: undefined class"); | |
| Class *left_class=awcontext.get_class(); | |
| if(left_class) { | |
| if(left_class.has_parent(right_class)) // dynamic call | |
| context=awcontext.value(); // it's 'self' instance | |
| else // static call | |
| context=right_class; // 'self' := class, not instance | |
| } else { // constructor: $some(^class:method[..]) call | |
| context=new(pool) VClass(pool, right_class); // 'self' := new instance of 'class:' | |
| awcontext.write(context); | |
| } | } |
| } | } |
| } | } |
| // first we're trying to locate method with that 'name' | |
| Method *method=context.get_method(name); | THROW(0,0, |
| if(!method) { // no such method: try to locate method ref field | 0, |
| Value *value=context.get_element(name); | "'"MAIN_METHOD_NAME"' method not found"); |
| if(value) { // good: we have some element of that 'name' | return 0; |
| Method_ref *method_ref=value->get_method_ref(); | |
| if(!method_ref) // bad: that field wasn't method_ref | |
| pool.exception().raise(name, "call: this field is not a method reference"); | |
| method=method_ref->method; | |
| context=method_ref->self; | |
| } else { // no element of that 'name', that must be operator then | |
| method=operators.get(name); | |
| if(!method) // bad: that 'name' is neither method nor field nor operator | |
| pool.exception().raise(name, "call: neither method nor field nor operator"); | |
| } | |
| } | |
| Array/*<Value&>*/ param_values(pool); | |
| get_params( | |
| iter, | |
| arcontext, | |
| ¶m_values); | |
| iter++; // skip ']' | |
| method_self_n_params_n_locals local_rcontext(pool, | |
| context, | |
| method->param_names, param_values, | |
| method->local_names); | |
| WContext local_wcontext(pool, context); | |
| String_iterator local_iter(method->code); | |
| process( | |
| local_rcontext/* $:vars */, context /* $self.vars */, | |
| local_rcontext, local_wcontext, | |
| local_iter, 0); | |
| awcontext.write(local_wcontext); | |
| } | |
| void get_names( | |
| String_iterator& iter, Char_types& stop_chars, | |
| Prefix prefix, Array& names, char& names_ended_before) { | |
| // can return count()=0 when $self alone | |
| } | |
| void get_params( | |
| String_iterator& iter, | |
| Value *arcontext, | |
| Array/*<Values&>*/& param_values) { | |
| } | } |