1
0
mirror of https://github.com/janet-lang/janet synced 2024-12-25 16:00:27 +00:00

Begin implementing module system.

This commit is contained in:
Calvin Rose 2017-04-12 21:21:46 -04:00
parent ded3d06387
commit e28e31f818
10 changed files with 90 additions and 62 deletions

View File

@ -16,7 +16,7 @@ all: $(GST_TARGET)
###################################
GST_CORE_SOURCES=$(addprefix core/,\
compile.c disasm.c parse.c stl.c strings.c \
value.c vm.c ds.c gc.c thread.c serialize.c)
value.c vm.c ds.c gc.c thread.c serialize.c capi.c)
GST_CORE_OBJECTS=$(patsubst %.c,%.o,$(GST_CORE_SOURCES))
$(GST_CORELIB): $(GST_CORE_OBJECTS) $(GST_HEADERS)
ar rcs $(GST_CORELIB) $(GST_CORE_OBJECTS)

View File

@ -16,10 +16,7 @@ void debug_repl(FILE *in, FILE *out) {
GstCompiler c;
gst_init(&vm);
vm.rootenv.type = GST_OBJECT;
vm.rootenv.data.object = gst_object(&vm, 10);
gst_object_put(&vm, vm.rootenv.data.object, gst_load_csymbol(&vm, "_ENV"), vm.rootenv);
gst_stl_load(&vm);
for (;;) {
@ -61,9 +58,8 @@ void debug_repl(FILE *in, FILE *out) {
/* Try to compile generated AST */
gst_compiler(&c, &vm);
func.type = GST_NIL;
gst_compiler_add_global(&c, "ans", func);
gst_stl_load(&c);
gst_compiler_env(&c, vm.rootenv);
gst_compiler_usemodule(&c, "std");
gst_compiler_global(&c, "ans", gst_object_get(vm.rootenv, gst_load_csymbol(&vm, "ans")));
func.type = GST_FUNCTION;
func.data.function = gst_compiler_compile(&c, p.value);
@ -98,7 +94,7 @@ void debug_repl(FILE *in, FILE *out) {
continue;
} else if (out) {
fprintf(out, "%s\n", (char *)gst_to_string(&vm, vm.ret));
gst_object_put(&vm, vm.rootenv.data.object, gst_load_csymbol(&vm, "ans"), vm.ret);
gst_object_put(&vm, vm.rootenv, gst_load_csymbol(&vm, "ans"), vm.ret);
}
}

23
core/capi.c Normal file
View File

@ -0,0 +1,23 @@
#include <gst/gst.h>
GstObject *gst_c_module(Gst *vm, const GstModuleItem *mod) {
GstObject *module = gst_object(vm, 10);
while (mod->name != NULL) {
GstValue key = gst_load_csymbol(vm, mod->name);
GstValue val;
val.type = GST_CFUNCTION;
val.data.cfunction = mod->data;
gst_object_put(vm, module, key, val);
mod++;
}
return module;
}
void gst_c_register(Gst *vm, const char *packagename, GstObject *mod) {
GstValue modv;
if (vm->rootenv == NULL)
vm->rootenv = gst_object(vm, 10);
modv.type = GST_OBJECT;
modv.data.object = mod;
gst_object_put(vm, vm->rootenv, gst_load_csymbol(vm, packagename), modv);
}

View File

@ -327,7 +327,8 @@ static uint16_t compiler_declare_symbol(GstCompiler *c, GstScope *scope, GstValu
/* Try to resolve a symbol. If the symbol can be resovled, return true and
* pass back the level and index by reference. */
static int symbol_resolve(GstScope *scope, GstValue x, uint16_t *level, uint16_t *index) {
static int symbol_resolve(GstCompiler *c, GstValue x, uint16_t *level, uint16_t *index) {
GstScope *scope = c->tail;
uint32_t currentLevel = scope->level;
while (scope) {
GstValue check = gst_object_get(scope->locals, x);
@ -336,6 +337,7 @@ static int symbol_resolve(GstScope *scope, GstValue x, uint16_t *level, uint16_t
*index = (uint16_t) check.data.number;
return 1;
}
scope = scope->parent;
}
return 0;
@ -409,13 +411,13 @@ static Slot compile_nonref_type(GstCompiler *c, FormOptions opts, GstValue x) {
/* Compile a symbol. Resolves any kind of symbol. */
static Slot compile_symbol(GstCompiler *c, FormOptions opts, GstValue sym) {
GstBuffer * buffer = c->buffer;
GstScope * scope = c->tail;
uint16_t index = 0;
uint16_t level = 0;
Slot ret;
if (opts.resultUnused) return nil_slot();
if (!symbol_resolve(scope, sym, &level, &index))
if (!symbol_resolve(c, sym, &level, &index)) {
c_error(c, "undefined symbol");
}
if (level > 0) {
/* We have an upvalue */
ret = compiler_get_target(c, opts);
@ -452,7 +454,7 @@ static Slot compile_assign(GstCompiler *c, FormOptions opts, GstValue left, GstV
Slot slot;
subOpts.isTail = 0;
subOpts.resultUnused = 0;
if (symbol_resolve(scope, left, &level, &target)) {
if (symbol_resolve(c, left, &level, &target)) {
/* Check if we have an up value. Otherwise, it's just a normal
* local variable */
if (level != 0) {
@ -1022,39 +1024,35 @@ void gst_compiler(GstCompiler *c, Gst *vm) {
compiler_push_scope(c, 0);
}
/* Add environment */
void gst_compiler_env(GstCompiler *c, GstValue env) {
/* Add a global variable */
void gst_compiler_global(GstCompiler *c, const char *name, GstValue x) {
GstValue sym = gst_load_csymbol(c->vm, name);
compiler_declare_symbol(c, c->tail, sym);
gst_array_push(c->vm, c->env, x);
}
/* Add many global variables */
void gst_compiler_globals(GstCompiler *c, GstObject *env) {
uint32_t i;
GstBucket *bucket;
/* Register everything in environment */
if (env.type == GST_OBJECT) {
for (i = 0; i < env.data.object->capacity; ++i) {
bucket = env.data.object->buckets[i];
while (bucket) {
if (bucket->key.type == GST_SYMBOL) {
compiler_declare_symbol(c, c->tail, bucket->key);
gst_array_push(c->vm, c->env, bucket->value);
}
bucket = bucket->next;
for (i = 0; i < env->capacity; ++i) {
bucket = env->buckets[i];
while (bucket) {
if (bucket->key.type == GST_SYMBOL) {
compiler_declare_symbol(c, c->tail, bucket->key);
gst_array_push(c->vm, c->env, bucket->value);
}
bucket = bucket->next;
}
}
}
/* Register a global for the compilation environment. */
void gst_compiler_add_global(GstCompiler *c, const char *name, GstValue x) {
GstValue sym = gst_load_cstring(c->vm, name);
sym.type = GST_SYMBOL;
compiler_declare_symbol(c, c->tail, sym);
gst_array_push(c->vm, c->env, x);
}
/* Register a global c function for the compilation environment. */
void gst_compiler_add_global_cfunction(GstCompiler *c, const char *name, GstCFunction f) {
GstValue func;
func.type = GST_CFUNCTION;
func.data.cfunction = f;
gst_compiler_add_global(c, name, func);
/* Use a module that was loaded into the vm */
void gst_compiler_usemodule(GstCompiler *c, const char *modulename) {
GstValue mod = gst_object_get(c->vm->rootenv, gst_load_csymbol(c->vm, modulename));
if (mod.type == GST_OBJECT) {
gst_compiler_globals(c, mod.data.object);
}
}
/* Compile interface. Returns a function that evaluates the

View File

@ -235,13 +235,15 @@ void gst_mem_tag(void *mem, uint32_t tags) {
/* Run garbage collection */
void gst_collect(Gst *vm) {
GstValueUnion renv;
/* Thread can be null */
if (vm->thread) {
GstValueUnion t;
t.thread = vm->thread;
gst_mark(vm, t, GST_THREAD);
}
gst_mark_value(vm, vm->rootenv);
renv.object = vm->rootenv;
gst_mark(vm, renv, GST_OBJECT);
gst_mark_value(vm, vm->ret);
gst_sweep(vm);
vm->nextCollection = 0;

View File

@ -396,12 +396,7 @@ int gst_stl_serialize(Gst *vm) {
/* Bootstraping */
/****/
struct GstRegistryItem {
const char *name;
GstCFunction func;
};
static const struct GstRegistryItem const registry[] = {
static const GstModuleItem const std_module[] = {
{"+", gst_stl_add},
{"*", gst_stl_mul},
{"-", gst_stl_sub},
@ -430,9 +425,7 @@ static const struct GstRegistryItem const registry[] = {
};
/* Load all libraries */
void gst_stl_load(GstCompiler *c) {
const struct GstRegistryItem *item;
for (item = registry; item->name; ++item) {
gst_compiler_add_global_cfunction(c, item->name, item->func);
}
void gst_stl_load(Gst *vm) {
GstObject *module = gst_c_module(vm, std_module);
gst_c_register(vm, "std", module);
}

View File

@ -504,16 +504,17 @@ void gst_init(Gst *vm) {
vm->black = 0;
/* Add thread */
vm->thread = NULL;
vm->rootenv.type = GST_NIL;
/* Set up string cache */
gst_stringcache_init(vm, 128);
/* Set up global env */
vm->rootenv = NULL;
}
/* Clear all memory associated with the VM */
void gst_deinit(Gst *vm) {
gst_clear_memory(vm);
vm->thread = NULL;
vm->rootenv.type = GST_NIL;
vm->rootenv = NULL;
vm->ret.type = GST_NIL;
gst_stringcache_deinit(vm);
}

View File

@ -20,14 +20,14 @@ struct GstCompiler {
/* Initialize the Compiler */
void gst_compiler(GstCompiler *c, Gst *vm);
/* Register an environment for compilation */
void gst_compiler_env(GstCompiler *c, GstValue env);
/* Add many globals */
void gst_compiler_globals(GstCompiler *c, GstObject *env);
/* Register a global for the compilation environment. */
void gst_compiler_add_global(GstCompiler *c, const char *name, GstValue x);
void gst_compiler_global(GstCompiler *c, const char *name, GstValue x);
/* Register a global c function for the compilation environment. */
void gst_compiler_add_global_cfunction(GstCompiler *c, const char *name, GstCFunction f);
/* Use a module */
void gst_compiler_usemodule(GstCompiler *c, const char *modulename);
/* Compile a function that evaluates the given form. */
GstFunction *gst_compiler_compile(GstCompiler *c, GstValue form);

View File

@ -131,6 +131,15 @@ typedef union GstValueUnion GstValueUnion;
/* Definitely implementation details */
typedef struct GstBucket GstBucket;
/* API Types */
typedef struct GstModuleItem GstModuleItem;
/* C Api data types */
struct GstModuleItem {
const char *name;
GstCFunction data;
};
/* Union datatype */
union GstValueUnion {
GstBoolean boolean;
@ -174,7 +183,7 @@ struct GstThread {
} status;
};
/* A dynamic array type. Useful for implementing a stack. */
/* A dynamic array type. */
struct GstArray {
uint32_t count;
uint32_t capacity;
@ -257,7 +266,7 @@ struct Gst {
/* Thread */
GstThread *thread;
/* A GC root */
GstValue rootenv;
GstObject *rootenv;
/* Return state */
const char *crash;
GstValue ret; /* Returned value from gst_start. Also holds errors. */
@ -462,4 +471,11 @@ GstValue gst_arg(Gst *vm, uint16_t index);
void gst_set_arg(Gst *vm, uint16_t index, GstValue x);
uint16_t gst_count_args(Gst *vm);
/***/
/* C Api */
/***/
GstObject *gst_c_module(Gst *vm, const GstModuleItem *mod);
void gst_c_register(Gst *vm, const char *packagename, GstObject *mod);
#endif // GST_H_defined

View File

@ -2,10 +2,9 @@
#define stl_h_INCLUDED
#include <gst/gst.h>
#include <gst/compile.h>
/* Load the standard library */
void gst_stl_load(GstCompiler *c);
void gst_stl_load(Gst *vm);
#endif // stl_h_INCLUDED