| 2551 | } |
| 2552 | |
| 2553 | GDScriptFunction *GDScriptCompiler::_make_static_initializer(Error &r_error, GDScript *p_script, const GDScriptParser::ClassNode *p_class) { |
| 2554 | r_error = OK; |
| 2555 | CodeGen codegen; |
| 2556 | codegen.generator = memnew(GDScriptByteCodeGenerator); |
| 2557 | |
| 2558 | codegen.class_node = p_class; |
| 2559 | codegen.script = p_script; |
| 2560 | |
| 2561 | StringName func_name = SNAME("@static_initializer"); |
| 2562 | bool is_static = true; |
| 2563 | Variant rpc_config; |
| 2564 | GDScriptDataType return_type; |
| 2565 | return_type.has_type = true; |
| 2566 | return_type.kind = GDScriptDataType::BUILTIN; |
| 2567 | return_type.builtin_type = Variant::NIL; |
| 2568 | |
| 2569 | codegen.function_name = func_name; |
| 2570 | codegen.is_static = is_static; |
| 2571 | codegen.generator->write_start(p_script, func_name, is_static, rpc_config, return_type); |
| 2572 | |
| 2573 | // The static initializer is always called on the same class where the static variables are defined, |
| 2574 | // so the CLASS address (current class) can be used instead of `codegen.add_constant(p_script)`. |
| 2575 | GDScriptCodeGenerator::Address class_addr(GDScriptCodeGenerator::Address::CLASS); |
| 2576 | |
| 2577 | // Initialize the default values for typed variables before anything. |
| 2578 | // This avoids crashes if they are accessed with validated calls before being properly initialized. |
| 2579 | // It may happen with out-of-order access or with `@onready` variables. |
| 2580 | for (const GDScriptParser::ClassNode::Member &member : p_class->members) { |
| 2581 | if (member.type != GDScriptParser::ClassNode::Member::VARIABLE) { |
| 2582 | continue; |
| 2583 | } |
| 2584 | |
| 2585 | const GDScriptParser::VariableNode *field = member.variable; |
| 2586 | if (!field->is_static) { |
| 2587 | continue; |
| 2588 | } |
| 2589 | |
| 2590 | GDScriptDataType field_type = _gdtype_from_datatype(field->get_datatype(), codegen.script); |
| 2591 | if (field_type.has_type) { |
| 2592 | codegen.generator->write_newline(field->start_line); |
| 2593 | |
| 2594 | if (field_type.builtin_type == Variant::ARRAY && field_type.has_container_element_type(0)) { |
| 2595 | GDScriptCodeGenerator::Address temp = codegen.add_temporary(field_type); |
| 2596 | codegen.generator->write_construct_typed_array(temp, field_type.get_container_element_type(0), Vector<GDScriptCodeGenerator::Address>()); |
| 2597 | codegen.generator->write_set_static_variable(temp, class_addr, p_script->static_variables_indices[field->identifier->name].index); |
| 2598 | codegen.generator->pop_temporary(); |
| 2599 | } else if (field_type.builtin_type == Variant::DICTIONARY && field_type.has_container_element_types()) { |
| 2600 | GDScriptCodeGenerator::Address temp = codegen.add_temporary(field_type); |
| 2601 | codegen.generator->write_construct_typed_dictionary(temp, field_type.get_container_element_type_or_variant(0), |
| 2602 | field_type.get_container_element_type_or_variant(1), Vector<GDScriptCodeGenerator::Address>()); |
| 2603 | codegen.generator->write_set_static_variable(temp, class_addr, p_script->static_variables_indices[field->identifier->name].index); |
| 2604 | codegen.generator->pop_temporary(); |
| 2605 | } else if (field_type.kind == GDScriptDataType::BUILTIN) { |
| 2606 | GDScriptCodeGenerator::Address temp = codegen.add_temporary(field_type); |
| 2607 | codegen.generator->write_construct(temp, field_type.builtin_type, Vector<GDScriptCodeGenerator::Address>()); |
| 2608 | codegen.generator->write_set_static_variable(temp, class_addr, p_script->static_variables_indices[field->identifier->name].index); |
| 2609 | codegen.generator->pop_temporary(); |
| 2610 | } |
nothing calls this directly
no test coverage detected