feat: expose wrenEnsureSlots API and rename foreignStackStart to apiStack for slot access outside foreign methods

Replace the internal `foreignStackStart` pointer with a public `apiStack` field
that tracks the base of available C API slots. Extract the static
`ensureStack` helper into a non-static `wrenEnsureStack` function declared in
the header, enabling `wrenEnsureSlots()` to create a fiber and stack when
called outside a foreign method. Update `callForeign` to use `apiStack` and
adjust `metaCompile` to write results through the new pointer. Add a
`ensureOutsideForeign` test that allocates slots on a fresh VM, verifies
slot count grows from 0 to 20, and exercises all 20 slots with double values
to confirm the stack is correctly initialized and usable.
This commit is contained in:
Bob Nystrom
2015-12-28 15:43:17 +00:00
parent 278d66bdc1
commit 6abebbe906
7 changed files with 157 additions and 99 deletions
+36 -1
View File
@@ -94,7 +94,41 @@ static void ensure(WrenVM* vm)
{
sum += (int)wrenGetSlotDouble(vm, i);
}
char result[100];
sprintf(result, "%d -> %d (%d)", before, after, sum);
wrenSetSlotString(vm, 0, result);
}
static void ensureOutsideForeign(WrenVM* vm)
{
// To test the behavior outside of a foreign method (which we're currently
// in), create a new separate VM.
WrenConfiguration config;
wrenInitConfiguration(&config);
WrenVM* otherVM = wrenNewVM(&config);
int before = wrenGetSlotCount(otherVM);
wrenEnsureSlots(otherVM, 20);
int after = wrenGetSlotCount(otherVM);
// Use the slots to make sure they're available.
for (int i = 0; i < 20; i++)
{
wrenSetSlotDouble(otherVM, i, i);
}
int sum = 0;
for (int i = 0; i < 20; i++)
{
sum += (int)wrenGetSlotDouble(otherVM, i);
}
wrenFreeVM(otherVM);
char result[100];
sprintf(result, "%d -> %d (%d)", before, after, sum);
wrenSetSlotString(vm, 0, result);
@@ -106,6 +140,7 @@ WrenForeignMethodFn slotsBindMethod(const char* signature)
if (strcmp(signature, "static Slots.getSlots(_,_,_,_,_)") == 0) return getSlots;
if (strcmp(signature, "static Slots.setSlots(_,_,_,_)") == 0) return setSlots;
if (strcmp(signature, "static Slots.ensure()") == 0) return ensure;
if (strcmp(signature, "static Slots.ensureOutsideForeign()") == 0) return ensureOutsideForeign;
return NULL;
}
+10 -3
View File
@@ -3,6 +3,7 @@ class Slots {
foreign static getSlots(bool, num, string, bytes, value)
foreign static setSlots(a, b, c, d)
foreign static ensure()
foreign static ensureOutsideForeign()
}
// If nothing is set in the return slot, it retains its previous value, the
@@ -10,8 +11,14 @@ class Slots {
System.print(Slots.noSet == Slots) // expect: true
var value = ["value"]
System.print(Slots.getSlots(true, "by\0te", 12.34, "str", value) == value) // expect: true
System.print(Slots.getSlots(true, "by\0te", 12.34, "str", value) == value)
// expect: true
System.print(Slots.setSlots(value, 0, 0, 0) == value) // expect: true
System.print(Slots.setSlots(value, 0, 0, 0) == value)
// expect: true
System.print(Slots.ensure()) // expect: 1 -> 20 (190)
System.print(Slots.ensure())
// expect: 1 -> 20 (190)
System.print(Slots.ensureOutsideForeign())
// expect: 0 -> 20 (190)