add support for external modules

This commit is contained in:
Fabien Freling 2019-10-01 16:44:50 +02:00
parent b6c60365ab
commit fe58e511e6
7 changed files with 72 additions and 18 deletions

View file

@ -1,5 +1,6 @@
add_subdirectory(engine) add_subdirectory(engine)
add_subdirectory(logic) add_subdirectory(logic)
add_subdirectory(scripts)
add_executable(sc-eng main.cpp) add_executable(sc-eng main.cpp)
target_link_libraries(sc-eng engine logic) target_link_libraries(sc-eng engine logic)

View file

@ -4,30 +4,73 @@
#include "wren/vm/wren_vm.h" #include "wren/vm/wren_vm.h"
#include <cassert> #include <cassert>
#include <cstdio>
#include <functional> #include <functional>
#include <iostream> #include <iostream>
#include <string>
void writeOutput(WrenVM *vm, const char *text) { void writeOutput(WrenVM *vm, const char *text) {
std::cout << "wren output:" << text << "\n"; std::cout << text;
} }
void errorOutput(WrenVM *vm, WrenErrorType type, const char *module, int line, const char *message) { void errorOutput(WrenVM *vm, WrenErrorType type, const char *module, int line, const char *message) {
std::cerr << "wren error [module \"" << module << "\", line " << line << "]: " << message << "\n"; if (module != nullptr) {
std::cerr << "wren error [module \"" << module << "\", line " << line << "]: " << message << "\n";
} else {
std::cerr << "wren error: " << message << "\n";
}
}
char *fileContent(const char *path) {
FILE *f = fopen(path, "rb");
if (f == NULL) {
return nullptr;
}
// Get the file length.
fseek(f, 0, SEEK_END);
size_t fileLength = ftell(f);
rewind(f);
// Read the file.
char *fileContent = (char *)malloc(fileLength + 1);
size_t bytesRead = fread(fileContent, sizeof(char), fileLength, f);
fclose(f);
if (fileLength != bytesRead) {
free(fileContent);
return nullptr;
}
fileContent[fileLength] = '\0';
return fileContent;
}
std::string getPath(const char *name) {
std::string root("/Users/ffreling/Code/scripted-engine/src/scripts/");
return root + name + ".wren";
}
char *loadModule(WrenVM *vm, const char *name) {
std::string path = getPath(name);
return fileContent(path.c_str());
} }
Logic::Logic(Engine *engine) { Logic::Logic(Engine *engine) {
WrenConfiguration wrenConfig; WrenConfiguration wrenConfig;
wrenInitConfiguration(&wrenConfig); wrenInitConfiguration(&wrenConfig);
// Setup user-defined data such as pointer to "global" objects.
_bundleData.engine = engine;
wrenConfig.userData = &_bundleData;
wrenConfig.bindForeignMethodFn = &Logic::bindForeignMethod; wrenConfig.bindForeignMethodFn = &Logic::bindForeignMethod;
wrenConfig.writeFn = &writeOutput; wrenConfig.writeFn = &writeOutput;
wrenConfig.errorFn = &errorOutput; wrenConfig.errorFn = &errorOutput;
wrenConfig.loadModuleFn = &loadModule;
_wrenVm = wrenNewVM(&wrenConfig); _wrenVm = wrenNewVM(&wrenConfig);
// Setup user-defined data such as pointer to "global" objects.
_bundleData.engine = engine;
wrenSetUserData(_wrenVm, &_bundleData);
WrenInterpretResult result = wrenInterpret(_wrenVm, "scripted-engine", "System.print(\"I am running in a VM!\")"); WrenInterpretResult result = wrenInterpret(_wrenVm, "scripted-engine", "System.print(\"I am running in a VM!\")");
assert(result == WREN_RESULT_SUCCESS); assert(result == WREN_RESULT_SUCCESS);
} }
@ -38,7 +81,7 @@ Logic::~Logic() {
void get_info(WrenVM *vm) { void get_info(WrenVM *vm) {
// Retrieve "global" objects defined in userData // Retrieve "global" objects defined in userData
BundleData *bundleData = reinterpret_cast<BundleData *>(vm->config.userData); BundleData *bundleData = reinterpret_cast<BundleData *>(wrenGetUserData(vm));
Engine *engine = bundleData->engine; Engine *engine = bundleData->engine;
assert(engine); assert(engine);
@ -48,25 +91,24 @@ void get_info(WrenVM *vm) {
WrenForeignMethodFn WrenForeignMethodFn
Logic::bindForeignMethod(WrenVM *vm, const char *module, const char *className, bool isStatic, const char *signature) { Logic::bindForeignMethod(WrenVM *vm, const char *module, const char *className, bool isStatic, const char *signature) {
if (strcmp(module, "scripted-engine") == 0) { if (strcmp(module, "engine") == 0) {
if (strcmp(className, "Engine") == 0) { if (strcmp(className, "Engine") == 0) {
if (isStatic && strcmp(signature, "get_info()") == 0) { if (isStatic && strcmp(signature, "getInfo()") == 0) {
return get_info; return get_info;
} }
// Other foreign methods on Math... // Other foreign methods on Engine...
} }
// Other classes in main... // Other classes in engine...
} }
// Other modules... // Other modules...
return nullptr; return nullptr;
} }
void Logic::interpret() { void Logic::interpret(const char *name) {
assert(_wrenVm); assert(_wrenVm);
WrenInterpretResult result = wrenInterpret(_wrenVm, "scripted-engine", "class Engine {\ std::string path = getPath(name);
foreign static get_info())\ char *script = fileContent(path.c_str());
}\ WrenInterpretResult result = wrenInterpret(_wrenVm, name, script);
Engine.get_info()");
assert(result == WREN_RESULT_SUCCESS); assert(result == WREN_RESULT_SUCCESS);
} }

View file

@ -15,7 +15,7 @@ public:
static WrenForeignMethodFn static WrenForeignMethodFn
bindForeignMethod(WrenVM *vm, const char *module, const char *className, bool isStatic, const char *signature); bindForeignMethod(WrenVM *vm, const char *module, const char *className, bool isStatic, const char *signature);
void interpret(); void interpret(const char *name);
void add_item(); void add_item();

View file

@ -5,7 +5,7 @@ int main() {
Engine e; Engine e;
Logic l(&e); Logic l(&e);
l.interpret(); l.interpret("logic");
return 0; return 0;
} }

View file

@ -0,0 +1,4 @@
set(MODULE scripts)
file(GLOB_RECURSE script_list "*.wren")
add_custom_target(${MODULE} SOURCES ${script_list})

3
src/scripts/engine.wren Normal file
View file

@ -0,0 +1,3 @@
class Engine {
foreign static getInfo()
}

4
src/scripts/logic.wren Normal file
View file

@ -0,0 +1,4 @@
import "engine" for Engine
System.print("This is logic.wren")
System.print(Engine.getInfo())