1 /*************************************************************************/ 2 /* gdscript.h */ 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 #ifndef GDSCRIPT_H 32 #define GDSCRIPT_H 33 34 #include "core/io/resource_loader.h" 35 #include "core/io/resource_saver.h" 36 #include "core/script_language.h" 37 #include "gdscript_function.h" 38 39 class GDScriptNativeClass : public Reference { 40 41 GDCLASS(GDScriptNativeClass, Reference); 42 43 StringName name; 44 45 protected: 46 bool _get(const StringName &p_name, Variant &r_ret) const; 47 static void _bind_methods(); 48 49 public: get_name()50 _FORCE_INLINE_ const StringName &get_name() const { return name; } 51 Variant _new(); 52 Object *instance(); 53 GDScriptNativeClass(const StringName &p_name); 54 }; 55 56 class GDScript : public Script { 57 58 GDCLASS(GDScript, Script); 59 bool tool; 60 bool valid; 61 62 struct MemberInfo { 63 int index; 64 StringName setter; 65 StringName getter; 66 MultiplayerAPI::RPCMode rpc_mode; 67 GDScriptDataType data_type; 68 }; 69 70 friend class GDScriptInstance; 71 friend class GDScriptFunction; 72 friend class GDScriptCompiler; 73 friend class GDScriptFunctions; 74 friend class GDScriptLanguage; 75 76 Variant _static_ref; //used for static call 77 Ref<GDScriptNativeClass> native; 78 Ref<GDScript> base; 79 GDScript *_base; //fast pointer access 80 GDScript *_owner; //for subclasses 81 82 Set<StringName> members; //members are just indices to the instanced script. 83 Map<StringName, Variant> constants; 84 Map<StringName, GDScriptFunction *> member_functions; 85 Map<StringName, MemberInfo> member_indices; //members are just indices to the instanced script. 86 Map<StringName, Ref<GDScript> > subclasses; 87 Map<StringName, Vector<StringName> > _signals; 88 89 #ifdef TOOLS_ENABLED 90 91 Map<StringName, int> member_lines; 92 93 Map<StringName, Variant> member_default_values; 94 95 List<PropertyInfo> members_cache; 96 Map<StringName, Variant> member_default_values_cache; 97 Ref<GDScript> base_cache; 98 Set<ObjectID> inheriters_cache; 99 bool source_changed_cache; 100 bool placeholder_fallback_enabled; 101 void _update_exports_values(Map<StringName, Variant> &values, List<PropertyInfo> &propnames); 102 103 #endif 104 Map<StringName, PropertyInfo> member_info; 105 106 GDScriptFunction *initializer; //direct pointer to _init , faster to locate 107 108 int subclass_count; 109 Set<Object *> instances; 110 //exported members 111 String source; 112 String path; 113 String name; 114 String fully_qualified_name; 115 SelfList<GDScript> script_list; 116 117 SelfList<GDScriptFunctionState>::List pending_func_states; 118 119 GDScriptInstance *_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_isref, Variant::CallError &r_error); 120 121 void _set_subclass_path(Ref<GDScript> &p_sc, const String &p_path); 122 123 #ifdef TOOLS_ENABLED 124 Set<PlaceHolderScriptInstance *> placeholders; 125 //void _update_placeholder(PlaceHolderScriptInstance *p_placeholder); 126 virtual void _placeholder_erased(PlaceHolderScriptInstance *p_placeholder); 127 #endif 128 129 #ifdef DEBUG_ENABLED 130 131 Map<ObjectID, List<Pair<StringName, Variant> > > pending_reload_state; 132 133 #endif 134 135 bool _update_exports(bool *r_err = nullptr, bool p_recursive_call = false); 136 137 void _save_orphaned_subclasses(); 138 139 protected: 140 bool _get(const StringName &p_name, Variant &r_ret) const; 141 bool _set(const StringName &p_name, const Variant &p_value); 142 void _get_property_list(List<PropertyInfo> *p_properties) const; 143 144 Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error); 145 //void call_multilevel(const StringName& p_method,const Variant** p_args,int p_argcount); 146 147 static void _bind_methods(); 148 149 public: is_valid()150 virtual bool is_valid() const { return valid; } 151 get_subclasses()152 const Map<StringName, Ref<GDScript> > &get_subclasses() const { return subclasses; } get_constants()153 const Map<StringName, Variant> &get_constants() const { return constants; } get_members()154 const Set<StringName> &get_members() const { return members; } get_member_type(const StringName & p_member)155 const GDScriptDataType &get_member_type(const StringName &p_member) const { 156 CRASH_COND(!member_indices.has(p_member)); 157 return member_indices[p_member].data_type; 158 } get_member_functions()159 const Map<StringName, GDScriptFunction *> &get_member_functions() const { return member_functions; } get_native()160 const Ref<GDScriptNativeClass> &get_native() const { return native; } get_script_class_name()161 const String &get_script_class_name() const { return name; } 162 163 virtual bool has_script_signal(const StringName &p_signal) const; 164 virtual void get_script_signal_list(List<MethodInfo> *r_signals) const; 165 is_tool()166 bool is_tool() const { return tool; } 167 Ref<GDScript> get_base() const; 168 debug_get_member_indices()169 const Map<StringName, MemberInfo> &debug_get_member_indices() const { return member_indices; } 170 const Map<StringName, GDScriptFunction *> &debug_get_member_functions() const; //this is debug only 171 StringName debug_get_member_by_index(int p_idx) const; 172 173 Variant _new(const Variant **p_args, int p_argcount, Variant::CallError &r_error); 174 virtual bool can_instance() const; 175 176 virtual Ref<Script> get_base_script() const; 177 178 virtual StringName get_instance_base_type() const; // this may not work in all scripts, will return empty if so 179 virtual ScriptInstance *instance_create(Object *p_this); 180 virtual PlaceHolderScriptInstance *placeholder_instance_create(Object *p_this); 181 virtual bool instance_has(const Object *p_this) const; 182 183 virtual bool has_source_code() const; 184 virtual String get_source_code() const; 185 virtual void set_source_code(const String &p_code); 186 virtual void update_exports(); 187 188 virtual Error reload(bool p_keep_state = false); 189 set_script_path(const String & p_path)190 void set_script_path(const String &p_path) { path = p_path; } //because subclasses need a path too... 191 Error load_source_code(const String &p_path); 192 Error load_byte_code(const String &p_path); 193 194 Vector<uint8_t> get_as_byte_code() const; 195 196 bool get_property_default_value(const StringName &p_property, Variant &r_value) const; 197 198 virtual void get_script_method_list(List<MethodInfo> *p_list) const; 199 virtual bool has_method(const StringName &p_method) const; 200 virtual MethodInfo get_method_info(const StringName &p_method) const; 201 202 virtual void get_script_property_list(List<PropertyInfo> *p_list) const; 203 204 virtual ScriptLanguage *get_language() const; 205 get_member_line(const StringName & p_member)206 virtual int get_member_line(const StringName &p_member) const { 207 #ifdef TOOLS_ENABLED 208 if (member_lines.has(p_member)) 209 return member_lines[p_member]; 210 else 211 #endif 212 return -1; 213 } 214 215 virtual void get_constants(Map<StringName, Variant> *p_constants); 216 virtual void get_members(Set<StringName> *p_members); 217 218 #ifdef TOOLS_ENABLED is_placeholder_fallback_enabled()219 virtual bool is_placeholder_fallback_enabled() const { return placeholder_fallback_enabled; } 220 #endif 221 222 GDScript(); 223 ~GDScript(); 224 }; 225 226 class GDScriptInstance : public ScriptInstance { 227 friend class GDScript; 228 friend class GDScriptFunction; 229 friend class GDScriptFunctions; 230 friend class GDScriptCompiler; 231 232 Object *owner; 233 Ref<GDScript> script; 234 #ifdef DEBUG_ENABLED 235 Map<StringName, int> member_indices_cache; //used only for hot script reloading 236 #endif 237 Vector<Variant> members; 238 bool base_ref; 239 240 SelfList<GDScriptFunctionState>::List pending_func_states; 241 242 void _ml_call_reversed(GDScript *sptr, const StringName &p_method, const Variant **p_args, int p_argcount); 243 244 public: get_owner()245 virtual Object *get_owner() { return owner; } 246 247 virtual bool set(const StringName &p_name, const Variant &p_value); 248 virtual bool get(const StringName &p_name, Variant &r_ret) const; 249 virtual void get_property_list(List<PropertyInfo> *p_properties) const; 250 virtual Variant::Type get_property_type(const StringName &p_name, bool *r_is_valid = NULL) const; 251 252 virtual void get_method_list(List<MethodInfo> *p_list) const; 253 virtual bool has_method(const StringName &p_method) const; 254 virtual Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error); 255 virtual void call_multilevel(const StringName &p_method, const Variant **p_args, int p_argcount); 256 virtual void call_multilevel_reversed(const StringName &p_method, const Variant **p_args, int p_argcount); 257 debug_get_member_by_index(int p_idx)258 Variant debug_get_member_by_index(int p_idx) const { return members[p_idx]; } 259 260 virtual void notification(int p_notification); 261 String to_string(bool *r_valid); 262 263 virtual Ref<Script> get_script() const; 264 265 virtual ScriptLanguage *get_language(); 266 267 void set_path(const String &p_path); 268 269 void reload_members(); 270 271 virtual MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const; 272 virtual MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const; 273 274 GDScriptInstance(); 275 ~GDScriptInstance(); 276 }; 277 278 #ifdef DEBUG_ENABLED 279 struct GDScriptWarning { 280 enum Code { 281 UNASSIGNED_VARIABLE, // Variable used but never assigned 282 UNASSIGNED_VARIABLE_OP_ASSIGN, // Variable never assigned but used in an assignment operation (+=, *=, etc) 283 UNUSED_VARIABLE, // Local variable is declared but never used 284 SHADOWED_VARIABLE, // Variable name shadowed by other variable 285 UNUSED_CLASS_VARIABLE, // Class variable is declared but never used in the file 286 UNUSED_ARGUMENT, // Function argument is never used 287 UNREACHABLE_CODE, // Code after a return statement 288 STANDALONE_EXPRESSION, // Expression not assigned to a variable 289 VOID_ASSIGNMENT, // Function returns void but it's assigned to a variable 290 NARROWING_CONVERSION, // Float value into an integer slot, precision is lost 291 FUNCTION_MAY_YIELD, // Typed assign of function call that yields (it may return a function state) 292 VARIABLE_CONFLICTS_FUNCTION, // Variable has the same name of a function 293 FUNCTION_CONFLICTS_VARIABLE, // Function has the same name of a variable 294 FUNCTION_CONFLICTS_CONSTANT, // Function has the same name of a constant 295 INCOMPATIBLE_TERNARY, // Possible values of a ternary if are not mutually compatible 296 UNUSED_SIGNAL, // Signal is defined but never emitted 297 RETURN_VALUE_DISCARDED, // Function call returns something but the value isn't used 298 PROPERTY_USED_AS_FUNCTION, // Function not found, but there's a property with the same name 299 CONSTANT_USED_AS_FUNCTION, // Function not found, but there's a constant with the same name 300 FUNCTION_USED_AS_PROPERTY, // Property not found, but there's a function with the same name 301 INTEGER_DIVISION, // Integer divide by integer, decimal part is discarded 302 UNSAFE_PROPERTY_ACCESS, // Property not found in the detected type (but can be in subtypes) 303 UNSAFE_METHOD_ACCESS, // Function not found in the detected type (but can be in subtypes) 304 UNSAFE_CAST, // Cast used in an unknown type 305 UNSAFE_CALL_ARGUMENT, // Function call argument is of a supertype of the require argument 306 DEPRECATED_KEYWORD, // The keyword is deprecated and should be replaced 307 STANDALONE_TERNARY, // Return value of ternary expression is discarded 308 WARNING_MAX, 309 } code; 310 Vector<String> symbols; 311 int line; 312 313 String get_name() const; 314 String get_message() const; 315 static String get_name_from_code(Code p_code); 316 static Code get_code_from_name(const String &p_name); 317 GDScriptWarningGDScriptWarning318 GDScriptWarning() : 319 code(WARNING_MAX), 320 line(-1) {} 321 }; 322 #endif // DEBUG_ENABLED 323 324 class GDScriptLanguage : public ScriptLanguage { 325 326 friend class GDScriptFunctionState; 327 328 static GDScriptLanguage *singleton; 329 330 Variant *_global_array; 331 Vector<Variant> global_array; 332 Map<StringName, int> globals; 333 Map<StringName, Variant> named_globals; 334 335 struct CallLevel { 336 337 Variant *stack; 338 GDScriptFunction *function; 339 GDScriptInstance *instance; 340 int *ip; 341 int *line; 342 }; 343 344 int _debug_parse_err_line; 345 String _debug_parse_err_file; 346 String _debug_error; 347 int _debug_call_stack_pos; 348 int _debug_max_call_stack; 349 CallLevel *_call_stack; 350 351 void _add_global(const StringName &p_name, const Variant &p_value); 352 353 friend class GDScriptInstance; 354 355 Mutex *lock; 356 357 friend class GDScript; 358 359 SelfList<GDScript>::List script_list; 360 friend class GDScriptFunction; 361 362 SelfList<GDScriptFunction>::List function_list; 363 bool profiling; 364 uint64_t script_frame_time; 365 366 Map<String, ObjectID> orphan_subclasses; 367 368 public: 369 int calls; 370 371 bool debug_break(const String &p_error, bool p_allow_continue = true); 372 bool debug_break_parse(const String &p_file, int p_line, const String &p_error); 373 enter_function(GDScriptInstance * p_instance,GDScriptFunction * p_function,Variant * p_stack,int * p_ip,int * p_line)374 _FORCE_INLINE_ void enter_function(GDScriptInstance *p_instance, GDScriptFunction *p_function, Variant *p_stack, int *p_ip, int *p_line) { 375 376 if (Thread::get_main_id() != Thread::get_caller_id()) 377 return; //no support for other threads than main for now 378 379 if (ScriptDebugger::get_singleton()->get_lines_left() > 0 && ScriptDebugger::get_singleton()->get_depth() >= 0) 380 ScriptDebugger::get_singleton()->set_depth(ScriptDebugger::get_singleton()->get_depth() + 1); 381 382 if (_debug_call_stack_pos >= _debug_max_call_stack) { 383 //stack overflow 384 _debug_error = "Stack Overflow (Stack Size: " + itos(_debug_max_call_stack) + ")"; 385 ScriptDebugger::get_singleton()->debug(this); 386 return; 387 } 388 389 _call_stack[_debug_call_stack_pos].stack = p_stack; 390 _call_stack[_debug_call_stack_pos].instance = p_instance; 391 _call_stack[_debug_call_stack_pos].function = p_function; 392 _call_stack[_debug_call_stack_pos].ip = p_ip; 393 _call_stack[_debug_call_stack_pos].line = p_line; 394 _debug_call_stack_pos++; 395 } 396 exit_function()397 _FORCE_INLINE_ void exit_function() { 398 399 if (Thread::get_main_id() != Thread::get_caller_id()) 400 return; //no support for other threads than main for now 401 402 if (ScriptDebugger::get_singleton()->get_lines_left() > 0 && ScriptDebugger::get_singleton()->get_depth() >= 0) 403 ScriptDebugger::get_singleton()->set_depth(ScriptDebugger::get_singleton()->get_depth() - 1); 404 405 if (_debug_call_stack_pos == 0) { 406 407 _debug_error = "Stack Underflow (Engine Bug)"; 408 ScriptDebugger::get_singleton()->debug(this); 409 return; 410 } 411 412 _debug_call_stack_pos--; 413 } 414 debug_get_current_stack_info()415 virtual Vector<StackInfo> debug_get_current_stack_info() { 416 if (Thread::get_main_id() != Thread::get_caller_id()) 417 return Vector<StackInfo>(); 418 419 Vector<StackInfo> csi; 420 csi.resize(_debug_call_stack_pos); 421 for (int i = 0; i < _debug_call_stack_pos; i++) { 422 csi.write[_debug_call_stack_pos - i - 1].line = _call_stack[i].line ? *_call_stack[i].line : 0; 423 if (_call_stack[i].function) { 424 csi.write[_debug_call_stack_pos - i - 1].func = _call_stack[i].function->get_name(); 425 csi.write[_debug_call_stack_pos - i - 1].file = _call_stack[i].function->get_script()->get_path(); 426 } 427 } 428 return csi; 429 } 430 431 struct { 432 433 StringName _init; 434 StringName _notification; 435 StringName _set; 436 StringName _get; 437 StringName _get_property_list; 438 StringName _script_source; 439 440 } strings; 441 get_global_array_size()442 _FORCE_INLINE_ int get_global_array_size() const { return global_array.size(); } get_global_array()443 _FORCE_INLINE_ Variant *get_global_array() { return _global_array; } get_global_map()444 _FORCE_INLINE_ const Map<StringName, int> &get_global_map() const { return globals; } get_named_globals_map()445 _FORCE_INLINE_ const Map<StringName, Variant> &get_named_globals_map() const { return named_globals; } 446 get_singleton()447 _FORCE_INLINE_ static GDScriptLanguage *get_singleton() { return singleton; } 448 449 virtual String get_name() const; 450 451 /* LANGUAGE FUNCTIONS */ 452 virtual void init(); 453 virtual String get_type() const; 454 virtual String get_extension() const; 455 virtual Error execute_file(const String &p_path); 456 virtual void finish(); 457 458 /* EDITOR FUNCTIONS */ 459 virtual void get_reserved_words(List<String> *p_words) const; 460 virtual void get_comment_delimiters(List<String> *p_delimiters) const; 461 virtual void get_string_delimiters(List<String> *p_delimiters) const; 462 virtual String _get_processed_template(const String &p_template, const String &p_base_class_name) const; 463 virtual Ref<Script> get_template(const String &p_class_name, const String &p_base_class_name) const; 464 virtual bool is_using_templates(); 465 virtual void make_template(const String &p_class_name, const String &p_base_class_name, Ref<Script> &p_script); 466 virtual bool validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path = "", List<String> *r_functions = NULL, List<ScriptLanguage::Warning> *r_warnings = NULL, Set<int> *r_safe_lines = NULL) const; 467 virtual Script *create_script() const; 468 virtual bool has_named_classes() const; 469 virtual bool supports_builtin_mode() const; can_inherit_from_file()470 virtual bool can_inherit_from_file() { return true; } 471 virtual int find_function(const String &p_function, const String &p_code) const; 472 virtual String make_function(const String &p_class, const String &p_name, const PoolStringArray &p_args) const; 473 virtual Error complete_code(const String &p_code, const String &p_path, Object *p_owner, List<ScriptCodeCompletionOption> *r_options, bool &r_forced, String &r_call_hint); 474 #ifdef TOOLS_ENABLED 475 virtual Error lookup_code(const String &p_code, const String &p_symbol, const String &p_path, Object *p_owner, LookupResult &r_result); 476 #endif 477 virtual String _get_indentation() const; 478 virtual void auto_indent_code(String &p_code, int p_from_line, int p_to_line) const; 479 virtual void add_global_constant(const StringName &p_variable, const Variant &p_value); 480 virtual void add_named_global_constant(const StringName &p_name, const Variant &p_value); 481 virtual void remove_named_global_constant(const StringName &p_name); 482 483 /* DEBUGGER FUNCTIONS */ 484 485 virtual String debug_get_error() const; 486 virtual int debug_get_stack_level_count() const; 487 virtual int debug_get_stack_level_line(int p_level) const; 488 virtual String debug_get_stack_level_function(int p_level) const; 489 virtual String debug_get_stack_level_source(int p_level) const; 490 virtual void debug_get_stack_level_locals(int p_level, List<String> *p_locals, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1); 491 virtual void debug_get_stack_level_members(int p_level, List<String> *p_members, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1); 492 virtual ScriptInstance *debug_get_stack_level_instance(int p_level); 493 virtual void debug_get_globals(List<String> *p_globals, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1); 494 virtual String debug_parse_stack_level_expression(int p_level, const String &p_expression, int p_max_subitems = -1, int p_max_depth = -1); 495 496 virtual void reload_all_scripts(); 497 virtual void reload_tool_script(const Ref<Script> &p_script, bool p_soft_reload); 498 499 virtual void frame(); 500 501 virtual void get_public_functions(List<MethodInfo> *p_functions) const; 502 virtual void get_public_constants(List<Pair<String, Variant> > *p_constants) const; 503 504 virtual void profiling_start(); 505 virtual void profiling_stop(); 506 507 virtual int profiling_get_accumulated_data(ProfilingInfo *p_info_arr, int p_info_max); 508 virtual int profiling_get_frame_data(ProfilingInfo *p_info_arr, int p_info_max); 509 510 /* LOADER FUNCTIONS */ 511 512 virtual void get_recognized_extensions(List<String> *p_extensions) const; 513 514 /* GLOBAL CLASSES */ 515 516 virtual bool handles_global_class_type(const String &p_type) const; 517 virtual String get_global_class_name(const String &p_path, String *r_base_type = NULL, String *r_icon_path = NULL) const; 518 519 void add_orphan_subclass(const String &p_qualified_name, const ObjectID &p_subclass); 520 Ref<GDScript> get_orphan_subclass(const String &p_qualified_name); 521 522 GDScriptLanguage(); 523 ~GDScriptLanguage(); 524 }; 525 526 class ResourceFormatLoaderGDScript : public ResourceFormatLoader { 527 public: 528 virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = NULL); 529 virtual void get_recognized_extensions(List<String> *p_extensions) const; 530 virtual bool handles_type(const String &p_type) const; 531 virtual String get_resource_type(const String &p_path) const; 532 virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false); 533 }; 534 535 class ResourceFormatSaverGDScript : public ResourceFormatSaver { 536 public: 537 virtual Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0); 538 virtual void get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const; 539 virtual bool recognize(const RES &p_resource) const; 540 }; 541 542 #endif // GDSCRIPT_H 543