major refactor

This commit is contained in:
blueloveTH 2024-06-02 16:53:51 +08:00
parent 9e4277e87f
commit 2dfb6ed07a
85 changed files with 665 additions and 640 deletions

View File

@ -1,5 +1,5 @@
#include "cJSON.h"
#include "pocketpy/pocketpy.h"
#include "pocketpy/pocketpy.hpp"
namespace pkpy {

View File

@ -8,7 +8,7 @@ static PyVar lua_popx_to_python(VM*);
template<typename T>
static void table_apply(VM* vm, T f){
PK_ASSERT(lua_istable(_L, -1));
assert(lua_istable(_L, -1));
lua_pushnil(_L); // [key]
while(lua_next(_L, -2) != 0){ // [key, val]
lua_pushvalue(_L, -2); // [key, val, key]
@ -191,7 +191,7 @@ static PyVar lua_popx_multi_to_python(VM* vm, int count){
}
return VAR(std::move(ret));
}
PK_FATAL_ERROR()
assert(false);
}
struct PyLuaFunction: PyLuaObject{

View File

@ -17,7 +17,7 @@ else()
endif()
include_directories(${CMAKE_CURRENT_LIST_DIR}/include)
aux_source_directory(${CMAKE_CURRENT_LIST_DIR}/src POCKETPY_SRC)
file(GLOB_RECURSE POCKETPY_SRC ${CMAKE_CURRENT_LIST_DIR}/src/*.cpp)
option(PK_USE_CJSON "" OFF)
if(PK_USE_CJSON)

View File

@ -1,3 +1,5 @@
python prebuild.py
SRC=$(find src/ -name "*.cpp")
FLAGS="-std=c++17 -Og -stdlib=libc++ -Iinclude -frtti -Wfatal-errors -g"

View File

@ -1,3 +1,3 @@
#pragma once
#include "pocketpy/pocketpy.h"
#include "pocketpy/pocketpy.hpp"

3
include/pocketpy.hpp Normal file
View File

@ -0,0 +1,3 @@
#pragma once
#include "pocketpy/pocketpy.hpp"

View File

@ -1,240 +0,0 @@
#pragma once
#include <cmath>
#include <cstring>
#include <ctime>
#include <stdexcept>
#include <string>
#include <chrono>
#include <string_view>
#include <memory>
#include <iostream>
#include <map>
#include <algorithm>
#include <variant>
#include <type_traits>
#include <typeindex>
#define PK_VERSION "2.0.0"
#define PK_VERSION_MAJOR 2
#define PK_VERSION_MINOR 0
#define PK_VERSION_PATCH 0
#include "config.h"
#include "export.h"
#include "_generated.h"
#ifdef min
#undef min
#endif
#ifdef max
#undef max
#endif
/*******************************************************************************/
#if PK_ENABLE_THREAD
#define PK_THREAD_LOCAL thread_local
#include <mutex>
struct GIL {
inline static std::mutex _mutex;
explicit GIL() { _mutex.lock(); }
~GIL() { _mutex.unlock(); }
};
#define PK_GLOBAL_SCOPE_LOCK() GIL _lock;
#else
#define PK_THREAD_LOCAL
#define PK_GLOBAL_SCOPE_LOCK()
#endif
/*******************************************************************************/
namespace pkpy{
namespace std = ::std;
using i64 = int64_t; // always 64-bit
using f64 = double; // always 64-bit
static_assert(sizeof(i64) == 8);
static_assert(sizeof(f64) == 8);
struct DummyInstance { };
struct DummyModule { };
struct NoReturn { };
struct Discarded { };
struct Type {
int16_t index;
constexpr Type(): index(0) {}
explicit constexpr Type(int index): index(index) {}
bool operator==(Type other) const { return this->index == other.index; }
bool operator!=(Type other) const { return this->index != other.index; }
constexpr operator int() const { return index; }
};
#define PK_LAMBDA(x) ([](VM* vm, ArgsView args) -> PyVar { return x; })
#define PK_VAR_LAMBDA(x) ([](VM* vm, ArgsView args) -> PyVar { return VAR(x); })
#define PK_ACTION(x) ([](VM* vm, ArgsView args) -> PyVar { x; return vm->None; })
#define PK_REGION(name) 1
#ifdef POCKETPY_H
#define PK_FATAL_ERROR() throw std::runtime_error( "L" + std::to_string(__LINE__) + " FATAL_ERROR()!");
#else
#define PK_FATAL_ERROR() throw std::runtime_error( __FILE__ + std::string(":") + std::to_string(__LINE__) + " FATAL_ERROR()!");
#endif
#define PK_ASSERT(x) if(!(x)) PK_FATAL_ERROR();
#if PK_DEBUG_EXTRA_CHECK
#define PK_DEBUG_ASSERT(x) if(!(x)) PK_FATAL_ERROR();
#else
#define PK_DEBUG_ASSERT(x)
#endif
// is_pod_v<> for c++17 and c++20
template<typename T>
inline constexpr bool is_pod_v = std::is_trivially_copyable_v<T> && std::is_standard_layout_v<T>;
#define PK_ALWAYS_PASS_BY_POINTER(T) \
T(const T&) = delete; \
T& operator=(const T&) = delete; \
T(T&&) = delete; \
T& operator=(T&&) = delete;
inline const char* kPlatformStrings[] = {
"win32", // 0
"emscripten", // 1
"ios", // 2
"darwin", // 3
"android", // 4
"linux", // 5
"unknown" // 6
};
#define PK_SLICE_LOOP(i, start, stop, step) for(int i=start; step>0?i<stop:i>stop; i+=step)
template<typename T>
inline constexpr bool is_integral_v = std::is_same_v<T, char>
|| std::is_same_v<T, short>
|| std::is_same_v<T, int>
|| std::is_same_v<T, long>
|| std::is_same_v<T, long long>
|| std::is_same_v<T, unsigned char>
|| std::is_same_v<T, unsigned short>
|| std::is_same_v<T, unsigned int>
|| std::is_same_v<T, unsigned long>
|| std::is_same_v<T, unsigned long long>
|| std::is_same_v<T, signed char>; // for imgui
template<typename T>
inline constexpr bool is_floating_point_v = std::is_same_v<T, float> || std::is_same_v<T, double>;
inline const char* PK_HEX_TABLE = "0123456789abcdef";
struct PyObject;
struct Frame;
class VM;
// by default, only `int` and `float` enable SSO
// users can specialize this template to enable SSO for other types
// SSO types cannot have instance dict
template<typename T>
inline constexpr bool is_sso_v = is_integral_v<T> || is_floating_point_v<T>;
// make a obj_get_t<T> for a given type T, if is_sso_v<T> is true, return T, else return T&
template<typename T>
using obj_get_t = std::conditional_t<is_sso_v<T>, T, T&>;
struct const_sso_var {};
struct PyVar final{
Type type;
bool is_ptr;
uint8_t flags;
// 12 bytes SSO
int _0; i64 _1;
// uninitialized
PyVar() = default;
// implict conversion
PyVar(PyObject* p);
/* We must initialize all members to allow == operator to work correctly */
// constexpr initialized
constexpr PyVar(const const_sso_var&, Type type, int value): type(type), is_ptr(false), flags(0), _0(value), _1(0) {}
// zero initialized
constexpr PyVar(std::nullptr_t): type(0), is_ptr(false), flags(0), _0(0), _1(0) {}
// PyObject* initialized (is_sso = false)
PyVar(Type type, PyObject* p): type(type), is_ptr(true), flags(0), _0(0), _1(reinterpret_cast<i64>(p)) {}
// SSO initialized (is_sso = true)
template<typename T>
PyVar(Type type, T value): type(type), is_ptr(false), flags(0), _0(0), _1(0) {
static_assert(sizeof(T) <= 12, "SSO size exceeded");
as<T>() = value;
}
template<typename T>
T& as(){
static_assert(!std::is_reference_v<T>);
if constexpr(sizeof(T) <= 8){
return reinterpret_cast<T&>(_1);
}else{
return reinterpret_cast<T&>(_0);
}
}
explicit operator bool() const { return (bool)type; }
void set_null() { _qword(0) = 0; _qword(1) = 0; }
i64 _qword(int i) const { return ((const i64*)this)[i]; }
i64& _qword(int i) { return ((i64*)this)[i]; }
bool operator==(const PyVar& other) const {
return _qword(0) == other._qword(0) && _qword(1) == other._qword(1);
}
bool operator!=(const PyVar& other) const {
return _qword(0) != other._qword(0) || _qword(1) != other._qword(1);
}
bool operator==(std::nullptr_t) const { return !(bool)type; }
bool operator!=(std::nullptr_t) const { return (bool)type; }
PyObject* get() const {
PK_DEBUG_ASSERT(is_ptr)
return reinterpret_cast<PyObject*>(_1);
}
PyObject* operator->() const {
PK_DEBUG_ASSERT(is_ptr)
return reinterpret_cast<PyObject*>(_1);
}
i64 hash() const { return _0 + _1; }
template<typename T>
obj_get_t<T> obj_get();
};
static_assert(sizeof(PyVar) == 16 && is_pod_v<PyVar>);
} // namespace pkpy
// specialize std::less for PyVar
namespace std {
template<>
struct less<pkpy::PyVar> {
bool operator()(const pkpy::PyVar& lhs, const pkpy::PyVar& rhs) const {
return memcmp(&lhs, &rhs, sizeof(pkpy::PyVar)) < 0;
}
};
}

View File

@ -1,7 +1,10 @@
#pragma once
#include "common.h"
#include "str.h"
#include "pocketpy/common/traits.hpp"
#include <typeindex>
#include <cassert>
#include <utility>
namespace pkpy {
@ -98,7 +101,7 @@ struct function<Ret(Params...)>{
}
Ret operator()(Params... params) const{
if(!_wrapper) throw std::runtime_error("empty function");
assert(_wrapper);
return _wrapper(_impl, std::forward<Params>(params)...);
}
};

View File

@ -0,0 +1,17 @@
#pragma once
#if PK_ENABLE_THREAD
#define PK_THREAD_LOCAL thread_local
#include <mutex>
struct GIL {
inline static std::mutex _mutex;
explicit GIL() { _mutex.lock(); }
~GIL() { _mutex.unlock(); }
};
#define PK_GLOBAL_SCOPE_LOCK() GIL _lock;
#else
#define PK_THREAD_LOCAL
#define PK_GLOBAL_SCOPE_LOCK()
#endif

View File

@ -1,11 +1,13 @@
#pragma once
#include "common.h"
#include <cstddef>
#include <string>
namespace pkpy{
void* pool128_alloc(size_t) noexcept;
void pool128_dealloc(void*) noexcept;
template<typename T>
void* pool128_alloc() noexcept{
return pool128_alloc(sizeof(T));

View File

@ -1,16 +1,16 @@
#pragma once
#include "common.h"
#include "memory.h"
#include "str.h"
#include "pocketpy/common/utils.hpp"
#include "pocketpy/common/str.hpp"
#include "pocketpy/config.h"
namespace pkpy{
template<typename T>
constexpr T default_invalid_value(){
if constexpr(std::is_same_v<PyVar, T>) return nullptr;
else if constexpr(std::is_same_v<int, T>) return -1;
else return Discarded();
if constexpr(std::is_same_v<int, T>) return -1;
else return nullptr;
}
template<typename T>
@ -80,7 +80,7 @@ while(!_items[i].first.empty()) { \
if(old_items[i].first.empty()) continue;
bool ok; uint16_t j;
HASH_PROBE_1(old_items[i].first, ok, j);
if(ok) PK_FATAL_ERROR();
assert(!ok);
_items[j] = old_items[i];
}
free(old_items);
@ -190,11 +190,4 @@ while(!_items[i].first.empty()) { \
#undef HASH_PROBE_1
};
using NameDict = NameDictImpl<PyVar>;
using NameDict_ = std::shared_ptr<NameDict>;
using NameDictInt = NameDictImpl<int>;
static_assert(sizeof(NameDict) <= 128);
} // namespace pkpy

View File

@ -1,8 +1,11 @@
#pragma once
#include "common.h"
#include "memory.h"
#include "vector.h"
#include "pocketpy/common/utils.hpp"
#include "pocketpy/common/memorypool.hpp"
#include "pocketpy/common/vector.hpp"
#include <string_view>
#include <map>
namespace pkpy {

View File

@ -0,0 +1,36 @@
#pragma once
#include <type_traits>
namespace pkpy{
// is_pod_v<> for c++17 and c++20
template<typename T>
inline constexpr bool is_pod_v = std::is_trivially_copyable_v<T> && std::is_standard_layout_v<T>;
// https://en.cppreference.com/w/cpp/types/is_integral
template<typename T>
inline constexpr bool is_integral_v = !std::is_same_v<T, bool> && std::is_integral_v<T>;
template<typename T>
inline constexpr bool is_floating_point_v = std::is_same_v<T, float> || std::is_same_v<T, double>;
// by default, only `int` and `float` enable SSO
// users can specialize this template to enable SSO for other types
// SSO types cannot have instance dict
template<typename T>
inline constexpr bool is_sso_v = is_integral_v<T> || is_floating_point_v<T>;
// if is_sso_v<T> is true, return T, else return T&
template<typename T>
using obj_get_t = std::conditional_t<is_sso_v<T>, T, T&>;
template<typename T>
constexpr inline bool is_trivially_relocatable_v = std::is_trivially_copyable_v<T> && std::is_trivially_destructible_v<T>;
template <typename, typename=void> struct has_gc_marker : std::false_type {};
template <typename T> struct has_gc_marker<T, std::void_t<decltype(&T::_gc_mark)>> : std::true_type {};
template<typename T>
inline constexpr int py_sizeof = 16 + sizeof(T);
} // namespace pkpy

View File

@ -0,0 +1,28 @@
#pragma once
#include <cstdint>
namespace pkpy{
using i64 = int64_t; // always 64-bit
using f64 = double; // always 64-bit
static_assert(sizeof(i64) == 8);
static_assert(sizeof(f64) == 8);
// Explicitly allow copying if copy constructor is deleted
struct explicit_copy_t {
explicit explicit_copy_t() = default;
};
// Dummy types
struct DummyInstance { };
struct DummyModule { };
struct NoReturn { };
// Forward declarations
struct PyObject;
struct Frame;
class VM;
}; // namespace pkpy

View File

@ -0,0 +1,28 @@
#pragma once
#define PK_REGION(name) 1
#define PK_ALWAYS_PASS_BY_POINTER(T) \
T(const T&) = delete; \
T& operator=(const T&) = delete; \
T(T&&) = delete; \
T& operator=(T&&) = delete;
#define PK_SLICE_LOOP(i, start, stop, step) for(int i=start; step>0?i<stop:i>stop; i+=step)
namespace pkpy{
// global constants
inline const char* PK_HEX_TABLE = "0123456789abcdef";
inline const char* kPlatformStrings[] = {
"win32", // 0
"emscripten", // 1
"ios", // 2
"darwin", // 3
"android", // 4
"linux", // 5
"unknown" // 6
};
} // namespace pkpy

View File

@ -1,17 +1,14 @@
#pragma once
#include "common.h"
#include "memory.h"
#include "pocketpy/common/traits.hpp"
#include "pocketpy/common/types.hpp"
#include <cstring>
#include <memory>
#include <cassert>
namespace pkpy{
struct explicit_copy_t {
explicit explicit_copy_t() = default;
};
template<typename T>
constexpr inline bool is_trivially_relocatable_v = std::is_trivially_copyable_v<T> && std::is_trivially_destructible_v<T>;
template<typename T>
struct array{
T* _data;
@ -48,12 +45,12 @@ struct array{
array& operator=(const array& other) = delete;
T& operator[](int i) {
PK_DEBUG_ASSERT(i>=0 && i<_size);
assert(i >= 0 && i < _size);
return _data[i];
}
const T& operator[](int i) const {
PK_DEBUG_ASSERT(i>=0 && i<_size);
assert(i >= 0 && i < _size);
return _data[i];
}
@ -192,7 +189,7 @@ struct vector{
}
void pop_back(){
PK_DEBUG_ASSERT(_size > 0);
assert(_size > 0);
_size--;
if constexpr(!std::is_trivially_destructible_v<T>){
_data[_size].~T();
@ -315,7 +312,7 @@ namespace pkpy {
{
if constexpr (std::is_trivially_copyable_v<T>)
{
std::memcpy(dest, src, sizeof(T) * n);
memcpy(dest, src, sizeof(T) * n);
}
else
{
@ -330,7 +327,7 @@ namespace pkpy {
{
if constexpr (is_trivially_relocatable_v<T>)
{
std::memcpy(dest, src, sizeof(T) * n);
memcpy(dest, src, sizeof(T) * n);
}
else
{

View File

@ -0,0 +1,6 @@
#pragma once
#define PK_VERSION "2.0.0"
#define PK_VERSION_MAJOR 2
#define PK_VERSION_MINOR 0
#define PK_VERSION_PATCH 0

View File

@ -1,9 +1,6 @@
#pragma once
#include "codeobject.h"
#include "common.h"
#include "expr.h"
#include "obj.h"
#include "pocketpy/compiler/expr.hpp"
namespace pkpy{

View File

@ -1,10 +1,7 @@
#pragma once
#include "codeobject.h"
#include "common.h"
#include "lexer.h"
#include "error.h"
#include "vm.h"
#include "pocketpy/objects/codeobject.hpp"
#include "pocketpy/compiler/lexer.hpp"
namespace pkpy{

View File

@ -1,9 +1,9 @@
#pragma once
#include "common.h"
#include "error.h"
#include "str.h"
#include "obj.h"
#include "pocketpy/objects/sourcedata.hpp"
#include "pocketpy/objects/error.hpp"
#include <variant>
namespace pkpy{

View File

@ -1,7 +1,6 @@
#pragma once
#include "cffi.h"
#include "vm.h"
#include "pocketpy/interpreter/cffi.hpp"
namespace pkpy{
struct NativeProxyFuncCBase {
@ -16,7 +15,7 @@ struct NativeProxyFuncC final: NativeProxyFuncCBase {
NativeProxyFuncC(_Fp func) : func(func) {}
PyVar operator()(VM* vm, ArgsView args) override {
PK_DEBUG_ASSERT(args.size() == N);
assert(args.size() == N);
return call<Ret>(vm, args, std::make_index_sequence<N>());
}
@ -40,7 +39,7 @@ struct NativeProxyMethodC final: NativeProxyFuncCBase {
NativeProxyMethodC(_Fp func) : func(func) {}
PyVar operator()(VM* vm, ArgsView args) override {
PK_DEBUG_ASSERT(args.size() == N+1);
assert(args.size() == N+1);
return call<Ret>(vm, args, std::make_index_sequence<N>());
}
@ -89,7 +88,7 @@ PyObject* VM::bind(PyObject* obj, const char* sig, const char* docstring, Ret(T:
template<typename T, typename F, bool ReadOnly>
PyObject* VM::bind_field(PyObject* obj, const char* name, F T::*field){
static_assert(!std::is_reference_v<F>);
PK_ASSERT(is_type(obj, tp_type));
assert(is_type(obj, tp_type));
std::string_view name_sv(name); int pos = name_sv.find(':');
if(pos > 0) name_sv = name_sv.substr(0, pos);
auto fget = [](VM* vm, ArgsView args) -> PyVar{
@ -201,4 +200,8 @@ PyObject* VM::bind_field(PyObject* obj, const char* name, F T::*field){
tgt[i] = CAST(T, _2); \
}); \
#define PK_LAMBDA(x) ([](VM* vm, ArgsView args) -> PyVar { return x; })
#define PK_VAR_LAMBDA(x) ([](VM* vm, ArgsView args) -> PyVar { return VAR(x); })
#define PK_ACTION(x) ([](VM* vm, ArgsView args) -> PyVar { x; return vm->None; })
} // namespace pkpy

View File

@ -1,4 +1,4 @@
#pragma once
#include "vm.h"
#include "pocketpy/interpreter/vm.hpp"
// dummy header for ceval.cpp

View File

@ -1,7 +1,6 @@
#pragma once
#include "common.h"
#include "vm.h"
#include "pocketpy/interpreter/vm.hpp"
namespace pkpy {

View File

@ -1,10 +1,6 @@
#pragma once
#include "codeobject.h"
#include "common.h"
#include "memory.h"
#include "obj.h"
#include "vector.h"
#include "pocketpy/objects/codeobject.hpp"
namespace pkpy{
@ -155,32 +151,12 @@ struct CallStack{
++_size;
}
void pop(){
PK_DEBUG_ASSERT(!empty())
LinkedFrame* p = _tail;
_tail = p->f_back;
p->~LinkedFrame();
pool128_dealloc(p);
--_size;
}
LinkedFrame* popx(){
PK_DEBUG_ASSERT(!empty())
LinkedFrame* p = _tail;
_tail = p->f_back;
--_size;
p->f_back = nullptr; // unlink
return p;
}
void pushx(LinkedFrame* p){
p->f_back = _tail;
_tail = p;
++_size;
}
void pop();
LinkedFrame* popx();
void pushx(LinkedFrame* p);
Frame& top() const {
PK_DEBUG_ASSERT(!empty())
assert(!empty());
return _tail->frame;
}

View File

@ -1,8 +1,9 @@
#pragma once
#include "common.h"
#include "memory.h"
#include "obj.h"
#include "pocketpy/config.h"
#include "pocketpy/common/vector.hpp"
#include "pocketpy/common/utils.hpp"
#include "pocketpy/objects/object.hpp"
namespace pkpy {
struct ManagedHeap{

View File

@ -1,8 +1,6 @@
#pragma once
#include "cffi.h"
#include "common.h"
#include "frame.h"
#include "pocketpy/interpreter/bindings.hpp"
namespace pkpy{

View File

@ -1,6 +1,6 @@
#pragma once
#include "frame.h"
#include "pocketpy/interpreter/frame.hpp"
namespace pkpy {

View File

@ -1,17 +1,12 @@
#pragma once
#include "codeobject.h"
#include "common.h"
#include "frame.h"
#include "error.h"
#include "gc.h"
#include "memory.h"
#include "obj.h"
#include "str.h"
#include "tuplelist.h"
#include "dict.h"
#include "profiler.h"
#include "pocketpy/objects/object.hpp"
#include "pocketpy/objects/dict.hpp"
#include "pocketpy/objects/error.hpp"
#include "pocketpy/objects/stackmemory.hpp"
#include "pocketpy/objects/builtins.hpp"
#include "pocketpy/interpreter/gc.hpp"
#include "pocketpy/interpreter/frame.hpp"
namespace pkpy{
@ -654,7 +649,10 @@ PyObject* VM::register_user_class(PyObject* mod, StrName name, RegisterFunc _reg
return vm->new_object<T>(cls_t);
});
}else{
bind_func(type, __new__, -1, PK_ACTION(vm->NotImplementedError()));
bind_func(type, __new__, -1, [](VM* vm, ArgsView args){
vm->NotImplementedError();
return vm->None;
});
}
}
return type;

View File

@ -1,6 +1,6 @@
#pragma once
#include "bindings.h"
#include "pocketpy/common/types.hpp"
namespace pkpy {

View File

@ -1,6 +1,6 @@
#pragma once
#include "bindings.h"
#include "pocketpy/common/types.hpp"
namespace pkpy {

View File

@ -1,6 +1,6 @@
#pragma once
#include "bindings.h"
#include "pocketpy/common/types.hpp"
namespace pkpy {

View File

@ -1,6 +1,6 @@
#pragma once
#include "bindings.h"
#include "pocketpy/common/types.hpp"
namespace pkpy{

View File

@ -1,6 +1,6 @@
#pragma once
#include "bindings.h"
#include "pocketpy/common/types.hpp"
namespace pkpy{

View File

@ -1,6 +1,6 @@
#pragma once
#include "bindings.h"
#include "pocketpy/common/types.hpp"
namespace pkpy{
unsigned char* _default_import_handler(const char*, int*);

View File

@ -1,6 +1,9 @@
#pragma once
#include "bindings.h"
#include "pocketpy/common/types.hpp"
#include "pocketpy/common/traits.hpp"
#include <cmath>
namespace pkpy{

View File

@ -1,6 +1,6 @@
#pragma once
#include "bindings.h"
#include "pocketpy/common/types.hpp"
namespace pkpy{

View File

@ -1,6 +1,6 @@
#pragma once
#include "bindings.h"
#include "pocketpy/common/types.hpp"
namespace pkpy{

View File

@ -0,0 +1,100 @@
#pragma once
#include "pocketpy/common/types.hpp"
#include "pocketpy/common/traits.hpp"
#include <cstdint>
#include <cassert>
#include <cstring>
namespace pkpy{
struct Type {
int16_t index;
constexpr Type(): index(0) {}
explicit constexpr Type(int index): index(index) {}
bool operator==(Type other) const { return this->index == other.index; }
bool operator!=(Type other) const { return this->index != other.index; }
constexpr operator int() const { return index; }
};
struct const_sso_var {};
struct PyVar final{
Type type;
bool is_ptr;
uint8_t flags;
// 12 bytes SSO
int _0; i64 _1;
// uninitialized
PyVar() = default;
// implict conversion
PyVar(PyObject* p);
/* We must initialize all members to allow == operator to work correctly */
// constexpr initialized
constexpr PyVar(const const_sso_var&, Type type, int value): type(type), is_ptr(false), flags(0), _0(value), _1(0) {}
// zero initialized
constexpr PyVar(std::nullptr_t): type(0), is_ptr(false), flags(0), _0(0), _1(0) {}
// PyObject* initialized (is_sso = false)
PyVar(Type type, PyObject* p): type(type), is_ptr(true), flags(0), _0(0), _1(reinterpret_cast<i64>(p)) {}
// SSO initialized (is_sso = true)
template<typename T>
PyVar(Type type, T value): type(type), is_ptr(false), flags(0), _0(0), _1(0) {
static_assert(sizeof(T) <= 12, "SSO size exceeded");
as<T>() = value;
}
template<typename T>
T& as(){
static_assert(!std::is_reference_v<T>);
if constexpr(sizeof(T) <= 8){
return reinterpret_cast<T&>(_1);
}else{
return reinterpret_cast<T&>(_0);
}
}
explicit operator bool() const { return (bool)type; }
void set_null() { _qword(0) = 0; _qword(1) = 0; }
i64 _qword(int i) const { return ((const i64*)this)[i]; }
i64& _qword(int i) { return ((i64*)this)[i]; }
bool operator==(const PyVar& other) const {
return _qword(0) == other._qword(0) && _qword(1) == other._qword(1);
}
bool operator!=(const PyVar& other) const {
return _qword(0) != other._qword(0) || _qword(1) != other._qword(1);
}
bool operator==(std::nullptr_t) const { return !(bool)type; }
bool operator!=(std::nullptr_t) const { return (bool)type; }
PyObject* get() const {
assert(is_ptr);
return reinterpret_cast<PyObject*>(_1);
}
PyObject* operator->() const {
assert(is_ptr);
return reinterpret_cast<PyObject*>(_1);
}
i64 hash() const { return _0 + _1; }
template<typename T>
obj_get_t<T> obj_get();
// for std::map<>
bool operator<(const PyVar& other) const {
return memcmp(this, &other, sizeof(PyVar)) < 0;
}
};
static_assert(sizeof(PyVar) == 16 && is_pod_v<PyVar>);
} // namespace pkpy

View File

@ -1,23 +1,10 @@
#pragma once
#include "common.h"
#include "namedict.h"
#include "tuplelist.h"
#include "pocketpy/common/vector.hpp"
#include "pocketpy/objects/object.hpp"
namespace pkpy{
#if PK_ENABLE_STD_FUNCTION
using NativeFuncC = function<PyVar(VM*, ArgsView)>;
#else
typedef PyVar (*NativeFuncC)(VM*, ArgsView);
#endif
enum class BindType{
DEFAULT,
STATICMETHOD,
CLASSMETHOD,
};
struct BoundMethod {
PyVar self;
PyVar func;
@ -50,13 +37,6 @@ struct Range {
i64 step = 1;
};
struct StackMemory{
int count;
StackMemory(int count) : count(count) {}
};
template<>
inline bool constexpr is_sso_v<StackMemory> = true;
struct StarWrapper{
int level; // either 1 or 2
@ -82,76 +62,19 @@ struct Slice {
void _gc_mark(VM*) const;
};
struct PyObject final{
static constexpr int FIXED_SIZE = 16;
bool gc_marked; // whether this object is marked
Type type; // we have a duplicated type here for convenience
NameDict* _attr; // gc will delete this on destruction
bool is_attr_valid() const noexcept { return _attr != nullptr; }
void* _value_ptr() noexcept { return (char*)this + FIXED_SIZE; }
template<typename T> T& as() noexcept {
static_assert(std::is_same_v<T, std::decay_t<T>>);
return *reinterpret_cast<T*>(_value_ptr());
}
NameDict& attr() {
PK_DEBUG_ASSERT(is_attr_valid())
return *_attr;
}
PyVar attr(StrName name) const {
PK_DEBUG_ASSERT(is_attr_valid())
return (*_attr)[name];
}
PyObject(Type type) : gc_marked(false), type(type), _attr(nullptr) {}
template<typename T, typename ...Args>
void placement_new(Args&&... args){
static_assert(std::is_same_v<T, std::decay_t<T>>);
new(_value_ptr()) T(std::forward<Args>(args)...);
// backdoor for important builtin types
if constexpr(std::is_same_v<T, DummyInstance>){
_enable_instance_dict();
}else if constexpr(std::is_same_v<T, Type>){
_enable_instance_dict(PK_TYPE_ATTR_LOAD_FACTOR);
}else if constexpr(std::is_same_v<T, DummyModule>){
_enable_instance_dict(PK_TYPE_ATTR_LOAD_FACTOR);
}
}
void _enable_instance_dict() {
_attr = new(pool128_alloc<NameDict>()) NameDict();
}
void _enable_instance_dict(float lf){
_attr = new(pool128_alloc<NameDict>()) NameDict(lf);
}
};
static_assert(sizeof(PyObject) <= PyObject::FIXED_SIZE);
template<typename T>
inline constexpr int py_sizeof = PyObject::FIXED_SIZE + sizeof(T);
inline const int kTpIntIndex = 3;
inline const int kTpFloatIndex = 4;
inline const int kTpStackMemoryIndex = 27;
inline bool is_tagged(PyVar p) noexcept { return !p.is_ptr; }
inline bool is_float(PyVar p) noexcept { return p.type.index == kTpFloatIndex; }
inline bool is_int(PyVar p) noexcept { return p.type.index == kTpIntIndex; }
inline bool is_type(PyVar obj, Type type) {
PK_DEBUG_ASSERT(obj != nullptr)
assert(obj != nullptr);
return obj.type == type;
}
template <typename, typename=void> struct has_gc_marker : std::false_type {};
template <typename T> struct has_gc_marker<T, std::void_t<decltype(&T::_gc_mark)>> : std::true_type {};
struct MappingProxy{
PyObject* obj;
MappingProxy(PyObject* obj) : obj(obj) {}
@ -169,7 +92,7 @@ obj_get_t<T> PyVar::obj_get(){
if constexpr(is_sso_v<T>){
return as<T>();
}else{
PK_DEBUG_ASSERT(is_ptr)
assert(is_ptr);
void* v = ((PyObject*)_1)->_value_ptr();
return *reinterpret_cast<T*>(v);
}

View File

@ -1,16 +1,29 @@
#pragma once
#include "obj.h"
#include "error.h"
#include "any.h"
#include "pocketpy/common/any.hpp"
#include "pocketpy/objects/tuplelist.hpp"
#include "pocketpy/objects/object.hpp"
#include "pocketpy/objects/sourcedata.hpp"
namespace pkpy{
#if PK_ENABLE_STD_FUNCTION
using NativeFuncC = function<PyVar(VM*, ArgsView)>;
#else
typedef PyVar (*NativeFuncC)(VM*, ArgsView);
#endif
enum class BindType{
DEFAULT,
STATICMETHOD,
CLASSMETHOD,
};
enum NameScope { NAME_LOCAL, NAME_GLOBAL, NAME_GLOBAL_UNKNOWN };
enum Opcode: uint8_t {
#define OPCODE(name) OP_##name,
#include "opcodes.h"
#include "pocketpy/opcodes.h"
#undef OPCODE
};
@ -158,8 +171,8 @@ struct Function{
template<typename T>
T& lambda_get_userdata(PyVar* p){
static_assert(std::is_same_v<T, std::decay_t<T>>);
int offset = p[-1] != PY_NULL ? -1 : -2;
return PK_OBJ_GET(NativeFunc, p[offset])._userdata.cast<T>();
int offset = p[-1] != nullptr ? -1 : -2;
return p[offset].obj_get<NativeFunc>()._userdata.cast<T>();
}
} // namespace pkpy

View File

@ -1,9 +1,7 @@
#pragma once
#include "obj.h"
#include "common.h"
#include "memory.h"
#include "str.h"
#include "pocketpy/objects/base.hpp"
#include "pocketpy/objects/tuplelist.hpp"
namespace pkpy{

View File

@ -1,8 +1,7 @@
#pragma once
#include "namedict.h"
#include "str.h"
#include "tuplelist.h"
#include "pocketpy/common/str.hpp"
#include "pocketpy/objects/sourcedata.hpp"
namespace pkpy{
@ -22,33 +21,6 @@ struct InternalException final{
InternalException(InternalExceptionType type, int arg=-1): type(type), arg(arg) {}
};
enum CompileMode {
EXEC_MODE,
EVAL_MODE,
REPL_MODE,
JSON_MODE,
CELL_MODE
};
struct SourceData {
PK_ALWAYS_PASS_BY_POINTER(SourceData)
Str filename;
CompileMode mode;
Str source;
vector<const char*> line_starts;
bool is_precompiled;
vector<Str> _precompiled_tokens;
SourceData(std::string_view source, const Str& filename, CompileMode mode);
SourceData(const Str& filename, CompileMode mode);
std::pair<const char*,const char*> _get_line(int lineno) const;
std::string_view get_line(int lineno) const;
Str snapshot(int lineno, const char* cursor, std::string_view name) const;
};
struct Exception {
StrName type;
Str msg;
@ -75,7 +47,7 @@ struct Exception {
Exception(StrName type): type(type), is_re(true), _ip_on_error(-1), _code_on_error(nullptr), _self(nullptr) {}
PyObject* self() const{
PK_ASSERT(_self != nullptr);
assert(_self != nullptr);
return _self;
}

View File

@ -0,0 +1,63 @@
#pragma once
#include "pocketpy/common/namedict.hpp"
#include "pocketpy/objects/base.hpp"
namespace pkpy{
using NameDict = NameDictImpl<PyVar>;
using NameDict_ = std::shared_ptr<NameDict>;
using NameDictInt = NameDictImpl<int>;
static_assert(sizeof(NameDict) <= 128);
struct PyObject final{
bool gc_marked; // whether this object is marked
Type type; // we have a duplicated type here for convenience
NameDict* _attr; // gc will delete this on destruction
bool is_attr_valid() const noexcept { return _attr != nullptr; }
void* _value_ptr() noexcept { return (char*)this + 16; }
template<typename T> T& as() noexcept {
static_assert(std::is_same_v<T, std::decay_t<T>>);
return *reinterpret_cast<T*>(_value_ptr());
}
NameDict& attr() {
assert(is_attr_valid());
return *_attr;
}
PyVar attr(StrName name) const {
assert(is_attr_valid());
return (*_attr)[name];
}
PyObject(Type type) : gc_marked(false), type(type), _attr(nullptr) {}
template<typename T, typename ...Args>
void placement_new(Args&&... args){
static_assert(std::is_same_v<T, std::decay_t<T>>);
new(_value_ptr()) T(std::forward<Args>(args)...);
// backdoor for important builtin types
if constexpr(std::is_same_v<T, DummyInstance>){
_enable_instance_dict();
}else if constexpr(std::is_same_v<T, Type>){
_enable_instance_dict(PK_TYPE_ATTR_LOAD_FACTOR);
}else if constexpr(std::is_same_v<T, DummyModule>){
_enable_instance_dict(PK_TYPE_ATTR_LOAD_FACTOR);
}
}
void _enable_instance_dict() {
_attr = new(pool128_alloc<NameDict>()) NameDict();
}
void _enable_instance_dict(float lf){
_attr = new(pool128_alloc<NameDict>()) NameDict(lf);
}
};
static_assert(sizeof(PyObject) <= 16);
} // namespace pkpy

View File

@ -0,0 +1,35 @@
#pragma once
#include "pocketpy/common/utils.hpp"
#include "pocketpy/common/str.hpp"
namespace pkpy{
enum CompileMode {
EXEC_MODE,
EVAL_MODE,
REPL_MODE,
JSON_MODE,
CELL_MODE
};
struct SourceData {
PK_ALWAYS_PASS_BY_POINTER(SourceData)
Str filename;
CompileMode mode;
Str source;
vector<const char*> line_starts;
bool is_precompiled;
vector<Str> _precompiled_tokens;
SourceData(std::string_view source, const Str& filename, CompileMode mode);
SourceData(const Str& filename, CompileMode mode);
std::pair<const char*,const char*> _get_line(int lineno) const;
std::string_view get_line(int lineno) const;
Str snapshot(int lineno, const char* cursor, std::string_view name) const;
};
} // namespace pkpy

View File

@ -0,0 +1,17 @@
#pragma once
#include "pocketpy/common/traits.hpp"
namespace pkpy{
struct StackMemory{
int count;
StackMemory(int count) : count(count) {}
};
template<>
inline bool constexpr is_sso_v<StackMemory> = true;
inline const int kTpStackMemoryIndex = 27;
} // namespace pkpy

View File

@ -1,9 +1,7 @@
#pragma once
#include "common.h"
#include "memory.h"
#include "str.h"
#include "vector.h"
#include "pocketpy/common/vector.hpp"
#include "pocketpy/objects/base.hpp"
namespace pkpy {

View File

@ -1,18 +0,0 @@
#pragma once
#include "compiler.h"
#include "obj.h"
#include "repl.h"
#include "iter.h"
#include "base64.h"
#include "cffi.h"
#include "linalg.h"
#include "easing.h"
#include "io.h"
#include "vm.h"
#include "random.h"
#include "bindings.h"
#include "csv.h"
#include "dataclasses.h"
#include "array2d.h"
#include "modules.h"

View File

@ -0,0 +1,8 @@
#pragma once
#include "pocketpy/objects/builtins.hpp"
#include "pocketpy/interpreter/vm.hpp"
#include "pocketpy/interpreter/iter.hpp"
#include "pocketpy/interpreter/bindings.hpp"
#include "pocketpy/compiler/compiler.hpp"
#include "pocketpy/tools/repl.hpp"

View File

@ -1,6 +1,6 @@
#pragma once
#include "vm.h"
#include "pocketpy/interpreter/vm.hpp"
namespace pkpy{

View File

@ -23,7 +23,7 @@ def get_sources():
sources = get_sources()
# use LF line endings instead of CRLF
with open("include/pocketpy/_generated.h", "wt", encoding='utf-8', newline='\n') as f:
with open("include/pocketpy/common/_generated.hpp", "wt", encoding='utf-8', newline='\n') as f:
data = '''#pragma once
// generated by prebuild.py
@ -35,9 +35,9 @@ namespace pkpy{
data += '} // namespace pkpy\n'
f.write(data)
with open("src/_generated.cpp", "wt", encoding='utf-8', newline='\n') as f:
with open("src/common/_generated.cpp", "wt", encoding='utf-8', newline='\n') as f:
data = '''// generated by prebuild.py
#include "pocketpy/_generated.h"
#include "pocketpy/common/_generated.hpp"
namespace pkpy{
'''

View File

@ -1,5 +1,5 @@
// generated by prebuild.py
#include "pocketpy/_generated.h"
#include "pocketpy/common/_generated.hpp"
namespace pkpy{
const char kPythonLibs__enum[] = "class Enum:\n def __init__(self, name, value):\n self.name = name\n self.value = value\n\n def __str__(self):\n return f'{type(self).__name__}.{self.name}'\n \n def __repr__(self):\n return f'<{str(self)}: {self.value!r}>'\n \n";

View File

@ -1,10 +1,14 @@
#include "pocketpy/any.h"
#include "pocketpy/common/any.hpp"
#include <stdexcept>
#include <cstdio>
namespace pkpy{
void any::__bad_any_cast(const std::type_index expected, const std::type_index actual){
Str error = _S("bad_any_cast: expected ", expected.name(), ", got ", actual.name());
throw std::runtime_error(error.c_str());
char error[256];
snprintf(error, sizeof(error), "bad_any_cast: expected %s, got %s", expected.name(), actual.name());
throw std::runtime_error(error);
}
any::any(any&& other) noexcept: data(other.data), _vt(other._vt){

View File

@ -1,4 +1,8 @@
#include "pocketpy/memory.h"
#include "pocketpy/common/memorypool.hpp"
#include "pocketpy/common/gil.hpp"
#include "pocketpy/config.h"
#include <cstring>
namespace pkpy{
@ -84,18 +88,6 @@ struct DoubleLinkedList{
_size--;
}
// void move_all_back(DoubleLinkedList<T>& other){
// if(other.empty()) return;
// other.tail.prev->next = &tail;
// tail.prev->next = other.head.next;
// other.head.next->prev = tail.prev;
// tail.prev = other.tail.prev;
// _size += other._size;
// other.head.next = &other.tail;
// other.tail.prev = &other.head;
// other._size = 0;
// }
bool empty() const {
#if PK_DEBUG_MEMORY_POOL
if(size() == 0){
@ -269,7 +261,6 @@ struct MemoryPool{
static MemoryPool<128> pool128;
void* pool128_alloc(size_t size) noexcept { return pool128.alloc(size); }
void pool128_dealloc(void* p) noexcept { pool128.dealloc(p); }

View File

@ -1,4 +1,10 @@
#include "pocketpy/str.h"
#include "pocketpy/common/str.hpp"
#include <stdexcept>
#include <cassert>
#include <ostream>
#include <algorithm>
#include <cmath>
namespace pkpy {
@ -60,7 +66,7 @@ int utf8len(unsigned char c, bool suppress){
for(int i=0; i<size; i++){
if(!isascii(data[i])){ is_ascii = false; break; }
}
PK_ASSERT(data[size] == '\0');
assert(data[size] == '\0');
}
Str::Str(const Str& other): size(other.size), is_ascii(other.is_ascii) {
@ -396,7 +402,7 @@ int utf8len(unsigned char c, bool suppress){
uint16_t index = ((_pesudo_random_index*5) + 1) & 65535;
if(index == 0) throw std::runtime_error("StrName index overflow");
auto res = _r_interned().emplace(index, s);
PK_ASSERT(res.second);
assert(res.second);
s = std::string_view(res.first->second);
_interned()[s] = index;
_pesudo_random_index = index;

View File

@ -1,4 +1,6 @@
#include "pocketpy/compiler.h"
#include "pocketpy/compiler/compiler.hpp"
#include "pocketpy/common/version.hpp"
#include "pocketpy/interpreter/vm.hpp"
namespace pkpy{
PrattRule Compiler::rules[kTokenCount];
@ -92,7 +94,7 @@ namespace pkpy{
else func->type = FuncType::NORMAL;
}
PK_ASSERT(func->type != FuncType::UNSET);
assert(func->type != FuncType::UNSET);
}
contexts.pop();
}
@ -322,7 +324,7 @@ namespace pkpy{
case TK("**"):
ctx()->s_expr.push(make_expr<StarredExpr>(2, ctx()->s_expr.popx()));
break;
default: PK_FATAL_ERROR();
default: assert(false);
}
}
@ -640,7 +642,7 @@ __EAT_DOTS_END:
TokenIndex op = curr().type;
advance();
PrattCallback infix = rules[op].infix;
PK_ASSERT(infix != nullptr);
assert(infix != nullptr);
(this->*infix)();
}
}
@ -1015,7 +1017,7 @@ __EAT_DOTS_END:
ctx()->emit_(OP_POP_TOP, BC_NOARG, BC_KEEPLINE);
}
}else{
PK_ASSERT(ctx()->s_expr.size() == 1)
assert(ctx()->s_expr.size() == 1);
ctx()->s_expr.pop();
}
}
@ -1185,7 +1187,7 @@ __EAT_DOTS_END:
if(std::holds_alternative<Str>(value)){
obj = VAR(std::get<Str>(value));
}
PK_ASSERT(obj != nullptr)
assert(obj != nullptr);
return obj;
}
@ -1239,7 +1241,7 @@ __EAT_DOTS_END:
if(it == token_indices.end()){
token_indices[token.sv()] = 0;
// assert no '\n' in token.sv()
for(char c: token.sv()) if(c=='\n') PK_FATAL_ERROR();
for(char c: token.sv()) assert(c!='\n');
}
}
}
@ -1336,7 +1338,7 @@ __EAT_DOTS_END:
}
CodeObject_ Compiler::compile(){
PK_ASSERT(i == 0) // make sure it is the first time to compile
assert(i == 0); // make sure it is the first time to compile
if(lexer.src->is_precompiled){
from_precompiled(lexer.src->source.c_str());
@ -1397,11 +1399,11 @@ __EAT_DOTS_END:
char c = 0;
if(s[i]>='0' && s[i]<='9') c += s[i]-'0';
else if(s[i]>='a' && s[i]<='f') c += s[i]-'a'+10;
else PK_FATAL_ERROR();
else assert(false);
c <<= 4;
if(s[i+1]>='0' && s[i+1]<='9') c += s[i+1]-'0';
else if(s[i+1]>='a' && s[i+1]<='f') c += s[i+1]-'a'+10;
else PK_FATAL_ERROR();
else assert(false);
buffer[i/2] = c;
}
buffer[s.size()/2] = 0;
@ -1409,7 +1411,7 @@ __EAT_DOTS_END:
}
int TokenDeserializer::read_count(){
PK_ASSERT(*curr == '=')
assert(*curr == '=');
curr++;
return read_uint('\n');
}

View File

@ -1,4 +1,5 @@
#include "pocketpy/expr.h"
#include "pocketpy/compiler/expr.hpp"
#include "pocketpy/interpreter/vm.hpp"
namespace pkpy{
@ -33,8 +34,7 @@ namespace pkpy{
auto curr_type = co->blocks[curr_iblock].type;
co->blocks[curr_iblock].end = co->codes.size();
curr_iblock = co->blocks[curr_iblock].parent;
if(curr_iblock < 0) PK_FATAL_ERROR();
assert(curr_iblock >= 0);
if(curr_type == CodeBlockType::FOR_LOOP){
// add a no op here to make block check work
emit_(OP_NO_OP, BC_NOARG, BC_KEEPLINE, true);
@ -127,7 +127,7 @@ namespace pkpy{
}
int CodeEmitContext::add_const(PyVar v){
PK_ASSERT(!is_type(v, VM::tp_str))
assert(!is_type(v, VM::tp_str));
// non-string deduplication
auto it = _co_consts_nonstring_dedup_map.find(v);
if(it != _co_consts_nonstring_dedup_map.end()){
@ -156,7 +156,7 @@ namespace pkpy{
case NAME_GLOBAL_UNKNOWN:
emit_(OP_STORE_NAME, StrName(name).index, line);
break;
default: PK_FATAL_ERROR(); break;
default: assert(false); break;
}
}
@ -191,7 +191,7 @@ namespace pkpy{
case NAME_GLOBAL_UNKNOWN:
ctx->emit_(OP_DELETE_NAME, StrName(name).index, line);
break;
default: PK_FATAL_ERROR(); break;
default: assert(false); break;
}
return true;
}
@ -246,7 +246,7 @@ namespace pkpy{
case TK("True"): ctx->emit_(OP_LOAD_TRUE, BC_NOARG, line); break;
case TK("False"): ctx->emit_(OP_LOAD_FALSE, BC_NOARG, line); break;
case TK("..."): ctx->emit_(OP_LOAD_ELLIPSIS, BC_NOARG, line); break;
default: PK_FATAL_ERROR();
default: assert(false);
}
}
@ -330,7 +330,7 @@ namespace pkpy{
void DictItemExpr::emit_(CodeEmitContext* ctx) {
if(is_starred()){
PK_ASSERT(key == nullptr);
assert(key == nullptr);
value->emit_(ctx);
}else{
value->emit_(ctx);
@ -647,7 +647,7 @@ namespace pkpy{
if(!kwargs.empty()){
for(auto& item: kwargs){
if(item.second->is_starred()){
PK_ASSERT(item.second->star_level() == 2)
assert(item.second->star_level() == 2);
item.second->emit_(ctx);
}else{
// k=v
@ -752,7 +752,7 @@ namespace pkpy{
case TK("^"): ctx->emit_(OP_BITWISE_XOR, BC_NOARG, line); break;
case TK("@"): ctx->emit_(OP_BINARY_MATMUL, BC_NOARG, line); break;
default: PK_FATAL_ERROR();
default: assert(false);
}
for(int i: jmps) ctx->patch_jump(i);

View File

@ -1,8 +1,7 @@
#include "pocketpy/lexer.h"
#include "pocketpy/compiler/lexer.hpp"
namespace pkpy{
static const uint32_t kLoRangeA[] = {170,186,443,448,660,1488,1519,1568,1601,1646,1649,1749,1774,1786,1791,1808,1810,1869,1969,1994,2048,2112,2144,2208,2230,2308,2365,2384,2392,2418,2437,2447,2451,2474,2482,2486,2493,2510,2524,2527,2544,2556,2565,2575,2579,2602,2610,2613,2616,2649,2654,2674,2693,2703,2707,2730,2738,2741,2749,2768,2784,2809,2821,2831,2835,2858,2866,2869,2877,2908,2911,2929,2947,2949,2958,2962,2969,2972,2974,2979,2984,2990,3024,3077,3086,3090,3114,3133,3160,3168,3200,3205,3214,3218,3242,3253,3261,3294,3296,3313,3333,3342,3346,3389,3406,3412,3423,3450,3461,3482,3507,3517,3520,3585,3634,3648,3713,3716,3718,3724,3749,3751,3762,3773,3776,3804,3840,3904,3913,3976,4096,4159,4176,4186,4193,4197,4206,4213,4238,4352,4682,4688,4696,4698,4704,4746,4752,4786,4792,4800,4802,4808,4824,4882,4888,4992,5121,5743,5761,5792,5873,5888,5902,5920,5952,5984,5998,6016,6108,6176,6212,6272,6279,6314,6320,6400,6480,6512,6528,6576,6656,6688,6917,6981,7043,7086,7098,7168,7245,7258,7401,7406,7413,7418,8501,11568,11648,11680,11688,11696,11704,11712,11720,11728,11736,12294,12348,12353,12447,12449,12543,12549,12593,12704,12784,13312,19968,40960,40982,42192,42240,42512,42538,42606,42656,42895,42999,43003,43011,43015,43020,43072,43138,43250,43259,43261,43274,43312,43360,43396,43488,43495,43514,43520,43584,43588,43616,43633,43642,43646,43697,43701,43705,43712,43714,43739,43744,43762,43777,43785,43793,43808,43816,43968,44032,55216,55243,63744,64112,64285,64287,64298,64312,64318,64320,64323,64326,64467,64848,64914,65008,65136,65142,65382,65393,65440,65474,65482,65490,65498,65536,65549,65576,65596,65599,65616,65664,66176,66208,66304,66349,66370,66384,66432,66464,66504,66640,66816,66864,67072,67392,67424,67584,67592,67594,67639,67644,67647,67680,67712,67808,67828,67840,67872,67968,68030,68096,68112,68117,68121,68192,68224,68288,68297,68352,68416,68448,68480,68608,68864,69376,69415,69424,69600,69635,69763,69840,69891,69956,69968,70006,70019,70081,70106,70108,70144,70163,70272,70280,70282,70287,70303,70320,70405,70415,70419,70442,70450,70453,70461,70480,70493,70656,70727,70751,70784,70852,70855,71040,71128,71168,71236,71296,71352,71424,71680,71935,72096,72106,72161,72163,72192,72203,72250,72272,72284,72349,72384,72704,72714,72768,72818,72960,72968,72971,73030,73056,73063,73066,73112,73440,73728,74880,77824,82944,92160,92736,92880,92928,93027,93053,93952,94032,94208,100352,110592,110928,110948,110960,113664,113776,113792,113808,123136,123214,123584,124928,126464,126469,126497,126500,126503,126505,126516,126521,126523,126530,126535,126537,126539,126541,126545,126548,126551,126553,126555,126557,126559,126561,126564,126567,126572,126580,126585,126590,126592,126603,126625,126629,126635,131072,173824,177984,178208,183984,194560};
static const uint32_t kLoRangeB[] = {170,186,443,451,660,1514,1522,1599,1610,1647,1747,1749,1775,1788,1791,1808,1839,1957,1969,2026,2069,2136,2154,2228,2237,2361,2365,2384,2401,2432,2444,2448,2472,2480,2482,2489,2493,2510,2525,2529,2545,2556,2570,2576,2600,2608,2611,2614,2617,2652,2654,2676,2701,2705,2728,2736,2739,2745,2749,2768,2785,2809,2828,2832,2856,2864,2867,2873,2877,2909,2913,2929,2947,2954,2960,2965,2970,2972,2975,2980,2986,3001,3024,3084,3088,3112,3129,3133,3162,3169,3200,3212,3216,3240,3251,3257,3261,3294,3297,3314,3340,3344,3386,3389,3406,3414,3425,3455,3478,3505,3515,3517,3526,3632,3635,3653,3714,3716,3722,3747,3749,3760,3763,3773,3780,3807,3840,3911,3948,3980,4138,4159,4181,4189,4193,4198,4208,4225,4238,4680,4685,4694,4696,4701,4744,4749,4784,4789,4798,4800,4805,4822,4880,4885,4954,5007,5740,5759,5786,5866,5880,5900,5905,5937,5969,5996,6000,6067,6108,6210,6264,6276,6312,6314,6389,6430,6509,6516,6571,6601,6678,6740,6963,6987,7072,7087,7141,7203,7247,7287,7404,7411,7414,7418,8504,11623,11670,11686,11694,11702,11710,11718,11726,11734,11742,12294,12348,12438,12447,12538,12543,12591,12686,12730,12799,19893,40943,40980,42124,42231,42507,42527,42539,42606,42725,42895,42999,43009,43013,43018,43042,43123,43187,43255,43259,43262,43301,43334,43388,43442,43492,43503,43518,43560,43586,43595,43631,43638,43642,43695,43697,43702,43709,43712,43714,43740,43754,43762,43782,43790,43798,43814,43822,44002,55203,55238,55291,64109,64217,64285,64296,64310,64316,64318,64321,64324,64433,64829,64911,64967,65019,65140,65276,65391,65437,65470,65479,65487,65495,65500,65547,65574,65594,65597,65613,65629,65786,66204,66256,66335,66368,66377,66421,66461,66499,66511,66717,66855,66915,67382,67413,67431,67589,67592,67637,67640,67644,67669,67702,67742,67826,67829,67861,67897,68023,68031,68096,68115,68119,68149,68220,68252,68295,68324,68405,68437,68466,68497,68680,68899,69404,69415,69445,69622,69687,69807,69864,69926,69956,70002,70006,70066,70084,70106,70108,70161,70187,70278,70280,70285,70301,70312,70366,70412,70416,70440,70448,70451,70457,70461,70480,70497,70708,70730,70751,70831,70853,70855,71086,71131,71215,71236,71338,71352,71450,71723,71935,72103,72144,72161,72163,72192,72242,72250,72272,72329,72349,72440,72712,72750,72768,72847,72966,72969,73008,73030,73061,73064,73097,73112,73458,74649,75075,78894,83526,92728,92766,92909,92975,93047,93071,94026,94032,100343,101106,110878,110930,110951,111355,113770,113788,113800,113817,123180,123214,123627,125124,126467,126495,126498,126500,126503,126514,126519,126521,126523,126530,126535,126537,126539,126543,126546,126548,126551,126553,126555,126557,126559,126562,126564,126570,126578,126583,126588,126590,126601,126619,126627,126633,126651,173782,177972,178205,183969,191456,195101};
@ -452,7 +451,7 @@ static bool is_unicode_Lo_char(uint32_t c) {
case 2: SyntaxError("invalid utf8 sequence: " + std::string(1, c)); break;
case 3: SyntaxError("@id contains invalid char"); break;
case 4: SyntaxError("invalid JSON token"); break;
default: PK_FATAL_ERROR();
default: assert(false);
}
return true;
}
@ -487,7 +486,7 @@ static bool is_unicode_Lo_char(uint32_t c) {
}
vector<Token> Lexer::run() {
PK_ASSERT(curr_char == src->source.c_str());
assert(curr_char == src->source.c_str());
while (lex_one_token());
return std::move(nexts);
}

View File

@ -1,4 +1,4 @@
#include "pocketpy/ceval.h"
#include "pocketpy/interpreter/ceval.hpp"
namespace pkpy{
@ -224,7 +224,7 @@ __NEXT_STEP:
TOP() = getattr(TOP(), StrName(byte.arg));
} DISPATCH()
case OP_LOAD_CLASS_GLOBAL:{
PK_ASSERT(__curr_class != nullptr);
assert(__curr_class != nullptr);
StrName _name(byte.arg);
PyVar _0 = getattr(__curr_class, _name, false);
if(_0 != nullptr) { PUSH(_0); DISPATCH() }
@ -284,7 +284,7 @@ __NEXT_STEP:
}else{
Function& func = frame->_callable->as<Function>();
if(func.decl == __dynamic_func_decl){
PK_DEBUG_ASSERT(func._closure != nullptr);
assert(func._closure != nullptr);
func._closure->set(_name, _0);
}else{
vm->NameError(_name);
@ -340,7 +340,7 @@ __NEXT_STEP:
}else{
Function& func = frame->_callable->as<Function>();
if(func.decl == __dynamic_func_decl){
PK_DEBUG_ASSERT(func._closure != nullptr);
assert(func._closure != nullptr);
bool ok = func._closure->del(_name);
if(!ok) vm->NameError(_name);
}else{
@ -941,7 +941,7 @@ __NEXT_STEP:
__curr_class = new_type_object(frame->_module, _name, PK_OBJ_GET(Type, _0), true);
} DISPATCH()
case OP_END_CLASS: {
PK_ASSERT(__curr_class != nullptr);
assert(__curr_class != nullptr);
StrName _name(byte.arg);
frame->_module->attr().set(_name, __curr_class);
// call on_end_subclass
@ -953,7 +953,7 @@ __NEXT_STEP:
__curr_class = nullptr;
} DISPATCH()
case OP_STORE_CLASS_ATTR:{
PK_ASSERT(__curr_class != nullptr);
assert(__curr_class != nullptr);
StrName _name(byte.arg);
PyVar _0 = POPX();
if(is_type(_0, tp_function)){
@ -968,7 +968,7 @@ __NEXT_STEP:
__curr_class = POPX().get();
} DISPATCH()
case OP_ADD_CLASS_ANNOTATION: {
PK_ASSERT(__curr_class != nullptr);
assert(__curr_class != nullptr);
StrName _name(byte.arg);
Type type = __curr_class->as<Type>();
_all_types[type].annotated_fields.push_back(_name);

View File

@ -1,4 +1,4 @@
#include "pocketpy/cffi.h"
#include "pocketpy/interpreter/cffi.hpp"
namespace pkpy{

View File

@ -1,4 +1,5 @@
#include "pocketpy/frame.h"
#include "pocketpy/objects/stackmemory.hpp"
#include "pocketpy/interpreter/frame.hpp"
namespace pkpy{
PyVar* FastLocals::try_get_name(StrName name){
@ -11,7 +12,7 @@ namespace pkpy{
NameDict_ dict = std::make_shared<NameDict>();
co->varnames_inv.apply([&](StrName name, int index){
PyVar value = a[index];
if(value != PY_NULL) dict->set(name, value);
if(value) dict->set(name, value);
});
return dict;
}
@ -45,7 +46,7 @@ namespace pkpy{
// pop possible stack memory slots
if(_s->top().type == kTpStackMemoryIndex){
int count = _s->top().as<StackMemory>().count;
PK_DEBUG_ASSERT(count < 0);
assert(count < 0);
_s->_sp += count;
_s->_sp -= 2; // pop header and tail
}
@ -99,4 +100,27 @@ namespace pkpy{
}
}
void CallStack::pop(){
assert(!empty());
LinkedFrame* p = _tail;
_tail = p->f_back;
p->~LinkedFrame();
pool128_dealloc(p);
--_size;
}
LinkedFrame* CallStack::popx(){
assert(!empty());
LinkedFrame* p = _tail;
_tail = p->f_back;
--_size;
p->f_back = nullptr; // unlink
return p;
}
void CallStack::pushx(LinkedFrame* p){
p->f_back = _tail;
_tail = p;
++_size;
}
} // namespace pkpy

View File

@ -1,4 +1,4 @@
#include "pocketpy/gc.h"
#include "pocketpy/interpreter/gc.hpp"
namespace pkpy{
@ -48,7 +48,7 @@ namespace pkpy{
}
int ManagedHeap::collect(){
PK_ASSERT(_gc_lock_counter == 0)
assert(_gc_lock_counter == 0);
mark();
int freed = sweep();
return freed;

View File

@ -1,4 +1,4 @@
#include "pocketpy/iter.h"
#include "pocketpy/interpreter/iter.hpp"
namespace pkpy{

View File

@ -1,4 +1,4 @@
#include "pocketpy/profiler.h"
#include "pocketpy/interpreter/profiler.hpp"
namespace pkpy{
@ -49,7 +49,7 @@ void LineProfiler::_step_end(int callstack_size, Frame* frame, int line){
_LineRecord* prev_record = top_frame_record.prev_record;
int id_delta = callstack_size - top_frame_record.callstack_size;
PK_ASSERT(abs(id_delta) <= 1)
assert(abs(id_delta) <= 1);
// current line is about to change
if(prev_record->line != line){
@ -77,7 +77,7 @@ void LineProfiler::end(){
prev_record->time += delta;
frames.pop();
PK_ASSERT(frames.empty());
assert(frames.empty());
}
Str LineProfiler::stats(){

View File

@ -1,4 +1,7 @@
#include "pocketpy/vm.h"
#include "pocketpy/interpreter/vm.hpp"
#include <iostream>
#include <cmath>
static const char* OP_NAMES[] = {
#define OPCODE(name) #name,
@ -358,7 +361,7 @@ namespace pkpy{
path = f_join(cpnts);
}
PK_ASSERT(path.begin()[0] != '.' && path.end()[-1] != '.');
assert(path.begin()[0] != '.' && path.end()[-1] != '.');
// check existing module
StrName name(path);
@ -388,7 +391,7 @@ namespace pkpy{
if(throw_err) ImportError(_S("module ", path.escape(), " not found"));
else return nullptr;
}
PK_ASSERT(out_size >= 0)
assert(out_size >= 0);
source = Str(std::string_view((char*)out, out_size));
free(out);
}else{
@ -787,7 +790,7 @@ Str VM::disassemble(CodeObject_ co){
}
std::string pointer;
if(std::find(jumpTargets.begin(), jumpTargets.end(), i) != jumpTargets.end()){
if(jumpTargets.contains(i)){
pointer = "-> ";
}else{
pointer = " ";
@ -817,7 +820,7 @@ void VM::__log_s_data(const char* title) {
if(title) ss << title << " | ";
std::map<PyVar*, int> sp_bases;
callstack.apply([&](Frame& f){
if(f._sp_base == nullptr) PK_FATAL_ERROR();
assert(f._sp_base != nullptr);
sp_bases[f._sp_base] += 1;
});
Frame* frame = &callstack.top();
@ -1046,7 +1049,7 @@ PyVar VM::vectorcall(int ARGC, int KWARGC, bool op_call){
// handle boundmethod, do a patch
if(callable_t == tp_bound_method){
PK_DEBUG_ASSERT(p0[1] == PY_NULL)
assert(p0[1] == PY_NULL);
BoundMethod& bm = PK_OBJ_GET(BoundMethod, callable);
callable = bm.func; // get unbound method
callable_t = _tp(callable);
@ -1097,11 +1100,7 @@ PyVar VM::vectorcall(int ARGC, int KWARGC, bool op_call){
callstack.popx(),
ArgsView(__vectorcall_buffer, __vectorcall_buffer + co->nlocals)
);
#if PK_DEBUG_EXTRA_CHECK
default: PK_FATAL_ERROR(); break;
#else
default: PK_UNREACHABLE()
#endif
default: PK_UNREACHABLE();
};
// simple or normal
@ -1138,7 +1137,7 @@ PyVar VM::vectorcall(int ARGC, int KWARGC, bool op_call){
// [type, NULL, args..., kwargs...]
PyVar new_f = *find_name_in_mro(PK_OBJ_GET(Type, callable), __new__);
PyVar obj;
PK_DEBUG_ASSERT(new_f != nullptr && p0[1]==PY_NULL);
assert(new_f != nullptr && p0[1]==PY_NULL);
if(new_f == __cached_object_new) {
// fast path for object.__new__
obj = vm->new_object<DummyInstance>(PK_OBJ_GET(Type, callable));
@ -1407,7 +1406,7 @@ PyObject* VM::bind(PyObject* obj, const char* sig, const char* docstring, Native
}
PyObject* VM::bind_property(PyObject* obj, const char* name, NativeFuncC fget, NativeFuncC fset){
PK_ASSERT(is_type(obj, tp_type));
assert(is_type(obj, tp_type));
std::string_view name_sv(name); int pos = name_sv.find(':');
if(pos > 0) name_sv = name_sv.substr(0, pos);
PyVar _0 = new_object<NativeFunc>(tp_native_func, fget, 1);
@ -1437,7 +1436,7 @@ void VM::AttributeError(PyVar obj, StrName name){
}
void VM::_error(PyVar e_obj){
PK_ASSERT(isinstance(e_obj, tp_exception))
assert(isinstance(e_obj, tp_exception));
Exception& e = PK_OBJ_GET(Exception, e_obj);
if(callstack.empty()){
e.is_re = false;
@ -1752,8 +1751,8 @@ void VM::__breakpoint(){
if(is_list){
int max_line = frame_0->co->src->line_starts.size() + 1;
start = std::max(1, lineno-5);
end = std::min(max_line, lineno+5);
start = (std::max)(1, lineno-5);
end = (std::min)(max_line, lineno+5);
}else{
start = frame_0->co->start_line;
end = frame_0->co->end_line;

View File

@ -1,4 +1,5 @@
#include "pocketpy/array2d.h"
#include "pocketpy/modules/array2d.hpp"
#include "pocketpy/interpreter/bindings.hpp"
namespace pkpy{
@ -340,10 +341,10 @@ struct Array2d{
for(int j = 0; j < self.n_rows; j++){
for(int i = 0; i < self.n_cols; i++){
if(vm->py_eq(self._get(i, j), value)){
left = std::min(left, i);
top = std::min(top, j);
right = std::max(right, i);
bottom = std::max(bottom, j);
left = (std::min)(left, i);
top = (std::min)(top, j);
right = (std::max)(right, i);
bottom = (std::max)(bottom, j);
}
}
}

View File

@ -1,4 +1,5 @@
#include "pocketpy/base64.h"
#include "pocketpy/modules/base64.hpp"
#include "pocketpy/interpreter/bindings.hpp"
namespace pkpy{

View File

@ -1,4 +1,5 @@
#include "pocketpy/csv.h"
#include "pocketpy/modules/csv.hpp"
#include "pocketpy/interpreter/bindings.hpp"
namespace pkpy{

View File

@ -1,4 +1,5 @@
#include "pocketpy/dataclasses.h"
#include "pocketpy/modules/dataclasses.hpp"
#include "pocketpy/interpreter/bindings.hpp"
namespace pkpy{

View File

@ -1,4 +1,7 @@
#include "pocketpy/easing.h"
#include "pocketpy/modules/easing.hpp"
#include "pocketpy/interpreter/bindings.hpp"
#include <cmath>
namespace pkpy{
// https://easings.net/

View File

@ -1,4 +1,5 @@
#include "pocketpy/io.h"
#include "pocketpy/modules/io.hpp"
#include "pocketpy/interpreter/bindings.hpp"
#if PK_ENABLE_OS
#include <filesystem>
@ -75,7 +76,7 @@ void FileIO::_register(VM* vm, PyObject* mod, PyObject* type){
}
unsigned char* buffer = (unsigned char*)malloc(buffer_size);
i64 actual_size = io_fread(buffer, 1, buffer_size, io.fp);
PK_ASSERT(actual_size <= buffer_size);
assert(actual_size <= buffer_size);
// in text mode, CR may be dropped, which may cause `actual_size < buffer_size`
Bytes b(buffer, actual_size);
if(io.is_text){

View File

@ -1,4 +1,5 @@
#include "pocketpy/linalg.h"
#include "pocketpy/modules/linalg.hpp"
#include "pocketpy/interpreter/bindings.hpp"
namespace pkpy{
@ -76,7 +77,7 @@ namespace pkpy{
static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float smoothTime, float maxSpeed, float deltaTime)
{
// Based on Game Programming Gems 4 Chapter 1.10
smoothTime = std::max(0.0001F, smoothTime);
smoothTime = (std::max)(0.0001F, smoothTime);
float omega = 2.0F / smoothTime;
float x = omega * deltaTime;

View File

@ -1,4 +1,12 @@
#include "pocketpy/modules.h"
#include "pocketpy/modules/modules.hpp"
#include "pocketpy/interpreter/bindings.hpp"
#include "pocketpy/common/version.hpp"
#include "pocketpy/export.h"
#include "pocketpy/common/_generated.hpp"
#include <chrono>
#include <cmath>
namespace pkpy{

View File

@ -1,4 +1,7 @@
#include "pocketpy/random.h"
#include "pocketpy/modules/random.hpp"
#include "pocketpy/interpreter/bindings.hpp"
#include <chrono>
/* https://github.com/clibs/mt19937ar

View File

@ -1,4 +0,0 @@
#include "pocketpy/namedict.h"
namespace pkpy{
} // namespace pkpy

6
src/objects/builtins.cpp Normal file
View File

@ -0,0 +1,6 @@
#include "pocketpy/objects/builtins.hpp"
namespace pkpy{
PyVar const PY_OP_CALL(Type(), new PyObject(Type()));
PyVar const PY_OP_YIELD(Type(), new PyObject(Type()));
} // namespace pkpy

View File

@ -1,4 +1,4 @@
#include "pocketpy/codeobject.h"
#include "pocketpy/objects/codeobject.hpp"
namespace pkpy{
@ -6,7 +6,4 @@ namespace pkpy{
src(src), name(name), nlocals(0), start_line(-1), end_line(-1) {
blocks.push_back(CodeBlock(CodeBlockType::NO_BLOCK, -1, 0));
}
PyVar const PY_OP_CALL(Type(), new PyObject(Type()));
PyVar const PY_OP_YIELD(Type(), new PyObject(Type()));
} // namespace pkpy

View File

@ -1,4 +1,4 @@
#include "pocketpy/dict.h"
#include "pocketpy/objects/dict.hpp"
namespace pkpy{
@ -140,7 +140,7 @@ namespace pkpy{
t[j++] = _items[i].first;
i = _items[i].next;
}
PK_ASSERT(j == _size);
assert(j == _size);
return t;
}
@ -152,7 +152,7 @@ namespace pkpy{
t[j++] = _items[i].second;
i = _items[i].next;
}
PK_ASSERT(j == _size);
assert(j == _size);
return t;
}

20
src/objects/error.cpp Normal file
View File

@ -0,0 +1,20 @@
#include "pocketpy/objects/error.hpp"
namespace pkpy{
Str Exception::summary() const {
SStream ss;
if(is_re) ss << "Traceback (most recent call last):\n";
// while(!st.empty()) {
// ss << st.top().snapshot() << '\n';
// st.pop();
// }
const auto& container = stacktrace.container();
for(int i=container.size()-1; i>=0; i--){
ss << container[i].snapshot() << '\n';
}
if (!msg.empty()) ss << type.sv() << ": " << msg;
else ss << type.sv();
return ss.str();
}
} // namespace pkpy

View File

@ -1,4 +1,4 @@
#include "pocketpy/obj.h"
#include "pocketpy/objects/object.hpp"
namespace pkpy{
PyVar::PyVar(PyObject* p): PyVar(p->type, p) {}

View File

@ -1,7 +1,6 @@
#include "pocketpy/error.h"
#include "pocketpy/objects/sourcedata.hpp"
namespace pkpy{
SourceData::SourceData(std::string_view source, const Str& filename, CompileMode mode): filename(filename), mode(mode) {
int index = 0;
// Skip utf8 BOM if there is any.
@ -64,21 +63,4 @@ namespace pkpy{
}
return ss.str();
}
Str Exception::summary() const {
SStream ss;
if(is_re) ss << "Traceback (most recent call last):\n";
// while(!st.empty()) {
// ss << st.top().snapshot() << '\n';
// st.pop();
// }
const auto& container = stacktrace.container();
for(int i=container.size()-1; i>=0; i--){
ss << container[i].snapshot() << '\n';
}
if (!msg.empty()) ss << type.sv() << ": " << msg;
else ss << type.sv();
return ss.str();
}
} // namespace pkpy

View File

@ -1,4 +1,4 @@
#include "pocketpy/tuplelist.h"
#include "pocketpy/objects/tuplelist.hpp"
namespace pkpy {

View File

@ -1,4 +1,19 @@
#include "pocketpy/pocketpy.h"
#include "pocketpy/pocketpy.hpp"
#include "pocketpy/common/_generated.hpp"
#include "pocketpy/modules/array2d.hpp"
#include "pocketpy/modules/base64.hpp"
#include "pocketpy/modules/csv.hpp"
#include "pocketpy/modules/dataclasses.hpp"
#include "pocketpy/modules/easing.hpp"
#include "pocketpy/modules/io.hpp"
#include "pocketpy/modules/linalg.hpp"
#include "pocketpy/modules/random.hpp"
#include "pocketpy/modules/modules.hpp"
#include <iostream>
#include <algorithm>
namespace pkpy{
@ -332,7 +347,7 @@ void __init_builtins(VM* _vm) {
// tp_object
_vm->bind__repr__(VM::tp_object, [](VM* vm, PyVar obj) -> Str{
if(is_tagged(obj)) PK_FATAL_ERROR();
assert(!is_tagged(obj));
SStream ss;
ss << "<" << _type_name(vm, vm->_tp(obj)) << " object at ";
ss.write_hex(obj.get());

View File

@ -3,6 +3,8 @@
#include "pocketpy.h"
#include "pocketpy_c.h"
#include <iostream>
using namespace pkpy;
#define PK_ASSERT_N_EXTRA_ELEMENTS(n) \
@ -21,7 +23,7 @@ static int count_extra_elements(VM* vm, int n){
if(vm->callstack.empty()){
return vm->s_data.size();
}
PK_ASSERT(!vm->__c.s_view.empty());
assert(!vm->__c.s_view.empty());
return vm->s_data._sp - vm->__c.s_view.top().end();
}
@ -31,7 +33,7 @@ static PyVar stack_item(VM* vm, int index){
if(vm->callstack.empty()){
begin = vm->s_data.begin();
}else{
PK_ASSERT(!vm->__c.s_view.empty());
assert(!vm->__c.s_view.empty());
begin = vm->__c.s_view.top().begin();
}
int size = end - begin;
@ -347,7 +349,7 @@ static PyVar c_function_wrapper(VM* vm, ArgsView args) {
vm->_error(e_obj);
return nullptr;
}
PK_ASSERT(retc == vm->s_data._sp-curr_sp);
assert(retc == vm->s_data._sp-curr_sp);
if(retc == 0) return vm->None;
if (retc == 1) return vm->s_data.popx();
ArgsView ret_view(curr_sp, vm->s_data._sp);

View File

@ -1,4 +1,7 @@
#include "pocketpy/repl.h"
#include "pocketpy/tools/repl.hpp"
#include "pocketpy/common/version.hpp"
#include "pocketpy/export.h"
namespace pkpy {
REPL::REPL(VM* vm) : vm(vm){