|
|
| version 1.100, 2009/08/26 13:55:57 | version 1.118, 2024/09/16 23:59:31 |
|---|---|
| Line 1 | Line 1 |
| /** @file | /** @file |
| Parser: compiler support helper functions decls. | Parser: compiler support helper functions decls. |
| Copyright (c) 2001-2009 ArtLebedev Group (http://www.artlebedev.com) | Copyright (c) 2001-2023 Art. Lebedev Studio (http://www.artlebedev.com) |
| Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru) | Authors: Konstantin Morshnev <moko@design.ru>, Alexandr Petrosian <paf@design.ru> |
| */ | */ |
| #ifndef COMPILE_TOOLS | #ifndef COMPILE_TOOLS |
| #define COMPILE_TOOLS | #define COMPILE_TOOLS |
| static const char * const IDENT_COMPILE_TOOLS_H="$Date$"; | #define IDENT_COMPILE_TOOLS_H "$Id$" |
| #include "pa_opcode.h" | #include "pa_opcode.h" |
| #include "pa_types.h" | #include "pa_types.h" |
| Line 87 public: | Line 87 public: |
| //@} | //@} |
| /// output: filled input 'methods' and 'error' if any | /// output: filled input 'methods' and 'error' if any |
| char error[MAX_STRING]; | const char *error; |
| Parse_control(Request& arequest, | Parse_control(Request& arequest, |
| VStateless_class* aclass, | VStateless_class* aclass, |
| Line 114 public: | Line 114 public: |
| ls_sp(0), | ls_sp(0), |
| in_call_value(false), | in_call_value(false), |
| explicit_result(false), | explicit_result(false), |
| append(false) { | append(false), |
| error("") { | |
| *cclasses+=aclass; | *cclasses+=aclass; |
| } | } |
| void class_add(){ | /// false if exception should be rised |
| bool class_add(){ | |
| if(cclass_new){ | if(cclass_new){ |
| cclass=cclass_new; | cclass=cclass_new; |
| // append to request's classes | |
| request.classes().put(cclass->name(), cclass); | |
| *cclasses+=cclass; | *cclasses+=cclass; |
| cclass_new=0; | cclass_new=0; |
| append=false; | append=false; |
| // append to request's classes | |
| if(!request.allow_class_replace) | |
| return request.classes().put_dont_replace(cclass->type(), cclass) == 0; | |
| request.classes().put(cclass->type(), cclass); | |
| } | } |
| return true; | |
| } | } |
| VStateless_class* get_existed_class(VStateless_class* aclass){ | VStateless_class* get_existed_class(VStateless_class* aclass){ |
| // checking existence of the class during processing @OPTIONS\npartial | |
| // can't use get_class because it will call @autouse[] if the class wasn't loaded | |
| if(aclass) | if(aclass) |
| if(Value* class_value=request.classes().get(aclass->name())) | return request.classes().get(aclass->type()); |
| return class_value->get_class(); | |
| return 0; | return 0; |
| } | } |
| Line 149 public: | Line 155 public: |
| } | } |
| void set_all_vars_local(){ | void set_all_vars_local(){ |
| if(cclass_new){ | (cclass_new ? cclass_new : cclass)->set_all_vars_local(); |
| cclass_new->set_all_vars_local(); | } |
| } else { | |
| cclass->set_all_vars_local(); | void set_methods_call_type(Method::Call_type call_type){ |
| } | (cclass_new ? cclass_new : cclass)->set_methods_call_type(call_type); |
| } | |
| Method::Call_type get_methods_call_type(){ | |
| return (cclass_new ? cclass_new : cclass)->get_methods_call_type(); | |
| } | } |
| void pos_next_line() { | void pos_next_line() { |
| Line 234 inline ArrayOperation* VL(Value* value, | Line 244 inline ArrayOperation* VL(Value* value, |
| /// Literal Array to(2) Value @return Value from literal Array OP+origin+Value | /// Literal Array to(2) Value @return Value from literal Array OP+origin+Value |
| Value* LA2V(ArrayOperation& literal_string_array, int offset=0, OP::OPCODE code=OP::OP_VALUE); | Value* LA2V(ArrayOperation& literal_string_array, int offset=0, OP::OPCODE code=OP::OP_VALUE); |
| /// Literal Array to(2) String @return String value from literal Array OP+origin+String array | /// Literal Array to(2) String @return String value from literal Array OP+origin+String array |
| inline const String* LA2S(ArrayOperation& literal_string_array, int offset=0, OP::OPCODE code=OP::OP_VALUE) { | inline const String* LA2S(ArrayOperation& literal_string_array, int offset=0, OP::OPCODE code=OP::OP_VALUE) { |
| if(Value* value=LA2V(literal_string_array, offset, code)) | if(Value* value=LA2V(literal_string_array, offset, code)) |
| Line 249 void maybe_change_string_literal_to_doub | Line 260 void maybe_change_string_literal_to_doub |
| void change_string_literal_value(ArrayOperation& literal_string_array, const String& new_value); | void change_string_literal_value(ArrayOperation& literal_string_array, const String& new_value); |
| void changetail_or_append(ArrayOperation& opcodes, | inline bool change(ArrayOperation& opcodes, int pos, OP::OPCODE find, OP::OPCODE replace) { |
| OP::OPCODE find, bool with_argument, OP::OPCODE replace, OP::OPCODE notfound); | if(pos>=0) { |
| Operation& op=opcodes.get_ref(pos); | |
| if(op.code==find) { | |
| op.code=replace; | |
| return true; | |
| } | |
| } | |
| return false; | |
| } | |
| bool maybe_change_first_opcode(ArrayOperation& opcodes, OP::OPCODE find, OP::OPCODE replace); | inline void change_or_append(ArrayOperation& opcodes, int pos, OP::OPCODE find, OP::OPCODE replace, OP::OPCODE notfound) { |
| if(change(opcodes, pos, find, replace)) | |
| return; | |
| opcodes+=Operation(notfound); | |
| } | |
| bool change_first(ArrayOperation& opcodes, OP::OPCODE find, OP::OPCODE replace); | |
| #ifdef OPTIMIZE_BYTECODE_GET_OBJECT_ELEMENT | #ifdef OPTIMIZE_BYTECODE_GET_OBJECT_ELEMENT |
| // OP_VALUE+origin+value+OP_GET_ELEMENT+OP_VALUE+origin+value+OP_GET_ELEMENT => OP_GET_OBJECT_ELEMENT+origin+value+origin+value | // OP_VALUE+origin+value+OP_GET_ELEMENT+OP_VALUE+origin+value+OP_GET_ELEMENT => OP_GET_OBJECT_ELEMENT+origin+value+origin+value |
| inline bool maybe_make_get_object_element(ArrayOperation& opcodes, ArrayOperation& diving_code, size_t divine_count){ | inline bool maybe_make_get_object_element(ArrayOperation& opcodes, ArrayOperation& diving_code, size_t diving_count){ |
| if(divine_count<8) | |
| return false; | |
| assert(diving_code[0].code==OP::OP_VALUE); | |
| if( | if( |
| diving_code[3].code==OP::OP_GET_ELEMENT | diving_count>=8 |
| && diving_code[0].code==OP::OP_VALUE | |
| && diving_code[3].code==OP::OP_GET_ELEMENT | |
| && diving_code[4].code==OP::OP_VALUE | && diving_code[4].code==OP::OP_VALUE |
| && diving_code[7].code==OP::OP_GET_ELEMENT | && diving_code[7].code==OP::OP_GET_ELEMENT |
| ){ | ){ |
| O(opcodes, OP::OP_GET_OBJECT_ELEMENT); | O(opcodes, OP::OP_GET_OBJECT_ELEMENT); |
| P(opcodes, diving_code, 1/*offset*/, 2/*limit*/); // copy first origin+value | P(opcodes, diving_code, 1 /*offset*/, 2 /*limit*/); // copy first origin+value |
| P(opcodes, diving_code, 5, 2); // second origin+value | P(opcodes, diving_code, 5, 2); // second origin+value |
| if(divine_count>8) | if(diving_count>8) |
| P(opcodes, diving_code, 8/*offset*/); // tail | P(opcodes, diving_code, 8 /*offset*/); // tail |
| return true; | return true; |
| } | } |
| return false; | return false; |
| Line 281 inline bool maybe_make_get_object_elemen | Line 304 inline bool maybe_make_get_object_elemen |
| #ifdef OPTIMIZE_BYTECODE_GET_OBJECT_VAR_ELEMENT | #ifdef OPTIMIZE_BYTECODE_GET_OBJECT_VAR_ELEMENT |
| // OP_VALUE+origin+value+OP_GET_ELEMENT+OP_WITH_READ+OP_VALUE+origin+value+OP_GET_ELEMENT+OP_GET_ELEMENT => OP_GET_OBJECT_VAR_ELEMENT+origin+value+origin+value | // OP_VALUE+origin+value+OP_GET_ELEMENT+OP_WITH_READ+OP_VALUE+origin+value+OP_GET_ELEMENT+OP_GET_ELEMENT => OP_GET_OBJECT_VAR_ELEMENT+origin+value+origin+value |
| inline bool maybe_make_get_object_var_element(ArrayOperation& opcodes, ArrayOperation& diving_code, size_t divine_count){ | inline bool maybe_make_get_object_var_element(ArrayOperation& opcodes, ArrayOperation& diving_code, size_t diving_count){ |
| if(divine_count!=10) | |
| return false; | |
| assert(diving_code[0].code==OP::OP_VALUE); | |
| if( | if( |
| diving_code[3].code==OP::OP_GET_ELEMENT | diving_count==10 |
| && diving_code[0].code==OP::OP_VALUE | |
| && diving_code[3].code==OP::OP_GET_ELEMENT | |
| && diving_code[4].code==OP::OP_WITH_READ | && diving_code[4].code==OP::OP_WITH_READ |
| && diving_code[5].code==OP::OP_VALUE | && diving_code[5].code==OP::OP_VALUE |
| && diving_code[8].code==OP::OP_GET_ELEMENT | && diving_code[8].code==OP::OP_GET_ELEMENT |
| && diving_code[9].code==OP::OP_GET_ELEMENT | && diving_code[9].code==OP::OP_GET_ELEMENT |
| ){ | ){ |
| O(opcodes, OP::OP_GET_OBJECT_VAR_ELEMENT); | O(opcodes, OP::OP_GET_OBJECT_VAR_ELEMENT); |
| P(opcodes, diving_code, 1/*offset*/, 2/*limit*/); // copy first origin+value | P(opcodes, diving_code, 1 /*offset*/, 2 /*limit*/); // copy first origin+value |
| P(opcodes, diving_code, 6, 2); // second origin+value | P(opcodes, diving_code, 6, 2); // second origin+value |
| return true; | return true; |
| } | } |
| Line 303 inline bool maybe_make_get_object_var_el | Line 324 inline bool maybe_make_get_object_var_el |
| #endif | #endif |
| bool maybe_make_self(ArrayOperation& opcodes, ArrayOperation& diving_code, size_t divine_count); | bool maybe_make_self(ArrayOperation& opcodes, ArrayOperation& diving_code, size_t diving_count); |
| #ifdef OPTIMIZE_BYTECODE_GET_ELEMENT__SPECIAL | |
| bool maybe_append_simple_diving_code(ArrayOperation& code, ArrayOperation& diving_code); | |
| bool is_special_element(ArrayOperation& opcodes); | |
| #endif | |
| #ifdef OPTIMIZE_BYTECODE_CONSTRUCT | #ifdef OPTIMIZE_BYTECODE_CONSTRUCT |
| inline bool maybe_optimize_construct(ArrayOperation& opcodes, ArrayOperation& var_ops, ArrayOperation& expr_ops){ | inline bool maybe_optimize_construct(ArrayOperation& opcodes, ArrayOperation& var_ops, ArrayOperation& expr_ops){ |
| Line 331 inline bool maybe_optimize_construct(Arr | Line 357 inline bool maybe_optimize_construct(Arr |
| with=0x30; | with=0x30; |
| break; | break; |
| } | } |
| default: break; | |
| } | } |
| if(with && var_ops[1].code==OP::OP_VALUE && var_ops.count()==4){ | if(with && var_ops[1].code==OP::OP_VALUE && var_ops.count()==4){ |
| Line 379 inline bool maybe_optimize_construct(Arr | Line 406 inline bool maybe_optimize_construct(Arr |
| } | } |
| #endif | #endif |
| Method::Call_type GetMethodCallType(Parse_control& pc, ArrayOperation& literal_string_array); | |
| void push_LS(Parse_control& pc, lexical_state new_state); | void push_LS(Parse_control& pc, lexical_state new_state); |
| void pop_LS(Parse_control& pc); | void pop_LS(Parse_control& pc); |