#include #include #include "slots.h" static void noSet(WrenVM* vm) { // Do nothing. } static void getSlots(WrenVM* vm) { bool result = true; if (wrenGetSlotBool(vm, 1) != true) result = false; int length; const char* bytes = wrenGetSlotBytes(vm, 2, &length); if (length != 5) result = false; if (memcmp(bytes, "by\0te", length) != 0) result = false; if (wrenGetSlotDouble(vm, 3) != 1.5) result = false; if (strcmp(wrenGetSlotString(vm, 4), "str") != 0) result = false; WrenHandle* handle = wrenGetSlotHandle(vm, 5); if (result) { // Otherwise, return the value so we can tell if we captured it correctly. wrenSetSlotHandle(vm, 0, handle); } else { // If anything failed, return false. wrenSetSlotBool(vm, 0, false); } wrenReleaseHandle(vm, handle); } static void setSlots(WrenVM* vm) { WrenHandle* handle = wrenGetSlotHandle(vm, 1); wrenSetSlotBool(vm, 1, true); wrenSetSlotBytes(vm, 2, "by\0te", 5); wrenSetSlotDouble(vm, 3, 1.5); wrenSetSlotString(vm, 4, "str"); wrenSetSlotNull(vm, 5); // Read the slots back to make sure they were set correctly. bool result = true; if (wrenGetSlotBool(vm, 1) != true) result = false; int length; const char* bytes = wrenGetSlotBytes(vm, 2, &length); if (length != 5) result = false; if (memcmp(bytes, "by\0te", length) != 0) result = false; if (wrenGetSlotDouble(vm, 3) != 1.5) result = false; if (strcmp(wrenGetSlotString(vm, 4), "str") != 0) result = false; if (wrenGetSlotType(vm, 5) != WREN_TYPE_NULL) result = false; if (result) { // Move the value into the return position. wrenSetSlotHandle(vm, 0, handle); } else { // If anything failed, return false. wrenSetSlotBool(vm, 0, false); } wrenReleaseHandle(vm, handle); } static void slotTypes(WrenVM* vm) { bool result = wrenGetSlotType(vm, 1) == WREN_TYPE_BOOL && wrenGetSlotType(vm, 2) == WREN_TYPE_FOREIGN && wrenGetSlotType(vm, 3) == WREN_TYPE_LIST && wrenGetSlotType(vm, 4) == WREN_TYPE_MAP && wrenGetSlotType(vm, 5) == WREN_TYPE_NULL && wrenGetSlotType(vm, 6) == WREN_TYPE_NUM && wrenGetSlotType(vm, 7) == WREN_TYPE_STRING && wrenGetSlotType(vm, 8) == WREN_TYPE_UNKNOWN; wrenSetSlotBool(vm, 0, result); } static void ensure(WrenVM* vm) { int before = wrenGetSlotCount(vm); wrenEnsureSlots(vm, 20); int after = wrenGetSlotCount(vm); // Use the slots to make sure they're available. for (int i = 0; i < 20; i++) { wrenSetSlotDouble(vm, i, i); } int sum = 0; for (int i = 0; i < 20; i++) { 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); } static void foreignClassAllocate(WrenVM* vm) { wrenSetSlotNewForeign(vm, 0, 0, 4); } static void getListCount(WrenVM* vm) { wrenSetSlotDouble(vm, 0, wrenGetListCount(vm, 1)); } static void getListElement(WrenVM* vm) { int index = (int)wrenGetSlotDouble(vm, 2); wrenGetListElement(vm, 1, index, 0); } static void getMapValue(WrenVM* vm) { wrenGetMapValue(vm, 1, 2, 0); } WrenForeignMethodFn slotsBindMethod(const char* signature) { if (strcmp(signature, "static Slots.noSet") == 0) return noSet; if (strcmp(signature, "static Slots.getSlots(_,_,_,_,_)") == 0) return getSlots; if (strcmp(signature, "static Slots.setSlots(_,_,_,_,_)") == 0) return setSlots; if (strcmp(signature, "static Slots.slotTypes(_,_,_,_,_,_,_,_)") == 0) return slotTypes; if (strcmp(signature, "static Slots.ensure()") == 0) return ensure; if (strcmp(signature, "static Slots.ensureOutsideForeign()") == 0) return ensureOutsideForeign; if (strcmp(signature, "static Slots.getListCount(_)") == 0) return getListCount; if (strcmp(signature, "static Slots.getListElement(_,_)") == 0) return getListElement; if (strcmp(signature, "static Slots.getMapValue(_,_)") == 0) return getMapValue; return NULL; } void slotsBindClass(const char* className, WrenForeignClassMethods* methods) { methods->allocate = foreignClassAllocate; }