Browse Source

Fix `as` operator generating opcode 38 errors

Closes #27489
Fixup of 466a76ac2c7c6634ed1d78fde4ac011e2e70b710

Additionally, update `GDScriptCompiler` test to use Ref and to include `as` expressions.
Bojidar Marinov 6 years ago
parent
commit
f04f127680
2 changed files with 37 additions and 10 deletions
  1. 19 5
      main/tests/test_gdscript.cpp
  2. 18 5
      modules/gdscript/gdscript_compiler.cpp

+ 19 - 5
main/tests/test_gdscript.cpp

@@ -288,6 +288,11 @@ static String _parser_expr(const GDScriptParser::Node *p_expr) {
 				}
 			}
 
+		} break;
+		case GDScriptParser::Node::TYPE_CAST: {
+			const GDScriptParser::CastNode *cast_node = static_cast<const GDScriptParser::CastNode *>(p_expr);
+			txt = _parser_expr(cast_node->source_node) + " as " + cast_node->cast_type.to_string();
+
 		} break;
 		case GDScriptParser::Node::TYPE_NEWLINE: {
 
@@ -668,6 +673,17 @@ static void _disassemble_class(const Ref<GDScript> &p_class, const Vector<String
 					txt += "= false";
 					incr += 2;
 
+				} break;
+				case GDScriptFunction::OPCODE_CAST_TO_SCRIPT: {
+
+					txt += " cast ";
+					txt += DADDR(3);
+					txt += "=";
+					txt += DADDR(1);
+					txt += " as ";
+					txt += DADDR(2);
+					incr += 4;
+
 				} break;
 				case GDScriptFunction::OPCODE_CONSTRUCT: {
 
@@ -1018,19 +1034,17 @@ MainLoop *test(TestType p_type) {
 			return NULL;
 		}
 
-		GDScript *script = memnew(GDScript);
+		Ref<GDScript> gds;
+		gds.instance();
 
 		GDScriptCompiler gdc;
-		err = gdc.compile(&parser, script);
+		err = gdc.compile(&parser, gds.ptr());
 		if (err) {
 
 			print_line("Compile Error:\n" + itos(gdc.get_error_line()) + ":" + itos(gdc.get_error_column()) + ":" + gdc.get_error());
-			memdelete(script);
 			return NULL;
 		}
 
-		Ref<GDScript> gds = Ref<GDScript>(script);
-
 		Ref<GDScript> current = gds;
 
 		while (current.is_valid()) {

+ 18 - 5
modules/gdscript/gdscript_compiler.cpp

@@ -480,16 +480,16 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser::
 			switch (cast_type.kind) {
 				case GDScriptDataType::BUILTIN: {
 					codegen.opcodes.push_back(GDScriptFunction::OPCODE_CAST_TO_BUILTIN);
-					codegen.opcodes.push_back(cn->cast_type.builtin_type);
+					codegen.opcodes.push_back(cast_type.builtin_type);
 				} break;
 				case GDScriptDataType::NATIVE: {
 					int class_idx;
-					if (GDScriptLanguage::get_singleton()->get_global_map().has(cn->cast_type.native_type)) {
+					if (GDScriptLanguage::get_singleton()->get_global_map().has(cast_type.native_type)) {
 
-						class_idx = GDScriptLanguage::get_singleton()->get_global_map()[cn->cast_type.native_type];
+						class_idx = GDScriptLanguage::get_singleton()->get_global_map()[cast_type.native_type];
 						class_idx |= (GDScriptFunction::ADDR_TYPE_GLOBAL << GDScriptFunction::ADDR_BITS); //argument (stack root)
 					} else {
-						_set_error("Invalid native class type '" + String(cn->cast_type.native_type) + "'.", cn);
+						_set_error("Invalid native class type '" + String(cast_type.native_type) + "'.", cn);
 						return -1;
 					}
 					codegen.opcodes.push_back(GDScriptFunction::OPCODE_CAST_TO_NATIVE); // perform operator
@@ -498,7 +498,7 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser::
 				case GDScriptDataType::SCRIPT:
 				case GDScriptDataType::GDSCRIPT: {
 
-					Variant script = cn->cast_type.script_type;
+					Variant script = cast_type.script_type;
 					int idx = codegen.get_constant_pos(script);
 					idx |= GDScriptFunction::ADDR_TYPE_LOCAL_CONSTANT << GDScriptFunction::ADDR_BITS; //make it a local constant (faster access)
 
@@ -1863,6 +1863,19 @@ Error GDScriptCompiler::_parse_class_level(GDScript *p_script, const GDScriptPar
 			p_script->base = base;
 			p_script->_base = base.ptr();
 			p_script->member_indices = base->member_indices;
+
+			if (p_class->base_type.kind == GDScriptParser::DataType::CLASS) {
+				if (!parsed_classes.has(p_script->_base)) {
+					if (parsing_classes.has(p_script->_base)) {
+						_set_error("Cyclic class reference for '" + String(p_class->name) + "'.", p_class);
+						return ERR_PARSE_ERROR;
+					}
+					Error err = _parse_class_level(p_script->_base, p_class->base_type.class_type, p_keep_state);
+					if (err) {
+						return err;
+					}
+				}
+			}
 		} break;
 		default: {
 			_set_error("Parser bug: invalid inheritance.", p_class);