mirror of
				https://github.com/janet-lang/janet
				synced 2025-10-30 23:23:07 +00:00 
			
		
		
		
	Work on more fixes to calling convention
This commit is contained in:
		
							
								
								
									
										3
									
								
								parse.c
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								parse.c
									
									
									
									
									
								
							| @@ -388,7 +388,6 @@ static int form_state(GstParser *p, uint8_t c) { | |||||||
| static void dispatch_char(GstParser *p, uint8_t c) { | static void dispatch_char(GstParser *p, uint8_t c) { | ||||||
|     int done = 0; |     int done = 0; | ||||||
|     ++p->index; |     ++p->index; | ||||||
|  |  | ||||||
|     /* Handle comments */ |     /* Handle comments */ | ||||||
|     if (p->flags & GST_PARSER_FLAG_INCOMMENT) { |     if (p->flags & GST_PARSER_FLAG_INCOMMENT) { | ||||||
|         if (c == '\n') { |         if (c == '\n') { | ||||||
| @@ -405,7 +404,7 @@ static void dispatch_char(GstParser *p, uint8_t c) { | |||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |     /* Dispatch character to state */ | ||||||
|     while (!done && p->status == GST_PARSER_PENDING) { |     while (!done && p->status == GST_PARSER_PENDING) { | ||||||
|         GstParseState *top = parser_peek(p); |         GstParseState *top = parser_peek(p); | ||||||
|         switch (top->type) { |         switch (top->type) { | ||||||
|   | |||||||
| @@ -4,3 +4,9 @@ | |||||||
| 	(a 2) | 	(a 2) | ||||||
| 	(a 3) | 	(a 3) | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | # Run call-for-each test | ||||||
|  |  | ||||||
|  | (call-for-each print 1 2 3 4) | ||||||
|  |  | ||||||
|  | (call-for-each (fn [a] (print a "hi")) 1 2 3 45) | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								stl.c
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								stl.c
									
									
									
									
									
								
							| @@ -46,6 +46,7 @@ int gst_stl_callforeach(Gst *vm) { | |||||||
|     if (argCount) { |     if (argCount) { | ||||||
|         for (i = 1; i < argCount; ++i) |         for (i = 1; i < argCount; ++i) | ||||||
|             gst_call(vm, func, 1, vm->thread->data + vm->thread->count + i); |             gst_call(vm, func, 1, vm->thread->data + vm->thread->count + i); | ||||||
|  |         vm->ret.type = GST_NIL; | ||||||
|         return GST_RETURN_OK; |         return GST_RETURN_OK; | ||||||
|     } else { |     } else { | ||||||
|         gst_c_throwc(vm, "expected at least one argument"); |         gst_c_throwc(vm, "expected at least one argument"); | ||||||
|   | |||||||
							
								
								
									
										84
									
								
								thread.c
									
									
									
									
									
								
							
							
						
						
									
										84
									
								
								thread.c
									
									
									
									
									
								
							| @@ -19,10 +19,10 @@ GstThread *gst_thread(Gst *vm, GstValue callee, uint32_t capacity) { | |||||||
| 	gst_frame_prevsize(stack) = 0; | 	gst_frame_prevsize(stack) = 0; | ||||||
| 	gst_frame_ret(stack) = 0; | 	gst_frame_ret(stack) = 0; | ||||||
| 	gst_frame_errloc(stack) = 0; | 	gst_frame_errloc(stack) = 0; | ||||||
| 	gst_frame_callee(stack) = callee; |  | ||||||
| 	gst_frame_pc(stack) = NULL; | 	gst_frame_pc(stack) = NULL; | ||||||
| 	gst_frame_env(stack) = NULL; | 	gst_frame_env(stack) = NULL; | ||||||
| 	gst_frame_errjmp(stack) = NULL; | 	gst_frame_errjmp(stack) = NULL; | ||||||
|  |     gst_thread_expand_callable(vm, thread, callee); | ||||||
| 	gst_thread_endframe(vm, thread); | 	gst_thread_endframe(vm, thread); | ||||||
|     return thread; |     return thread; | ||||||
| } | } | ||||||
| @@ -83,10 +83,49 @@ void gst_thread_tuplepack(Gst *vm, GstThread *thread, uint32_t n) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* Expand a callee on the stack frame to its delegate function. This means that | ||||||
|  |  * objects and userdata that have a "call" attribut in their class will be | ||||||
|  |  * replaced with their delegate function. Call this before pushing any | ||||||
|  |  * arguments to the stack. Returns the new stack. */ | ||||||
|  | GstValue *gst_thread_expand_callable(Gst *vm, GstThread *thread, GstValue callee) { | ||||||
|  |     uint32_t i; | ||||||
|  |     GstValue *stack; | ||||||
|  |     GstObject *meta; | ||||||
|  |     for (i = 0; i < 200; ++i) { | ||||||
|  |         switch(callee.type) { | ||||||
|  |             default: | ||||||
|  |                 return NULL; | ||||||
|  |             case GST_FUNCTION: | ||||||
|  |                 stack = thread->data + thread->count; | ||||||
|  |                 gst_frame_callee(stack) = callee; | ||||||
|  |                 gst_frame_pc(stack) = callee.data.function->def->byteCode; | ||||||
|  |                 return stack; | ||||||
|  |             case GST_CFUNCTION: | ||||||
|  |                 stack = thread->data + thread->count; | ||||||
|  |                 gst_frame_callee(stack) = callee; | ||||||
|  |                 gst_frame_pc(stack) = NULL; | ||||||
|  |                 return stack; | ||||||
|  |             case GST_OBJECT: | ||||||
|  |                 meta = callee.data.object->meta; | ||||||
|  |                 if (meta == NULL) return NULL; | ||||||
|  |                 gst_thread_push(vm, thread, callee); | ||||||
|  |                 callee = gst_object_get_cstring(meta, "call"); | ||||||
|  |                 continue; | ||||||
|  |             case GST_USERDATA: | ||||||
|  |                 meta = ((GstUserdataHeader *)callee.data.pointer - 1)->meta; | ||||||
|  |                 gst_thread_push(vm, thread, callee); | ||||||
|  |                 callee = gst_object_get_cstring(meta, "call"); | ||||||
|  |                 continue; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     /* Callables nested to deeply */ | ||||||
|  |     return NULL; | ||||||
|  | } | ||||||
|  |  | ||||||
| /* Push a stack frame to a thread, with space for arity arguments. Returns the new | /* Push a stack frame to a thread, with space for arity arguments. Returns the new | ||||||
|  * stack. */ |  * stack. */ | ||||||
| GstValue *gst_thread_beginframe(Gst *vm, GstThread *thread, GstValue callee, uint32_t arity) { | GstValue *gst_thread_beginframe(Gst *vm, GstThread *thread, GstValue callee, uint32_t arity) { | ||||||
|     uint32_t frameOffset, recurCount; |     uint32_t frameOffset; | ||||||
|     GstValue *oldStack, *newStack; |     GstValue *oldStack, *newStack; | ||||||
|  |  | ||||||
| 	/* Push the frame */ | 	/* Push the frame */ | ||||||
| @@ -100,43 +139,10 @@ GstValue *gst_thread_beginframe(Gst *vm, GstThread *thread, GstValue callee, uin | |||||||
| 	gst_frame_size(newStack) = 0; | 	gst_frame_size(newStack) = 0; | ||||||
| 	thread->count += frameOffset;  | 	thread->count += frameOffset;  | ||||||
|  |  | ||||||
|     /* Get the true callee of next stack frame */ |     /* Get real callable */ | ||||||
|     recurCount = 200; |     if (gst_thread_expand_callable(vm, thread, callee) == NULL) | ||||||
|     recur: |         return NULL; | ||||||
|     if (!recurCount) { |      | ||||||
|        return NULL; |  | ||||||
|     } |  | ||||||
| 	switch(callee.type) { |  | ||||||
| 	default: return NULL; |  | ||||||
| 	case GST_FUNCTION: |  | ||||||
|     	gst_frame_callee(newStack) = callee; |  | ||||||
|     	gst_frame_pc(newStack) = callee.data.function->def->byteCode; |  | ||||||
|     	break; |  | ||||||
| 	case GST_CFUNCTION: |  | ||||||
|     	gst_frame_callee(newStack) = callee; |  | ||||||
|     	gst_frame_pc(newStack) = NULL; |  | ||||||
|         break; |  | ||||||
| 	case GST_OBJECT: |  | ||||||
| 		{ |  | ||||||
| 			GstObject *meta = callee.data.object->meta; |  | ||||||
| 			if (meta == NULL) return NULL; |  | ||||||
| 			gst_thread_push(vm, thread, callee); |  | ||||||
| 			callee = gst_object_get_cstring(meta, "call"); |  | ||||||
| 			newStack = thread->data + thread->count; |  | ||||||
| 			--recurCount; |  | ||||||
| 			goto recur; |  | ||||||
| 		} |  | ||||||
| 	case GST_USERDATA: |  | ||||||
| 		{ |  | ||||||
| 			GstObject *meta = ((GstUserdataHeader *)callee.data.pointer - 1)->meta; |  | ||||||
| 			gst_thread_push(vm, thread, callee); |  | ||||||
| 			callee = gst_object_get_cstring(meta, "call"); |  | ||||||
| 			newStack = thread->data + thread->count; |  | ||||||
| 			--recurCount; |  | ||||||
| 			goto recur; |  | ||||||
| 		} |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| 	/* Ensure the extra space and initialize to nil */ | 	/* Ensure the extra space and initialize to nil */ | ||||||
|     gst_thread_pushnil(vm, thread, arity); |     gst_thread_pushnil(vm, thread, arity); | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										6
									
								
								thread.h
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								thread.h
									
									
									
									
									
								
							| @@ -21,6 +21,12 @@ void gst_thread_pushnil(Gst *vm, GstThread *thread, uint32_t n); | |||||||
| /* Package up extra args after and including n into tuple at n*/ | /* Package up extra args after and including n into tuple at n*/ | ||||||
| void gst_thread_tuplepack(Gst *vm, GstThread *thread, uint32_t n);  | void gst_thread_tuplepack(Gst *vm, GstThread *thread, uint32_t n);  | ||||||
|  |  | ||||||
|  | /* Expand a callee on the stack frame to its delegate function. This means that | ||||||
|  |  * objects and userdata that have a "call" attribut in their class will be | ||||||
|  |  * replaced with their delegate function. Call this before pushing any | ||||||
|  |  * arguments to the stack. Returns the new stack. */ | ||||||
|  | GstValue *gst_thread_expand_callable(Gst *vm, GstThread *thread, GstValue callee); | ||||||
|  |  | ||||||
| /* Push a stack frame to a thread, with space for arity arguments. Returns the new | /* Push a stack frame to a thread, with space for arity arguments. Returns the new | ||||||
|  * stack. */ |  * stack. */ | ||||||
| GstValue *gst_thread_beginframe(Gst *vm, GstThread *thread, GstValue callee, uint32_t arity);  | GstValue *gst_thread_beginframe(Gst *vm, GstThread *thread, GstValue callee, uint32_t arity);  | ||||||
|   | |||||||
							
								
								
									
										134
									
								
								vm.c
									
									
									
									
									
								
							
							
						
						
									
										134
									
								
								vm.c
									
									
									
									
									
								
							| @@ -66,7 +66,7 @@ static int gst_continue_size(Gst *vm, uint32_t stackBase) { | |||||||
|             temp.data.number = v1.data.number op v2.data.number; \ |             temp.data.number = v1.data.number op v2.data.number; \ | ||||||
|             stack[pc[1]] = temp; \ |             stack[pc[1]] = temp; \ | ||||||
|             pc += 4; \ |             pc += 4; \ | ||||||
|             break; |             continue; | ||||||
|  |  | ||||||
|         case GST_OP_ADD: /* Addition */ |         case GST_OP_ADD: /* Addition */ | ||||||
|             OP_BINARY_MATH(+) |             OP_BINARY_MATH(+) | ||||||
| @@ -87,7 +87,7 @@ static int gst_continue_size(Gst *vm, uint32_t stackBase) { | |||||||
|             temp.data.boolean = !gst_truthy(stack[pc[2]]); |             temp.data.boolean = !gst_truthy(stack[pc[2]]); | ||||||
|             stack[pc[1]] = temp; |             stack[pc[1]] = temp; | ||||||
|             pc += 3; |             pc += 3; | ||||||
|             break; |             continue; | ||||||
|  |  | ||||||
|         case GST_OP_NEG: /* Unary negation */ |         case GST_OP_NEG: /* Unary negation */ | ||||||
|             v1 = stack[pc[2]]; |             v1 = stack[pc[2]]; | ||||||
| @@ -96,7 +96,7 @@ static int gst_continue_size(Gst *vm, uint32_t stackBase) { | |||||||
|             temp.data.number = -v1.data.number; |             temp.data.number = -v1.data.number; | ||||||
|             stack[pc[1]] = temp; |             stack[pc[1]] = temp; | ||||||
|             pc += 3; |             pc += 3; | ||||||
|             break; |             continue; | ||||||
|  |  | ||||||
|         case GST_OP_INV: /* Unary multiplicative inverse */ |         case GST_OP_INV: /* Unary multiplicative inverse */ | ||||||
|             v1 = stack[pc[2]]; |             v1 = stack[pc[2]]; | ||||||
| @@ -105,34 +105,34 @@ static int gst_continue_size(Gst *vm, uint32_t stackBase) { | |||||||
|             temp.data.number = 1 / v1.data.number; |             temp.data.number = 1 / v1.data.number; | ||||||
|             stack[pc[1]] = temp; |             stack[pc[1]] = temp; | ||||||
|             pc += 3; |             pc += 3; | ||||||
|             break; |             continue; | ||||||
|  |  | ||||||
|         case GST_OP_FLS: /* Load False */ |         case GST_OP_FLS: /* Load False */ | ||||||
|             temp.type = GST_BOOLEAN; |             temp.type = GST_BOOLEAN; | ||||||
|             temp.data.boolean = 0; |             temp.data.boolean = 0; | ||||||
|             stack[pc[1]] = temp; |             stack[pc[1]] = temp; | ||||||
|             pc += 2; |             pc += 2; | ||||||
|             break; |             continue; | ||||||
|  |  | ||||||
|         case GST_OP_TRU: /* Load True */ |         case GST_OP_TRU: /* Load True */ | ||||||
|             temp.type = GST_BOOLEAN; |             temp.type = GST_BOOLEAN; | ||||||
|             temp.data.boolean = 1; |             temp.data.boolean = 1; | ||||||
|             stack[pc[1]] = temp; |             stack[pc[1]] = temp; | ||||||
|             pc += 2; |             pc += 2; | ||||||
|             break; |             continue; | ||||||
|  |  | ||||||
|         case GST_OP_NIL: /* Load Nil */ |         case GST_OP_NIL: /* Load Nil */ | ||||||
|             temp.type = GST_NIL; |             temp.type = GST_NIL; | ||||||
|             stack[pc[1]] = temp; |             stack[pc[1]] = temp; | ||||||
|             pc += 2; |             pc += 2; | ||||||
|             break; |             continue; | ||||||
|  |  | ||||||
|         case GST_OP_I16: /* Load Small Integer */ |         case GST_OP_I16: /* Load Small Integer */ | ||||||
|             temp.type = GST_NUMBER; |             temp.type = GST_NUMBER; | ||||||
|             temp.data.number = ((int16_t *)(pc))[2]; |             temp.data.number = ((int16_t *)(pc))[2]; | ||||||
|             stack[pc[1]] = temp; |             stack[pc[1]] = temp; | ||||||
|             pc += 3; |             pc += 3; | ||||||
|             break; |             continue; | ||||||
|  |  | ||||||
|         case GST_OP_UPV: /* Load Up Value */ |         case GST_OP_UPV: /* Load Up Value */ | ||||||
|         case GST_OP_SUV: /* Set Up Value */ |         case GST_OP_SUV: /* Set Up Value */ | ||||||
| @@ -163,7 +163,7 @@ static int gst_continue_size(Gst *vm, uint32_t stackBase) { | |||||||
|                 } |                 } | ||||||
|                 pc += 4; |                 pc += 4; | ||||||
|             } |             } | ||||||
|             break; |             continue; | ||||||
|  |  | ||||||
|         case GST_OP_JIF: /* Jump If */ |         case GST_OP_JIF: /* Jump If */ | ||||||
|             if (gst_truthy(stack[pc[1]])) { |             if (gst_truthy(stack[pc[1]])) { | ||||||
| @@ -171,11 +171,11 @@ static int gst_continue_size(Gst *vm, uint32_t stackBase) { | |||||||
|             } else { |             } else { | ||||||
|                 pc += *((int32_t *)(pc + 2)); |                 pc += *((int32_t *)(pc + 2)); | ||||||
|             } |             } | ||||||
|             break; |             continue; | ||||||
|  |  | ||||||
|         case GST_OP_JMP: /* Jump */ |         case GST_OP_JMP: /* Jump */ | ||||||
|             pc += *((int32_t *)(pc + 1)); |             pc += *((int32_t *)(pc + 1)); | ||||||
|             break; |             continue; | ||||||
|  |  | ||||||
|         case GST_OP_CST: /* Load constant value */ |         case GST_OP_CST: /* Load constant value */ | ||||||
|             v1 = gst_frame_callee(stack); |             v1 = gst_frame_callee(stack); | ||||||
| @@ -184,26 +184,26 @@ static int gst_continue_size(Gst *vm, uint32_t stackBase) { | |||||||
|                 gst_error(vm, GST_NO_UPVALUE); |                 gst_error(vm, GST_NO_UPVALUE); | ||||||
|             stack[pc[1]] = v1.data.function->def->literals[pc[2]]; |             stack[pc[1]] = v1.data.function->def->literals[pc[2]]; | ||||||
|             pc += 3; |             pc += 3; | ||||||
|             break; |             continue; | ||||||
|  |  | ||||||
|         case GST_OP_I32: /* Load 32 bit integer */ |         case GST_OP_I32: /* Load 32 bit integer */ | ||||||
|             temp.type = GST_NUMBER; |             temp.type = GST_NUMBER; | ||||||
|             temp.data.number = *((int32_t *)(pc + 2)); |             temp.data.number = *((int32_t *)(pc + 2)); | ||||||
|             stack[pc[1]] = temp; |             stack[pc[1]] = temp; | ||||||
|             pc += 4; |             pc += 4; | ||||||
|             break; |             continue; | ||||||
|  |  | ||||||
|         case GST_OP_F64: /* Load 64 bit float */ |         case GST_OP_F64: /* Load 64 bit float */ | ||||||
|             temp.type = GST_NUMBER; |             temp.type = GST_NUMBER; | ||||||
|             temp.data.number = (GstNumber) *((double *)(pc + 2)); |             temp.data.number = (GstNumber) *((double *)(pc + 2)); | ||||||
|             stack[pc[1]] = temp; |             stack[pc[1]] = temp; | ||||||
|             pc += 6; |             pc += 6; | ||||||
|             break; |             continue; | ||||||
|  |  | ||||||
|         case GST_OP_MOV: /* Move Values */ |         case GST_OP_MOV: /* Move Values */ | ||||||
|             stack[pc[1]] = stack[pc[2]]; |             stack[pc[1]] = stack[pc[2]]; | ||||||
|             pc += 3; |             pc += 3; | ||||||
|             break; |             continue; | ||||||
|  |  | ||||||
|         case GST_OP_CLN: /* Create closure from constant FuncDef */ |         case GST_OP_CLN: /* Create closure from constant FuncDef */ | ||||||
|             { |             { | ||||||
| @@ -239,21 +239,21 @@ static int gst_continue_size(Gst *vm, uint32_t stackBase) { | |||||||
|             temp.data.boolean = gst_equals(stack[pc[2]], stack[pc[3]]); |             temp.data.boolean = gst_equals(stack[pc[2]], stack[pc[3]]); | ||||||
|             stack[pc[1]] = temp; |             stack[pc[1]] = temp; | ||||||
|             pc += 4; |             pc += 4; | ||||||
|             break; |             continue; | ||||||
|  |  | ||||||
|         case GST_OP_LTN: /* Less Than */ |         case GST_OP_LTN: /* Less Than */ | ||||||
|             temp.type = GST_BOOLEAN; |             temp.type = GST_BOOLEAN; | ||||||
|             temp.data.boolean = (gst_compare(stack[pc[2]], stack[pc[3]]) == -1); |             temp.data.boolean = (gst_compare(stack[pc[2]], stack[pc[3]]) == -1); | ||||||
|             stack[pc[1]] = temp; |             stack[pc[1]] = temp; | ||||||
|             pc += 4; |             pc += 4; | ||||||
|             break; |             continue; | ||||||
|  |  | ||||||
|         case GST_OP_LTE: /* Less Than or Equal to */ |         case GST_OP_LTE: /* Less Than or Equal to */ | ||||||
|             temp.type = GST_BOOLEAN; |             temp.type = GST_BOOLEAN; | ||||||
|             temp.data.boolean = (gst_compare(stack[pc[2]], stack[pc[3]]) != 1); |             temp.data.boolean = (gst_compare(stack[pc[2]], stack[pc[3]]) != 1); | ||||||
|             stack[pc[1]] = temp; |             stack[pc[1]] = temp; | ||||||
|             pc += 4; |             pc += 4; | ||||||
|             break; |             continue; | ||||||
|  |  | ||||||
|         case GST_OP_ARR: /* Array literal */ |         case GST_OP_ARR: /* Array literal */ | ||||||
|             { |             { | ||||||
| @@ -309,8 +309,8 @@ static int gst_continue_size(Gst *vm, uint32_t stackBase) { | |||||||
|                 if (err != NULL) |                 if (err != NULL) | ||||||
|                     gst_error(vm, err); |                     gst_error(vm, err); | ||||||
|                 pc += 4; |                 pc += 4; | ||||||
|                 break; |  | ||||||
|             } |             } | ||||||
|  |             continue; | ||||||
|  |  | ||||||
|         case GST_OP_SET: /* Associative set */ |         case GST_OP_SET: /* Associative set */ | ||||||
|             { |             { | ||||||
| @@ -319,8 +319,8 @@ static int gst_continue_size(Gst *vm, uint32_t stackBase) { | |||||||
|                 if (err != NULL) |                 if (err != NULL) | ||||||
|                     gst_error(vm, err); |                     gst_error(vm, err); | ||||||
|                 pc += 4; |                 pc += 4; | ||||||
|                 break; |  | ||||||
|             } |             } | ||||||
|  |             break; | ||||||
|  |  | ||||||
|         case GST_OP_ERR: /* Throw error */ |         case GST_OP_ERR: /* Throw error */ | ||||||
|             vm->ret = stack[pc[1]]; |             vm->ret = stack[pc[1]]; | ||||||
| @@ -330,40 +330,45 @@ static int gst_continue_size(Gst *vm, uint32_t stackBase) { | |||||||
|             gst_frame_errloc(stack) = pc[1]; |             gst_frame_errloc(stack) = pc[1]; | ||||||
|             gst_frame_errjmp(stack) = pc + *(uint32_t *)(pc + 2); |             gst_frame_errjmp(stack) = pc + *(uint32_t *)(pc + 2); | ||||||
|             pc += 4; |             pc += 4; | ||||||
|             break; |             continue; | ||||||
|  |  | ||||||
|         case GST_OP_UTY: /* End try block */ |         case GST_OP_UTY: /* End try block */ | ||||||
|             gst_frame_errjmp(stack) = NULL; |             gst_frame_errjmp(stack) = NULL; | ||||||
|             pc++; |             pc++; | ||||||
|             break; |             continue; | ||||||
|  |  | ||||||
|         case GST_OP_RTN: /* Return nil */ |         case GST_OP_RTN: /* Return nil */ | ||||||
|             stack = gst_thread_popframe(vm, &thread); |             stack = gst_thread_popframe(vm, &thread); | ||||||
|             if (thread.count < stackBase) { |             if (thread.count < stackBase) { | ||||||
|                 vm->ret.type = GST_NIL; |                 vm->ret.type = GST_NIL; | ||||||
|  |                 GST_STATE_WRITE(); | ||||||
|                 return GST_RETURN_OK; |                 return GST_RETURN_OK; | ||||||
|             } |             } | ||||||
|  |             pc = gst_frame_pc(stack); | ||||||
|             stack[gst_frame_ret(stack)].type = GST_NIL; |             stack[gst_frame_ret(stack)].type = GST_NIL; | ||||||
|             break; |             continue; | ||||||
|  |  | ||||||
|         case GST_OP_RET: /* Return */ |         case GST_OP_RET: /* Return */ | ||||||
|         	temp = stack[pc[1]]; |         	temp = stack[pc[1]]; | ||||||
|             stack = gst_thread_popframe(vm, &thread); |             stack = gst_thread_popframe(vm, &thread); | ||||||
|             if (thread.count < stackBase) { |             if (thread.count < stackBase) { | ||||||
|                 vm->ret = temp; |                 vm->ret = temp; | ||||||
|  |                 GST_STATE_WRITE(); | ||||||
|                 return GST_RETURN_OK; |                 return GST_RETURN_OK; | ||||||
|             } |             } | ||||||
|  |             pc = gst_frame_pc(stack); | ||||||
|             stack[gst_frame_ret(stack)] = temp; |             stack[gst_frame_ret(stack)] = temp; | ||||||
|             break; |             continue; | ||||||
|  |  | ||||||
|         case GST_OP_CAL: /* Call */ |         case GST_OP_CAL: /* Call */ | ||||||
|         case GST_OP_TCL: /* Tail call */ |         case GST_OP_TCL: /* Tail call */ | ||||||
|         	{ |         	{ | ||||||
|             	GstValue *oldStack; |             	GstValue *oldStack; | ||||||
|             	temp = stack[pc[1]]; |             	temp = stack[pc[1]]; | ||||||
|  |                 int isTCall = *pc == GST_OP_TCL; | ||||||
|             	uint32_t i, arity, offset, size; |             	uint32_t i, arity, offset, size; | ||||||
|             	uint16_t ret = pc[2]; |             	uint16_t ret = pc[2]; | ||||||
|             	offset = (*pc == GST_OP_CAL) ? 4 : 3; |             	offset = isTCall ? 3 : 4; | ||||||
| 				arity = pc[offset - 1]; | 				arity = pc[offset - 1]; | ||||||
| 				/* Push new frame */ | 				/* Push new frame */ | ||||||
| 				stack = gst_thread_beginframe(vm, &thread, temp, arity); | 				stack = gst_thread_beginframe(vm, &thread, temp, arity); | ||||||
| @@ -375,7 +380,7 @@ static int gst_continue_size(Gst *vm, uint32_t stackBase) { | |||||||
|     			/* Finish new frame */ |     			/* Finish new frame */ | ||||||
| 				gst_thread_endframe(vm, &thread); | 				gst_thread_endframe(vm, &thread); | ||||||
| 				/* Check tail call - if so, replace frame. */ | 				/* Check tail call - if so, replace frame. */ | ||||||
| 				if (*pc == GST_OP_TCL) { | 				if (isTCall) { | ||||||
| 					stack = gst_thread_tail(vm, &thread); | 					stack = gst_thread_tail(vm, &thread); | ||||||
| 				} else { | 				} else { | ||||||
| 					gst_frame_ret(oldStack) = ret; | 					gst_frame_ret(oldStack) = ret; | ||||||
| @@ -384,7 +389,8 @@ static int gst_continue_size(Gst *vm, uint32_t stackBase) { | |||||||
| 				temp = gst_frame_callee(stack); | 				temp = gst_frame_callee(stack); | ||||||
| 				if (temp.type == GST_FUNCTION) { | 				if (temp.type == GST_FUNCTION) { | ||||||
|     				/* Save pc and set new pc */ |     				/* Save pc and set new pc */ | ||||||
|     				gst_frame_pc(oldStack) = pc + offset + arity; |                     if (!isTCall) | ||||||
|  |                         gst_frame_pc(oldStack) = pc + offset + arity; | ||||||
|     				pc = temp.data.function->def->byteCode; |     				pc = temp.data.function->def->byteCode; | ||||||
| 				} else { | 				} else { | ||||||
| 					int status; | 					int status; | ||||||
| @@ -393,12 +399,17 @@ static int gst_continue_size(Gst *vm, uint32_t stackBase) { | |||||||
| 					status = temp.data.cfunction(vm); | 					status = temp.data.cfunction(vm); | ||||||
| 					GST_STATE_SYNC(); | 					GST_STATE_SYNC(); | ||||||
| 					stack = gst_thread_popframe(vm, &thread); | 					stack = gst_thread_popframe(vm, &thread); | ||||||
| 					pc += offset + arity; |  | ||||||
| 					if (status == GST_RETURN_OK) | 					if (status == GST_RETURN_OK) | ||||||
|     					if (thread.count < stackBase) |     					if (thread.count < stackBase) { | ||||||
|  |                             GST_STATE_WRITE(); | ||||||
|         					return status; |         					return status; | ||||||
|     					else |                         } else {  | ||||||
|         					stack[gst_frame_ret(stack)] = vm->ret; |         					stack[gst_frame_ret(stack)] = vm->ret; | ||||||
|  |                             if (isTCall) | ||||||
|  |                                 pc = gst_frame_pc(stack); | ||||||
|  |                             else | ||||||
|  |                                 pc += offset + arity; | ||||||
|  |                         } | ||||||
| 					else | 					else | ||||||
|     					goto vm_error; |     					goto vm_error; | ||||||
| 				} | 				} | ||||||
| @@ -416,7 +427,7 @@ static int gst_continue_size(Gst *vm, uint32_t stackBase) { | |||||||
|             stack[gst_frame_errloc(stack)] = vm->ret; |             stack[gst_frame_errloc(stack)] = vm->ret; | ||||||
|             break; |             break; | ||||||
|  |  | ||||||
|       } /* end switch */ |         } /* end switch */ | ||||||
|  |  | ||||||
|         /* TODO: Move collection only to places that allocate memory */ |         /* TODO: Move collection only to places that allocate memory */ | ||||||
|         /* This, however, is good for testing to ensure no memory leaks */ |         /* This, however, is good for testing to ensure no memory leaks */ | ||||||
| @@ -434,28 +445,59 @@ int gst_continue(Gst *vm) { | |||||||
|  |  | ||||||
| /* Run the vm with a given function */ | /* Run the vm with a given function */ | ||||||
| int gst_run(Gst *vm, GstValue callee) { | int gst_run(Gst *vm, GstValue callee) { | ||||||
|     vm->thread = gst_thread(vm, callee, 64); |  | ||||||
|     return gst_continue(vm); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* Call a gst function */ |  | ||||||
| int gst_call(Gst *vm, GstValue callee, uint32_t arity, GstValue *args) { |  | ||||||
|     GstValue *stack; |     GstValue *stack; | ||||||
|     uint32_t i; |     vm->thread = gst_thread(vm, callee, 64); | ||||||
|     stack = gst_thread_beginframe(vm, vm->thread, callee, arity); |     if (vm->thread == NULL) | ||||||
|     for (i = 0; i < arity; ++i)  |         return GST_RETURN_CRASH; | ||||||
|         stack[i] = args[i]; |     stack = gst_thread_stack(vm->thread); | ||||||
|     gst_thread_endframe(vm, vm->thread); |     /* If callee was not actually a function, get the delegate function */ | ||||||
| 	callee = gst_frame_callee(stack); |     callee = gst_frame_callee(stack); | ||||||
| 	if (callee.type == GST_FUNCTION) { |     if (callee.type == GST_CFUNCTION) { | ||||||
|     	return gst_continue(vm); |  | ||||||
| 	} else { |  | ||||||
| 		int status; | 		int status; | ||||||
| 		vm->ret.type = GST_NIL; | 		vm->ret.type = GST_NIL; | ||||||
| 		status = callee.data.cfunction(vm); | 		status = callee.data.cfunction(vm); | ||||||
| 		gst_thread_popframe(vm, vm->thread); | 		gst_thread_popframe(vm, vm->thread); | ||||||
| 		return status; | 		return status; | ||||||
|  |     } else { | ||||||
|  |         return gst_continue(vm); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Call a gst function */ | ||||||
|  | int gst_call(Gst *vm, GstValue callee, uint32_t arity, GstValue *args) { | ||||||
|  |     GstValue *stack; | ||||||
|  |     uint32_t i, size; | ||||||
|  |     int status; | ||||||
|  |  | ||||||
|  |     /* Set the return position */ | ||||||
|  |     stack = gst_thread_stack(vm->thread); | ||||||
|  |     gst_frame_ret(stack) = gst_frame_size(stack); | ||||||
|  |  | ||||||
|  |     /* Add extra space for returning value */ | ||||||
|  |     gst_thread_pushnil(vm, vm->thread, 1); | ||||||
|  |     stack = gst_thread_beginframe(vm, vm->thread, callee, arity); | ||||||
|  |  | ||||||
|  |     /* Write args to stack */ | ||||||
|  |     size = gst_frame_size(stack) - arity;  | ||||||
|  |     for (i = 0; i < arity; ++i)  | ||||||
|  |         stack[i + size] = args[i]; | ||||||
|  |     gst_thread_endframe(vm, vm->thread); | ||||||
|  |  | ||||||
|  |     /* Call function */ | ||||||
|  | 	callee = gst_frame_callee(stack); | ||||||
|  | 	if (callee.type == GST_FUNCTION) { | ||||||
|  |         gst_frame_pc(stack) = callee.data.function->def->byteCode; | ||||||
|  |     	status = gst_continue(vm); | ||||||
|  | 	} else { | ||||||
|  | 		vm->ret.type = GST_NIL; | ||||||
|  | 		status = callee.data.cfunction(vm); | ||||||
|  | 		gst_thread_popframe(vm, vm->thread); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  |     /* Pop the extra nil */ | ||||||
|  |     --gst_frame_size(gst_thread_stack(vm->thread)); | ||||||
|  |  | ||||||
|  |     return status; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Get an argument from the stack */ | /* Get an argument from the stack */ | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Calvin Rose
					Calvin Rose