mirror of
				https://github.com/janet-lang/janet
				synced 2025-10-31 15:43:01 +00:00 
			
		
		
		
	More work on compiler. Still has memory leak?
This commit is contained in:
		| @@ -32,7 +32,7 @@ | ||||
| #include <readline/history.h> | ||||
|  | ||||
| /* Compile and run an ast */ | ||||
| int debug_compile_and_run(Gst *vm, GstValue ast, GstValue env) { | ||||
| int debug_compile_and_run(Gst *vm, GstValue ast, GstValue last) { | ||||
|     GstCompiler c; | ||||
|     GstValue func; | ||||
|     /* Try to compile generated AST */ | ||||
| @@ -40,7 +40,8 @@ int debug_compile_and_run(Gst *vm, GstValue ast, GstValue env) { | ||||
|     gst_compiler_usemodule(&c, "std"); | ||||
|     gst_compiler_usemodule(&c, "std.io"); | ||||
|     gst_compiler_usemodule(&c, "std.parse"); | ||||
|     gst_compiler_globals(&c, env); | ||||
|     gst_compiler_usemodule(&c, "std.compile"); | ||||
|     gst_compiler_global(&c, "_", last); | ||||
|     func = gst_wrap_function(gst_compiler_compile(&c, ast)); | ||||
|     /* Check for compilation errors */ | ||||
|     if (c.error) { | ||||
| @@ -105,7 +106,6 @@ int debug_run(Gst *vm, FILE *in) { | ||||
| int debug_repl(Gst *vm) { | ||||
|     const char *buffer, *reader; | ||||
|     GstParser p; | ||||
|     GstValue *st; | ||||
|     for (;;) { | ||||
|         /* Init parser */ | ||||
|         gst_parser(&p, vm); | ||||
| @@ -131,10 +131,7 @@ int debug_repl(Gst *vm) { | ||||
|             printf("Unexpected end of source\n"); | ||||
|             continue; | ||||
|         } | ||||
|         /* Add _ to environemt */ | ||||
|         st = gst_struct_begin(vm, 1); | ||||
|         gst_struct_put(st, gst_string_cv(vm, "_"), vm->ret); | ||||
|         if (!debug_compile_and_run(vm, gst_parse_consume(&p), gst_wrap_struct(gst_struct_end(vm, st)))) { | ||||
|         if (!debug_compile_and_run(vm, gst_parse_consume(&p), vm->ret)) { | ||||
|             printf("%s\n", gst_to_string(vm, vm->ret)); | ||||
|         } | ||||
|     } | ||||
| @@ -147,6 +144,7 @@ int main(int argc, const char **argv) { | ||||
|     gst_init(&vm); | ||||
|     gst_stl_load(&vm); | ||||
|     gst_parse_load(&vm); | ||||
|     gst_compile_load(&vm); | ||||
|     if (argc > 1) { | ||||
|         const char *filename; | ||||
|         FILE *f; | ||||
|   | ||||
							
								
								
									
										235
									
								
								core/compile.c
									
									
									
									
									
								
							
							
						
						
									
										235
									
								
								core/compile.c
									
									
									
									
									
								
							| @@ -72,6 +72,7 @@ struct SlotTracker { | ||||
|     Slot *slots; | ||||
|     uint32_t count; | ||||
|     uint32_t capacity; | ||||
|     SlotTracker *next; | ||||
| }; | ||||
|  | ||||
| /* A GstScope is a lexical scope in the program. It is | ||||
| @@ -88,6 +89,8 @@ struct GstScope { | ||||
|     uint16_t *freeHeap; | ||||
|     GstTable *literals; | ||||
|     GstArray *literalsArray; | ||||
|     GstTable *namedLiterals; | ||||
|     GstTable *nilNamedLiterals; /* Work around tables not containg nil */ | ||||
|     GstTable *locals; | ||||
|     GstScope *parent; | ||||
| }; | ||||
| @@ -142,10 +145,14 @@ static GstScope *compiler_push_scope(GstCompiler *c, int sameFunction) { | ||||
|         scope->nextLocal = c->tail->nextLocal; | ||||
|         scope->literals = c->tail->literals; | ||||
|         scope->literalsArray = c->tail->literalsArray; | ||||
|         scope->namedLiterals = c->tail->namedLiterals; | ||||
|         scope->nilNamedLiterals = c->tail->nilNamedLiterals; | ||||
|     } else { | ||||
|         scope->nextLocal = 0; | ||||
|         scope->literals = gst_table(c->vm, 10); | ||||
|         scope->literalsArray = gst_array(c->vm, 10); | ||||
|         scope->namedLiterals = gst_table(c->vm, 10); | ||||
|         scope->nilNamedLiterals = gst_table(c->vm, 10); | ||||
|     } | ||||
|     c->tail = scope; | ||||
|     return scope; | ||||
| @@ -204,6 +211,9 @@ static void tracker_init(GstCompiler *c, SlotTracker *tracker) { | ||||
|     tracker->slots = gst_alloc(c->vm, 10 * sizeof(Slot)); | ||||
|     tracker->count = 0; | ||||
|     tracker->capacity = 10; | ||||
|     /* Push to tracker stack */ | ||||
|     tracker->next = (SlotTracker *) c->trackers; | ||||
|     c->trackers = tracker; | ||||
| } | ||||
|  | ||||
| /* Free up a slot if it is a temporary slot (does not | ||||
| @@ -300,6 +310,8 @@ static void compiler_tracker_free(GstCompiler *c, GstScope *scope, SlotTracker * | ||||
|     for (i = tracker->count - 1; i < tracker->count; --i) { | ||||
|         compiler_drop_slot(c, scope, tracker->slots[i]); | ||||
|     } | ||||
|     /* Pop from tracker stack */ | ||||
|     c->trackers = tracker->next; | ||||
| } | ||||
|  | ||||
| /* Add a new Slot to a slot tracker. */ | ||||
| @@ -350,7 +362,7 @@ 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(GstCompiler *c, GstValue x, uint16_t *level, uint16_t *index) { | ||||
| static int symbol_resolve(GstCompiler *c, GstValue x, uint16_t *level, uint16_t *index, GstValue *out) { | ||||
|     GstScope *scope = c->tail; | ||||
|     uint32_t currentLevel = scope->level; | ||||
|     while (scope) { | ||||
| @@ -360,7 +372,18 @@ static int symbol_resolve(GstCompiler *c, GstValue x, uint16_t *level, uint16_t | ||||
|             *index = (uint16_t) check.data.integer; | ||||
|             return 1; | ||||
|         } | ||||
|          | ||||
|         /* Check for named literals */ | ||||
|         check = gst_table_get(scope->namedLiterals, x); | ||||
|         if (check.type != GST_NIL) { | ||||
|             *out = check; | ||||
|             return 2;  | ||||
|         } | ||||
|         /* Check for nil named literal */ | ||||
|         check = gst_table_get(scope->nilNamedLiterals, x); | ||||
|         if (check.type != GST_NIL) { | ||||
|             *out = gst_wrap_nil(); | ||||
|             return 2; | ||||
|         } | ||||
|         scope = scope->parent; | ||||
|     } | ||||
|     return 0; | ||||
| @@ -377,23 +400,6 @@ static int symbol_resolve(GstCompiler *c, GstValue x, uint16_t *level, uint16_t | ||||
|  * as the location on the stack. */ | ||||
| static Slot compile_value(GstCompiler *c, FormOptions opts, GstValue x); | ||||
|  | ||||
| /* Compile a structure that evaluates to a literal value. Useful | ||||
|  * for objects like strings, or anything else that cannot be instatiated | ||||
|  * from bytecode and doesn't do anything in the AST. */ | ||||
| static Slot compile_literal(GstCompiler *c, FormOptions opts, GstValue x) { | ||||
|     GstScope *scope = c->tail; | ||||
|     GstBuffer *buffer = c->buffer; | ||||
|     Slot ret; | ||||
|     uint16_t literalIndex; | ||||
|     if (opts.resultUnused) return nil_slot(); | ||||
|     ret = compiler_get_target(c, opts); | ||||
|     literalIndex = compiler_add_literal(c, scope, x); | ||||
|     gst_buffer_push_u16(c->vm, buffer, GST_OP_CST); | ||||
|     gst_buffer_push_u16(c->vm, buffer, ret.index); | ||||
|     gst_buffer_push_u16(c->vm, buffer, literalIndex); | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| /* Compile boolean, nil, and number values. */ | ||||
| static Slot compile_nonref_type(GstCompiler *c, FormOptions opts, GstValue x) { | ||||
|     GstBuffer *buffer = c->buffer; | ||||
| @@ -430,17 +436,48 @@ static Slot compile_nonref_type(GstCompiler *c, FormOptions opts, GstValue x) { | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| /* Compile a structure that evaluates to a literal value. Useful | ||||
|  * for objects like strings, or anything else that cannot be instantiated | ||||
|  * from bytecode and doesn't do anything in the AST. */ | ||||
| static Slot compile_literal(GstCompiler *c, FormOptions opts, GstValue x) { | ||||
|     GstScope *scope = c->tail; | ||||
|     GstBuffer *buffer = c->buffer; | ||||
|     Slot ret; | ||||
|     uint16_t literalIndex; | ||||
|     if (opts.resultUnused) return nil_slot(); | ||||
|     switch (x.type) { | ||||
|         case GST_INTEGER: | ||||
|         case GST_REAL: | ||||
|         case GST_BOOLEAN: | ||||
|         case GST_NIL: | ||||
|             return compile_nonref_type(c, opts, x); | ||||
|         default: | ||||
|             break; | ||||
|     } | ||||
|     ret = compiler_get_target(c, opts); | ||||
|     literalIndex = compiler_add_literal(c, scope, x); | ||||
|     gst_buffer_push_u16(c->vm, buffer, GST_OP_CST); | ||||
|     gst_buffer_push_u16(c->vm, buffer, ret.index); | ||||
|     gst_buffer_push_u16(c->vm, buffer, literalIndex); | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| /* Compile a symbol. Resolves any kind of symbol. */ | ||||
| static Slot compile_symbol(GstCompiler *c, FormOptions opts, GstValue sym) { | ||||
|     GstValue lit = gst_wrap_nil(); | ||||
|     GstBuffer * buffer = c->buffer; | ||||
|     uint16_t index = 0; | ||||
|     uint16_t level = 0; | ||||
|     Slot ret; | ||||
|     if (opts.resultUnused) return nil_slot(); | ||||
|     if (!symbol_resolve(c, sym, &level, &index)) { | ||||
|     int status = symbol_resolve(c, sym, &level, &index, &lit); | ||||
|     if (!status) { | ||||
|         c_error(c, "undefined symbol"); | ||||
|     } | ||||
|     if (level > 0) { | ||||
|     if (opts.resultUnused) return nil_slot(); | ||||
|     if (status == 2) { | ||||
|         /* We have a named literal */ | ||||
|         return compile_literal(c, opts, lit); | ||||
|     } else if (level > 0) { | ||||
|         /* We have an upvalue */ | ||||
|         ret = compiler_get_target(c, opts); | ||||
|         gst_buffer_push_u16(c->vm, buffer, GST_OP_UPV); | ||||
| @@ -468,15 +505,20 @@ static Slot compile_symbol(GstCompiler *c, FormOptions opts, GstValue sym) { | ||||
|  | ||||
| /* Compile an assignment operation */ | ||||
| static Slot compile_assign(GstCompiler *c, FormOptions opts, GstValue left, GstValue right) { | ||||
|     GstValue lit = gst_wrap_nil(); | ||||
|     GstScope *scope = c->tail; | ||||
|     GstBuffer *buffer = c->buffer; | ||||
|     FormOptions subOpts; | ||||
|     uint16_t target = 0; | ||||
|     uint16_t level = 0; | ||||
|     Slot slot; | ||||
|     int status; | ||||
|     subOpts.isTail = 0; | ||||
|     subOpts.resultUnused = 0; | ||||
|     if (symbol_resolve(c, left, &level, &target)) { | ||||
|     status = symbol_resolve(c, left, &level, &target, &lit); | ||||
|     if (status == 2) { | ||||
|         c_error(c, "cannot set binding"); | ||||
|     } else if (status == 1) { | ||||
|         /* Check if we have an up value. Otherwise, it's just a normal | ||||
|          * local variable */ | ||||
|         if (level != 0) { | ||||
| @@ -1028,39 +1070,32 @@ static Slot compile_value(GstCompiler *c, FormOptions opts, GstValue x) { | ||||
| void gst_compiler(GstCompiler *c, Gst *vm) { | ||||
|     c->vm = vm; | ||||
|     c->buffer = gst_buffer(vm, 128); | ||||
|     c->env = gst_array(vm, 10); | ||||
|     c->tail = NULL; | ||||
|     c->error = NULL; | ||||
|     c->trackers = NULL; | ||||
|     compiler_push_scope(c, 0); | ||||
| } | ||||
|  | ||||
| /* Add a global variable */ | ||||
| void gst_compiler_global(GstCompiler *c, const char *name, GstValue x) { | ||||
|     GstScope *scope = c->tail; | ||||
|     GstValue sym = gst_string_cv(c->vm, name); | ||||
|     compiler_declare_symbol(c, c->tail, sym); | ||||
|     gst_array_push(c->vm, c->env, x);                 | ||||
|     if (x.type == GST_NIL) | ||||
|         gst_table_put(c->vm, scope->nilNamedLiterals, sym, gst_wrap_boolean(1)); | ||||
|     else | ||||
|         gst_table_put(c->vm, scope->namedLiterals, sym, x); | ||||
| } | ||||
|  | ||||
| /* Add many global variables */ | ||||
| void gst_compiler_globals(GstCompiler *c, GstValue env) { | ||||
|     GstScope *scope = c->tail; | ||||
|     const GstValue *data; | ||||
|     uint32_t len; | ||||
|     uint32_t i; | ||||
|     if (env.type == GST_TABLE) { | ||||
|         GstTable *t = env.data.table; | ||||
|         for (i = 0; i < t->capacity; i += 2) { | ||||
|             if (t->data[i].type == GST_STRING) { | ||||
|                 compiler_declare_symbol(c, c->tail, t->data[i]); | ||||
|                 gst_array_push(c->vm, c->env, t->data[i + 1]);                 | ||||
|             } | ||||
|         } | ||||
|     } else if (env.type == GST_STRUCT) { | ||||
|         const GstValue *st = env.data.st; | ||||
|         for (i = 0; i < gst_struct_capacity(st); i += 2) { | ||||
|             if (st[i].type == GST_STRING) { | ||||
|                 compiler_declare_symbol(c, c->tail, st[i]); | ||||
|                 gst_array_push(c->vm, c->env, st[i + 1]);                 | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     if (gst_hashtable_view(env, &data, &len)) | ||||
|         for (i = 0; i < len; i += 2) | ||||
|             if (data[i].type == GST_STRING) | ||||
|                 gst_table_put(c->vm, scope->namedLiterals, data[i], data[i + 1]); | ||||
| } | ||||
|  | ||||
| /* Use a module that was loaded into the vm */ | ||||
| @@ -1076,6 +1111,7 @@ GstFunction *gst_compiler_compile(GstCompiler *c, GstValue form) { | ||||
|     GstFuncDef *def; | ||||
|     if (setjmp(c->onError)) { | ||||
|         /* Clear all but root scope */ | ||||
|         c->trackers = NULL; | ||||
|         if (c->tail) | ||||
|             c->tail->parent = NULL; | ||||
|         if (c->error == NULL) | ||||
| @@ -1088,16 +1124,10 @@ GstFunction *gst_compiler_compile(GstCompiler *c, GstValue form) { | ||||
|     compiler_return(c, compile_value(c, opts, form)); | ||||
|     def = compiler_gen_funcdef(c, c->buffer->count, 0); | ||||
|     { | ||||
|         uint32_t envSize = c->env->count; | ||||
|         GstFuncEnv *env = gst_alloc(c->vm, sizeof(GstFuncEnv)); | ||||
|         GstFunction *func = gst_alloc(c->vm, sizeof(GstFunction)); | ||||
|         if (envSize) { | ||||
|             env->values = gst_alloc(c->vm, sizeof(GstValue) * envSize); | ||||
|             gst_memcpy(env->values, c->env->data, envSize * sizeof(GstValue)); | ||||
|         } else { | ||||
|         env->values = NULL; | ||||
|         } | ||||
|         env->stackOffset = envSize; | ||||
|         env->stackOffset = 0; | ||||
|         env->thread = NULL; | ||||
|         func->parent = NULL; | ||||
|         func->def = def; | ||||
| @@ -1105,3 +1135,108 @@ GstFunction *gst_compiler_compile(GstCompiler *c, GstValue form) { | ||||
|         return func; | ||||
|     } | ||||
| } | ||||
|  | ||||
| /***/ | ||||
| /* Stl */ | ||||
| /***/ | ||||
|  | ||||
| /* GC mark mark all memory used by the compiler */ | ||||
| static void gst_compiler_mark(Gst *vm, void *data, uint32_t len) { | ||||
|     SlotTracker *st; | ||||
|     GstScope *scope; | ||||
| 	GstCompiler *c = (GstCompiler *) data; | ||||
| 	if (len != sizeof(GstCompiler)) | ||||
|     	return; | ||||
|     /* Mark compiler */ | ||||
|     gst_mark_value(vm, gst_wrap_buffer(c->buffer)); | ||||
|     /* Mark trackers */ | ||||
|     st = (SlotTracker *) c->trackers; | ||||
|     while (st) { | ||||
| 		gst_mark_mem(vm, st->slots); | ||||
| 		st = st->next; | ||||
|     } | ||||
|     /* Mark scopes */ | ||||
|     scope = c->tail; | ||||
|     while (scope) { | ||||
|         gst_mark_mem(vm, scope->freeHeap); | ||||
|         gst_mark_value(vm, gst_wrap_array(scope->literalsArray)); | ||||
|         gst_mark_value(vm, gst_wrap_table(scope->locals)); | ||||
|         gst_mark_value(vm, gst_wrap_table(scope->literals)); | ||||
|         gst_mark_value(vm, gst_wrap_table(scope->namedLiterals)); | ||||
|         gst_mark_value(vm, gst_wrap_table(scope->nilNamedLiterals)); | ||||
| 		scope = scope->parent; | ||||
|     } | ||||
| } | ||||
|  | ||||
| /* Compiler userdata type */ | ||||
| static const GstUserType gst_stl_compilertype = { | ||||
| 	"std.compiler", | ||||
| 	NULL, | ||||
| 	NULL, | ||||
| 	NULL, | ||||
| 	&gst_compiler_mark | ||||
| }; | ||||
|  | ||||
| /* Create a compiler userdata */ | ||||
| static int gst_stl_compiler(Gst *vm) { | ||||
| 	GstCompiler *c = gst_userdata(vm, sizeof(GstCompiler), &gst_stl_compilertype); | ||||
| 	gst_compiler(c, vm); | ||||
| 	gst_c_return(vm, gst_wrap_userdata(c)); | ||||
| } | ||||
|  | ||||
| /* Add a binding to the compiler's current scope. */ | ||||
| static int gst_stl_compiler_binding(Gst *vm) { | ||||
| 	GstCompiler *c = gst_check_userdata(vm, 0, &gst_stl_compilertype); | ||||
|     GstScope *scope; | ||||
|     GstValue sym; | ||||
| 	const uint8_t *data; | ||||
| 	uint32_t len; | ||||
| 	if (!c) | ||||
|     	gst_c_throwc(vm, "expected compiler"); | ||||
|     if (!gst_chararray_view(gst_arg(vm, 1), &data, &len)) | ||||
|         gst_c_throwc(vm, "expected string/buffer"); | ||||
|     scope = c->tail; | ||||
|     sym = gst_wrap_string(gst_string_b(c->vm, data, len)); | ||||
|     gst_table_put(c->vm, scope->namedLiterals, sym, gst_arg(vm, 2)); | ||||
|     gst_c_return(vm, gst_wrap_userdata(c)); | ||||
| } | ||||
|  | ||||
| /* Compile a value */ | ||||
| static int gst_stl_compiler_compile(Gst *vm) { | ||||
|     GstFunction *ret; | ||||
| 	GstCompiler *c = gst_check_userdata(vm, 0, &gst_stl_compilertype); | ||||
| 	if (!c) | ||||
|     	gst_c_throwc(vm, "expected compiler"); | ||||
|     ret = gst_compiler_compile(c, gst_arg(vm, 1)); | ||||
|     if (ret == NULL) | ||||
|         gst_c_throwc(vm, c->error); | ||||
|     gst_c_return(vm, gst_wrap_function(ret)); | ||||
| } | ||||
|  | ||||
| /* Use an environment during compilation. Names that are declared more than | ||||
|  * once should use their final declared value. */ | ||||
| static int gst_stl_compiler_bindings(Gst *vm) { | ||||
|     GstValue env; | ||||
|     GstCompiler *c = gst_check_userdata(vm, 0, &gst_stl_compilertype); | ||||
|     if (!c) | ||||
|         gst_c_throwc(vm, "expected compiler"); | ||||
|     env = gst_arg(vm, 1); | ||||
|     if (env.type != GST_TABLE && env.type != GST_STRUCT) | ||||
|         gst_c_throwc(vm, "expected table/struct"); | ||||
|     gst_compiler_globals(c, env); | ||||
|     gst_c_return(vm, gst_wrap_userdata(c)); | ||||
| } | ||||
|  | ||||
| /* The module stuff */ | ||||
| static const GstModuleItem gst_compile_module[] = { | ||||
|     {"compiler", gst_stl_compiler}, | ||||
|     {"compile", gst_stl_compiler_compile}, | ||||
|     {"binding!", gst_stl_compiler_binding}, | ||||
|     {"bindings!", gst_stl_compiler_bindings}, | ||||
|     {NULL, NULL} | ||||
| }; | ||||
|  | ||||
| /* Load compiler library */ | ||||
| void gst_compile_load(Gst *vm) { | ||||
|     gst_module_put(vm, "std.compile", gst_cmodule_struct(vm, gst_compile_module)); | ||||
| } | ||||
|   | ||||
							
								
								
									
										33
									
								
								core/value.c
									
									
									
									
									
								
							
							
						
						
									
										33
									
								
								core/value.c
									
									
									
									
									
								
							| @@ -96,6 +96,37 @@ static const uint8_t *string_description(Gst *vm, const char *title, void *point | ||||
|     return gst_string_b(vm, buf, c - buf); | ||||
| } | ||||
|  | ||||
| /* Gets the string value of userdata. Allocates memory, so is slower than | ||||
|  * string_description. */ | ||||
| static const uint8_t *string_udata(Gst *vm, const char *title, void *pointer) { | ||||
|     uint32_t strlen = 0; | ||||
|     uint8_t *c, *buf; | ||||
|     uint32_t i; | ||||
|     union { | ||||
|         uint8_t bytes[sizeof(void *)]; | ||||
|         void *p; | ||||
|     } pbuf; | ||||
|  | ||||
|     while (title[strlen]) ++strlen; | ||||
|     c = buf = gst_alloc(vm, strlen + 5 + 2 * sizeof(void *)); | ||||
|     pbuf.p = pointer; | ||||
|     *c++ = '<'; | ||||
|     for (i = 0; title[i]; ++i) | ||||
|         *c++ = ((uint8_t *)title) [i]; | ||||
|     *c++ = ' '; | ||||
|     *c++ = '0'; | ||||
|     *c++ = 'x'; | ||||
|     for (i = sizeof(void *); i > 0; --i) { | ||||
|         uint8_t byte = pbuf.bytes[i - 1]; | ||||
|         if (!byte) continue; | ||||
|         *c++ = HEX(byte >> 4); | ||||
|         *c++ = HEX(byte & 0xF); | ||||
|     } | ||||
|     *c++ = '>'; | ||||
|     return gst_string_b(vm, buf, c - buf); | ||||
|  | ||||
| } | ||||
|  | ||||
| #undef GST_BUFSIZE | ||||
|  | ||||
| /* Returns a string pointer or NULL if could not allocate memory. */ | ||||
| @@ -131,7 +162,7 @@ const uint8_t *gst_to_string(Gst *vm, GstValue x) { | ||||
|     case GST_THREAD: | ||||
|         return string_description(vm, "thread", x.data.pointer); | ||||
|     case GST_USERDATA: | ||||
|         return string_description(vm, "userdata", x.data.pointer); | ||||
|         return string_udata(vm, gst_udata_type(x.data.pointer)->name, x.data.pointer); | ||||
|     case GST_FUNCENV: | ||||
|         return string_description(vm, "funcenv", x.data.pointer); | ||||
|     case GST_FUNCDEF: | ||||
|   | ||||
| @@ -35,8 +35,8 @@ struct GstCompiler { | ||||
|     const char *error; | ||||
|     jmp_buf onError; | ||||
|     GstScope *tail; | ||||
|     GstArray *env; | ||||
|     GstBuffer *buffer; | ||||
|     void *trackers; | ||||
| }; | ||||
|  | ||||
| /* Initialize the Compiler */ | ||||
| @@ -54,4 +54,7 @@ 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); | ||||
|  | ||||
| /* Load the library */ | ||||
| void gst_compile_load(Gst *vm); | ||||
|  | ||||
| #endif /* end of include guard: COMPILE_H_9VXF71HY */ | ||||
|   | ||||
| @@ -41,6 +41,11 @@ | ||||
| #define gst_struct_capacity(t) (gst_struct_length(t) * 4) | ||||
| #define gst_struct_hash(t) (gst_struct_raw(t)[1]) | ||||
|  | ||||
| /* Userdata utils */ | ||||
| #define gst_udata_header(u) ((GstUserdataHeader *)(u) - 1) | ||||
| #define gst_udata_type(u) (gst_udata_header(u)->type) | ||||
| #define gst_udata_size(u) (gst_udata_header(u)->size) | ||||
|  | ||||
| /* Memcpy for moving memory */ | ||||
| #ifndef gst_memcpy | ||||
| #include <string.h> | ||||
| @@ -260,7 +265,7 @@ struct GstFunction { | ||||
|  | ||||
| /* Defines a type for userdata */ | ||||
| struct GstUserType { | ||||
|     const char *id; | ||||
|     const char *name; | ||||
|     GstValue (*serialize)(Gst *vm, void *data, uint32_t len); | ||||
|     GstValue (*deserialize)(Gst *vm, GstValue in); | ||||
|     void (*finalize)(Gst *vm, void *data, uint32_t len); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Calvin Rose
					Calvin Rose