Add API to get the type of object in a slot.

This commit is contained in:
Bob Nystrom
2016-02-19 07:18:00 -08:00
parent fa0a507b48
commit ef3aa07d84
6 changed files with 79 additions and 2 deletions

View File

@ -162,12 +162,30 @@ typedef struct
int heapGrowthPercent;
} WrenConfiguration;
typedef enum {
typedef enum
{
WREN_RESULT_SUCCESS,
WREN_RESULT_COMPILE_ERROR,
WREN_RESULT_RUNTIME_ERROR
} WrenInterpretResult;
// The type of an object stored in a slot.
//
// This is not necessarily the object's *class*, but instead its low level
// representation type.
typedef enum
{
WREN_TYPE_BOOL,
WREN_TYPE_NUM,
WREN_TYPE_FOREIGN,
WREN_TYPE_LIST,
WREN_TYPE_NULL,
WREN_TYPE_STRING,
// The object is of a type that isn't accessible by the C API.
WREN_TYPE_UNKNOWN
} WrenType;
// Initializes [configuration] with all of its default values.
//
// Call this before setting the particular fields you care about.
@ -263,6 +281,9 @@ int wrenGetSlotCount(WrenVM* vm);
// It is an error to call this from a finalizer.
void wrenEnsureSlots(WrenVM* vm, int numSlots);
// Gets the type of the object in [slot].
WrenType wrenGetSlotType(WrenVM* vm, int slot);
// Reads a boolean value from [slot].
//
// It is an error to call this if the slot does not contain a boolean value.

View File

@ -1512,6 +1512,20 @@ static void validateApiSlot(WrenVM* vm, int slot)
ASSERT(slot < wrenGetSlotCount(vm), "Not that many slots.");
}
// Gets the type of the object in [slot].
WrenType wrenGetSlotType(WrenVM* vm, int slot)
{
validateApiSlot(vm, slot);
if (IS_BOOL(vm->apiStack[slot])) return WREN_TYPE_BOOL;
if (IS_NUM(vm->apiStack[slot])) return WREN_TYPE_NUM;
if (IS_FOREIGN(vm->apiStack[slot])) return WREN_TYPE_FOREIGN;
if (IS_LIST(vm->apiStack[slot])) return WREN_TYPE_LIST;
if (IS_NULL(vm->apiStack[slot])) return WREN_TYPE_NULL;
if (IS_STRING(vm->apiStack[slot])) return WREN_TYPE_STRING;
return WREN_TYPE_UNKNOWN;
}
bool wrenGetSlotBool(WrenVM* vm, int slot)
{
validateApiSlot(vm, slot);

View File

@ -63,7 +63,15 @@ static WrenForeignClassMethods bindForeignClass(
if (strcmp(module, "main") != 0) return methods;
foreignClassBindClass(className, &methods);
if (methods.allocate != NULL) return methods;
slotsBindClass(className, &methods);
if (methods.allocate != NULL) return methods;
fprintf(stderr,
"Unknown foreign class '%s' for test '%s'\n", className, testName);
exit(1);
return methods;
}

View File

@ -74,6 +74,20 @@ static void setSlots(WrenVM* vm)
}
}
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_NULL &&
wrenGetSlotType(vm, 5) == WREN_TYPE_NUM &&
wrenGetSlotType(vm, 6) == WREN_TYPE_STRING &&
wrenGetSlotType(vm, 7) == WREN_TYPE_UNKNOWN;
wrenSetSlotBool(vm, 0, result);
}
static void ensure(WrenVM* vm)
{
int before = wrenGetSlotCount(vm);
@ -134,13 +148,24 @@ static void ensureOutsideForeign(WrenVM* vm)
wrenSetSlotString(vm, 0, result);
}
static void foreignClassAllocate(WrenVM* vm)
{
wrenSetSlotNewForeign(vm, 0, 0, 4);
}
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;
return NULL;
}
void slotsBindClass(const char* className, WrenForeignClassMethods* methods)
{
methods->allocate = foreignClassAllocate;
}

View File

@ -1,3 +1,4 @@
#include "wren.h"
WrenForeignMethodFn slotsBindMethod(const char* signature);
void slotsBindClass(const char* className, WrenForeignClassMethods* methods);

View File

@ -2,10 +2,15 @@ class Slots {
foreign static noSet
foreign static getSlots(bool, num, string, bytes, value)
foreign static setSlots(a, b, c, d)
foreign static slotTypes(bool, foreignObj, list, nullObj, num, string, unknown)
foreign static ensure()
foreign static ensureOutsideForeign()
}
foreign class ForeignType {
construct new() {}
}
// If nothing is set in the return slot, it retains its previous value, the
// receiver.
System.print(Slots.noSet == Slots) // expect: true
@ -17,6 +22,9 @@ System.print(Slots.getSlots(true, "by\0te", 12.34, "str", value) == value)
System.print(Slots.setSlots(value, 0, 0, 0) == value)
// expect: true
System.print(Slots.slotTypes(false, ForeignType.new(), [], null, 1.2, "str", 1..2))
// expect: true
System.print(Slots.ensure())
// expect: 1 -> 20 (190)