Started a Cobor Virtual Machine implementation for running the code.
This commit is contained in:
0
cobor_vm_extension/cobor_vm/.gdignore
Normal file
0
cobor_vm_extension/cobor_vm/.gdignore
Normal file
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include "godot_cpp/classes/ref_counted.hpp"
|
||||
|
||||
namespace CoborVM
|
||||
{
|
||||
class CoborVirtualMachine : public godot::RefCounted
|
||||
{
|
||||
GDCLASS(CoborVirtualMachine, godot::RefCounted)
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
CoborVirtualMachine() = default;
|
||||
~CoborVirtualMachine() override = default;
|
||||
|
||||
godot::PackedStringArray parse_source_code(godot::String source_code);
|
||||
};
|
||||
}
|
||||
24
cobor_vm_extension/cobor_vm/include/example_class.hpp
Normal file
24
cobor_vm_extension/cobor_vm/include/example_class.hpp
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "godot_cpp/classes/ref_counted.hpp"
|
||||
#include "godot_cpp/classes/wrapped.hpp"
|
||||
#include "godot_cpp/variant/variant.hpp"
|
||||
|
||||
using namespace godot;
|
||||
|
||||
namespace CoborVM
|
||||
{
|
||||
class ExampleClass : public RefCounted
|
||||
{
|
||||
GDCLASS(ExampleClass, RefCounted)
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
ExampleClass() = default;
|
||||
~ExampleClass() override = default;
|
||||
|
||||
void print_type(const Variant &p_variant) const;
|
||||
};
|
||||
}
|
||||
7
cobor_vm_extension/cobor_vm/include/register_types.h
Normal file
7
cobor_vm_extension/cobor_vm/include/register_types.h
Normal file
@@ -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
|
||||
224
cobor_vm_extension/cobor_vm/src/cobor_virtual_machine.cpp
Normal file
224
cobor_vm_extension/cobor_vm/src/cobor_virtual_machine.cpp
Normal file
@@ -0,0 +1,224 @@
|
||||
#include "cobor_virtual_machine.hpp"
|
||||
|
||||
enum Instruction
|
||||
{
|
||||
ERR,
|
||||
|
||||
SET,
|
||||
CLR,
|
||||
CPY,
|
||||
SWP,
|
||||
|
||||
ADD,
|
||||
SUB,
|
||||
MUL,
|
||||
DIV,
|
||||
|
||||
SKIP,
|
||||
JMP,
|
||||
JMPTO,
|
||||
|
||||
EQL,
|
||||
BIGR,
|
||||
SMLR,
|
||||
ZERO,
|
||||
};
|
||||
|
||||
struct ExecutableStep
|
||||
{
|
||||
Instruction instruction = Instruction::ERR;
|
||||
int arg1;
|
||||
int arg2;
|
||||
int arg3;
|
||||
|
||||
int lineNumber;
|
||||
};
|
||||
|
||||
void CoborVM::CoborVirtualMachine::_bind_methods()
|
||||
{
|
||||
godot::ClassDB::bind_method(godot::D_METHOD("parse_source_code", "source_code"), &CoborVirtualMachine::parse_source_code);
|
||||
}
|
||||
|
||||
Instruction stringToInstruction(godot::String command_string);
|
||||
ExecutableStep InstructionToExecutableStep(Instruction Instruction, godot::PackedStringArray line);
|
||||
|
||||
godot::PackedStringArray CoborVM::CoborVirtualMachine::parse_source_code(godot::String source_code)
|
||||
{
|
||||
godot::PackedStringArray parseFaults;
|
||||
|
||||
source_code = source_code.to_upper();
|
||||
auto lines = source_code.split("\n");
|
||||
int lineNumber = 0;
|
||||
for (auto &line : lines)
|
||||
{
|
||||
line = line.strip_edges();
|
||||
auto words = line.split(" ", false);
|
||||
Instruction command = stringToInstruction(words[0]);
|
||||
if (command == ERR)
|
||||
{
|
||||
parseFaults.append(godot::String("Error: Invalid command at line ") +
|
||||
godot::String::num_int64(lineNumber) +
|
||||
godot::String(": {") + line + godot::String("}"));
|
||||
continue;
|
||||
}
|
||||
|
||||
lineNumber++;
|
||||
}
|
||||
|
||||
return parseFaults;
|
||||
}
|
||||
|
||||
Instruction stringToInstruction(godot::String command_string)
|
||||
{
|
||||
std::string cmd = command_string.utf8().get_data();
|
||||
if (cmd == "SET")
|
||||
return SET;
|
||||
if (cmd == "CLR")
|
||||
return CLR;
|
||||
if (cmd == "MV")
|
||||
return CPY;
|
||||
if (cmd == "SWP")
|
||||
return SWP;
|
||||
if (cmd == "ADD")
|
||||
return ADD;
|
||||
if (cmd == "SUB")
|
||||
return SUB;
|
||||
if (cmd == "MUL")
|
||||
return MUL;
|
||||
if (cmd == "DIV")
|
||||
return DIV;
|
||||
if (cmd == "SKIP")
|
||||
return SKIP;
|
||||
if (cmd == "JMP")
|
||||
return JMP;
|
||||
if (cmd == "JMPTO")
|
||||
return JMPTO;
|
||||
if (cmd == "EQL")
|
||||
return EQL;
|
||||
if (cmd == "BIGR")
|
||||
return BIGR;
|
||||
if (cmd == "SMLR")
|
||||
return SMLR;
|
||||
if (cmd == "ZERO")
|
||||
return ZERO;
|
||||
return ERR;
|
||||
}
|
||||
|
||||
ExecutableStep InstructionToExecutableStep(Instruction instruction, godot::PackedStringArray line, int lineNumber)
|
||||
{
|
||||
ExecutableStep executableStep;
|
||||
executableStep.lineNumber = lineNumber;
|
||||
|
||||
godot::String arg1 = "0", arg2 = "0", arg3 = "0";
|
||||
|
||||
switch (instruction)
|
||||
{
|
||||
// Instructions with no arguments
|
||||
case Instruction::SKIP:
|
||||
if (line.size() != 1)
|
||||
return executableStep;
|
||||
break;
|
||||
|
||||
// Instructions with one literal argument
|
||||
case Instruction::JMP:
|
||||
case Instruction::JMPTO:
|
||||
if (line.size() != 2)
|
||||
return executableStep;
|
||||
arg1 = line[1];
|
||||
if (!arg1.is_valid_int())
|
||||
return executableStep;
|
||||
break;
|
||||
|
||||
// Instructions with one pointer argument
|
||||
case Instruction::CLR:
|
||||
case Instruction::ZERO:
|
||||
if (line.size() != 2)
|
||||
return executableStep;
|
||||
|
||||
arg1 = line[1];
|
||||
if (!arg1.begins_with("/"))
|
||||
return executableStep;
|
||||
arg1 = arg1.trim_prefix("/");
|
||||
if (!arg1.is_valid_int())
|
||||
return executableStep;
|
||||
break;
|
||||
|
||||
// Instructions with one literal argument and one pointer argument
|
||||
case Instruction::SET:
|
||||
if (line.size() != 3)
|
||||
return executableStep;
|
||||
|
||||
arg1 = line[1];
|
||||
if (!arg1.is_valid_int())
|
||||
return executableStep;
|
||||
arg2 = line[2];
|
||||
if (!arg2.begins_with("/"))
|
||||
return executableStep;
|
||||
arg2 = arg2.trim_prefix("/");
|
||||
if (!arg2.is_valid_int())
|
||||
return executableStep;
|
||||
break;
|
||||
|
||||
// Instructions with two pointer argument
|
||||
case Instruction::CPY:
|
||||
case Instruction::SWP:
|
||||
case Instruction::EQL:
|
||||
case Instruction::BIGR:
|
||||
case Instruction::SMLR:
|
||||
if (line.size() != 3)
|
||||
return executableStep;
|
||||
|
||||
arg1 = line[1];
|
||||
if (!arg1.begins_with("/"))
|
||||
return executableStep;
|
||||
arg1 = arg1.trim_prefix("/");
|
||||
if (!arg1.is_valid_int())
|
||||
return executableStep;
|
||||
arg2 = line[2];
|
||||
if (!arg2.begins_with("/"))
|
||||
return executableStep;
|
||||
arg2 = arg2.trim_prefix("/");
|
||||
if (!arg2.is_valid_int())
|
||||
return executableStep;
|
||||
break;
|
||||
|
||||
// Instructions with three pointer argument
|
||||
case Instruction::ADD:
|
||||
case Instruction::SUB:
|
||||
case Instruction::MUL:
|
||||
case Instruction::DIV:
|
||||
if (line.size() != 4)
|
||||
return executableStep;
|
||||
|
||||
arg1 = line[1];
|
||||
if (!arg1.begins_with("/"))
|
||||
return executableStep;
|
||||
arg1 = arg1.trim_prefix("/");
|
||||
if (!arg1.is_valid_int())
|
||||
return executableStep;
|
||||
arg2 = line[2];
|
||||
if (!arg2.begins_with("/"))
|
||||
return executableStep;
|
||||
arg2 = arg2.trim_prefix("/");
|
||||
if (!arg2.is_valid_int())
|
||||
return executableStep;
|
||||
arg3 = line[3];
|
||||
if (!arg3.begins_with("/"))
|
||||
return executableStep;
|
||||
arg3 = arg3.trim_prefix("/");
|
||||
if (!arg3.is_valid_int())
|
||||
return executableStep;
|
||||
break;
|
||||
|
||||
default:
|
||||
return executableStep;
|
||||
break;
|
||||
}
|
||||
executableStep.instruction = instruction;
|
||||
executableStep.arg1 = arg1.to_int();
|
||||
executableStep.arg2 = arg2.to_int();
|
||||
executableStep.arg3 = arg3.to_int();
|
||||
executableStep.lineNumber = lineNumber;
|
||||
return executableStep;
|
||||
}
|
||||
|
||||
BIN
cobor_vm_extension/cobor_vm/src/cobor_virtual_machine.os
Normal file
BIN
cobor_vm_extension/cobor_vm/src/cobor_virtual_machine.os
Normal file
Binary file not shown.
9
cobor_vm_extension/cobor_vm/src/example_class.cpp
Normal file
9
cobor_vm_extension/cobor_vm/src/example_class.cpp
Normal file
@@ -0,0 +1,9 @@
|
||||
#include "example_class.hpp"
|
||||
|
||||
void CoborVM::ExampleClass::_bind_methods() {
|
||||
godot::ClassDB::bind_method(D_METHOD("print_type", "variant"), &ExampleClass::print_type);
|
||||
}
|
||||
|
||||
void CoborVM::ExampleClass::print_type(const Variant &p_variant) const {
|
||||
print_line(vformat("Type: %d", p_variant.get_type()));
|
||||
}
|
||||
BIN
cobor_vm_extension/cobor_vm/src/example_class.os
Normal file
BIN
cobor_vm_extension/cobor_vm/src/example_class.os
Normal file
Binary file not shown.
20
cobor_vm_extension/cobor_vm/src/gen/doc_data.gen.cpp
Normal file
20
cobor_vm_extension/cobor_vm/src/gen/doc_data.gen.cpp
Normal file
@@ -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
cobor_vm_extension/cobor_vm/src/gen/doc_data.gen.os
Normal file
BIN
cobor_vm_extension/cobor_vm/src/gen/doc_data.gen.os
Normal file
Binary file not shown.
40
cobor_vm_extension/cobor_vm/src/register_types.cpp
Normal file
40
cobor_vm_extension/cobor_vm/src/register_types.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
#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 "example_class.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::ExampleClass);
|
||||
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
cobor_vm_extension/cobor_vm/src/register_types.os
Normal file
BIN
cobor_vm_extension/cobor_vm/src/register_types.os
Normal file
Binary file not shown.
Reference in New Issue
Block a user