Move meta and random to "aux" modules.

Wren now has three classes of modules:

- The one magic "core" module that's built in and always needed.
- Auxiliary libraries like "meta" and "random". These do not have any
  dependencies, so can be used even when you embed Wren inside an
  application. But they're also optional and can be disabled if you
  don't need them.
- CLI modules. These ones need libuv and are tied to the CLI wrapper
  around the VM.
This commit is contained in:
Bob Nystrom
2015-10-17 22:09:48 -07:00
parent 3ca480cbf4
commit e5176607d9
15 changed files with 264 additions and 167 deletions
+9 -5
View File
@@ -44,11 +44,15 @@
#endif
#endif
// If true, loads the "meta" built in module.
//
// Defaults to on.
#ifndef WREN_USE_META_MODULE
#define WREN_USE_META_MODULE 1
// The VM includes a number of optional "auxiliary" modules. You can choose to
// include these or not. By default, they are all available. To disable one,
// set the corresponding `WREN_AUX_<name>` define to `0`.
#ifndef WREN_AUX_META
#define WREN_AUX_META 1
#endif
#ifndef WREN_AUX_RANDOM
#define WREN_AUX_RANDOM 1
#endif
// These flags are useful for debugging and hacking on Wren itself. They are not
-56
View File
@@ -1,56 +0,0 @@
#include "wren_meta.h"
#if WREN_USE_META_MODULE
#include <string.h>
#include "wren_primitive.h"
#include "wren_meta.wren.inc"
void metaCompile(WrenVM* vm)
{
// Evaluate the code in the module where the calling function was defined.
// That's one stack frame back from the top since the top-most frame is the
// helper eval() method in Meta itself.
Value callingFn = OBJ_VAL(vm->fiber->frames[vm->fiber->numFrames - 2].fn);
ObjModule* module = IS_FN(callingFn)
? AS_FN(callingFn)->module
: AS_CLOSURE(callingFn)->fn->module;
// Compile it.
ObjFn* fn = wrenCompile(vm, module, wrenGetArgumentString(vm, 1), false);
if (fn == NULL) return;
// Return the result. We can't use the public API for this since we have a
// bare ObjFn.
*vm->foreignCallSlot = OBJ_VAL(fn);
vm->foreignCallSlot = NULL;
}
static WrenForeignMethodFn bindMetaForeignMethods(WrenVM* vm,
const char* module,
const char* className,
bool isStatic,
const char* signature)
{
// There is only one foreign method in the meta module.
ASSERT(strcmp(module, "meta") == 0, "Should be in meta module.");
ASSERT(strcmp(className, "Meta") == 0, "Should be in Meta class.");
ASSERT(isStatic, "Should be static.");
ASSERT(strcmp(signature, "compile_(_)") == 0, "Should be compile method.");
return metaCompile;
}
void wrenLoadMetaModule(WrenVM* vm)
{
WrenBindForeignMethodFn previousBindFn = vm->config.bindForeignMethodFn;
vm->config.bindForeignMethodFn = bindMetaForeignMethods;
wrenInterpretInModule(vm, "meta", metaModuleSource);
vm->config.bindForeignMethodFn = previousBindFn;
}
#endif
-15
View File
@@ -1,15 +0,0 @@
#ifndef wren_meta_h
#define wren_meta_h
#include "wren_common.h"
#include "wren.h"
// This module defines the Meta class and its associated methods.
#if WREN_USE_META_MODULE
void wrenLoadMetaModule(WrenVM* vm);
#endif
#endif
-15
View File
@@ -1,15 +0,0 @@
// Generated automatically from builtin/meta.wren. Do not edit.
static const char* metaModuleSource =
"class Meta {\n"
" static eval(source) {\n"
" if (!(source is String)) Fiber.abort(\"Source code must be a string.\")\n"
"\n"
" var fn = compile_(source)\n"
" // TODO: Include compile errors.\n"
" if (fn == null) Fiber.abort(\"Could not compile source code.\")\n"
"\n"
" Fiber.new(fn).call()\n"
" }\n"
"\n"
" foreign static compile_(source)\n"
"}\n";
+18 -14
View File
@@ -8,8 +8,11 @@
#include "wren_debug.h"
#include "wren_vm.h"
#if WREN_USE_META_MODULE
#include "wren_meta.h"
#if WREN_AUX_META
#include "wren_aux_meta.h"
#endif
#if WREN_AUX_RANDOM
#include "wren_aux_random.h"
#endif
#if WREN_DEBUG_TRACE_MEMORY || WREN_DEBUG_TRACE_GC
@@ -57,10 +60,14 @@ WrenVM* wrenNewVM(WrenConfiguration* config)
wrenInitializeCore(vm);
#if WREN_USE_META_MODULE
// TODO: Lazy load these.
#if WREN_AUX_META
wrenLoadMetaModule(vm);
#endif
#if WREN_AUX_RANDOM
wrenLoadRandomModule(vm);
#endif
return vm;
}
@@ -449,17 +456,14 @@ static ObjFiber* loadModule(WrenVM* vm, Value name, const char* source)
// multiple times.
wrenMapSet(vm, vm->modules, name, OBJ_VAL(module));
// Implicitly import the core module (unless we *are* core).
if (!IS_NULL(name))
// Implicitly import the core module.
ObjModule* coreModule = getModule(vm, NULL_VAL);
for (int i = 0; i < coreModule->variables.count; i++)
{
ObjModule* coreModule = getModule(vm, NULL_VAL);
for (int i = 0; i < coreModule->variables.count; i++)
{
wrenDefineVariable(vm, module,
coreModule->variableNames.data[i].buffer,
coreModule->variableNames.data[i].length,
coreModule->variables.data[i]);
}
wrenDefineVariable(vm, module,
coreModule->variableNames.data[i].buffer,
coreModule->variableNames.data[i].length,
coreModule->variables.data[i]);
}
}