Annotation of parser3/src/main/compile_tools.C, revision 1.74
1.29 paf 1: /** @file
1.30 paf 2: Parser: compiler support helper functions.
3:
1.72 moko 4: Copyright (c) 2001-2015 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.74 ! moko 16: volatile const char * IDENT_COMPILE_TOOLS_C="$Id: compile_tools.C,v 1.73 2016/05/24 11:55:14 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
46: bool maybe_make_self(ArrayOperation& opcodes, ArrayOperation& diving_code, size_t divine_count){
47: const String* first_name=LA2S(diving_code);
48:
1.74 ! moko 49: if(first_name && SYMBOLS_EQ(*first_name,Symbols::self)){
1.67 misha 50: #ifdef OPTIMIZE_BYTECODE_GET_SELF_ELEMENT
51: if(
52: divine_count>=8
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);
59: P(opcodes, diving_code, 5/*offset*/, 2/*limit*/); // copy second origin+value. we know that the first one is "self"
60: if(divine_count>8)
61: P(opcodes, diving_code, 8/*offset*/); // copy tail
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 */
68: P(opcodes, diving_code, divine_count>=4?4/*OP::OP_VALUE+origin+string+OP::OP_GET_ELEMENTx*/:3/*OP::OP_+origin+string*/);
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);
91: return (
92: name
93: && (
94: *name==class_element_name
95: || *name==class_name_element_name
96: )
97: );
98: }
99: #endif
1.67 misha 100:
1.68 misha 101: Method::Call_type GetMethodCallType(Parse_control& pc, ArrayOperation& literal_array) {
102: const String* full_name=LA2S(literal_array);
103: int pos=full_name->pos(':');
104: if(pos > 0) {
105: const String call_type=full_name->mid(0, pos);
106: if(call_type!=method_call_type_static)
107: throw Exception("parser.compile",
108: &call_type,
1.71 moko 109: "incorrect method call type. the only valid call type method prefix is '" METHOD_CALL_TYPE_STATIC "'"
1.68 misha 110: );
111: const String *sole_name=&full_name->mid(pos+1, full_name->length());
112: // replace full method name (static:method) by sole method name (method). it will be used later.
113: change_string_literal_value(literal_array, *sole_name);
114: return Method::CT_STATIC;
115: }
116: return pc.get_methods_call_type();
117: }
118:
1.55 paf 119: void push_LS(Parse_control& pc, lexical_state new_state) {
1.42 paf 120: if(pc.ls_sp<MAX_LEXICAL_STATES) {
121: pc.ls_stack[pc.ls_sp++]=pc.ls;
122: pc.ls=new_state;
1.1 paf 123: } else
1.55 paf 124: throw Exception(0, 0,
125: "push_LS: ls_stack overflow");
1.1 paf 126: }
1.55 paf 127: void pop_LS(Parse_control& pc) {
1.42 paf 128: if(--pc.ls_sp>=0)
129: pc.ls=pc.ls_stack[pc.ls_sp];
1.1 paf 130: else
1.55 paf 131: throw Exception(0, 0,
132: "pop_LS: ls_stack underflow");
133: }
134:
135: const String& Parse_control::alias_method(const String& name) {
136: return (main_alias && name==main_method_name)?*main_alias:name;
1.1 paf 137: }
E-mail: