diff --git a/src/module/io.c b/src/module/io.c index 3300ec40..2355d14c 100644 --- a/src/module/io.c +++ b/src/module/io.c @@ -107,33 +107,18 @@ static void directoryListCallback(uv_fs_t* request) uv_dirent_t entry; - // TODO: Right now, there's no way to create a list using the C API, so - // create a buffer containing all of the result paths terminated by '\0'. - // We'll split that back into a list in Wren. - size_t bufferLength = 0; - size_t bufferCapacity = 1024; - char* buffer = (char*)malloc(bufferCapacity); + WrenVM* vm = getVM(); + wrenEnsureSlots(vm, 3); + wrenSetSlotNewList(vm, 2); while (uv_fs_scandir_next(request, &entry) != UV_EOF) { - size_t length = strlen(entry.name); - - // Grow the buffer if needed. - while (bufferLength + length + 1 > bufferCapacity) - { - bufferCapacity *= 2; - buffer = (char*)realloc(buffer, bufferCapacity); - } - - // Copy the path, including the null terminator. - memcpy(buffer + bufferLength, entry.name, length + 1); - bufferLength += length + 1; + wrenSetSlotString(vm, 1, entry.name); + wrenInsertInList(vm, 2, -1, 1); } schedulerResume(freeRequest(request), true); - wrenSetSlotBytes(getVM(), 2, buffer, bufferLength); schedulerFinishResume(); - free(buffer); } void directoryList(WrenVM* vm) diff --git a/src/module/io.wren b/src/module/io.wren index d641743a..9694d2f9 100644 --- a/src/module/io.wren +++ b/src/module/io.wren @@ -5,28 +5,7 @@ class Directory { if (!(path is String)) Fiber.abort("Path must be a string.") list_(path, Fiber.current) - - // We get back a byte array containing all of the paths, each terminated by - // a zero byte. - var entryBuffer = Scheduler.runNextScheduled_() - - // TODO: Add split() to String. - // Split it into an array of strings. - var entries = [] - var start = 0 - var i = 0 - var bytes = entryBuffer.bytes - while (i < bytes.count) { - if (bytes[i] == 0) { - var entry = entryBuffer[start...i] - start = i + 1 - entries.add(entry) - } - - i = i + 1 - } - - return entries + return Scheduler.runNextScheduled_() } foreign static list_(path, fiber) diff --git a/src/module/io.wren.inc b/src/module/io.wren.inc index 32b62086..770657c9 100644 --- a/src/module/io.wren.inc +++ b/src/module/io.wren.inc @@ -7,28 +7,7 @@ static const char* ioModuleSource = " if (!(path is String)) Fiber.abort(\"Path must be a string.\")\n" "\n" " list_(path, Fiber.current)\n" -"\n" -" // We get back a byte array containing all of the paths, each terminated by\n" -" // a zero byte.\n" -" var entryBuffer = Scheduler.runNextScheduled_()\n" -"\n" -" // TODO: Add split() to String.\n" -" // Split it into an array of strings.\n" -" var entries = []\n" -" var start = 0\n" -" var i = 0\n" -" var bytes = entryBuffer.bytes\n" -" while (i < bytes.count) {\n" -" if (bytes[i] == 0) {\n" -" var entry = entryBuffer[start...i]\n" -" start = i + 1\n" -" entries.add(entry)\n" -" }\n" -"\n" -" i = i + 1\n" -" }\n" -"\n" -" return entries\n" +" return Scheduler.runNextScheduled_()\n" " }\n" "\n" " foreign static list_(path, fiber)\n" diff --git a/src/vm/wren_debug.c b/src/vm/wren_debug.c index 572c826d..2d5d7063 100644 --- a/src/vm/wren_debug.c +++ b/src/vm/wren_debug.c @@ -20,6 +20,9 @@ void wrenDebugPrintStackTrace(ObjFiber* fiber) CallFrame* frame = &fiber->frames[i]; ObjFn* fn = wrenUpwrapClosure(frame->fn); + // Skip over stub functions for calling methods from the C API. + if (fn->module == NULL) continue; + // The built-in core module has no name. We explicitly omit it from stack // traces since we don't want to highlight to a user the implementation // detail of what part of the core module is written in C and what is Wren. diff --git a/src/vm/wren_vm.c b/src/vm/wren_vm.c index f281a62f..2d6f0029 100644 --- a/src/vm/wren_vm.c +++ b/src/vm/wren_vm.c @@ -1311,23 +1311,30 @@ WrenInterpretResult wrenCall(WrenVM* vm, WrenValue* method) ASSERT(vm->fiber->stackTop - vm->fiber->stack >= fn->arity, "Stack must have enough arguments for method."); - callFunction(vm, vm->fiber, (Obj*)fn, fn->arity); + // Discard any extra temporary slots. We take for granted that the stub + // function has exactly one slot for each arguments. + vm->fiber->stackTop = &vm->fiber->stack[fn->maxSlots]; + callFunction(vm, vm->fiber, (Obj*)fn, 0); return runInterpreter(vm, vm->fiber); } WrenValue* wrenCaptureValue(WrenVM* vm, Value value) { + if (IS_OBJ(value)) wrenPushRoot(vm, AS_OBJ(value)); + // Make a handle for it. WrenValue* wrappedValue = ALLOCATE(vm, WrenValue); wrappedValue->value = value; + if (IS_OBJ(value)) wrenPopRoot(vm); + // Add it to the front of the linked list of handles. if (vm->valueHandles != NULL) vm->valueHandles->prev = wrappedValue; wrappedValue->prev = NULL; wrappedValue->next = vm->valueHandles; vm->valueHandles = wrappedValue; - + return wrappedValue; } diff --git a/test/api/call.c b/test/api/call.c index f7d8af8a..d119dde9 100644 --- a/test/api/call.c +++ b/test/api/call.c @@ -73,6 +73,15 @@ void callRunTests(WrenVM* vm) wrenSetSlotBytes(vm, 2, "b\0y\0t\0e", 7); wrenCall(vm, two); + // Call ignores with extra temporary slots on stack. + wrenEnsureSlots(vm, 10); + wrenSetSlotValue(vm, 0, callClass); + for (int i = 1; i < 10; i++) + { + wrenSetSlotDouble(vm, i, i * 0.1); + } + wrenCall(vm, one); + wrenReleaseValue(vm, callClass); wrenReleaseValue(vm, noParams); wrenReleaseValue(vm, zero); diff --git a/test/api/call.wren b/test/api/call.wren index 889a7936..afe8e9e3 100644 --- a/test/api/call.wren +++ b/test/api/call.wren @@ -33,3 +33,4 @@ class Call { // expect: two string another // expect: two null [a, b] // expect: two str [98, 0, 121, 0, 116, 0, 101] +// expect: one 0.1