From e687fc6a4a658a6f74868b284352722c98f19ab6 Mon Sep 17 00:00:00 2001 From: Relintai Date: Tue, 12 Jul 2022 12:20:34 +0200 Subject: [PATCH] Added a new cscript module. It's a copy of gdscript, and it's build is disabled for now. I plan to experiment with it to have a scripting language that's syntax is as close to c (c++) as possible. --- modules/cscript/SCsub | 12 + modules/cscript/config.py | 21 + modules/cscript/cscript.cpp | 2293 +++++ modules/cscript/cscript.h | 567 ++ modules/cscript/cscript_compiler.cpp | 2236 +++++ modules/cscript/cscript_compiler.h | 169 + modules/cscript/cscript_editor.cpp | 3552 +++++++ modules/cscript/cscript_function.cpp | 1879 ++++ modules/cscript/cscript_function.h | 389 + modules/cscript/cscript_functions.cpp | 1984 ++++ modules/cscript/cscript_functions.h | 138 + modules/cscript/cscript_parser.cpp | 8926 +++++++++++++++++ modules/cscript/cscript_parser.h | 699 ++ modules/cscript/cscript_tokenizer.cpp | 1498 +++ modules/cscript/cscript_tokenizer.h | 306 + modules/cscript/doc_classes/@CScript.xml | 1237 +++ modules/cscript/doc_classes/CScript.xml | 35 + .../cscript/editor/cscript_highlighter.cpp | 395 + modules/cscript/editor/cscript_highlighter.h | 71 + modules/cscript/icons/icon_c_script.svg | 65 + modules/cscript/register_types.cpp | 170 + modules/cscript/register_types.h | 36 + 22 files changed, 26678 insertions(+) create mode 100644 modules/cscript/SCsub create mode 100644 modules/cscript/config.py create mode 100644 modules/cscript/cscript.cpp create mode 100644 modules/cscript/cscript.h create mode 100644 modules/cscript/cscript_compiler.cpp create mode 100644 modules/cscript/cscript_compiler.h create mode 100644 modules/cscript/cscript_editor.cpp create mode 100644 modules/cscript/cscript_function.cpp create mode 100644 modules/cscript/cscript_function.h create mode 100644 modules/cscript/cscript_functions.cpp create mode 100644 modules/cscript/cscript_functions.h create mode 100644 modules/cscript/cscript_parser.cpp create mode 100644 modules/cscript/cscript_parser.h create mode 100644 modules/cscript/cscript_tokenizer.cpp create mode 100644 modules/cscript/cscript_tokenizer.h create mode 100644 modules/cscript/doc_classes/@CScript.xml create mode 100644 modules/cscript/doc_classes/CScript.xml create mode 100644 modules/cscript/editor/cscript_highlighter.cpp create mode 100644 modules/cscript/editor/cscript_highlighter.h create mode 100644 modules/cscript/icons/icon_c_script.svg create mode 100644 modules/cscript/register_types.cpp create mode 100644 modules/cscript/register_types.h diff --git a/modules/cscript/SCsub b/modules/cscript/SCsub new file mode 100644 index 000000000..a4af0cf66 --- /dev/null +++ b/modules/cscript/SCsub @@ -0,0 +1,12 @@ +#!/usr/bin/env python + +Import("env") +Import("env_modules") + +env_gdscript = env_modules.Clone() + +env_gdscript.add_source_files(env.modules_sources, "*.cpp") + +if env["tools"]: + env_gdscript.add_source_files(env.modules_sources, "./editor/*.cpp") + \ No newline at end of file diff --git a/modules/cscript/config.py b/modules/cscript/config.py new file mode 100644 index 000000000..f22ac6711 --- /dev/null +++ b/modules/cscript/config.py @@ -0,0 +1,21 @@ + +def can_build(env, platform): + #return True + #not yet + return False + + +def configure(env): + pass + + +def get_doc_classes(): + return [ + "@CScript", + "CScript", + "CScriptFunctionState", + ] + + +def get_doc_path(): + return "doc_classes" diff --git a/modules/cscript/cscript.cpp b/modules/cscript/cscript.cpp new file mode 100644 index 000000000..db110202a --- /dev/null +++ b/modules/cscript/cscript.cpp @@ -0,0 +1,2293 @@ +/*************************************************************************/ +/* gdscript.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 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 */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "cscript.h" + +#include "core/core_string_names.h" +#include "core/engine.h" +#include "core/global_constants.h" +#include "core/io/file_access_encrypted.h" +#include "core/os/file_access.h" +#include "core/os/os.h" +#include "core/project_settings.h" +#include "cscript_compiler.h" + +/////////////////////////// + +GDScriptNativeClass::GDScriptNativeClass(const StringName &p_name) { + name = p_name; +} + +bool GDScriptNativeClass::_get(const StringName &p_name, Variant &r_ret) const { + bool ok; + int v = ClassDB::get_integer_constant(name, p_name, &ok); + + if (ok) { + r_ret = v; + return true; + } else { + return false; + } +} + +void GDScriptNativeClass::_bind_methods() { + ClassDB::bind_method(D_METHOD("new"), &GDScriptNativeClass::_new); +} + +Variant GDScriptNativeClass::_new() { + Object *o = instance(); + ERR_FAIL_COND_V_MSG(!o, Variant(), "Class type: '" + String(name) + "' is not instantiable."); + + Reference *ref = Object::cast_to(o); + if (ref) { + return REF(ref); + } else { + return o; + } +} + +Object *GDScriptNativeClass::instance() { + return ClassDB::instance(name); +} + +void GDScript::_clear_pending_func_states() { + GDScriptLanguage::get_singleton()->lock.lock(); + while (SelfList *E = pending_func_states.first()) { + // Order matters since clearing the stack may already cause + // the GDSCriptFunctionState to be destroyed and thus removed from the list. + pending_func_states.remove(E); + E->self()->_clear_stack(); + } + GDScriptLanguage::get_singleton()->lock.unlock(); +} + +GDScriptInstance *GDScript::_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_isref, Variant::CallError &r_error) { + /* STEP 1, CREATE */ + + GDScriptInstance *instance = memnew(GDScriptInstance); + instance->base_ref = p_isref; + instance->members.resize(member_indices.size()); + instance->script = Ref(this); + instance->owner = p_owner; +#ifdef DEBUG_ENABLED + //needed for hot reloading + for (Map::Element *E = member_indices.front(); E; E = E->next()) { + instance->member_indices_cache[E->key()] = E->get().index; + } +#endif + instance->owner->set_script_instance(instance); + + /* STEP 2, INITIALIZE AND CONSTRUCT */ + + GDScriptLanguage::singleton->lock.lock(); + instances.insert(instance->owner); + GDScriptLanguage::singleton->lock.unlock(); + + initializer->call(instance, p_args, p_argcount, r_error); + + if (r_error.error != Variant::CallError::CALL_OK) { + instance->script = Ref(); + instance->owner->set_script_instance(nullptr); +#ifndef NO_THREADS + GDScriptLanguage::singleton->lock.lock(); +#endif + instances.erase(p_owner); +#ifndef NO_THREADS + GDScriptLanguage::singleton->lock.unlock(); +#endif + + ERR_FAIL_COND_V(r_error.error != Variant::CallError::CALL_OK, nullptr); //error constructing + } + + //@TODO make thread safe + return instance; +} + +Variant GDScript::_new(const Variant **p_args, int p_argcount, Variant::CallError &r_error) { + /* STEP 1, CREATE */ + + if (!valid) { + r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD; + return Variant(); + } + + r_error.error = Variant::CallError::CALL_OK; + REF ref; + Object *owner = nullptr; + + GDScript *_baseptr = this; + while (_baseptr->_base) { + _baseptr = _baseptr->_base; + } + + ERR_FAIL_COND_V(_baseptr->native.is_null(), Variant()); + if (_baseptr->native.ptr()) { + owner = _baseptr->native->instance(); + } else { + owner = memnew(Reference); //by default, no base means use reference + } + ERR_FAIL_COND_V_MSG(!owner, Variant(), "Can't inherit from a virtual class."); + + Reference *r = Object::cast_to(owner); + if (r) { + ref = REF(r); + } + + GDScriptInstance *instance = _create_instance(p_args, p_argcount, owner, r != nullptr, r_error); + if (!instance) { + if (ref.is_null()) { + memdelete(owner); //no owner, sorry + } + return Variant(); + } + + if (ref.is_valid()) { + return ref; + } else { + return owner; + } +} + +bool GDScript::can_instance() const { +#ifdef TOOLS_ENABLED + return valid && (tool || ScriptServer::is_scripting_enabled()); +#else + return valid; +#endif +} + +Ref