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; int heapGrowthPercent;
} WrenConfiguration; } WrenConfiguration;
typedef enum { typedef enum
{
WREN_RESULT_SUCCESS, WREN_RESULT_SUCCESS,
WREN_RESULT_COMPILE_ERROR, WREN_RESULT_COMPILE_ERROR,
WREN_RESULT_RUNTIME_ERROR WREN_RESULT_RUNTIME_ERROR
} WrenInterpretResult; } 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. // Initializes [configuration] with all of its default values.
// //
// Call this before setting the particular fields you care about. // 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. // It is an error to call this from a finalizer.
void wrenEnsureSlots(WrenVM* vm, int numSlots); 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]. // Reads a boolean value from [slot].
// //
// It is an error to call this if the slot does not contain a boolean value. // 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."); 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) bool wrenGetSlotBool(WrenVM* vm, int slot)
{ {
validateApiSlot(vm, slot); validateApiSlot(vm, slot);

View File

@ -63,7 +63,15 @@ static WrenForeignClassMethods bindForeignClass(
if (strcmp(module, "main") != 0) return methods; if (strcmp(module, "main") != 0) return methods;
foreignClassBindClass(className, &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; 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) static void ensure(WrenVM* vm)
{ {
int before = wrenGetSlotCount(vm); int before = wrenGetSlotCount(vm);
@ -134,13 +148,24 @@ static void ensureOutsideForeign(WrenVM* vm)
wrenSetSlotString(vm, 0, result); wrenSetSlotString(vm, 0, result);
} }
static void foreignClassAllocate(WrenVM* vm)
{
wrenSetSlotNewForeign(vm, 0, 0, 4);
}
WrenForeignMethodFn slotsBindMethod(const char* signature) WrenForeignMethodFn slotsBindMethod(const char* signature)
{ {
if (strcmp(signature, "static Slots.noSet") == 0) return noSet; if (strcmp(signature, "static Slots.noSet") == 0) return noSet;
if (strcmp(signature, "static Slots.getSlots(_,_,_,_,_)") == 0) return getSlots; if (strcmp(signature, "static Slots.getSlots(_,_,_,_,_)") == 0) return getSlots;
if (strcmp(signature, "static Slots.setSlots(_,_,_,_)") == 0) return setSlots; 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.ensure()") == 0) return ensure;
if (strcmp(signature, "static Slots.ensureOutsideForeign()") == 0) return ensureOutsideForeign; if (strcmp(signature, "static Slots.ensureOutsideForeign()") == 0) return ensureOutsideForeign;
return NULL; return NULL;
} }
void slotsBindClass(const char* className, WrenForeignClassMethods* methods)
{
methods->allocate = foreignClassAllocate;
}

View File

@ -1,3 +1,4 @@
#include "wren.h" #include "wren.h"
WrenForeignMethodFn slotsBindMethod(const char* signature); 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 noSet
foreign static getSlots(bool, num, string, bytes, value) foreign static getSlots(bool, num, string, bytes, value)
foreign static setSlots(a, b, c, d) foreign static setSlots(a, b, c, d)
foreign static slotTypes(bool, foreignObj, list, nullObj, num, string, unknown)
foreign static ensure() foreign static ensure()
foreign static ensureOutsideForeign() foreign static ensureOutsideForeign()
} }
foreign class ForeignType {
construct new() {}
}
// If nothing is set in the return slot, it retains its previous value, the // If nothing is set in the return slot, it retains its previous value, the
// receiver. // receiver.
System.print(Slots.noSet == Slots) // expect: true 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) System.print(Slots.setSlots(value, 0, 0, 0) == value)
// expect: true // expect: true
System.print(Slots.slotTypes(false, ForeignType.new(), [], null, 1.2, "str", 1..2))
// expect: true
System.print(Slots.ensure()) System.print(Slots.ensure())
// expect: 1 -> 20 (190) // expect: 1 -> 20 (190)