Skip to content

Commit

Permalink
Functions for operating on Maps from C (#725)
Browse files Browse the repository at this point in the history
new API functions for maps:
wrenSetSlotNewMap
wrenGetMapCount
wrenGetMapContainsKey
wrenGetMapValue
wrenSetMapValue
wrenRemoveMapValue
  • Loading branch information
avivbeeri committed Jun 14, 2020
1 parent 344d343 commit de6a312
Show file tree
Hide file tree
Showing 19 changed files with 374 additions and 7 deletions.
4 changes: 4 additions & 0 deletions projects/make.bsd/wren_test.make
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 "$<"
Expand Down
4 changes: 4 additions & 0 deletions projects/make.mac/wren_test.make
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 "$<"
Expand Down
4 changes: 4 additions & 0 deletions projects/make/wren_test.make
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 "$<"
Expand Down
Binary file added projects/premake/premake5.exe
Binary file not shown.
2 changes: 2 additions & 0 deletions projects/vs2017/wren_test.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -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" />
Expand All @@ -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" />
Expand Down
6 changes: 6 additions & 0 deletions projects/vs2017/wren_test.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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>
Expand Down
2 changes: 2 additions & 0 deletions projects/vs2019/wren_test.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -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" />
Expand All @@ -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" />
Expand Down
6 changes: 6 additions & 0 deletions projects/vs2019/wren_test.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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>
Expand Down
6 changes: 6 additions & 0 deletions projects/xcode/wren_test.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -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 */; };
Expand Down Expand Up @@ -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>"; };
Expand All @@ -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>"; };
Expand Down Expand Up @@ -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 */,
Expand Down Expand Up @@ -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 */,
Expand Down
24 changes: 24 additions & 0 deletions src/include/wren.h
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ typedef enum
WREN_TYPE_NUM,
WREN_TYPE_FOREIGN,
WREN_TYPE_LIST,
WREN_TYPE_MAP,
WREN_TYPE_NULL,
WREN_TYPE_STRING,

Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions src/vm/wren_value.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
82 changes: 82 additions & 0 deletions src/vm/wren_vm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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)
{
Expand Down
3 changes: 3 additions & 0 deletions test/api/api_tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
1 change: 1 addition & 0 deletions test/api/api_tests.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down

0 comments on commit de6a312

Please sign in to comment.