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:
parent
ded3d06387
commit
e28e31f818
2
Makefile
2
Makefile
@ -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)
|
||||
|
@ -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
23
core/capi.c
Normal 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);
|
||||
}
|
@ -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,14 +1024,19 @@ 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];
|
||||
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);
|
||||
@ -1039,22 +1046,13 @@ void gst_compiler_env(GstCompiler *c, GstValue env) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 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);
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* Compile interface. Returns a function that evaluates the
|
||||
|
@ -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;
|
||||
|
15
core/stl.c
15
core/stl.c
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user