mirror of
https://github.com/wren-lang/wren.git
synced 2026-01-12 14:48:40 +01:00
The original attempt at handling the returns from loadModuleFn wasn't ideal. 889cae5ff1
Instead of making the host go via the VM allocation and need to understand it semantically, we can instead solve the problem of the unfreed return result directly.
This also opens up the option of providing a length parameter or other information needed later (length is optional, and not used as of right now, but exists to show intent).
159 lines
3.9 KiB
C
159 lines
3.9 KiB
C
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "resolution.h"
|
|
|
|
static void write(WrenVM* vm, const char* text)
|
|
{
|
|
printf("%s", text);
|
|
}
|
|
|
|
static void reportError(WrenVM* vm, WrenErrorType type,
|
|
const char* module, int line, const char* message)
|
|
{
|
|
if (type == WREN_ERROR_RUNTIME) printf("%s\n", message);
|
|
}
|
|
|
|
static void loadModuleComplete(WrenVM* vm, const char* module, WrenLoadModuleResult result)
|
|
{
|
|
free((void*)result.source);
|
|
}
|
|
|
|
static WrenLoadModuleResult loadModule(WrenVM* vm, const char* module)
|
|
{
|
|
printf("loading %s\n", module);
|
|
|
|
const char* source;
|
|
if (strcmp(module, "main/baz/bang") == 0)
|
|
{
|
|
source = "import \"foo|bar\"";
|
|
}
|
|
else
|
|
{
|
|
source = "System.print(\"ok\")";
|
|
}
|
|
|
|
char* string = (char*)malloc(strlen(source) + 1);
|
|
strcpy(string, source);
|
|
|
|
WrenLoadModuleResult result = {0};
|
|
result.onComplete = loadModuleComplete;
|
|
result.source = string;
|
|
return result;
|
|
}
|
|
|
|
static void runTestVM(WrenVM* vm, WrenConfiguration* configuration,
|
|
const char* source)
|
|
{
|
|
configuration->writeFn = write;
|
|
configuration->errorFn = reportError;
|
|
configuration->loadModuleFn = loadModule;
|
|
|
|
WrenVM* otherVM = wrenNewVM(configuration);
|
|
|
|
// We should be able to execute code.
|
|
WrenInterpretResult result = wrenInterpret(otherVM, "main", source);
|
|
if (result != WREN_RESULT_SUCCESS)
|
|
{
|
|
wrenSetSlotString(vm, 0, "error");
|
|
}
|
|
else
|
|
{
|
|
wrenSetSlotString(vm, 0, "success");
|
|
}
|
|
|
|
wrenFreeVM(otherVM);
|
|
}
|
|
|
|
static void noResolver(WrenVM* vm)
|
|
{
|
|
WrenConfiguration configuration;
|
|
wrenInitConfiguration(&configuration);
|
|
|
|
// Should default to no resolution function.
|
|
if (configuration.resolveModuleFn != NULL)
|
|
{
|
|
wrenSetSlotString(vm, 0, "Did not have null resolve function.");
|
|
return;
|
|
}
|
|
|
|
runTestVM(vm, &configuration, "import \"foo/bar\"");
|
|
}
|
|
|
|
static const char* resolveToNull(WrenVM* vm, const char* importer,
|
|
const char* name)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
static void returnsNull(WrenVM* vm)
|
|
{
|
|
WrenConfiguration configuration;
|
|
wrenInitConfiguration(&configuration);
|
|
|
|
configuration.resolveModuleFn = resolveToNull;
|
|
runTestVM(vm, &configuration, "import \"foo/bar\"");
|
|
}
|
|
|
|
static const char* resolveChange(WrenVM* vm, const char* importer,
|
|
const char* name)
|
|
{
|
|
// Concatenate importer and name.
|
|
size_t length = strlen(importer) + 1 + strlen(name) + 1;
|
|
char* result = (char*)malloc(length);
|
|
strcpy(result, importer);
|
|
strcat(result, "/");
|
|
strcat(result, name);
|
|
|
|
// Replace "|" with "/".
|
|
for (size_t i = 0; i < length; i++)
|
|
{
|
|
if (result[i] == '|') result[i] = '/';
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static void changesString(WrenVM* vm)
|
|
{
|
|
WrenConfiguration configuration;
|
|
wrenInitConfiguration(&configuration);
|
|
|
|
configuration.resolveModuleFn = resolveChange;
|
|
runTestVM(vm, &configuration, "import \"foo|bar\"");
|
|
}
|
|
|
|
static void shared(WrenVM* vm)
|
|
{
|
|
WrenConfiguration configuration;
|
|
wrenInitConfiguration(&configuration);
|
|
|
|
configuration.resolveModuleFn = resolveChange;
|
|
runTestVM(vm, &configuration, "import \"foo|bar\"\nimport \"foo/bar\"");
|
|
}
|
|
|
|
static void importer(WrenVM* vm)
|
|
{
|
|
WrenConfiguration configuration;
|
|
wrenInitConfiguration(&configuration);
|
|
|
|
configuration.resolveModuleFn = resolveChange;
|
|
runTestVM(vm, &configuration, "import \"baz|bang\"");
|
|
}
|
|
|
|
WrenForeignMethodFn resolutionBindMethod(const char* signature)
|
|
{
|
|
if (strcmp(signature, "static Resolution.noResolver()") == 0) return noResolver;
|
|
if (strcmp(signature, "static Resolution.returnsNull()") == 0) return returnsNull;
|
|
if (strcmp(signature, "static Resolution.changesString()") == 0) return changesString;
|
|
if (strcmp(signature, "static Resolution.shared()") == 0) return shared;
|
|
if (strcmp(signature, "static Resolution.importer()") == 0) return importer;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void resolutionBindClass(const char* className, WrenForeignClassMethods* methods)
|
|
{
|
|
// methods->allocate = foreignClassAllocate;
|
|
}
|