diff options
Diffstat (limited to 'modules/gdscript')
-rw-r--r-- | modules/gdscript/gdscript.cpp | 26 | ||||
-rw-r--r-- | modules/gdscript/gdscript_compiler.cpp | 28 | ||||
-rw-r--r-- | modules/gdscript/gdscript_editor.cpp | 14 | ||||
-rw-r--r-- | modules/gdscript/gdscript_function.cpp | 16 | ||||
-rw-r--r-- | modules/gdscript/gdscript_function.h | 1 | ||||
-rw-r--r-- | modules/gdscript/gdscript_parser.cpp | 46 | ||||
-rw-r--r-- | modules/gdscript/gdscript_parser.h | 1 |
7 files changed, 116 insertions, 16 deletions
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index e05bc7d591..33d9c011f2 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -126,7 +126,10 @@ GDScriptInstance *GDScript::_create_instance(const Variant **p_args, int p_argco GDScriptLanguage::singleton->lock->unlock(); #endif - ERR_FAIL_COND_V(r_error.error != Variant::CallError::CALL_OK, NULL); //error constructing + if (r_error.error != Variant::CallError::CALL_OK) { + memdelete(instance); + ERR_FAIL_COND_V(r_error.error != Variant::CallError::CALL_OK, NULL); //error constructing + } } //@TODO make thread safe @@ -719,22 +722,36 @@ Error GDScript::load_byte_code(const String &p_path) { FileAccess *fa = FileAccess::open(p_path, FileAccess::READ); ERR_FAIL_COND_V(!fa, ERR_CANT_OPEN); + FileAccessEncrypted *fae = memnew(FileAccessEncrypted); ERR_FAIL_COND_V(!fae, ERR_CANT_OPEN); + Vector<uint8_t> key; key.resize(32); for (int i = 0; i < key.size(); i++) { key.write[i] = script_encryption_key[i]; } + Error err = fae->open_and_parse(fa, key, FileAccessEncrypted::MODE_READ); - ERR_FAIL_COND_V(err, err); + + if (err) { + fa->close(); + memdelete(fa); + memdelete(fae); + + ERR_FAIL_COND_V(err, err); + } + bytecode.resize(fae->get_len()); fae->get_buffer(bytecode.ptrw(), bytecode.size()); + fae->close(); memdelete(fae); + } else { bytecode = FileAccess::get_file_as_array(p_path); } + ERR_FAIL_COND_V(bytecode.size() == 0, ERR_PARSE_ERROR); path = p_path; @@ -2097,7 +2114,7 @@ RES ResourceFormatLoaderGDScript::load(const String &p_path, const String &p_ori Error err = script->load_byte_code(p_path); if (err != OK) { - + memdelete(script); ERR_FAIL_COND_V(err != OK, RES()); } @@ -2105,7 +2122,7 @@ RES ResourceFormatLoaderGDScript::load(const String &p_path, const String &p_ori Error err = script->load_source_code(p_path); if (err != OK) { - + memdelete(script); ERR_FAIL_COND_V(err != OK, RES()); } @@ -2120,6 +2137,7 @@ RES ResourceFormatLoaderGDScript::load(const String &p_path, const String &p_ori return scriptres; } + void ResourceFormatLoaderGDScript::get_recognized_extensions(List<String> *p_extensions) const { p_extensions->push_back("gd"); diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index 1403184557..006fbece53 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -1253,6 +1253,25 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: codegen.opcodes.push_back(src_address_b); // argument 2 (unary only takes one parameter) } break; + case GDScriptParser::OperatorNode::OP_IS_BUILTIN: { + ERR_FAIL_COND_V(on->arguments.size() != 2, false); + ERR_FAIL_COND_V(on->arguments[1]->type != GDScriptParser::Node::TYPE_TYPE, false); + + int slevel = p_stack_level; + + int src_address_a = _parse_expression(codegen, on->arguments[0], slevel); + if (src_address_a < 0) + return -1; + + if (src_address_a & GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS) + slevel++; //uses stack for return, increase stack + + const GDScriptParser::TypeNode *tn = static_cast<const GDScriptParser::TypeNode *>(on->arguments[1]); + + codegen.opcodes.push_back(GDScriptFunction::OPCODE_IS_BUILTIN); // perform operator + codegen.opcodes.push_back(src_address_a); // argument 1 + codegen.opcodes.push_back((int)tn->vtype); // argument 2 (unary only takes one parameter) + } break; default: { ERR_EXPLAIN("Bug in bytecode compiler, unexpected operator #" + itos(on->op) + " in parse tree while parsing expression."); @@ -1322,6 +1341,8 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo int ret = _parse_expression(codegen, op, p_stack_level); if (ret < 0) { + memdelete(id); + memdelete(op); return ERR_PARSE_ERROR; } @@ -1341,6 +1362,8 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo // compile the condition int ret = _parse_expression(codegen, branch.compiled_pattern, p_stack_level); if (ret < 0) { + memdelete(id); + memdelete(op); return ERR_PARSE_ERROR; } @@ -1353,6 +1376,8 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo Error err = _parse_block(codegen, branch.body, p_stack_level, p_break_addr, continue_addr); if (err) { + memdelete(id); + memdelete(op); return ERR_PARSE_ERROR; } @@ -1364,6 +1389,9 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo codegen.opcodes.write[break_addr + 1] = codegen.opcodes.size(); + memdelete(id); + memdelete(op); + } break; case GDScriptParser::ControlFlowNode::CF_IF: { diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp index 30400f01e9..d3068fb6d0 100644 --- a/modules/gdscript/gdscript_editor.cpp +++ b/modules/gdscript/gdscript_editor.cpp @@ -63,8 +63,8 @@ Ref<Script> GDScriptLanguage::get_template(const String &p_class_name, const Str String _template = "extends %BASE%\n" "\n" "# Declare member variables here. Examples:\n" - "# var a %INT_TYPE%= 2\n" - "# var b %STRING_TYPE%= \"text\"\n" + "# var a%INT_TYPE% = 2\n" + "# var b%STRING_TYPE% = \"text\"\n" "\n" "# Called when the node enters the scene tree for the first time.\n" "func _ready()%VOID_RETURN%:\n" @@ -76,9 +76,9 @@ Ref<Script> GDScriptLanguage::get_template(const String &p_class_name, const Str #ifdef TOOLS_ENABLED if (EDITOR_DEF("text_editor/completion/add_type_hints", false)) { - _template = _template.replace("%INT_TYPE%", ": int "); - _template = _template.replace("%STRING_TYPE%", ": String "); - _template = _template.replace("%FLOAT_TYPE%", " : float"); + _template = _template.replace("%INT_TYPE%", ": int"); + _template = _template.replace("%STRING_TYPE%", ": String"); + _template = _template.replace("%FLOAT_TYPE%", ": float"); _template = _template.replace("%VOID_RETURN%", " -> void"); } else { _template = _template.replace("%INT_TYPE%", ""); @@ -466,7 +466,7 @@ String GDScriptLanguage::make_function(const String &p_class, const String &p_na if (th) { String type = p_args[i].get_slice(":", 1); if (!type.empty() && type != "var") { - s += " : " + type; + s += ": " + type; } } } @@ -2596,7 +2596,7 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_base } method_hint += arg; if (use_type_hint && mi.arguments[i].type != Variant::NIL) { - method_hint += " : "; + method_hint += ": "; if (mi.arguments[i].type == Variant::OBJECT && mi.arguments[i].class_name != StringName()) { method_hint += mi.arguments[i].class_name.operator String(); } else { diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp index bae3f48923..d615b58b24 100644 --- a/modules/gdscript/gdscript_function.cpp +++ b/modules/gdscript/gdscript_function.cpp @@ -191,6 +191,7 @@ static String _get_var_type(const Variant *p_type) { static const void *switch_table_ops[] = { \ &&OPCODE_OPERATOR, \ &&OPCODE_EXTENDS_TEST, \ + &&OPCODE_IS_BUILTIN, \ &&OPCODE_SET, \ &&OPCODE_GET, \ &&OPCODE_SET_NAMED, \ @@ -536,6 +537,21 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a } DISPATCH_OPCODE; + OPCODE(OPCODE_IS_BUILTIN) { + + CHECK_SPACE(4); + + GET_VARIANT_PTR(value, 1); + Variant::Type var_type = (Variant::Type)_code_ptr[ip + 2]; + GET_VARIANT_PTR(dst, 3); + + GD_ERR_BREAK(var_type < 0 || var_type >= Variant::VARIANT_MAX); + + *dst = value->get_type() == var_type; + ip += 4; + } + DISPATCH_OPCODE; + OPCODE(OPCODE_SET) { CHECK_SPACE(3); diff --git a/modules/gdscript/gdscript_function.h b/modules/gdscript/gdscript_function.h index 3ce84290fd..633cca35d3 100644 --- a/modules/gdscript/gdscript_function.h +++ b/modules/gdscript/gdscript_function.h @@ -136,6 +136,7 @@ public: enum Opcode { OPCODE_OPERATOR, OPCODE_EXTENDS_TEST, + OPCODE_IS_BUILTIN, OPCODE_SET, OPCODE_GET, OPCODE_SET_NAMED, diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index a3f5e1819e..7502f09d8a 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -861,6 +861,20 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s op->arguments.push_back(subexpr); expr=op;*/ + } else if (tokenizer->get_token() == GDScriptTokenizer::TK_PR_IS && tokenizer->get_token(1) == GDScriptTokenizer::TK_BUILT_IN_TYPE) { + // 'is' operator with built-in type + OperatorNode *op = alloc_node<OperatorNode>(); + op->op = OperatorNode::OP_IS_BUILTIN; + op->arguments.push_back(expr); + + tokenizer->advance(); + + TypeNode *tn = alloc_node<TypeNode>(); + tn->vtype = tokenizer->get_token_type(); + op->arguments.push_back(tn); + tokenizer->advance(); + + expr = op; } else if (tokenizer->get_token() == GDScriptTokenizer::TK_BRACKET_OPEN) { // array tokenizer->advance(); @@ -1071,6 +1085,15 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s expr = op; + } else if (tokenizer->get_token() == GDScriptTokenizer::TK_BUILT_IN_TYPE && expression.size() > 0 && expression[expression.size() - 1].is_op && expression[expression.size() - 1].op == OperatorNode::OP_IS) { + Expression e = expression[expression.size() - 1]; + e.op = OperatorNode::OP_IS_BUILTIN; + expression.write[expression.size() - 1] = e; + + TypeNode *tn = alloc_node<TypeNode>(); + tn->vtype = tokenizer->get_token_type(); + expr = tn; + tokenizer->advance(); } else { //find list [ or find dictionary { @@ -1329,6 +1352,7 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s switch (expression[i].op) { case OperatorNode::OP_IS: + case OperatorNode::OP_IS_BUILTIN: priority = -1; break; //before anything @@ -3915,14 +3939,15 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "FLAGS") { - //current_export.hint=PROPERTY_HINT_ALL_FLAGS; tokenizer->advance(); if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE) { + ERR_EXPLAIN("Exporting bit flags hint requires string constants."); + WARN_DEPRECATED break; } if (tokenizer->get_token() != GDScriptTokenizer::TK_COMMA) { - _set_error("Expected ')' or ',' in bit flags hint."); + _set_error("Expected ',' in bit flags hint."); return; } @@ -5793,6 +5818,13 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) { case Node::TYPE_CONSTANT: { node_type = _type_from_variant(static_cast<ConstantNode *>(p_node)->value); } break; + case Node::TYPE_TYPE: { + TypeNode *tn = static_cast<TypeNode *>(p_node); + node_type.has_type = true; + node_type.is_meta_type = true; + node_type.kind = DataType::BUILTIN; + node_type.builtin_type = tn->vtype; + } break; case Node::TYPE_ARRAY: { node_type.has_type = true; node_type.kind = DataType::BUILTIN; @@ -5896,7 +5928,8 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) { // yield can return anything node_type.has_type = false; } break; - case OperatorNode::OP_IS: { + case OperatorNode::OP_IS: + case OperatorNode::OP_IS_BUILTIN: { if (op->arguments.size() != 2) { _set_error("Parser bug: binary operation without 2 arguments.", op->line); @@ -5913,8 +5946,11 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) { } type_type.is_meta_type = false; // Test the actual type if (!_is_type_compatible(type_type, value_type) && !_is_type_compatible(value_type, type_type)) { - // TODO: Make this a warning? - _set_error("A value of type '" + value_type.to_string() + "' will never be an instance of '" + type_type.to_string() + "'.", op->line); + if (op->op == OperatorNode::OP_IS) { + _set_error("A value of type '" + value_type.to_string() + "' will never be an instance of '" + type_type.to_string() + "'.", op->line); + } else { + _set_error("A value of type '" + value_type.to_string() + "' will never be of type '" + type_type.to_string() + "'.", op->line); + } return DataType(); } } diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h index dbe523a0b9..3c51e3f372 100644 --- a/modules/gdscript/gdscript_parser.h +++ b/modules/gdscript/gdscript_parser.h @@ -345,6 +345,7 @@ public: OP_PARENT_CALL, OP_YIELD, OP_IS, + OP_IS_BUILTIN, //indexing operator OP_INDEX, OP_INDEX_NAMED, |