Replaced godot-cpp with submodule
This commit is contained in:
BIN
extensions/cobor_terrain_extension/.sconsign.dblite
Normal file
BIN
extensions/cobor_terrain_extension/.sconsign.dblite
Normal file
Binary file not shown.
15
extensions/cobor_terrain_extension/.vscode/c_cpp_properties.json
vendored
Normal file
15
extensions/cobor_terrain_extension/.vscode/c_cpp_properties.json
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"includePath": [
|
||||
"${workspaceFolder}/**",
|
||||
"${workspaceFolder}/../godot-cpp/**"
|
||||
],
|
||||
"intelliSenseMode": "linux-gcc-x64",
|
||||
"compilerPath": "/usr/bin/gcc",
|
||||
"cStandard": "c17",
|
||||
"cppStandard": "gnu++17"
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
||||
61
extensions/cobor_terrain_extension/.vscode/settings.json
vendored
Normal file
61
extensions/cobor_terrain_extension/.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
{
|
||||
"files.associations": {
|
||||
"*.inc": "cpp",
|
||||
"array": "cpp",
|
||||
"atomic": "cpp",
|
||||
"bit": "cpp",
|
||||
"cctype": "cpp",
|
||||
"cerrno": "cpp",
|
||||
"climits": "cpp",
|
||||
"clocale": "cpp",
|
||||
"cmath": "cpp",
|
||||
"compare": "cpp",
|
||||
"concepts": "cpp",
|
||||
"condition_variable": "cpp",
|
||||
"cstdarg": "cpp",
|
||||
"cstddef": "cpp",
|
||||
"cstdint": "cpp",
|
||||
"cstdio": "cpp",
|
||||
"cstdlib": "cpp",
|
||||
"cstring": "cpp",
|
||||
"ctime": "cpp",
|
||||
"cwchar": "cpp",
|
||||
"cwctype": "cpp",
|
||||
"deque": "cpp",
|
||||
"list": "cpp",
|
||||
"set": "cpp",
|
||||
"string": "cpp",
|
||||
"unordered_map": "cpp",
|
||||
"vector": "cpp",
|
||||
"exception": "cpp",
|
||||
"algorithm": "cpp",
|
||||
"functional": "cpp",
|
||||
"iterator": "cpp",
|
||||
"memory": "cpp",
|
||||
"memory_resource": "cpp",
|
||||
"numeric": "cpp",
|
||||
"optional": "cpp",
|
||||
"random": "cpp",
|
||||
"ratio": "cpp",
|
||||
"string_view": "cpp",
|
||||
"system_error": "cpp",
|
||||
"tuple": "cpp",
|
||||
"type_traits": "cpp",
|
||||
"utility": "cpp",
|
||||
"initializer_list": "cpp",
|
||||
"iosfwd": "cpp",
|
||||
"iostream": "cpp",
|
||||
"istream": "cpp",
|
||||
"limits": "cpp",
|
||||
"mutex": "cpp",
|
||||
"new": "cpp",
|
||||
"numbers": "cpp",
|
||||
"ostream": "cpp",
|
||||
"semaphore": "cpp",
|
||||
"stdexcept": "cpp",
|
||||
"stop_token": "cpp",
|
||||
"streambuf": "cpp",
|
||||
"thread": "cpp",
|
||||
"typeinfo": "cpp"
|
||||
}
|
||||
}
|
||||
65
extensions/cobor_terrain_extension/SConstruct
Normal file
65
extensions/cobor_terrain_extension/SConstruct
Normal file
@@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env python
|
||||
import os
|
||||
import sys
|
||||
|
||||
from methods import print_error
|
||||
|
||||
|
||||
libname = "cobor_terrain_extension"
|
||||
projectdir = "."
|
||||
|
||||
localEnv = Environment(tools=["default"], PLATFORM="")
|
||||
|
||||
# Build profiles can be used to decrease compile times.
|
||||
# You can either specify "disabled_classes", OR
|
||||
# explicitly specify "enabled_classes" which disables all other classes.
|
||||
# Modify the example file as needed and uncomment the line below or
|
||||
# manually specify the build_profile parameter when running SCons.
|
||||
|
||||
# localEnv["build_profile"] = "build_profile.json"
|
||||
|
||||
customs = ["custom.py"]
|
||||
customs = [os.path.abspath(path) for path in customs]
|
||||
|
||||
opts = Variables(customs, ARGUMENTS)
|
||||
opts.Update(localEnv)
|
||||
|
||||
Help(opts.GenerateHelpText(localEnv))
|
||||
|
||||
env = localEnv.Clone()
|
||||
|
||||
if not (os.path.isdir("../godot-cpp") and os.listdir("../godot-cpp")):
|
||||
print_error("""godot-cpp is not available within this folder, as Git submodules haven't been initialized.
|
||||
Run the following command to download godot-cpp:
|
||||
|
||||
git submodule update --init --recursive""")
|
||||
sys.exit(1)
|
||||
|
||||
env = SConscript("../godot-cpp/SConstruct", {"env": env, "customs": customs})
|
||||
|
||||
env.Append(CPPPATH=["cobor_terrain/include/"])
|
||||
env.Append(CPPPATH=["cobor_terrain/src/"])
|
||||
sources = Glob("cobor_terrain/src/*.cpp")
|
||||
|
||||
if env["target"] in ["editor", "template_debug"]:
|
||||
try:
|
||||
doc_data = env.GodotCPPDocData("cobor_terrain/src/gen/doc_data.gen.cpp", source=Glob("doc_classes/*.xml"))
|
||||
sources.append(doc_data)
|
||||
except AttributeError:
|
||||
print("Not including class reference as we're targeting a pre-4.3 baseline.")
|
||||
|
||||
# .dev doesn't inhibit compatibility, so we don't need to key it.
|
||||
# .universal just means "compatible with all relevant arches" so we don't need to key it.
|
||||
suffix = env['suffix'].replace(".dev", "").replace(".universal", "")
|
||||
|
||||
lib_filename = "{}{}{}{}".format(env.subst('$SHLIBPREFIX'), libname, suffix, env.subst('$SHLIBSUFFIX'))
|
||||
|
||||
library = env.SharedLibrary(
|
||||
"bin/{}/{}".format(env['platform'], lib_filename),
|
||||
source=sources,
|
||||
)
|
||||
|
||||
# copy = env.Install("{}/bin/{}/".format(projectdir, env["platform"]), library)
|
||||
|
||||
default_args = [library]
|
||||
Default(*default_args)
|
||||
Binary file not shown.
Binary file not shown.
10
extensions/cobor_terrain_extension/cobor_terrain.gdextension
Normal file
10
extensions/cobor_terrain_extension/cobor_terrain.gdextension
Normal file
@@ -0,0 +1,10 @@
|
||||
[configuration]
|
||||
|
||||
entry_symbol = "cobor_terrain_library_init"
|
||||
compatibility_minimum = "4.1"
|
||||
|
||||
[libraries]
|
||||
; Relative paths ensure that our GDExtension can be placed anywhere in the project directory.
|
||||
|
||||
linux.x86_64.debug = "./bin/linux/libcobor_terrain_extension.linux.template_debug.x86_64.so"
|
||||
linux.x86_64.release = "./bin/linux/libcobor_terrain_extension.linux.template_release.x86_64.so"
|
||||
@@ -0,0 +1 @@
|
||||
uid://dskh86iu7g6lk
|
||||
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include "godot_cpp/classes/ref_counted.hpp"
|
||||
|
||||
namespace CoborTerrain
|
||||
{
|
||||
class CoborTerrainEngine : public godot::RefCounted
|
||||
{
|
||||
GDCLASS(CoborTerrainEngine, godot::RefCounted)
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
CoborTerrainEngine() = default;
|
||||
~CoborTerrainEngine() override = default;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#ifndef COBOR_TERRAIN_REGISTER_TYPES_H
|
||||
#define COBOR_TERRAIN_REGISTER_TYPES_H
|
||||
|
||||
void initialize_gdextension_types();
|
||||
void uninitialize_gdextension_types();
|
||||
|
||||
#endif // COBOR_TERRAIN_REGISTER_TYPES_H
|
||||
@@ -0,0 +1,8 @@
|
||||
#include "cobor_terrain_engine.hpp"
|
||||
|
||||
using namespace CoborTerrain;
|
||||
|
||||
void CoborTerrain::CoborTerrainEngine::_bind_methods()
|
||||
{
|
||||
// godot::ClassDB::bind_method(godot::D_METHOD("parse_source_code", "source_code"), &CoborVirtualMachine::parse_source_code);
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,20 @@
|
||||
/* THIS FILE IS GENERATED DO NOT EDIT */
|
||||
|
||||
#include <godot_cpp/godot.hpp>
|
||||
|
||||
static const char *_doc_data_hash = "-4005597214191675931";
|
||||
static const int _doc_data_uncompressed_size = 0;
|
||||
static const int _doc_data_compressed_size = 8;
|
||||
static const unsigned char _doc_data_compressed[] = {
|
||||
120,
|
||||
218,
|
||||
3,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
};
|
||||
|
||||
static godot::internal::DocDataRegistration _doc_data_registration(_doc_data_hash, _doc_data_uncompressed_size, _doc_data_compressed_size, _doc_data_compressed);
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,38 @@
|
||||
#include "register_types.h"
|
||||
|
||||
#include <gdextension_interface.h>
|
||||
#include <godot_cpp/core/class_db.hpp>
|
||||
#include <godot_cpp/core/defs.hpp>
|
||||
#include <godot_cpp/godot.hpp>
|
||||
|
||||
#include "cobor_terrain_engine.hpp"
|
||||
|
||||
using namespace godot;
|
||||
|
||||
void initialize_gdextension_types(ModuleInitializationLevel p_level)
|
||||
{
|
||||
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
|
||||
return;
|
||||
}
|
||||
GDREGISTER_CLASS(CoborTerrain::CoborTerrainEngine);
|
||||
}
|
||||
|
||||
void uninitialize_gdextension_types(ModuleInitializationLevel p_level) {
|
||||
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C"
|
||||
{
|
||||
// Initialization
|
||||
GDExtensionBool GDE_EXPORT cobor_terrain_library_init(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization)
|
||||
{
|
||||
GDExtensionBinding::InitObject init_obj(p_get_proc_address, p_library, r_initialization);
|
||||
init_obj.register_initializer(initialize_gdextension_types);
|
||||
init_obj.register_terminator(uninitialize_gdextension_types);
|
||||
init_obj.set_minimum_library_initialization_level(MODULE_INITIALIZATION_LEVEL_SCENE);
|
||||
|
||||
return init_obj.init();
|
||||
}
|
||||
}
|
||||
Binary file not shown.
52
extensions/cobor_terrain_extension/methods.py
Normal file
52
extensions/cobor_terrain_extension/methods.py
Normal file
@@ -0,0 +1,52 @@
|
||||
import os
|
||||
import sys
|
||||
from enum import Enum
|
||||
|
||||
# Colors are disabled in non-TTY environments such as pipes. This means
|
||||
# that if output is redirected to a file, it won't contain color codes.
|
||||
# Colors are always enabled on continuous integration.
|
||||
_colorize = bool(sys.stdout.isatty() or os.environ.get("CI"))
|
||||
|
||||
|
||||
class ANSI(Enum):
|
||||
"""
|
||||
Enum class for adding ansi colorcodes directly into strings.
|
||||
Automatically converts values to strings representing their
|
||||
internal value, or an empty string in a non-colorized scope.
|
||||
"""
|
||||
|
||||
RESET = "\x1b[0m"
|
||||
|
||||
BOLD = "\x1b[1m"
|
||||
ITALIC = "\x1b[3m"
|
||||
UNDERLINE = "\x1b[4m"
|
||||
STRIKETHROUGH = "\x1b[9m"
|
||||
REGULAR = "\x1b[22;23;24;29m"
|
||||
|
||||
BLACK = "\x1b[30m"
|
||||
RED = "\x1b[31m"
|
||||
GREEN = "\x1b[32m"
|
||||
YELLOW = "\x1b[33m"
|
||||
BLUE = "\x1b[34m"
|
||||
MAGENTA = "\x1b[35m"
|
||||
CYAN = "\x1b[36m"
|
||||
WHITE = "\x1b[37m"
|
||||
|
||||
PURPLE = "\x1b[38;5;93m"
|
||||
PINK = "\x1b[38;5;206m"
|
||||
ORANGE = "\x1b[38;5;214m"
|
||||
GRAY = "\x1b[38;5;244m"
|
||||
|
||||
def __str__(self) -> str:
|
||||
global _colorize
|
||||
return str(self.value) if _colorize else ""
|
||||
|
||||
|
||||
def print_warning(*values: object) -> None:
|
||||
"""Prints a warning message with formatting."""
|
||||
print(f"{ANSI.YELLOW}{ANSI.BOLD}WARNING:{ANSI.REGULAR}", *values, ANSI.RESET, file=sys.stderr)
|
||||
|
||||
|
||||
def print_error(*values: object) -> None:
|
||||
"""Prints an error message with formatting."""
|
||||
print(f"{ANSI.RED}{ANSI.BOLD}ERROR:{ANSI.REGULAR}", *values, ANSI.RESET, file=sys.stderr)
|
||||
BIN
extensions/cobor_vm_extension/.sconsign.dblite
Normal file
BIN
extensions/cobor_vm_extension/.sconsign.dblite
Normal file
Binary file not shown.
15
extensions/cobor_vm_extension/.vscode/c_cpp_properties.json
vendored
Normal file
15
extensions/cobor_vm_extension/.vscode/c_cpp_properties.json
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"includePath": [
|
||||
"${workspaceFolder}/**",
|
||||
"${workspaceFolder}/../godot-cpp/**"
|
||||
],
|
||||
"intelliSenseMode": "linux-gcc-x64",
|
||||
"compilerPath": "/usr/bin/gcc",
|
||||
"cStandard": "c17",
|
||||
"cppStandard": "gnu++17"
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
||||
61
extensions/cobor_vm_extension/.vscode/settings.json
vendored
Normal file
61
extensions/cobor_vm_extension/.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
{
|
||||
"files.associations": {
|
||||
"*.inc": "cpp",
|
||||
"array": "cpp",
|
||||
"atomic": "cpp",
|
||||
"bit": "cpp",
|
||||
"cctype": "cpp",
|
||||
"cerrno": "cpp",
|
||||
"climits": "cpp",
|
||||
"clocale": "cpp",
|
||||
"cmath": "cpp",
|
||||
"compare": "cpp",
|
||||
"concepts": "cpp",
|
||||
"condition_variable": "cpp",
|
||||
"cstdarg": "cpp",
|
||||
"cstddef": "cpp",
|
||||
"cstdint": "cpp",
|
||||
"cstdio": "cpp",
|
||||
"cstdlib": "cpp",
|
||||
"cstring": "cpp",
|
||||
"ctime": "cpp",
|
||||
"cwchar": "cpp",
|
||||
"cwctype": "cpp",
|
||||
"deque": "cpp",
|
||||
"list": "cpp",
|
||||
"set": "cpp",
|
||||
"string": "cpp",
|
||||
"unordered_map": "cpp",
|
||||
"vector": "cpp",
|
||||
"exception": "cpp",
|
||||
"algorithm": "cpp",
|
||||
"functional": "cpp",
|
||||
"iterator": "cpp",
|
||||
"memory": "cpp",
|
||||
"memory_resource": "cpp",
|
||||
"numeric": "cpp",
|
||||
"optional": "cpp",
|
||||
"random": "cpp",
|
||||
"ratio": "cpp",
|
||||
"string_view": "cpp",
|
||||
"system_error": "cpp",
|
||||
"tuple": "cpp",
|
||||
"type_traits": "cpp",
|
||||
"utility": "cpp",
|
||||
"initializer_list": "cpp",
|
||||
"iosfwd": "cpp",
|
||||
"iostream": "cpp",
|
||||
"istream": "cpp",
|
||||
"limits": "cpp",
|
||||
"mutex": "cpp",
|
||||
"new": "cpp",
|
||||
"numbers": "cpp",
|
||||
"ostream": "cpp",
|
||||
"semaphore": "cpp",
|
||||
"stdexcept": "cpp",
|
||||
"stop_token": "cpp",
|
||||
"streambuf": "cpp",
|
||||
"thread": "cpp",
|
||||
"typeinfo": "cpp"
|
||||
}
|
||||
}
|
||||
65
extensions/cobor_vm_extension/SConstruct
Normal file
65
extensions/cobor_vm_extension/SConstruct
Normal file
@@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env python
|
||||
import os
|
||||
import sys
|
||||
|
||||
from methods import print_error
|
||||
|
||||
|
||||
libname = "cobor_vm_extension"
|
||||
projectdir = "."
|
||||
|
||||
localEnv = Environment(tools=["default"], PLATFORM="")
|
||||
|
||||
# Build profiles can be used to decrease compile times.
|
||||
# You can either specify "disabled_classes", OR
|
||||
# explicitly specify "enabled_classes" which disables all other classes.
|
||||
# Modify the example file as needed and uncomment the line below or
|
||||
# manually specify the build_profile parameter when running SCons.
|
||||
|
||||
# localEnv["build_profile"] = "build_profile.json"
|
||||
|
||||
customs = ["custom.py"]
|
||||
customs = [os.path.abspath(path) for path in customs]
|
||||
|
||||
opts = Variables(customs, ARGUMENTS)
|
||||
opts.Update(localEnv)
|
||||
|
||||
Help(opts.GenerateHelpText(localEnv))
|
||||
|
||||
env = localEnv.Clone()
|
||||
|
||||
if not (os.path.isdir("../godot-cpp") and os.listdir("../godot-cpp")):
|
||||
print_error("""godot-cpp is not available within this folder, as Git submodules haven't been initialized.
|
||||
Run the following command to download godot-cpp:
|
||||
|
||||
git submodule update --init --recursive""")
|
||||
sys.exit(1)
|
||||
|
||||
env = SConscript("../godot-cpp/SConstruct", {"env": env, "customs": customs})
|
||||
|
||||
env.Append(CPPPATH=["cobor_vm/include/"])
|
||||
env.Append(CPPPATH=["cobor_vm/src/"])
|
||||
sources = Glob("cobor_vm/src/*.cpp")
|
||||
|
||||
if env["target"] in ["editor", "template_debug"]:
|
||||
try:
|
||||
doc_data = env.GodotCPPDocData("cobor_vm/src/gen/doc_data.gen.cpp", source=Glob("doc_classes/*.xml"))
|
||||
sources.append(doc_data)
|
||||
except AttributeError:
|
||||
print("Not including class reference as we're targeting a pre-4.3 baseline.")
|
||||
|
||||
# .dev doesn't inhibit compatibility, so we don't need to key it.
|
||||
# .universal just means "compatible with all relevant arches" so we don't need to key it.
|
||||
suffix = env['suffix'].replace(".dev", "").replace(".universal", "")
|
||||
|
||||
lib_filename = "{}{}{}{}".format(env.subst('$SHLIBPREFIX'), libname, suffix, env.subst('$SHLIBSUFFIX'))
|
||||
|
||||
library = env.SharedLibrary(
|
||||
"bin/{}/{}".format(env['platform'], lib_filename),
|
||||
source=sources,
|
||||
)
|
||||
|
||||
# copy = env.Install("{}/bin/{}/".format(projectdir, env["platform"]), library)
|
||||
|
||||
default_args = [library]
|
||||
Default(*default_args)
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
10
extensions/cobor_vm_extension/cobor_vm.gdextension
Normal file
10
extensions/cobor_vm_extension/cobor_vm.gdextension
Normal file
@@ -0,0 +1,10 @@
|
||||
[configuration]
|
||||
|
||||
entry_symbol = "cobor_vm_library_init"
|
||||
compatibility_minimum = "4.1"
|
||||
|
||||
[libraries]
|
||||
; Relative paths ensure that our GDExtension can be placed anywhere in the project directory.
|
||||
|
||||
linux.x86_64.debug = "./bin/linux/libcobor_vm_extension.linux.template_debug.x86_64.so"
|
||||
linux.x86_64.release = "./bin/linux/libcobor_vm_extension.linux.template_release.x86_64.so"
|
||||
1
extensions/cobor_vm_extension/cobor_vm.gdextension.uid
Normal file
1
extensions/cobor_vm_extension/cobor_vm.gdextension.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://ckjbrjvokj8nh
|
||||
0
extensions/cobor_vm_extension/cobor_vm/.gdignore
Normal file
0
extensions/cobor_vm_extension/cobor_vm/.gdignore
Normal file
@@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
#include "constants.hpp"
|
||||
#include "godot_cpp/classes/ref_counted.hpp"
|
||||
|
||||
namespace CoborVM
|
||||
{
|
||||
class CoborVirtualMachine : public godot::RefCounted
|
||||
{
|
||||
GDCLASS(CoborVirtualMachine, godot::RefCounted)
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
private:
|
||||
std::vector<ExecutableStep> program;
|
||||
std::vector<int32_t> register_memory;
|
||||
|
||||
public:
|
||||
CoborVirtualMachine() = default;
|
||||
~CoborVirtualMachine() override = default;
|
||||
|
||||
godot::PackedStringArray parse_source_code(godot::String source_code);
|
||||
godot::String set_registers(int size, godot::PackedInt32Array preloaded_values);
|
||||
godot::PackedInt32Array get_registers();
|
||||
int get_program_counter();
|
||||
godot::String run_step();
|
||||
godot::String run_all();
|
||||
|
||||
private:
|
||||
// Execution
|
||||
godot::String run_executable_step(ExecutableStep step);
|
||||
// Parsing
|
||||
bool string_to_instruction(godot::String command_string, Instruction &outInstruction);
|
||||
bool instruction_to_executable_step(Instruction instruction, godot::PackedStringArray line, ExecutableStep &outExecutableStep);
|
||||
bool validate_and_parse_pointer(const godot::String &arg, int &outValue);
|
||||
bool validate_and_parse_literal(const godot::String &arg, int &outValue);
|
||||
};
|
||||
}
|
||||
96
extensions/cobor_vm_extension/cobor_vm/include/constants.hpp
Normal file
96
extensions/cobor_vm_extension/cobor_vm/include/constants.hpp
Normal file
@@ -0,0 +1,96 @@
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace CoborVM
|
||||
{
|
||||
enum Instruction
|
||||
{
|
||||
EMPTY,
|
||||
|
||||
SET,
|
||||
CLR,
|
||||
CPY,
|
||||
SWP,
|
||||
|
||||
ADD,
|
||||
SUB,
|
||||
MUL,
|
||||
DIV,
|
||||
|
||||
SKIP,
|
||||
JMP,
|
||||
JMPTO,
|
||||
|
||||
EQL,
|
||||
BIGR,
|
||||
SMLR,
|
||||
ZERO,
|
||||
};
|
||||
|
||||
struct ExecutableStep
|
||||
{
|
||||
Instruction instruction = Instruction::EMPTY;
|
||||
int arg1;
|
||||
int arg2;
|
||||
int arg3;
|
||||
|
||||
int lineNumber;
|
||||
};
|
||||
|
||||
// Map from string to instruction
|
||||
const std::unordered_map<std::string, Instruction> stringToInstructionMap = {
|
||||
{"SET", SET},
|
||||
{"CLR", CLR},
|
||||
{"CPY", CPY},
|
||||
{"SWP", SWP},
|
||||
{"ADD", ADD},
|
||||
{"SUB", SUB},
|
||||
{"MUL", MUL},
|
||||
{"DIV", DIV},
|
||||
{"SKIP", SKIP},
|
||||
{"JMP", JMP},
|
||||
{"JMPTO", JMPTO},
|
||||
{"EQL", EQL},
|
||||
{"BIGR", BIGR},
|
||||
{"SMLR", SMLR},
|
||||
{"ZERO", ZERO}};
|
||||
|
||||
// Map from instruction to string
|
||||
const std::unordered_map<Instruction, std::string> InstructionToStringMap = {
|
||||
{SET, "SET"},
|
||||
{CLR, "CLR"},
|
||||
{CPY, "CPY"},
|
||||
{SWP, "SWP"},
|
||||
{ADD, "ADD"},
|
||||
{SUB, "SUB"},
|
||||
{MUL, "MUL"},
|
||||
{DIV, "DIV"},
|
||||
{SKIP, "SKIP"},
|
||||
{JMP, "JMP"},
|
||||
{JMPTO, "JMPTO"},
|
||||
{EQL, "EQL"},
|
||||
{BIGR, "BIGR"},
|
||||
{SMLR, "SMLR"},
|
||||
{ZERO, "ZERO"}};
|
||||
|
||||
// Define the expected argument types for each instruction (true = pointer, false = literal)
|
||||
const std::unordered_map<Instruction, std::vector<bool>> instructionPatterns = {
|
||||
{Instruction::SKIP, {}}, // No arguments
|
||||
{Instruction::EMPTY, {}},
|
||||
{Instruction::JMP, {false}}, // One literal argument
|
||||
{Instruction::JMPTO, {false}},
|
||||
{Instruction::CLR, {true}}, // One pointer argument
|
||||
{Instruction::ZERO, {true}},
|
||||
{Instruction::SET, {false, true}}, // One literal and one pointer argument
|
||||
{Instruction::CPY, {true, true}}, // Two pointer arguments
|
||||
{Instruction::SWP, {true, true}},
|
||||
{Instruction::EQL, {true, true}},
|
||||
{Instruction::BIGR, {true, true}},
|
||||
{Instruction::SMLR, {true, true}},
|
||||
{Instruction::ADD, {true, true, true}}, // Three pointer arguments
|
||||
{Instruction::SUB, {true, true, true}},
|
||||
{Instruction::MUL, {true, true, true}},
|
||||
{Instruction::DIV, {true, true, true}},
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#ifndef COBOR_VM_REGISTER_TYPES_H
|
||||
#define COBOR_VM_REGISTER_TYPES_H
|
||||
|
||||
void initialize_gdextension_types();
|
||||
void uninitialize_gdextension_types();
|
||||
|
||||
#endif // COBOR_VM_REGISTER_TYPES_H
|
||||
@@ -0,0 +1,358 @@
|
||||
#include "cobor_virtual_machine.hpp"
|
||||
|
||||
using namespace CoborVM;
|
||||
|
||||
void CoborVM::CoborVirtualMachine::_bind_methods()
|
||||
{
|
||||
godot::ClassDB::bind_method(godot::D_METHOD("parse_source_code", "source_code"), &CoborVirtualMachine::parse_source_code);
|
||||
godot::ClassDB::bind_method(godot::D_METHOD("set_registers", "size", "preloaded_values"), &CoborVirtualMachine::set_registers);
|
||||
godot::ClassDB::bind_method(godot::D_METHOD("get_registers"), &CoborVirtualMachine::get_registers);
|
||||
godot::ClassDB::bind_method(godot::D_METHOD("get_program_counter"), &CoborVirtualMachine::get_program_counter);
|
||||
godot::ClassDB::bind_method(godot::D_METHOD("run_step"), &CoborVirtualMachine::run_step);
|
||||
godot::ClassDB::bind_method(godot::D_METHOD("run_all"), &CoborVirtualMachine::run_all);
|
||||
}
|
||||
|
||||
godot::PackedStringArray CoborVM::CoborVirtualMachine::parse_source_code(godot::String source_code)
|
||||
{
|
||||
godot::PackedStringArray parseFaults;
|
||||
program.clear();
|
||||
|
||||
source_code = source_code.to_upper();
|
||||
auto lines = source_code.split("\n");
|
||||
int lineNumber = 0;
|
||||
for (auto &line : lines)
|
||||
{
|
||||
lineNumber++;
|
||||
ExecutableStep step;
|
||||
step.instruction = EMPTY;
|
||||
step.lineNumber = lineNumber;
|
||||
|
||||
line = line.strip_edges();
|
||||
if (!line.is_empty())
|
||||
{
|
||||
auto words = line.split(" ", false);
|
||||
Instruction instruction;
|
||||
if (!string_to_instruction(words[0], instruction))
|
||||
{
|
||||
parseFaults.append(godot::String("Error: Invalid instruction at line ") +
|
||||
godot::String::num_int64(lineNumber) +
|
||||
godot::String(": {") + line + godot::String("}"));
|
||||
continue;
|
||||
}
|
||||
if (!instruction_to_executable_step(instruction, words, step))
|
||||
{
|
||||
parseFaults.append(godot::String("Error: Invalid arguments at line ") +
|
||||
godot::String::num_int64(lineNumber) +
|
||||
godot::String(": {") + line + godot::String("}"));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
program.emplace_back(step);
|
||||
}
|
||||
|
||||
return parseFaults;
|
||||
}
|
||||
|
||||
godot::String CoborVM::CoborVirtualMachine::set_registers(int size, godot::PackedInt32Array preloaded_values)
|
||||
{
|
||||
if (size <= 0)
|
||||
return godot::String("Size must be one or higher");
|
||||
register_memory = std::vector<int32_t>(size);
|
||||
int i = 0;
|
||||
for (int value : preloaded_values)
|
||||
{
|
||||
if (i >= size)
|
||||
break;
|
||||
register_memory[i] = value;
|
||||
i++;
|
||||
}
|
||||
return godot::String();
|
||||
}
|
||||
|
||||
godot::PackedInt32Array CoborVM::CoborVirtualMachine::get_registers()
|
||||
{
|
||||
godot::PackedInt32Array ret;
|
||||
for (int32_t value : register_memory)
|
||||
{
|
||||
ret.append(value);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int CoborVM::CoborVirtualMachine::get_program_counter()
|
||||
{
|
||||
return register_memory[0];
|
||||
}
|
||||
|
||||
godot::String CoborVM::CoborVirtualMachine::run_step()
|
||||
{
|
||||
if (program.empty())
|
||||
return godot::String("No program is compiled to run.");
|
||||
if (register_memory.empty())
|
||||
return godot::String("Registers are not set.");
|
||||
|
||||
int program_counter = register_memory[0];
|
||||
if (program_counter < 0 || program_counter >= program.size())
|
||||
return godot::String("Program counter pointing outside program scope: ") +
|
||||
godot::String::num_int64(program_counter);
|
||||
|
||||
ExecutableStep step = program[program_counter];
|
||||
auto err = run_executable_step(step);
|
||||
if (!err.is_empty())
|
||||
{
|
||||
return godot::String("Execution failed at line: ") +
|
||||
godot::String::num_int64(step.lineNumber) +
|
||||
godot::String(" with error: ") +
|
||||
err;
|
||||
}
|
||||
|
||||
register_memory[0]++;
|
||||
return godot::String();
|
||||
}
|
||||
|
||||
godot::String CoborVM::CoborVirtualMachine::run_all()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
int program_counter = register_memory[0];
|
||||
if (program.size() <= program_counter)
|
||||
break;
|
||||
auto result = run_step();
|
||||
if (!result.is_empty())
|
||||
return result;
|
||||
}
|
||||
return godot::String();
|
||||
}
|
||||
|
||||
godot::String CoborVM::CoborVirtualMachine::run_executable_step(ExecutableStep step)
|
||||
{
|
||||
godot::String error_message;
|
||||
|
||||
auto check_register = [this, &error_message](int64_t reg) -> bool
|
||||
{
|
||||
if (reg >= register_memory.size())
|
||||
{
|
||||
error_message = godot::String("Pointing outside register memory at /") + godot::String::num_int64(reg);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
switch (step.instruction)
|
||||
{
|
||||
case EMPTY:
|
||||
break;
|
||||
|
||||
case SET:
|
||||
{
|
||||
if (!check_register(step.arg2))
|
||||
return error_message;
|
||||
register_memory[step.arg2] = step.arg1;
|
||||
break;
|
||||
}
|
||||
|
||||
case CLR:
|
||||
{
|
||||
if (!check_register(step.arg1))
|
||||
return error_message;
|
||||
register_memory[step.arg1] = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case CPY:
|
||||
{
|
||||
if (!check_register(step.arg1) || !check_register(step.arg2))
|
||||
return error_message;
|
||||
register_memory[step.arg2] = register_memory[step.arg1];
|
||||
break;
|
||||
}
|
||||
|
||||
case SWP:
|
||||
{
|
||||
if (!check_register(step.arg1) || !check_register(step.arg2))
|
||||
return error_message;
|
||||
std::swap(register_memory[step.arg1], register_memory[step.arg2]);
|
||||
break;
|
||||
}
|
||||
|
||||
case ADD:
|
||||
{
|
||||
if (!check_register(step.arg1) || !check_register(step.arg2) || !check_register(step.arg3))
|
||||
return error_message;
|
||||
register_memory[step.arg3] = register_memory[step.arg1] + register_memory[step.arg2];
|
||||
break;
|
||||
}
|
||||
|
||||
case SUB:
|
||||
{
|
||||
if (!check_register(step.arg1) || !check_register(step.arg2) || !check_register(step.arg3))
|
||||
return error_message;
|
||||
register_memory[step.arg3] = register_memory[step.arg1] - register_memory[step.arg2];
|
||||
break;
|
||||
}
|
||||
|
||||
case MUL:
|
||||
{
|
||||
if (!check_register(step.arg1) || !check_register(step.arg2) || !check_register(step.arg3))
|
||||
return error_message;
|
||||
register_memory[step.arg3] = register_memory[step.arg1] * register_memory[step.arg2];
|
||||
break;
|
||||
}
|
||||
|
||||
case DIV:
|
||||
{
|
||||
if (!check_register(step.arg1) || !check_register(step.arg2) || !check_register(step.arg3))
|
||||
return error_message;
|
||||
if (register_memory[step.arg2] == 0)
|
||||
{
|
||||
return godot::String("Dividing by zero! Check register: ") + godot::String::num_int64(step.arg2);
|
||||
}
|
||||
register_memory[step.arg3] = register_memory[step.arg1] / register_memory[step.arg2];
|
||||
break;
|
||||
}
|
||||
|
||||
case SKIP:
|
||||
{
|
||||
register_memory[0]++;
|
||||
break;
|
||||
}
|
||||
|
||||
case JMP:
|
||||
{
|
||||
register_memory[0] += step.arg1;
|
||||
break;
|
||||
}
|
||||
|
||||
case JMPTO:
|
||||
{
|
||||
register_memory[0] = step.arg1;
|
||||
break;
|
||||
}
|
||||
|
||||
case EQL:
|
||||
{
|
||||
if (!check_register(step.arg1) || !check_register(step.arg2))
|
||||
return error_message;
|
||||
if (register_memory[step.arg1] == register_memory[step.arg2])
|
||||
register_memory[0]++;
|
||||
break;
|
||||
}
|
||||
|
||||
case BIGR:
|
||||
{
|
||||
if (!check_register(step.arg1) || !check_register(step.arg2))
|
||||
return error_message;
|
||||
if (register_memory[step.arg1] < register_memory[step.arg2])
|
||||
register_memory[0]++;
|
||||
break;
|
||||
}
|
||||
|
||||
case SMLR:
|
||||
{
|
||||
if (!check_register(step.arg1) || !check_register(step.arg2))
|
||||
return error_message;
|
||||
if (register_memory[step.arg1] > register_memory[step.arg2])
|
||||
register_memory[0]++;
|
||||
break;
|
||||
}
|
||||
|
||||
case ZERO:
|
||||
{
|
||||
if (!check_register(step.arg1))
|
||||
return error_message;
|
||||
if (register_memory[step.arg1] == 0)
|
||||
register_memory[0]++;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return godot::String("Unknown instruction! This is not on you.");
|
||||
}
|
||||
return godot::String();
|
||||
}
|
||||
|
||||
bool CoborVM::CoborVirtualMachine::string_to_instruction(godot::String command_string, Instruction &outInstruction)
|
||||
{
|
||||
std::string cmd = command_string.utf8().get_data();
|
||||
|
||||
auto it = stringToInstructionMap.find(cmd);
|
||||
if (it != stringToInstructionMap.end())
|
||||
{
|
||||
outInstruction = it->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CoborVM::CoborVirtualMachine::instruction_to_executable_step(Instruction instruction, godot::PackedStringArray line, ExecutableStep &outExecutableStep)
|
||||
{
|
||||
outExecutableStep.instruction = instruction;
|
||||
|
||||
auto it = instructionPatterns.find(instruction);
|
||||
if (it == instructionPatterns.end())
|
||||
{
|
||||
return false; // Unknown instruction
|
||||
}
|
||||
|
||||
const std::vector<bool> &pattern = it->second;
|
||||
if (line.size() != pattern.size() + 1)
|
||||
{ // +1 for the instruction itself
|
||||
return false; // Incorrect number of arguments
|
||||
}
|
||||
|
||||
int arg1 = 0, arg2 = 0, arg3 = 0;
|
||||
for (size_t i = 0; i < pattern.size(); ++i)
|
||||
{
|
||||
bool isPointer = pattern[i];
|
||||
godot::String arg = line[i + 1]; // +1 to skip the instruction
|
||||
|
||||
if (isPointer)
|
||||
{
|
||||
if (!validate_and_parse_pointer(arg, (i == 0) ? arg1 : (i == 1) ? arg2
|
||||
: arg3))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!validate_and_parse_literal(arg, (i == 0) ? arg1 : (i == 1) ? arg2
|
||||
: arg3))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
outExecutableStep.arg1 = arg1;
|
||||
outExecutableStep.arg2 = arg2;
|
||||
outExecutableStep.arg3 = arg3;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CoborVM::CoborVirtualMachine::validate_and_parse_pointer(const godot::String &arg, int &outValue)
|
||||
{
|
||||
if (!arg.begins_with("/"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
godot::String trimmedArg = arg.trim_prefix("/");
|
||||
if (!trimmedArg.is_valid_int())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
outValue = trimmedArg.to_int();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CoborVM::CoborVirtualMachine::validate_and_parse_literal(const godot::String &arg, int &outValue)
|
||||
{
|
||||
if (!arg.is_valid_int())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
outValue = arg.to_int();
|
||||
return true;
|
||||
}
|
||||
Binary file not shown.
BIN
extensions/cobor_vm_extension/cobor_vm/src/example_class.os
Normal file
BIN
extensions/cobor_vm_extension/cobor_vm/src/example_class.os
Normal file
Binary file not shown.
@@ -0,0 +1,20 @@
|
||||
/* THIS FILE IS GENERATED DO NOT EDIT */
|
||||
|
||||
#include <godot_cpp/godot.hpp>
|
||||
|
||||
static const char *_doc_data_hash = "626471190447146946";
|
||||
static const int _doc_data_uncompressed_size = 0;
|
||||
static const int _doc_data_compressed_size = 8;
|
||||
static const unsigned char _doc_data_compressed[] = {
|
||||
120,
|
||||
218,
|
||||
3,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
};
|
||||
|
||||
static godot::internal::DocDataRegistration _doc_data_registration(_doc_data_hash, _doc_data_uncompressed_size, _doc_data_compressed_size, _doc_data_compressed);
|
||||
|
||||
BIN
extensions/cobor_vm_extension/cobor_vm/src/gen/doc_data.gen.os
Normal file
BIN
extensions/cobor_vm_extension/cobor_vm/src/gen/doc_data.gen.os
Normal file
Binary file not shown.
@@ -0,0 +1,38 @@
|
||||
#include "register_types.h"
|
||||
|
||||
#include <gdextension_interface.h>
|
||||
#include <godot_cpp/core/class_db.hpp>
|
||||
#include <godot_cpp/core/defs.hpp>
|
||||
#include <godot_cpp/godot.hpp>
|
||||
|
||||
#include "cobor_virtual_machine.hpp"
|
||||
|
||||
using namespace godot;
|
||||
|
||||
void initialize_gdextension_types(ModuleInitializationLevel p_level)
|
||||
{
|
||||
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
|
||||
return;
|
||||
}
|
||||
GDREGISTER_CLASS(CoborVM::CoborVirtualMachine);
|
||||
}
|
||||
|
||||
void uninitialize_gdextension_types(ModuleInitializationLevel p_level) {
|
||||
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C"
|
||||
{
|
||||
// Initialization
|
||||
GDExtensionBool GDE_EXPORT cobor_vm_library_init(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization)
|
||||
{
|
||||
GDExtensionBinding::InitObject init_obj(p_get_proc_address, p_library, r_initialization);
|
||||
init_obj.register_initializer(initialize_gdextension_types);
|
||||
init_obj.register_terminator(uninitialize_gdextension_types);
|
||||
init_obj.set_minimum_library_initialization_level(MODULE_INITIALIZATION_LEVEL_SCENE);
|
||||
|
||||
return init_obj.init();
|
||||
}
|
||||
}
|
||||
BIN
extensions/cobor_vm_extension/cobor_vm/src/register_types.os
Normal file
BIN
extensions/cobor_vm_extension/cobor_vm/src/register_types.os
Normal file
Binary file not shown.
1
extensions/cobor_vm_extension/example.gdextension.uid
Normal file
1
extensions/cobor_vm_extension/example.gdextension.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://dku1li0a05p5h
|
||||
52
extensions/cobor_vm_extension/methods.py
Normal file
52
extensions/cobor_vm_extension/methods.py
Normal file
@@ -0,0 +1,52 @@
|
||||
import os
|
||||
import sys
|
||||
from enum import Enum
|
||||
|
||||
# Colors are disabled in non-TTY environments such as pipes. This means
|
||||
# that if output is redirected to a file, it won't contain color codes.
|
||||
# Colors are always enabled on continuous integration.
|
||||
_colorize = bool(sys.stdout.isatty() or os.environ.get("CI"))
|
||||
|
||||
|
||||
class ANSI(Enum):
|
||||
"""
|
||||
Enum class for adding ansi colorcodes directly into strings.
|
||||
Automatically converts values to strings representing their
|
||||
internal value, or an empty string in a non-colorized scope.
|
||||
"""
|
||||
|
||||
RESET = "\x1b[0m"
|
||||
|
||||
BOLD = "\x1b[1m"
|
||||
ITALIC = "\x1b[3m"
|
||||
UNDERLINE = "\x1b[4m"
|
||||
STRIKETHROUGH = "\x1b[9m"
|
||||
REGULAR = "\x1b[22;23;24;29m"
|
||||
|
||||
BLACK = "\x1b[30m"
|
||||
RED = "\x1b[31m"
|
||||
GREEN = "\x1b[32m"
|
||||
YELLOW = "\x1b[33m"
|
||||
BLUE = "\x1b[34m"
|
||||
MAGENTA = "\x1b[35m"
|
||||
CYAN = "\x1b[36m"
|
||||
WHITE = "\x1b[37m"
|
||||
|
||||
PURPLE = "\x1b[38;5;93m"
|
||||
PINK = "\x1b[38;5;206m"
|
||||
ORANGE = "\x1b[38;5;214m"
|
||||
GRAY = "\x1b[38;5;244m"
|
||||
|
||||
def __str__(self) -> str:
|
||||
global _colorize
|
||||
return str(self.value) if _colorize else ""
|
||||
|
||||
|
||||
def print_warning(*values: object) -> None:
|
||||
"""Prints a warning message with formatting."""
|
||||
print(f"{ANSI.YELLOW}{ANSI.BOLD}WARNING:{ANSI.REGULAR}", *values, ANSI.RESET, file=sys.stderr)
|
||||
|
||||
|
||||
def print_error(*values: object) -> None:
|
||||
"""Prints an error message with formatting."""
|
||||
print(f"{ANSI.RED}{ANSI.BOLD}ERROR:{ANSI.REGULAR}", *values, ANSI.RESET, file=sys.stderr)
|
||||
1
extensions/godot-cpp
Submodule
1
extensions/godot-cpp
Submodule
Submodule extensions/godot-cpp added at d502d8e8aa
Reference in New Issue
Block a user