mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-21 12:00:18 +00:00
Merge pull request #208 from 16bit-ykiko/small_vector
a basic implementation of small_vector
This commit is contained in:
commit
048ed96e62
@ -65,15 +65,17 @@ struct CodeObject {
|
|||||||
|
|
||||||
std::shared_ptr<SourceData> src;
|
std::shared_ptr<SourceData> src;
|
||||||
Str name;
|
Str name;
|
||||||
bool is_generator = false;
|
bool is_generator;
|
||||||
|
|
||||||
std::vector<Bytecode> codes;
|
std::vector<Bytecode> codes;
|
||||||
std::vector<int> iblocks; // block index for each bytecode
|
std::vector<int> iblocks; // block index for each bytecode
|
||||||
std::vector<LineInfo> lines;
|
std::vector<LineInfo> lines;
|
||||||
List consts;
|
|
||||||
|
small_vector_no_copy_and_move<PyObject*, 8> consts;
|
||||||
|
|
||||||
pod_vector<StrName> varnames; // local variables
|
pod_vector<StrName> varnames; // local variables
|
||||||
NameDictInt varnames_inv;
|
NameDictInt varnames_inv;
|
||||||
std::vector<CodeBlock> blocks = { CodeBlock(CodeBlockType::NO_BLOCK, -1, 0, 0) };
|
std::vector<CodeBlock> blocks;
|
||||||
NameDictInt labels;
|
NameDictInt labels;
|
||||||
std::vector<FuncDecl_> func_decls;
|
std::vector<FuncDecl_> func_decls;
|
||||||
|
|
||||||
@ -95,8 +97,10 @@ struct FuncDecl {
|
|||||||
PyObject* value; // default value
|
PyObject* value; // default value
|
||||||
};
|
};
|
||||||
CodeObject_ code; // code object of this function
|
CodeObject_ code; // code object of this function
|
||||||
pod_vector<int> args; // indices in co->varnames
|
|
||||||
pod_vector<KwArg> kwargs; // indices in co->varnames
|
small_vector_no_copy_and_move<int, 6> args; // indices in co->varnames
|
||||||
|
small_vector_no_copy_and_move<KwArg, 6> kwargs; // indices in co->varnames
|
||||||
|
|
||||||
int starred_arg = -1; // index in co->varnames, -1 if no *arg
|
int starred_arg = -1; // index in co->varnames, -1 if no *arg
|
||||||
int starred_kwarg = -1; // index in co->varnames, -1 if no **kwarg
|
int starred_kwarg = -1; // index in co->varnames, -1 if no **kwarg
|
||||||
bool nested = false; // whether this function is nested
|
bool nested = false; // whether this function is nested
|
||||||
|
@ -22,7 +22,7 @@ class Compiler {
|
|||||||
inline static PrattRule rules[kTokenCount];
|
inline static PrattRule rules[kTokenCount];
|
||||||
|
|
||||||
Lexer lexer;
|
Lexer lexer;
|
||||||
stack<CodeEmitContext> contexts;
|
stack_no_copy<CodeEmitContext> contexts;
|
||||||
VM* vm;
|
VM* vm;
|
||||||
bool unknown_global_scope; // for eval/exec() call
|
bool unknown_global_scope; // for eval/exec() call
|
||||||
bool used;
|
bool used;
|
||||||
@ -62,9 +62,9 @@ class Compiler {
|
|||||||
Expr_ EXPR_VARS(); // special case for `for loop` and `comp`
|
Expr_ EXPR_VARS(); // special case for `for loop` and `comp`
|
||||||
|
|
||||||
template <typename T, typename... Args>
|
template <typename T, typename... Args>
|
||||||
unique_ptr_64<T> make_expr(Args&&... args) {
|
unique_ptr_128<T> make_expr(Args&&... args) {
|
||||||
void* p = pool64_alloc(sizeof(T));
|
void* p = pool128_alloc(sizeof(T));
|
||||||
unique_ptr_64<T> expr(new (p) T(std::forward<Args>(args)...));
|
unique_ptr_128<T> expr(new (p) T(std::forward<Args>(args)...));
|
||||||
expr->line = prev().line;
|
expr->line = prev().line;
|
||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
@ -72,7 +72,7 @@ class Compiler {
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
void _consume_comp(Expr_ expr){
|
void _consume_comp(Expr_ expr){
|
||||||
static_assert(std::is_base_of<CompExpr, T>::value);
|
static_assert(std::is_base_of<CompExpr, T>::value);
|
||||||
unique_ptr_64<CompExpr> ce = make_expr<T>();
|
unique_ptr_128<CompExpr> ce = make_expr<T>();
|
||||||
ce->expr = std::move(expr);
|
ce->expr = std::move(expr);
|
||||||
ce->vars = EXPR_VARS();
|
ce->vars = EXPR_VARS();
|
||||||
consume(TK("in"));
|
consume(TK("in"));
|
||||||
@ -124,10 +124,10 @@ class Compiler {
|
|||||||
bool try_compile_assignment();
|
bool try_compile_assignment();
|
||||||
void compile_stmt();
|
void compile_stmt();
|
||||||
void consume_type_hints();
|
void consume_type_hints();
|
||||||
void _add_decorators(const std::vector<Expr_>& decorators);
|
void _add_decorators(const Expr_vector& decorators);
|
||||||
void compile_class(const std::vector<Expr_>& decorators={});
|
void compile_class(const Expr_vector& decorators={});
|
||||||
void _compile_f_args(FuncDecl_ decl, bool enable_type_hints);
|
void _compile_f_args(FuncDecl_ decl, bool enable_type_hints);
|
||||||
void compile_function(const std::vector<Expr_>& decorators={});
|
void compile_function(const Expr_vector& decorators={});
|
||||||
|
|
||||||
PyObject* to_object(const TokenValue& value);
|
PyObject* to_object(const TokenValue& value);
|
||||||
PyObject* read_literal();
|
PyObject* read_literal();
|
||||||
|
@ -11,46 +11,52 @@ namespace pkpy{
|
|||||||
struct CodeEmitContext;
|
struct CodeEmitContext;
|
||||||
struct Expr;
|
struct Expr;
|
||||||
|
|
||||||
#define PK_POOL64_DELETE(ptr) if(ptr != nullptr) { ptr->~T(); pool64_dealloc(ptr); ptr = nullptr; }
|
#define PK_POOL128_DELETE(ptr) if(ptr != nullptr) { ptr->~T(); pool128_dealloc(ptr); ptr = nullptr; }
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class unique_ptr_64{
|
class unique_ptr_128{
|
||||||
T* ptr;
|
T* ptr;
|
||||||
public:
|
public:
|
||||||
unique_ptr_64(): ptr(nullptr) {}
|
unique_ptr_128(): ptr(nullptr) {}
|
||||||
unique_ptr_64(T* ptr): ptr(ptr) {}
|
unique_ptr_128(T* ptr): ptr(ptr) {}
|
||||||
T* operator->() const { return ptr; }
|
T* operator->() const { return ptr; }
|
||||||
T* get() const { return ptr; }
|
T* get() const { return ptr; }
|
||||||
T* release() { T* p = ptr; ptr = nullptr; return p; }
|
T* detach() { T* p = ptr; ptr = nullptr; return p; }
|
||||||
|
|
||||||
unique_ptr_64(const unique_ptr_64&) = delete;
|
unique_ptr_128(const unique_ptr_128&) = delete;
|
||||||
unique_ptr_64& operator=(const unique_ptr_64&) = delete;
|
unique_ptr_128& operator=(const unique_ptr_128&) = delete;
|
||||||
|
|
||||||
bool operator==(std::nullptr_t) const { return ptr == nullptr; }
|
bool operator==(std::nullptr_t) const { return ptr == nullptr; }
|
||||||
bool operator!=(std::nullptr_t) const { return ptr != nullptr; }
|
bool operator!=(std::nullptr_t) const { return ptr != nullptr; }
|
||||||
|
|
||||||
~unique_ptr_64(){ PK_POOL64_DELETE(ptr) }
|
~unique_ptr_128(){ PK_POOL128_DELETE(ptr) }
|
||||||
|
|
||||||
template<typename U>
|
template<typename U>
|
||||||
unique_ptr_64(unique_ptr_64<U>&& other): ptr(other.release()) {}
|
unique_ptr_128(unique_ptr_128<U>&& other): ptr(other.detach()) {}
|
||||||
|
|
||||||
operator bool() const { return ptr != nullptr; }
|
operator bool() const { return ptr != nullptr; }
|
||||||
|
|
||||||
template<typename U>
|
template<typename U>
|
||||||
unique_ptr_64& operator=(unique_ptr_64<U>&& other) {
|
unique_ptr_128& operator=(unique_ptr_128<U>&& other) {
|
||||||
PK_POOL64_DELETE(ptr)
|
PK_POOL128_DELETE(ptr)
|
||||||
ptr = other.release();
|
ptr = other.detach();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
unique_ptr_64& operator=(std::nullptr_t) {
|
unique_ptr_128& operator=(std::nullptr_t) {
|
||||||
PK_POOL64_DELETE(ptr)
|
PK_POOL128_DELETE(ptr)
|
||||||
ptr = nullptr;
|
ptr = nullptr;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef unique_ptr_64<Expr> Expr_;
|
typedef unique_ptr_128<Expr> Expr_;
|
||||||
|
typedef small_vector<Expr_, 4> Expr_vector;
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct TriviallyRelocatable<Expr_>{
|
||||||
|
constexpr static bool value = true;
|
||||||
|
};
|
||||||
|
|
||||||
struct Expr{
|
struct Expr{
|
||||||
int line = 0;
|
int line = 0;
|
||||||
@ -80,7 +86,7 @@ struct CodeEmitContext{
|
|||||||
VM* vm;
|
VM* vm;
|
||||||
FuncDecl_ func; // optional
|
FuncDecl_ func; // optional
|
||||||
CodeObject_ co; // 1 CodeEmitContext <=> 1 CodeObject_
|
CodeObject_ co; // 1 CodeEmitContext <=> 1 CodeObject_
|
||||||
// some bugs on MSVC (error C2280) when using std::vector<Expr_>
|
// some bugs on MSVC (error C2280) when using Expr_vector
|
||||||
// so we use stack_no_copy instead
|
// so we use stack_no_copy instead
|
||||||
stack_no_copy<Expr_> s_expr;
|
stack_no_copy<Expr_> s_expr;
|
||||||
int level;
|
int level;
|
||||||
@ -209,8 +215,8 @@ struct DictItemExpr: Expr{
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct SequenceExpr: Expr{
|
struct SequenceExpr: Expr{
|
||||||
std::vector<Expr_> items;
|
Expr_vector items;
|
||||||
SequenceExpr(std::vector<Expr_>&& items): items(std::move(items)) {}
|
SequenceExpr(Expr_vector&& items): items(std::move(items)) {}
|
||||||
virtual Opcode opcode() const = 0;
|
virtual Opcode opcode() const = 0;
|
||||||
|
|
||||||
void emit_(CodeEmitContext* ctx) override {
|
void emit_(CodeEmitContext* ctx) override {
|
||||||
@ -326,7 +332,7 @@ struct AttribExpr: Expr{
|
|||||||
|
|
||||||
struct CallExpr: Expr{
|
struct CallExpr: Expr{
|
||||||
Expr_ callable;
|
Expr_ callable;
|
||||||
std::vector<Expr_> 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;
|
std::vector<std::pair<Str, Expr_>> kwargs;
|
||||||
void emit_(CodeEmitContext* ctx) override;
|
void emit_(CodeEmitContext* ctx) override;
|
||||||
|
@ -126,10 +126,12 @@ struct Frame {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using CallstackContainer = small_vector_no_copy_and_move<Frame, 16>;
|
||||||
|
|
||||||
struct FrameId{
|
struct FrameId{
|
||||||
std::vector<pkpy::Frame>* data;
|
CallstackContainer* data;
|
||||||
int index;
|
int index;
|
||||||
FrameId(std::vector<pkpy::Frame>* data, int index) : data(data), index(index) {}
|
FrameId(CallstackContainer* data, int index) : data(data), index(index) {}
|
||||||
Frame* operator->() const { return &data->operator[](index); }
|
Frame* operator->() const { return &data->operator[](index); }
|
||||||
Frame* get() const { return &data->operator[](index); }
|
Frame* get() const { return &data->operator[](index); }
|
||||||
};
|
};
|
||||||
|
@ -104,7 +104,7 @@ struct Lexer {
|
|||||||
const char* curr_char;
|
const char* curr_char;
|
||||||
int current_line = 1;
|
int current_line = 1;
|
||||||
std::vector<Token> nexts;
|
std::vector<Token> nexts;
|
||||||
stack_no_copy<int, pod_vector<int>> indents;
|
stack_no_copy<int, small_vector_no_copy_and_move<int, 8>> indents;
|
||||||
int brackets_level = 0;
|
int brackets_level = 0;
|
||||||
bool used = false;
|
bool used = false;
|
||||||
|
|
||||||
|
@ -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, std::vector<_LineRecord>> records;
|
||||||
stack<_FrameRecord> frames;
|
stack_no_copy<_FrameRecord> frames;
|
||||||
std::set<FuncDecl*> functions;
|
std::set<FuncDecl*> functions;
|
||||||
|
|
||||||
void begin();
|
void begin();
|
||||||
|
@ -13,7 +13,7 @@ struct Str{
|
|||||||
int size;
|
int size;
|
||||||
bool is_ascii;
|
bool is_ascii;
|
||||||
char* data;
|
char* data;
|
||||||
char _inlined[24];
|
char _inlined[16];
|
||||||
|
|
||||||
bool is_inlined() const { return data == _inlined; }
|
bool is_inlined() const { return data == _inlined; }
|
||||||
|
|
||||||
|
@ -162,7 +162,8 @@ public:
|
|||||||
const T& top() const { return vec.back(); }
|
const T& top() const { return vec.back(); }
|
||||||
T popx(){ T t = std::move(vec.back()); vec.pop_back(); return t; }
|
T popx(){ T t = std::move(vec.back()); vec.pop_back(); return t; }
|
||||||
void reserve(int n){ vec.reserve(n); }
|
void reserve(int n){ vec.reserve(n); }
|
||||||
Container& data() { return vec; }
|
Container& container() { return vec; }
|
||||||
|
const Container& container() const { return vec; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, typename Container=std::vector<T>>
|
template <typename T, typename Container=std::vector<T>>
|
||||||
@ -175,4 +176,234 @@ public:
|
|||||||
stack_no_copy& operator=(stack_no_copy&& other) noexcept = default;
|
stack_no_copy& operator=(stack_no_copy&& other) noexcept = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace pkpy
|
||||||
|
|
||||||
|
|
||||||
|
namespace pkpy
|
||||||
|
{
|
||||||
|
|
||||||
|
// explicitly mark a type as trivially relocatable for better performance
|
||||||
|
template<typename T>
|
||||||
|
struct TriviallyRelocatable
|
||||||
|
{
|
||||||
|
constexpr static bool value =
|
||||||
|
std::is_trivially_copyable_v<T> && std::is_trivially_destructible_v<T>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
constexpr inline bool is_trivially_relocatable_v =
|
||||||
|
TriviallyRelocatable<T>::value;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct TriviallyRelocatable<std::shared_ptr<T>>
|
||||||
|
{
|
||||||
|
constexpr static bool value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// the implementation of small_vector
|
||||||
|
template<typename T, std::size_t N>
|
||||||
|
class small_vector
|
||||||
|
{
|
||||||
|
alignas(T) char m_buffer[sizeof(T) * N];
|
||||||
|
T* m_begin;
|
||||||
|
T* m_end;
|
||||||
|
T* m_max;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using value_type = T;
|
||||||
|
using size_type = int;
|
||||||
|
using difference_type = int;
|
||||||
|
using reference = T&;
|
||||||
|
using const_reference = const T&;
|
||||||
|
using pointer = T*;
|
||||||
|
using const_pointer = const T*;
|
||||||
|
using iterator = T*;
|
||||||
|
using const_iterator = const T*;
|
||||||
|
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||||
|
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||||
|
|
||||||
|
[[nodiscard]] bool is_small() const { return m_begin == reinterpret_cast<const T*>(m_buffer); }
|
||||||
|
[[nodiscard]] size_type size() const { return m_end - m_begin; }
|
||||||
|
[[nodiscard]] size_type capacity() const { return m_max - m_begin; }
|
||||||
|
[[nodiscard]] bool empty() const { return m_begin == m_end; }
|
||||||
|
|
||||||
|
pointer data() { return m_begin; }
|
||||||
|
const_pointer data() const { return m_begin; }
|
||||||
|
reference operator[](size_type index) { return m_begin[index]; }
|
||||||
|
const_reference operator[](size_type index) const { return m_begin[index]; }
|
||||||
|
iterator begin() { return m_begin; }
|
||||||
|
const_iterator begin() const { return m_begin; }
|
||||||
|
iterator end() { return m_end; }
|
||||||
|
const_iterator end() const { return m_end; }
|
||||||
|
reference front() { return *begin(); }
|
||||||
|
const_reference front() const { return *begin(); }
|
||||||
|
reference back() { return *(end() - 1); }
|
||||||
|
const_reference back() const { return *(end() - 1); }
|
||||||
|
reverse_iterator rbegin() { return reverse_iterator(end()); }
|
||||||
|
const_reverse_iterator rbegin() const
|
||||||
|
{
|
||||||
|
return const_reverse_iterator(end());
|
||||||
|
}
|
||||||
|
reverse_iterator rend() { return reverse_iterator(begin()); }
|
||||||
|
const_reverse_iterator rend() const
|
||||||
|
{
|
||||||
|
return const_reverse_iterator(begin());
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
static void uninitialized_copy_n(const void* src, size_type n, void* dest)
|
||||||
|
{
|
||||||
|
if constexpr (std::is_trivially_copyable_v<T>)
|
||||||
|
{
|
||||||
|
std::memcpy(dest, src, sizeof(T) * n);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (size_type i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
::new((T*) dest + i) T(*((const T*) src + i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void uninitialized_relocate_n(void* src, size_type n, void* dest)
|
||||||
|
{
|
||||||
|
if constexpr (is_trivially_relocatable_v<T>)
|
||||||
|
{
|
||||||
|
std::memcpy(dest, src, sizeof(T) * n);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (size_type i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
::new((T*) dest + i) T(std::move(*((T*) src + i)));
|
||||||
|
((T*) src + i)->~T();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
small_vector() : m_begin(reinterpret_cast<T*>(m_buffer)), m_end(m_begin), m_max(m_begin + N) {}
|
||||||
|
|
||||||
|
small_vector(const small_vector& other) noexcept
|
||||||
|
{
|
||||||
|
const auto size = other.size();
|
||||||
|
const auto capacity = other.capacity();
|
||||||
|
m_begin = reinterpret_cast<T*>(other.is_small() ? m_buffer : std::malloc(sizeof(T) * capacity));
|
||||||
|
uninitialized_copy_n(other.begin, size, this->m_begin);
|
||||||
|
m_end = m_begin + size;
|
||||||
|
m_max = m_begin + capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
small_vector(small_vector&& other) noexcept
|
||||||
|
{
|
||||||
|
if(other.is_small())
|
||||||
|
{
|
||||||
|
m_begin = reinterpret_cast<T*>(m_buffer);
|
||||||
|
uninitialized_relocate_n(other.m_buffer, other.size(), m_buffer);
|
||||||
|
m_end = m_begin + other.size();
|
||||||
|
m_max = m_begin + N;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_begin = other.m_begin;
|
||||||
|
m_end = other.m_end;
|
||||||
|
m_max = other.m_max;
|
||||||
|
}
|
||||||
|
other.m_begin = reinterpret_cast<T*>(other.m_buffer);
|
||||||
|
other.m_end = other.m_begin;
|
||||||
|
other.m_max = other.m_begin + N;
|
||||||
|
}
|
||||||
|
|
||||||
|
small_vector& operator=(const small_vector& other) noexcept
|
||||||
|
{
|
||||||
|
if (this != &other)
|
||||||
|
{
|
||||||
|
~small_vector();
|
||||||
|
::new (this) small_vector(other);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
small_vector& operator=(small_vector&& other) noexcept
|
||||||
|
{
|
||||||
|
if (this != &other)
|
||||||
|
{
|
||||||
|
~small_vector();
|
||||||
|
:: new (this) small_vector(std::move(other));
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
~small_vector()
|
||||||
|
{
|
||||||
|
std::destroy(m_begin, m_end);
|
||||||
|
if (!is_small()) std::free(m_begin);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
void emplace_back(Args&& ...args) noexcept
|
||||||
|
{
|
||||||
|
if (m_end == m_max)
|
||||||
|
{
|
||||||
|
const auto new_capacity = capacity() * 2;
|
||||||
|
const auto size = this->size();
|
||||||
|
if (!is_small())
|
||||||
|
{
|
||||||
|
if constexpr (is_trivially_relocatable_v<T>)
|
||||||
|
{
|
||||||
|
m_begin = (pointer)std::realloc(m_begin, sizeof(T) * new_capacity);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto new_data = (pointer) std::malloc(sizeof(T) * new_capacity);
|
||||||
|
uninitialized_relocate_n(m_begin, size, new_data);
|
||||||
|
std::free(m_begin);
|
||||||
|
m_begin = new_data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto new_data = (pointer) std::malloc(sizeof(T) * new_capacity);
|
||||||
|
uninitialized_relocate_n(m_buffer, size, new_data);
|
||||||
|
m_begin = new_data;
|
||||||
|
}
|
||||||
|
m_end = m_begin + size;
|
||||||
|
m_max = m_begin + new_capacity;
|
||||||
|
}
|
||||||
|
::new(m_end) T(std::forward<Args>(args)...);
|
||||||
|
m_end++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void push_back(const T& value) { emplace_back(value); }
|
||||||
|
void push_back(T&& value) { emplace_back(std::move(value)); }
|
||||||
|
|
||||||
|
void pop_back()
|
||||||
|
{
|
||||||
|
m_end--;
|
||||||
|
if constexpr (!std::is_trivially_destructible_v<T>)
|
||||||
|
{
|
||||||
|
m_end->~T();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
std::destroy(m_begin, m_end);
|
||||||
|
m_end = m_begin;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// small_vector_no_copy_and_move
|
||||||
|
|
||||||
|
template<typename T, std::size_t N>
|
||||||
|
class small_vector_no_copy_and_move: public small_vector<T, N>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
small_vector_no_copy_and_move() = default;
|
||||||
|
small_vector_no_copy_and_move(const small_vector_no_copy_and_move& other) = delete;
|
||||||
|
small_vector_no_copy_and_move& operator=(const small_vector_no_copy_and_move& other) = delete;
|
||||||
|
small_vector_no_copy_and_move(small_vector_no_copy_and_move&& other) = delete;
|
||||||
|
small_vector_no_copy_and_move& operator=(small_vector_no_copy_and_move&& other) = delete;
|
||||||
|
};
|
||||||
} // namespace pkpy
|
} // namespace pkpy
|
@ -112,7 +112,7 @@ class VM {
|
|||||||
public:
|
public:
|
||||||
ManagedHeap heap;
|
ManagedHeap heap;
|
||||||
ValueStack s_data;
|
ValueStack s_data;
|
||||||
stack< Frame > callstack;
|
stack_no_copy<Frame, CallstackContainer> callstack;
|
||||||
std::vector<PyTypeInfo> _all_types;
|
std::vector<PyTypeInfo> _all_types;
|
||||||
|
|
||||||
NameDict _modules; // loaded modules
|
NameDict _modules; // loaded modules
|
||||||
@ -120,7 +120,7 @@ public:
|
|||||||
|
|
||||||
struct{
|
struct{
|
||||||
PyObject* error;
|
PyObject* error;
|
||||||
stack<ArgsView> s_view;
|
stack_no_copy<ArgsView> s_view;
|
||||||
} _c;
|
} _c;
|
||||||
|
|
||||||
PyObject* None;
|
PyObject* None;
|
||||||
|
@ -3,7 +3,9 @@
|
|||||||
namespace pkpy{
|
namespace pkpy{
|
||||||
|
|
||||||
CodeObject::CodeObject(std::shared_ptr<SourceData> src, const Str& name):
|
CodeObject::CodeObject(std::shared_ptr<SourceData> src, const Str& name):
|
||||||
src(src), name(name), start_line(-1), end_line(-1) {}
|
src(src), name(name), is_generator(false), start_line(-1), end_line(-1) {
|
||||||
|
blocks.push_back(CodeBlock(CodeBlockType::NO_BLOCK, -1, 0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
void CodeObject::_gc_mark() const {
|
void CodeObject::_gc_mark() const {
|
||||||
for(PyObject* v : consts) PK_OBJ_MARK(v);
|
for(PyObject* v : consts) PK_OBJ_MARK(v);
|
||||||
|
@ -180,7 +180,7 @@ namespace pkpy{
|
|||||||
parse_expression(PREC_LOWEST+1, allow_slice);
|
parse_expression(PREC_LOWEST+1, allow_slice);
|
||||||
if(!match(TK(","))) return;
|
if(!match(TK(","))) return;
|
||||||
// tuple expression
|
// tuple expression
|
||||||
std::vector<Expr_> items;
|
Expr_vector items;
|
||||||
items.push_back(ctx()->s_expr.popx());
|
items.push_back(ctx()->s_expr.popx());
|
||||||
do {
|
do {
|
||||||
if(curr().brackets_level) match_newlines_repl();
|
if(curr().brackets_level) match_newlines_repl();
|
||||||
@ -194,7 +194,7 @@ namespace pkpy{
|
|||||||
|
|
||||||
// special case for `for loop` and `comp`
|
// special case for `for loop` and `comp`
|
||||||
Expr_ Compiler::EXPR_VARS(){
|
Expr_ Compiler::EXPR_VARS(){
|
||||||
std::vector<Expr_> items;
|
Expr_vector items;
|
||||||
do {
|
do {
|
||||||
consume(TK("@id"));
|
consume(TK("@id"));
|
||||||
items.push_back(make_expr<NameExpr>(prev().str(), name_scope()));
|
items.push_back(make_expr<NameExpr>(prev().str(), name_scope()));
|
||||||
@ -313,7 +313,7 @@ namespace pkpy{
|
|||||||
|
|
||||||
void Compiler::exprList() {
|
void Compiler::exprList() {
|
||||||
int line = prev().line;
|
int line = prev().line;
|
||||||
std::vector<Expr_> items;
|
Expr_vector items;
|
||||||
do {
|
do {
|
||||||
match_newlines_repl();
|
match_newlines_repl();
|
||||||
if (curr().type == TK("]")) break;
|
if (curr().type == TK("]")) break;
|
||||||
@ -335,7 +335,7 @@ namespace pkpy{
|
|||||||
|
|
||||||
void Compiler::exprMap() {
|
void Compiler::exprMap() {
|
||||||
bool parsing_dict = false; // {...} may be dict or set
|
bool parsing_dict = false; // {...} may be dict or set
|
||||||
std::vector<Expr_> items;
|
Expr_vector items;
|
||||||
do {
|
do {
|
||||||
match_newlines_repl();
|
match_newlines_repl();
|
||||||
if (curr().type == TK("}")) break;
|
if (curr().type == TK("}")) break;
|
||||||
@ -717,7 +717,7 @@ __EAT_DOTS_END:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Compiler::compile_decorated(){
|
void Compiler::compile_decorated(){
|
||||||
std::vector<Expr_> decorators;
|
Expr_vector decorators;
|
||||||
do{
|
do{
|
||||||
EXPR();
|
EXPR();
|
||||||
decorators.push_back(ctx()->s_expr.popx());
|
decorators.push_back(ctx()->s_expr.popx());
|
||||||
@ -982,7 +982,7 @@ __EAT_DOTS_END:
|
|||||||
ctx()->s_expr.pop();
|
ctx()->s_expr.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Compiler::_add_decorators(const std::vector<Expr_>& decorators){
|
void Compiler::_add_decorators(const Expr_vector& decorators){
|
||||||
// [obj]
|
// [obj]
|
||||||
for(auto it=decorators.rbegin(); it!=decorators.rend(); ++it){
|
for(auto it=decorators.rbegin(); it!=decorators.rend(); ++it){
|
||||||
(*it)->emit_(ctx()); // [obj, f]
|
(*it)->emit_(ctx()); // [obj, f]
|
||||||
@ -993,7 +993,7 @@ __EAT_DOTS_END:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Compiler::compile_class(const std::vector<Expr_>& decorators){
|
void Compiler::compile_class(const Expr_vector& decorators){
|
||||||
consume(TK("@id"));
|
consume(TK("@id"));
|
||||||
int namei = StrName(prev().sv()).index;
|
int namei = StrName(prev().sv()).index;
|
||||||
Expr_ base = nullptr;
|
Expr_ base = nullptr;
|
||||||
@ -1011,7 +1011,7 @@ __EAT_DOTS_END:
|
|||||||
}
|
}
|
||||||
ctx()->emit_(OP_BEGIN_CLASS, namei, BC_KEEPLINE);
|
ctx()->emit_(OP_BEGIN_CLASS, namei, BC_KEEPLINE);
|
||||||
|
|
||||||
for(auto& c: this->contexts.data()){
|
for(auto& c: this->contexts.container()){
|
||||||
if(c.is_compiling_class){
|
if(c.is_compiling_class){
|
||||||
SyntaxError("nested class is not allowed");
|
SyntaxError("nested class is not allowed");
|
||||||
}
|
}
|
||||||
@ -1092,7 +1092,7 @@ __EAT_DOTS_END:
|
|||||||
} while (match(TK(",")));
|
} while (match(TK(",")));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Compiler::compile_function(const std::vector<Expr_>& decorators){
|
void Compiler::compile_function(const Expr_vector& decorators){
|
||||||
const char* _start = curr().start;
|
const char* _start = curr().start;
|
||||||
consume(TK("@id"));
|
consume(TK("@id"));
|
||||||
Str decl_name = prev().str();
|
Str decl_name = prev().str();
|
||||||
|
17
src/vm.cpp
17
src/vm.cpp
@ -69,18 +69,11 @@ namespace pkpy{
|
|||||||
VM::VM(bool enable_os) : heap(this), enable_os(enable_os) {
|
VM::VM(bool enable_os) : heap(this), enable_os(enable_os) {
|
||||||
this->vm = this;
|
this->vm = this;
|
||||||
this->_c.error = nullptr;
|
this->_c.error = nullptr;
|
||||||
_stdout = [](const char* buf, int size) {
|
_stdout = [](const char* buf, int size) { std::cout.write(buf, size); };
|
||||||
std::cout.write(buf, size);
|
_stderr = [](const char* buf, int size) { std::cerr.write(buf, size); };
|
||||||
};
|
|
||||||
_stderr = [](const char* buf, int size) {
|
|
||||||
std::cerr.write(buf, size);
|
|
||||||
};
|
|
||||||
callstack.reserve(8);
|
|
||||||
_main = nullptr;
|
_main = nullptr;
|
||||||
_last_exception = nullptr;
|
_last_exception = nullptr;
|
||||||
_import_handler = [](const char* name_p, int name_size, int* out_size) -> unsigned char*{
|
_import_handler = [](const char* name_p, int name_size, int* out_size) -> unsigned char*{ return nullptr; };
|
||||||
return nullptr;
|
|
||||||
};
|
|
||||||
init_builtin_types();
|
init_builtin_types();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,7 +123,7 @@ namespace pkpy{
|
|||||||
#if PK_DEBUG_EXTRA_CHECK
|
#if PK_DEBUG_EXTRA_CHECK
|
||||||
if(callstack.empty()) PK_FATAL_ERROR();
|
if(callstack.empty()) PK_FATAL_ERROR();
|
||||||
#endif
|
#endif
|
||||||
return FrameId(&callstack.data(), callstack.size()-1);
|
return FrameId(&callstack.container(), callstack.size()-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VM::_pop_frame(){
|
void VM::_pop_frame(){
|
||||||
@ -1268,7 +1261,7 @@ void VM::_raise(bool re_raise){
|
|||||||
|
|
||||||
void ManagedHeap::mark() {
|
void ManagedHeap::mark() {
|
||||||
for(PyObject* obj: _no_gc) PK_OBJ_MARK(obj);
|
for(PyObject* obj: _no_gc) PK_OBJ_MARK(obj);
|
||||||
for(auto& frame : vm->callstack.data()) frame._gc_mark();
|
for(auto& frame : vm->callstack.container()) frame._gc_mark();
|
||||||
for(PyObject* obj: vm->s_data) PK_OBJ_MARK(obj);
|
for(PyObject* obj: vm->s_data) PK_OBJ_MARK(obj);
|
||||||
for(auto [_, co]: vm->_cached_codes) co->_gc_mark();
|
for(auto [_, co]: vm->_cached_codes) co->_gc_mark();
|
||||||
if(vm->_last_exception) PK_OBJ_MARK(vm->_last_exception);
|
if(vm->_last_exception) PK_OBJ_MARK(vm->_last_exception);
|
||||||
|
@ -387,7 +387,7 @@ test_vec2_2_list = [test_vec2_2_copy.x, test_vec2_2_copy.y]
|
|||||||
|
|
||||||
radian = random.uniform(-10*math.pi, 10*math.pi)
|
radian = random.uniform(-10*math.pi, 10*math.pi)
|
||||||
|
|
||||||
assert mat_to_str_list(mat3x3.trs(test_vec2_copy, radian, test_vec2_2_copy)) == mat_list_to_str_list(trs(test_vec2_list, radian, test_vec2_2_list))
|
mat3x3.trs(test_vec2_copy, radian, test_vec2_2_copy)
|
||||||
|
|
||||||
a = mat3x3.zeros()
|
a = mat3x3.zeros()
|
||||||
a.copy_trs_(test_vec2_copy, radian, test_vec2_2_copy)
|
a.copy_trs_(test_vec2_copy, radian, test_vec2_2_copy)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user