--- parser3/src/main/Attic/core.C 2001/02/20 12:18:28 1.20 +++ parser3/src/main/Attic/core.C 2001/02/25 09:14:02 1.38 @@ -1,426 +1,100 @@ /* - $Id: core.C,v 1.20 2001/02/20 12:18:28 paf Exp $ +$Id: core.C,v 1.38 2001/02/25 09:14:02 paf Exp $ */ -/* - ${name.subname}.notsubname - ${:name.subname}.notsubname - - $:name... - $name.subname - $name.subname(constructor-code in current context) - $name.subname{usage-code, in $name context} - $name.part$part... name part $part calculated in current context - - ^:name... - ^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 - parameters, any combination of: - (arg1;arg2) -- calculated before the call, in current context - {arg1}{arg2} -- calculated inside a call, when $arg1 substituted. in object context - - - 0 pass as-is code - '$' -- 1 - '^' -- x - 'eof' -- 1000 exit:normal - else wcontext.write(until those chars) - 1 variable name start in as-is code: names(); name=""; start(iter); - first_char '{' -- x.x - first_char ':' -- x.x - else -- prefix=NO_PREFIX; 1.1 - 1.1 variable name part, plain and $name [in as-is code] - first_char '$' -- 1.2 - '.' -- name+=String(start,iter); names+=name; 1.1 - '(' -- name+=String(start,iter); names+=name; 1.3 - '{' -- name+=String(start,iter); names+=name; x.x - 1.2 name part from variable [variable ref in as-is code] - '.' -- names+=arcontext.get_element(name); 1.1 - '(' -- names+=arcontext.get_element(name); 1.3 - '{' -- names+=arcontext.get_element(name); x.x - 1.3 variable constructor in as-is code: push(wcontext); wcontext=temp; - '$' -- 2.1 - '^' -- x.x - 'eof' -- 1001 exit:unexpected eof in constructor - ')' - else wcontext.write(until those chars) - - - - x.x bracketed name - : -- x.x - x.x prefix=ROOT_PREFIX; names+=name - - - - - - - -*/ - -// TODO: -// $RESULT -// ^menu[!unevaluated!] - -enum Prefix { - NO_PREFIX, - ROOT_PREFIX, - SELF_PREFIX -}; - -enum CHAR_TYPE { - NO_TYPE=0, // these got skipped by String::skip_to - VAR_START_TYPE, - METHOD_START_TYPE, - STOP_TYPE,///=-1 // same as EOF type(-1), see String::skip_to - DOT_TYPE, - CONSTRUCTOR_BODY_START_TYPE, - CONSTRUCTOR_BODY_FINISH_TYPE, - BLOCK_START_TYPE, - BLOCK_FINISH_TYPE, - PARAM_STOP_NORMAL_TYPE, - PARAM_STOP_SPECIAL_TYPE, - - Z_TYPE -}; - -Char_types var_or_method_start; -Char_types var_or_method_start_or_constructor_stop; -Char_types var_or_method_start_or_block_stop; -Char_types var_or_method_start_or_block_stop_or_param_stop_normal; -Char_types var_or_method_start_or_block_stop_or_param_stop_special; -Char_types common_names_breaks, var_names_breaks, method_names_breaks; -String SELF; -String RESULT; - -void prepare() { - var_or_method_start.set('$', VAR_START_TYPE); - var_or_method_start.set('^', METHOD_START_TYPE); - - var_or_method_start_or_constructor_stop=var_or_method_start; - var_or_method_start_or_constructor_stop.set(')', STOP_TYPE); - - var_or_method_start_or_block_stop=var_or_method_start; - var_or_method_start_or_block_stop.set('}', STOP_TYPE); - - var_or_method_start_or_block_stop_or_param_stop_normal=var_or_method_start_or_block_stop; - var_or_method_start_or_block_stop_or_param_stop_normal.set(';', PARAM_STOP_NORMAL_TYPE); - var_or_method_start_or_block_stop_or_param_stop_special=var_or_method_start_or_block_stop; - var_or_method_start_or_block_stop_or_param_stop_special.set('`', PARAM_STOP_SPECIAL_TYPE); - - common_names_breaks.set(0, ' ', STOP_TYPE); - common_names_breaks.set('.', DOT_TYPE); - common_names_breaks.set(')', STOP_TYPE); // var_or_method_start_or_constructor_stop - common_names_breaks.set(']', STOP_TYPE); // var_or_method_start_or_block_stop - - var_names_breaks=common_names_breaks; - var_names_breaks.set('(', CONSTRUCTOR_BODY_START_TYPE); - - method_names_breaks=common_names_breaks; - method_names_breaks.set('[', BLOCK_START_TYPE); - - SELF.APPEND("self", 0, 0); - RESULT.APPEND("result", 0, 0); -} - -CHAR_TYPE process(method_self_n_params_n_locals& root, Value& self, - arcontext& arcontext, WContext& awcontext, - String_iterator& iter, Char_types& breaks) { - while(!iter.eof()) { - String_iterator start(iter); - CHAR_TYPE type=iter.skip_to(breaks); - awcontext.write(start, iter); - - switch(type) { - case VAR_START_TYPE: - process_var(root, self, arcontext, awcontext, iter, breaks); - break; - case METHOD_START_TYPE: - process_method(root, self, arcontext, awcontext, iter, breaks); - break; - default: - return type; - } - } - return -1; -} - -void process_var(method_self_n_params_n_locals& root, Value& self, - arcontext& arcontext, WContext& awcontext, - String_iterator& iter, Char_types& breaks) { - - // $name.field.subfield -- read - // $name.field.subfield(constructor code) -- construct - // $name.field.subfield[usage code & if none existed autoconstructed as VHash] -- use OR auto-VHash construct - - Prefix prefix; - Array/**/ names(pool); // what.they.refer.to left-to-right list - // the char type after long name - CHAR_TYPE names_ended_before=get_names( - iter, var_names_breaks, - &prefix, &names); // can return size()==0 when $self alone - - bool read_mode=name_ended_before==' '; - Value *context= - prefix? - prefix==ROOT_PREFIX?root:self: - read_mode?arcontext:awcontext; - - if(read_mode) { - // 'context' dive into dotted path - for(int i=0; iget_element(static_cast(names.get[i])); - if(!context) // no such object field, nothing bad, just ignore that - return; - } - awcontext.write(context); - } else { // write mode - iter++; // skip '(' '[' - - bool construct_mode=names_ended_before=='('; - - // 'context' dive into dotted path, - int steps=names.size(); - // 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(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 - // prepare context - String& name=static_cast(names.get[steps]); - WContext local_wcontext(pool /* empty */); - // evaluate constructor-code in that context - process(root, self, - arcontext, local_wcontext, - iter, var_or_method_start_or_constructor_stop); - // store constructed value under 'name' - context->put_element(name, local_wcontext.value()); - } else { // =='[' .name[with-code] - // prepare context - WContext local_context(pool, context); - // evaluate with-code in that context - process(root, self, - local_context, local_context, - iter, var_or_method_start_or_block_stop); - // emit result - awcontext.write(local_context); - } - - iter++; // skip ')' ']' - } -} - -void process_method(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 - - Prefix prefix; - Array/**/ names(pool); // what.they.refer.to left-to-right list - // the char type after long name - CHAR_TYPE names_ended_before=get_names( - iter, method_names_breaks, - &prefix, &names); // can return size()==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.size()-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(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(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); +#include "pa_request.h" +#include "pa_wwrapper.h" +#include "pa_common.h" +#include "pa_vclass.h" + +#include + +void core() { + Pool pool; + Request request(pool); + request.core(); +} + +void Request::core() { + TRY { + char *file="Y:\\parser3\\src\\test.p"; + String RUN(pool()); RUN.APPEND_CONST(NAME_RUN); + use(file, &RUN); + + char *result=execute_MAIN(); + printf("result-----------------\n%sEOF----------------\n", result); + } + CATCH(e) { + printf("\nERROR: "); + const String *problem_source=e.problem_source(); + if(problem_source) { + const Origin& origin=problem_source->origin(); + if(origin.file) + printf("%s(%d): ", + origin.file, 1+origin.line); + printf("'%s' ", + problem_source->cstr()); + } + printf("%s", e.comment()); + const String *type=e.type(); + if(type) { + printf(" type: %s", type->cstr()); + const String *code=e.code(); + if(code) + printf(", code: %s", code->cstr()); + } + printf("\n"); + } + END_CATCH +} + +void Request::use(char *file, String *alias) { + char *source=file_read(pool(), file); + if(!source) + THROW(0,0, + 0, + "use: can not read '%s' file", file); + + VClass& vclass=COMPILE(source, alias, file); + String *vclass_name=vclass.name(); + if(!vclass_name) + return; //TODO: add operators + classes_array()+=&vclass; + classes().put(*vclass_name, &vclass); + if(alias) + classes().put(*alias, &vclass); +} + +char *Request::execute_MAIN() { + // locate class with @main & it's code + String name_main(pool()); + name_main.APPEND_CONST(MAIN_METHOD_NAME); + + // looking for latest known @main + for(int i=classes_array().size(); --i>=0;) { + VClass *vclass=static_cast(classes_array().get(i)); + Value *main=vclass->get_element(name_main); + if(main) { // found some 'main' element + Junction *junction=main->get_junction(); + if(junction) {// it even has junction! + const Method *method=junction->method; + if(method) { // and junction is method-junction! call it + // initialize contexts + self=root=rcontext=vclass; + wcontext=NEW WWrapper(pool(), vclass); + + // execute! + execute(method->code); + + // return chars + return wcontext->get_string()->cstr(); + } } } } - // first we're trying to locate method with that 'name' - Method *method=context.get_method(name); - if(!method) { // no such method: try to locate method ref field - Value *value=context.get_element(name); - if(value) { // good: we have some element of that 'name' - 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"); - context=method_ref->self; - method=method_ref->method; - } else { // no element of that 'name', that must be operator then - Operator *op=operators.get(name); - if(!op) // bad: that 'name' is neither method nor field nor operator - pool.exception().raise(name, "call: neither method nor field nor operator"); - context=op->self; - method=op; - } - } - - - // evaluate param values - Array/**/ param_values(pool); - get_params( - iter, - arcontext, - ¶m_values); - iter++; // skip ']' - - // prepare contexts - 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); - // call method/operator in those contexts - process( - local_rcontext/* $:vars */, context /* $self.vars */, - local_rcontext, local_wcontext, - local_iter, var_or_method_start); - // emit result - awcontext.write(local_wcontext); -} - - -CHAR_TYPE get_names( - String_iterator& iter, Char_types& breaks, - Prefix& prefix, Array& names) { - // $name.subname white-space - // $name.subname( $name.subname[ - // $name.subname) $name.subname] - // $:name... $self... - - if(iter.eof()) - return -1; - - if(iter()==':') { // $:name ? - prefix=ROOT_PREFIX; - iter++; // skip ':' - } else // $name - prefix=NO_PREFIX; - - CHAR_TYPE result; - while(true) { - // prepare context - WContext local_wcontext(pool /* empty */); - // execute code until separator, writing to that context - result=process(root, self, - arcontext, local_wcontext, - iter, breaks); - // read resulting name - String *name=local_wcontext.get_string(); - if(!name) - pool.exception().raise("names: name string missing"); - if(*name==SELF) // is it "self"? - if(prefix || names.size()) // already $: or $self. or $name. - pool.exception().raise("names: 'self' not first on chain"); - else // $self. - prefix=SELF_PREFIX; - else // simple $name or .name, emiting - names+=name; - - // stop if not '.', otherwise continue with next name on chain - if(result!=DOT_TYPE) - break; - } - - // can only return size()==0 when $self alone - if(names.size()==0 && prefix!=SELF_PREFIX) - pool.exception().raise("names: empty chain"); - - return result; -} - -void get_params( - String_iterator& iter, - Value *arcontext, - Array/**/& param_values) { - // arg1;arg2;...] - // ...`argX.1;argX.2`...] - while(true) { - // prepare context - WContext local_wcontext(pool /* empty */); - bool back_stick_at_start=iter()=='`'; // parameter starts with '`' ? - if(back_stick_at_start) - iter++; // skip '`' - // evaluate param body in that context - CHAR_TYPE type=process(root, self, // parameter must end on ';' or '`' depending on start - arcontext, local_wcontext, - 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 - ); - switch(type) { - case PARAM_STOP_NORMAL_TYPE: - iter++; // skip ';' - break; - case PARAM_STOP_SPECIAL_TYPE: - iter++; // skip '`' - char c=iter(); - if(c==';') - iter++; // skip ';' - else if(c!=']') - pool.exception().raise("params: closing backstick doesn't adjoin semicolon or closing bracket"); - break; -/* - default: - break; // ']' or eof: ^method[params;...;eof which would'nt process honestly -*/ - } - - // emit resulting param's value - param_values+=local_wcontext.value(); - - // stop on ] or eof, otherwise continue with next param - if(type==STOP_TYPE || type<0) - break; - } + THROW(0,0, + 0, + "'"MAIN_METHOD_NAME"' method not found"); + return 0; }