mirror of
https://github.com/janet-lang/janet
synced 2024-12-24 23:40:27 +00:00
Work on more fixes to calling convention
This commit is contained in:
parent
3274e87a45
commit
84b7e96921
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");
|
||||||
|
80
thread.c
80
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,42 +139,9 @@ 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:
|
|
||||||
if (!recurCount) {
|
|
||||||
return NULL;
|
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);
|
||||||
|
128
vm.c
128
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,6 +389,7 @@ 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 */
|
||||||
|
if (!isTCall)
|
||||||
gst_frame_pc(oldStack) = pc + offset + arity;
|
gst_frame_pc(oldStack) = pc + offset + arity;
|
||||||
pc = temp.data.function->def->byteCode;
|
pc = temp.data.function->def->byteCode;
|
||||||
} else {
|
} else {
|
||||||
@ -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;
|
||||||
}
|
}
|
||||||
@ -434,30 +445,61 @@ 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 */
|
||||||
GstValue gst_arg(Gst *vm, uint16_t index) {
|
GstValue gst_arg(Gst *vm, uint16_t index) {
|
||||||
GstValue *stack = gst_thread_stack(vm->thread);
|
GstValue *stack = gst_thread_stack(vm->thread);
|
||||||
|
Loading…
Reference in New Issue
Block a user