feat: add scheduler module and refactor built-in module loading into shared modules.c

Introduce a new scheduler module with fiber-based cooperative multitasking, including native bindings for resume operations and a Wren class for scheduling callables. Refactor the existing timer module and CLI code to use a centralized built-in module registry in modules.c, replacing direct includes of timer.h and timer.wren.inc. Update Xcode project and Makefile to compile the new scheduler.c, modules.c, and their generated .wren.inc sources.
This commit is contained in:
Bob Nystrom
2015-09-13 18:32:39 +00:00
parent 95626bb136
commit 34bcc6bd2d
18 changed files with 291 additions and 110 deletions
+3 -3
View File
@@ -3,8 +3,7 @@
#include <string.h>
#include "io.h"
#include "timer.h"
#include "modules.h"
char const* rootDirectory = NULL;
@@ -73,7 +72,8 @@ char* wrenFilePath(const char* name)
char* readModule(WrenVM* vm, const char* module)
{
if (strcmp(module, "timer") == 0) return timerGetSource();
char* source = readBuiltInModule(module);
if (source != NULL) return source;
// First try to load the module with a ".wren" extension.
char* modulePath = wrenFilePath(module);
+83
View File
@@ -0,0 +1,83 @@
#include <stdlib.h>
#include <string.h>
#include "modules.h"
#include "scheduler.wren.inc"
#include "timer.wren.inc"
#include "scheduler.h"
#include "timer.h"
typedef struct
{
// The name of the module.
const char* name;
// Pointer to the string containing the source code of the module. We use a
// pointer here because the string variable itself is not a constant
// expression so can't be used in the initializer below.
const char **source;
// The function that binds foreign methods in this module.
WrenForeignMethodFn (*bindMethodFn)(WrenVM* vm, const char* className,
bool isStatic, const char* signature);
// The function that binds foreign classes in this module.
WrenForeignClassMethods (*bindClassFn)(WrenVM* vm, const char* className);
} BuiltInModule;
// The array of built-in modules.
static BuiltInModule modules[] =
{
{"scheduler", &schedulerModuleSource, schedulerBindForeign, NULL},
{"timer", &timerModuleSource, timerBindForeign, NULL},
// Sentinel marking the end of the list.
{NULL, NULL, NULL, NULL}
};
// Looks for a built-in module with [name].
//
// Returns the BuildInModule for it or NULL if not found.
static BuiltInModule* findModule(const char* name)
{
for (int i = 0; modules[i].name != NULL; i++)
{
if (strcmp(name, modules[i].name) == 0) return &modules[i];
}
return NULL;
}
char* readBuiltInModule(const char* name)
{
BuiltInModule* module = findModule(name);
if (module == NULL) return NULL;
size_t length = strlen(*module->source);
char* copy = (char*)malloc(length + 1);
strncpy(copy, *module->source, length + 1);
return copy;
}
WrenForeignMethodFn bindBuiltInForeignMethod(
WrenVM* vm, const char* moduleName, const char* className, bool isStatic,
const char* signature)
{
BuiltInModule* module = findModule(moduleName);
if (module == NULL) return NULL;
return module->bindMethodFn(vm, className, isStatic, signature);
}
WrenForeignClassMethods bindBuiltInForeignClass(
WrenVM* vm, const char* moduleName, const char* className)
{
WrenForeignClassMethods methods = { NULL, NULL };
BuiltInModule* module = findModule(moduleName);
if (module == NULL) return methods;
return module->bindClassFn(vm, className);
}
+19
View File
@@ -0,0 +1,19 @@
#ifndef modules_h
#define modules_h
#include "wren.h"
char* readBuiltInModule(const char* module);
// Looks up a foreign method in a built-in module.
//
// Returns `NULL` if [moduleName] is not a built-in module.
WrenForeignMethodFn bindBuiltInForeignMethod(
WrenVM* vm, const char* moduleName, const char* className, bool isStatic,
const char* signature);
// Binds foreign classes declared in a built-in modules.
WrenForeignClassMethods bindBuiltInForeignClass(
WrenVM* vm, const char* moduleName, const char* className);
#endif
+14 -14
View File
@@ -2,8 +2,9 @@
#include <string.h>
#include "io.h"
#include "modules.h"
#include "vm.h"
#include "timer.h"
#include "scheduler.h"
#define MAX_LINE_LENGTH 1024 // TODO: Something less arbitrary.
@@ -15,16 +16,15 @@ static WrenBindForeignClassFn bindClassFn = NULL;
uv_loop_t* loop;
/// Binds foreign methods declared in either built in modules, or the injected
/// API test modules.
// Binds foreign methods declared in either built in modules, or the injected
// API test modules.
static WrenForeignMethodFn bindForeignMethod(WrenVM* vm, const char* module,
const char* className, bool isStatic, const char* signature)
{
if (strcmp(module, "timer") == 0)
{
return timerBindForeign(vm, className, isStatic, signature);
}
WrenForeignMethodFn method = bindBuiltInForeignMethod(vm, module, className,
isStatic, signature);
if (method != NULL) return method;
if (bindMethodFn != NULL)
{
return bindMethodFn(vm, module, className, isStatic, signature);
@@ -33,14 +33,14 @@ static WrenForeignMethodFn bindForeignMethod(WrenVM* vm, const char* module,
return NULL;
}
/// Binds foreign classes declared in either built in modules, or the injected
/// API test modules.
// Binds foreign classes declared in either built in modules, or the injected
// API test modules.
static WrenForeignClassMethods bindForeignClass(
WrenVM* vm, const char* module, const char* className)
{
WrenForeignClassMethods methods = { NULL, NULL };
// TODO: Bind classes for built-in modules here.
WrenForeignClassMethods methods = bindBuiltInForeignClass(vm, module,
className);
if (methods.allocate != NULL) return methods;
if (bindClassFn != NULL)
{
@@ -70,7 +70,7 @@ static void initVM()
static void freeVM()
{
timerReleaseMethods();
schedulerReleaseMethods();
uv_loop_close(loop);
free(loop);