mirror of
https://github.com/pocketpy/pocketpy
synced 2025-11-05 19:20:17 +00:00
Add some dict bindings
This commit is contained in:
parent
8ae999ecdf
commit
f88b1a1436
@ -35,7 +35,7 @@ endif()
|
|||||||
include_directories(${CMAKE_CURRENT_LIST_DIR}/include)
|
include_directories(${CMAKE_CURRENT_LIST_DIR}/include)
|
||||||
file(GLOB_RECURSE POCKETPY_SRC_CPP ${CMAKE_CURRENT_LIST_DIR}/src/*.cpp)
|
file(GLOB_RECURSE POCKETPY_SRC_CPP ${CMAKE_CURRENT_LIST_DIR}/src/*.cpp)
|
||||||
file(GLOB_RECURSE POCKETPY_SRC_C ${CMAKE_CURRENT_LIST_DIR}/src/*.c)
|
file(GLOB_RECURSE POCKETPY_SRC_C ${CMAKE_CURRENT_LIST_DIR}/src/*.c)
|
||||||
set(POCKETPY_SRC ${POCKETPY_SRC_CPP} ${POCKETPY_SRC_C})
|
set(POCKETPY_SRC ${POCKETPY_SRC_C})
|
||||||
|
|
||||||
option(PK_USE_CJSON "" OFF)
|
option(PK_USE_CJSON "" OFF)
|
||||||
if(PK_USE_CJSON)
|
if(PK_USE_CJSON)
|
||||||
@ -95,7 +95,7 @@ elseif(PK_BUILD_STATIC_LIB)
|
|||||||
add_library(${PROJECT_NAME} STATIC ${POCKETPY_SRC})
|
add_library(${PROJECT_NAME} STATIC ${POCKETPY_SRC})
|
||||||
else()
|
else()
|
||||||
set(PROJECT_EXE_NAME main)
|
set(PROJECT_EXE_NAME main)
|
||||||
add_executable(${PROJECT_EXE_NAME} src2/main.cpp)
|
add_executable(${PROJECT_EXE_NAME} src2/main.c)
|
||||||
if (BUILD_TESTING_SANITIZE)
|
if (BUILD_TESTING_SANITIZE)
|
||||||
# static linked main, for sanitizing purpose
|
# static linked main, for sanitizing purpose
|
||||||
add_library(${PROJECT_NAME} STATIC ${POCKETPY_SRC})
|
add_library(${PROJECT_NAME} STATIC ${POCKETPY_SRC})
|
||||||
|
|||||||
@ -44,7 +44,6 @@ pkpy_Dict pkpy_Dict__copy(const pkpy_Dict* self);
|
|||||||
/**
|
/**
|
||||||
* @brief Set a key-value pair into the `pkpy_Dict`
|
* @brief Set a key-value pair into the `pkpy_Dict`
|
||||||
* @param self `pkpy_Dict` instance
|
* @param self `pkpy_Dict` instance
|
||||||
* @param vm __eq__ and __hash__ context
|
|
||||||
* @param key key to set
|
* @param key key to set
|
||||||
* @param val value to set
|
* @param val value to set
|
||||||
* @return `true` if the key is newly added, `false` if the key already exists
|
* @return `true` if the key is newly added, `false` if the key already exists
|
||||||
@ -54,7 +53,6 @@ bool pkpy_Dict__set(pkpy_Dict* self, py_TValue key, py_TValue val);
|
|||||||
/**
|
/**
|
||||||
* @brief Check if a key exists in the `pkpy_Dict`
|
* @brief Check if a key exists in the `pkpy_Dict`
|
||||||
* @param self `pkpy_Dict` instance
|
* @param self `pkpy_Dict` instance
|
||||||
* @param vm __eq__ and __hash__ context
|
|
||||||
* @param key key to check
|
* @param key key to check
|
||||||
* @return `true` if the key exists, `false` otherwise
|
* @return `true` if the key exists, `false` otherwise
|
||||||
*/
|
*/
|
||||||
@ -63,7 +61,6 @@ bool pkpy_Dict__contains(const pkpy_Dict* self, py_TValue key);
|
|||||||
/**
|
/**
|
||||||
* @brief Remove a key from the `pkpy_Dict`
|
* @brief Remove a key from the `pkpy_Dict`
|
||||||
* @param self `pkpy_Dict` instance
|
* @param self `pkpy_Dict` instance
|
||||||
* @param vm __eq__ and __hash__ context
|
|
||||||
* @param key key to remove
|
* @param key key to remove
|
||||||
* @return `true` if the key was found and removed, `false` if the key doesn't exist
|
* @return `true` if the key was found and removed, `false` if the key doesn't exist
|
||||||
*/
|
*/
|
||||||
@ -72,7 +69,6 @@ bool pkpy_Dict__del(pkpy_Dict* self, py_TValue key);
|
|||||||
/**
|
/**
|
||||||
* @brief Try to get a value from the `pkpy_Dict`
|
* @brief Try to get a value from the `pkpy_Dict`
|
||||||
* @param self `pkpy_Dict` instance
|
* @param self `pkpy_Dict` instance
|
||||||
* @param vm __eq__ and __hash__ context
|
|
||||||
* @param key key to get
|
* @param key key to get
|
||||||
* @return the value associated with the key, `NULL` if the key doesn't exist
|
* @return the value associated with the key, `NULL` if the key doesn't exist
|
||||||
*/
|
*/
|
||||||
@ -81,7 +77,6 @@ const py_TValue* pkpy_Dict__try_get(const pkpy_Dict* self, py_TValue key);
|
|||||||
/**
|
/**
|
||||||
* @brief Update the `pkpy_Dict` with another one
|
* @brief Update the `pkpy_Dict` with another one
|
||||||
* @param self `pkpy_Dict` instance
|
* @param self `pkpy_Dict` instance
|
||||||
* @param vm __eq__ and __hash__ context
|
|
||||||
* @param other `pkpy_Dict` instance to update with
|
* @param other `pkpy_Dict` instance to update with
|
||||||
*/
|
*/
|
||||||
void pkpy_Dict__update(pkpy_Dict* self, const pkpy_Dict* other);
|
void pkpy_Dict__update(pkpy_Dict* self, const pkpy_Dict* other);
|
||||||
@ -92,6 +87,15 @@ void pkpy_Dict__update(pkpy_Dict* self, const pkpy_Dict* other);
|
|||||||
*/
|
*/
|
||||||
void pkpy_Dict__clear(pkpy_Dict* self);
|
void pkpy_Dict__clear(pkpy_Dict* self);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Try to pop the latest inserted key-value pair from the `pkpy_Dict`
|
||||||
|
* @param self `pkpy_Dict` instance
|
||||||
|
* @param key key will be filled with the current key, can be `NULL` if not needed
|
||||||
|
* @param value value will be filled with the current value, can be `NULL` if not needed
|
||||||
|
* @return `true` if the operation was successful, `false` if the `pkpy_Dict` is empty
|
||||||
|
*/
|
||||||
|
bool pkpy_Dict__try_pop(pkpy_Dict* self, py_TValue *key, py_TValue *val);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Iterate over the `pkpy_Dict`
|
* @brief Iterate over the `pkpy_Dict`
|
||||||
* @param self `pkpy_Dict` instance
|
* @param self `pkpy_Dict` instance
|
||||||
|
|||||||
@ -118,6 +118,7 @@ bool py_issubclass(py_Type derived, py_Type base);
|
|||||||
#define py_offset(p, i) (py_Ref)((char*)p + ((i) << 4))
|
#define py_offset(p, i) (py_Ref)((char*)p + ((i) << 4))
|
||||||
|
|
||||||
#define TypeError(x) false
|
#define TypeError(x) false
|
||||||
|
#define KeyError(...) false
|
||||||
#define py_arg(i) py_offset(argv, i)
|
#define py_arg(i) py_offset(argv, i)
|
||||||
#define py_checkargc(n) \
|
#define py_checkargc(n) \
|
||||||
if(argc != n) return TypeError()
|
if(argc != n) return TypeError()
|
||||||
|
|||||||
@ -4,13 +4,17 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include "dict.h"
|
||||||
|
|
||||||
#define DICT_MAX_LOAD 0.75
|
#define DICT_MAX_LOAD 0.75
|
||||||
#define DICT_HASH_NEXT(h) ((h) * 5 + 1)
|
#define DICT_HASH_NEXT(h) ((h) * 5 + 1)
|
||||||
#define DICT_HASH_TRANS(h) ((int)((h) & 0xffffffff)) // used for tansform value from __hash__
|
#define DICT_HASH_TRANS(h) ((int)((h) & 0xffffffff)) // used for tansform value from __hash__
|
||||||
#define PK_DICT_COMPACT_MODE 1
|
#define PK_DICT_COMPACT_MODE 1
|
||||||
#define pkpy_Var__is_null(self) ((self)->type == 0)
|
#define pkpy_Var__is_null(self) ((self)->type == 0)
|
||||||
#define pkpy_Var__set_null(self) do { (self)->type = 0; } while(0)
|
#define pkpy_Var__set_null(self) \
|
||||||
|
do { \
|
||||||
|
(self)->type = 0; \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
struct pkpy_DictEntry {
|
struct pkpy_DictEntry {
|
||||||
py_TValue key;
|
py_TValue key;
|
||||||
@ -33,7 +37,9 @@ inline extern int pkpy_Dict__idx_null(const pkpy_Dict* self) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline extern int pkpy_Dict__ht_byte_size(const pkpy_Dict* self) { return self->_htcap * pkpy_Dict__idx_size(self); }
|
inline extern int pkpy_Dict__ht_byte_size(const pkpy_Dict* self) {
|
||||||
|
return self->_htcap * pkpy_Dict__idx_size(self);
|
||||||
|
}
|
||||||
|
|
||||||
void pkpy_Dict__ctor(pkpy_Dict* self) {
|
void pkpy_Dict__ctor(pkpy_Dict* self) {
|
||||||
self->count = 0;
|
self->count = 0;
|
||||||
@ -61,7 +67,7 @@ pkpy_Dict pkpy_Dict__copy(const pkpy_Dict* self) {
|
|||||||
static int pkpy_Dict__htget(const pkpy_Dict* self, int h) {
|
static int pkpy_Dict__htget(const pkpy_Dict* self, int h) {
|
||||||
#if PK_DICT_COMPACT_MODE
|
#if PK_DICT_COMPACT_MODE
|
||||||
const int loc = pkpy_Dict__idx_size(self) * h;
|
const int loc = pkpy_Dict__idx_size(self) * h;
|
||||||
const int *p = (const int*)(((const char*)self->_hashtable) + (loc & (~3)));
|
const int* p = (const int*)(((const char*)self->_hashtable) + (loc & (~3)));
|
||||||
return (*p >> ((loc & 3) * 8)) & pkpy_Dict__idx_null(self);
|
return (*p >> ((loc & 3) * 8)) & pkpy_Dict__idx_null(self);
|
||||||
#else
|
#else
|
||||||
return ((const int*)self->_hashtable)[h];
|
return ((const int*)self->_hashtable)[h];
|
||||||
@ -71,7 +77,7 @@ static int pkpy_Dict__htget(const pkpy_Dict* self, int h) {
|
|||||||
static void pkpy_Dict__htset(pkpy_Dict* self, int h, int v) {
|
static void pkpy_Dict__htset(pkpy_Dict* self, int h, int v) {
|
||||||
#if PK_DICT_COMPACT_MODE
|
#if PK_DICT_COMPACT_MODE
|
||||||
const int loc = pkpy_Dict__idx_size(self) * h;
|
const int loc = pkpy_Dict__idx_size(self) * h;
|
||||||
int *p = (int*)(((char*)self->_hashtable) + (loc & (~3)));
|
int* p = (int*)(((char*)self->_hashtable) + (loc & (~3)));
|
||||||
const int shift = (loc & 3) * 8;
|
const int shift = (loc & 3) * 8;
|
||||||
*p = (v << shift) | (*p & ~(pkpy_Dict__idx_null(self) << shift));
|
*p = (v << shift) | (*p & ~(pkpy_Dict__idx_null(self) << shift));
|
||||||
#else
|
#else
|
||||||
@ -174,7 +180,8 @@ bool pkpy_Dict__contains(const pkpy_Dict* self, py_TValue key) {
|
|||||||
|
|
||||||
static bool pkpy_Dict__refactor(pkpy_Dict* self) {
|
static bool pkpy_Dict__refactor(pkpy_Dict* self) {
|
||||||
int deleted_slots = self->_entries.count - self->count;
|
int deleted_slots = self->_entries.count - self->count;
|
||||||
if(deleted_slots <= 8 || deleted_slots < self->_entries.count * (1 - DICT_MAX_LOAD)) return false;
|
if(deleted_slots <= 8 || deleted_slots < self->_entries.count * (1 - DICT_MAX_LOAD))
|
||||||
|
return false;
|
||||||
|
|
||||||
// shrink
|
// shrink
|
||||||
// free(self->_hashtable);
|
// free(self->_hashtable);
|
||||||
@ -184,10 +191,10 @@ static bool pkpy_Dict__refactor(pkpy_Dict* self) {
|
|||||||
memset(self->_hashtable, 0xff, pkpy_Dict__ht_byte_size(self));
|
memset(self->_hashtable, 0xff, pkpy_Dict__ht_byte_size(self));
|
||||||
|
|
||||||
int new_cnt = 0;
|
int new_cnt = 0;
|
||||||
for (int i = 0; i < self->_entries.count; ++i) {
|
for(int i = 0; i < self->_entries.count; ++i) {
|
||||||
struct pkpy_DictEntry* entry = &c11__getitem(struct pkpy_DictEntry, &self->_entries, i);
|
struct pkpy_DictEntry* entry = &c11__getitem(struct pkpy_DictEntry, &self->_entries, i);
|
||||||
if(pkpy_Var__is_null(&entry->key)) continue;
|
if(pkpy_Var__is_null(&entry->key)) continue;
|
||||||
if (i > new_cnt) c11__setitem(struct pkpy_DictEntry, &self->_entries, new_cnt, *entry);
|
if(i > new_cnt) c11__setitem(struct pkpy_DictEntry, &self->_entries, new_cnt, *entry);
|
||||||
new_cnt += 1;
|
new_cnt += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,7 +227,7 @@ bool pkpy_Dict__del(pkpy_Dict* self, py_TValue key) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const py_TValue *pkpy_Dict__try_get(const pkpy_Dict* self, py_TValue key) {
|
const py_TValue* pkpy_Dict__try_get(const pkpy_Dict* self, py_TValue key) {
|
||||||
int64_t out;
|
int64_t out;
|
||||||
int err = py_hash(&key, &out);
|
int err = py_hash(&key, &out);
|
||||||
int hash = DICT_HASH_TRANS(out);
|
int hash = DICT_HASH_TRANS(out);
|
||||||
@ -233,7 +240,7 @@ const py_TValue *pkpy_Dict__try_get(const pkpy_Dict* self, py_TValue key) {
|
|||||||
return &entry->val;
|
return &entry->val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pkpy_Dict__update(pkpy_Dict *self, const pkpy_Dict *other) {
|
void pkpy_Dict__update(pkpy_Dict* self, const pkpy_Dict* other) {
|
||||||
for(int i = 0; i < other->_entries.count; i++) {
|
for(int i = 0; i < other->_entries.count; i++) {
|
||||||
struct pkpy_DictEntry* entry = &c11__getitem(struct pkpy_DictEntry, &other->_entries, i);
|
struct pkpy_DictEntry* entry = &c11__getitem(struct pkpy_DictEntry, &other->_entries, i);
|
||||||
if(pkpy_Var__is_null(&entry->key)) continue;
|
if(pkpy_Var__is_null(&entry->key)) continue;
|
||||||
@ -241,14 +248,14 @@ void pkpy_Dict__update(pkpy_Dict *self, const pkpy_Dict *other) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pkpy_Dict__clear(pkpy_Dict *self) {
|
void pkpy_Dict__clear(pkpy_Dict* self) {
|
||||||
self->count = 0;
|
self->count = 0;
|
||||||
self->_entries.count = 0;
|
self->_entries.count = 0;
|
||||||
memset(self->_hashtable, 0xff, pkpy_Dict__ht_byte_size(self));
|
memset(self->_hashtable, 0xff, pkpy_Dict__ht_byte_size(self));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pkpy_Dict__next_entry_idx(const pkpy_Dict* self, int idx) {
|
static int pkpy_Dict__next_entry_idx(const pkpy_Dict* self, int idx) {
|
||||||
while (idx < self->_entries.count) {
|
while(idx < self->_entries.count) {
|
||||||
struct pkpy_DictEntry* entry = &c11__getitem(struct pkpy_DictEntry, &self->_entries, idx);
|
struct pkpy_DictEntry* entry = &c11__getitem(struct pkpy_DictEntry, &self->_entries, idx);
|
||||||
if(!pkpy_Var__is_null(&entry->key)) break;
|
if(!pkpy_Var__is_null(&entry->key)) break;
|
||||||
idx++;
|
idx++;
|
||||||
@ -256,20 +263,39 @@ static int pkpy_Dict__next_entry_idx(const pkpy_Dict* self, int idx) {
|
|||||||
return idx;
|
return idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
pkpy_DictIter pkpy_Dict__iter(const pkpy_Dict *self) {
|
bool pkpy_Dict__try_pop(pkpy_Dict* self, py_TValue* key, py_TValue* val) {
|
||||||
|
int idx = self->count - 1;
|
||||||
|
struct pkpy_DictEntry* entry;
|
||||||
|
do {
|
||||||
|
if (idx < 0)
|
||||||
|
return false;
|
||||||
|
entry = &c11__getitem(struct pkpy_DictEntry, &self->_entries, idx);
|
||||||
|
idx--;
|
||||||
|
} while (pkpy_Var__is_null(&entry->key));
|
||||||
|
|
||||||
|
if(key) *key = entry->key;
|
||||||
|
if(val) *val = entry->val;
|
||||||
|
pkpy_Var__set_null(&entry->key);
|
||||||
|
self->count -= 1;
|
||||||
|
pkpy_Dict__refactor(self);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
pkpy_DictIter pkpy_Dict__iter(const pkpy_Dict* self) {
|
||||||
return (pkpy_DictIter){
|
return (pkpy_DictIter){
|
||||||
._dict = self,
|
._dict = self,
|
||||||
._index = pkpy_Dict__next_entry_idx(self, 0),
|
._index = pkpy_Dict__next_entry_idx(self, 0),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pkpy_DictIter__next(pkpy_DictIter *self, py_TValue *key, py_TValue *val) {
|
bool pkpy_DictIter__next(pkpy_DictIter* self, py_TValue* key, py_TValue* val) {
|
||||||
if(self->_index >= self->_dict->_entries.count) return false;
|
if(self->_index >= self->_dict->_entries.count) return false;
|
||||||
|
|
||||||
struct pkpy_DictEntry* entry = &c11__getitem(struct pkpy_DictEntry, &self->_dict->_entries, self->_index);
|
struct pkpy_DictEntry* entry =
|
||||||
|
&c11__getitem(struct pkpy_DictEntry, &self->_dict->_entries, self->_index);
|
||||||
if(pkpy_Var__is_null(&entry->key)) return false;
|
if(pkpy_Var__is_null(&entry->key)) return false;
|
||||||
if (key) *key = entry->key;
|
if(key) *key = entry->key;
|
||||||
if (val) *val = entry->val;
|
if(val) *val = entry->val;
|
||||||
|
|
||||||
self->_index = pkpy_Dict__next_entry_idx(self->_dict, self->_index + 1);
|
self->_index = pkpy_Dict__next_entry_idx(self->_dict, self->_index + 1);
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@ -4,10 +4,224 @@
|
|||||||
#include "pocketpy/objects/object.h"
|
#include "pocketpy/objects/object.h"
|
||||||
#include "pocketpy/interpreter/vm.h"
|
#include "pocketpy/interpreter/vm.h"
|
||||||
|
|
||||||
void py_newdict(py_Ref out){
|
#include "pocketpy/common/vector.h"
|
||||||
|
#include "pocketpy/objects/dict.h"
|
||||||
|
|
||||||
|
py_Type pk_dict__register() {
|
||||||
|
pk_VM* vm = pk_current_vm;
|
||||||
|
py_Type type = pk_VM__new_type(vm, "dict", tp_object, NULL, false);
|
||||||
|
pk_TypeInfo* ti = c11__at(pk_TypeInfo, &vm->types, type);
|
||||||
|
ti->dtor = (void (*)(void*))pkpy_Dict__dtor;
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
void py_newdict(py_Ref out) {
|
||||||
|
pk_VM* vm = pk_current_vm;
|
||||||
|
PyObject* obj = pk_ManagedHeap__gcnew(&vm->heap, tp_dict, 0, sizeof(pkpy_Dict));
|
||||||
|
pkpy_Dict* userdata = PyObject__userdata(obj);
|
||||||
|
pkpy_Dict__ctor(userdata);
|
||||||
|
out->type = tp_dict;
|
||||||
|
out->is_ptr = true;
|
||||||
|
out->_obj = obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
// dict medthods
|
||||||
|
// https://docs.python.org/3/library/stdtypes.html#dict
|
||||||
|
|
||||||
|
// TODO: list(d)
|
||||||
|
|
||||||
|
bool _py_dict__len__(int argc, py_Ref argv) {
|
||||||
|
py_checkargc(1);
|
||||||
|
pkpy_Dict* dict = py_touserdata(py_arg(0));
|
||||||
|
py_newint(py_retval(), dict->count);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _py_dict__getitem__(int argc, py_Ref argv) {
|
||||||
|
py_checkargc(2);
|
||||||
|
pkpy_Dict* dict = py_touserdata(py_arg(0));
|
||||||
|
py_Ref key = py_arg(1);
|
||||||
|
py_TValue* val = pkpy_Dict__try_get(dict, *key);
|
||||||
|
if (val) {
|
||||||
|
*py_retval() = *val;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return KeyError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _py_dict__setitem__(int argc, py_Ref argv) {
|
||||||
|
py_checkargc(3);
|
||||||
|
pkpy_Dict* dict = py_touserdata(py_arg(0));
|
||||||
|
py_Ref key = py_arg(1), val = py_arg(2);
|
||||||
|
pkpy_Dict__set(dict, *key, *val);
|
||||||
|
py_newnone(py_retval());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _py_dict__delitem__(int argc, py_Ref argv) {
|
||||||
|
py_checkargc(2);
|
||||||
|
pkpy_Dict* dict = py_touserdata(py_arg(0));
|
||||||
|
py_Ref key = py_arg(1);
|
||||||
|
pkpy_Dict__del(dict, *key);
|
||||||
|
py_newnone(py_retval());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _py_dict__contains__(int argc, py_Ref argv) {
|
||||||
|
py_checkargc(2);
|
||||||
|
pkpy_Dict* dict = py_touserdata(py_arg(0));
|
||||||
|
py_Ref key = py_arg(1);
|
||||||
|
py_newbool(py_retval(), pkpy_Dict__contains(dict, *key));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: iter(d)
|
||||||
|
|
||||||
|
bool _py_dict__clear(int argc, py_Ref argv) {
|
||||||
|
py_checkargc(1);
|
||||||
|
pkpy_Dict* dict = py_touserdata(py_arg(0));
|
||||||
|
pkpy_Dict__clear(dict);
|
||||||
|
py_newnone(py_retval());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _py_dict__copy(int argc, py_Ref argv) {
|
||||||
|
py_checkargc(1);
|
||||||
|
pkpy_Dict* dict = py_touserdata(py_arg(0));
|
||||||
|
py_Ref ret = py_retval();
|
||||||
|
py_newdict(ret);
|
||||||
|
pkpy_Dict__update(py_touserdata(ret), dict);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: classmethod fromkeys
|
||||||
|
|
||||||
|
bool _py_dict__get(int argc, py_Ref argv) {
|
||||||
|
if (argc < 2 || argc > 3)
|
||||||
|
return TypeError();
|
||||||
|
|
||||||
|
pkpy_Dict* dict = py_touserdata(py_arg(0));
|
||||||
|
py_Ref key = py_arg(1);
|
||||||
|
py_TValue* val = pkpy_Dict__try_get(dict, *key);
|
||||||
|
if (val) {
|
||||||
|
*py_retval() = *val;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc == 3)
|
||||||
|
*py_retval() = *py_arg(2);
|
||||||
|
else
|
||||||
|
py_newnone(py_retval());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: method items
|
||||||
|
|
||||||
|
// TODO: method keys
|
||||||
|
|
||||||
|
bool _py_dict__pop(int argc, py_Ref argv) {
|
||||||
|
if (argc < 2 || argc > 3)
|
||||||
|
return TypeError();
|
||||||
|
|
||||||
|
pkpy_Dict* dict = py_touserdata(py_arg(0));
|
||||||
|
py_Ref key = py_arg(1);
|
||||||
|
py_TValue* val = pkpy_Dict__try_get(dict, *key);
|
||||||
|
if (val) {
|
||||||
|
pkpy_Dict__del(dict, *key);
|
||||||
|
*py_retval() = *val;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc == 3) {
|
||||||
|
*py_retval() = *py_arg(2);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return KeyError();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _py_dict__popitem(int argc, py_Ref argv) {
|
||||||
|
py_checkargc(1);
|
||||||
|
|
||||||
|
pkpy_Dict* dict = py_touserdata(py_arg(0));
|
||||||
|
py_StackRef key = py_pushtmp(), val = py_pushtmp();
|
||||||
|
|
||||||
|
py_Ref ret = py_retval();
|
||||||
|
if (pkpy_Dict__try_pop(dict, key, val)) {
|
||||||
|
py_newtuple(ret, 2);
|
||||||
|
py_setslot(ret, 0, key);
|
||||||
|
py_setslot(ret, 1, val);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return KeyError();
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://docs.python.org/3/library/stdtypes.html#dict-views
|
||||||
|
// TODO: dict_keys, dict_values, dict_items
|
||||||
|
// TODO: dict_iterator, dict_keyiterator, dict_valueiterator
|
||||||
|
|
||||||
|
// TODO: reversed(d)
|
||||||
|
|
||||||
|
bool _py_dict__setdefault(int argc, py_Ref argv) {
|
||||||
|
if (argc < 2 || argc > 3)
|
||||||
|
return TypeError();
|
||||||
|
|
||||||
|
pkpy_Dict* dict = py_touserdata(py_arg(0));
|
||||||
|
py_Ref key = py_arg(1);
|
||||||
|
py_TValue* val = pkpy_Dict__try_get(dict, *key);
|
||||||
|
if (val) {
|
||||||
|
*py_retval() = *val;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
py_Ref dft;
|
||||||
|
if (argc == 3) {
|
||||||
|
dft = py_arg(2);
|
||||||
|
} else {
|
||||||
|
dft = py_pushtmp();
|
||||||
|
py_newnone(dft);
|
||||||
|
}
|
||||||
|
|
||||||
|
pkpy_Dict__set(dict, *key, *dft);
|
||||||
|
*py_retval() = *dft;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _py_dict__update(int argc, py_Ref argv) {
|
||||||
|
// TODO: accept kwargs
|
||||||
|
py_checkargc(2);
|
||||||
|
|
||||||
|
pkpy_Dict* me = py_touserdata(py_arg(0));
|
||||||
|
pkpy_Dict* other = py_touserdata(py_arg(1));
|
||||||
|
pkpy_Dict__update(me, other);
|
||||||
|
py_newnone(py_retval());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: method values
|
||||||
|
|
||||||
|
bool _py_dict__or__(int argc, py_Ref argv) {
|
||||||
|
py_checkargc(2);
|
||||||
|
|
||||||
|
pkpy_Dict* me = py_touserdata(py_arg(0));
|
||||||
|
pkpy_Dict* other = py_touserdata(py_arg(1));
|
||||||
|
|
||||||
|
py_Ref ret = py_retval();
|
||||||
|
py_newdict(ret);
|
||||||
|
pkpy_Dict__update(py_touserdata(ret), me);
|
||||||
|
pkpy_Dict__update(py_touserdata(ret), other);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: method operator |=
|
||||||
|
|
||||||
|
py_Type pk_set__register() {
|
||||||
|
// TODO: implement
|
||||||
}
|
}
|
||||||
|
|
||||||
void py_newset(py_Ref out){
|
void py_newset(py_Ref out){
|
||||||
|
// TODO: implement
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user