mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-23 13:00:17 +00:00
up
This commit is contained in:
parent
6a27bc8bda
commit
7efb440388
@ -55,6 +55,7 @@ class Compiler {
|
||||
}
|
||||
|
||||
static void init_pratt_rules(){
|
||||
if(rules[TK(".")].precedence != PREC_NONE) return;
|
||||
// http://journal.stuffwithstuff.com/2011/03/19/pratt-parsers-expression-parsing-made-easy/
|
||||
#define METHOD(name) &Compiler::name
|
||||
#define NO_INFIX nullptr, PREC_NONE
|
||||
|
@ -7,7 +7,7 @@ namespace pkpy{
|
||||
|
||||
static THREAD_LOCAL uint64_t kFrameGlobalId = 0;
|
||||
|
||||
using ValueStack = small_vector<PyObject*, 6>;
|
||||
using ValueStack = pod_vector<PyObject*>;
|
||||
|
||||
struct Frame {
|
||||
ValueStack _data;
|
||||
|
@ -100,7 +100,7 @@ struct Lexer {
|
||||
const char* curr_char;
|
||||
int current_line = 1;
|
||||
std::vector<Token> nexts;
|
||||
small_stack<int, 4> indents;
|
||||
stack<int> indents;
|
||||
int brackets_level = 0;
|
||||
bool used = false;
|
||||
|
||||
|
46
src/memory.h
46
src/memory.h
@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
#include "vector.h"
|
||||
|
||||
namespace pkpy{
|
||||
|
||||
@ -69,48 +68,12 @@ shared_ptr<T> make_sp(Args&&... args) {
|
||||
return shared_ptr<T>(p);
|
||||
}
|
||||
|
||||
template<typename T, int __Bucket, bool __ZeroInit>
|
||||
struct FreeListA {
|
||||
std::vector<T*> buckets[__Bucket+1];
|
||||
|
||||
T* alloc(int n){
|
||||
static_assert(std::is_standard_layout_v<T>);
|
||||
T* p;
|
||||
if(n > __Bucket || buckets[n].empty()){
|
||||
p = (T*)malloc(sizeof(T) * n);
|
||||
}else{
|
||||
p = buckets[n].back();
|
||||
buckets[n].pop_back();
|
||||
}
|
||||
if constexpr(__ZeroInit){
|
||||
// the constructor of T should be equivalent to zero initialization
|
||||
memset((void*)p, 0, sizeof(T) * n);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
void dealloc(T* p, int n){
|
||||
if(p == nullptr) return;
|
||||
if(n > __Bucket || buckets[n].size() >= 80){
|
||||
free(p);
|
||||
}else{
|
||||
buckets[n].push_back(p);
|
||||
}
|
||||
}
|
||||
|
||||
~FreeListA(){
|
||||
for(int i=0; i<=__Bucket; i++){
|
||||
for(T* p : buckets[i]) free(p);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct LinkedListNode{
|
||||
LinkedListNode* prev;
|
||||
LinkedListNode* next;
|
||||
};
|
||||
|
||||
|
||||
template<typename T>
|
||||
struct DoubleLinkedList{
|
||||
static_assert(std::is_base_of_v<LinkedListNode, T>);
|
||||
@ -295,6 +258,9 @@ struct MemoryPool{
|
||||
}
|
||||
|
||||
void dealloc(void* p){
|
||||
#if DEBUG_MEMORY_POOL
|
||||
if(p == nullptr) throw std::runtime_error("MemoryPool::dealloc() called on nullptr");
|
||||
#endif
|
||||
Block* block = (Block*)((char*)p - sizeof(void*));
|
||||
if(block->arena == nullptr){
|
||||
free(block);
|
||||
@ -328,4 +294,8 @@ struct MemoryPool{
|
||||
}
|
||||
};
|
||||
|
||||
inline MemoryPool<64> pool64;
|
||||
inline MemoryPool<128> pool128;
|
||||
inline MemoryPool<256> pool256;
|
||||
|
||||
}; // namespace pkpy
|
||||
|
@ -34,8 +34,6 @@ inline static uint16_t find_perfect_hash_seed(uint16_t capacity, const std::vect
|
||||
|
||||
struct NameDict {
|
||||
using Item = std::pair<StrName, PyObject*>;
|
||||
inline static THREAD_LOCAL FreeListA<Item, 32, true> _pool;
|
||||
|
||||
uint16_t _capacity;
|
||||
uint16_t _size;
|
||||
float _load_factor;
|
||||
@ -43,31 +41,36 @@ struct NameDict {
|
||||
uint16_t _mask;
|
||||
Item* _items;
|
||||
|
||||
void _alloc(int cap){
|
||||
_items = (Item*)pool128.alloc(cap * sizeof(Item));
|
||||
memset(_items, 0, cap * sizeof(Item));
|
||||
}
|
||||
|
||||
NameDict(uint16_t capacity=2, float load_factor=0.67, uint16_t hash_seed=kHashSeeds[0]):
|
||||
_capacity(capacity), _size(0), _load_factor(load_factor),
|
||||
_hash_seed(hash_seed), _mask(capacity-1) {
|
||||
_items = _pool.alloc(_capacity);
|
||||
_alloc(capacity);
|
||||
}
|
||||
|
||||
NameDict(const NameDict& other) {
|
||||
memcpy(this, &other, sizeof(NameDict));
|
||||
_items = _pool.alloc(_capacity);
|
||||
_alloc(_capacity);
|
||||
for(int i=0; i<_capacity; i++){
|
||||
_items[i] = other._items[i];
|
||||
}
|
||||
}
|
||||
|
||||
NameDict& operator=(const NameDict& other) {
|
||||
_pool.dealloc(_items, _capacity);
|
||||
pool128.dealloc(_items);
|
||||
memcpy(this, &other, sizeof(NameDict));
|
||||
_items = _pool.alloc(_capacity);
|
||||
_alloc(_capacity);
|
||||
for(int i=0; i<_capacity; i++){
|
||||
_items[i] = other._items[i];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
~NameDict(){ _pool.dealloc(_items, _capacity); }
|
||||
~NameDict(){ pool128.dealloc(_items); }
|
||||
|
||||
NameDict(NameDict&&) = delete;
|
||||
NameDict& operator=(NameDict&&) = delete;
|
||||
@ -109,7 +112,7 @@ while(!_items[i].first.empty()) { \
|
||||
_capacity = find_next_capacity(_capacity * 2);
|
||||
_mask = _capacity - 1;
|
||||
}
|
||||
_items = _pool.alloc(_capacity);
|
||||
_alloc(_capacity);
|
||||
for(uint16_t i=0; i<old_capacity; i++){
|
||||
if(old_items[i].first.empty()) continue;
|
||||
bool ok; uint16_t j;
|
||||
@ -117,7 +120,7 @@ while(!_items[i].first.empty()) { \
|
||||
if(ok) UNREACHABLE();
|
||||
_items[j] = old_items[i];
|
||||
}
|
||||
_pool.dealloc(old_items, old_capacity);
|
||||
pool128.dealloc(old_items);
|
||||
}
|
||||
|
||||
void _try_perfect_rehash(){
|
||||
|
143
src/new_str.h
Normal file
143
src/new_str.h
Normal file
@ -0,0 +1,143 @@
|
||||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
#include "memory.h"
|
||||
#include <string_view>
|
||||
|
||||
namespace pkpy{
|
||||
|
||||
struct String{
|
||||
char* data;
|
||||
int size;
|
||||
|
||||
String(): data((char*)pool64.alloc(0)), size(0) {}
|
||||
String(int size): data((char*)pool64.alloc(size)), size(size) {}
|
||||
String(const char* str) {
|
||||
size = strlen(str);
|
||||
data = (char*)pool64.alloc(size);
|
||||
memcpy(data, str, size);
|
||||
}
|
||||
|
||||
String(const String& other): data((char*)pool64.alloc(other.size)), size(other.size) {
|
||||
memcpy(data, other.data, size);
|
||||
}
|
||||
|
||||
String(String&& other): data(other.data), size(other.size) {
|
||||
other.data = nullptr;
|
||||
}
|
||||
|
||||
String& operator=(const String& other){
|
||||
if(data!=nullptr) pool64.dealloc(data);
|
||||
size = other.size;
|
||||
data = (char*)pool64.alloc(size);
|
||||
memcpy(data, other.data, size);
|
||||
return *this;
|
||||
}
|
||||
|
||||
String& operator=(String&& other){
|
||||
if(data!=nullptr) pool64.dealloc(data);
|
||||
size = other.size;
|
||||
data = other.data;
|
||||
other.data = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
~String(){
|
||||
if(data!=nullptr) pool64.dealloc(data);
|
||||
}
|
||||
|
||||
char operator[](int idx) const {
|
||||
return data[idx];
|
||||
}
|
||||
|
||||
int length() const {
|
||||
return size;
|
||||
}
|
||||
|
||||
String operator+(const String& other) const {
|
||||
String ret(size + other.size);
|
||||
memcpy(ret.data, data, size);
|
||||
memcpy(ret.data + size, other.data, other.size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, const String& str){
|
||||
os.write(str.data, str.size);
|
||||
return os;
|
||||
}
|
||||
|
||||
bool operator==(const String& other) const {
|
||||
if(size != other.size) return false;
|
||||
return memcmp(data, other.data, size) == 0;
|
||||
}
|
||||
|
||||
bool operator!=(const String& other) const {
|
||||
if(size != other.size) return true;
|
||||
return memcmp(data, other.data, size) != 0;
|
||||
}
|
||||
|
||||
bool operator<(const String& other) const {
|
||||
int ret = strncmp(data, other.data, std::min(size, other.size));
|
||||
if(ret != 0) return ret < 0;
|
||||
return size < other.size;
|
||||
}
|
||||
|
||||
bool operator>(const String& other) const {
|
||||
int ret = strncmp(data, other.data, std::min(size, other.size));
|
||||
if(ret != 0) return ret > 0;
|
||||
return size > other.size;
|
||||
}
|
||||
|
||||
bool operator<=(const String& other) const {
|
||||
int ret = strncmp(data, other.data, std::min(size, other.size));
|
||||
if(ret != 0) return ret < 0;
|
||||
return size <= other.size;
|
||||
}
|
||||
|
||||
bool operator>=(const String& other) const {
|
||||
int ret = strncmp(data, other.data, std::min(size, other.size));
|
||||
if(ret != 0) return ret > 0;
|
||||
return size >= other.size;
|
||||
}
|
||||
|
||||
String substr(int start, int len) const {
|
||||
String ret(len);
|
||||
memcpy(ret.data, data + start, len);
|
||||
return ret;
|
||||
}
|
||||
|
||||
String substr(int start) const {
|
||||
return substr(start, size - start);
|
||||
}
|
||||
|
||||
char* dup_c_str() const {
|
||||
char* p = (char*)malloc(size + 1);
|
||||
memcpy(p, data, size);
|
||||
p[size] = 0;
|
||||
return p;
|
||||
}
|
||||
|
||||
std::string_view view() const {
|
||||
return std::string_view(data, size);
|
||||
}
|
||||
|
||||
std::string str() const {
|
||||
return std::string(data, size);
|
||||
}
|
||||
|
||||
String lstrip() const {
|
||||
std::string copy = str();
|
||||
copy.erase(copy.begin(), std::find_if(copy.begin(), copy.end(), [](char c) {
|
||||
// std::isspace(c) does not working on windows (Debug)
|
||||
return c != ' ' && c != '\t' && c != '\r' && c != '\n';
|
||||
}));
|
||||
return String(copy.c_str());
|
||||
}
|
||||
};
|
||||
|
||||
struct UnicodeString: String{
|
||||
|
||||
};
|
||||
|
||||
|
||||
} // namespace pkpy
|
@ -3,19 +3,18 @@
|
||||
#include "common.h"
|
||||
#include "memory.h"
|
||||
#include "str.h"
|
||||
#include "vector.h"
|
||||
|
||||
namespace pkpy {
|
||||
|
||||
using List = small_vector<PyObject*, 4>;
|
||||
using List = pod_vector<PyObject*>;
|
||||
|
||||
class Args {
|
||||
inline static THREAD_LOCAL FreeListA<PyObject*, 10, false> _pool;
|
||||
|
||||
PyObject** _args;
|
||||
int _size;
|
||||
|
||||
void _alloc(int n){
|
||||
this->_args = (n==0) ? nullptr : _pool.alloc(n);
|
||||
this->_args = (n==0) ? nullptr : (PyObject**)pool64.alloc(n * sizeof(void*));
|
||||
this->_size = n;
|
||||
}
|
||||
|
||||
@ -48,7 +47,7 @@ public:
|
||||
PyObject* operator[](int i) const { return _args[i]; }
|
||||
|
||||
Args& operator=(Args&& other) noexcept {
|
||||
_pool.dealloc(_args, _size);
|
||||
if(_args!=nullptr) pool64.dealloc(_args);
|
||||
this->_args = other._args;
|
||||
this->_size = other._size;
|
||||
other._args = nullptr;
|
||||
@ -71,10 +70,10 @@ public:
|
||||
_alloc(old_size+1);
|
||||
_args[0] = self;
|
||||
for(int i=0; i<old_size; i++) _args[i+1] = old_args[i];
|
||||
_pool.dealloc(old_args, old_size);
|
||||
if(old_args!=nullptr) pool64.dealloc(old_args);
|
||||
}
|
||||
|
||||
~Args(){ _pool.dealloc(_args, _size); }
|
||||
~Args(){ if(_args!=nullptr) pool64.dealloc(_args); }
|
||||
};
|
||||
|
||||
inline const Args& no_arg() {
|
||||
|
77
src/vector.h
77
src/vector.h
@ -1,65 +1,51 @@
|
||||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
#include "memory.h"
|
||||
|
||||
namespace pkpy{
|
||||
|
||||
template<typename T, int N>
|
||||
struct small_vector{
|
||||
template<typename T>
|
||||
struct pod_vector{
|
||||
static_assert(128 % sizeof(T) == 0);
|
||||
static_assert(std::is_pod_v<T>);
|
||||
static constexpr int N = 128 / sizeof(T);
|
||||
static_assert(N > 4);
|
||||
int _size;
|
||||
int _capacity;
|
||||
T* _data;
|
||||
T _buffer[N];
|
||||
|
||||
small_vector(): _size(0), _capacity(N) {
|
||||
static_assert(std::is_pod_v<T>);
|
||||
_data = _buffer;
|
||||
pod_vector(): _size(0), _capacity(N) {
|
||||
_data = (T*)pool128.alloc(_capacity * sizeof(T));
|
||||
}
|
||||
|
||||
small_vector(int size): _size(0), _capacity(N){
|
||||
_data = _buffer;
|
||||
reserve(size);
|
||||
_size = size;
|
||||
pod_vector(int size): _size(size), _capacity(std::max(N, size)) {
|
||||
_data = (T*)pool128.alloc(_capacity * sizeof(T));
|
||||
}
|
||||
|
||||
small_vector(const small_vector& other): _size(other._size), _capacity(other._capacity) {
|
||||
if(other.is_small()){
|
||||
_data = _buffer;
|
||||
memcpy(_buffer, other._buffer, sizeof(T) * _size);
|
||||
} else {
|
||||
_data = (T*)malloc(sizeof(T) * _capacity);
|
||||
memcpy(_data, other._data, sizeof(T) * _size);
|
||||
}
|
||||
pod_vector(const pod_vector& other): _size(other._size), _capacity(other._capacity) {
|
||||
_data = (T*)pool128.alloc(_capacity * sizeof(T));
|
||||
memcpy(_data, other._data, sizeof(T) * _size);
|
||||
}
|
||||
|
||||
small_vector(small_vector&& other) noexcept {
|
||||
pod_vector(pod_vector&& other) noexcept {
|
||||
_size = other._size;
|
||||
_capacity = other._capacity;
|
||||
if(other.is_small()){
|
||||
_data = _buffer;
|
||||
memcpy(_buffer, other._buffer, sizeof(T) * _size);
|
||||
} else {
|
||||
_data = other._data;
|
||||
other._data = other._buffer;
|
||||
}
|
||||
_data = other._data;
|
||||
other._data = nullptr;
|
||||
}
|
||||
|
||||
small_vector& operator=(small_vector&& other) noexcept {
|
||||
if (!is_small()) free(_data);
|
||||
pod_vector& operator=(pod_vector&& other) noexcept {
|
||||
if(_data!=nullptr) pool128.dealloc(_data);
|
||||
_size = other._size;
|
||||
_capacity = other._capacity;
|
||||
if(other.is_small()){
|
||||
_data = _buffer;
|
||||
memcpy(_buffer, other._buffer, sizeof(T) * _size);
|
||||
} else {
|
||||
_data = other._data;
|
||||
other._data = other._buffer;
|
||||
}
|
||||
_data = other._data;
|
||||
other._data = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// remove copy assignment
|
||||
small_vector& operator=(const small_vector& other) = delete;
|
||||
pod_vector& operator=(const pod_vector& other) = delete;
|
||||
|
||||
template<typename __ValueT>
|
||||
void push_back(__ValueT&& t) {
|
||||
@ -70,16 +56,12 @@ struct small_vector{
|
||||
void reserve(int cap){
|
||||
if(cap < _capacity) return;
|
||||
_capacity = cap;
|
||||
if (is_small()) {
|
||||
_data = (T*)malloc(sizeof(T) * _capacity);
|
||||
memcpy(_data, _buffer, sizeof(T) * _size);
|
||||
} else {
|
||||
_data = (T*)realloc(_data, sizeof(T) * _capacity);
|
||||
}
|
||||
if(_data!=nullptr) pool128.dealloc(_data);
|
||||
_data = (T*)pool128.alloc(_capacity * sizeof(T));
|
||||
}
|
||||
|
||||
void pop_back() { _size--; }
|
||||
void extend(const small_vector& other){
|
||||
void extend(const pod_vector& other){
|
||||
for(int i=0; i<other.size(); i++) push_back(other[i]);
|
||||
}
|
||||
|
||||
@ -97,7 +79,6 @@ struct small_vector{
|
||||
int size() const { return _size; }
|
||||
T* data() { return _data; }
|
||||
const T* data() const { return _data; }
|
||||
bool is_small() const { return _data == _buffer; }
|
||||
void pop_back_n(int n) { _size -= n; }
|
||||
void clear() { _size=0; }
|
||||
|
||||
@ -114,8 +95,8 @@ struct small_vector{
|
||||
_size--;
|
||||
}
|
||||
|
||||
~small_vector() {
|
||||
if (!is_small()) free(_data);
|
||||
~pod_vector() {
|
||||
if(_data!=nullptr) pool128.dealloc(_data);
|
||||
}
|
||||
};
|
||||
|
||||
@ -136,6 +117,6 @@ public:
|
||||
const Container& data() const { return vec; }
|
||||
};
|
||||
|
||||
template <typename T, int N>
|
||||
using small_stack = stack<T, small_vector<T, N>>;
|
||||
template <typename T>
|
||||
using pod_stack = stack<T, pod_vector<T>>;
|
||||
} // namespace pkpy
|
Loading…
x
Reference in New Issue
Block a user