diff options
Diffstat (limited to 'modules/gdscript/gdscript_compiler.h')
-rw-r--r-- | modules/gdscript/gdscript_compiler.h | 170 |
1 files changed, 76 insertions, 94 deletions
diff --git a/modules/gdscript/gdscript_compiler.h b/modules/gdscript/gdscript_compiler.h index 315d4f1842..7d5bee93ac 100644 --- a/modules/gdscript/gdscript_compiler.h +++ b/modules/gdscript/gdscript_compiler.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,108 +31,86 @@ #ifndef GDSCRIPT_COMPILER_H #define GDSCRIPT_COMPILER_H -#include "core/set.h" +#include "core/templates/set.h" #include "gdscript.h" +#include "gdscript_codegen.h" +#include "gdscript_function.h" #include "gdscript_parser.h" class GDScriptCompiler { - const GDScriptParser *parser; + const GDScriptParser *parser = nullptr; Set<GDScript *> parsed_classes; Set<GDScript *> parsing_classes; - GDScript *main_script; + GDScript *main_script = nullptr; + struct CodeGen { - GDScript *script; - const GDScriptParser::ClassNode *class_node; - const GDScriptParser::FunctionNode *function_node; - bool debug_stack; - - List<Map<StringName, int>> stack_id_stack; - Map<StringName, int> stack_identifiers; - - List<GDScriptFunction::StackDebug> stack_debug; - List<Map<StringName, int>> block_identifier_stack; - Map<StringName, int> block_identifiers; - - void add_stack_identifier(const StringName &p_id, int p_stackpos) { - stack_identifiers[p_id] = p_stackpos; - if (debug_stack) { - block_identifiers[p_id] = p_stackpos; - GDScriptFunction::StackDebug sd; - sd.added = true; - sd.line = current_line; - sd.identifier = p_id; - sd.pos = p_stackpos; - stack_debug.push_back(sd); - } + GDScript *script = nullptr; + const GDScriptParser::ClassNode *class_node = nullptr; + const GDScriptParser::FunctionNode *function_node = nullptr; + StringName function_name; + GDScriptCodeGenerator *generator = nullptr; + Map<StringName, GDScriptCodeGenerator::Address> parameters; + Map<StringName, GDScriptCodeGenerator::Address> locals; + List<Map<StringName, GDScriptCodeGenerator::Address>> locals_stack; + + GDScriptCodeGenerator::Address add_local(const StringName &p_name, const GDScriptDataType &p_type) { + uint32_t addr = generator->add_local(p_name, p_type); + locals[p_name] = GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::LOCAL_VARIABLE, addr, p_type); + return locals[p_name]; } - void push_stack_identifiers() { - stack_id_stack.push_back(stack_identifiers); - if (debug_stack) { - block_identifier_stack.push_back(block_identifiers); - block_identifiers.clear(); - } + GDScriptCodeGenerator::Address add_local_constant(const StringName &p_name, const Variant &p_value) { + uint32_t addr = generator->add_local_constant(p_name, p_value); + locals[p_name] = GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::CONSTANT, addr); + return locals[p_name]; } - void pop_stack_identifiers() { - stack_identifiers = stack_id_stack.back()->get(); - stack_id_stack.pop_back(); - - if (debug_stack) { - for (Map<StringName, int>::Element *E = block_identifiers.front(); E; E = E->next()) { - GDScriptFunction::StackDebug sd; - sd.added = false; - sd.identifier = E->key(); - sd.line = current_line; - sd.pos = E->get(); - stack_debug.push_back(sd); - } - block_identifiers = block_identifier_stack.back()->get(); - block_identifier_stack.pop_back(); - } + GDScriptCodeGenerator::Address add_temporary(const GDScriptDataType &p_type = GDScriptDataType()) { + uint32_t addr = generator->add_temporary(p_type); + return GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::TEMPORARY, addr, p_type); } - HashMap<Variant, int, VariantHasher, VariantComparator> constant_map; - Map<StringName, int> name_map; -#ifdef TOOLS_ENABLED - Vector<StringName> named_globals; -#endif - - int get_name_map_pos(const StringName &p_identifier) { - int ret; - if (!name_map.has(p_identifier)) { - ret = name_map.size(); - name_map[p_identifier] = ret; - } else { - ret = name_map[p_identifier]; + GDScriptCodeGenerator::Address add_constant(const Variant &p_constant) { + GDScriptDataType type; + type.has_type = true; + type.kind = GDScriptDataType::BUILTIN; + type.builtin_type = p_constant.get_type(); + if (type.builtin_type == Variant::OBJECT) { + Object *obj = p_constant; + if (obj) { + type.kind = GDScriptDataType::NATIVE; + type.native_type = obj->get_class_name(); + + Ref<Script> script = obj->get_script(); + if (script.is_valid()) { + type.script_type = script.ptr(); + Ref<GDScript> gdscript = script; + if (gdscript.is_valid()) { + type.kind = GDScriptDataType::GDSCRIPT; + } else { + type.kind = GDScriptDataType::SCRIPT; + } + } + } else { + type.builtin_type = Variant::NIL; + } } - return ret; - } - int get_constant_pos(const Variant &p_constant) { - if (constant_map.has(p_constant)) { - return constant_map[p_constant]; - } - int pos = constant_map.size(); - constant_map[p_constant] = pos; - return pos; + uint32_t addr = generator->add_or_get_constant(p_constant); + return GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::CONSTANT, addr, type); } - Vector<int> opcodes; - void alloc_stack(int p_level) { - if (p_level >= stack_max) { - stack_max = p_level + 1; - } - } - void alloc_call(int p_params) { - if (p_params >= call_max) { - call_max = p_params; - } + void start_block() { + Map<StringName, GDScriptCodeGenerator::Address> old_locals = locals; + locals_stack.push_back(old_locals); + generator->start_block(); } - int current_line; - int stack_max; - int call_max; + void end_block() { + locals = locals_stack.back()->get(); + locals_stack.pop_back(); + generator->end_block(); + } }; bool _is_class_member_property(CodeGen &codegen, const StringName &p_name); @@ -140,22 +118,26 @@ class GDScriptCompiler { void _set_error(const String &p_error, const GDScriptParser::Node *p_node); - bool _create_unary_operator(CodeGen &codegen, const GDScriptParser::OperatorNode *on, Variant::Operator op, int p_stack_level); - bool _create_binary_operator(CodeGen &codegen, const GDScriptParser::OperatorNode *on, Variant::Operator op, int p_stack_level, bool p_initializer = false, int p_index_addr = 0); + Error _create_binary_operator(CodeGen &codegen, const GDScriptParser::BinaryOpNode *on, Variant::Operator op, bool p_initializer = false, const GDScriptCodeGenerator::Address &p_index_addr = GDScriptCodeGenerator::Address()); + Error _create_binary_operator(CodeGen &codegen, const GDScriptParser::ExpressionNode *p_left_operand, const GDScriptParser::ExpressionNode *p_right_operand, Variant::Operator op, bool p_initializer = false, const GDScriptCodeGenerator::Address &p_index_addr = GDScriptCodeGenerator::Address()); - GDScriptDataType _gdtype_from_datatype(const GDScriptParser::DataType &p_datatype) const; + GDScriptDataType _gdtype_from_datatype(const GDScriptParser::DataType &p_datatype, GDScript *p_owner = nullptr) const; - int _parse_assign_right_expression(CodeGen &codegen, const GDScriptParser::OperatorNode *p_expression, int p_stack_level, int p_index_addr = 0); - int _parse_expression(CodeGen &codegen, const GDScriptParser::Node *p_expression, int p_stack_level, bool p_root = false, bool p_initializer = false, int p_index_addr = 0); - Error _parse_block(CodeGen &codegen, const GDScriptParser::BlockNode *p_block, int p_stack_level = 0, int p_break_addr = -1, int p_continue_addr = -1); - Error _parse_function(GDScript *p_script, const GDScriptParser::ClassNode *p_class, const GDScriptParser::FunctionNode *p_func, bool p_for_ready = false); + GDScriptCodeGenerator::Address _parse_assign_right_expression(CodeGen &codegen, Error &r_error, const GDScriptParser::AssignmentNode *p_assignmentint, const GDScriptCodeGenerator::Address &p_index_addr = GDScriptCodeGenerator::Address()); + GDScriptCodeGenerator::Address _parse_expression(CodeGen &codegen, Error &r_error, const GDScriptParser::ExpressionNode *p_expression, bool p_root = false, bool p_initializer = false, const GDScriptCodeGenerator::Address &p_index_addr = GDScriptCodeGenerator::Address()); + GDScriptCodeGenerator::Address _parse_match_pattern(CodeGen &codegen, Error &r_error, const GDScriptParser::PatternNode *p_pattern, const GDScriptCodeGenerator::Address &p_value_addr, const GDScriptCodeGenerator::Address &p_type_addr, const GDScriptCodeGenerator::Address &p_previous_test, bool p_is_first, bool p_is_nested); + void _add_locals_in_block(CodeGen &codegen, const GDScriptParser::SuiteNode *p_block); + Error _parse_block(CodeGen &codegen, const GDScriptParser::SuiteNode *p_block, bool p_add_locals = true); + GDScriptFunction *_parse_function(Error &r_error, GDScript *p_script, const GDScriptParser::ClassNode *p_class, const GDScriptParser::FunctionNode *p_func, bool p_for_ready = false, bool p_for_lambda = false); + Error _parse_setter_getter(GDScript *p_script, const GDScriptParser::ClassNode *p_class, const GDScriptParser::VariableNode *p_variable, bool p_is_setter); Error _parse_class_level(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state); Error _parse_class_blocks(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state); void _make_scripts(GDScript *p_script, const GDScriptParser::ClassNode *p_class, bool p_keep_state); - int err_line; - int err_column; + int err_line = 0; + int err_column = 0; StringName source; String error; + bool within_await = false; public: Error compile(const GDScriptParser *p_parser, GDScript *p_script, bool p_keep_state = false); |