mirror of
https://github.com/janet-lang/janet
synced 2025-06-10 10:34:13 +00:00
Add initial untested support for varargs in vm
This commit is contained in:
parent
69624495ec
commit
18aaf9480b
@ -723,10 +723,11 @@ static GstFuncDef *compiler_gen_funcdef(GstCompiler *c, uint32_t lastNBytes, uin
|
|||||||
/* Initialize the new FuncDef */
|
/* Initialize the new FuncDef */
|
||||||
def->locals = scope->frameSize;
|
def->locals = scope->frameSize;
|
||||||
def->arity = arity;
|
def->arity = arity;
|
||||||
|
def->flags = 0;
|
||||||
return def;
|
return def;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compile a function from a function literal */
|
/* Compile a function from a function literal source form */
|
||||||
static Slot compile_function(GstCompiler *c, FormOptions opts, GstValue *form) {
|
static Slot compile_function(GstCompiler *c, FormOptions opts, GstValue *form) {
|
||||||
GstScope *scope = c->tail;
|
GstScope *scope = c->tail;
|
||||||
GstBuffer *buffer = c->buffer;
|
GstBuffer *buffer = c->buffer;
|
||||||
|
@ -107,12 +107,16 @@ struct GstObject {
|
|||||||
GstValue meta;
|
GstValue meta;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Some function defintion flags */
|
||||||
|
#define GST_FUNCDEF_FLAG_VARARG 1
|
||||||
|
|
||||||
/* A function defintion. Contains information need to instatiate closures. */
|
/* A function defintion. Contains information need to instatiate closures. */
|
||||||
struct GstFuncDef {
|
struct GstFuncDef {
|
||||||
uint32_t locals;
|
uint32_t locals;
|
||||||
uint32_t arity;
|
uint32_t arity; /* Not including varargs */
|
||||||
uint32_t literalsLen;
|
uint32_t literalsLen;
|
||||||
uint32_t byteCodeLen;
|
uint32_t byteCodeLen;
|
||||||
|
uint32_t flags;
|
||||||
GstValue *literals; /* Contains strings, FuncDefs, etc. */
|
GstValue *literals; /* Contains strings, FuncDefs, etc. */
|
||||||
uint16_t *byteCode;
|
uint16_t *byteCode;
|
||||||
};
|
};
|
||||||
|
66
vm.c
66
vm.c
@ -202,6 +202,9 @@ int gst_start(Gst *vm, GstValue func) {
|
|||||||
|
|
||||||
case GST_OP_CAL: /* Call */
|
case GST_OP_CAL: /* Call */
|
||||||
{
|
{
|
||||||
|
int varArgs;
|
||||||
|
uint32_t expectedArity;
|
||||||
|
uint32_t normalArity;
|
||||||
temp = stack[pc[1]];
|
temp = stack[pc[1]];
|
||||||
uint32_t arity = pc[3];
|
uint32_t arity = pc[3];
|
||||||
uint32_t oldCount = thread.count;
|
uint32_t oldCount = thread.count;
|
||||||
@ -217,8 +220,15 @@ int gst_start(Gst *vm, GstValue func) {
|
|||||||
if (temp.type == GST_FUNCTION) {
|
if (temp.type == GST_FUNCTION) {
|
||||||
GstFunction *fn = temp.data.function;
|
GstFunction *fn = temp.data.function;
|
||||||
locals = fn->def->locals;
|
locals = fn->def->locals;
|
||||||
|
varArgs = fn->def->flags & GST_FUNCDEF_FLAG_VARARG;
|
||||||
|
expectedArity = fn->def->arity;
|
||||||
|
if (arity > expectedArity)
|
||||||
|
normalArity = expectedArity;
|
||||||
|
else
|
||||||
|
normalArity = arity;
|
||||||
} else if (temp.type == GST_CFUNCTION) {
|
} else if (temp.type == GST_CFUNCTION) {
|
||||||
locals = arity;
|
locals = normalArity = expectedArity = arity;
|
||||||
|
varArgs = 0;
|
||||||
} else {
|
} else {
|
||||||
gst_error(vm, GST_EXPECTED_FUNCTION);
|
gst_error(vm, GST_EXPECTED_FUNCTION);
|
||||||
}
|
}
|
||||||
@ -254,9 +264,24 @@ int gst_start(Gst *vm, GstValue func) {
|
|||||||
oldBase = thread.data + oldCount;
|
oldBase = thread.data + oldCount;
|
||||||
|
|
||||||
/* Write arguments to new stack */
|
/* Write arguments to new stack */
|
||||||
for (i = 0; i < arity; ++i)
|
for (i = 0; i < normalArity; ++i)
|
||||||
stack[i] = oldBase[pc[4 + i]];
|
stack[i] = oldBase[pc[4 + i]];
|
||||||
|
|
||||||
|
/* Clear stack */
|
||||||
|
for (; i < locals; ++i)
|
||||||
|
stack[i].type = GST_NIL;
|
||||||
|
|
||||||
|
/* Check for varargs and put them in a tuple */
|
||||||
|
if (varArgs) {
|
||||||
|
GstValue *tuple;
|
||||||
|
uint32_t j;
|
||||||
|
tuple = gst_tuple(vm, arity - expectedArity);
|
||||||
|
for (j = expectedArity; j < arity; ++j)
|
||||||
|
tuple[j - expectedArity] = stack[j];
|
||||||
|
stack[expectedArity].type = GST_TUPLE;
|
||||||
|
stack[expectedArity].data.tuple = tuple;
|
||||||
|
}
|
||||||
|
|
||||||
/* Call the function */
|
/* Call the function */
|
||||||
if (temp.type == GST_CFUNCTION) {
|
if (temp.type == GST_CFUNCTION) {
|
||||||
/* Save current state to vm thread */
|
/* Save current state to vm thread */
|
||||||
@ -265,14 +290,12 @@ int gst_start(Gst *vm, GstValue func) {
|
|||||||
*vm->thread = thread;
|
*vm->thread = thread;
|
||||||
vm->ret.type = GST_NIL;
|
vm->ret.type = GST_NIL;
|
||||||
status = temp.data.cfunction(vm);
|
status = temp.data.cfunction(vm);
|
||||||
v1 = vm->ret;
|
v2 = vm->ret;
|
||||||
if (status == GST_RETURN_OK)
|
if (status == GST_RETURN_OK)
|
||||||
goto ret;
|
goto ret;
|
||||||
else
|
else
|
||||||
goto vm_error;
|
goto vm_error;
|
||||||
} else {
|
} else {
|
||||||
for (; i < locals; ++i)
|
|
||||||
stack[i].type = GST_NIL;
|
|
||||||
pc = temp.data.function->def->byteCode;
|
pc = temp.data.function->def->byteCode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -407,6 +430,9 @@ int gst_start(Gst *vm, GstValue func) {
|
|||||||
|
|
||||||
case GST_OP_TCL: /* Tail call */
|
case GST_OP_TCL: /* Tail call */
|
||||||
{
|
{
|
||||||
|
int varArgs;
|
||||||
|
uint32_t expectedArity;
|
||||||
|
uint32_t normalArity;
|
||||||
temp = stack[pc[1]];
|
temp = stack[pc[1]];
|
||||||
uint32_t arity = pc[2];
|
uint32_t arity = pc[2];
|
||||||
uint16_t locals;
|
uint16_t locals;
|
||||||
@ -425,14 +451,21 @@ int gst_start(Gst *vm, GstValue func) {
|
|||||||
|
|
||||||
/* Get size of new stack frame */
|
/* Get size of new stack frame */
|
||||||
if (temp.type == GST_CFUNCTION) {
|
if (temp.type == GST_CFUNCTION) {
|
||||||
locals = arity;
|
locals = normalArity = expectedArity = arity;
|
||||||
|
varArgs = 0;
|
||||||
} else if (temp.type == GST_FUNCTION) {
|
} else if (temp.type == GST_FUNCTION) {
|
||||||
locals = temp.data.function->def->locals;
|
locals = temp.data.function->def->locals;
|
||||||
|
varArgs = temp.data.function->def->flags & GST_FUNCDEF_FLAG_VARARG;
|
||||||
|
expectedArity = temp.data.function->def->arity;
|
||||||
|
if (arity > expectedArity)
|
||||||
|
normalArity = expectedArity;
|
||||||
|
else
|
||||||
|
normalArity = arity;
|
||||||
} else {
|
} else {
|
||||||
gst_error(vm, GST_EXPECTED_FUNCTION);
|
gst_error(vm, GST_EXPECTED_FUNCTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get enough space for manipulating args */
|
/* Get enough space for manipulating args - at least twice current frame size */
|
||||||
if (arity > frame.size) {
|
if (arity > frame.size) {
|
||||||
workspace = arity;
|
workspace = arity;
|
||||||
} else {
|
} else {
|
||||||
@ -451,20 +484,31 @@ int gst_start(Gst *vm, GstValue func) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Copy the arguments into the extra space */
|
/* Copy the arguments into the extra space */
|
||||||
for (i = 0; i < arity; ++i)
|
for (i = 0; i < normalArity; ++i)
|
||||||
stack[workspace + i] = stack[pc[3 + i]];
|
stack[workspace + i] = stack[pc[3 + i]];
|
||||||
|
|
||||||
/* Copy the end of the stack to the parameter position */
|
/* Copy the end of the stack to the parameter position */
|
||||||
gst_memcpy(stack, stack + workspace, arity * sizeof(GstValue));
|
gst_memcpy(stack, stack + workspace, normalArity * sizeof(GstValue));
|
||||||
|
|
||||||
/* Update the stack frame */
|
/* Update the stack frame */
|
||||||
frame.callee = temp;
|
frame.callee = temp;
|
||||||
frame.size = locals;
|
frame.size = locals;
|
||||||
|
|
||||||
/* Nil the non argument part of the stack for gc */
|
/* Nil the non argument part of the stack for gc */
|
||||||
for (i = arity; i < frame.size; ++i)
|
for (i = normalArity; i < frame.size; ++i)
|
||||||
stack[i].type = GST_NIL;
|
stack[i].type = GST_NIL;
|
||||||
|
|
||||||
|
/* Check for varargs and put them in a tuple */
|
||||||
|
if (varArgs) {
|
||||||
|
GstValue *tuple;
|
||||||
|
uint32_t j;
|
||||||
|
tuple = gst_tuple(vm, arity - expectedArity);
|
||||||
|
for (j = expectedArity; j < arity; ++j)
|
||||||
|
tuple[j - expectedArity] = stack[workspace + j];
|
||||||
|
stack[expectedArity].type = GST_TUPLE;
|
||||||
|
stack[expectedArity].data.tuple = tuple;
|
||||||
|
}
|
||||||
|
|
||||||
/* Call the function */
|
/* Call the function */
|
||||||
if (temp.type == GST_CFUNCTION) {
|
if (temp.type == GST_CFUNCTION) {
|
||||||
/* Save current state to vm thread */
|
/* Save current state to vm thread */
|
||||||
@ -473,7 +517,7 @@ int gst_start(Gst *vm, GstValue func) {
|
|||||||
*vm->thread = thread;
|
*vm->thread = thread;
|
||||||
vm->ret.type = GST_NIL;
|
vm->ret.type = GST_NIL;
|
||||||
status = temp.data.cfunction(vm);
|
status = temp.data.cfunction(vm);
|
||||||
v1 = vm->ret;
|
v2 = vm->ret;
|
||||||
if (status == GST_RETURN_OK)
|
if (status == GST_RETURN_OK)
|
||||||
goto ret;
|
goto ret;
|
||||||
else
|
else
|
||||||
|
Loading…
x
Reference in New Issue
Block a user