Functions for operating on Maps from C (#725)

new API functions for maps:
wrenSetSlotNewMap
wrenGetMapCount
wrenGetMapContainsKey
wrenGetMapValue
wrenSetMapValue
wrenRemoveMapValue
This commit is contained in:
Aviv Beeri
2020-06-14 22:45:23 +01:00
committed by GitHub
parent 344d3432b3
commit de6a312868
19 changed files with 374 additions and 7 deletions

View File

@ -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;

View File

@ -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
View 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
View 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
View 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.

View File

@ -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;
}

View File

@ -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