mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 11:30:18 +00:00
use new vector impl
This commit is contained in:
parent
ac82f6f33f
commit
a59592b799
@ -1,5 +1,5 @@
|
|||||||
SRC=$(find src/ -name "*.cpp")
|
SRC=$(find src/ -name "*.cpp")
|
||||||
|
|
||||||
FLAGS="-std=c++17 -O2 -stdlib=libc++ -Iinclude -frtti -Wfatal-errors -g"
|
FLAGS="-std=c++17 -Og -stdlib=libc++ -Iinclude -frtti -Wfatal-errors -g"
|
||||||
|
|
||||||
clang++ $FLAGS -o main src2/main.cpp $SRC
|
clang++ $FLAGS -o main src2/main.cpp $SRC
|
||||||
|
@ -70,17 +70,17 @@ struct CodeObject {
|
|||||||
std::shared_ptr<SourceData> src;
|
std::shared_ptr<SourceData> src;
|
||||||
Str name;
|
Str name;
|
||||||
|
|
||||||
std::vector<Bytecode> codes;
|
vector<Bytecode> codes;
|
||||||
std::vector<LineInfo> lines;
|
vector<LineInfo> lines;
|
||||||
|
|
||||||
small_vector_2<PyVar, 8> consts; // constants
|
small_vector_2<PyVar, 8> consts; // constants
|
||||||
small_vector_2<StrName, 8> varnames; // local variables
|
small_vector_2<StrName, 8> varnames; // local variables
|
||||||
int nlocals; // varnames.size()
|
int nlocals; // varnames.size()
|
||||||
|
|
||||||
NameDictInt varnames_inv;
|
NameDictInt varnames_inv;
|
||||||
std::vector<CodeBlock> blocks;
|
vector<CodeBlock> blocks;
|
||||||
NameDictInt labels;
|
NameDictInt labels;
|
||||||
std::vector<FuncDecl_> func_decls;
|
vector<FuncDecl_> func_decls;
|
||||||
|
|
||||||
int start_line;
|
int start_line;
|
||||||
int end_line;
|
int end_line;
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
@ -27,11 +27,11 @@ class Compiler {
|
|||||||
bool unknown_global_scope; // for eval/exec() call
|
bool unknown_global_scope; // for eval/exec() call
|
||||||
// for parsing token stream
|
// for parsing token stream
|
||||||
int i = 0;
|
int i = 0;
|
||||||
std::vector<Token> tokens;
|
vector<Token> tokens;
|
||||||
|
|
||||||
const Token& prev() const{ return tokens.at(i-1); }
|
const Token& prev() const{ return tokens[i-1]; }
|
||||||
const Token& curr() const{ return tokens.at(i); }
|
const Token& curr() const{ return tokens[i]; }
|
||||||
const Token& next() const{ return tokens.at(i+1); }
|
const Token& next() const{ return tokens[i+1]; }
|
||||||
const Token& err() const{
|
const Token& err() const{
|
||||||
if(i >= tokens.size()) return prev();
|
if(i >= tokens.size()) return prev();
|
||||||
return curr();
|
return curr();
|
||||||
|
@ -37,10 +37,10 @@ struct SourceData {
|
|||||||
CompileMode mode;
|
CompileMode mode;
|
||||||
|
|
||||||
Str source;
|
Str source;
|
||||||
pod_vector<const char*> line_starts;
|
vector<const char*> line_starts;
|
||||||
|
|
||||||
bool is_precompiled;
|
bool is_precompiled;
|
||||||
std::vector<Str> _precompiled_tokens;
|
vector<Str> _precompiled_tokens;
|
||||||
|
|
||||||
SourceData(std::string_view source, const Str& filename, CompileMode mode);
|
SourceData(std::string_view source, const Str& filename, CompileMode mode);
|
||||||
SourceData(const Str& filename, CompileMode mode);
|
SourceData(const Str& filename, CompileMode mode);
|
||||||
|
@ -352,7 +352,7 @@ struct CallExpr: Expr{
|
|||||||
Expr_ callable;
|
Expr_ callable;
|
||||||
Expr_vector args;
|
Expr_vector args;
|
||||||
// **a will be interpreted as a special keyword argument: {"**": a}
|
// **a will be interpreted as a special keyword argument: {"**": a}
|
||||||
std::vector<std::pair<Str, Expr_>> kwargs;
|
vector<std::pair<Str, Expr_>> kwargs;
|
||||||
void emit_(CodeEmitContext* ctx) override;
|
void emit_(CodeEmitContext* ctx) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -8,8 +8,8 @@
|
|||||||
|
|
||||||
namespace pkpy {
|
namespace pkpy {
|
||||||
struct ManagedHeap{
|
struct ManagedHeap{
|
||||||
std::vector<PyObject*> _no_gc;
|
vector<PyObject*> _no_gc;
|
||||||
std::vector<PyObject*> gen;
|
vector<PyObject*> gen;
|
||||||
VM* vm;
|
VM* vm;
|
||||||
void (*_gc_on_delete)(VM*, PyObject*) = nullptr;
|
void (*_gc_on_delete)(VM*, PyObject*) = nullptr;
|
||||||
void (*_gc_marker_ex)(VM*) = nullptr;
|
void (*_gc_marker_ex)(VM*) = nullptr;
|
||||||
|
@ -30,7 +30,7 @@ constexpr const char* kTokens[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
using TokenValue = std::variant<std::monostate, i64, f64, Str>;
|
using TokenValue = std::variant<std::monostate, i64, f64, Str>;
|
||||||
const TokenIndex kTokenCount = sizeof(kTokens) / sizeof(kTokens[0]);
|
const int kTokenCount = sizeof(kTokens) / sizeof(kTokens[0]);
|
||||||
|
|
||||||
constexpr TokenIndex TK(const char token[]) {
|
constexpr TokenIndex TK(const char token[]) {
|
||||||
for(int k=0; k<kTokenCount; k++){
|
for(int k=0; k<kTokenCount; k++){
|
||||||
@ -99,7 +99,7 @@ struct Lexer {
|
|||||||
const char* token_start;
|
const char* token_start;
|
||||||
const char* curr_char;
|
const char* curr_char;
|
||||||
int current_line = 1;
|
int current_line = 1;
|
||||||
std::vector<Token> nexts;
|
vector<Token> nexts;
|
||||||
stack_no_copy<int, small_vector_2<int, 8>> indents;
|
stack_no_copy<int, small_vector_2<int, 8>> indents;
|
||||||
int brackets_level = 0;
|
int brackets_level = 0;
|
||||||
|
|
||||||
@ -129,7 +129,7 @@ struct Lexer {
|
|||||||
void SyntaxError(){ throw_err("SyntaxError", "invalid syntax"); }
|
void SyntaxError(){ throw_err("SyntaxError", "invalid syntax"); }
|
||||||
void IndentationError(Str msg){ throw_err("IndentationError", msg); }
|
void IndentationError(Str msg){ throw_err("IndentationError", msg); }
|
||||||
Lexer(VM* vm, std::shared_ptr<SourceData> src);
|
Lexer(VM* vm, std::shared_ptr<SourceData> src);
|
||||||
std::vector<Token> run();
|
vector<Token> run();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -13,17 +13,11 @@ constexpr T default_invalid_value(){
|
|||||||
else return Discarded();
|
else return Discarded();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
struct NameDictItem{
|
|
||||||
StrName first;
|
|
||||||
T second;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct NameDictImpl {
|
struct NameDictImpl {
|
||||||
PK_ALWAYS_PASS_BY_POINTER(NameDictImpl)
|
PK_ALWAYS_PASS_BY_POINTER(NameDictImpl)
|
||||||
|
|
||||||
using Item = NameDictItem<T>;
|
using Item = std::pair<StrName, T>;
|
||||||
static constexpr uint16_t kInitialCapacity = 16;
|
static constexpr uint16_t kInitialCapacity = 16;
|
||||||
static_assert(is_pod_v<T>);
|
static_assert(is_pod_v<T>);
|
||||||
|
|
||||||
@ -166,19 +160,21 @@ while(!_items[i].first.empty()) { \
|
|||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
pod_vector<StrName> keys() const {
|
array<StrName> keys() const {
|
||||||
pod_vector<StrName> v;
|
array<StrName> v(_size);
|
||||||
|
int j = 0;
|
||||||
for(uint16_t i=0; i<_capacity; i++){
|
for(uint16_t i=0; i<_capacity; i++){
|
||||||
if(_items[i].first.empty()) continue;
|
if(_items[i].first.empty()) continue;
|
||||||
v.push_back(_items[i].first);
|
new (&v[j++]) StrName(_items[i].first);
|
||||||
}
|
}
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
pod_vector<NameDictItem<T>> items() const{
|
array<Item> items() const{
|
||||||
pod_vector<NameDictItem<T>> v;
|
array<Item> v(_size);
|
||||||
|
int j = 0;
|
||||||
apply([&](StrName key, T val){
|
apply([&](StrName key, T val){
|
||||||
v.push_back(NameDictItem<T>{key, val});
|
new(&v[j++]) Item(key, val);
|
||||||
});
|
});
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ struct _FrameRecord{
|
|||||||
|
|
||||||
struct LineProfiler{
|
struct LineProfiler{
|
||||||
// filename -> records
|
// filename -> records
|
||||||
std::map<std::string_view, std::vector<_LineRecord>> records;
|
std::map<std::string_view, vector<_LineRecord>> records;
|
||||||
stack_no_copy<_FrameRecord> frames;
|
stack_no_copy<_FrameRecord> frames;
|
||||||
std::set<FuncDecl*> functions;
|
std::set<FuncDecl*> functions;
|
||||||
|
|
||||||
|
@ -77,8 +77,8 @@ struct Str{
|
|||||||
int index(const Str& sub, int start=0) const;
|
int index(const Str& sub, int start=0) const;
|
||||||
Str replace(char old, char new_) const;
|
Str replace(char old, char new_) const;
|
||||||
Str replace(const Str& old, const Str& new_, int count=-1) const;
|
Str replace(const Str& old, const Str& new_, int count=-1) const;
|
||||||
pod_vector<std::string_view> split(const Str& sep) const;
|
vector<std::string_view> split(const Str& sep) const;
|
||||||
pod_vector<std::string_view> split(char sep) const;
|
vector<std::string_view> split(char sep) const;
|
||||||
int count(const Str& sub) const;
|
int count(const Str& sub) const;
|
||||||
|
|
||||||
/*************unicode*************/
|
/*************unicode*************/
|
||||||
@ -127,15 +127,15 @@ struct StrName {
|
|||||||
|
|
||||||
struct SStream{
|
struct SStream{
|
||||||
PK_ALWAYS_PASS_BY_POINTER(SStream)
|
PK_ALWAYS_PASS_BY_POINTER(SStream)
|
||||||
// pod_vector<T> is allocated by pool128 so the buffer can be moved into Str without a copy
|
|
||||||
pod_vector<char> buffer;
|
vector<char> buffer;
|
||||||
int _precision = -1;
|
int _precision = -1;
|
||||||
|
|
||||||
bool empty() const { return buffer.empty(); }
|
bool empty() const { return buffer.empty(); }
|
||||||
void setprecision(int precision) { _precision = precision; }
|
void setprecision(int precision) { _precision = precision; }
|
||||||
|
|
||||||
SStream(){}
|
SStream() {}
|
||||||
SStream(int guess_size){ buffer.reserve(guess_size); }
|
SStream(int guess_size) { buffer.reserve(guess_size);}
|
||||||
|
|
||||||
Str str();
|
Str str();
|
||||||
|
|
||||||
|
@ -35,8 +35,8 @@ struct Tuple {
|
|||||||
void _gc_mark(VM*) const;
|
void _gc_mark(VM*) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct List: pod_vector<PyVar>{
|
struct List: public vector<PyVar>{
|
||||||
using pod_vector<PyVar>::pod_vector;
|
using vector<PyVar>::vector;
|
||||||
void _gc_mark(VM*) const;
|
void _gc_mark(VM*) const;
|
||||||
|
|
||||||
Tuple to_tuple() const{
|
Tuple to_tuple() const{
|
||||||
|
@ -5,147 +5,216 @@
|
|||||||
|
|
||||||
namespace pkpy{
|
namespace pkpy{
|
||||||
|
|
||||||
|
struct explicit_copy_t {
|
||||||
|
explicit explicit_copy_t() = default;
|
||||||
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct pod_vector{
|
struct array{
|
||||||
static constexpr int SizeT = sizeof(T);
|
|
||||||
static constexpr int N = 128 / SizeT;
|
|
||||||
static constexpr int Growth = 2;
|
|
||||||
|
|
||||||
// static_assert(128 % SizeT == 0);
|
|
||||||
static_assert(is_pod_v<T>);
|
|
||||||
static_assert(N >= 4);
|
|
||||||
|
|
||||||
int _size;
|
|
||||||
int _capacity;
|
|
||||||
T* _data;
|
T* _data;
|
||||||
|
int _size;
|
||||||
|
|
||||||
using size_type = int;
|
using size_type = int;
|
||||||
|
|
||||||
pod_vector(): _size(0), _capacity(N) {
|
array(): _data(nullptr), _size(0) {}
|
||||||
_data = (T*)pool128_alloc(_capacity * SizeT);
|
array(int size): _data((T*)malloc(sizeof(T) * size)), _size(size) {}
|
||||||
}
|
array(array&& other) noexcept: _data(other._data), _size(other._size) {
|
||||||
|
|
||||||
// support initializer list
|
|
||||||
pod_vector(std::initializer_list<T> il): _size(il.size()), _capacity(std::max(N, _size)) {
|
|
||||||
_data = (T*)pool128_alloc(_capacity * SizeT);
|
|
||||||
for(int i=0; i<_size; i++) _data[i] = *(il.begin() + i);
|
|
||||||
}
|
|
||||||
|
|
||||||
pod_vector(int size): _size(size), _capacity(std::max(N, size)) {
|
|
||||||
_data = (T*)pool128_alloc(_capacity * SizeT);
|
|
||||||
}
|
|
||||||
|
|
||||||
pod_vector(const pod_vector& other): _size(other._size), _capacity(other._capacity) {
|
|
||||||
_data = (T*)pool128_alloc(_capacity * SizeT);
|
|
||||||
memcpy(_data, other._data, SizeT * _size);
|
|
||||||
}
|
|
||||||
|
|
||||||
pod_vector(pod_vector&& other) noexcept {
|
|
||||||
_size = other._size;
|
|
||||||
_capacity = other._capacity;
|
|
||||||
_data = other._data;
|
|
||||||
other._data = nullptr;
|
other._data = nullptr;
|
||||||
|
other._size = 0;
|
||||||
|
}
|
||||||
|
array(const array& other) = delete;
|
||||||
|
array(explicit_copy_t, const array& other) {
|
||||||
|
_data = (T*)malloc(sizeof(T) * other._size);
|
||||||
|
_size = other._size;
|
||||||
|
for(int i=0; i<_size; i++) _data[i] = other._data[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
pod_vector& operator=(pod_vector&& other) noexcept {
|
array& operator=(array&& other) noexcept{
|
||||||
if(_data!=nullptr) pool128_dealloc(_data);
|
if(_data){
|
||||||
_size = other._size;
|
std::destroy(begin(), end());
|
||||||
_capacity = other._capacity;
|
free(_data);
|
||||||
|
}
|
||||||
_data = other._data;
|
_data = other._data;
|
||||||
|
_size = other._size;
|
||||||
other._data = nullptr;
|
other._data = nullptr;
|
||||||
|
other._size = 0;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove copy assignment
|
array& operator=(const array& other) = delete;
|
||||||
pod_vector& operator=(const pod_vector& other) = delete;
|
|
||||||
|
|
||||||
template<typename __ValueT>
|
T& operator[](int i) {
|
||||||
void push_back(__ValueT&& t) {
|
PK_DEBUG_ASSERT(i>=0 && i<_size);
|
||||||
if (_size == _capacity) reserve(_capacity*Growth);
|
return _data[i];
|
||||||
_data[_size++] = std::forward<__ValueT>(t);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename... Args>
|
const T& operator[](int i) const {
|
||||||
void emplace_back(Args&&... args) {
|
PK_DEBUG_ASSERT(i>=0 && i<_size);
|
||||||
if (_size == _capacity) reserve(_capacity*Growth);
|
return _data[i];
|
||||||
new (&_data[_size++]) T(std::forward<Args>(args)...);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void reserve(int cap){
|
|
||||||
if(cap <= _capacity) return;
|
|
||||||
_capacity = cap;
|
|
||||||
T* old_data = _data;
|
|
||||||
_data = (T*)pool128_alloc(_capacity * SizeT);
|
|
||||||
if(old_data != nullptr){
|
|
||||||
memcpy(_data, old_data, SizeT * _size);
|
|
||||||
pool128_dealloc(old_data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void pop_back() { _size--; }
|
|
||||||
T popx_back() { T t = std::move(_data[_size-1]); _size--; return t; }
|
|
||||||
|
|
||||||
void extend(const pod_vector& other){
|
|
||||||
for(int i=0; i<other.size(); i++) push_back(other[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void extend(const T* begin, const T* end){
|
|
||||||
for(auto it=begin; it!=end; it++) push_back(*it);
|
|
||||||
}
|
|
||||||
|
|
||||||
T& operator[](int index) { return _data[index]; }
|
|
||||||
const T& operator[](int index) const { return _data[index]; }
|
|
||||||
|
|
||||||
T* begin() { return _data; }
|
|
||||||
T* end() { return _data + _size; }
|
|
||||||
const T* begin() const { return _data; }
|
|
||||||
const T* end() const { return _data + _size; }
|
|
||||||
T& back() { return _data[_size - 1]; }
|
|
||||||
const T& back() const { return _data[_size - 1]; }
|
|
||||||
|
|
||||||
bool empty() const { return _size == 0; }
|
|
||||||
int size() const { return _size; }
|
int size() const { return _size; }
|
||||||
T* data() { return _data; }
|
|
||||||
const T* data() const { return _data; }
|
|
||||||
void clear() { _size=0; }
|
|
||||||
|
|
||||||
template<typename __ValueT>
|
T* begin() const{ return _data; }
|
||||||
void insert(int i, __ValueT&& val){
|
T* end() const{ return _data + _size; }
|
||||||
if (_size == _capacity) reserve(_capacity*Growth);
|
|
||||||
for(int j=_size; j>i; j--) _data[j] = _data[j-1];
|
|
||||||
_data[i] = std::forward<__ValueT>(val);
|
|
||||||
_size++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void erase(int i){
|
|
||||||
for(int j=i; j<_size-1; j++) _data[j] = _data[j+1];
|
|
||||||
_size--;
|
|
||||||
}
|
|
||||||
|
|
||||||
void reverse(){
|
|
||||||
std::reverse(_data, _data+_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void resize(int size){
|
|
||||||
if(size > _capacity) reserve(size);
|
|
||||||
_size = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<T*, int> detach() noexcept {
|
std::pair<T*, int> detach() noexcept {
|
||||||
T* p = _data;
|
std::pair<T*, int> retval(_data, _size);
|
||||||
int size = _size;
|
|
||||||
_data = nullptr;
|
_data = nullptr;
|
||||||
_size = 0;
|
_size = 0;
|
||||||
return {p, size};
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
~pod_vector() {
|
~array() {
|
||||||
if(_data != nullptr) pool128_dealloc(_data);
|
if(_data){
|
||||||
|
std::destroy(begin(), end());
|
||||||
|
free(_data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
template <typename T, typename Container=std::vector<T>>
|
template<typename T>
|
||||||
|
struct vector{
|
||||||
|
T* _data;
|
||||||
|
int _capacity;
|
||||||
|
int _size;
|
||||||
|
|
||||||
|
using size_type = int;
|
||||||
|
|
||||||
|
vector(): _data(nullptr), _capacity(0), _size(0) {}
|
||||||
|
vector(int size):
|
||||||
|
_data((T*)malloc(sizeof(T) * size)),
|
||||||
|
_capacity(size), _size(size) {}
|
||||||
|
vector(vector&& other) noexcept:
|
||||||
|
_data(other._data), _capacity(other._capacity), _size(other._size) {
|
||||||
|
other._data = nullptr;
|
||||||
|
other._capacity = 0;
|
||||||
|
other._size = 0;
|
||||||
|
}
|
||||||
|
vector(const vector& other) = delete;
|
||||||
|
vector(explicit_copy_t, const vector& other):
|
||||||
|
_data((T*)malloc(sizeof(T) * other._size)),
|
||||||
|
_capacity(other._size), _size(other._size) {
|
||||||
|
for(int i=0; i<_size; i++) _data[i] = other._data[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// allow move
|
||||||
|
vector& operator=(vector&& other) noexcept{
|
||||||
|
if(_data){
|
||||||
|
std::destroy(begin(), end());
|
||||||
|
free(_data);
|
||||||
|
}
|
||||||
|
new (this) vector(std::move(other));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
// disallow copy
|
||||||
|
vector& operator=(const vector& other) = delete;
|
||||||
|
|
||||||
|
bool empty() const { return _size == 0; }
|
||||||
|
int size() const { return _size; }
|
||||||
|
int capacity() const { return _capacity; }
|
||||||
|
T& back() { return _data[_size-1]; }
|
||||||
|
|
||||||
|
T* begin() const { return _data; }
|
||||||
|
T* end() const { return _data + _size; }
|
||||||
|
T* data() const { return _data; }
|
||||||
|
|
||||||
|
void reserve(int cap){
|
||||||
|
if(cap < 4) cap = 4; // minimum capacity
|
||||||
|
if(cap <= capacity()) return;
|
||||||
|
T* new_data = (T*)malloc(sizeof(T) * cap);
|
||||||
|
if constexpr(std::is_trivially_copyable_v<T>){
|
||||||
|
memcpy(new_data, _data, sizeof(T) * _size);
|
||||||
|
}else{
|
||||||
|
for(int i=0; i<_size; i++){
|
||||||
|
new(&new_data[i]) T(std::move(_data[i]));
|
||||||
|
_data[i].~T();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(_data) free(_data);
|
||||||
|
_data = new_data;
|
||||||
|
_capacity = cap;
|
||||||
|
}
|
||||||
|
|
||||||
|
void resize(int size){
|
||||||
|
reserve(size);
|
||||||
|
_size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void push_back(const T& t){
|
||||||
|
if(_size == _capacity) reserve(_capacity * 2);
|
||||||
|
new (&_data[_size++]) T(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
void push_back(T&& t){
|
||||||
|
if(_size == _capacity) reserve(_capacity * 2);
|
||||||
|
new(&_data[_size++]) T(std::move(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
void emplace_back(Args&&... args){
|
||||||
|
if(_size == _capacity) reserve(_capacity * 2);
|
||||||
|
new(&_data[_size++]) T(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
T& operator[](int i) { return _data[i]; }
|
||||||
|
const T& operator[](int i) const { return _data[i]; }
|
||||||
|
|
||||||
|
void extend(T* begin, T* end){
|
||||||
|
int n = end - begin;
|
||||||
|
reserve(_size + n);
|
||||||
|
for(int i=0; i<n; i++) new(&_data[_size++]) T(begin[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void insert(int index, const T& t){
|
||||||
|
if(_size == _capacity) reserve(_capacity * 2);
|
||||||
|
for(int i=_size; i>index; i--) _data[i] = std::move(_data[i-1]);
|
||||||
|
_data[index] = t;
|
||||||
|
_size++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void erase(int index){
|
||||||
|
for(int i=index; i<_size-1; i++) _data[i] = std::move(_data[i+1]);
|
||||||
|
_size--;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pop_back(){
|
||||||
|
PK_DEBUG_ASSERT(_size > 0);
|
||||||
|
_size--;
|
||||||
|
if constexpr(!std::is_trivially_destructible_v<T>){
|
||||||
|
_data[_size].~T();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear(){
|
||||||
|
std::destroy(begin(), end());
|
||||||
|
_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<T*, int> detach() noexcept {
|
||||||
|
std::pair<T*, int> retval(_data, _size);
|
||||||
|
_data = nullptr;
|
||||||
|
_capacity = 0;
|
||||||
|
_size = 0;
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
void swap(vector& other){
|
||||||
|
std::swap(_data, other._data);
|
||||||
|
std::swap(_capacity, other._capacity);
|
||||||
|
std::swap(_size, other._size);
|
||||||
|
}
|
||||||
|
|
||||||
|
~vector(){
|
||||||
|
if(_data){
|
||||||
|
std::destroy(begin(), end());
|
||||||
|
free(_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, typename Container=vector<T>>
|
||||||
class stack{
|
class stack{
|
||||||
Container vec;
|
Container vec;
|
||||||
public:
|
public:
|
||||||
@ -167,7 +236,7 @@ public:
|
|||||||
const Container& container() const { return vec; }
|
const Container& container() const { return vec; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, typename Container=std::vector<T>>
|
template <typename T, typename Container=vector<T>>
|
||||||
class stack_no_copy: public stack<T, Container>{
|
class stack_no_copy: public stack<T, Container>{
|
||||||
public:
|
public:
|
||||||
stack_no_copy() = default;
|
stack_no_copy() = default;
|
||||||
|
@ -74,7 +74,7 @@ struct PyTypeInfo{
|
|||||||
PyTypeInfo(PyObject* obj, Type base, PyObject* mod, StrName name, bool subclass_enabled, Vt vt={}):
|
PyTypeInfo(PyObject* obj, Type base, PyObject* mod, StrName name, bool subclass_enabled, Vt vt={}):
|
||||||
obj(obj), base(base), mod(mod), name(name), subclass_enabled(subclass_enabled), vt(vt) {}
|
obj(obj), base(base), mod(mod), name(name), subclass_enabled(subclass_enabled), vt(vt) {}
|
||||||
|
|
||||||
std::vector<StrName> annotated_fields = {};
|
vector<StrName> annotated_fields = {};
|
||||||
|
|
||||||
// unary operators
|
// unary operators
|
||||||
Str (*m__repr__)(VM* vm, PyVar) = nullptr;
|
Str (*m__repr__)(VM* vm, PyVar) = nullptr;
|
||||||
@ -127,8 +127,8 @@ struct PyTypeInfo{
|
|||||||
struct ImportContext{
|
struct ImportContext{
|
||||||
PK_ALWAYS_PASS_BY_POINTER(ImportContext)
|
PK_ALWAYS_PASS_BY_POINTER(ImportContext)
|
||||||
|
|
||||||
std::vector<Str> pending;
|
vector<Str> pending;
|
||||||
std::vector<bool> pending_is_init; // a.k.a __init__.py
|
vector<bool> pending_is_init; // a.k.a __init__.py
|
||||||
|
|
||||||
ImportContext() {}
|
ImportContext() {}
|
||||||
|
|
||||||
@ -159,7 +159,7 @@ public:
|
|||||||
ManagedHeap heap;
|
ManagedHeap heap;
|
||||||
ValueStack s_data;
|
ValueStack s_data;
|
||||||
CallStack callstack;
|
CallStack callstack;
|
||||||
std::vector<PyTypeInfo> _all_types;
|
vector<PyTypeInfo> _all_types;
|
||||||
|
|
||||||
NameDict _modules; // loaded modules
|
NameDict _modules; // loaded modules
|
||||||
std::map<StrName, Str> _lazy_modules; // lazy loaded modules
|
std::map<StrName, Str> _lazy_modules; // lazy loaded modules
|
||||||
|
@ -931,7 +931,7 @@ __NEXT_STEP:
|
|||||||
if(_1 == StopIteration) break;
|
if(_1 == StopIteration) break;
|
||||||
extras.push_back(_1);
|
extras.push_back(_1);
|
||||||
}
|
}
|
||||||
PUSH(VAR(extras));
|
PUSH(VAR(std::move(extras)));
|
||||||
} DISPATCH()
|
} DISPATCH()
|
||||||
/*****************************************/
|
/*****************************************/
|
||||||
case OP_BEGIN_CLASS:{
|
case OP_BEGIN_CLASS:{
|
||||||
@ -1056,7 +1056,9 @@ __NEXT_STEP:
|
|||||||
Exception& _e = PK_OBJ_GET(Exception, e_obj);
|
Exception& _e = PK_OBJ_GET(Exception, e_obj);
|
||||||
bool is_base_frame_to_be_popped = frame == base_frame;
|
bool is_base_frame_to_be_popped = frame == base_frame;
|
||||||
__pop_frame();
|
__pop_frame();
|
||||||
if(callstack.empty()) throw _e; // propagate to the top level
|
if(callstack.empty()){
|
||||||
|
throw std::move(_e); // propagate to the top level
|
||||||
|
}
|
||||||
frame = &callstack.top();
|
frame = &callstack.top();
|
||||||
PUSH(e_obj);
|
PUSH(e_obj);
|
||||||
if(is_base_frame_to_be_popped){
|
if(is_base_frame_to_be_popped){
|
||||||
|
@ -1292,7 +1292,7 @@ __EAT_DOTS_END:
|
|||||||
}
|
}
|
||||||
|
|
||||||
int count = deserializer.read_count();
|
int count = deserializer.read_count();
|
||||||
std::vector<Str>& precompiled_tokens = lexer.src->_precompiled_tokens;
|
vector<Str>& precompiled_tokens = lexer.src->_precompiled_tokens;
|
||||||
for(int i=0; i<count; i++){
|
for(int i=0; i<count; i++){
|
||||||
precompiled_tokens.push_back(deserializer.read_string('\n'));
|
precompiled_tokens.push_back(deserializer.read_string('\n'));
|
||||||
}
|
}
|
||||||
@ -1379,7 +1379,7 @@ __EAT_DOTS_END:
|
|||||||
PyVar e_obj = vm->call(vm->builtins->attr(type), VAR(msg));
|
PyVar e_obj = vm->call(vm->builtins->attr(type), VAR(msg));
|
||||||
Exception& e = PK_OBJ_GET(Exception, e_obj);
|
Exception& e = PK_OBJ_GET(Exception, e_obj);
|
||||||
e.st_push(src, lineno, cursor, "");
|
e.st_push(src, lineno, cursor, "");
|
||||||
throw e;
|
throw std::move(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string_view TokenDeserializer::read_string(char c){
|
std::string_view TokenDeserializer::read_string(char c){
|
||||||
|
@ -73,7 +73,7 @@ __NEXT_LINE:
|
|||||||
if(ret.size() == 0){
|
if(ret.size() == 0){
|
||||||
vm->ValueError("empty csvfile");
|
vm->ValueError("empty csvfile");
|
||||||
}
|
}
|
||||||
List header = CAST(List&, ret[0]);
|
const List& header = CAST(List&, ret[0]);
|
||||||
List new_ret;
|
List new_ret;
|
||||||
for(int i=1; i<ret.size(); i++){
|
for(int i=1; i<ret.size(); i++){
|
||||||
const List& row = CAST(List&, ret[i]);
|
const List& row = CAST(List&, ret[i]);
|
||||||
|
@ -66,14 +66,16 @@ namespace pkpy{
|
|||||||
}
|
}
|
||||||
|
|
||||||
Str Exception::summary() const {
|
Str Exception::summary() const {
|
||||||
stack<ExceptionLine> st(stacktrace);
|
|
||||||
SStream ss;
|
SStream ss;
|
||||||
if(is_re) ss << "Traceback (most recent call last):\n";
|
if(is_re) ss << "Traceback (most recent call last):\n";
|
||||||
while(!st.empty()) {
|
// while(!st.empty()) {
|
||||||
ss << st.top().snapshot() << '\n';
|
// ss << st.top().snapshot() << '\n';
|
||||||
st.pop();
|
// st.pop();
|
||||||
|
// }
|
||||||
|
const auto& container = stacktrace.container();
|
||||||
|
for(int i=container.size()-1; i>=0; i--){
|
||||||
|
ss << container[i].snapshot() << '\n';
|
||||||
}
|
}
|
||||||
// TODO: allow users to override the behavior
|
|
||||||
if (!msg.empty()) ss << type.sv() << ": " << msg;
|
if (!msg.empty()) ss << type.sv() << ": " << msg;
|
||||||
else ss << type.sv();
|
else ss << type.sv();
|
||||||
return ss.str();
|
return ss.str();
|
||||||
|
@ -3,7 +3,8 @@
|
|||||||
namespace pkpy{
|
namespace pkpy{
|
||||||
|
|
||||||
int ManagedHeap::sweep(){
|
int ManagedHeap::sweep(){
|
||||||
std::vector<PyObject*> alive;
|
vector<PyObject*> alive;
|
||||||
|
alive.reserve(gen.size() / 2);
|
||||||
for(PyObject* obj: gen){
|
for(PyObject* obj: gen){
|
||||||
if(obj->gc_marked){
|
if(obj->gc_marked){
|
||||||
obj->gc_marked = false;
|
obj->gc_marked = false;
|
||||||
|
@ -485,7 +485,7 @@ static bool is_unicode_Lo_char(uint32_t c) {
|
|||||||
this->indents.push(0);
|
this->indents.push(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Token> Lexer::run() {
|
vector<Token> Lexer::run() {
|
||||||
PK_ASSERT(curr_char == src->source.c_str());
|
PK_ASSERT(curr_char == src->source.c_str());
|
||||||
while (lex_one_token());
|
while (lex_one_token());
|
||||||
return std::move(nexts);
|
return std::move(nexts);
|
||||||
|
@ -622,7 +622,7 @@ void __init_builtins(VM* _vm) {
|
|||||||
const Str& self = _CAST(Str&, args[0]);
|
const Str& self = _CAST(Str&, args[0]);
|
||||||
const Str& sep = CAST(Str&, args[1]);
|
const Str& sep = CAST(Str&, args[1]);
|
||||||
if(sep.empty()) vm->ValueError("empty separator");
|
if(sep.empty()) vm->ValueError("empty separator");
|
||||||
pod_vector<std::string_view> parts;
|
vector<std::string_view> parts;
|
||||||
if(sep.size == 1){
|
if(sep.size == 1){
|
||||||
parts = self.split(sep[0]);
|
parts = self.split(sep[0]);
|
||||||
}else{
|
}else{
|
||||||
@ -635,8 +635,7 @@ void __init_builtins(VM* _vm) {
|
|||||||
|
|
||||||
_vm->bind(_vm->_t(VM::tp_str), "splitlines(self)", [](VM* vm, ArgsView args) {
|
_vm->bind(_vm->_t(VM::tp_str), "splitlines(self)", [](VM* vm, ArgsView args) {
|
||||||
const Str& self = _CAST(Str&, args[0]);
|
const Str& self = _CAST(Str&, args[0]);
|
||||||
pod_vector<std::string_view> parts;
|
vector<std::string_view> parts = self.split('\n');
|
||||||
parts = self.split('\n');
|
|
||||||
List ret(parts.size());
|
List ret(parts.size());
|
||||||
for(int i=0; i<parts.size(); i++) ret[i] = VAR(Str(parts[i]));
|
for(int i=0; i<parts.size(); i++) ret[i] = VAR(Str(parts[i]));
|
||||||
return VAR(std::move(ret));
|
return VAR(std::move(ret));
|
||||||
@ -797,7 +796,9 @@ void __init_builtins(VM* _vm) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
bool reverse = CAST(bool, args[2]);
|
bool reverse = CAST(bool, args[2]);
|
||||||
if(reverse) self.reverse();
|
if(reverse){
|
||||||
|
std::reverse(self.begin(), self.end());
|
||||||
|
}
|
||||||
return vm->None;
|
return vm->None;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -892,7 +893,9 @@ void __init_builtins(VM* _vm) {
|
|||||||
List& self = _CAST(List&, args[0]);
|
List& self = _CAST(List&, args[0]);
|
||||||
if(args.size() == 1+0){
|
if(args.size() == 1+0){
|
||||||
if(self.empty()) vm->IndexError("pop from empty list");
|
if(self.empty()) vm->IndexError("pop from empty list");
|
||||||
return self.popx_back();
|
PyVar retval = self.back();
|
||||||
|
self.pop_back();
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
if(args.size() == 1+1){
|
if(args.size() == 1+1){
|
||||||
i64 index = CAST(i64, args[1]);
|
i64 index = CAST(i64, args[1]);
|
||||||
@ -936,7 +939,7 @@ void __init_builtins(VM* _vm) {
|
|||||||
int n = _CAST(int, _1);
|
int n = _CAST(int, _1);
|
||||||
List result;
|
List result;
|
||||||
result.reserve(self.size() * n);
|
result.reserve(self.size() * n);
|
||||||
for(int i = 0; i < n; i++) result.extend(self);
|
for(int i = 0; i < n; i++) result.extend(self.begin(), self.end());
|
||||||
return VAR(std::move(result));
|
return VAR(std::move(result));
|
||||||
});
|
});
|
||||||
_vm->bind_func(VM::tp_list, "__rmul__", 2, [](VM* vm, ArgsView args) {
|
_vm->bind_func(VM::tp_list, "__rmul__", 2, [](VM* vm, ArgsView args) {
|
||||||
@ -945,7 +948,7 @@ void __init_builtins(VM* _vm) {
|
|||||||
int n = _CAST(int, args[1]);
|
int n = _CAST(int, args[1]);
|
||||||
List result;
|
List result;
|
||||||
result.reserve(self.size() * n);
|
result.reserve(self.size() * n);
|
||||||
for(int i = 0; i < n; i++) result.extend(self);
|
for(int i = 0; i < n; i++) result.extend(self.begin(), self.end());
|
||||||
return VAR(std::move(result));
|
return VAR(std::move(result));
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -964,11 +967,14 @@ void __init_builtins(VM* _vm) {
|
|||||||
return vm->None;
|
return vm->None;
|
||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind_func(VM::tp_list, "copy", 1, PK_LAMBDA(VAR(_CAST(List, args[0]))));
|
_vm->bind_func(VM::tp_list, "copy", 1, [](VM* vm, ArgsView args){
|
||||||
|
const List& self = _CAST(List&, args[0]);
|
||||||
|
return VAR(List(explicit_copy_t(), self));
|
||||||
|
});
|
||||||
|
|
||||||
#define BIND_RICH_CMP(name, op, _t, _T) \
|
#define BIND_RICH_CMP(name, op, _t, _T) \
|
||||||
_vm->bind__##name##__(_vm->_t, [](VM* vm, PyVar lhs, PyVar rhs){ \
|
_vm->bind__##name##__(_vm->_t, [](VM* vm, PyVar lhs, PyVar rhs){ \
|
||||||
if(!is_type(rhs, vm->_t)) return vm->NotImplemented; \
|
if(!is_type(rhs, vm->_t)) return vm->NotImplemented; \
|
||||||
auto& a = _CAST(_T&, lhs); \
|
auto& a = _CAST(_T&, lhs); \
|
||||||
auto& b = _CAST(_T&, rhs); \
|
auto& b = _CAST(_T&, rhs); \
|
||||||
for(int i=0; i<a.size() && i<b.size(); i++){ \
|
for(int i=0; i<a.size() && i<b.size(); i++){ \
|
||||||
@ -993,8 +999,8 @@ void __init_builtins(VM* _vm) {
|
|||||||
_vm->bind__add__(VM::tp_list, [](VM* vm, PyVar _0, PyVar _1) {
|
_vm->bind__add__(VM::tp_list, [](VM* vm, PyVar _0, PyVar _1) {
|
||||||
const List& self = _CAST(List&, _0);
|
const List& self = _CAST(List&, _0);
|
||||||
const List& other = CAST(List&, _1);
|
const List& other = CAST(List&, _1);
|
||||||
List new_list(self); // copy construct
|
List new_list(explicit_copy_t(), self);
|
||||||
new_list.extend(other);
|
new_list.extend(other.begin(), other.end());
|
||||||
return VAR(std::move(new_list));
|
return VAR(std::move(new_list));
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1637,7 +1643,7 @@ void VM::__post_init_builtin_types(){
|
|||||||
try{
|
try{
|
||||||
// initialize dummy func_decl for exec/eval
|
// initialize dummy func_decl for exec/eval
|
||||||
CodeObject_ dynamic_co = compile("def _(): pass", "<dynamic>", EXEC_MODE);
|
CodeObject_ dynamic_co = compile("def _(): pass", "<dynamic>", EXEC_MODE);
|
||||||
__dynamic_func_decl = dynamic_co->func_decls.at(0);
|
__dynamic_func_decl = dynamic_co->func_decls[0];
|
||||||
// initialize builtins
|
// initialize builtins
|
||||||
CodeObject_ code = compile(kPythonLibs_builtins, "<builtins>", EXEC_MODE);
|
CodeObject_ code = compile(kPythonLibs_builtins, "<builtins>", EXEC_MODE);
|
||||||
this->_exec(code, this->builtins);
|
this->_exec(code, this->builtins);
|
||||||
|
@ -40,7 +40,7 @@ void LineProfiler::_step(int callstack_size, Frame* frame){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
frames.top().prev_record = &file_records.at(line);
|
frames.top().prev_record = &file_records[line];
|
||||||
}
|
}
|
||||||
|
|
||||||
void LineProfiler::_step_end(int callstack_size, Frame* frame, int line){
|
void LineProfiler::_step_end(int callstack_size, Frame* frame, int line){
|
||||||
@ -87,11 +87,11 @@ Str LineProfiler::stats(){
|
|||||||
int end_line = decl->code->end_line;
|
int end_line = decl->code->end_line;
|
||||||
if(start_line == -1 || end_line == -1) continue;
|
if(start_line == -1 || end_line == -1) continue;
|
||||||
std::string_view filename = decl->code->src->filename.sv();
|
std::string_view filename = decl->code->src->filename.sv();
|
||||||
std::vector<_LineRecord>& file_records = records[filename];
|
vector<_LineRecord>& file_records = records[filename];
|
||||||
if(file_records.empty()) continue;
|
if(file_records.empty()) continue;
|
||||||
clock_t total_time = 0;
|
clock_t total_time = 0;
|
||||||
for(int line = start_line; line <= end_line; line++){
|
for(int line = start_line; line <= end_line; line++){
|
||||||
total_time += file_records.at(line).time;
|
total_time += file_records[line].time;
|
||||||
}
|
}
|
||||||
ss << "Total time: " << (f64)total_time / CLOCKS_PER_SEC << "s\n";
|
ss << "Total time: " << (f64)total_time / CLOCKS_PER_SEC << "s\n";
|
||||||
ss << "File: " << filename << "\n";
|
ss << "File: " << filename << "\n";
|
||||||
@ -99,7 +99,7 @@ Str LineProfiler::stats(){
|
|||||||
ss << "Line # Hits Time Per Hit % Time Line Contents\n";
|
ss << "Line # Hits Time Per Hit % Time Line Contents\n";
|
||||||
ss << "==============================================================\n";
|
ss << "==============================================================\n";
|
||||||
for(int line = start_line; line <= end_line; line++){
|
for(int line = start_line; line <= end_line; line++){
|
||||||
const _LineRecord& record = file_records.at(line);
|
const _LineRecord& record = file_records[line];
|
||||||
if(!record.is_valid()) continue;
|
if(!record.is_valid()) continue;
|
||||||
ss << left_pad(std::to_string(line), 6);
|
ss << left_pad(std::to_string(line), 6);
|
||||||
if(record.hits == 0){
|
if(record.hits == 0){
|
||||||
|
@ -190,7 +190,7 @@ struct Random{
|
|||||||
PyVar* data = view.begin();
|
PyVar* data = view.begin();
|
||||||
int size = view.size();
|
int size = view.size();
|
||||||
if(size == 0) vm->IndexError("cannot choose from an empty sequence");
|
if(size == 0) vm->IndexError("cannot choose from an empty sequence");
|
||||||
pod_vector<f64> cum_weights(size);
|
array<f64> cum_weights(size);
|
||||||
if(args[2] == vm->None){
|
if(args[2] == vm->None){
|
||||||
for(int i = 0; i < size; i++) cum_weights[i] = i + 1;
|
for(int i = 0; i < size; i++) cum_weights[i] = i + 1;
|
||||||
}else{
|
}else{
|
||||||
|
24
src/str.cpp
24
src/str.cpp
@ -333,8 +333,8 @@ int utf8len(unsigned char c, bool suppress){
|
|||||||
return _byte_index_to_unicode(size);
|
return _byte_index_to_unicode(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
pod_vector<std::string_view> Str::split(const Str& sep) const{
|
vector<std::string_view> Str::split(const Str& sep) const{
|
||||||
pod_vector<std::string_view> result;
|
vector<std::string_view> result;
|
||||||
std::string_view tmp;
|
std::string_view tmp;
|
||||||
int start = 0;
|
int start = 0;
|
||||||
while(true){
|
while(true){
|
||||||
@ -349,8 +349,8 @@ int utf8len(unsigned char c, bool suppress){
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
pod_vector<std::string_view> Str::split(char sep) const{
|
vector<std::string_view> Str::split(char sep) const{
|
||||||
pod_vector<std::string_view> result;
|
vector<std::string_view> result;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for(int j = 0; j < size; j++){
|
for(int j = 0; j < size; j++){
|
||||||
if(data[j] == sep){
|
if(data[j] == sep){
|
||||||
@ -404,29 +404,35 @@ int utf8len(unsigned char c, bool suppress){
|
|||||||
}
|
}
|
||||||
|
|
||||||
Str SStream::str(){
|
Str SStream::str(){
|
||||||
|
#if 0
|
||||||
// after this call, the buffer is no longer valid
|
// after this call, the buffer is no longer valid
|
||||||
buffer.reserve(buffer.size() + 1); // allocate one more byte for '\0'
|
buffer.reserve(buffer.size() + 1); // allocate one more byte for '\0'
|
||||||
buffer[buffer.size()] = '\0'; // set '\0'
|
buffer[buffer.size()] = '\0'; // set '\0'
|
||||||
return Str(buffer.detach());
|
return Str(buffer.detach());
|
||||||
|
#else
|
||||||
|
#warning "SStream::str() needs to be optimized"
|
||||||
|
buffer.push_back('\0');
|
||||||
|
return Str(buffer.data(), buffer.size()-1);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SStream& SStream::operator<<(const Str& s){
|
SStream& SStream::operator<<(const Str& s){
|
||||||
buffer.extend(s.begin(), s.end());
|
for(char c: s) buffer.push_back(c);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
SStream& SStream::operator<<(const char* s){
|
SStream& SStream::operator<<(const char* s){
|
||||||
buffer.extend(s, s + strlen(s));
|
while(*s) buffer.push_back(*s++);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
SStream& SStream::operator<<(const std::string& s){
|
SStream& SStream::operator<<(const std::string& s){
|
||||||
buffer.extend(s.data(), s.data() + s.size());
|
for(char c: s) buffer.push_back(c);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
SStream& SStream::operator<<(std::string_view s){
|
SStream& SStream::operator<<(std::string_view s){
|
||||||
buffer.extend(s.data(), s.data() + s.size());
|
for(char c: s) buffer.push_back(c);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -459,7 +465,7 @@ int utf8len(unsigned char c, bool suppress){
|
|||||||
buffer.push_back('-');
|
buffer.push_back('-');
|
||||||
val = -val;
|
val = -val;
|
||||||
}
|
}
|
||||||
char* begin = buffer.end();
|
auto begin = buffer.end();
|
||||||
while(val){
|
while(val){
|
||||||
buffer.push_back('0' + val % 10);
|
buffer.push_back('0' + val % 10);
|
||||||
val /= 10;
|
val /= 10;
|
||||||
|
12
src/vm.cpp
12
src/vm.cpp
@ -330,7 +330,7 @@ namespace pkpy{
|
|||||||
|
|
||||||
PyVar VM::py_import(Str path, bool throw_err){
|
PyVar VM::py_import(Str path, bool throw_err){
|
||||||
if(path.empty()) vm->ValueError("empty module name");
|
if(path.empty()) vm->ValueError("empty module name");
|
||||||
static auto f_join = [](const pod_vector<std::string_view>& cpnts){
|
static auto f_join = [](const vector<std::string_view>& cpnts){
|
||||||
SStream ss;
|
SStream ss;
|
||||||
for(int i=0; i<cpnts.size(); i++){
|
for(int i=0; i<cpnts.size(); i++){
|
||||||
if(i != 0) ss << ".";
|
if(i != 0) ss << ".";
|
||||||
@ -346,7 +346,7 @@ namespace pkpy{
|
|||||||
Str curr_path = __import_context.pending.back();
|
Str curr_path = __import_context.pending.back();
|
||||||
bool curr_is_init = __import_context.pending_is_init.back();
|
bool curr_is_init = __import_context.pending_is_init.back();
|
||||||
// convert relative path to absolute path
|
// convert relative path to absolute path
|
||||||
pod_vector<std::string_view> cpnts = curr_path.split('.');
|
vector<std::string_view> cpnts = curr_path.split('.');
|
||||||
int prefix = 0; // how many dots in the prefix
|
int prefix = 0; // how many dots in the prefix
|
||||||
for(int i=0; i<path.length(); i++){
|
for(int i=0; i<path.length(); i++){
|
||||||
if(path[i] == '.') prefix++;
|
if(path[i] == '.') prefix++;
|
||||||
@ -366,7 +366,7 @@ namespace pkpy{
|
|||||||
PyVar ext_mod = _modules.try_get(name);
|
PyVar ext_mod = _modules.try_get(name);
|
||||||
if(ext_mod != nullptr) return ext_mod;
|
if(ext_mod != nullptr) return ext_mod;
|
||||||
|
|
||||||
pod_vector<std::string_view> path_cpnts = path.split('.');
|
vector<std::string_view> path_cpnts = path.split('.');
|
||||||
// check circular import
|
// check circular import
|
||||||
if(__import_context.pending.size() > 128){
|
if(__import_context.pending.size() > 128){
|
||||||
ImportError("maximum recursion depth exceeded while importing");
|
ImportError("maximum recursion depth exceeded while importing");
|
||||||
@ -769,7 +769,7 @@ Str VM::disassemble(CodeObject_ co){
|
|||||||
return s + std::string(n - s.length(), ' ');
|
return s + std::string(n - s.length(), ' ');
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<int> jumpTargets;
|
vector<int> jumpTargets;
|
||||||
for(int i=0; i<co->codes.size(); i++){
|
for(int i=0; i<co->codes.size(); i++){
|
||||||
Bytecode byte = co->codes[i];
|
Bytecode byte = co->codes[i];
|
||||||
if(byte.is_forward_jump()){
|
if(byte.is_forward_jump()){
|
||||||
@ -1442,7 +1442,7 @@ void VM::_error(PyVar e_obj){
|
|||||||
Exception& e = PK_OBJ_GET(Exception, e_obj);
|
Exception& e = PK_OBJ_GET(Exception, e_obj);
|
||||||
if(callstack.empty()){
|
if(callstack.empty()){
|
||||||
e.is_re = false;
|
e.is_re = false;
|
||||||
throw e;
|
throw std::move(e);
|
||||||
}
|
}
|
||||||
PUSH(e_obj);
|
PUSH(e_obj);
|
||||||
__raise_exc();
|
__raise_exc();
|
||||||
@ -1665,7 +1665,7 @@ void VM::__breakpoint(){
|
|||||||
bool show_headers = true;
|
bool show_headers = true;
|
||||||
|
|
||||||
while(true){
|
while(true){
|
||||||
std::vector<LinkedFrame*> frames;
|
vector<LinkedFrame*> frames;
|
||||||
LinkedFrame* lf = callstack._tail;
|
LinkedFrame* lf = callstack._tail;
|
||||||
while(lf != nullptr){
|
while(lf != nullptr){
|
||||||
frames.push_back(lf);
|
frames.push_back(lf);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user