mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 11:30:18 +00:00
This commit is contained in:
parent
6bda10cce8
commit
9e27f4f146
142
src/dict.h
142
src/dict.h
@ -8,23 +8,40 @@
|
|||||||
namespace pkpy{
|
namespace pkpy{
|
||||||
|
|
||||||
struct Dict{
|
struct Dict{
|
||||||
using Item = std::pair<PyObject*, PyObject*>;
|
struct Item{
|
||||||
|
PyObject* first;
|
||||||
|
PyObject* second;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ItemNode{
|
||||||
|
int prev;
|
||||||
|
int next;
|
||||||
|
};
|
||||||
|
|
||||||
static constexpr int __Capacity = 8;
|
static constexpr int __Capacity = 8;
|
||||||
static constexpr float __LoadFactor = 0.67f;
|
static constexpr float __LoadFactor = 0.67f;
|
||||||
|
// by ensuring this, we can use pool64 to alloc ItemNode and pool128 to alloc Item
|
||||||
|
static_assert(sizeof(Item) == 2*sizeof(ItemNode));
|
||||||
static_assert(sizeof(Item) * __Capacity <= 128);
|
static_assert(sizeof(Item) * __Capacity <= 128);
|
||||||
|
static_assert(sizeof(ItemNode) * __Capacity <= 64);
|
||||||
|
|
||||||
VM* vm;
|
VM* vm;
|
||||||
int _capacity;
|
int _capacity;
|
||||||
int _mask;
|
int _mask;
|
||||||
int _size;
|
int _size;
|
||||||
int _critical_size;
|
int _critical_size;
|
||||||
|
int _head_idx; // for order preserving
|
||||||
|
int _tail_idx; // for order preserving
|
||||||
Item* _items;
|
Item* _items;
|
||||||
|
ItemNode* _nodes; // for order preserving
|
||||||
|
|
||||||
Dict(VM* vm): vm(vm), _capacity(__Capacity),
|
Dict(VM* vm): vm(vm), _capacity(__Capacity),
|
||||||
_mask(__Capacity-1),
|
_mask(__Capacity-1),
|
||||||
_size(0), _critical_size(__Capacity*__LoadFactor+0.5f){
|
_size(0), _critical_size(__Capacity*__LoadFactor+0.5f), _head_idx(-1), _tail_idx(-1){
|
||||||
_items = (Item*)pool128.alloc(_capacity * sizeof(Item));
|
_items = (Item*)pool128.alloc(_capacity * sizeof(Item));
|
||||||
memset(_items, 0, _capacity * sizeof(Item));
|
memset(_items, 0, _capacity * sizeof(Item));
|
||||||
|
_nodes = (ItemNode*)pool64.alloc(_capacity * sizeof(ItemNode));
|
||||||
|
memset(_nodes, -1, _capacity * sizeof(ItemNode));
|
||||||
}
|
}
|
||||||
|
|
||||||
int size() const { return _size; }
|
int size() const { return _size; }
|
||||||
@ -35,8 +52,12 @@ struct Dict{
|
|||||||
_mask = other._mask;
|
_mask = other._mask;
|
||||||
_size = other._size;
|
_size = other._size;
|
||||||
_critical_size = other._critical_size;
|
_critical_size = other._critical_size;
|
||||||
|
_head_idx = other._head_idx;
|
||||||
|
_tail_idx = other._tail_idx;
|
||||||
_items = other._items;
|
_items = other._items;
|
||||||
|
_nodes = other._nodes;
|
||||||
other._items = nullptr;
|
other._items = nullptr;
|
||||||
|
other._nodes = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Dict(const Dict& other){
|
Dict(const Dict& other){
|
||||||
@ -45,8 +66,12 @@ struct Dict{
|
|||||||
_mask = other._mask;
|
_mask = other._mask;
|
||||||
_size = other._size;
|
_size = other._size;
|
||||||
_critical_size = other._critical_size;
|
_critical_size = other._critical_size;
|
||||||
|
_head_idx = other._head_idx;
|
||||||
|
_tail_idx = other._tail_idx;
|
||||||
_items = (Item*)pool128.alloc(_capacity * sizeof(Item));
|
_items = (Item*)pool128.alloc(_capacity * sizeof(Item));
|
||||||
memcpy(_items, other._items, _capacity * sizeof(Item));
|
memcpy(_items, other._items, _capacity * sizeof(Item));
|
||||||
|
_nodes = (ItemNode*)pool64.alloc(_capacity * sizeof(ItemNode));
|
||||||
|
memcpy(_nodes, other._nodes, _capacity * sizeof(ItemNode));
|
||||||
}
|
}
|
||||||
|
|
||||||
Dict& operator=(const Dict&) = delete;
|
Dict& operator=(const Dict&) = delete;
|
||||||
@ -55,15 +80,23 @@ struct Dict{
|
|||||||
void _probe(PyObject* key, bool& ok, int& i) const;
|
void _probe(PyObject* key, bool& ok, int& i) const;
|
||||||
|
|
||||||
void set(PyObject* key, PyObject* val){
|
void set(PyObject* key, PyObject* val){
|
||||||
|
// do possible rehash
|
||||||
|
if(_size+1 > _critical_size) _rehash();
|
||||||
bool ok; int i;
|
bool ok; int i;
|
||||||
_probe(key, ok, i);
|
_probe(key, ok, i);
|
||||||
if(!ok) {
|
if(!ok) {
|
||||||
_size++;
|
_size++;
|
||||||
if(_size > _critical_size){
|
|
||||||
_rehash();
|
|
||||||
_probe(key, ok, i);
|
|
||||||
}
|
|
||||||
_items[i].first = key;
|
_items[i].first = key;
|
||||||
|
|
||||||
|
// append to tail
|
||||||
|
if(_size == 0+1){
|
||||||
|
_head_idx = i;
|
||||||
|
_tail_idx = i;
|
||||||
|
}else{
|
||||||
|
_nodes[i].prev = _tail_idx;
|
||||||
|
_nodes[_tail_idx].next = i;
|
||||||
|
_tail_idx = i;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_items[i].second = val;
|
_items[i].second = val;
|
||||||
}
|
}
|
||||||
@ -73,15 +106,19 @@ struct Dict{
|
|||||||
int old_capacity = _capacity;
|
int old_capacity = _capacity;
|
||||||
_capacity *= 2;
|
_capacity *= 2;
|
||||||
_mask = _capacity - 1;
|
_mask = _capacity - 1;
|
||||||
_critical_size = _capacity * __LoadFactor + 0.5f;
|
_size = 0;
|
||||||
|
_critical_size = _capacity*__LoadFactor+0.5f;
|
||||||
|
_head_idx = -1;
|
||||||
|
_tail_idx = -1;
|
||||||
|
pool64.dealloc(_nodes);
|
||||||
_items = (Item*)pool128.alloc(_capacity * sizeof(Item));
|
_items = (Item*)pool128.alloc(_capacity * sizeof(Item));
|
||||||
memset(_items, 0, _capacity * sizeof(Item));
|
memset(_items, 0, _capacity * sizeof(Item));
|
||||||
|
_nodes = (ItemNode*)pool64.alloc(_capacity * sizeof(ItemNode));
|
||||||
|
memset(_nodes, -1, _capacity * sizeof(ItemNode));
|
||||||
|
|
||||||
for(int i=0; i<old_capacity; i++){
|
for(int i=0; i<old_capacity; i++){
|
||||||
if(old_items[i].first == nullptr) continue;
|
if(old_items[i].first == nullptr) continue;
|
||||||
bool ok; int j;
|
set(old_items[i].first, old_items[i].second);
|
||||||
_probe(old_items[i].first, ok, j);
|
|
||||||
if(ok) FATAL_ERROR();
|
|
||||||
_items[j] = old_items[i];
|
|
||||||
}
|
}
|
||||||
pool128.dealloc(old_items);
|
pool128.dealloc(old_items);
|
||||||
}
|
}
|
||||||
@ -106,45 +143,82 @@ struct Dict{
|
|||||||
_items[i].first = nullptr;
|
_items[i].first = nullptr;
|
||||||
_items[i].second = nullptr;
|
_items[i].second = nullptr;
|
||||||
_size--;
|
_size--;
|
||||||
|
|
||||||
|
if(_size == 0){
|
||||||
|
_head_idx = -1;
|
||||||
|
_tail_idx = -1;
|
||||||
|
}else{
|
||||||
|
if(_head_idx == i){
|
||||||
|
_head_idx = _nodes[i].next;
|
||||||
|
_nodes[_head_idx].prev = -1;
|
||||||
|
}else if(_tail_idx == i){
|
||||||
|
_tail_idx = _nodes[i].prev;
|
||||||
|
_nodes[_tail_idx].next = -1;
|
||||||
|
}else{
|
||||||
|
_nodes[_nodes[i].prev].next = _nodes[i].next;
|
||||||
|
_nodes[_nodes[i].next].prev = _nodes[i].prev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_nodes[i].prev = -1;
|
||||||
|
_nodes[i].next = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void update(const Dict& other){
|
void update(const Dict& other){
|
||||||
for(int i=0; i<other._capacity; i++){
|
other.apply([&](PyObject* k, PyObject* v){ set(k, v); });
|
||||||
if(other._items[i].first == nullptr) continue;
|
|
||||||
set(other._items[i].first, other._items[i].second);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<Item> items() const {
|
|
||||||
std::vector<Item> v;
|
|
||||||
for(int i=0; i<_capacity; i++){
|
|
||||||
if(_items[i].first == nullptr) continue;
|
|
||||||
v.push_back(_items[i]);
|
|
||||||
}
|
|
||||||
return v;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename __Func>
|
template<typename __Func>
|
||||||
void apply(__Func f) const {
|
void apply(__Func f) const {
|
||||||
for(int i=0; i<_capacity; i++){
|
int i = _head_idx;
|
||||||
if(_items[i].first == nullptr) continue;
|
while(i != -1){
|
||||||
f(_items[i].first, _items[i].second);
|
f(_items[i].first, _items[i].second);
|
||||||
|
i = _nodes[i].next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Tuple keys() const{
|
||||||
|
Tuple t(_size);
|
||||||
|
int i = _head_idx;
|
||||||
|
int j = 0;
|
||||||
|
while(i != -1){
|
||||||
|
t[j++] = _items[i].first;
|
||||||
|
i = _nodes[i].next;
|
||||||
|
}
|
||||||
|
PK_ASSERT(j == _size);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
Tuple values() const{
|
||||||
|
Tuple t(_size);
|
||||||
|
int i = _head_idx;
|
||||||
|
int j = 0;
|
||||||
|
while(i != -1){
|
||||||
|
t[j++] = _items[i].second;
|
||||||
|
i = _nodes[i].next;
|
||||||
|
}
|
||||||
|
PK_ASSERT(j == _size);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
void clear(){
|
void clear(){
|
||||||
memset(_items, 0, _capacity * sizeof(Item));
|
|
||||||
_size = 0;
|
_size = 0;
|
||||||
|
_head_idx = -1;
|
||||||
|
_tail_idx = -1;
|
||||||
|
memset(_items, 0, _capacity * sizeof(Item));
|
||||||
|
memset(_nodes, -1, _capacity * sizeof(ItemNode));
|
||||||
}
|
}
|
||||||
|
|
||||||
~Dict(){ if(_items!=nullptr) pool128.dealloc(_items); }
|
~Dict(){
|
||||||
|
if(_items==nullptr) return;
|
||||||
|
pool128.dealloc(_items);
|
||||||
|
pool64.dealloc(_nodes);
|
||||||
|
}
|
||||||
|
|
||||||
void _gc_mark() const{
|
void _gc_mark() const{
|
||||||
for(int i=0; i<_capacity; i++){
|
apply([](PyObject* k, PyObject* v){
|
||||||
if(_items[i].first == nullptr) continue;
|
PK_OBJ_MARK(k);
|
||||||
PK_OBJ_MARK(_items[i].first);
|
PK_OBJ_MARK(v);
|
||||||
PK_OBJ_MARK(_items[i].second);
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
58
src/easing.h
58
src/easing.h
@ -12,31 +12,31 @@ namespace pkpy{
|
|||||||
|
|
||||||
static const double PI = 3.1415926545;
|
static const double PI = 3.1415926545;
|
||||||
|
|
||||||
inline static double easeLinear( double x ) {
|
static double easeLinear( double x ) {
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static double easeInSine( double x ) {
|
static double easeInSine( double x ) {
|
||||||
return 1.0 - std::cos( x * PI / 2 );
|
return 1.0 - std::cos( x * PI / 2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static double easeOutSine( double x ) {
|
static double easeOutSine( double x ) {
|
||||||
return std::sin( x * PI / 2 );
|
return std::sin( x * PI / 2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static double easeInOutSine( double x ) {
|
static double easeInOutSine( double x ) {
|
||||||
return -( std::cos( PI * x ) - 1 ) / 2;
|
return -( std::cos( PI * x ) - 1 ) / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static double easeInQuad( double x ) {
|
static double easeInQuad( double x ) {
|
||||||
return x * x;
|
return x * x;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static double easeOutQuad( double x ) {
|
static double easeOutQuad( double x ) {
|
||||||
return 1 - std::pow( 1 - x, 2 );
|
return 1 - std::pow( 1 - x, 2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static double easeInOutQuad( double x ) {
|
static double easeInOutQuad( double x ) {
|
||||||
if( x < 0.5 ) {
|
if( x < 0.5 ) {
|
||||||
return 2 * x * x;
|
return 2 * x * x;
|
||||||
} else {
|
} else {
|
||||||
@ -44,15 +44,15 @@ inline static double easeInOutQuad( double x ) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static double easeInCubic( double x ) {
|
static double easeInCubic( double x ) {
|
||||||
return x * x * x;
|
return x * x * x;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static double easeOutCubic( double x ) {
|
static double easeOutCubic( double x ) {
|
||||||
return 1 - std::pow( 1 - x, 3 );
|
return 1 - std::pow( 1 - x, 3 );
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static double easeInOutCubic( double x ) {
|
static double easeInOutCubic( double x ) {
|
||||||
if( x < 0.5 ) {
|
if( x < 0.5 ) {
|
||||||
return 4 * x * x * x;
|
return 4 * x * x * x;
|
||||||
} else {
|
} else {
|
||||||
@ -60,15 +60,15 @@ inline static double easeInOutCubic( double x ) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static double easeInQuart( double x ) {
|
static double easeInQuart( double x ) {
|
||||||
return std::pow( x, 4 );
|
return std::pow( x, 4 );
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static double easeOutQuart( double x ) {
|
static double easeOutQuart( double x ) {
|
||||||
return 1 - std::pow( 1 - x, 4 );
|
return 1 - std::pow( 1 - x, 4 );
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static double easeInOutQuart( double x ) {
|
static double easeInOutQuart( double x ) {
|
||||||
if( x < 0.5 ) {
|
if( x < 0.5 ) {
|
||||||
return 8 * std::pow( x, 4 );
|
return 8 * std::pow( x, 4 );
|
||||||
} else {
|
} else {
|
||||||
@ -76,15 +76,15 @@ inline static double easeInOutQuart( double x ) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static double easeInQuint( double x ) {
|
static double easeInQuint( double x ) {
|
||||||
return std::pow( x, 5 );
|
return std::pow( x, 5 );
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static double easeOutQuint( double x ) {
|
static double easeOutQuint( double x ) {
|
||||||
return 1 - std::pow( 1 - x, 5 );
|
return 1 - std::pow( 1 - x, 5 );
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static double easeInOutQuint( double x ) {
|
static double easeInOutQuint( double x ) {
|
||||||
if( x < 0.5 ) {
|
if( x < 0.5 ) {
|
||||||
return 16 * std::pow( x, 5 );
|
return 16 * std::pow( x, 5 );
|
||||||
} else {
|
} else {
|
||||||
@ -92,11 +92,11 @@ inline static double easeInOutQuint( double x ) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static double easeInExpo( double x ) {
|
static double easeInExpo( double x ) {
|
||||||
return x == 0 ? 0 : std::pow( 2, 10 * x - 10 );
|
return x == 0 ? 0 : std::pow( 2, 10 * x - 10 );
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static double easeOutExpo( double x ) {
|
static double easeOutExpo( double x ) {
|
||||||
return x == 1 ? 1 : 1 - std::pow( 2, -10 * x );
|
return x == 1 ? 1 : 1 - std::pow( 2, -10 * x );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,15 +112,15 @@ inline double easeInOutExpo( double x ) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static double easeInCirc( double x ) {
|
static double easeInCirc( double x ) {
|
||||||
return 1 - std::sqrt( 1 - std::pow( x, 2 ) );
|
return 1 - std::sqrt( 1 - std::pow( x, 2 ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static double easeOutCirc( double x ) {
|
static double easeOutCirc( double x ) {
|
||||||
return std::sqrt( 1 - std::pow( x - 1, 2 ) );
|
return std::sqrt( 1 - std::pow( x - 1, 2 ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static double easeInOutCirc( double x ) {
|
static double easeInOutCirc( double x ) {
|
||||||
if( x < 0.5 ) {
|
if( x < 0.5 ) {
|
||||||
return (1 - std::sqrt( 1 - std::pow( 2 * x, 2 ) )) / 2;
|
return (1 - std::sqrt( 1 - std::pow( 2 * x, 2 ) )) / 2;
|
||||||
} else {
|
} else {
|
||||||
@ -128,19 +128,19 @@ inline static double easeInOutCirc( double x ) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static double easeInBack( double x ) {
|
static double easeInBack( double x ) {
|
||||||
const double c1 = 1.70158;
|
const double c1 = 1.70158;
|
||||||
const double c3 = c1 + 1;
|
const double c3 = c1 + 1;
|
||||||
return c3 * x * x * x - c1 * x * x;
|
return c3 * x * x * x - c1 * x * x;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static double easeOutBack( double x ) {
|
static double easeOutBack( double x ) {
|
||||||
const double c1 = 1.70158;
|
const double c1 = 1.70158;
|
||||||
const double c3 = c1 + 1;
|
const double c3 = c1 + 1;
|
||||||
return 1 + c3 * std::pow( x - 1, 3 ) + c1 * std::pow( x - 1, 2 );
|
return 1 + c3 * std::pow( x - 1, 3 ) + c1 * std::pow( x - 1, 2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static double easeInOutBack( double x ) {
|
static double easeInOutBack( double x ) {
|
||||||
const double c1 = 1.70158;
|
const double c1 = 1.70158;
|
||||||
const double c2 = c1 * 1.525;
|
const double c2 = c1 * 1.525;
|
||||||
if( x < 0.5 ) {
|
if( x < 0.5 ) {
|
||||||
@ -150,7 +150,7 @@ inline static double easeInOutBack( double x ) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static double easeInElastic( double x ) {
|
static double easeInElastic( double x ) {
|
||||||
const double c4 = (2 * PI) / 3;
|
const double c4 = (2 * PI) / 3;
|
||||||
if( x == 0 ) {
|
if( x == 0 ) {
|
||||||
return 0;
|
return 0;
|
||||||
@ -161,7 +161,7 @@ inline static double easeInElastic( double x ) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static double easeOutElastic( double x ) {
|
static double easeOutElastic( double x ) {
|
||||||
const double c4 = (2 * PI) / 3;
|
const double c4 = (2 * PI) / 3;
|
||||||
if( x == 0 ) {
|
if( x == 0 ) {
|
||||||
return 0;
|
return 0;
|
||||||
@ -185,7 +185,7 @@ inline double easeInOutElastic( double x ) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static double easeOutBounce( double x ) {
|
static double easeOutBounce( double x ) {
|
||||||
const double n1 = 7.5625;
|
const double n1 = 7.5625;
|
||||||
const double d1 = 2.75;
|
const double d1 = 2.75;
|
||||||
if( x < 1 / d1 ) {
|
if( x < 1 / d1 ) {
|
||||||
@ -202,11 +202,11 @@ inline static double easeOutBounce( double x ) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline double easeInBounce( double x ) {
|
static double easeInBounce( double x ) {
|
||||||
return 1 - easeOutBounce(1 - x);
|
return 1 - easeOutBounce(1 - x);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static double easeInOutBounce( double x ) {
|
static double easeInOutBounce( double x ) {
|
||||||
return x < 0.5
|
return x < 0.5
|
||||||
? (1 - easeOutBounce(1 - 2 * x)) / 2
|
? (1 - easeOutBounce(1 - 2 * x)) / 2
|
||||||
: (1 + easeOutBounce(2 * x - 1)) / 2;
|
: (1 + easeOutBounce(2 * x - 1)) / 2;
|
||||||
|
@ -249,11 +249,6 @@ struct MemoryPool{
|
|||||||
inline MemoryPool<64> pool64;
|
inline MemoryPool<64> pool64;
|
||||||
inline MemoryPool<128> pool128;
|
inline MemoryPool<128> pool128;
|
||||||
|
|
||||||
// get the total memory usage of pkpy (across all VMs)
|
|
||||||
inline size_t memory_usage(){
|
|
||||||
return pool64.allocated_size() + pool128.allocated_size();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct shared_ptr {
|
struct shared_ptr {
|
||||||
int* counter;
|
int* counter;
|
||||||
|
@ -1058,11 +1058,8 @@ inline void init_builtins(VM* _vm) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind__iter__(_vm->tp_dict, [](VM* vm, PyObject* obj) {
|
_vm->bind__iter__(_vm->tp_dict, [](VM* vm, PyObject* obj) {
|
||||||
Dict& self = _CAST(Dict&, obj);
|
const Dict& self = _CAST(Dict&, obj);
|
||||||
auto items = self.items();
|
return vm->py_iter(VAR(self.keys()));
|
||||||
Tuple t(items.size());
|
|
||||||
for(int i=0; i<items.size(); i++) t[i] = items[i].first;
|
|
||||||
return vm->py_iter(VAR(std::move(t)));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind_method<-1>("dict", "get", [](VM* vm, ArgsView args) {
|
_vm->bind_method<-1>("dict", "get", [](VM* vm, ArgsView args) {
|
||||||
@ -1081,26 +1078,22 @@ inline void init_builtins(VM* _vm) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind_method<0>("dict", "keys", [](VM* vm, ArgsView args) {
|
_vm->bind_method<0>("dict", "keys", [](VM* vm, ArgsView args) {
|
||||||
Dict& self = _CAST(Dict&, args[0]);
|
const Dict& self = _CAST(Dict&, args[0]);
|
||||||
List keys;
|
return VAR(self.keys());
|
||||||
for(auto& item : self.items()) keys.push_back(item.first);
|
|
||||||
return VAR(std::move(keys));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind_method<0>("dict", "values", [](VM* vm, ArgsView args) {
|
_vm->bind_method<0>("dict", "values", [](VM* vm, ArgsView args) {
|
||||||
Dict& self = _CAST(Dict&, args[0]);
|
const Dict& self = _CAST(Dict&, args[0]);
|
||||||
List values;
|
return VAR(self.values());
|
||||||
for(auto& item : self.items()) values.push_back(item.second);
|
|
||||||
return VAR(std::move(values));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind_method<0>("dict", "items", [](VM* vm, ArgsView args) {
|
_vm->bind_method<0>("dict", "items", [](VM* vm, ArgsView args) {
|
||||||
Dict& self = _CAST(Dict&, args[0]);
|
const Dict& self = _CAST(Dict&, args[0]);
|
||||||
List items;
|
Tuple items(self.size());
|
||||||
for(auto& item : self.items()){
|
int j = 0;
|
||||||
PyObject* t = VAR(Tuple({item.first, item.second}));
|
self.apply([&](PyObject* k, PyObject* v){
|
||||||
items.push_back(std::move(t));
|
items[j++] = VAR(Tuple({k, v}));
|
||||||
}
|
});
|
||||||
return VAR(std::move(items));
|
return VAR(std::move(items));
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1127,13 +1120,15 @@ inline void init_builtins(VM* _vm) {
|
|||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "{";
|
ss << "{";
|
||||||
bool first = true;
|
bool first = true;
|
||||||
for(auto& item : self.items()){
|
|
||||||
|
self.apply([&](PyObject* k, PyObject* v){
|
||||||
if(!first) ss << ", ";
|
if(!first) ss << ", ";
|
||||||
first = false;
|
first = false;
|
||||||
Str key = CAST(Str&, vm->py_repr(item.first));
|
Str key = CAST(Str&, vm->py_repr(k));
|
||||||
Str value = CAST(Str&, vm->py_repr(item.second));
|
Str value = CAST(Str&, vm->py_repr(v));
|
||||||
ss << key << ": " << value;
|
ss << key << ": " << value;
|
||||||
}
|
});
|
||||||
|
|
||||||
ss << "}";
|
ss << "}";
|
||||||
return VAR(ss.str());
|
return VAR(ss.str());
|
||||||
});
|
});
|
||||||
@ -1143,13 +1138,15 @@ inline void init_builtins(VM* _vm) {
|
|||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "{";
|
ss << "{";
|
||||||
bool first = true;
|
bool first = true;
|
||||||
for(auto& item : self.items()){
|
|
||||||
|
self.apply([&](PyObject* k, PyObject* v){
|
||||||
if(!first) ss << ", ";
|
if(!first) ss << ", ";
|
||||||
first = false;
|
first = false;
|
||||||
Str key = CAST(Str&, item.first).escape(false);
|
Str key = CAST(Str&, k).escape(false);
|
||||||
Str value = CAST(Str&, vm->py_json(item.second));
|
Str value = CAST(Str&, vm->py_json(v));
|
||||||
ss << key << ": " << value;
|
ss << key << ": " << value;
|
||||||
}
|
});
|
||||||
|
|
||||||
ss << "}";
|
ss << "}";
|
||||||
return VAR(ss.str());
|
return VAR(ss.str());
|
||||||
});
|
});
|
||||||
@ -1159,7 +1156,9 @@ inline void init_builtins(VM* _vm) {
|
|||||||
if(!is_non_tagged_type(b, vm->tp_dict)) return vm->NotImplemented;
|
if(!is_non_tagged_type(b, vm->tp_dict)) return vm->NotImplemented;
|
||||||
Dict& other = _CAST(Dict&, b);
|
Dict& other = _CAST(Dict&, b);
|
||||||
if(self.size() != other.size()) return vm->False;
|
if(self.size() != other.size()) return vm->False;
|
||||||
for(auto& item : self.items()){
|
for(int i=0; i<self._capacity; i++){
|
||||||
|
auto item = self._items[i];
|
||||||
|
if(item.first == nullptr) continue;
|
||||||
PyObject* value = other.try_get(item.first);
|
PyObject* value = other.try_get(item.first);
|
||||||
if(value == nullptr) return vm->False;
|
if(value == nullptr) return vm->False;
|
||||||
if(!vm->py_equals(item.second, value)) return vm->False;
|
if(!vm->py_equals(item.second, value)) return vm->False;
|
||||||
|
3
src/vm.h
3
src/vm.h
@ -1604,7 +1604,8 @@ inline void Dict::_probe(PyObject *key, bool &ok, int &i) const{
|
|||||||
i = vm->py_hash(key) & _mask;
|
i = vm->py_hash(key) & _mask;
|
||||||
while(_items[i].first != nullptr) {
|
while(_items[i].first != nullptr) {
|
||||||
if(vm->py_equals(_items[i].first, key)) { ok = true; break; }
|
if(vm->py_equals(_items[i].first, key)) { ok = true; break; }
|
||||||
i = (i + 1) & _mask;
|
// https://github.com/python/cpython/blob/3.8/Objects/dictobject.c#L166
|
||||||
|
i = ((5*i) + 1) & _mask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,10 +26,9 @@ assert len(tinydict) == 3
|
|||||||
assert tinydict == updated_dict
|
assert tinydict == updated_dict
|
||||||
|
|
||||||
dishes = {'eggs': 2, 'sausage': 1, 'bacon': 1, 'spam': 500}
|
dishes = {'eggs': 2, 'sausage': 1, 'bacon': 1, 'spam': 500}
|
||||||
keys = dishes.keys()
|
# dict is now ordered
|
||||||
values = dishes.values()
|
assert dishes.keys() == ('eggs', 'sausage', 'bacon', 'spam')
|
||||||
assert sorted(keys) == sorted(['eggs', 'sausage', 'bacon', 'spam'])
|
assert dishes.values() == (2, 1, 1, 500)
|
||||||
assert sorted(values) == sorted([2, 1, 1, 500])
|
|
||||||
|
|
||||||
d={1:"a",2:"b",3:"c"}
|
d={1:"a",2:"b",3:"c"}
|
||||||
result=[]
|
result=[]
|
||||||
@ -37,7 +36,14 @@ for k,v in d.items():
|
|||||||
result.append(k)
|
result.append(k)
|
||||||
result.append(v)
|
result.append(v)
|
||||||
assert len(result) == 6
|
assert len(result) == 6
|
||||||
assert set(result) == set([1, 'a', 2, 'b', 3, 'c'])
|
|
||||||
|
del d[2]
|
||||||
|
assert len(d) == 2
|
||||||
|
assert d.keys() == (1, 3)
|
||||||
|
assert d.values() == ('a', 'c')
|
||||||
|
del d[1]
|
||||||
|
del d[3]
|
||||||
|
assert len(d) == 0
|
||||||
|
|
||||||
# test __eq__
|
# test __eq__
|
||||||
d1 = {1:2, 3:4}
|
d1 = {1:2, 3:4}
|
||||||
@ -66,4 +72,12 @@ assert b == {1: 2, 3: 4}
|
|||||||
a = {1:2, 3:4, 7:8}
|
a = {1:2, 3:4, 7:8}
|
||||||
b = {**a, 1:5, 3:6}
|
b = {**a, 1:5, 3:6}
|
||||||
c = {**a, **b}
|
c = {**a, **b}
|
||||||
assert c == {1: 5, 3: 6, 7: 8}
|
assert c == {1: 5, 3: 6, 7: 8}
|
||||||
|
|
||||||
|
a = {}
|
||||||
|
for i in range(1000):
|
||||||
|
a[i] = i
|
||||||
|
assert len(a) == 1000
|
||||||
|
for i in range(1000):
|
||||||
|
del a[i]
|
||||||
|
assert len(a) == 0
|
Loading…
x
Reference in New Issue
Block a user