Annotation of parser3/src/main/compile_tools.C, revision 1.80
1.29 paf 1: /** @file
1.30 paf 2: Parser: compiler support helper functions.
3:
1.79 moko 4: Copyright (c) 2001-2017 Art. Lebedev Studio (http://www.artlebedev.com)
1.45 paf 5: Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
1.51 paf 6: */
1.30 paf 7:
1.1 paf 8: #include "compile_tools.h"
9: #include "pa_string.h"
10: #include "pa_array.h"
11: #include "pa_exception.h"
1.9 paf 12: #include "pa_vstring.h"
1.15 paf 13: #include "pa_vdouble.h"
1.67 misha 14: #include "pa_vmethod_frame.h"
1.1 paf 15:
1.80 ! moko 16: volatile const char * IDENT_COMPILE_TOOLS_C="$Id: compile_tools.C,v 1.79 2017/02/07 22:00:40 moko Exp $" IDENT_COMPILE_TOOLS_H;
1.69 moko 17:
1.61 misha 18: Value* LA2V(ArrayOperation& literal_string_array, int offset, OP::OPCODE code) {
19: return literal_string_array[offset+0].code==code?literal_string_array[offset+2/*skip opcode&origin*/].value
1.43 paf 20: :0;
1.15 paf 21: }
22:
1.58 paf 23: void maybe_change_string_literal_to_double_literal(ArrayOperation& literal_array) {
1.60 misha 24: assert(literal_array[0].code==OP::OP_VALUE);
1.58 paf 25: VString& vstring=*static_cast<VString*>(literal_array[2/*opcode+origin*/].value);
26: if(isdigit(vstring.string().first_char()))
27: literal_array.put(2/*opcode+origin*/, &vstring.as_expr_result());
1.1 paf 28: }
1.53 paf 29:
1.55 paf 30: void change_string_literal_value(ArrayOperation& literal_string_array, const String& new_value) {
1.60 misha 31: assert(literal_string_array[0].code==OP::OP_VALUE);
1.58 paf 32: static_cast<VString*>(literal_string_array[2/*opcode+origin*/].value)->set_string(new_value);
1.53 paf 33: }
34:
1.70 misha 35: bool change_first(ArrayOperation& opcodes, OP::OPCODE find, OP::OPCODE replace) {
36: Operation& op=opcodes.get_ref(0);
37: if(op.code!=find)
1.66 misha 38: return false;
1.1 paf 39:
1.70 misha 40: op.code=replace;
1.66 misha 41: return true;
1.62 misha 42: }
43:
1.67 misha 44:
45: // OP_VALUE+origin+self+OP_GET_ELEMENT+OP_VALUE+origin+value+OP_GET_ELEMENT => OP_WITH_SELF__VALUE__GET_ELEMENT+origin+value
1.80 ! moko 46: bool maybe_make_self(ArrayOperation& opcodes, ArrayOperation& diving_code, size_t diving_count){
1.67 misha 47: const String* first_name=LA2S(diving_code);
48:
1.75 moko 49: if(first_name && SYMBOLS_EQ(*first_name,SELF_SYMBOL)){
1.67 misha 50: #ifdef OPTIMIZE_BYTECODE_GET_SELF_ELEMENT
51: if(
1.80 ! moko 52: diving_count>=8
1.67 misha 53: && diving_code[3].code==OP::OP_GET_ELEMENT
54: && diving_code[4].code==OP::OP_VALUE
55: && diving_code[7].code==OP::OP_GET_ELEMENT
56: ){
57: // optimization for $self.field and ^self.method
58: O(opcodes, OP::OP_WITH_SELF__VALUE__GET_ELEMENT);
1.80 ! moko 59: P(opcodes, diving_code, 5 /*offset*/, 2 /*limit*/); // copy second origin+value. we know that the first one is "self"
! 60: if(diving_count>8)
! 61: P(opcodes, diving_code, 8 /*offset*/); // copy tail
1.67 misha 62: } else
63: #endif
64: {
65: // self.xxx... => xxx...
66: // OP_VALUE+origin+string+OP_GET_ELEMENT+... -> OP_WITH_SELF+...
67: O(opcodes, OP::OP_WITH_SELF); /* stack: starting context */
1.80 ! moko 68: P(opcodes, diving_code, diving_count >=4 ? 4 /*OP::OP_VALUE+origin+string+OP::OP_GET_ELEMENTx*/ : 3 /*OP::OP_+origin+string*/);
1.67 misha 69: }
70: return true;
71: }
72: return false;
73: }
74:
1.70 misha 75: #ifdef OPTIMIZE_BYTECODE_GET_ELEMENT__SPECIAL
76: bool maybe_append_simple_diving_code(ArrayOperation& code, ArrayOperation& diving_code){
77: if(
78: diving_code.count()==3
79: && diving_code[0].code==OP::OP_STRING__WRITE
80: ){
81: O(code, OP::OP_VALUE);
82: P(code, diving_code, 1/*offset*/, 2/*limit*/); /*copy origin+value*/
83: return true;
84: } else {
85: return false;
86: }
87: }
88:
89: bool is_special_element(ArrayOperation& opcodes){
90: const String* name=LA2S(opcodes);
1.78 moko 91: return name && ( SYMBOLS_EQ(*name,CLASS_SYMBOL) || SYMBOLS_EQ(*name,CLASS_NAME_SYMBOL) );
1.70 misha 92: }
93: #endif
1.67 misha 94:
1.68 misha 95: Method::Call_type GetMethodCallType(Parse_control& pc, ArrayOperation& literal_array) {
96: const String* full_name=LA2S(literal_array);
97: int pos=full_name->pos(':');
98: if(pos > 0) {
99: const String call_type=full_name->mid(0, pos);
1.75 moko 100: if(call_type!=Symbols::STATIC_SYMBOL)
101: throw Exception("parser.compile", &call_type, "incorrect method call type. the only valid call type method prefix is 'static'");
1.68 misha 102: const String *sole_name=&full_name->mid(pos+1, full_name->length());
103: // replace full method name (static:method) by sole method name (method). it will be used later.
104: change_string_literal_value(literal_array, *sole_name);
105: return Method::CT_STATIC;
106: }
107: return pc.get_methods_call_type();
108: }
109:
1.55 paf 110: void push_LS(Parse_control& pc, lexical_state new_state) {
1.42 paf 111: if(pc.ls_sp<MAX_LEXICAL_STATES) {
112: pc.ls_stack[pc.ls_sp++]=pc.ls;
113: pc.ls=new_state;
1.1 paf 114: } else
1.77 moko 115: throw Exception(0, 0, "push_LS: ls_stack overflow");
1.1 paf 116: }
1.55 paf 117: void pop_LS(Parse_control& pc) {
1.42 paf 118: if(--pc.ls_sp>=0)
119: pc.ls=pc.ls_stack[pc.ls_sp];
1.1 paf 120: else
1.77 moko 121: throw Exception(0, 0, "pop_LS: ls_stack underflow");
1.55 paf 122: }
123:
124: const String& Parse_control::alias_method(const String& name) {
125: return (main_alias && name==main_method_name)?*main_alias:name;
1.1 paf 126: }
E-mail: