mirror of
				https://github.com/janet-lang/janet
				synced 2025-10-31 15:43:01 +00:00 
			
		
		
		
	Add errorParent to threads.
This commit is contained in:
		
							
								
								
									
										11
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								Makefile
									
									
									
									
									
								
							| @@ -19,12 +19,10 @@ GST_CORE_SOURCES=$(addprefix core/,\ | |||||||
| 				 compile.c disasm.c parse.c stl.c ids.c util.c\ | 				 compile.c disasm.c parse.c stl.c ids.c util.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) | ||||||
| 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) |  | ||||||
| 	ar rcs $(GST_CORELIB) $(GST_CORE_OBJECTS) |  | ||||||
|  |  | ||||||
| ############################## | ###################### | ||||||
| ##### The example client ##### | ##### The client ##### | ||||||
| ############################## | ###################### | ||||||
| GST_CLIENT_SOURCES=client/main.c | GST_CLIENT_SOURCES=client/main.c | ||||||
| GST_CLIENT_OBJECTS=$(patsubst %.c,%.o,$(GST_CLIENT_SOURCES)) | GST_CLIENT_OBJECTS=$(patsubst %.c,%.o,$(GST_CLIENT_SOURCES)) | ||||||
| $(GST_TARGET): $(GST_CLIENT_OBJECTS) $(GST_CORE_OBJECTS) | $(GST_TARGET): $(GST_CLIENT_OBJECTS) $(GST_CORE_OBJECTS) | ||||||
| @@ -50,4 +48,7 @@ clean: | |||||||
| 	rm $(GST_CLIENT_OBJECTS) || true | 	rm $(GST_CLIENT_OBJECTS) || true | ||||||
| 	rm vgcore.* || true | 	rm vgcore.* || true | ||||||
|  |  | ||||||
|  | test: $(GST_TARGET) | ||||||
|  | 	gsttests/basic.gst | ||||||
|  |  | ||||||
| .PHONY: clean install run debug valgrind | .PHONY: clean install run debug valgrind | ||||||
|   | |||||||
| @@ -117,6 +117,8 @@ int debug_repl(Gst *vm) { | |||||||
|                 break; |                 break; | ||||||
|             if (!reader || *reader == '\0') { |             if (!reader || *reader == '\0') { | ||||||
|                 buffer = readline(">> "); |                 buffer = readline(">> "); | ||||||
|  |                 if (*buffer == '\0') | ||||||
|  |                     return 0; | ||||||
|                 add_history(buffer); |                 add_history(buffer); | ||||||
|                 reader = buffer; |                 reader = buffer; | ||||||
|             } |             } | ||||||
|   | |||||||
| @@ -945,6 +945,7 @@ static SpecialFormHelper get_special(const GstValue *form) { | |||||||
|                     return compile_apply; |                     return compile_apply; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |             break; | ||||||
|         case 'd': |         case 'd': | ||||||
|             { |             { | ||||||
|                 if (gst_string_length(name) == 2 && |                 if (gst_string_length(name) == 2 && | ||||||
| @@ -989,6 +990,7 @@ static SpecialFormHelper get_special(const GstValue *form) { | |||||||
|                     return compile_tran; |                     return compile_tran; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |             break; | ||||||
|         case 'w': |         case 'w': | ||||||
|             { |             { | ||||||
|                 if (gst_string_length(name) == 5 && |                 if (gst_string_length(name) == 5 && | ||||||
|   | |||||||
| @@ -147,6 +147,8 @@ void gst_mark(Gst *vm, GstValueUnion x, GstType type) { | |||||||
|                     frame = gst_mark_stackframe(vm, frame); |                     frame = gst_mark_stackframe(vm, frame); | ||||||
|                 if (thread->parent) |                 if (thread->parent) | ||||||
|                     gst_mark_value(vm, gst_wrap_thread(thread->parent)); |                     gst_mark_value(vm, gst_wrap_thread(thread->parent)); | ||||||
|  |                 if (thread->errorParent) | ||||||
|  |                     gst_mark_value(vm, gst_wrap_thread(thread->errorParent)); | ||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -101,6 +101,8 @@ static void parser_push(GstParser *p, ParseType type, uint8_t character) { | |||||||
|     switch (type) { |     switch (type) { | ||||||
|         case PTYPE_STRING: |         case PTYPE_STRING: | ||||||
|             top->buf.string.state = STRING_STATE_BASE; |             top->buf.string.state = STRING_STATE_BASE; | ||||||
|  |             top->buf.string.buffer = gst_buffer(p->vm, 10); | ||||||
|  |             break; | ||||||
|         case PTYPE_TOKEN: |         case PTYPE_TOKEN: | ||||||
|             top->buf.string.buffer = gst_buffer(p->vm, 10); |             top->buf.string.buffer = gst_buffer(p->vm, 10); | ||||||
|             break; |             break; | ||||||
| @@ -458,6 +460,8 @@ static void dispatch_char(GstParser *p, uint8_t c) { | |||||||
|  */ |  */ | ||||||
| int gst_parse_cstring(GstParser *p, const char *string) { | int gst_parse_cstring(GstParser *p, const char *string) { | ||||||
|     int bytesRead = 0; |     int bytesRead = 0; | ||||||
|  |     if (!string) | ||||||
|  |         return 0; | ||||||
|     while ((p->status == GST_PARSER_PENDING || p->status == GST_PARSER_ROOT) |     while ((p->status == GST_PARSER_PENDING || p->status == GST_PARSER_ROOT) | ||||||
|             && (string[bytesRead] != '\0')) { |             && (string[bytesRead] != '\0')) { | ||||||
|         dispatch_char(p, string[bytesRead++]); |         dispatch_char(p, string[bytesRead++]); | ||||||
| @@ -468,6 +472,8 @@ int gst_parse_cstring(GstParser *p, const char *string) { | |||||||
| /* Parse a gst string */ | /* Parse a gst string */ | ||||||
| int gst_parse_string(GstParser *p, const uint8_t *string) { | int gst_parse_string(GstParser *p, const uint8_t *string) { | ||||||
|     uint32_t i; |     uint32_t i; | ||||||
|  |     if (!string) | ||||||
|  |         return 0; | ||||||
|     for (i = 0; i < gst_string_length(string); ++i) { |     for (i = 0; i < gst_string_length(string); ++i) { | ||||||
|         if (p->status != GST_PARSER_PENDING && p->status != GST_PARSER_ROOT) break; |         if (p->status != GST_PARSER_PENDING && p->status != GST_PARSER_ROOT) break; | ||||||
|         dispatch_char(p, string[i]); |         dispatch_char(p, string[i]); | ||||||
|   | |||||||
| @@ -38,7 +38,7 @@ | |||||||
|  * Byte 207: Buffer  - [u32 capacity][u32 length]*[u8... characters] |  * Byte 207: Buffer  - [u32 capacity][u32 length]*[u8... characters] | ||||||
|  * Byte 208: Array   - [u32 length]*[value... elements] |  * Byte 208: Array   - [u32 length]*[value... elements] | ||||||
|  * Byte 209: Tuple   - [u32 length]*[value... elements] |  * Byte 209: Tuple   - [u32 length]*[value... elements] | ||||||
|  * Byte 210: Thread  - [value parent][u8 state][u32 frames]*[[value callee][value env] |  * Byte 210: Thread  - [value parent][value errorParent][u8 state][u32 frames]*[[value callee][value env] | ||||||
|  *  [u32 pcoffset][u32 ret][u32 args][u32 size]*[value ...stack]] |  *  [u32 pcoffset][u32 ret][u32 args][u32 size]*[value ...stack]] | ||||||
|  * Byte 211: Table   - [u32 length]*2*[value... kvs] |  * Byte 211: Table   - [u32 length]*2*[value... kvs] | ||||||
|  * Byte 212: FuncDef - [u32 locals][u32 arity][u32 flags][u32 literallen]*[value... |  * Byte 212: FuncDef - [u32 locals][u32 arity][u32 flags][u32 literallen]*[value... | ||||||
| @@ -249,7 +249,16 @@ static const char *gst_deserialize_impl( | |||||||
|                 } else if (ret.type == GST_THREAD) { |                 } else if (ret.type == GST_THREAD) { | ||||||
|                     t->parent = ret.data.thread; |                     t->parent = ret.data.thread; | ||||||
|                 } else { |                 } else { | ||||||
|                     return "expected thread parent to thread"; |                     return "expected thread parent to be thread"; | ||||||
|  |                 } | ||||||
|  |                 err = gst_deserialize_impl(vm, data, end, &data, visited, &ret); | ||||||
|  |                 if (err != NULL) return err; | ||||||
|  |                 if (ret.type == GST_NIL) { | ||||||
|  |                     t->errorParent = NULL; | ||||||
|  |                 } else if (ret.type == GST_THREAD) { | ||||||
|  |                     t->errorParent = ret.data.thread; | ||||||
|  |                 } else { | ||||||
|  |                     return "expected thread error parent to be thread"; | ||||||
|                 } |                 } | ||||||
|                 deser_assert(data < end, UEB); |                 deser_assert(data < end, UEB); | ||||||
|                 statusbyte = *data++; |                 statusbyte = *data++; | ||||||
| @@ -520,10 +529,10 @@ const char *gst_serialize_impl( | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     /* Check tuples and structs before other reference types. |     /* Check tuples and structs before other reference types. | ||||||
|      * They ae immutable, and thus cannot be referenced by other values |      * They are immutable, and thus cannot be referenced by other values | ||||||
|      * until they are fully constructed. This creates some strange behavior |      * until they are fully constructed. This creates some strange behavior | ||||||
|      * if they are treated like other reference types because they cannot |      * if they are treated like other reference types because they cannot | ||||||
|      * be added to the visited table before recusring into serializing their |      * be added to the visited table before recursing into serializing their | ||||||
|      * arguments */ |      * arguments */ | ||||||
|     if (x.type == GST_STRUCT || x.type == GST_TUPLE) { |     if (x.type == GST_STRUCT || x.type == GST_TUPLE) { | ||||||
|         if (x.type == GST_STRUCT) { |         if (x.type == GST_STRUCT) { | ||||||
| @@ -632,6 +641,11 @@ const char *gst_serialize_impl( | |||||||
|                     err = gst_serialize_impl(vm, buffer, visited, nextId, gst_wrap_thread(t->parent)); |                     err = gst_serialize_impl(vm, buffer, visited, nextId, gst_wrap_thread(t->parent)); | ||||||
|                 else |                 else | ||||||
|                     err = gst_serialize_impl(vm, buffer, visited, nextId, gst_wrap_nil()); |                     err = gst_serialize_impl(vm, buffer, visited, nextId, gst_wrap_nil()); | ||||||
|  |                 if (t->errorParent) | ||||||
|  |                     err = gst_serialize_impl(vm, buffer, visited, nextId, | ||||||
|  | 							gst_wrap_thread(t->errorParent)); | ||||||
|  |                 else | ||||||
|  |                     err = gst_serialize_impl(vm, buffer, visited, nextId, gst_wrap_nil()); | ||||||
|                 if (err != NULL) return err; |                 if (err != NULL) return err; | ||||||
|                 /* Write the status byte */ |                 /* Write the status byte */ | ||||||
|                 write_byte(t->status); |                 write_byte(t->status); | ||||||
|   | |||||||
							
								
								
									
										31
									
								
								core/stl.c
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								core/stl.c
									
									
									
									
									
								
							| @@ -446,9 +446,21 @@ int gst_stl_string(Gst *vm) { | |||||||
| int gst_stl_thread(Gst *vm) { | int gst_stl_thread(Gst *vm) { | ||||||
|     GstThread *t; |     GstThread *t; | ||||||
|     GstValue callee = gst_arg(vm, 0); |     GstValue callee = gst_arg(vm, 0); | ||||||
|  |     GstValue parent = gst_arg(vm, 1); | ||||||
|  |     GstValue errorParent = gst_arg(vm, 2); | ||||||
|  |     t = gst_thread(vm, callee, 10); | ||||||
|     if (callee.type != GST_FUNCTION && callee.type != GST_CFUNCTION) |     if (callee.type != GST_FUNCTION && callee.type != GST_CFUNCTION) | ||||||
|         gst_c_throwc(vm, "expected function in thread constructor"); |         gst_c_throwc(vm, "expected function in thread constructor"); | ||||||
|     t = gst_thread(vm, callee, 10); |     if (parent.type == GST_THREAD) { | ||||||
|  |         t->parent = parent.data.thread;     | ||||||
|  |     } else if (parent.type != GST_NIL) { | ||||||
|  |         gst_c_throwc(vm, "expected thread/nil as parent"); | ||||||
|  |     } | ||||||
|  |     if (errorParent.type == GST_THREAD) { | ||||||
|  |         t->errorParent = errorParent.data.thread;     | ||||||
|  |     } else if (errorParent.type != GST_NIL) { | ||||||
|  |         gst_c_throwc(vm, "expected thread/nil as error parent"); | ||||||
|  |     } | ||||||
|     t->parent = vm->thread; |     t->parent = vm->thread; | ||||||
|     gst_c_return(vm, gst_wrap_thread(t)); |     gst_c_return(vm, gst_wrap_thread(t)); | ||||||
| } | } | ||||||
| @@ -669,12 +681,13 @@ int gst_stl_namespace_set(Gst *vm) { | |||||||
|  |  | ||||||
| /* Get the table or struct associated with a given namespace */ | /* Get the table or struct associated with a given namespace */ | ||||||
| int gst_stl_namespace_get(Gst *vm) { | int gst_stl_namespace_get(Gst *vm) { | ||||||
|     GstValue name = gst_arg(vm, 0); |     return gst_callc(vm, gst_stl_get, 2, gst_wrap_table(vm->modules), gst_arg(vm, 0)); | ||||||
|     GstValue check; |     /*GstValue name = gst_arg(vm, 0);*/ | ||||||
|     if (name.type != GST_STRING) |     /*GstValue check;*/ | ||||||
|         gst_c_throwc(vm, "expected string"); |     /*if (name.type != GST_STRING)*/ | ||||||
|     check = gst_table_get(vm->modules, name); |         /*gst_c_throwc(vm, "expected string");*/ | ||||||
|     gst_c_return(vm, check); |     /*check = gst_table_get(vm->modules, name);*/ | ||||||
|  |     /*gst_c_return(vm, check);*/ | ||||||
| } | } | ||||||
|  |  | ||||||
| /***/ | /***/ | ||||||
| @@ -796,7 +809,7 @@ int gst_stl_close(Gst *vm) { | |||||||
| } | } | ||||||
|  |  | ||||||
| /* Functions in the io module */ | /* Functions in the io module */ | ||||||
| static const GstModuleItem const io_dat[] = { | static const GstModuleItem io_dat[] = { | ||||||
|     {"open", gst_stl_open}, |     {"open", gst_stl_open}, | ||||||
|     {"slurp", gst_stl_slurp}, |     {"slurp", gst_stl_slurp}, | ||||||
|     {"read", gst_stl_read}, |     {"read", gst_stl_read}, | ||||||
| @@ -914,7 +927,7 @@ int gst_stl_debugp(Gst *vm) { | |||||||
| /* Bootstraping */ | /* Bootstraping */ | ||||||
| /****/ | /****/ | ||||||
|  |  | ||||||
| static const GstModuleItem const std_module[] = { | static const GstModuleItem std_module[] = { | ||||||
|     /* Arithmetic */ |     /* Arithmetic */ | ||||||
|     {"+", gst_stl_add}, |     {"+", gst_stl_add}, | ||||||
|     {"*", gst_stl_mul}, |     {"*", gst_stl_mul}, | ||||||
|   | |||||||
| @@ -42,6 +42,7 @@ GstThread *gst_thread(Gst *vm, GstValue callee, uint32_t capacity) { | |||||||
|     gst_frame_callee(stack) = callee; |     gst_frame_callee(stack) = callee; | ||||||
|     gst_thread_endframe(vm, thread); |     gst_thread_endframe(vm, thread); | ||||||
|     thread->parent = NULL; /* Need to set parent manually */ |     thread->parent = NULL; /* Need to set parent manually */ | ||||||
|  |     thread->errorParent = NULL; | ||||||
|     return thread; |     return thread; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										15
									
								
								core/util.c
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								core/util.c
									
									
									
									
									
								
							| @@ -237,3 +237,18 @@ GstInteger gst_endrange(GstInteger raw, uint32_t len) { | |||||||
|         return len + raw + 1; |         return len + raw + 1; | ||||||
|     return raw; |     return raw; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | int gst_callc(Gst *vm, GstCFunction fn, int numargs, ...) { | ||||||
|  |     int result, i; | ||||||
|  |     va_list args; | ||||||
|  |     GstValue *stack; | ||||||
|  |     va_start(args, numargs); | ||||||
|  |     stack = gst_thread_beginframe(vm, vm->thread, gst_wrap_cfunction(fn), numargs); | ||||||
|  |     for (i = 0; i < numargs; ++i) { | ||||||
|  |         stack[i] = va_arg(args, GstValue); | ||||||
|  |     } | ||||||
|  |     va_end(args); | ||||||
|  |     result = fn(vm); | ||||||
|  |     gst_thread_popframe(vm, vm->thread); | ||||||
|  |     return result; | ||||||
|  | } | ||||||
|   | |||||||
| @@ -394,9 +394,9 @@ int gst_continue(Gst *vm) { | |||||||
|         /* Handle errors from c functions and vm opcodes */ |         /* Handle errors from c functions and vm opcodes */ | ||||||
|         vm_error: |         vm_error: | ||||||
|             vm->thread->status = GST_THREAD_ERROR; |             vm->thread->status = GST_THREAD_ERROR; | ||||||
|             if (vm->thread->parent == NULL) |             if (vm->thread->errorParent == NULL) | ||||||
|                 return GST_RETURN_ERROR; |                 return GST_RETURN_ERROR; | ||||||
|             vm->thread = vm->thread->parent; |             vm->thread = vm->thread->errorParent; | ||||||
|             stack = vm->thread->data + vm->thread->count; |             stack = vm->thread->data + vm->thread->count; | ||||||
|             stack[gst_frame_ret(stack)] = vm->ret; |             stack[gst_frame_ret(stack)] = vm->ret; | ||||||
|             pc = gst_frame_pc(stack); |             pc = gst_frame_pc(stack); | ||||||
|   | |||||||
| @@ -1,11 +1,8 @@ | |||||||
| # Define assert | (do | ||||||
| (: assert (fn [x e] (if x x (do (print e) (exit 1))))) | (: assert (fn [x e] (if x x (do (print e) (exit 1))))) | ||||||
|  | (assert (= 10 (+ 1 2 3 4)) "addition") | ||||||
| # Basic Math | (assert (= -8 (- 1 2 3 4)) "subtraction") | ||||||
| (assert (= 10 (+ 1 2 3 4), "addition") | (assert (= 24 (* 1 2 3 4)) "multiplication") | ||||||
| (assert (= -8 (- 1 2 3 4), "subtraction") | (assert (= 0.1 (/ 1.0 10)) "division") | ||||||
| (assert (= 24 (* 1 2 3 4), "multiplication") |  | ||||||
| (assert (= 0.1 (/ 1 10), "division") |  | ||||||
|  |  | ||||||
| # All good |  | ||||||
| (exit 0) | (exit 0) | ||||||
|  | ) | ||||||
|   | |||||||
| @@ -24,6 +24,7 @@ | |||||||
| #define GST_H_defined | #define GST_H_defined | ||||||
|  |  | ||||||
| #include <stdint.h> | #include <stdint.h> | ||||||
|  | #include <stdarg.h> | ||||||
|  |  | ||||||
| /* String utils */ | /* String utils */ | ||||||
| #define gst_string_raw(s) ((uint32_t *)(s) - 2) | #define gst_string_raw(s) ((uint32_t *)(s) - 2) | ||||||
| @@ -206,6 +207,7 @@ struct GstThread { | |||||||
|     uint32_t capacity; |     uint32_t capacity; | ||||||
|     GstValue *data; |     GstValue *data; | ||||||
|     GstThread *parent; |     GstThread *parent; | ||||||
|  |     GstThread *errorParent; | ||||||
|     enum { |     enum { | ||||||
|         GST_THREAD_PENDING = 0, |         GST_THREAD_PENDING = 0, | ||||||
|         GST_THREAD_ALIVE, |         GST_THREAD_ALIVE, | ||||||
| @@ -490,10 +492,13 @@ uint32_t gst_count_args(Gst *vm); | |||||||
| /* C Api */ | /* C Api */ | ||||||
| /****/ | /****/ | ||||||
|  |  | ||||||
| void gst_module(Gst *vm, const char *packagename, const GstModuleItem *mod); | void gst_module(Gst *vm, const char *name, const GstModuleItem *mod); | ||||||
| void gst_module_mutable(Gst *vm, const char *packagename, const GstModuleItem *mod); | void gst_module_mutable(Gst *vm, const char *name, const GstModuleItem *mod); | ||||||
|  | void gst_module_put(Gst *vm, const char *packagename, const char *name, GstValue x); | ||||||
| GstValue gst_module_get(Gst *vm, const char *packagename); | GstValue gst_module_get(Gst *vm, const char *packagename); | ||||||
| void gst_module_put(Gst *vm, const char *packagename, const char *name, GstValue v); | void gst_register_put(Gst *vm, const char *packagename, GstValue mod); | ||||||
|  | GstValue gst_register_get(Gst *vm, const char *name); | ||||||
|  | int gst_callc(Gst *vm, GstCFunction fn, int numargs, ...); | ||||||
|  |  | ||||||
| /* Wrap data in GstValue */ | /* Wrap data in GstValue */ | ||||||
| GstValue gst_wrap_nil(); | GstValue gst_wrap_nil(); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Calvin Rose
					Calvin Rose