forked from Mirror/wren
Functions for operating on Maps from C (#725)
new API functions for maps: wrenSetSlotNewMap wrenGetMapCount wrenGetMapContainsKey wrenGetMapValue wrenSetMapValue wrenRemoveMapValue
This commit is contained in:
@ -121,6 +121,7 @@ OBJECTS += $(OBJDIR)/get_variable.o
|
||||
OBJECTS += $(OBJDIR)/handle.o
|
||||
OBJECTS += $(OBJDIR)/lists.o
|
||||
OBJECTS += $(OBJDIR)/main.o
|
||||
OBJECTS += $(OBJDIR)/maps.o
|
||||
OBJECTS += $(OBJDIR)/new_vm.o
|
||||
OBJECTS += $(OBJDIR)/reset_stack_after_call_abort.o
|
||||
OBJECTS += $(OBJDIR)/reset_stack_after_foreign_construct.o
|
||||
@ -219,6 +220,9 @@ $(OBJDIR)/handle.o: ../../test/api/handle.c
|
||||
$(OBJDIR)/lists.o: ../../test/api/lists.c
|
||||
@echo $(notdir $<)
|
||||
$(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
|
||||
$(OBJDIR)/maps.o: ../../test/api/maps.c
|
||||
@echo $(notdir $<)
|
||||
$(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
|
||||
$(OBJDIR)/new_vm.o: ../../test/api/new_vm.c
|
||||
@echo $(notdir $<)
|
||||
$(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
|
||||
|
||||
@ -129,6 +129,7 @@ OBJECTS += $(OBJDIR)/get_variable.o
|
||||
OBJECTS += $(OBJDIR)/handle.o
|
||||
OBJECTS += $(OBJDIR)/lists.o
|
||||
OBJECTS += $(OBJDIR)/main.o
|
||||
OBJECTS += $(OBJDIR)/maps.o
|
||||
OBJECTS += $(OBJDIR)/new_vm.o
|
||||
OBJECTS += $(OBJDIR)/reset_stack_after_call_abort.o
|
||||
OBJECTS += $(OBJDIR)/reset_stack_after_foreign_construct.o
|
||||
@ -227,6 +228,9 @@ $(OBJDIR)/handle.o: ../../test/api/handle.c
|
||||
$(OBJDIR)/lists.o: ../../test/api/lists.c
|
||||
@echo $(notdir $<)
|
||||
$(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
|
||||
$(OBJDIR)/maps.o: ../../test/api/maps.c
|
||||
@echo $(notdir $<)
|
||||
$(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
|
||||
$(OBJDIR)/new_vm.o: ../../test/api/new_vm.c
|
||||
@echo $(notdir $<)
|
||||
$(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
|
||||
|
||||
@ -121,6 +121,7 @@ OBJECTS += $(OBJDIR)/get_variable.o
|
||||
OBJECTS += $(OBJDIR)/handle.o
|
||||
OBJECTS += $(OBJDIR)/lists.o
|
||||
OBJECTS += $(OBJDIR)/main.o
|
||||
OBJECTS += $(OBJDIR)/maps.o
|
||||
OBJECTS += $(OBJDIR)/new_vm.o
|
||||
OBJECTS += $(OBJDIR)/reset_stack_after_call_abort.o
|
||||
OBJECTS += $(OBJDIR)/reset_stack_after_foreign_construct.o
|
||||
@ -219,6 +220,9 @@ $(OBJDIR)/handle.o: ../../test/api/handle.c
|
||||
$(OBJDIR)/lists.o: ../../test/api/lists.c
|
||||
@echo $(notdir $<)
|
||||
$(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
|
||||
$(OBJDIR)/maps.o: ../../test/api/maps.c
|
||||
@echo $(notdir $<)
|
||||
$(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
|
||||
$(OBJDIR)/new_vm.o: ../../test/api/new_vm.c
|
||||
@echo $(notdir $<)
|
||||
$(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
|
||||
|
||||
BIN
projects/premake/premake5.exe
Normal file
BIN
projects/premake/premake5.exe
Normal file
Binary file not shown.
@ -265,6 +265,7 @@
|
||||
<ClInclude Include="..\..\test\api\get_variable.h" />
|
||||
<ClInclude Include="..\..\test\api\handle.h" />
|
||||
<ClInclude Include="..\..\test\api\lists.h" />
|
||||
<ClInclude Include="..\..\test\api\maps.h" />
|
||||
<ClInclude Include="..\..\test\api\new_vm.h" />
|
||||
<ClInclude Include="..\..\test\api\reset_stack_after_call_abort.h" />
|
||||
<ClInclude Include="..\..\test\api\reset_stack_after_foreign_construct.h" />
|
||||
@ -284,6 +285,7 @@
|
||||
<ClCompile Include="..\..\test\api\get_variable.c" />
|
||||
<ClCompile Include="..\..\test\api\handle.c" />
|
||||
<ClCompile Include="..\..\test\api\lists.c" />
|
||||
<ClCompile Include="..\..\test\api\maps.c" />
|
||||
<ClCompile Include="..\..\test\api\new_vm.c" />
|
||||
<ClCompile Include="..\..\test\api\reset_stack_after_call_abort.c" />
|
||||
<ClCompile Include="..\..\test\api\reset_stack_after_foreign_construct.c" />
|
||||
|
||||
@ -36,6 +36,9 @@
|
||||
<ClInclude Include="..\..\test\api\lists.h">
|
||||
<Filter>api</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\test\api\maps.h">
|
||||
<Filter>api</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\test\api\new_vm.h">
|
||||
<Filter>api</Filter>
|
||||
</ClInclude>
|
||||
@ -87,6 +90,9 @@
|
||||
<ClCompile Include="..\..\test\api\lists.c">
|
||||
<Filter>api</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\test\api\maps.c">
|
||||
<Filter>api</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\test\api\new_vm.c">
|
||||
<Filter>api</Filter>
|
||||
</ClCompile>
|
||||
|
||||
@ -265,6 +265,7 @@
|
||||
<ClInclude Include="..\..\test\api\get_variable.h" />
|
||||
<ClInclude Include="..\..\test\api\handle.h" />
|
||||
<ClInclude Include="..\..\test\api\lists.h" />
|
||||
<ClInclude Include="..\..\test\api\maps.h" />
|
||||
<ClInclude Include="..\..\test\api\new_vm.h" />
|
||||
<ClInclude Include="..\..\test\api\reset_stack_after_call_abort.h" />
|
||||
<ClInclude Include="..\..\test\api\reset_stack_after_foreign_construct.h" />
|
||||
@ -284,6 +285,7 @@
|
||||
<ClCompile Include="..\..\test\api\get_variable.c" />
|
||||
<ClCompile Include="..\..\test\api\handle.c" />
|
||||
<ClCompile Include="..\..\test\api\lists.c" />
|
||||
<ClCompile Include="..\..\test\api\maps.c" />
|
||||
<ClCompile Include="..\..\test\api\new_vm.c" />
|
||||
<ClCompile Include="..\..\test\api\reset_stack_after_call_abort.c" />
|
||||
<ClCompile Include="..\..\test\api\reset_stack_after_foreign_construct.c" />
|
||||
|
||||
@ -36,6 +36,9 @@
|
||||
<ClInclude Include="..\..\test\api\lists.h">
|
||||
<Filter>api</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\test\api\maps.h">
|
||||
<Filter>api</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\test\api\new_vm.h">
|
||||
<Filter>api</Filter>
|
||||
</ClInclude>
|
||||
@ -87,6 +90,9 @@
|
||||
<ClCompile Include="..\..\test\api\lists.c">
|
||||
<Filter>api</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\test\api\maps.c">
|
||||
<Filter>api</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\test\api\new_vm.c">
|
||||
<Filter>api</Filter>
|
||||
</ClCompile>
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
31D07E222B367F941ED1DC62 /* test.c in Sources */ = {isa = PBXBuildFile; fileRef = 7B2F762A1E7AFF5C394BCC6A /* test.c */; };
|
||||
47E53E839E72A8F576EBBCC3 /* call.c in Sources */ = {isa = PBXBuildFile; fileRef = 2F776B0B32E83D3DB454E14B /* call.c */; };
|
||||
4D8AE463A8CC37D57C2682A3 /* handle.c in Sources */ = {isa = PBXBuildFile; fileRef = 069BFCEB1DAE981D0DCA932B /* handle.c */; };
|
||||
4EA04F0DA52DB97F7DA6CD4D /* maps.c in Sources */ = {isa = PBXBuildFile; fileRef = 3AEABBF53E5B8E27BFC83235 /* maps.c */; };
|
||||
59615B339DB000A5DFD73973 /* resolution.c in Sources */ = {isa = PBXBuildFile; fileRef = 535262BB751E0FEDB1D338FB /* resolution.c */; };
|
||||
78667B8C71CC7CFE6567D9CC /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 6E0F7DF4115B07262C2BD434 /* main.c */; };
|
||||
7CCD7163EDF01255A3B6BFA3 /* api_tests.c in Sources */ = {isa = PBXBuildFile; fileRef = 21B810EB49F2C99D318E572B /* api_tests.c */; };
|
||||
@ -58,6 +59,7 @@
|
||||
30E3DEE9D44B0C9BEB80C529 /* reset_stack_after_foreign_construct.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = reset_stack_after_foreign_construct.h; path = ../../test/api/reset_stack_after_foreign_construct.h; sourceTree = "<group>"; };
|
||||
310165BFD4689371EB9E4BFF /* reset_stack_after_foreign_construct.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = reset_stack_after_foreign_construct.c; path = ../../test/api/reset_stack_after_foreign_construct.c; sourceTree = "<group>"; };
|
||||
33526D1DD64093CF6566735D /* slots.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = slots.c; path = ../../test/api/slots.c; sourceTree = "<group>"; };
|
||||
3AEABBF53E5B8E27BFC83235 /* maps.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = maps.c; path = ../../test/api/maps.c; sourceTree = "<group>"; };
|
||||
3E23E7FBE1120EAD7037EE3B /* lists.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = lists.h; path = ../../test/api/lists.h; sourceTree = "<group>"; };
|
||||
41058591E3F3AC4373198BD1 /* lists.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = lists.c; path = ../../test/api/lists.c; sourceTree = "<group>"; };
|
||||
50338489786E3D3B6009CAC9 /* benchmark.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = benchmark.c; path = ../../test/api/benchmark.c; sourceTree = "<group>"; };
|
||||
@ -73,6 +75,7 @@
|
||||
9C375BF5B349F727A365F235 /* handle.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = handle.h; path = ../../test/api/handle.h; sourceTree = "<group>"; };
|
||||
A415E4D5A786B70728F35B15 /* call.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = call.h; path = ../../test/api/call.h; sourceTree = "<group>"; };
|
||||
ABEF15744F3A9EA66A0B6BB4 /* test.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = test.h; path = ../../test/test.h; sourceTree = "<group>"; };
|
||||
AF8935BFB2FA07F13466ABFF /* maps.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = maps.h; path = ../../test/api/maps.h; sourceTree = "<group>"; };
|
||||
B0175F83D8521835BFEDA5C3 /* user_data.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = user_data.c; path = ../../test/api/user_data.c; sourceTree = "<group>"; };
|
||||
B0267C45D1F229770EA75285 /* resolution.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = resolution.h; path = ../../test/api/resolution.h; sourceTree = "<group>"; };
|
||||
B1B12E89FA506CBB1D7C24C9 /* reset_stack_after_call_abort.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = reset_stack_after_call_abort.c; path = ../../test/api/reset_stack_after_call_abort.c; sourceTree = "<group>"; };
|
||||
@ -128,6 +131,8 @@
|
||||
9C375BF5B349F727A365F235 /* handle.h */,
|
||||
41058591E3F3AC4373198BD1 /* lists.c */,
|
||||
3E23E7FBE1120EAD7037EE3B /* lists.h */,
|
||||
3AEABBF53E5B8E27BFC83235 /* maps.c */,
|
||||
AF8935BFB2FA07F13466ABFF /* maps.h */,
|
||||
C22EBF6BD9415A9DC95D55AB /* new_vm.c */,
|
||||
57CA1E756EDCB9A75EF8B4B5 /* new_vm.h */,
|
||||
B1B12E89FA506CBB1D7C24C9 /* reset_stack_after_call_abort.c */,
|
||||
@ -259,6 +264,7 @@
|
||||
E21864B54F40732750D362F5 /* get_variable.c in Sources */,
|
||||
4D8AE463A8CC37D57C2682A3 /* handle.c in Sources */,
|
||||
1C5491694BE6605B26F39FA9 /* lists.c in Sources */,
|
||||
4EA04F0DA52DB97F7DA6CD4D /* maps.c in Sources */,
|
||||
29C70EE3850862555862AD23 /* new_vm.c in Sources */,
|
||||
BD0CC4E181C21B533630C321 /* reset_stack_after_call_abort.c in Sources */,
|
||||
8F510F77A173C5697A74FDB7 /* reset_stack_after_foreign_construct.c in Sources */,
|
||||
|
||||
@ -263,6 +263,7 @@ typedef enum
|
||||
WREN_TYPE_NUM,
|
||||
WREN_TYPE_FOREIGN,
|
||||
WREN_TYPE_LIST,
|
||||
WREN_TYPE_MAP,
|
||||
WREN_TYPE_NULL,
|
||||
WREN_TYPE_STRING,
|
||||
|
||||
@ -440,6 +441,9 @@ void* wrenSetSlotNewForeign(WrenVM* vm, int slot, int classSlot, size_t size);
|
||||
// Stores a new empty list in [slot].
|
||||
void wrenSetSlotNewList(WrenVM* vm, int slot);
|
||||
|
||||
// Stores a new empty map in [slot].
|
||||
void wrenSetSlotNewMap(WrenVM* vm, int slot);
|
||||
|
||||
// Stores null in [slot].
|
||||
void wrenSetSlotNull(WrenVM* vm, int slot);
|
||||
|
||||
@ -470,6 +474,26 @@ void wrenGetListElement(WrenVM* vm, int listSlot, int index, int elementSlot);
|
||||
// an element, use `-1` for the index.
|
||||
void wrenInsertInList(WrenVM* vm, int listSlot, int index, int elementSlot);
|
||||
|
||||
// Returns the number of entries in the map stored in [slot].
|
||||
int wrenGetMapCount(WrenVM* vm, int slot);
|
||||
|
||||
// Returns true if the key in [keySlot] is found in the map placed in [mapSlot].
|
||||
bool wrenGetMapContainsKey(WrenVM* vm, int mapSlot, int keySlot);
|
||||
|
||||
// Retrieves a value with the key in [keySlot] from the map in [mapSlot] and
|
||||
// stores it in [valueSlot].
|
||||
void wrenGetMapValue(WrenVM* vm, int mapSlot, int keySlot, int valueSlot);
|
||||
|
||||
// Takes the value stored at [valueSlot] and inserts it into the map stored
|
||||
// at [mapSlot] with key [keySlot].
|
||||
void wrenSetMapValue(WrenVM* vm, int mapSlot, int keySlot, int valueSlot);
|
||||
|
||||
// Removes a value from the map in [mapSlot], with the key from [keySlot],
|
||||
// and place it in [removedValueSlot]. If not found, [removedValueSlot] is
|
||||
// set to null, the same behaviour as the Wren Map API.
|
||||
void wrenRemoveMapValue(WrenVM* vm, int mapSlot, int keySlot,
|
||||
int removedValueSlot);
|
||||
|
||||
// Looks up the top level variable with [name] in resolved [module] and stores
|
||||
// it in [slot].
|
||||
void wrenGetVariable(WrenVM* vm, const char* module, const char* name,
|
||||
|
||||
@ -76,6 +76,7 @@
|
||||
#define IS_FOREIGN(value) (wrenIsObjType(value, OBJ_FOREIGN)) // ObjForeign
|
||||
#define IS_INSTANCE(value) (wrenIsObjType(value, OBJ_INSTANCE)) // ObjInstance
|
||||
#define IS_LIST(value) (wrenIsObjType(value, OBJ_LIST)) // ObjList
|
||||
#define IS_MAP(value) (wrenIsObjType(value, OBJ_MAP)) // ObjMap
|
||||
#define IS_RANGE(value) (wrenIsObjType(value, OBJ_RANGE)) // ObjRange
|
||||
#define IS_STRING(value) (wrenIsObjType(value, OBJ_STRING)) // ObjString
|
||||
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
#include "wren_compiler.h"
|
||||
#include "wren_core.h"
|
||||
#include "wren_debug.h"
|
||||
#include "wren_primitive.h"
|
||||
#include "wren_vm.h"
|
||||
|
||||
#if WREN_OPT_META
|
||||
@ -1596,6 +1597,7 @@ WrenType wrenGetSlotType(WrenVM* vm, int slot)
|
||||
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_MAP(vm->apiStack[slot])) return WREN_TYPE_MAP;
|
||||
if (IS_NULL(vm->apiStack[slot])) return WREN_TYPE_NULL;
|
||||
if (IS_STRING(vm->apiStack[slot])) return WREN_TYPE_STRING;
|
||||
|
||||
@ -1694,6 +1696,11 @@ void wrenSetSlotNewList(WrenVM* vm, int slot)
|
||||
setSlot(vm, slot, OBJ_VAL(wrenNewList(vm, 0)));
|
||||
}
|
||||
|
||||
void wrenSetSlotNewMap(WrenVM* vm, int slot)
|
||||
{
|
||||
setSlot(vm, slot, OBJ_VAL(wrenNewMap(vm)));
|
||||
}
|
||||
|
||||
void wrenSetSlotNull(WrenVM* vm, int slot)
|
||||
{
|
||||
setSlot(vm, slot, NULL_VAL);
|
||||
@ -1748,6 +1755,81 @@ void wrenInsertInList(WrenVM* vm, int listSlot, int index, int elementSlot)
|
||||
wrenListInsert(vm, list, vm->apiStack[elementSlot], index);
|
||||
}
|
||||
|
||||
int wrenGetMapCount(WrenVM* vm, int slot)
|
||||
{
|
||||
validateApiSlot(vm, slot);
|
||||
ASSERT(IS_MAP(vm->apiStack[slot]), "Slot must hold a map.");
|
||||
|
||||
ObjMap* map = AS_MAP(vm->apiStack[slot]);
|
||||
return map->count;
|
||||
}
|
||||
|
||||
bool wrenGetMapContainsKey(WrenVM* vm, int mapSlot, int keySlot)
|
||||
{
|
||||
validateApiSlot(vm, mapSlot);
|
||||
validateApiSlot(vm, keySlot);
|
||||
ASSERT(IS_MAP(vm->apiStack[mapSlot]), "Slot must hold a map.");
|
||||
|
||||
Value key = vm->apiStack[keySlot];
|
||||
if (!validateKey(vm, key)) return false;
|
||||
|
||||
ObjMap* map = AS_MAP(vm->apiStack[mapSlot]);
|
||||
Value value = wrenMapGet(map, key);
|
||||
|
||||
return !IS_UNDEFINED(value);
|
||||
}
|
||||
|
||||
void wrenGetMapValue(WrenVM* vm, int mapSlot, int keySlot, int valueSlot)
|
||||
{
|
||||
validateApiSlot(vm, mapSlot);
|
||||
validateApiSlot(vm, keySlot);
|
||||
validateApiSlot(vm, valueSlot);
|
||||
ASSERT(IS_MAP(vm->apiStack[mapSlot]), "Slot must hold a map.");
|
||||
|
||||
ObjMap* map = AS_MAP(vm->apiStack[mapSlot]);
|
||||
Value value = wrenMapGet(map, vm->apiStack[keySlot]);
|
||||
if (IS_UNDEFINED(value)) {
|
||||
value = NULL_VAL;
|
||||
}
|
||||
|
||||
vm->apiStack[valueSlot] = value;
|
||||
}
|
||||
|
||||
void wrenSetMapValue(WrenVM* vm, int mapSlot, int keySlot, int valueSlot)
|
||||
{
|
||||
validateApiSlot(vm, mapSlot);
|
||||
validateApiSlot(vm, keySlot);
|
||||
validateApiSlot(vm, valueSlot);
|
||||
ASSERT(IS_MAP(vm->apiStack[mapSlot]), "Must insert into a map.");
|
||||
|
||||
Value key = vm->apiStack[keySlot];
|
||||
if (!validateKey(vm, key)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Value value = vm->apiStack[valueSlot];
|
||||
ObjMap* map = AS_MAP(vm->apiStack[mapSlot]);
|
||||
|
||||
wrenMapSet(vm, map, key, value);
|
||||
}
|
||||
|
||||
void wrenRemoveMapValue(WrenVM* vm, int mapSlot, int keySlot,
|
||||
int removedValueSlot)
|
||||
{
|
||||
validateApiSlot(vm, mapSlot);
|
||||
validateApiSlot(vm, keySlot);
|
||||
ASSERT(IS_MAP(vm->apiStack[mapSlot]), "Slot must hold a map.");
|
||||
|
||||
Value key = vm->apiStack[keySlot];
|
||||
if (!validateKey(vm, key)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ObjMap* map = AS_MAP(vm->apiStack[mapSlot]);
|
||||
Value removed = wrenMapRemoveKey(vm, map, key);
|
||||
setSlot(vm, removedValueSlot, removed);
|
||||
}
|
||||
|
||||
void wrenGetVariable(WrenVM* vm, const char* module, const char* name,
|
||||
int slot)
|
||||
{
|
||||
|
||||
@ -40,6 +40,9 @@ WrenForeignMethodFn APITest_bindForeignMethod(
|
||||
method = listsBindMethod(fullName);
|
||||
if (method != NULL) return method;
|
||||
|
||||
method = mapsBindMethod(fullName);
|
||||
if (method != NULL) return method;
|
||||
|
||||
method = newVMBindMethod(fullName);
|
||||
if (method != NULL) return method;
|
||||
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
#include "foreign_class.h"
|
||||
#include "handle.h"
|
||||
#include "lists.h"
|
||||
#include "maps.h"
|
||||
#include "new_vm.h"
|
||||
#include "reset_stack_after_call_abort.h"
|
||||
#include "reset_stack_after_foreign_construct.h"
|
||||
|
||||
130
test/api/maps.c
Normal file
130
test/api/maps.c
Normal file
@ -0,0 +1,130 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "maps.h"
|
||||
|
||||
static void newMap(WrenVM* vm)
|
||||
{
|
||||
wrenSetSlotNewMap(vm, 0);
|
||||
}
|
||||
|
||||
static void invalidInsert(WrenVM* vm)
|
||||
{
|
||||
wrenSetSlotNewMap(vm, 0);
|
||||
|
||||
wrenEnsureSlots(vm, 3);
|
||||
// Foreign Class is in slot 1
|
||||
wrenSetSlotString(vm, 2, "England");
|
||||
wrenSetMapValue(vm, 0, 1, 2); // expect this to cause errors
|
||||
}
|
||||
|
||||
static void insert(WrenVM* vm)
|
||||
{
|
||||
wrenSetSlotNewMap(vm, 0);
|
||||
|
||||
wrenEnsureSlots(vm, 3);
|
||||
|
||||
// Insert String
|
||||
wrenSetSlotString(vm, 1, "England");
|
||||
wrenSetSlotString(vm, 2, "London");
|
||||
wrenSetMapValue(vm, 0, 1, 2);
|
||||
|
||||
// Insert Double
|
||||
wrenSetSlotDouble(vm, 1, 1.0);
|
||||
wrenSetSlotDouble(vm, 2, 42.0);
|
||||
wrenSetMapValue(vm, 0, 1, 2);
|
||||
|
||||
// Insert Boolean
|
||||
wrenSetSlotBool(vm, 1, false);
|
||||
wrenSetSlotBool(vm, 2, true);
|
||||
wrenSetMapValue(vm, 0, 1, 2);
|
||||
|
||||
// Insert Null
|
||||
wrenSetSlotNull(vm, 1);
|
||||
wrenSetSlotNull(vm, 2);
|
||||
wrenSetMapValue(vm, 0, 1, 2);
|
||||
|
||||
// Insert List
|
||||
wrenSetSlotString(vm, 1, "Empty");
|
||||
wrenSetSlotNewList(vm, 2);
|
||||
wrenSetMapValue(vm, 0, 1, 2);
|
||||
}
|
||||
|
||||
static void remove(WrenVM* vm)
|
||||
{
|
||||
wrenEnsureSlots(vm, 3);
|
||||
|
||||
wrenSetSlotString(vm, 2, "key");
|
||||
wrenRemoveMapValue(vm, 1, 2, 0);
|
||||
}
|
||||
|
||||
static void countWren(WrenVM* vm)
|
||||
{
|
||||
int count = wrenGetMapCount(vm, 1);
|
||||
wrenSetSlotDouble(vm, 0, count);
|
||||
}
|
||||
|
||||
static void countAPI(WrenVM* vm)
|
||||
{
|
||||
insert(vm);
|
||||
int count = wrenGetMapCount(vm, 0);
|
||||
wrenSetSlotDouble(vm, 0, count);
|
||||
}
|
||||
|
||||
static void containsWren(WrenVM* vm)
|
||||
{
|
||||
bool result = wrenGetMapContainsKey(vm, 1, 2);
|
||||
wrenSetSlotBool(vm, 0, result);
|
||||
}
|
||||
|
||||
|
||||
static void containsAPI(WrenVM* vm)
|
||||
{
|
||||
insert(vm);
|
||||
|
||||
wrenEnsureSlots(vm, 1);
|
||||
wrenSetSlotString(vm, 1, "England");
|
||||
|
||||
bool result = wrenGetMapContainsKey(vm, 0, 1);
|
||||
wrenSetSlotBool(vm, 0, result);
|
||||
}
|
||||
|
||||
static void containsAPIFalse(WrenVM* vm)
|
||||
{
|
||||
insert(vm);
|
||||
|
||||
wrenEnsureSlots(vm, 1);
|
||||
wrenSetSlotString(vm, 1, "DefinitelyNotARealKey");
|
||||
|
||||
bool result = wrenGetMapContainsKey(vm, 0, 1);
|
||||
wrenSetSlotBool(vm, 0, result);
|
||||
}
|
||||
|
||||
|
||||
WrenForeignMethodFn mapsBindMethod(const char* signature)
|
||||
{
|
||||
if (strcmp(signature, "static Maps.newMap()") == 0) return newMap;
|
||||
if (strcmp(signature, "static Maps.insert()") == 0) return insert;
|
||||
if (strcmp(signature, "static Maps.remove(_)") == 0) return remove;
|
||||
if (strcmp(signature, "static Maps.count(_)") == 0) return countWren;
|
||||
if (strcmp(signature, "static Maps.count()") == 0) return countAPI;
|
||||
if (strcmp(signature, "static Maps.contains()") == 0) return containsAPI;
|
||||
if (strcmp(signature, "static Maps.containsFalse()") == 0) return containsAPIFalse;
|
||||
if (strcmp(signature, "static Maps.contains(_,_)") == 0) return containsWren;
|
||||
if (strcmp(signature, "static Maps.invalidInsert(_)") == 0) return invalidInsert;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void foreignAllocate(WrenVM* vm) {
|
||||
wrenSetSlotNewForeign(vm, 0, 0, 0);
|
||||
}
|
||||
|
||||
void mapBindClass(
|
||||
const char* className, WrenForeignClassMethods* methods)
|
||||
{
|
||||
if (strcmp(className, "ForeignClass") == 0)
|
||||
{
|
||||
methods->allocate = foreignAllocate;
|
||||
return;
|
||||
}
|
||||
}
|
||||
5
test/api/maps.h
Normal file
5
test/api/maps.h
Normal file
@ -0,0 +1,5 @@
|
||||
#include "wren.h"
|
||||
|
||||
WrenForeignMethodFn mapsBindMethod(const char* signature);
|
||||
void mapBindClass(
|
||||
const char* className, WrenForeignClassMethods* methods);
|
||||
68
test/api/maps.wren
Normal file
68
test/api/maps.wren
Normal file
@ -0,0 +1,68 @@
|
||||
class ForeignClass {
|
||||
construct new() {}
|
||||
}
|
||||
|
||||
class Maps {
|
||||
foreign static newMap()
|
||||
foreign static insert()
|
||||
foreign static contains(map, key)
|
||||
foreign static contains()
|
||||
foreign static containsFalse()
|
||||
foreign static count()
|
||||
foreign static count(map)
|
||||
foreign static remove(map)
|
||||
foreign static invalidInsert(obj)
|
||||
}
|
||||
|
||||
// map new + get/set API
|
||||
|
||||
var map = Maps.newMap()
|
||||
System.print(map is Map) // expect: true
|
||||
System.print(map.count) // expect: 0
|
||||
|
||||
var data = Maps.insert()
|
||||
System.print(data["England"]) // expect: London
|
||||
System.print(data["Empty"]) // expect: []
|
||||
System.print(data[1.0]) // expect: 42
|
||||
System.print(data[false]) // expect: true
|
||||
System.print(data[null]) // expect: null
|
||||
|
||||
// remove API
|
||||
|
||||
var removed = Maps.remove({ "key":"value", "other":"data" })
|
||||
System.print(removed) // expect: value
|
||||
|
||||
var removedNone = Maps.remove({})
|
||||
System.print(removedNone) // expect: null
|
||||
|
||||
// count API
|
||||
|
||||
var countMap = { "key":"value", "other":"data", 4:"number key" }
|
||||
System.print(Maps.count(countMap)) // expect: 3
|
||||
Maps.remove(countMap) //remove using API
|
||||
System.print(Maps.count(countMap)) // expect: 2
|
||||
countMap.remove("other") //remove wren side
|
||||
System.print(Maps.count(countMap)) // expect: 1
|
||||
|
||||
var countAPI = Maps.count()
|
||||
System.print(countAPI) // expect: 5
|
||||
|
||||
//contains key API
|
||||
|
||||
var containsMap = { "key":"value", "other":"data", 4:"number key" }
|
||||
System.print(Maps.contains(containsMap, "key")) // expect: true
|
||||
System.print(Maps.contains(containsMap, "fake")) // expect: false
|
||||
System.print(Maps.contains(containsMap, "other")) // expect: true
|
||||
|
||||
Maps.remove(containsMap) //remove using API
|
||||
System.print(Maps.contains(containsMap, "key")) // expect: false
|
||||
|
||||
containsMap.remove("other") //remove wren side
|
||||
System.print(Maps.contains(containsMap, "other")) // expect: false
|
||||
|
||||
System.print(Maps.contains()) // expect: true
|
||||
System.print(Maps.containsFalse()) // expect: false
|
||||
|
||||
//
|
||||
|
||||
Maps.invalidInsert(ForeignClass.new()) // expect runtime error: Key must be a value type.
|
||||
@ -82,10 +82,11 @@ static void slotTypes(WrenVM* vm)
|
||||
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;
|
||||
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);
|
||||
}
|
||||
@ -166,16 +167,22 @@ static void getListElement(WrenVM* vm)
|
||||
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.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;
|
||||
}
|
||||
|
||||
@ -2,11 +2,12 @@ class Slots {
|
||||
foreign static noSet
|
||||
foreign static getSlots(bool, num, string, bytes, value)
|
||||
foreign static setSlots(a, b, c, d, e)
|
||||
foreign static slotTypes(bool, foreignObj, list, nullObj, num, string, unknown)
|
||||
foreign static slotTypes(bool, foreignObj, list, map, nullObj, num, string, unknown)
|
||||
foreign static ensure()
|
||||
foreign static ensureOutsideForeign()
|
||||
foreign static getListCount(list)
|
||||
foreign static getListElement(list, index)
|
||||
foreign static getMapValue(map, key)
|
||||
}
|
||||
|
||||
foreign class ForeignType {
|
||||
@ -24,7 +25,7 @@ System.print(Slots.getSlots(true, "by\0te", 1.5, "str", value) == value)
|
||||
System.print(Slots.setSlots(value, 0, 0, 0, 0) == value)
|
||||
// expect: true
|
||||
|
||||
System.print(Slots.slotTypes(false, ForeignType.new(), [], null, 1.2, "str", 1..2))
|
||||
System.print(Slots.slotTypes(false, ForeignType.new(), [], {}, null, 1.2, "str", 1..2))
|
||||
// expect: true
|
||||
|
||||
System.print(Slots.ensure())
|
||||
@ -37,3 +38,14 @@ var ducks = ["Huey", "Dewey", "Louie"]
|
||||
System.print(Slots.getListCount(ducks)) // expect: 3
|
||||
System.print(Slots.getListElement(ducks, 0)) // expect: Huey
|
||||
System.print(Slots.getListElement(ducks, 1)) // expect: Dewey
|
||||
|
||||
var capitals = {
|
||||
"England": "London",
|
||||
"Scotland": "Edinburgh",
|
||||
"Wales": "Cardiff",
|
||||
"N. Ireland": "Belfast"
|
||||
}
|
||||
|
||||
System.print(Slots.getMapValue(capitals, "England")) // expect: London
|
||||
System.print(Slots.getMapValue(capitals, "Wales")) // expect: Cardiff
|
||||
System.print(Slots.getMapValue(capitals, "S. Ireland")) // expect: null
|
||||
|
||||
Reference in New Issue
Block a user