feat: add foreign class support with allocation, construct opcodes, and CLI callback wiring

Implement the initial infrastructure for foreign classes in the Wren VM, including new opcodes (FOREIGN_CONSTRUCT, FOREIGN_CLASS), a WrenBindForeignClassFn callback type in the public API, and updated CLI vm.c to store and forward foreign binding callbacks via setForeignCallbacks(). The compiler now tracks whether a class is foreign via a new isForeign flag in ClassCompiler, emits CODE_FOREIGN_CONSTRUCT instead of CODE_CONSTRUCT for foreign class constructors, and errors on field definitions inside foreign classes. The debug dump and opcode header gain entries for the new opcodes, and wrenBindSuperclass handles the -1 numFields sentinel for foreign classes to prevent field inheritance from superclasses.
This commit is contained in:
Bob Nystrom
2015-08-15 19:07:53 +00:00
parent 7551fa8c9b
commit 2dc209e585
33 changed files with 720 additions and 119 deletions
+2 -2
View File
@@ -9,7 +9,7 @@
static int runRepl()
{
WrenVM* vm = createVM(NULL);
WrenVM* vm = createVM();
printf("\\\\/\"-\n");
printf(" \\_/ wren v0.0.0\n");
@@ -50,7 +50,7 @@ int main(int argc, const char* argv[])
}
else if (argc == 2)
{
runFile(NULL, argv[1]);
runFile(argv[1]);
}
return 0;
+17 -10
View File
@@ -4,25 +4,25 @@
#include "io.h"
#include "vm.h"
WrenVM* createVM(WrenBindForeignMethodFn bindForeign)
static WrenBindForeignMethodFn bindMethodFn = NULL;
static WrenBindForeignClassFn bindClassFn = NULL;
WrenVM* createVM()
{
WrenConfiguration config;
config.bindForeignMethodFn = bindForeign;
wrenInitConfiguration(&config);
config.bindForeignMethodFn = bindMethodFn;
config.bindForeignClassFn = bindClassFn;
config.loadModuleFn = readModule;
// Since we're running in a standalone process, be generous with memory.
config.initialHeapSize = 1024 * 1024 * 100;
// Use defaults for these.
config.reallocateFn = NULL;
config.minHeapSize = 0;
config.heapGrowthPercent = 0;
return wrenNewVM(&config);
}
void runFile(WrenBindForeignMethodFn bindForeign, const char* path)
void runFile(const char* path)
{
// Use the directory where the file is as the root to resolve imports
// relative to.
@@ -43,7 +43,7 @@ void runFile(WrenBindForeignMethodFn bindForeign, const char* path)
exit(66);
}
WrenVM* vm = createVM(bindForeign);
WrenVM* vm = createVM();
WrenInterpretResult result = wrenInterpret(vm, path, source);
@@ -55,3 +55,10 @@ void runFile(WrenBindForeignMethodFn bindForeign, const char* path)
if (result == WREN_RESULT_COMPILE_ERROR) exit(65); // EX_DATAERR.
if (result == WREN_RESULT_RUNTIME_ERROR) exit(70); // EX_SOFTWARE.
}
void setForeignCallbacks(
WrenBindForeignMethodFn bindMethod, WrenBindForeignClassFn bindClass)
{
bindMethodFn = bindMethod;
bindClassFn = bindClass;
}
+9 -2
View File
@@ -4,11 +4,18 @@
#include "wren.h"
// Creates a new Wren VM with the CLI's module loader and other configuration.
WrenVM* createVM(WrenBindForeignMethodFn bindForeign);
WrenVM* createVM();
// Executes the Wren script at [path] in a new VM.
//
// Exits if the script failed or could not be loaded.
void runFile(WrenBindForeignMethodFn bindForeign, const char* path);
void runFile(const char* path);
// Adds additional callbacks to use when binding foreign members from Wren.
//
// Used by the API test executable to let it wire up its own foreign functions.
// This must be called before calling [createVM()].
void setForeignCallbacks(WrenBindForeignMethodFn bindMethod,
WrenBindForeignClassFn bindClass);
#endif