mirror of
https://github.com/janet-lang/janet
synced 2024-12-26 00:10: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/,\
|
GST_CORE_SOURCES=$(addprefix core/,\
|
||||||
compile.c disasm.c parse.c stl.c strings.c \
|
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_CORE_OBJECTS=$(patsubst %.c,%.o,$(GST_CORE_SOURCES))
|
||||||
$(GST_CORELIB): $(GST_CORE_OBJECTS) $(GST_HEADERS)
|
$(GST_CORELIB): $(GST_CORE_OBJECTS) $(GST_HEADERS)
|
||||||
ar rcs $(GST_CORELIB) $(GST_CORE_OBJECTS)
|
ar rcs $(GST_CORELIB) $(GST_CORE_OBJECTS)
|
||||||
|
@ -16,10 +16,7 @@ void debug_repl(FILE *in, FILE *out) {
|
|||||||
GstCompiler c;
|
GstCompiler c;
|
||||||
|
|
||||||
gst_init(&vm);
|
gst_init(&vm);
|
||||||
|
gst_stl_load(&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);
|
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
|
||||||
@ -61,9 +58,8 @@ void debug_repl(FILE *in, FILE *out) {
|
|||||||
/* Try to compile generated AST */
|
/* Try to compile generated AST */
|
||||||
gst_compiler(&c, &vm);
|
gst_compiler(&c, &vm);
|
||||||
func.type = GST_NIL;
|
func.type = GST_NIL;
|
||||||
gst_compiler_add_global(&c, "ans", func);
|
gst_compiler_usemodule(&c, "std");
|
||||||
gst_stl_load(&c);
|
gst_compiler_global(&c, "ans", gst_object_get(vm.rootenv, gst_load_csymbol(&vm, "ans")));
|
||||||
gst_compiler_env(&c, vm.rootenv);
|
|
||||||
func.type = GST_FUNCTION;
|
func.type = GST_FUNCTION;
|
||||||
func.data.function = gst_compiler_compile(&c, p.value);
|
func.data.function = gst_compiler_compile(&c, p.value);
|
||||||
|
|
||||||
@ -98,7 +94,7 @@ void debug_repl(FILE *in, FILE *out) {
|
|||||||
continue;
|
continue;
|
||||||
} else if (out) {
|
} else if (out) {
|
||||||
fprintf(out, "%s\n", (char *)gst_to_string(&vm, vm.ret));
|
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
|
/* Try to resolve a symbol. If the symbol can be resovled, return true and
|
||||||
* pass back the level and index by reference. */
|
* 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;
|
uint32_t currentLevel = scope->level;
|
||||||
while (scope) {
|
while (scope) {
|
||||||
GstValue check = gst_object_get(scope->locals, x);
|
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;
|
*index = (uint16_t) check.data.number;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
scope = scope->parent;
|
scope = scope->parent;
|
||||||
}
|
}
|
||||||
return 0;
|
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. */
|
/* Compile a symbol. Resolves any kind of symbol. */
|
||||||
static Slot compile_symbol(GstCompiler *c, FormOptions opts, GstValue sym) {
|
static Slot compile_symbol(GstCompiler *c, FormOptions opts, GstValue sym) {
|
||||||
GstBuffer * buffer = c->buffer;
|
GstBuffer * buffer = c->buffer;
|
||||||
GstScope * scope = c->tail;
|
|
||||||
uint16_t index = 0;
|
uint16_t index = 0;
|
||||||
uint16_t level = 0;
|
uint16_t level = 0;
|
||||||
Slot ret;
|
Slot ret;
|
||||||
if (opts.resultUnused) return nil_slot();
|
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");
|
c_error(c, "undefined symbol");
|
||||||
|
}
|
||||||
if (level > 0) {
|
if (level > 0) {
|
||||||
/* We have an upvalue */
|
/* We have an upvalue */
|
||||||
ret = compiler_get_target(c, opts);
|
ret = compiler_get_target(c, opts);
|
||||||
@ -452,7 +454,7 @@ static Slot compile_assign(GstCompiler *c, FormOptions opts, GstValue left, GstV
|
|||||||
Slot slot;
|
Slot slot;
|
||||||
subOpts.isTail = 0;
|
subOpts.isTail = 0;
|
||||||
subOpts.resultUnused = 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
|
/* Check if we have an up value. Otherwise, it's just a normal
|
||||||
* local variable */
|
* local variable */
|
||||||
if (level != 0) {
|
if (level != 0) {
|
||||||
@ -1022,14 +1024,19 @@ void gst_compiler(GstCompiler *c, Gst *vm) {
|
|||||||
compiler_push_scope(c, 0);
|
compiler_push_scope(c, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add environment */
|
/* Add a global variable */
|
||||||
void gst_compiler_env(GstCompiler *c, GstValue env) {
|
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;
|
uint32_t i;
|
||||||
GstBucket *bucket;
|
GstBucket *bucket;
|
||||||
/* Register everything in environment */
|
for (i = 0; i < env->capacity; ++i) {
|
||||||
if (env.type == GST_OBJECT) {
|
bucket = env->buckets[i];
|
||||||
for (i = 0; i < env.data.object->capacity; ++i) {
|
|
||||||
bucket = env.data.object->buckets[i];
|
|
||||||
while (bucket) {
|
while (bucket) {
|
||||||
if (bucket->key.type == GST_SYMBOL) {
|
if (bucket->key.type == GST_SYMBOL) {
|
||||||
compiler_declare_symbol(c, c->tail, bucket->key);
|
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. */
|
/* Use a module that was loaded into the vm */
|
||||||
void gst_compiler_add_global(GstCompiler *c, const char *name, GstValue x) {
|
void gst_compiler_usemodule(GstCompiler *c, const char *modulename) {
|
||||||
GstValue sym = gst_load_cstring(c->vm, name);
|
GstValue mod = gst_object_get(c->vm->rootenv, gst_load_csymbol(c->vm, modulename));
|
||||||
sym.type = GST_SYMBOL;
|
if (mod.type == GST_OBJECT) {
|
||||||
compiler_declare_symbol(c, c->tail, sym);
|
gst_compiler_globals(c, mod.data.object);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compile interface. Returns a function that evaluates the
|
/* Compile interface. Returns a function that evaluates the
|
||||||
|
@ -235,13 +235,15 @@ void gst_mem_tag(void *mem, uint32_t tags) {
|
|||||||
|
|
||||||
/* Run garbage collection */
|
/* Run garbage collection */
|
||||||
void gst_collect(Gst *vm) {
|
void gst_collect(Gst *vm) {
|
||||||
|
GstValueUnion renv;
|
||||||
/* Thread can be null */
|
/* Thread can be null */
|
||||||
if (vm->thread) {
|
if (vm->thread) {
|
||||||
GstValueUnion t;
|
GstValueUnion t;
|
||||||
t.thread = vm->thread;
|
t.thread = vm->thread;
|
||||||
gst_mark(vm, t, GST_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_mark_value(vm, vm->ret);
|
||||||
gst_sweep(vm);
|
gst_sweep(vm);
|
||||||
vm->nextCollection = 0;
|
vm->nextCollection = 0;
|
||||||
|
15
core/stl.c
15
core/stl.c
@ -396,12 +396,7 @@ int gst_stl_serialize(Gst *vm) {
|
|||||||
/* Bootstraping */
|
/* Bootstraping */
|
||||||
/****/
|
/****/
|
||||||
|
|
||||||
struct GstRegistryItem {
|
static const GstModuleItem const std_module[] = {
|
||||||
const char *name;
|
|
||||||
GstCFunction func;
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct GstRegistryItem const registry[] = {
|
|
||||||
{"+", gst_stl_add},
|
{"+", gst_stl_add},
|
||||||
{"*", gst_stl_mul},
|
{"*", gst_stl_mul},
|
||||||
{"-", gst_stl_sub},
|
{"-", gst_stl_sub},
|
||||||
@ -430,9 +425,7 @@ static const struct GstRegistryItem const registry[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Load all libraries */
|
/* Load all libraries */
|
||||||
void gst_stl_load(GstCompiler *c) {
|
void gst_stl_load(Gst *vm) {
|
||||||
const struct GstRegistryItem *item;
|
GstObject *module = gst_c_module(vm, std_module);
|
||||||
for (item = registry; item->name; ++item) {
|
gst_c_register(vm, "std", module);
|
||||||
gst_compiler_add_global_cfunction(c, item->name, item->func);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -504,16 +504,17 @@ void gst_init(Gst *vm) {
|
|||||||
vm->black = 0;
|
vm->black = 0;
|
||||||
/* Add thread */
|
/* Add thread */
|
||||||
vm->thread = NULL;
|
vm->thread = NULL;
|
||||||
vm->rootenv.type = GST_NIL;
|
|
||||||
/* Set up string cache */
|
/* Set up string cache */
|
||||||
gst_stringcache_init(vm, 128);
|
gst_stringcache_init(vm, 128);
|
||||||
|
/* Set up global env */
|
||||||
|
vm->rootenv = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear all memory associated with the VM */
|
/* Clear all memory associated with the VM */
|
||||||
void gst_deinit(Gst *vm) {
|
void gst_deinit(Gst *vm) {
|
||||||
gst_clear_memory(vm);
|
gst_clear_memory(vm);
|
||||||
vm->thread = NULL;
|
vm->thread = NULL;
|
||||||
vm->rootenv.type = GST_NIL;
|
vm->rootenv = NULL;
|
||||||
vm->ret.type = GST_NIL;
|
vm->ret.type = GST_NIL;
|
||||||
gst_stringcache_deinit(vm);
|
gst_stringcache_deinit(vm);
|
||||||
}
|
}
|
||||||
|
@ -20,14 +20,14 @@ struct GstCompiler {
|
|||||||
/* Initialize the Compiler */
|
/* Initialize the Compiler */
|
||||||
void gst_compiler(GstCompiler *c, Gst *vm);
|
void gst_compiler(GstCompiler *c, Gst *vm);
|
||||||
|
|
||||||
/* Register an environment for compilation */
|
/* Add many globals */
|
||||||
void gst_compiler_env(GstCompiler *c, GstValue env);
|
void gst_compiler_globals(GstCompiler *c, GstObject *env);
|
||||||
|
|
||||||
/* Register a global for the compilation environment. */
|
/* 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. */
|
/* Use a module */
|
||||||
void gst_compiler_add_global_cfunction(GstCompiler *c, const char *name, GstCFunction f);
|
void gst_compiler_usemodule(GstCompiler *c, const char *modulename);
|
||||||
|
|
||||||
/* Compile a function that evaluates the given form. */
|
/* Compile a function that evaluates the given form. */
|
||||||
GstFunction *gst_compiler_compile(GstCompiler *c, GstValue form);
|
GstFunction *gst_compiler_compile(GstCompiler *c, GstValue form);
|
||||||
|
@ -131,6 +131,15 @@ typedef union GstValueUnion GstValueUnion;
|
|||||||
/* Definitely implementation details */
|
/* Definitely implementation details */
|
||||||
typedef struct GstBucket GstBucket;
|
typedef struct GstBucket GstBucket;
|
||||||
|
|
||||||
|
/* API Types */
|
||||||
|
typedef struct GstModuleItem GstModuleItem;
|
||||||
|
|
||||||
|
/* C Api data types */
|
||||||
|
struct GstModuleItem {
|
||||||
|
const char *name;
|
||||||
|
GstCFunction data;
|
||||||
|
};
|
||||||
|
|
||||||
/* Union datatype */
|
/* Union datatype */
|
||||||
union GstValueUnion {
|
union GstValueUnion {
|
||||||
GstBoolean boolean;
|
GstBoolean boolean;
|
||||||
@ -174,7 +183,7 @@ struct GstThread {
|
|||||||
} status;
|
} status;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* A dynamic array type. Useful for implementing a stack. */
|
/* A dynamic array type. */
|
||||||
struct GstArray {
|
struct GstArray {
|
||||||
uint32_t count;
|
uint32_t count;
|
||||||
uint32_t capacity;
|
uint32_t capacity;
|
||||||
@ -257,7 +266,7 @@ struct Gst {
|
|||||||
/* Thread */
|
/* Thread */
|
||||||
GstThread *thread;
|
GstThread *thread;
|
||||||
/* A GC root */
|
/* A GC root */
|
||||||
GstValue rootenv;
|
GstObject *rootenv;
|
||||||
/* Return state */
|
/* Return state */
|
||||||
const char *crash;
|
const char *crash;
|
||||||
GstValue ret; /* Returned value from gst_start. Also holds errors. */
|
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);
|
void gst_set_arg(Gst *vm, uint16_t index, GstValue x);
|
||||||
uint16_t gst_count_args(Gst *vm);
|
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
|
#endif // GST_H_defined
|
||||||
|
@ -2,10 +2,9 @@
|
|||||||
#define stl_h_INCLUDED
|
#define stl_h_INCLUDED
|
||||||
|
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
#include <gst/compile.h>
|
|
||||||
|
|
||||||
/* Load the standard library */
|
/* Load the standard library */
|
||||||
void gst_stl_load(GstCompiler *c);
|
void gst_stl_load(Gst *vm);
|
||||||
|
|
||||||
#endif // stl_h_INCLUDED
|
#endif // stl_h_INCLUDED
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user