1 /*************************************************************************/
2 /* gdscript_compiler.cpp */
3 /*************************************************************************/
4 /* This file is part of: */
5 /* GODOT ENGINE */
6 /* https://godotengine.org */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
9 /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
10 /* */
11 /* Permission is hereby granted, free of charge, to any person obtaining */
12 /* a copy of this software and associated documentation files (the */
13 /* "Software"), to deal in the Software without restriction, including */
14 /* without limitation the rights to use, copy, modify, merge, publish, */
15 /* distribute, sublicense, and/or sell copies of the Software, and to */
16 /* permit persons to whom the Software is furnished to do so, subject to */
17 /* the following conditions: */
18 /* */
19 /* The above copyright notice and this permission notice shall be */
20 /* included in all copies or substantial portions of the Software. */
21 /* */
22 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
25 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29 /*************************************************************************/
30
31 #include "gdscript_compiler.h"
32
33 #include "gdscript.h"
34
_is_class_member_property(CodeGen & codegen,const StringName & p_name)35 bool GDScriptCompiler::_is_class_member_property(CodeGen &codegen, const StringName &p_name) {
36
37 if (codegen.function_node && codegen.function_node->_static)
38 return false;
39
40 if (codegen.stack_identifiers.has(p_name))
41 return false; //shadowed
42
43 return _is_class_member_property(codegen.script, p_name);
44 }
45
_is_class_member_property(GDScript * owner,const StringName & p_name)46 bool GDScriptCompiler::_is_class_member_property(GDScript *owner, const StringName &p_name) {
47
48 GDScript *scr = owner;
49 GDScriptNativeClass *nc = NULL;
50 while (scr) {
51
52 if (scr->native.is_valid())
53 nc = scr->native.ptr();
54 scr = scr->_base;
55 }
56
57 ERR_FAIL_COND_V(!nc, false);
58
59 return ClassDB::has_property(nc->get_name(), p_name);
60 }
61
_set_error(const String & p_error,const GDScriptParser::Node * p_node)62 void GDScriptCompiler::_set_error(const String &p_error, const GDScriptParser::Node *p_node) {
63
64 if (error != "")
65 return;
66
67 error = p_error;
68 if (p_node) {
69 err_line = p_node->line;
70 err_column = p_node->column;
71 } else {
72 err_line = 0;
73 err_column = 0;
74 }
75 }
76
_create_unary_operator(CodeGen & codegen,const GDScriptParser::OperatorNode * on,Variant::Operator op,int p_stack_level)77 bool GDScriptCompiler::_create_unary_operator(CodeGen &codegen, const GDScriptParser::OperatorNode *on, Variant::Operator op, int p_stack_level) {
78
79 ERR_FAIL_COND_V(on->arguments.size() != 1, false);
80
81 int src_address_a = _parse_expression(codegen, on->arguments[0], p_stack_level);
82 if (src_address_a < 0)
83 return false;
84
85 codegen.opcodes.push_back(GDScriptFunction::OPCODE_OPERATOR); // perform operator
86 codegen.opcodes.push_back(op); //which operator
87 codegen.opcodes.push_back(src_address_a); // argument 1
88 codegen.opcodes.push_back(src_address_a); // argument 2 (repeated)
89 //codegen.opcodes.push_back(GDScriptFunction::ADDR_TYPE_NIL); // argument 2 (unary only takes one parameter)
90 return true;
91 }
92
_create_binary_operator(CodeGen & codegen,const GDScriptParser::OperatorNode * on,Variant::Operator op,int p_stack_level,bool p_initializer,int p_index_addr)93 bool GDScriptCompiler::_create_binary_operator(CodeGen &codegen, const GDScriptParser::OperatorNode *on, Variant::Operator op, int p_stack_level, bool p_initializer, int p_index_addr) {
94
95 ERR_FAIL_COND_V(on->arguments.size() != 2, false);
96
97 int src_address_a = _parse_expression(codegen, on->arguments[0], p_stack_level, false, p_initializer, p_index_addr);
98 if (src_address_a < 0)
99 return false;
100 if (src_address_a & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS)
101 p_stack_level++; //uses stack for return, increase stack
102
103 int src_address_b = _parse_expression(codegen, on->arguments[1], p_stack_level, false, p_initializer);
104 if (src_address_b < 0)
105 return false;
106
107 codegen.opcodes.push_back(GDScriptFunction::OPCODE_OPERATOR); // perform operator
108 codegen.opcodes.push_back(op); //which operator
109 codegen.opcodes.push_back(src_address_a); // argument 1
110 codegen.opcodes.push_back(src_address_b); // argument 2 (unary only takes one parameter)
111 return true;
112 }
113
_gdtype_from_datatype(const GDScriptParser::DataType & p_datatype) const114 GDScriptDataType GDScriptCompiler::_gdtype_from_datatype(const GDScriptParser::DataType &p_datatype) const {
115 if (!p_datatype.has_type) {
116 return GDScriptDataType();
117 }
118
119 GDScriptDataType result;
120 result.has_type = true;
121
122 switch (p_datatype.kind) {
123 case GDScriptParser::DataType::BUILTIN: {
124 result.kind = GDScriptDataType::BUILTIN;
125 result.builtin_type = p_datatype.builtin_type;
126 } break;
127 case GDScriptParser::DataType::NATIVE: {
128 result.kind = GDScriptDataType::NATIVE;
129 result.native_type = p_datatype.native_type;
130 } break;
131 case GDScriptParser::DataType::SCRIPT: {
132 result.kind = GDScriptDataType::SCRIPT;
133 result.script_type = p_datatype.script_type;
134 result.native_type = result.script_type->get_instance_base_type();
135 } break;
136 case GDScriptParser::DataType::GDSCRIPT: {
137 result.kind = GDScriptDataType::GDSCRIPT;
138 result.script_type = p_datatype.script_type;
139 result.native_type = result.script_type->get_instance_base_type();
140 } break;
141 case GDScriptParser::DataType::CLASS: {
142 // Locate class by constructing the path to it and following that path
143 GDScriptParser::ClassNode *class_type = p_datatype.class_type;
144 List<StringName> names;
145 while (class_type->owner) {
146 names.push_back(class_type->name);
147 class_type = class_type->owner;
148 }
149
150 Ref<GDScript> script = Ref<GDScript>(main_script);
151 while (names.back()) {
152 if (!script->subclasses.has(names.back()->get())) {
153 ERR_PRINT("Parser bug: Cannot locate datatype class.");
154 result.has_type = false;
155 return GDScriptDataType();
156 }
157 script = script->subclasses[names.back()->get()];
158 names.pop_back();
159 }
160
161 result.kind = GDScriptDataType::GDSCRIPT;
162 result.script_type = script;
163 result.native_type = script->get_instance_base_type();
164 } break;
165 default: {
166 ERR_PRINT("Parser bug: converting unresolved type.");
167 return GDScriptDataType();
168 }
169 }
170
171 return result;
172 }
173
_parse_assign_right_expression(CodeGen & codegen,const GDScriptParser::OperatorNode * p_expression,int p_stack_level,int p_index_addr)174 int GDScriptCompiler::_parse_assign_right_expression(CodeGen &codegen, const GDScriptParser::OperatorNode *p_expression, int p_stack_level, int p_index_addr) {
175
176 Variant::Operator var_op = Variant::OP_MAX;
177
178 switch (p_expression->op) {
179
180 case GDScriptParser::OperatorNode::OP_ASSIGN_ADD: var_op = Variant::OP_ADD; break;
181 case GDScriptParser::OperatorNode::OP_ASSIGN_SUB: var_op = Variant::OP_SUBTRACT; break;
182 case GDScriptParser::OperatorNode::OP_ASSIGN_MUL: var_op = Variant::OP_MULTIPLY; break;
183 case GDScriptParser::OperatorNode::OP_ASSIGN_DIV: var_op = Variant::OP_DIVIDE; break;
184 case GDScriptParser::OperatorNode::OP_ASSIGN_MOD: var_op = Variant::OP_MODULE; break;
185 case GDScriptParser::OperatorNode::OP_ASSIGN_SHIFT_LEFT: var_op = Variant::OP_SHIFT_LEFT; break;
186 case GDScriptParser::OperatorNode::OP_ASSIGN_SHIFT_RIGHT: var_op = Variant::OP_SHIFT_RIGHT; break;
187 case GDScriptParser::OperatorNode::OP_ASSIGN_BIT_AND: var_op = Variant::OP_BIT_AND; break;
188 case GDScriptParser::OperatorNode::OP_ASSIGN_BIT_OR: var_op = Variant::OP_BIT_OR; break;
189 case GDScriptParser::OperatorNode::OP_ASSIGN_BIT_XOR: var_op = Variant::OP_BIT_XOR; break;
190 case GDScriptParser::OperatorNode::OP_INIT_ASSIGN:
191 case GDScriptParser::OperatorNode::OP_ASSIGN: {
192
193 //none
194 } break;
195 default: {
196
197 ERR_FAIL_V(-1);
198 }
199 }
200
201 bool initializer = p_expression->op == GDScriptParser::OperatorNode::OP_INIT_ASSIGN;
202
203 if (var_op == Variant::OP_MAX) {
204
205 return _parse_expression(codegen, p_expression->arguments[1], p_stack_level, false, initializer);
206 }
207
208 if (!_create_binary_operator(codegen, p_expression, var_op, p_stack_level, initializer, p_index_addr))
209 return -1;
210
211 int dst_addr = (p_stack_level) | (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
212 codegen.opcodes.push_back(dst_addr); // append the stack level as destination address of the opcode
213 codegen.alloc_stack(p_stack_level);
214 return dst_addr;
215 }
216
_parse_expression(CodeGen & codegen,const GDScriptParser::Node * p_expression,int p_stack_level,bool p_root,bool p_initializer,int p_index_addr)217 int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser::Node *p_expression, int p_stack_level, bool p_root, bool p_initializer, int p_index_addr) {
218
219 switch (p_expression->type) {
220 //should parse variable declaration and adjust stack accordingly...
221 case GDScriptParser::Node::TYPE_IDENTIFIER: {
222 //return identifier
223 //wait, identifier could be a local variable or something else... careful here, must reference properly
224 //as stack may be more interesting to work with
225
226 //This could be made much simpler by just indexing "self", but done this way (with custom self-addressing modes) increases performance a lot.
227
228 const GDScriptParser::IdentifierNode *in = static_cast<const GDScriptParser::IdentifierNode *>(p_expression);
229
230 StringName identifier = in->name;
231
232 // TRY STACK!
233 if (!p_initializer && codegen.stack_identifiers.has(identifier)) {
234
235 int pos = codegen.stack_identifiers[identifier];
236 return pos | (GDScriptFunction::ADDR_TYPE_STACK_VARIABLE << GDScriptFunction::ADDR_BITS);
237 }
238
239 // TRY CLASS MEMBER
240 if (_is_class_member_property(codegen, identifier)) {
241 //get property
242 codegen.opcodes.push_back(GDScriptFunction::OPCODE_GET_MEMBER); // perform operator
243 codegen.opcodes.push_back(codegen.get_name_map_pos(identifier)); // argument 2 (unary only takes one parameter)
244 int dst_addr = (p_stack_level) | (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
245 codegen.opcodes.push_back(dst_addr); // append the stack level as destination address of the opcode
246 codegen.alloc_stack(p_stack_level);
247 return dst_addr;
248 }
249
250 //TRY MEMBERS!
251 if (!codegen.function_node || !codegen.function_node->_static) {
252
253 // TRY MEMBER VARIABLES!
254 //static function
255 if (codegen.script->member_indices.has(identifier)) {
256
257 int idx = codegen.script->member_indices[identifier].index;
258 return idx | (GDScriptFunction::ADDR_TYPE_MEMBER << GDScriptFunction::ADDR_BITS); //argument (stack root)
259 }
260 }
261
262 //TRY CLASS CONSTANTS
263
264 GDScript *owner = codegen.script;
265 while (owner) {
266
267 GDScript *scr = owner;
268 GDScriptNativeClass *nc = NULL;
269 while (scr) {
270
271 if (scr->constants.has(identifier)) {
272
273 //int idx=scr->constants[identifier];
274 int idx = codegen.get_name_map_pos(identifier);
275 return idx | (GDScriptFunction::ADDR_TYPE_CLASS_CONSTANT << GDScriptFunction::ADDR_BITS); //argument (stack root)
276 }
277 if (scr->native.is_valid())
278 nc = scr->native.ptr();
279 scr = scr->_base;
280 }
281
282 // CLASS C++ Integer Constant
283
284 if (nc) {
285
286 bool success = false;
287 int constant = ClassDB::get_integer_constant(nc->get_name(), identifier, &success);
288 if (success) {
289 Variant key = constant;
290 int idx;
291
292 if (!codegen.constant_map.has(key)) {
293
294 idx = codegen.constant_map.size();
295 codegen.constant_map[key] = idx;
296
297 } else {
298 idx = codegen.constant_map[key];
299 }
300
301 return idx | (GDScriptFunction::ADDR_TYPE_LOCAL_CONSTANT << GDScriptFunction::ADDR_BITS); //make it a local constant (faster access)
302 }
303 }
304
305 owner = owner->_owner;
306 }
307
308 if (GDScriptLanguage::get_singleton()->get_global_map().has(identifier)) {
309
310 int idx = GDScriptLanguage::get_singleton()->get_global_map()[identifier];
311 return idx | (GDScriptFunction::ADDR_TYPE_GLOBAL << GDScriptFunction::ADDR_BITS); //argument (stack root)
312 }
313
314 /* TRY GLOBAL CLASSES */
315
316 if (ScriptServer::is_global_class(identifier)) {
317
318 const GDScriptParser::ClassNode *class_node = codegen.class_node;
319 while (class_node->owner) {
320 class_node = class_node->owner;
321 }
322
323 if (class_node->name == identifier) {
324 _set_error("Using own name in class file is not allowed (creates a cyclic reference)", p_expression);
325 return -1;
326 }
327
328 RES res = ResourceLoader::load(ScriptServer::get_global_class_path(identifier));
329 if (res.is_null()) {
330 _set_error("Can't load global class " + String(identifier) + ", cyclic reference?", p_expression);
331 return -1;
332 }
333
334 Variant key = res;
335 int idx;
336
337 if (!codegen.constant_map.has(key)) {
338
339 idx = codegen.constant_map.size();
340 codegen.constant_map[key] = idx;
341
342 } else {
343 idx = codegen.constant_map[key];
344 }
345
346 return idx | (GDScriptFunction::ADDR_TYPE_LOCAL_CONSTANT << GDScriptFunction::ADDR_BITS); //make it a local constant (faster access)
347 }
348
349 #ifdef TOOLS_ENABLED
350 if (GDScriptLanguage::get_singleton()->get_named_globals_map().has(identifier)) {
351
352 int idx = codegen.named_globals.find(identifier);
353 if (idx == -1) {
354 idx = codegen.named_globals.size();
355 codegen.named_globals.push_back(identifier);
356 }
357 return idx | (GDScriptFunction::ADDR_TYPE_NAMED_GLOBAL << GDScriptFunction::ADDR_BITS);
358 }
359 #endif
360
361 //not found, error
362
363 _set_error("Identifier not found: " + String(identifier), p_expression);
364
365 return -1;
366
367 } break;
368 case GDScriptParser::Node::TYPE_CONSTANT: {
369 //return constant
370 const GDScriptParser::ConstantNode *cn = static_cast<const GDScriptParser::ConstantNode *>(p_expression);
371
372 int idx;
373
374 if (!codegen.constant_map.has(cn->value)) {
375
376 idx = codegen.constant_map.size();
377 codegen.constant_map[cn->value] = idx;
378
379 } else {
380 idx = codegen.constant_map[cn->value];
381 }
382
383 return idx | (GDScriptFunction::ADDR_TYPE_LOCAL_CONSTANT << GDScriptFunction::ADDR_BITS); //argument (stack root)
384
385 } break;
386 case GDScriptParser::Node::TYPE_SELF: {
387 //return constant
388 if (codegen.function_node && codegen.function_node->_static) {
389 _set_error("'self' not present in static function!", p_expression);
390 return -1;
391 }
392 return (GDScriptFunction::ADDR_TYPE_SELF << GDScriptFunction::ADDR_BITS);
393 } break;
394 case GDScriptParser::Node::TYPE_ARRAY: {
395
396 const GDScriptParser::ArrayNode *an = static_cast<const GDScriptParser::ArrayNode *>(p_expression);
397 Vector<int> values;
398
399 int slevel = p_stack_level;
400
401 for (int i = 0; i < an->elements.size(); i++) {
402
403 int ret = _parse_expression(codegen, an->elements[i], slevel);
404 if (ret < 0)
405 return ret;
406 if ((ret >> GDScriptFunction::ADDR_BITS & GDScriptFunction::ADDR_TYPE_STACK) == GDScriptFunction::ADDR_TYPE_STACK) {
407 slevel++;
408 codegen.alloc_stack(slevel);
409 }
410
411 values.push_back(ret);
412 }
413
414 codegen.opcodes.push_back(GDScriptFunction::OPCODE_CONSTRUCT_ARRAY);
415 codegen.opcodes.push_back(values.size());
416 for (int i = 0; i < values.size(); i++)
417 codegen.opcodes.push_back(values[i]);
418
419 int dst_addr = (p_stack_level) | (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
420 codegen.opcodes.push_back(dst_addr); // append the stack level as destination address of the opcode
421 codegen.alloc_stack(p_stack_level);
422 return dst_addr;
423
424 } break;
425 case GDScriptParser::Node::TYPE_DICTIONARY: {
426
427 const GDScriptParser::DictionaryNode *dn = static_cast<const GDScriptParser::DictionaryNode *>(p_expression);
428 Vector<int> values;
429
430 int slevel = p_stack_level;
431
432 for (int i = 0; i < dn->elements.size(); i++) {
433
434 int ret = _parse_expression(codegen, dn->elements[i].key, slevel);
435 if (ret < 0)
436 return ret;
437 if ((ret >> GDScriptFunction::ADDR_BITS & GDScriptFunction::ADDR_TYPE_STACK) == GDScriptFunction::ADDR_TYPE_STACK) {
438 slevel++;
439 codegen.alloc_stack(slevel);
440 }
441
442 values.push_back(ret);
443
444 ret = _parse_expression(codegen, dn->elements[i].value, slevel);
445 if (ret < 0)
446 return ret;
447 if ((ret >> GDScriptFunction::ADDR_BITS & GDScriptFunction::ADDR_TYPE_STACK) == GDScriptFunction::ADDR_TYPE_STACK) {
448 slevel++;
449 codegen.alloc_stack(slevel);
450 }
451
452 values.push_back(ret);
453 }
454
455 codegen.opcodes.push_back(GDScriptFunction::OPCODE_CONSTRUCT_DICTIONARY);
456 codegen.opcodes.push_back(dn->elements.size());
457 for (int i = 0; i < values.size(); i++)
458 codegen.opcodes.push_back(values[i]);
459
460 int dst_addr = (p_stack_level) | (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
461 codegen.opcodes.push_back(dst_addr); // append the stack level as destination address of the opcode
462 codegen.alloc_stack(p_stack_level);
463 return dst_addr;
464
465 } break;
466 case GDScriptParser::Node::TYPE_CAST: {
467 const GDScriptParser::CastNode *cn = static_cast<const GDScriptParser::CastNode *>(p_expression);
468
469 int slevel = p_stack_level;
470 int src_addr = _parse_expression(codegen, cn->source_node, slevel);
471 if (src_addr < 0)
472 return src_addr;
473 if (src_addr & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS) {
474 slevel++;
475 codegen.alloc_stack(slevel);
476 }
477
478 GDScriptDataType cast_type = _gdtype_from_datatype(cn->cast_type);
479
480 switch (cast_type.kind) {
481 case GDScriptDataType::BUILTIN: {
482 codegen.opcodes.push_back(GDScriptFunction::OPCODE_CAST_TO_BUILTIN);
483 codegen.opcodes.push_back(cast_type.builtin_type);
484 } break;
485 case GDScriptDataType::NATIVE: {
486 int class_idx;
487 if (GDScriptLanguage::get_singleton()->get_global_map().has(cast_type.native_type)) {
488
489 class_idx = GDScriptLanguage::get_singleton()->get_global_map()[cast_type.native_type];
490 class_idx |= (GDScriptFunction::ADDR_TYPE_GLOBAL << GDScriptFunction::ADDR_BITS); //argument (stack root)
491 } else {
492 _set_error("Invalid native class type '" + String(cast_type.native_type) + "'.", cn);
493 return -1;
494 }
495 codegen.opcodes.push_back(GDScriptFunction::OPCODE_CAST_TO_NATIVE); // perform operator
496 codegen.opcodes.push_back(class_idx); // variable type
497 } break;
498 case GDScriptDataType::SCRIPT:
499 case GDScriptDataType::GDSCRIPT: {
500
501 Variant script = cast_type.script_type;
502 int idx = codegen.get_constant_pos(script);
503 idx |= GDScriptFunction::ADDR_TYPE_LOCAL_CONSTANT << GDScriptFunction::ADDR_BITS; //make it a local constant (faster access)
504
505 codegen.opcodes.push_back(GDScriptFunction::OPCODE_CAST_TO_SCRIPT); // perform operator
506 codegen.opcodes.push_back(idx); // variable type
507 } break;
508 default: {
509 _set_error("Parser bug: unresolved data type.", cn);
510 return -1;
511 }
512 }
513
514 codegen.opcodes.push_back(src_addr); // source address
515 int dst_addr = (p_stack_level) | (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
516 codegen.opcodes.push_back(dst_addr); // append the stack level as destination address of the opcode
517 codegen.alloc_stack(p_stack_level);
518 return dst_addr;
519
520 } break;
521 case GDScriptParser::Node::TYPE_OPERATOR: {
522 //hell breaks loose
523
524 const GDScriptParser::OperatorNode *on = static_cast<const GDScriptParser::OperatorNode *>(p_expression);
525 switch (on->op) {
526
527 //call/constructor operator
528 case GDScriptParser::OperatorNode::OP_PARENT_CALL: {
529
530 ERR_FAIL_COND_V(on->arguments.size() < 1, -1);
531
532 const GDScriptParser::IdentifierNode *in = (const GDScriptParser::IdentifierNode *)on->arguments[0];
533
534 Vector<int> arguments;
535 int slevel = p_stack_level;
536 for (int i = 1; i < on->arguments.size(); i++) {
537
538 int ret = _parse_expression(codegen, on->arguments[i], slevel);
539 if (ret < 0)
540 return ret;
541 if ((ret >> GDScriptFunction::ADDR_BITS & GDScriptFunction::ADDR_TYPE_STACK) == GDScriptFunction::ADDR_TYPE_STACK) {
542 slevel++;
543 codegen.alloc_stack(slevel);
544 }
545 arguments.push_back(ret);
546 }
547
548 //push call bytecode
549 codegen.opcodes.push_back(GDScriptFunction::OPCODE_CALL_SELF_BASE); // basic type constructor
550
551 codegen.opcodes.push_back(codegen.get_name_map_pos(in->name)); //instance
552 codegen.opcodes.push_back(arguments.size()); //argument count
553 codegen.alloc_call(arguments.size());
554 for (int i = 0; i < arguments.size(); i++)
555 codegen.opcodes.push_back(arguments[i]); //arguments
556
557 } break;
558 case GDScriptParser::OperatorNode::OP_CALL: {
559
560 if (on->arguments[0]->type == GDScriptParser::Node::TYPE_TYPE) {
561 //construct a basic type
562 ERR_FAIL_COND_V(on->arguments.size() < 1, -1);
563
564 const GDScriptParser::TypeNode *tn = (const GDScriptParser::TypeNode *)on->arguments[0];
565 int vtype = tn->vtype;
566
567 Vector<int> arguments;
568 int slevel = p_stack_level;
569 for (int i = 1; i < on->arguments.size(); i++) {
570
571 int ret = _parse_expression(codegen, on->arguments[i], slevel);
572 if (ret < 0)
573 return ret;
574 if ((ret >> GDScriptFunction::ADDR_BITS & GDScriptFunction::ADDR_TYPE_STACK) == GDScriptFunction::ADDR_TYPE_STACK) {
575 slevel++;
576 codegen.alloc_stack(slevel);
577 }
578 arguments.push_back(ret);
579 }
580
581 //push call bytecode
582 codegen.opcodes.push_back(GDScriptFunction::OPCODE_CONSTRUCT); // basic type constructor
583 codegen.opcodes.push_back(vtype); //instance
584 codegen.opcodes.push_back(arguments.size()); //argument count
585 codegen.alloc_call(arguments.size());
586 for (int i = 0; i < arguments.size(); i++)
587 codegen.opcodes.push_back(arguments[i]); //arguments
588
589 } else if (on->arguments[0]->type == GDScriptParser::Node::TYPE_BUILT_IN_FUNCTION) {
590 //built in function
591
592 ERR_FAIL_COND_V(on->arguments.size() < 1, -1);
593
594 Vector<int> arguments;
595 int slevel = p_stack_level;
596 for (int i = 1; i < on->arguments.size(); i++) {
597
598 int ret = _parse_expression(codegen, on->arguments[i], slevel);
599 if (ret < 0)
600 return ret;
601
602 if ((ret >> GDScriptFunction::ADDR_BITS & GDScriptFunction::ADDR_TYPE_STACK) == GDScriptFunction::ADDR_TYPE_STACK) {
603 slevel++;
604 codegen.alloc_stack(slevel);
605 }
606
607 arguments.push_back(ret);
608 }
609
610 codegen.opcodes.push_back(GDScriptFunction::OPCODE_CALL_BUILT_IN);
611 codegen.opcodes.push_back(static_cast<const GDScriptParser::BuiltInFunctionNode *>(on->arguments[0])->function);
612 codegen.opcodes.push_back(on->arguments.size() - 1);
613 codegen.alloc_call(on->arguments.size() - 1);
614 for (int i = 0; i < arguments.size(); i++)
615 codegen.opcodes.push_back(arguments[i]);
616
617 } else {
618 //regular function
619 ERR_FAIL_COND_V(on->arguments.size() < 2, -1);
620
621 const GDScriptParser::Node *instance = on->arguments[0];
622
623 if (instance->type == GDScriptParser::Node::TYPE_SELF) {
624 //room for optimization
625 }
626
627 Vector<int> arguments;
628 int slevel = p_stack_level;
629
630 for (int i = 0; i < on->arguments.size(); i++) {
631
632 int ret;
633
634 if (i == 0 && on->arguments[i]->type == GDScriptParser::Node::TYPE_SELF && codegen.function_node && codegen.function_node->_static) {
635 //static call to self
636 ret = (GDScriptFunction::ADDR_TYPE_CLASS << GDScriptFunction::ADDR_BITS);
637 } else if (i == 1) {
638
639 if (on->arguments[i]->type != GDScriptParser::Node::TYPE_IDENTIFIER) {
640 _set_error("Attempt to call a non-identifier.", on);
641 return -1;
642 }
643 GDScriptParser::IdentifierNode *id = static_cast<GDScriptParser::IdentifierNode *>(on->arguments[i]);
644 ret = codegen.get_name_map_pos(id->name);
645
646 } else {
647
648 ret = _parse_expression(codegen, on->arguments[i], slevel);
649 if (ret < 0)
650 return ret;
651 if ((ret >> GDScriptFunction::ADDR_BITS & GDScriptFunction::ADDR_TYPE_STACK) == GDScriptFunction::ADDR_TYPE_STACK) {
652 slevel++;
653 codegen.alloc_stack(slevel);
654 }
655 }
656 arguments.push_back(ret);
657 }
658
659 codegen.opcodes.push_back(p_root ? GDScriptFunction::OPCODE_CALL : GDScriptFunction::OPCODE_CALL_RETURN); // perform operator
660 codegen.opcodes.push_back(on->arguments.size() - 2);
661 codegen.alloc_call(on->arguments.size() - 2);
662 for (int i = 0; i < arguments.size(); i++)
663 codegen.opcodes.push_back(arguments[i]);
664 }
665 } break;
666 case GDScriptParser::OperatorNode::OP_YIELD: {
667
668 ERR_FAIL_COND_V(on->arguments.size() && on->arguments.size() != 2, -1);
669
670 Vector<int> arguments;
671 int slevel = p_stack_level;
672 for (int i = 0; i < on->arguments.size(); i++) {
673
674 int ret = _parse_expression(codegen, on->arguments[i], slevel);
675 if (ret < 0)
676 return ret;
677 if ((ret >> GDScriptFunction::ADDR_BITS & GDScriptFunction::ADDR_TYPE_STACK) == GDScriptFunction::ADDR_TYPE_STACK) {
678 slevel++;
679 codegen.alloc_stack(slevel);
680 }
681 arguments.push_back(ret);
682 }
683
684 //push call bytecode
685 codegen.opcodes.push_back(arguments.size() == 0 ? GDScriptFunction::OPCODE_YIELD : GDScriptFunction::OPCODE_YIELD_SIGNAL); // basic type constructor
686 for (int i = 0; i < arguments.size(); i++)
687 codegen.opcodes.push_back(arguments[i]); //arguments
688 codegen.opcodes.push_back(GDScriptFunction::OPCODE_YIELD_RESUME);
689 //next will be where to place the result :)
690
691 } break;
692
693 //indexing operator
694 case GDScriptParser::OperatorNode::OP_INDEX:
695 case GDScriptParser::OperatorNode::OP_INDEX_NAMED: {
696
697 ERR_FAIL_COND_V(on->arguments.size() != 2, -1);
698
699 int slevel = p_stack_level;
700 bool named = (on->op == GDScriptParser::OperatorNode::OP_INDEX_NAMED);
701
702 int from = _parse_expression(codegen, on->arguments[0], slevel);
703 if (from < 0)
704 return from;
705
706 int index;
707 if (p_index_addr != 0) {
708 index = p_index_addr;
709 } else if (named) {
710 if (on->arguments[0]->type == GDScriptParser::Node::TYPE_SELF && codegen.script && codegen.function_node && !codegen.function_node->_static) {
711
712 GDScriptParser::IdentifierNode *identifier = static_cast<GDScriptParser::IdentifierNode *>(on->arguments[1]);
713 const Map<StringName, GDScript::MemberInfo>::Element *MI = codegen.script->member_indices.find(identifier->name);
714
715 #ifdef DEBUG_ENABLED
716 if (MI && MI->get().getter == codegen.function_node->name) {
717 String n = static_cast<GDScriptParser::IdentifierNode *>(on->arguments[1])->name;
718 _set_error("Must use '" + n + "' instead of 'self." + n + "' in getter.", on);
719 return -1;
720 }
721 #endif
722
723 if (MI && MI->get().getter == "") {
724 // Faster than indexing self (as if no self. had been used)
725 return (MI->get().index) | (GDScriptFunction::ADDR_TYPE_MEMBER << GDScriptFunction::ADDR_BITS);
726 }
727 }
728
729 index = codegen.get_name_map_pos(static_cast<GDScriptParser::IdentifierNode *>(on->arguments[1])->name);
730
731 } else {
732
733 if (on->arguments[1]->type == GDScriptParser::Node::TYPE_CONSTANT && static_cast<const GDScriptParser::ConstantNode *>(on->arguments[1])->value.get_type() == Variant::STRING) {
734 //also, somehow, named (speed up anyway)
735 StringName name = static_cast<const GDScriptParser::ConstantNode *>(on->arguments[1])->value;
736 index = codegen.get_name_map_pos(name);
737 named = true;
738
739 } else {
740 //regular indexing
741 if (from & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS) {
742 slevel++;
743 codegen.alloc_stack(slevel);
744 }
745
746 index = _parse_expression(codegen, on->arguments[1], slevel);
747 if (index < 0)
748 return index;
749 }
750 }
751
752 codegen.opcodes.push_back(named ? GDScriptFunction::OPCODE_GET_NAMED : GDScriptFunction::OPCODE_GET); // perform operator
753 codegen.opcodes.push_back(from); // argument 1
754 codegen.opcodes.push_back(index); // argument 2 (unary only takes one parameter)
755
756 } break;
757 case GDScriptParser::OperatorNode::OP_AND: {
758
759 // AND operator with early out on failure
760
761 int res = _parse_expression(codegen, on->arguments[0], p_stack_level);
762 if (res < 0)
763 return res;
764 codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP_IF_NOT);
765 codegen.opcodes.push_back(res);
766 int jump_fail_pos = codegen.opcodes.size();
767 codegen.opcodes.push_back(0);
768
769 res = _parse_expression(codegen, on->arguments[1], p_stack_level);
770 if (res < 0)
771 return res;
772
773 codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP_IF_NOT);
774 codegen.opcodes.push_back(res);
775 int jump_fail_pos2 = codegen.opcodes.size();
776 codegen.opcodes.push_back(0);
777
778 codegen.alloc_stack(p_stack_level); //it will be used..
779 codegen.opcodes.push_back(GDScriptFunction::OPCODE_ASSIGN_TRUE);
780 codegen.opcodes.push_back(p_stack_level | GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
781 codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP);
782 codegen.opcodes.push_back(codegen.opcodes.size() + 3);
783 codegen.opcodes.write[jump_fail_pos] = codegen.opcodes.size();
784 codegen.opcodes.write[jump_fail_pos2] = codegen.opcodes.size();
785 codegen.opcodes.push_back(GDScriptFunction::OPCODE_ASSIGN_FALSE);
786 codegen.opcodes.push_back(p_stack_level | GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
787 return p_stack_level | GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS;
788
789 } break;
790 case GDScriptParser::OperatorNode::OP_OR: {
791
792 // OR operator with early out on success
793
794 int res = _parse_expression(codegen, on->arguments[0], p_stack_level);
795 if (res < 0)
796 return res;
797 codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP_IF);
798 codegen.opcodes.push_back(res);
799 int jump_success_pos = codegen.opcodes.size();
800 codegen.opcodes.push_back(0);
801
802 res = _parse_expression(codegen, on->arguments[1], p_stack_level);
803 if (res < 0)
804 return res;
805
806 codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP_IF);
807 codegen.opcodes.push_back(res);
808 int jump_success_pos2 = codegen.opcodes.size();
809 codegen.opcodes.push_back(0);
810
811 codegen.alloc_stack(p_stack_level); //it will be used..
812 codegen.opcodes.push_back(GDScriptFunction::OPCODE_ASSIGN_FALSE);
813 codegen.opcodes.push_back(p_stack_level | GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
814 codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP);
815 codegen.opcodes.push_back(codegen.opcodes.size() + 3);
816 codegen.opcodes.write[jump_success_pos] = codegen.opcodes.size();
817 codegen.opcodes.write[jump_success_pos2] = codegen.opcodes.size();
818 codegen.opcodes.push_back(GDScriptFunction::OPCODE_ASSIGN_TRUE);
819 codegen.opcodes.push_back(p_stack_level | GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
820 return p_stack_level | GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS;
821
822 } break;
823 // ternary operators
824 case GDScriptParser::OperatorNode::OP_TERNARY_IF: {
825
826 // x IF a ELSE y operator with early out on failure
827
828 int res = _parse_expression(codegen, on->arguments[0], p_stack_level);
829 if (res < 0)
830 return res;
831 codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP_IF_NOT);
832 codegen.opcodes.push_back(res);
833 int jump_fail_pos = codegen.opcodes.size();
834 codegen.opcodes.push_back(0);
835
836 res = _parse_expression(codegen, on->arguments[1], p_stack_level);
837 if (res < 0)
838 return res;
839
840 codegen.alloc_stack(p_stack_level); //it will be used..
841 codegen.opcodes.push_back(GDScriptFunction::OPCODE_ASSIGN);
842 codegen.opcodes.push_back(p_stack_level | GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
843 codegen.opcodes.push_back(res);
844 codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP);
845 int jump_past_pos = codegen.opcodes.size();
846 codegen.opcodes.push_back(0);
847
848 codegen.opcodes.write[jump_fail_pos] = codegen.opcodes.size();
849 res = _parse_expression(codegen, on->arguments[2], p_stack_level);
850 if (res < 0)
851 return res;
852
853 codegen.opcodes.push_back(GDScriptFunction::OPCODE_ASSIGN);
854 codegen.opcodes.push_back(p_stack_level | GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
855 codegen.opcodes.push_back(res);
856
857 codegen.opcodes.write[jump_past_pos] = codegen.opcodes.size();
858
859 return p_stack_level | GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS;
860
861 } break;
862 //unary operators
863 case GDScriptParser::OperatorNode::OP_NEG: {
864 if (!_create_unary_operator(codegen, on, Variant::OP_NEGATE, p_stack_level)) return -1;
865 } break;
866 case GDScriptParser::OperatorNode::OP_POS: {
867 if (!_create_unary_operator(codegen, on, Variant::OP_POSITIVE, p_stack_level)) return -1;
868 } break;
869 case GDScriptParser::OperatorNode::OP_NOT: {
870 if (!_create_unary_operator(codegen, on, Variant::OP_NOT, p_stack_level)) return -1;
871 } break;
872 case GDScriptParser::OperatorNode::OP_BIT_INVERT: {
873 if (!_create_unary_operator(codegen, on, Variant::OP_BIT_NEGATE, p_stack_level)) return -1;
874 } break;
875 //binary operators (in precedence order)
876 case GDScriptParser::OperatorNode::OP_IN: {
877 if (!_create_binary_operator(codegen, on, Variant::OP_IN, p_stack_level)) return -1;
878 } break;
879 case GDScriptParser::OperatorNode::OP_EQUAL: {
880 if (!_create_binary_operator(codegen, on, Variant::OP_EQUAL, p_stack_level)) return -1;
881 } break;
882 case GDScriptParser::OperatorNode::OP_NOT_EQUAL: {
883 if (!_create_binary_operator(codegen, on, Variant::OP_NOT_EQUAL, p_stack_level)) return -1;
884 } break;
885 case GDScriptParser::OperatorNode::OP_LESS: {
886 if (!_create_binary_operator(codegen, on, Variant::OP_LESS, p_stack_level)) return -1;
887 } break;
888 case GDScriptParser::OperatorNode::OP_LESS_EQUAL: {
889 if (!_create_binary_operator(codegen, on, Variant::OP_LESS_EQUAL, p_stack_level)) return -1;
890 } break;
891 case GDScriptParser::OperatorNode::OP_GREATER: {
892 if (!_create_binary_operator(codegen, on, Variant::OP_GREATER, p_stack_level)) return -1;
893 } break;
894 case GDScriptParser::OperatorNode::OP_GREATER_EQUAL: {
895 if (!_create_binary_operator(codegen, on, Variant::OP_GREATER_EQUAL, p_stack_level)) return -1;
896 } break;
897 case GDScriptParser::OperatorNode::OP_ADD: {
898 if (!_create_binary_operator(codegen, on, Variant::OP_ADD, p_stack_level)) return -1;
899 } break;
900 case GDScriptParser::OperatorNode::OP_SUB: {
901 if (!_create_binary_operator(codegen, on, Variant::OP_SUBTRACT, p_stack_level)) return -1;
902 } break;
903 case GDScriptParser::OperatorNode::OP_MUL: {
904 if (!_create_binary_operator(codegen, on, Variant::OP_MULTIPLY, p_stack_level)) return -1;
905 } break;
906 case GDScriptParser::OperatorNode::OP_DIV: {
907 if (!_create_binary_operator(codegen, on, Variant::OP_DIVIDE, p_stack_level)) return -1;
908 } break;
909 case GDScriptParser::OperatorNode::OP_MOD: {
910 if (!_create_binary_operator(codegen, on, Variant::OP_MODULE, p_stack_level)) return -1;
911 } break;
912 //case GDScriptParser::OperatorNode::OP_SHIFT_LEFT: { if (!_create_binary_operator(codegen,on,Variant::OP_SHIFT_LEFT,p_stack_level)) return -1;} break;
913 //case GDScriptParser::OperatorNode::OP_SHIFT_RIGHT: { if (!_create_binary_operator(codegen,on,Variant::OP_SHIFT_RIGHT,p_stack_level)) return -1;} break;
914 case GDScriptParser::OperatorNode::OP_BIT_AND: {
915 if (!_create_binary_operator(codegen, on, Variant::OP_BIT_AND, p_stack_level)) return -1;
916 } break;
917 case GDScriptParser::OperatorNode::OP_BIT_OR: {
918 if (!_create_binary_operator(codegen, on, Variant::OP_BIT_OR, p_stack_level)) return -1;
919 } break;
920 case GDScriptParser::OperatorNode::OP_BIT_XOR: {
921 if (!_create_binary_operator(codegen, on, Variant::OP_BIT_XOR, p_stack_level)) return -1;
922 } break;
923 //shift
924 case GDScriptParser::OperatorNode::OP_SHIFT_LEFT: {
925 if (!_create_binary_operator(codegen, on, Variant::OP_SHIFT_LEFT, p_stack_level)) return -1;
926 } break;
927 case GDScriptParser::OperatorNode::OP_SHIFT_RIGHT: {
928 if (!_create_binary_operator(codegen, on, Variant::OP_SHIFT_RIGHT, p_stack_level)) return -1;
929 } break;
930 //assignment operators
931 case GDScriptParser::OperatorNode::OP_ASSIGN_ADD:
932 case GDScriptParser::OperatorNode::OP_ASSIGN_SUB:
933 case GDScriptParser::OperatorNode::OP_ASSIGN_MUL:
934 case GDScriptParser::OperatorNode::OP_ASSIGN_DIV:
935 case GDScriptParser::OperatorNode::OP_ASSIGN_MOD:
936 case GDScriptParser::OperatorNode::OP_ASSIGN_SHIFT_LEFT:
937 case GDScriptParser::OperatorNode::OP_ASSIGN_SHIFT_RIGHT:
938 case GDScriptParser::OperatorNode::OP_ASSIGN_BIT_AND:
939 case GDScriptParser::OperatorNode::OP_ASSIGN_BIT_OR:
940 case GDScriptParser::OperatorNode::OP_ASSIGN_BIT_XOR:
941 case GDScriptParser::OperatorNode::OP_INIT_ASSIGN:
942 case GDScriptParser::OperatorNode::OP_ASSIGN: {
943
944 ERR_FAIL_COND_V(on->arguments.size() != 2, -1);
945
946 if (on->arguments[0]->type == GDScriptParser::Node::TYPE_OPERATOR && (static_cast<GDScriptParser::OperatorNode *>(on->arguments[0])->op == GDScriptParser::OperatorNode::OP_INDEX || static_cast<GDScriptParser::OperatorNode *>(on->arguments[0])->op == GDScriptParser::OperatorNode::OP_INDEX_NAMED)) {
947
948 // SET (chained) MODE!
949 #ifdef DEBUG_ENABLED
950 if (static_cast<GDScriptParser::OperatorNode *>(on->arguments[0])->op == GDScriptParser::OperatorNode::OP_INDEX_NAMED) {
951 const GDScriptParser::OperatorNode *inon = static_cast<GDScriptParser::OperatorNode *>(on->arguments[0]);
952
953 if (inon->arguments[0]->type == GDScriptParser::Node::TYPE_SELF && codegen.script && codegen.function_node && !codegen.function_node->_static) {
954
955 const Map<StringName, GDScript::MemberInfo>::Element *MI = codegen.script->member_indices.find(static_cast<GDScriptParser::IdentifierNode *>(inon->arguments[1])->name);
956 if (MI && MI->get().setter == codegen.function_node->name) {
957 String n = static_cast<GDScriptParser::IdentifierNode *>(inon->arguments[1])->name;
958 _set_error("Must use '" + n + "' instead of 'self." + n + "' in setter.", inon);
959 return -1;
960 }
961 }
962 }
963 #endif
964
965 int slevel = p_stack_level;
966
967 GDScriptParser::OperatorNode *op = static_cast<GDScriptParser::OperatorNode *>(on->arguments[0]);
968
969 /* Find chain of sets */
970
971 StringName assign_property;
972
973 List<GDScriptParser::OperatorNode *> chain;
974
975 {
976 //create get/set chain
977 GDScriptParser::OperatorNode *n = op;
978 while (true) {
979
980 chain.push_back(n);
981 if (n->arguments[0]->type != GDScriptParser::Node::TYPE_OPERATOR) {
982
983 //check for a built-in property
984 if (n->arguments[0]->type == GDScriptParser::Node::TYPE_IDENTIFIER) {
985
986 GDScriptParser::IdentifierNode *identifier = static_cast<GDScriptParser::IdentifierNode *>(n->arguments[0]);
987 if (_is_class_member_property(codegen, identifier->name)) {
988 assign_property = identifier->name;
989 }
990 }
991 break;
992 }
993 n = static_cast<GDScriptParser::OperatorNode *>(n->arguments[0]);
994 if (n->op != GDScriptParser::OperatorNode::OP_INDEX && n->op != GDScriptParser::OperatorNode::OP_INDEX_NAMED)
995 break;
996 }
997 }
998
999 /* Chain of gets */
1000
1001 //get at (potential) root stack pos, so it can be returned
1002 int prev_pos = _parse_expression(codegen, chain.back()->get()->arguments[0], slevel);
1003 if (prev_pos < 0)
1004 return prev_pos;
1005 int retval = prev_pos;
1006
1007 if (retval & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS) {
1008 slevel++;
1009 codegen.alloc_stack(slevel);
1010 }
1011
1012 Vector<int> setchain;
1013
1014 if (assign_property != StringName()) {
1015
1016 // recover and assign at the end, this allows stuff like
1017 // position.x+=2.0
1018 // in Node2D
1019 setchain.push_back(prev_pos);
1020 setchain.push_back(codegen.get_name_map_pos(assign_property));
1021 setchain.push_back(GDScriptFunction::OPCODE_SET_MEMBER);
1022 }
1023
1024 for (List<GDScriptParser::OperatorNode *>::Element *E = chain.back(); E; E = E->prev()) {
1025
1026 if (E == chain.front()) //ignore first
1027 break;
1028
1029 bool named = E->get()->op == GDScriptParser::OperatorNode::OP_INDEX_NAMED;
1030 int key_idx;
1031
1032 if (named) {
1033
1034 key_idx = codegen.get_name_map_pos(static_cast<const GDScriptParser::IdentifierNode *>(E->get()->arguments[1])->name);
1035 //printf("named key %x\n",key_idx);
1036
1037 } else {
1038
1039 if (prev_pos & (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS)) {
1040 slevel++;
1041 codegen.alloc_stack(slevel);
1042 }
1043
1044 GDScriptParser::Node *key = E->get()->arguments[1];
1045 key_idx = _parse_expression(codegen, key, slevel);
1046 //printf("expr key %x\n",key_idx);
1047
1048 //stack was raised here if retval was stack but..
1049 }
1050
1051 if (key_idx < 0) //error
1052 return key_idx;
1053
1054 codegen.opcodes.push_back(named ? GDScriptFunction::OPCODE_GET_NAMED : GDScriptFunction::OPCODE_GET);
1055 codegen.opcodes.push_back(prev_pos);
1056 codegen.opcodes.push_back(key_idx);
1057 slevel++;
1058 codegen.alloc_stack(slevel);
1059 int dst_pos = (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS) | slevel;
1060
1061 codegen.opcodes.push_back(dst_pos);
1062
1063 //add in reverse order, since it will be reverted
1064
1065 setchain.push_back(dst_pos);
1066 setchain.push_back(key_idx);
1067 setchain.push_back(prev_pos);
1068 setchain.push_back(named ? GDScriptFunction::OPCODE_SET_NAMED : GDScriptFunction::OPCODE_SET);
1069
1070 prev_pos = dst_pos;
1071 }
1072
1073 setchain.invert();
1074
1075 int set_index;
1076 bool named = false;
1077
1078 if (op->op == GDScriptParser::OperatorNode::OP_INDEX_NAMED) {
1079
1080 set_index = codegen.get_name_map_pos(static_cast<const GDScriptParser::IdentifierNode *>(op->arguments[1])->name);
1081 named = true;
1082 } else {
1083
1084 set_index = _parse_expression(codegen, op->arguments[1], slevel + 1);
1085 named = false;
1086 }
1087
1088 if (set_index < 0) //error
1089 return set_index;
1090
1091 if (set_index & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS) {
1092 slevel++;
1093 codegen.alloc_stack(slevel);
1094 }
1095
1096 int set_value = _parse_assign_right_expression(codegen, on, slevel + 1, named ? 0 : set_index);
1097 if (set_value < 0) //error
1098 return set_value;
1099
1100 codegen.opcodes.push_back(named ? GDScriptFunction::OPCODE_SET_NAMED : GDScriptFunction::OPCODE_SET);
1101 codegen.opcodes.push_back(prev_pos);
1102 codegen.opcodes.push_back(set_index);
1103 codegen.opcodes.push_back(set_value);
1104
1105 for (int i = 0; i < setchain.size(); i++) {
1106
1107 codegen.opcodes.push_back(setchain[i]);
1108 }
1109
1110 return retval;
1111
1112 } else if (on->arguments[0]->type == GDScriptParser::Node::TYPE_IDENTIFIER && _is_class_member_property(codegen, static_cast<GDScriptParser::IdentifierNode *>(on->arguments[0])->name)) {
1113 //assignment to member property
1114
1115 int slevel = p_stack_level;
1116
1117 int src_address = _parse_assign_right_expression(codegen, on, slevel);
1118 if (src_address < 0)
1119 return -1;
1120
1121 StringName name = static_cast<GDScriptParser::IdentifierNode *>(on->arguments[0])->name;
1122
1123 codegen.opcodes.push_back(GDScriptFunction::OPCODE_SET_MEMBER);
1124 codegen.opcodes.push_back(codegen.get_name_map_pos(name));
1125 codegen.opcodes.push_back(src_address);
1126
1127 return GDScriptFunction::ADDR_TYPE_NIL << GDScriptFunction::ADDR_BITS;
1128 } else {
1129
1130 //REGULAR ASSIGNMENT MODE!!
1131
1132 int slevel = p_stack_level;
1133
1134 int dst_address_a = _parse_expression(codegen, on->arguments[0], slevel, false, on->op == GDScriptParser::OperatorNode::OP_INIT_ASSIGN);
1135 if (dst_address_a < 0)
1136 return -1;
1137
1138 if (dst_address_a & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS) {
1139 slevel++;
1140 codegen.alloc_stack(slevel);
1141 }
1142
1143 int src_address_b = _parse_assign_right_expression(codegen, on, slevel);
1144 if (src_address_b < 0)
1145 return -1;
1146
1147 GDScriptDataType assign_type = _gdtype_from_datatype(on->arguments[0]->get_datatype());
1148
1149 if (assign_type.has_type && !on->datatype.has_type) {
1150 // Typed assignment
1151 switch (assign_type.kind) {
1152 case GDScriptDataType::BUILTIN: {
1153 codegen.opcodes.push_back(GDScriptFunction::OPCODE_ASSIGN_TYPED_BUILTIN); // perform operator
1154 codegen.opcodes.push_back(assign_type.builtin_type); // variable type
1155 codegen.opcodes.push_back(dst_address_a); // argument 1
1156 codegen.opcodes.push_back(src_address_b); // argument 2
1157 } break;
1158 case GDScriptDataType::NATIVE: {
1159 int class_idx;
1160 if (GDScriptLanguage::get_singleton()->get_global_map().has(assign_type.native_type)) {
1161
1162 class_idx = GDScriptLanguage::get_singleton()->get_global_map()[assign_type.native_type];
1163 class_idx |= (GDScriptFunction::ADDR_TYPE_GLOBAL << GDScriptFunction::ADDR_BITS); //argument (stack root)
1164 } else {
1165 _set_error("Invalid native class type '" + String(assign_type.native_type) + "'.", on->arguments[0]);
1166 return -1;
1167 }
1168 codegen.opcodes.push_back(GDScriptFunction::OPCODE_ASSIGN_TYPED_NATIVE); // perform operator
1169 codegen.opcodes.push_back(class_idx); // variable type
1170 codegen.opcodes.push_back(dst_address_a); // argument 1
1171 codegen.opcodes.push_back(src_address_b); // argument 2
1172 } break;
1173 case GDScriptDataType::SCRIPT:
1174 case GDScriptDataType::GDSCRIPT: {
1175
1176 Variant script = assign_type.script_type;
1177 int idx = codegen.get_constant_pos(script);
1178 idx |= GDScriptFunction::ADDR_TYPE_LOCAL_CONSTANT << GDScriptFunction::ADDR_BITS; //make it a local constant (faster access)
1179
1180 codegen.opcodes.push_back(GDScriptFunction::OPCODE_ASSIGN_TYPED_SCRIPT); // perform operator
1181 codegen.opcodes.push_back(idx); // variable type
1182 codegen.opcodes.push_back(dst_address_a); // argument 1
1183 codegen.opcodes.push_back(src_address_b); // argument 2
1184 } break;
1185 default: {
1186 ERR_PRINT("Compiler bug: unresolved assign.");
1187
1188 // Shouldn't get here, but fail-safe to a regular assignment
1189 codegen.opcodes.push_back(GDScriptFunction::OPCODE_ASSIGN); // perform operator
1190 codegen.opcodes.push_back(dst_address_a); // argument 1
1191 codegen.opcodes.push_back(src_address_b); // argument 2 (unary only takes one parameter)
1192 }
1193 }
1194 } else {
1195 // Either untyped assignment or already type-checked by the parser
1196 codegen.opcodes.push_back(GDScriptFunction::OPCODE_ASSIGN); // perform operator
1197 codegen.opcodes.push_back(dst_address_a); // argument 1
1198 codegen.opcodes.push_back(src_address_b); // argument 2 (unary only takes one parameter)
1199 }
1200 return dst_address_a; //if anything, returns wathever was assigned or correct stack position
1201 }
1202 } break;
1203 case GDScriptParser::OperatorNode::OP_IS: {
1204
1205 ERR_FAIL_COND_V(on->arguments.size() != 2, false);
1206
1207 int slevel = p_stack_level;
1208
1209 int src_address_a = _parse_expression(codegen, on->arguments[0], slevel);
1210 if (src_address_a < 0)
1211 return -1;
1212
1213 if (src_address_a & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS)
1214 slevel++; //uses stack for return, increase stack
1215
1216 int src_address_b = _parse_expression(codegen, on->arguments[1], slevel);
1217 if (src_address_b < 0)
1218 return -1;
1219
1220 codegen.opcodes.push_back(GDScriptFunction::OPCODE_EXTENDS_TEST); // perform operator
1221 codegen.opcodes.push_back(src_address_a); // argument 1
1222 codegen.opcodes.push_back(src_address_b); // argument 2 (unary only takes one parameter)
1223
1224 } break;
1225 case GDScriptParser::OperatorNode::OP_IS_BUILTIN: {
1226 ERR_FAIL_COND_V(on->arguments.size() != 2, false);
1227 ERR_FAIL_COND_V(on->arguments[1]->type != GDScriptParser::Node::TYPE_TYPE, false);
1228
1229 int slevel = p_stack_level;
1230
1231 int src_address_a = _parse_expression(codegen, on->arguments[0], slevel);
1232 if (src_address_a < 0)
1233 return -1;
1234
1235 if (src_address_a & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS)
1236 slevel++; //uses stack for return, increase stack
1237
1238 const GDScriptParser::TypeNode *tn = static_cast<const GDScriptParser::TypeNode *>(on->arguments[1]);
1239
1240 codegen.opcodes.push_back(GDScriptFunction::OPCODE_IS_BUILTIN); // perform operator
1241 codegen.opcodes.push_back(src_address_a); // argument 1
1242 codegen.opcodes.push_back((int)tn->vtype); // argument 2 (unary only takes one parameter)
1243 } break;
1244 default: {
1245
1246 ERR_FAIL_V_MSG(0, "Bug in bytecode compiler, unexpected operator #" + itos(on->op) + " in parse tree while parsing expression."); //unreachable code
1247
1248 } break;
1249 }
1250
1251 int dst_addr = (p_stack_level) | (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
1252 codegen.opcodes.push_back(dst_addr); // append the stack level as destination address of the opcode
1253 codegen.alloc_stack(p_stack_level);
1254 return dst_addr;
1255 } break;
1256 //TYPE_TYPE,
1257 default: {
1258
1259 ERR_FAIL_V_MSG(-1, "Bug in bytecode compiler, unexpected node in parse tree while parsing expression."); //unreachable code
1260 } break;
1261 }
1262 }
1263
_parse_block(CodeGen & codegen,const GDScriptParser::BlockNode * p_block,int p_stack_level,int p_break_addr,int p_continue_addr)1264 Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::BlockNode *p_block, int p_stack_level, int p_break_addr, int p_continue_addr) {
1265
1266 codegen.push_stack_identifiers();
1267 int new_identifiers = 0;
1268 codegen.current_line = p_block->line;
1269
1270 for (int i = 0; i < p_block->statements.size(); i++) {
1271
1272 const GDScriptParser::Node *s = p_block->statements[i];
1273
1274 switch (s->type) {
1275 case GDScriptParser::Node::TYPE_NEWLINE: {
1276 #ifdef DEBUG_ENABLED
1277 const GDScriptParser::NewLineNode *nl = static_cast<const GDScriptParser::NewLineNode *>(s);
1278 codegen.opcodes.push_back(GDScriptFunction::OPCODE_LINE);
1279 codegen.opcodes.push_back(nl->line);
1280 codegen.current_line = nl->line;
1281 #endif
1282 } break;
1283 case GDScriptParser::Node::TYPE_CONTROL_FLOW: {
1284 // try subblocks
1285
1286 const GDScriptParser::ControlFlowNode *cf = static_cast<const GDScriptParser::ControlFlowNode *>(s);
1287
1288 switch (cf->cf_type) {
1289
1290 case GDScriptParser::ControlFlowNode::CF_MATCH: {
1291 GDScriptParser::MatchNode *match = cf->match;
1292
1293 GDScriptParser::IdentifierNode *id = memnew(GDScriptParser::IdentifierNode);
1294 id->name = "#match_value";
1295
1296 // var #match_value
1297 // copied because there is no _parse_statement :(
1298 codegen.add_stack_identifier(id->name, p_stack_level++);
1299 codegen.alloc_stack(p_stack_level);
1300 new_identifiers++;
1301
1302 GDScriptParser::OperatorNode *op = memnew(GDScriptParser::OperatorNode);
1303 op->op = GDScriptParser::OperatorNode::OP_ASSIGN;
1304 op->arguments.push_back(id);
1305 op->arguments.push_back(match->val_to_match);
1306
1307 int ret = _parse_expression(codegen, op, p_stack_level);
1308 if (ret < 0) {
1309 memdelete(id);
1310 memdelete(op);
1311 return ERR_PARSE_ERROR;
1312 }
1313
1314 // break address
1315 codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP);
1316 codegen.opcodes.push_back(codegen.opcodes.size() + 3);
1317 int break_addr = codegen.opcodes.size();
1318 codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP);
1319 codegen.opcodes.push_back(0); // break addr
1320
1321 for (int j = 0; j < match->compiled_pattern_branches.size(); j++) {
1322 GDScriptParser::MatchNode::CompiledPatternBranch branch = match->compiled_pattern_branches[j];
1323
1324 // jump over continue
1325 // jump unconditionally
1326 // continue address
1327 // compile the condition
1328 int ret2 = _parse_expression(codegen, branch.compiled_pattern, p_stack_level);
1329 if (ret2 < 0) {
1330 memdelete(id);
1331 memdelete(op);
1332 return ERR_PARSE_ERROR;
1333 }
1334
1335 codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP_IF);
1336 codegen.opcodes.push_back(ret2);
1337 codegen.opcodes.push_back(codegen.opcodes.size() + 3);
1338 int continue_addr = codegen.opcodes.size();
1339 codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP);
1340 codegen.opcodes.push_back(0);
1341
1342 Error err = _parse_block(codegen, branch.body, p_stack_level, p_break_addr, continue_addr);
1343 if (err) {
1344 memdelete(id);
1345 memdelete(op);
1346 return ERR_PARSE_ERROR;
1347 }
1348
1349 codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP);
1350 codegen.opcodes.push_back(break_addr);
1351
1352 codegen.opcodes.write[continue_addr + 1] = codegen.opcodes.size();
1353 }
1354
1355 codegen.opcodes.write[break_addr + 1] = codegen.opcodes.size();
1356
1357 memdelete(id);
1358 memdelete(op);
1359
1360 } break;
1361
1362 case GDScriptParser::ControlFlowNode::CF_IF: {
1363
1364 int ret2 = _parse_expression(codegen, cf->arguments[0], p_stack_level, false);
1365 if (ret2 < 0)
1366 return ERR_PARSE_ERROR;
1367
1368 codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP_IF_NOT);
1369 codegen.opcodes.push_back(ret2);
1370 int else_addr = codegen.opcodes.size();
1371 codegen.opcodes.push_back(0); //temporary
1372
1373 Error err = _parse_block(codegen, cf->body, p_stack_level, p_break_addr, p_continue_addr);
1374 if (err)
1375 return err;
1376
1377 if (cf->body_else) {
1378
1379 codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP);
1380 int end_addr = codegen.opcodes.size();
1381 codegen.opcodes.push_back(0);
1382 codegen.opcodes.write[else_addr] = codegen.opcodes.size();
1383
1384 codegen.opcodes.push_back(GDScriptFunction::OPCODE_LINE);
1385 codegen.opcodes.push_back(cf->body_else->line);
1386 codegen.current_line = cf->body_else->line;
1387
1388 Error err2 = _parse_block(codegen, cf->body_else, p_stack_level, p_break_addr, p_continue_addr);
1389 if (err2)
1390 return err2;
1391
1392 codegen.opcodes.write[end_addr] = codegen.opcodes.size();
1393 } else {
1394 //end without else
1395 codegen.opcodes.write[else_addr] = codegen.opcodes.size();
1396 }
1397
1398 } break;
1399 case GDScriptParser::ControlFlowNode::CF_FOR: {
1400
1401 int slevel = p_stack_level;
1402 int iter_stack_pos = slevel;
1403 int iterator_pos = (slevel++) | (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
1404 int counter_pos = (slevel++) | (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
1405 int container_pos = (slevel++) | (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
1406 codegen.alloc_stack(slevel);
1407
1408 codegen.push_stack_identifiers();
1409 codegen.add_stack_identifier(static_cast<const GDScriptParser::IdentifierNode *>(cf->arguments[0])->name, iter_stack_pos);
1410
1411 int ret2 = _parse_expression(codegen, cf->arguments[1], slevel, false);
1412 if (ret2 < 0)
1413 return ERR_COMPILATION_FAILED;
1414
1415 //assign container
1416 codegen.opcodes.push_back(GDScriptFunction::OPCODE_ASSIGN);
1417 codegen.opcodes.push_back(container_pos);
1418 codegen.opcodes.push_back(ret2);
1419
1420 //begin loop
1421 codegen.opcodes.push_back(GDScriptFunction::OPCODE_ITERATE_BEGIN);
1422 codegen.opcodes.push_back(counter_pos);
1423 codegen.opcodes.push_back(container_pos);
1424 codegen.opcodes.push_back(codegen.opcodes.size() + 4);
1425 codegen.opcodes.push_back(iterator_pos);
1426 codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP); //skip code for next
1427 codegen.opcodes.push_back(codegen.opcodes.size() + 8);
1428 //break loop
1429 int break_pos = codegen.opcodes.size();
1430 codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP); //skip code for next
1431 codegen.opcodes.push_back(0); //skip code for next
1432 //next loop
1433 int continue_pos = codegen.opcodes.size();
1434 codegen.opcodes.push_back(GDScriptFunction::OPCODE_ITERATE);
1435 codegen.opcodes.push_back(counter_pos);
1436 codegen.opcodes.push_back(container_pos);
1437 codegen.opcodes.push_back(break_pos);
1438 codegen.opcodes.push_back(iterator_pos);
1439
1440 Error err = _parse_block(codegen, cf->body, slevel, break_pos, continue_pos);
1441 if (err)
1442 return err;
1443
1444 codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP);
1445 codegen.opcodes.push_back(continue_pos);
1446 codegen.opcodes.write[break_pos + 1] = codegen.opcodes.size();
1447
1448 codegen.pop_stack_identifiers();
1449
1450 } break;
1451 case GDScriptParser::ControlFlowNode::CF_WHILE: {
1452
1453 codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP);
1454 codegen.opcodes.push_back(codegen.opcodes.size() + 3);
1455 int break_addr = codegen.opcodes.size();
1456 codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP);
1457 codegen.opcodes.push_back(0);
1458 int continue_addr = codegen.opcodes.size();
1459
1460 int ret2 = _parse_expression(codegen, cf->arguments[0], p_stack_level, false);
1461 if (ret2 < 0)
1462 return ERR_PARSE_ERROR;
1463 codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP_IF_NOT);
1464 codegen.opcodes.push_back(ret2);
1465 codegen.opcodes.push_back(break_addr);
1466 Error err = _parse_block(codegen, cf->body, p_stack_level, break_addr, continue_addr);
1467 if (err)
1468 return err;
1469 codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP);
1470 codegen.opcodes.push_back(continue_addr);
1471
1472 codegen.opcodes.write[break_addr + 1] = codegen.opcodes.size();
1473
1474 } break;
1475 case GDScriptParser::ControlFlowNode::CF_BREAK: {
1476
1477 if (p_break_addr < 0) {
1478
1479 _set_error("'break'' not within loop", cf);
1480 return ERR_COMPILATION_FAILED;
1481 }
1482 codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP);
1483 codegen.opcodes.push_back(p_break_addr);
1484
1485 } break;
1486 case GDScriptParser::ControlFlowNode::CF_CONTINUE: {
1487
1488 if (p_continue_addr < 0) {
1489
1490 _set_error("'continue' not within loop", cf);
1491 return ERR_COMPILATION_FAILED;
1492 }
1493
1494 codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP);
1495 codegen.opcodes.push_back(p_continue_addr);
1496
1497 } break;
1498 case GDScriptParser::ControlFlowNode::CF_RETURN: {
1499
1500 int ret2;
1501
1502 if (cf->arguments.size()) {
1503
1504 ret2 = _parse_expression(codegen, cf->arguments[0], p_stack_level, false);
1505 if (ret2 < 0)
1506 return ERR_PARSE_ERROR;
1507
1508 } else {
1509
1510 ret2 = GDScriptFunction::ADDR_TYPE_NIL << GDScriptFunction::ADDR_BITS;
1511 }
1512
1513 codegen.opcodes.push_back(GDScriptFunction::OPCODE_RETURN);
1514 codegen.opcodes.push_back(ret2);
1515
1516 } break;
1517 }
1518 } break;
1519 case GDScriptParser::Node::TYPE_ASSERT: {
1520 #ifdef DEBUG_ENABLED
1521 // try subblocks
1522
1523 const GDScriptParser::AssertNode *as = static_cast<const GDScriptParser::AssertNode *>(s);
1524
1525 int ret2 = _parse_expression(codegen, as->condition, p_stack_level, false);
1526 if (ret2 < 0)
1527 return ERR_PARSE_ERROR;
1528
1529 int message_ret = 0;
1530 if (as->message) {
1531 message_ret = _parse_expression(codegen, as->message, p_stack_level + 1, false);
1532 if (message_ret < 0)
1533 return ERR_PARSE_ERROR;
1534 }
1535
1536 codegen.opcodes.push_back(GDScriptFunction::OPCODE_ASSERT);
1537 codegen.opcodes.push_back(ret2);
1538 codegen.opcodes.push_back(message_ret);
1539 #endif
1540 } break;
1541 case GDScriptParser::Node::TYPE_BREAKPOINT: {
1542 #ifdef DEBUG_ENABLED
1543 // try subblocks
1544 codegen.opcodes.push_back(GDScriptFunction::OPCODE_BREAKPOINT);
1545 #endif
1546 } break;
1547 case GDScriptParser::Node::TYPE_LOCAL_VAR: {
1548
1549 const GDScriptParser::LocalVarNode *lv = static_cast<const GDScriptParser::LocalVarNode *>(s);
1550
1551 // since we are using properties now for most class access, allow shadowing of class members to make user's life easier.
1552 //
1553 //if (_is_class_member_property(codegen, lv->name)) {
1554 // _set_error("Name for local variable '" + String(lv->name) + "' can't shadow class property of the same name.", lv);
1555 // return ERR_ALREADY_EXISTS;
1556 //}
1557
1558 codegen.add_stack_identifier(lv->name, p_stack_level++);
1559 codegen.alloc_stack(p_stack_level);
1560 new_identifiers++;
1561
1562 } break;
1563 default: {
1564 //expression
1565 int ret2 = _parse_expression(codegen, s, p_stack_level, true);
1566 if (ret2 < 0)
1567 return ERR_PARSE_ERROR;
1568 } break;
1569 }
1570 }
1571 codegen.pop_stack_identifiers();
1572 return OK;
1573 }
1574
_parse_function(GDScript * p_script,const GDScriptParser::ClassNode * p_class,const GDScriptParser::FunctionNode * p_func,bool p_for_ready)1575 Error GDScriptCompiler::_parse_function(GDScript *p_script, const GDScriptParser::ClassNode *p_class, const GDScriptParser::FunctionNode *p_func, bool p_for_ready) {
1576
1577 Vector<int> bytecode;
1578 CodeGen codegen;
1579
1580 codegen.class_node = p_class;
1581 codegen.script = p_script;
1582 codegen.function_node = p_func;
1583 codegen.stack_max = 0;
1584 codegen.current_line = 0;
1585 codegen.call_max = 0;
1586 codegen.debug_stack = ScriptDebugger::get_singleton() != NULL;
1587 Vector<StringName> argnames;
1588
1589 int stack_level = 0;
1590
1591 if (p_func) {
1592 for (int i = 0; i < p_func->arguments.size(); i++) {
1593 // since we are using properties now for most class access, allow shadowing of class members to make user's life easier.
1594 //
1595 //if (_is_class_member_property(p_script, p_func->arguments[i])) {
1596 // _set_error("Name for argument '" + String(p_func->arguments[i]) + "' can't shadow class property of the same name.", p_func);
1597 // return ERR_ALREADY_EXISTS;
1598 //}
1599
1600 codegen.add_stack_identifier(p_func->arguments[i], i);
1601 #ifdef TOOLS_ENABLED
1602 argnames.push_back(p_func->arguments[i]);
1603 #endif
1604 }
1605 stack_level = p_func->arguments.size();
1606 }
1607
1608 codegen.alloc_stack(stack_level);
1609
1610 /* Parse initializer -if applies- */
1611
1612 bool is_initializer = !p_for_ready && !p_func;
1613
1614 if (is_initializer || (p_func && String(p_func->name) == "_init")) {
1615 //parse initializer for class members
1616 if (!p_func && p_class->extends_used && p_script->native.is_null()) {
1617
1618 //call implicit parent constructor
1619 codegen.opcodes.push_back(GDScriptFunction::OPCODE_CALL_SELF_BASE);
1620 codegen.opcodes.push_back(codegen.get_name_map_pos("_init"));
1621 codegen.opcodes.push_back(0);
1622 codegen.opcodes.push_back((GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS) | 0);
1623 }
1624 Error err = _parse_block(codegen, p_class->initializer, stack_level);
1625 if (err)
1626 return err;
1627 is_initializer = true;
1628 }
1629
1630 if (p_for_ready || (p_func && String(p_func->name) == "_ready")) {
1631 //parse initializer for class members
1632 if (p_class->ready->statements.size()) {
1633 Error err = _parse_block(codegen, p_class->ready, stack_level);
1634 if (err)
1635 return err;
1636 }
1637 }
1638
1639 /* Parse default argument code -if applies- */
1640
1641 Vector<int> defarg_addr;
1642 StringName func_name;
1643
1644 if (p_func) {
1645
1646 if (p_func->default_values.size()) {
1647
1648 codegen.opcodes.push_back(GDScriptFunction::OPCODE_JUMP_TO_DEF_ARGUMENT);
1649 defarg_addr.push_back(codegen.opcodes.size());
1650 for (int i = 0; i < p_func->default_values.size(); i++) {
1651
1652 _parse_expression(codegen, p_func->default_values[i], stack_level, true);
1653 defarg_addr.push_back(codegen.opcodes.size());
1654 }
1655
1656 defarg_addr.invert();
1657 }
1658
1659 Error err = _parse_block(codegen, p_func->body, stack_level);
1660 if (err)
1661 return err;
1662
1663 func_name = p_func->name;
1664 } else {
1665 if (p_for_ready)
1666 func_name = "_ready";
1667 else
1668 func_name = "_init";
1669 }
1670
1671 codegen.opcodes.push_back(GDScriptFunction::OPCODE_END);
1672
1673 /*
1674 if (String(p_func->name)=="") { //initializer func
1675 gdfunc = &p_script->initializer;
1676 */
1677 //} else { //regular func
1678 p_script->member_functions[func_name] = memnew(GDScriptFunction);
1679 GDScriptFunction *gdfunc = p_script->member_functions[func_name];
1680 //}
1681
1682 if (p_func) {
1683 gdfunc->_static = p_func->_static;
1684 gdfunc->rpc_mode = p_func->rpc_mode;
1685 gdfunc->argument_types.resize(p_func->argument_types.size());
1686 for (int i = 0; i < p_func->argument_types.size(); i++) {
1687 gdfunc->argument_types.write[i] = _gdtype_from_datatype(p_func->argument_types[i]);
1688 }
1689 gdfunc->return_type = _gdtype_from_datatype(p_func->return_type);
1690 } else {
1691 gdfunc->_static = false;
1692 gdfunc->rpc_mode = MultiplayerAPI::RPC_MODE_DISABLED;
1693 gdfunc->return_type = GDScriptDataType();
1694 gdfunc->return_type.has_type = true;
1695 gdfunc->return_type.kind = GDScriptDataType::BUILTIN;
1696 gdfunc->return_type.builtin_type = Variant::NIL;
1697 }
1698
1699 #ifdef TOOLS_ENABLED
1700 gdfunc->arg_names = argnames;
1701 #endif
1702 //constants
1703 if (codegen.constant_map.size()) {
1704 gdfunc->_constant_count = codegen.constant_map.size();
1705 gdfunc->constants.resize(codegen.constant_map.size());
1706 gdfunc->_constants_ptr = gdfunc->constants.ptrw();
1707 const Variant *K = NULL;
1708 while ((K = codegen.constant_map.next(K))) {
1709 int idx = codegen.constant_map[*K];
1710 gdfunc->constants.write[idx] = *K;
1711 }
1712 } else {
1713
1714 gdfunc->_constants_ptr = NULL;
1715 gdfunc->_constant_count = 0;
1716 }
1717 //global names
1718 if (codegen.name_map.size()) {
1719
1720 gdfunc->global_names.resize(codegen.name_map.size());
1721 gdfunc->_global_names_ptr = &gdfunc->global_names[0];
1722 for (Map<StringName, int>::Element *E = codegen.name_map.front(); E; E = E->next()) {
1723
1724 gdfunc->global_names.write[E->get()] = E->key();
1725 }
1726 gdfunc->_global_names_count = gdfunc->global_names.size();
1727
1728 } else {
1729 gdfunc->_global_names_ptr = NULL;
1730 gdfunc->_global_names_count = 0;
1731 }
1732
1733 #ifdef TOOLS_ENABLED
1734 // Named globals
1735 if (codegen.named_globals.size()) {
1736 gdfunc->named_globals.resize(codegen.named_globals.size());
1737 gdfunc->_named_globals_ptr = gdfunc->named_globals.ptr();
1738 for (int i = 0; i < codegen.named_globals.size(); i++) {
1739 gdfunc->named_globals.write[i] = codegen.named_globals[i];
1740 }
1741 gdfunc->_named_globals_count = gdfunc->named_globals.size();
1742 }
1743 #endif
1744
1745 if (codegen.opcodes.size()) {
1746
1747 gdfunc->code = codegen.opcodes;
1748 gdfunc->_code_ptr = &gdfunc->code[0];
1749 gdfunc->_code_size = codegen.opcodes.size();
1750
1751 } else {
1752
1753 gdfunc->_code_ptr = NULL;
1754 gdfunc->_code_size = 0;
1755 }
1756
1757 if (defarg_addr.size()) {
1758
1759 gdfunc->default_arguments = defarg_addr;
1760 gdfunc->_default_arg_count = defarg_addr.size() - 1;
1761 gdfunc->_default_arg_ptr = &gdfunc->default_arguments[0];
1762 } else {
1763 gdfunc->_default_arg_count = 0;
1764 gdfunc->_default_arg_ptr = NULL;
1765 }
1766
1767 gdfunc->_argument_count = p_func ? p_func->arguments.size() : 0;
1768 gdfunc->_stack_size = codegen.stack_max;
1769 gdfunc->_call_size = codegen.call_max;
1770 gdfunc->name = func_name;
1771 #ifdef DEBUG_ENABLED
1772 if (ScriptDebugger::get_singleton()) {
1773 String signature;
1774 //path
1775 if (p_script->get_path() != String())
1776 signature += p_script->get_path();
1777 //loc
1778 if (p_func) {
1779 signature += "::" + itos(p_func->body->line);
1780 } else {
1781 signature += "::0";
1782 }
1783
1784 //function and class
1785
1786 if (p_class->name) {
1787 signature += "::" + String(p_class->name) + "." + String(func_name);
1788 } else {
1789 signature += "::" + String(func_name);
1790 }
1791
1792 gdfunc->profile.signature = signature;
1793 }
1794 #endif
1795 gdfunc->_script = p_script;
1796 gdfunc->source = source;
1797
1798 #ifdef DEBUG_ENABLED
1799
1800 {
1801 gdfunc->func_cname = (String(source) + " - " + String(func_name)).utf8();
1802 gdfunc->_func_cname = gdfunc->func_cname.get_data();
1803 }
1804
1805 #endif
1806 if (p_func) {
1807 gdfunc->_initial_line = p_func->line;
1808 #ifdef TOOLS_ENABLED
1809
1810 p_script->member_lines[func_name] = p_func->line;
1811 #endif
1812 } else {
1813 gdfunc->_initial_line = 0;
1814 }
1815
1816 if (codegen.debug_stack)
1817 gdfunc->stack_debug = codegen.stack_debug;
1818
1819 if (is_initializer)
1820 p_script->initializer = gdfunc;
1821
1822 return OK;
1823 }
1824
_parse_class_level(GDScript * p_script,const GDScriptParser::ClassNode * p_class,bool p_keep_state)1825 Error GDScriptCompiler::_parse_class_level(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state) {
1826
1827 parsing_classes.insert(p_script);
1828
1829 if (p_class->owner && p_class->owner->owner) {
1830 // Owner is not root
1831 if (!parsed_classes.has(p_script->_owner)) {
1832 if (parsing_classes.has(p_script->_owner)) {
1833 _set_error("Cyclic class reference for '" + String(p_class->name) + "'.", p_class);
1834 return ERR_PARSE_ERROR;
1835 }
1836 Error err = _parse_class_level(p_script->_owner, p_class->owner, p_keep_state);
1837 if (err) {
1838 return err;
1839 }
1840 }
1841 }
1842
1843 p_script->native = Ref<GDScriptNativeClass>();
1844 p_script->base = Ref<GDScript>();
1845 p_script->_base = NULL;
1846 p_script->members.clear();
1847 p_script->constants.clear();
1848 for (Map<StringName, GDScriptFunction *>::Element *E = p_script->member_functions.front(); E; E = E->next()) {
1849 memdelete(E->get());
1850 }
1851 p_script->member_functions.clear();
1852 p_script->member_indices.clear();
1853 p_script->member_info.clear();
1854 p_script->_signals.clear();
1855 p_script->initializer = NULL;
1856
1857 p_script->tool = p_class->tool;
1858 p_script->name = p_class->name;
1859
1860 Ref<GDScriptNativeClass> native;
1861
1862 GDScriptDataType base_type = _gdtype_from_datatype(p_class->base_type);
1863 // Inheritance
1864 switch (base_type.kind) {
1865 case GDScriptDataType::NATIVE: {
1866 int native_idx = GDScriptLanguage::get_singleton()->get_global_map()[base_type.native_type];
1867 native = GDScriptLanguage::get_singleton()->get_global_array()[native_idx];
1868 ERR_FAIL_COND_V(native.is_null(), ERR_BUG);
1869 p_script->native = native;
1870 } break;
1871 case GDScriptDataType::GDSCRIPT: {
1872 Ref<GDScript> base = base_type.script_type;
1873 p_script->base = base;
1874 p_script->_base = base.ptr();
1875 p_script->member_indices = base->member_indices;
1876
1877 if (p_class->base_type.kind == GDScriptParser::DataType::CLASS) {
1878 if (!parsed_classes.has(p_script->_base)) {
1879 if (parsing_classes.has(p_script->_base)) {
1880 _set_error("Cyclic class reference for '" + String(p_class->name) + "'.", p_class);
1881 return ERR_PARSE_ERROR;
1882 }
1883 Error err = _parse_class_level(p_script->_base, p_class->base_type.class_type, p_keep_state);
1884 if (err) {
1885 return err;
1886 }
1887 }
1888 }
1889 } break;
1890 default: {
1891 _set_error("Parser bug: invalid inheritance.", p_class);
1892 return ERR_BUG;
1893 } break;
1894 }
1895
1896 for (int i = 0; i < p_class->variables.size(); i++) {
1897
1898 StringName name = p_class->variables[i].identifier;
1899
1900 GDScript::MemberInfo minfo;
1901 minfo.index = p_script->member_indices.size();
1902 minfo.setter = p_class->variables[i].setter;
1903 minfo.getter = p_class->variables[i].getter;
1904 minfo.rpc_mode = p_class->variables[i].rpc_mode;
1905 minfo.data_type = _gdtype_from_datatype(p_class->variables[i].data_type);
1906
1907 PropertyInfo prop_info = minfo.data_type;
1908 prop_info.name = name;
1909 PropertyInfo export_info = p_class->variables[i]._export;
1910
1911 if (export_info.type != Variant::NIL) {
1912
1913 if (!minfo.data_type.has_type) {
1914 prop_info.type = export_info.type;
1915 prop_info.class_name = export_info.class_name;
1916 }
1917 prop_info.hint = export_info.hint;
1918 prop_info.hint_string = export_info.hint_string;
1919 prop_info.usage = export_info.usage;
1920 #ifdef TOOLS_ENABLED
1921 if (p_class->variables[i].default_value.get_type() != Variant::NIL) {
1922 p_script->member_default_values[name] = p_class->variables[i].default_value;
1923 }
1924 #endif
1925 } else {
1926 prop_info.usage = PROPERTY_USAGE_SCRIPT_VARIABLE;
1927 }
1928
1929 p_script->member_info[name] = prop_info;
1930 p_script->member_indices[name] = minfo;
1931 p_script->members.insert(name);
1932
1933 #ifdef TOOLS_ENABLED
1934 p_script->member_lines[name] = p_class->variables[i].line;
1935 #endif
1936 }
1937
1938 for (Map<StringName, GDScriptParser::ClassNode::Constant>::Element *E = p_class->constant_expressions.front(); E; E = E->next()) {
1939
1940 StringName name = E->key();
1941
1942 ERR_CONTINUE(E->get().expression->type != GDScriptParser::Node::TYPE_CONSTANT);
1943
1944 GDScriptParser::ConstantNode *constant = static_cast<GDScriptParser::ConstantNode *>(E->get().expression);
1945
1946 p_script->constants.insert(name, constant->value);
1947 #ifdef TOOLS_ENABLED
1948
1949 p_script->member_lines[name] = E->get().expression->line;
1950 #endif
1951 }
1952
1953 for (int i = 0; i < p_class->_signals.size(); i++) {
1954
1955 StringName name = p_class->_signals[i].name;
1956
1957 GDScript *c = p_script;
1958
1959 while (c) {
1960
1961 if (c->_signals.has(name)) {
1962 _set_error("Signal '" + name + "' redefined (in current or parent class)", p_class);
1963 return ERR_ALREADY_EXISTS;
1964 }
1965
1966 if (c->base.is_valid()) {
1967 c = c->base.ptr();
1968 } else {
1969 c = NULL;
1970 }
1971 }
1972
1973 if (native.is_valid()) {
1974 if (ClassDB::has_signal(native->get_name(), name)) {
1975 _set_error("Signal '" + name + "' redefined (original in native class '" + String(native->get_name()) + "')", p_class);
1976 return ERR_ALREADY_EXISTS;
1977 }
1978 }
1979
1980 p_script->_signals[name] = p_class->_signals[i].arguments;
1981 }
1982
1983 parsed_classes.insert(p_script);
1984 parsing_classes.erase(p_script);
1985
1986 //parse sub-classes
1987
1988 for (int i = 0; i < p_class->subclasses.size(); i++) {
1989 StringName name = p_class->subclasses[i]->name;
1990 Ref<GDScript> &subclass = p_script->subclasses[name];
1991 GDScript *subclass_ptr = subclass.ptr();
1992
1993 // Subclass might still be parsing, just skip it
1994 if (!parsed_classes.has(subclass_ptr) && !parsing_classes.has(subclass_ptr)) {
1995 Error err = _parse_class_level(subclass_ptr, p_class->subclasses[i], p_keep_state);
1996 if (err)
1997 return err;
1998 }
1999
2000 #ifdef TOOLS_ENABLED
2001
2002 p_script->member_lines[name] = p_class->subclasses[i]->line;
2003 #endif
2004
2005 p_script->constants.insert(name, subclass); //once parsed, goes to the list of constants
2006 }
2007
2008 return OK;
2009 }
2010
_parse_class_blocks(GDScript * p_script,const GDScriptParser::ClassNode * p_class,bool p_keep_state)2011 Error GDScriptCompiler::_parse_class_blocks(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state) {
2012 //parse methods
2013
2014 bool has_initializer = false;
2015 bool has_ready = false;
2016
2017 for (int i = 0; i < p_class->functions.size(); i++) {
2018
2019 if (!has_initializer && p_class->functions[i]->name == "_init")
2020 has_initializer = true;
2021 if (!has_ready && p_class->functions[i]->name == "_ready")
2022 has_ready = true;
2023 Error err = _parse_function(p_script, p_class, p_class->functions[i]);
2024 if (err)
2025 return err;
2026 }
2027
2028 //parse static methods
2029
2030 for (int i = 0; i < p_class->static_functions.size(); i++) {
2031
2032 Error err = _parse_function(p_script, p_class, p_class->static_functions[i]);
2033 if (err)
2034 return err;
2035 }
2036
2037 if (!has_initializer) {
2038 //create a constructor
2039 Error err = _parse_function(p_script, p_class, NULL);
2040 if (err)
2041 return err;
2042 }
2043
2044 if (!has_ready && p_class->ready->statements.size()) {
2045 //create a constructor
2046 Error err = _parse_function(p_script, p_class, NULL, true);
2047 if (err)
2048 return err;
2049 }
2050
2051 #ifdef DEBUG_ENABLED
2052
2053 //validate instances if keeping state
2054
2055 if (p_keep_state) {
2056 for (Set<Object *>::Element *E = p_script->instances.front(); E;) {
2057
2058 Set<Object *>::Element *N = E->next();
2059
2060 ScriptInstance *si = E->get()->get_script_instance();
2061 if (si->is_placeholder()) {
2062 #ifdef TOOLS_ENABLED
2063 PlaceHolderScriptInstance *psi = static_cast<PlaceHolderScriptInstance *>(si);
2064
2065 if (p_script->is_tool()) {
2066 //re-create as an instance
2067 p_script->placeholders.erase(psi); //remove placeholder
2068
2069 GDScriptInstance *instance = memnew(GDScriptInstance);
2070 instance->base_ref = Object::cast_to<Reference>(E->get());
2071 instance->members.resize(p_script->member_indices.size());
2072 instance->script = Ref<GDScript>(p_script);
2073 instance->owner = E->get();
2074
2075 //needed for hot reloading
2076 for (Map<StringName, GDScript::MemberInfo>::Element *F = p_script->member_indices.front(); F; F = F->next()) {
2077 instance->member_indices_cache[F->key()] = F->get().index;
2078 }
2079 instance->owner->set_script_instance(instance);
2080
2081 /* STEP 2, INITIALIZE AND CONSTRUCT */
2082
2083 Variant::CallError ce;
2084 p_script->initializer->call(instance, NULL, 0, ce);
2085
2086 if (ce.error != Variant::CallError::CALL_OK) {
2087 //well, tough luck, not goinna do anything here
2088 }
2089 }
2090 #endif
2091 } else {
2092
2093 GDScriptInstance *gi = static_cast<GDScriptInstance *>(si);
2094 gi->reload_members();
2095 }
2096
2097 E = N;
2098 }
2099 }
2100 #endif
2101
2102 for (int i = 0; i < p_class->subclasses.size(); i++) {
2103 StringName name = p_class->subclasses[i]->name;
2104 GDScript *subclass = p_script->subclasses[name].ptr();
2105
2106 Error err = _parse_class_blocks(subclass, p_class->subclasses[i], p_keep_state);
2107 if (err) {
2108 return err;
2109 }
2110 }
2111
2112 p_script->valid = true;
2113 return OK;
2114 }
2115
_make_scripts(GDScript * p_script,const GDScriptParser::ClassNode * p_class,bool p_keep_state)2116 void GDScriptCompiler::_make_scripts(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state) {
2117
2118 Map<StringName, Ref<GDScript> > old_subclasses;
2119
2120 if (p_keep_state) {
2121 old_subclasses = p_script->subclasses;
2122 }
2123
2124 p_script->subclasses.clear();
2125
2126 for (int i = 0; i < p_class->subclasses.size(); i++) {
2127 StringName name = p_class->subclasses[i]->name;
2128
2129 Ref<GDScript> subclass;
2130 String fully_qualified_name = p_script->fully_qualified_name + "::" + name;
2131
2132 if (old_subclasses.has(name)) {
2133 subclass = old_subclasses[name];
2134 } else {
2135 Ref<GDScript> orphan_subclass = GDScriptLanguage::get_singleton()->get_orphan_subclass(fully_qualified_name);
2136 if (orphan_subclass.is_valid()) {
2137 subclass = orphan_subclass;
2138 } else {
2139 subclass.instance();
2140 }
2141 }
2142
2143 subclass->_owner = p_script;
2144 subclass->fully_qualified_name = fully_qualified_name;
2145 p_script->subclasses.insert(name, subclass);
2146
2147 _make_scripts(subclass.ptr(), p_class->subclasses[i], false);
2148 }
2149 }
2150
compile(const GDScriptParser * p_parser,GDScript * p_script,bool p_keep_state)2151 Error GDScriptCompiler::compile(const GDScriptParser *p_parser, GDScript *p_script, bool p_keep_state) {
2152
2153 err_line = -1;
2154 err_column = -1;
2155 error = "";
2156 parser = p_parser;
2157 main_script = p_script;
2158 const GDScriptParser::Node *root = parser->get_parse_tree();
2159 ERR_FAIL_COND_V(root->type != GDScriptParser::Node::TYPE_CLASS, ERR_INVALID_DATA);
2160
2161 source = p_script->get_path();
2162
2163 // The best fully qualified name for a base level script is its file path
2164 p_script->fully_qualified_name = p_script->path;
2165
2166 // Create scripts for subclasses beforehand so they can be referenced
2167 _make_scripts(p_script, static_cast<const GDScriptParser::ClassNode *>(root), p_keep_state);
2168
2169 p_script->_owner = NULL;
2170 Error err = _parse_class_level(p_script, static_cast<const GDScriptParser::ClassNode *>(root), p_keep_state);
2171
2172 if (err)
2173 return err;
2174
2175 err = _parse_class_blocks(p_script, static_cast<const GDScriptParser::ClassNode *>(root), p_keep_state);
2176
2177 if (err)
2178 return err;
2179
2180 return OK;
2181 }
2182
get_error() const2183 String GDScriptCompiler::get_error() const {
2184
2185 return error;
2186 }
get_error_line() const2187 int GDScriptCompiler::get_error_line() const {
2188
2189 return err_line;
2190 }
get_error_column() const2191 int GDScriptCompiler::get_error_column() const {
2192
2193 return err_column;
2194 }
2195
GDScriptCompiler()2196 GDScriptCompiler::GDScriptCompiler() {
2197 }
2198