mirror of
https://github.com/pocketpy/pocketpy
synced 2025-12-10 12:10:16 +00:00
Compare commits
8 Commits
3d5a59bd15
...
1d319c4ab6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1d319c4ab6 | ||
|
|
2f14689e2f | ||
|
|
3e7af41e1f | ||
|
|
92090aeaa1 | ||
|
|
976f809f80 | ||
|
|
1fb4ebdf5b | ||
|
|
1f9187ccae | ||
|
|
74df367f3c |
@ -8,6 +8,7 @@ set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
if(MSVC)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /utf-8 /jumptablerdata /GS-")
|
||||
add_compile_options(/wd4267 /wd4244)
|
||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Ox")
|
||||
@ -44,23 +45,6 @@ if ("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
set(PK_IS_MAIN TRUE)
|
||||
option(PK_BUILD_SHARED_LIB "Build shared library" OFF)
|
||||
option(PK_BUILD_STATIC_LIB "Build static library" OFF)
|
||||
|
||||
# @szdytom favored testing
|
||||
# disabled by default because @blueloveTH doesn't like it :C
|
||||
option(BUILD_TESTING "Build the testing tree." OFF)
|
||||
if (BUILD_TESTING)
|
||||
option(BUILD_TESTING_SANITIZE "Build the source with sanitizers" OFF)
|
||||
if (BUILD_TESTING_SANITIZE)
|
||||
if (MSVC)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /fsanitize=address /fno-omit-frame-pointer")
|
||||
else()
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address,leak,undefined")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
enable_testing()
|
||||
add_subdirectory(tests/)
|
||||
endif()
|
||||
else()
|
||||
set(PK_IS_MAIN FALSE)
|
||||
option(PK_BUILD_SHARED_LIB "Build shared library" OFF)
|
||||
@ -68,18 +52,19 @@ else()
|
||||
endif()
|
||||
|
||||
if(PK_BUILD_SHARED_LIB)
|
||||
message(">> Building shared library")
|
||||
add_library(${PROJECT_NAME} SHARED ${POCKETPY_SRC})
|
||||
elseif(PK_BUILD_STATIC_LIB)
|
||||
message(">> Building static library")
|
||||
add_library(${PROJECT_NAME} STATIC ${POCKETPY_SRC})
|
||||
else()
|
||||
set(PROJECT_EXE_NAME main)
|
||||
add_executable(${PROJECT_EXE_NAME} src2/main.c)
|
||||
# shared linked main
|
||||
message(">> Building shared library + executable")
|
||||
add_library(${PROJECT_NAME} SHARED ${POCKETPY_SRC})
|
||||
target_link_libraries(${PROJECT_EXE_NAME} ${PROJECT_NAME})
|
||||
add_executable(main src2/main.c)
|
||||
target_link_libraries(main ${PROJECT_NAME})
|
||||
endif()
|
||||
|
||||
# link math library
|
||||
if(UNIX)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE m)
|
||||
target_link_libraries(${PROJECT_NAME} m)
|
||||
endif()
|
||||
@ -13,8 +13,8 @@ cmake -B simulatorarm64 -G Xcode $FLAGS -DPLATFORM=SIMULATORARM64 ..
|
||||
cmake --build simulatorarm64 --config Release
|
||||
|
||||
xcodebuild -create-xcframework \
|
||||
-library os64/Release-iphoneos/libpocketpy.a -headers ../include \
|
||||
-library simulatorarm64/Release-iphonesimulator/libpocketpy.a -headers ../include \
|
||||
-library os64/Release-iphoneos/libpocketpy.a -headers ../include/pocketpy/pocketpy.h \
|
||||
-library simulatorarm64/Release-iphonesimulator/libpocketpy.a -headers ../include/pocketpy/pocketpy.h \
|
||||
-output pocketpy.xcframework
|
||||
|
||||
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "pocketpy/pocketpy.h"
|
||||
@ -34,7 +34,7 @@
|
||||
* `strcmp`.
|
||||
*/
|
||||
bool c11__stable_sort(void* ptr,
|
||||
int count,
|
||||
int length,
|
||||
int elem_size,
|
||||
int (*f_lt)(const void* a, const void* b, void* extra),
|
||||
void* extra);
|
||||
|
||||
@ -9,17 +9,17 @@
|
||||
|
||||
typedef struct c11_array {
|
||||
void* data;
|
||||
int count;
|
||||
int length;
|
||||
int elem_size;
|
||||
} c11_array;
|
||||
|
||||
void c11_array__ctor(c11_array* self, int elem_size, int count);
|
||||
void c11_array__ctor(c11_array* self, int elem_size, int length);
|
||||
void c11_array__dtor(c11_array* self);
|
||||
c11_array c11_array__copy(const c11_array* self);
|
||||
|
||||
typedef struct c11_vector {
|
||||
void* data;
|
||||
int count;
|
||||
int length;
|
||||
int capacity;
|
||||
int elem_size;
|
||||
} c11_vector;
|
||||
@ -39,43 +39,43 @@ c11_array c11_vector__submit(c11_vector* self);
|
||||
|
||||
#define c11_vector__push(T, self, elem) \
|
||||
do { \
|
||||
if((self)->count == (self)->capacity) c11_vector__reserve((self), (self)->capacity * 2); \
|
||||
((T*)(self)->data)[(self)->count] = (elem); \
|
||||
(self)->count++; \
|
||||
if((self)->length == (self)->capacity) c11_vector__reserve((self), (self)->capacity * 2); \
|
||||
((T*)(self)->data)[(self)->length] = (elem); \
|
||||
(self)->length++; \
|
||||
} while(0)
|
||||
|
||||
#define c11_vector__pop(self) (--(self)->count)
|
||||
#define c11_vector__pop(self) (--(self)->length)
|
||||
|
||||
#define c11_vector__back(T, self) (((T*)(self)->data)[(self)->count - 1])
|
||||
#define c11_vector__back(T, self) (((T*)(self)->data)[(self)->length - 1])
|
||||
|
||||
#define c11_vector__extend(T, self, p, size) \
|
||||
do { \
|
||||
c11_vector__reserve((self), (self)->count + (size)); \
|
||||
memcpy((T*)(self)->data + (self)->count, (p), (size) * sizeof(T)); \
|
||||
(self)->count += (size); \
|
||||
c11_vector__reserve((self), (self)->length + (size)); \
|
||||
memcpy((T*)(self)->data + (self)->length, (p), (size) * sizeof(T)); \
|
||||
(self)->length += (size); \
|
||||
} while(0)
|
||||
|
||||
#define c11_vector__insert(T, self, index, elem) \
|
||||
do { \
|
||||
if((self)->count == (self)->capacity) c11_vector__reserve((self), (self)->capacity * 2); \
|
||||
if((self)->length == (self)->capacity) c11_vector__reserve((self), (self)->capacity * 2); \
|
||||
T* p = (T*)(self)->data + (index); \
|
||||
memmove(p + 1, p, ((self)->count - (index)) * sizeof(T)); \
|
||||
memmove(p + 1, p, ((self)->length - (index)) * sizeof(T)); \
|
||||
*p = (elem); \
|
||||
(self)->count++; \
|
||||
(self)->length++; \
|
||||
} while(0)
|
||||
|
||||
#define c11_vector__erase(T, self, index) \
|
||||
do { \
|
||||
T* p = (T*)(self)->data + (index); \
|
||||
memmove(p, p + 1, ((self)->count - (index)-1) * sizeof(T)); \
|
||||
(self)->count--; \
|
||||
memmove(p, p + 1, ((self)->length - (index)-1) * sizeof(T)); \
|
||||
(self)->length--; \
|
||||
} while(0)
|
||||
|
||||
#define c11__reverse(T, self) \
|
||||
do { \
|
||||
if(!self->data) break; \
|
||||
T* p = (T*)(self)->data; \
|
||||
T* q = (T*)(self)->data + (self)->count - 1; \
|
||||
T* q = (T*)(self)->data + (self)->length - 1; \
|
||||
while(p < q) { \
|
||||
T tmp = *p; \
|
||||
*p = *q; \
|
||||
@ -87,4 +87,4 @@ c11_array c11_vector__submit(c11_vector* self);
|
||||
|
||||
// NOTE: here we do an extra NULL check for it to avoid UB
|
||||
#define c11__foreach(T, self, it) \
|
||||
for(T* it = (self)->data; it && it != (T*)(self)->data + (self)->count; it++)
|
||||
for(T* it = (self)->data; it && it != (T*)(self)->data + (self)->length; it++)
|
||||
|
||||
@ -65,27 +65,27 @@ typedef bool (*py_CFunction)(int argc, py_StackRef argv) PY_RAISE PY_RETURN;
|
||||
enum py_CompileMode { EXEC_MODE, EVAL_MODE, SINGLE_MODE };
|
||||
|
||||
/// A shorthand for `True`.
|
||||
extern py_GlobalRef py_True;
|
||||
PK_EXPORT extern py_GlobalRef py_True;
|
||||
/// A shorthand for `False`.
|
||||
extern py_GlobalRef py_False;
|
||||
PK_EXPORT extern py_GlobalRef py_False;
|
||||
/// A shorthand for `None`.
|
||||
extern py_GlobalRef py_None;
|
||||
PK_EXPORT extern py_GlobalRef py_None;
|
||||
/// A shorthand for `nil`. `nil` is not a valid python object.
|
||||
extern py_GlobalRef py_NIL;
|
||||
PK_EXPORT extern py_GlobalRef py_NIL;
|
||||
|
||||
/************* Global Setup *************/
|
||||
|
||||
/// Initialize pocketpy and the default VM.
|
||||
void py_initialize();
|
||||
PK_EXPORT void py_initialize();
|
||||
/// Finalize pocketpy and free all VMs.
|
||||
void py_finalize();
|
||||
PK_EXPORT void py_finalize();
|
||||
/// Get the current VM index.
|
||||
int py_currentvm();
|
||||
PK_EXPORT int py_currentvm();
|
||||
/// Switch to a VM.
|
||||
/// @param index index of the VM ranging from 0 to 16 (exclusive). `0` is the default VM.
|
||||
void py_switchvm(int index);
|
||||
PK_EXPORT void py_switchvm(int index);
|
||||
/// Set `sys.argv`. Used for storing command-line arguments.
|
||||
void py_sys_setargv(int argc, char** argv);
|
||||
PK_EXPORT void py_sys_setargv(int argc, char** argv);
|
||||
|
||||
/// Run a source string.
|
||||
/// @param source source string.
|
||||
@ -93,81 +93,81 @@ void py_sys_setargv(int argc, char** argv);
|
||||
/// @param mode compile mode. Use `EXEC_MODE` for statements `EVAL_MODE` for expressions.
|
||||
/// @param module target module. Use NULL for the main module.
|
||||
/// @return `true` if the execution is successful or `false` if an exception is raised.
|
||||
bool py_exec(const char* source,
|
||||
const char* filename,
|
||||
enum py_CompileMode mode,
|
||||
py_Ref module) PY_RAISE PY_RETURN;
|
||||
PK_EXPORT bool py_exec(const char* source,
|
||||
const char* filename,
|
||||
enum py_CompileMode mode,
|
||||
py_Ref module) PY_RAISE PY_RETURN;
|
||||
|
||||
/// Evaluate a source string. Equivalent to `py_exec(source, "<string>", EVAL_MODE, module)`.
|
||||
bool py_eval(const char* source, py_Ref module) PY_RAISE PY_RETURN;
|
||||
PK_EXPORT bool py_eval(const char* source, py_Ref module) PY_RAISE PY_RETURN;
|
||||
|
||||
/// Compile a source string into a code object.
|
||||
/// Use python's `exec()` or `eval()` to execute it.
|
||||
bool py_compile(const char* source,
|
||||
const char* filename,
|
||||
enum py_CompileMode mode,
|
||||
bool is_dynamic) PY_RAISE PY_RETURN;
|
||||
PK_EXPORT bool py_compile(const char* source,
|
||||
const char* filename,
|
||||
enum py_CompileMode mode,
|
||||
bool is_dynamic) PY_RAISE PY_RETURN;
|
||||
|
||||
/// Python equivalent to `globals()`.
|
||||
void py_newglobals(py_Ref);
|
||||
PK_EXPORT void py_newglobals(py_Ref);
|
||||
/// Python equivalent to `locals()`.
|
||||
/// @return a temporary object, which expires on the associated function return.
|
||||
void py_newlocals(py_Ref);
|
||||
PK_EXPORT void py_newlocals(py_Ref);
|
||||
|
||||
/************* Values Creation *************/
|
||||
|
||||
/// Create an `int` object.
|
||||
void py_newint(py_Ref, py_i64);
|
||||
PK_EXPORT void py_newint(py_Ref, py_i64);
|
||||
/// Create a `float` object.
|
||||
void py_newfloat(py_Ref, py_f64);
|
||||
PK_EXPORT void py_newfloat(py_Ref, py_f64);
|
||||
/// Create a `bool` object.
|
||||
void py_newbool(py_Ref, bool);
|
||||
PK_EXPORT void py_newbool(py_Ref, bool);
|
||||
/// Create a `str` object from a null-terminated string (utf-8).
|
||||
void py_newstr(py_Ref, const char*);
|
||||
PK_EXPORT void py_newstr(py_Ref, const char*);
|
||||
/// Create a `str` object from a char array (utf-8).
|
||||
void py_newstrn(py_Ref, const char*, int);
|
||||
PK_EXPORT void py_newstrn(py_Ref, const char*, int);
|
||||
/// Create a `bytes` object with `n` UNINITIALIZED bytes.
|
||||
unsigned char* py_newbytes(py_Ref, int n);
|
||||
PK_EXPORT unsigned char* py_newbytes(py_Ref, int n);
|
||||
/// Create a `None` object.
|
||||
void py_newnone(py_Ref);
|
||||
PK_EXPORT void py_newnone(py_Ref);
|
||||
/// Create a `NotImplemented` object.
|
||||
void py_newnotimplemented(py_Ref out);
|
||||
PK_EXPORT void py_newnotimplemented(py_Ref out);
|
||||
/// Create a `...` object.
|
||||
void py_newellipsis(py_Ref out);
|
||||
PK_EXPORT void py_newellipsis(py_Ref out);
|
||||
/// Create a `nil` object. `nil` is an invalid representation of an object.
|
||||
/// Don't use it unless you know what you are doing.
|
||||
void py_newnil(py_Ref);
|
||||
PK_EXPORT void py_newnil(py_Ref);
|
||||
/// Create a `tuple` with `n` UNINITIALIZED elements.
|
||||
/// You should initialize all elements before using it.
|
||||
void py_newtuple(py_Ref, int n);
|
||||
PK_EXPORT void py_newtuple(py_Ref, int n);
|
||||
/// Create an empty `list`.
|
||||
void py_newlist(py_Ref);
|
||||
PK_EXPORT void py_newlist(py_Ref);
|
||||
/// Create a `list` with `n` UNINITIALIZED elements.
|
||||
/// You should initialize all elements before using it.
|
||||
void py_newlistn(py_Ref, int n);
|
||||
PK_EXPORT void py_newlistn(py_Ref, int n);
|
||||
/// Create an empty `dict`.
|
||||
void py_newdict(py_Ref);
|
||||
PK_EXPORT void py_newdict(py_Ref);
|
||||
/// Create an UNINITIALIZED `slice` object.
|
||||
/// You should use `py_setslot()` to set `start`, `stop`, and `step`.
|
||||
void py_newslice(py_Ref);
|
||||
PK_EXPORT void py_newslice(py_Ref);
|
||||
/// Create a `nativefunc` object.
|
||||
void py_newnativefunc(py_Ref out, py_CFunction);
|
||||
PK_EXPORT void py_newnativefunc(py_Ref out, py_CFunction);
|
||||
/// Create a `function` object.
|
||||
py_Name
|
||||
PK_EXPORT py_Name
|
||||
py_newfunction(py_Ref out, const char* sig, py_CFunction f, const char* docstring, int slots);
|
||||
/// Create a `boundmethod` object.
|
||||
void py_newboundmethod(py_Ref out, py_Ref self, py_Ref func);
|
||||
PK_EXPORT void py_newboundmethod(py_Ref out, py_Ref self, py_Ref func);
|
||||
|
||||
/************* Name Convertions *************/
|
||||
|
||||
/// Convert a null-terminated string to a name.
|
||||
py_Name py_name(const char*);
|
||||
PK_EXPORT py_Name py_name(const char*);
|
||||
/// Convert a name to a null-terminated string.
|
||||
const char* py_name2str(py_Name);
|
||||
PK_EXPORT const char* py_name2str(py_Name);
|
||||
/// Convert a name to a `c11_sv`.
|
||||
py_Name py_namev(c11_sv name);
|
||||
PK_EXPORT py_Name py_namev(c11_sv name);
|
||||
/// Convert a `c11_sv` to a name.
|
||||
c11_sv py_name2sv(py_Name);
|
||||
PK_EXPORT c11_sv py_name2sv(py_Name);
|
||||
|
||||
#define py_ismagicname(name) (name <= __missing__)
|
||||
|
||||
@ -178,7 +178,10 @@ c11_sv py_name2sv(py_Name);
|
||||
/// @param base base type.
|
||||
/// @param module module where the type is defined. Use `NULL` for built-in types.
|
||||
/// @param dtor destructor function. Use `NULL` if not needed.
|
||||
py_Type py_newtype(const char* name, py_Type base, const py_GlobalRef module, py_Dtor dtor);
|
||||
PK_EXPORT py_Type py_newtype(const char* name,
|
||||
py_Type base,
|
||||
const py_GlobalRef module,
|
||||
py_Dtor dtor);
|
||||
|
||||
/// Create a new object.
|
||||
/// @param out output reference.
|
||||
@ -186,32 +189,32 @@ py_Type py_newtype(const char* name, py_Type base, const py_GlobalRef module, py
|
||||
/// @param slots number of slots. Use `-1` to create a `__dict__`.
|
||||
/// @param udsize size of your userdata.
|
||||
/// @return pointer to the userdata.
|
||||
void* py_newobject(py_Ref out, py_Type type, int slots, int udsize);
|
||||
PK_EXPORT void* py_newobject(py_Ref out, py_Type type, int slots, int udsize);
|
||||
|
||||
/************* Type Cast *************/
|
||||
|
||||
/// Convert an `int` object in python to `int64_t`.
|
||||
py_i64 py_toint(py_Ref);
|
||||
PK_EXPORT py_i64 py_toint(py_Ref);
|
||||
/// Convert a `float` object in python to `double`.
|
||||
py_f64 py_tofloat(py_Ref);
|
||||
PK_EXPORT py_f64 py_tofloat(py_Ref);
|
||||
/// Cast a `int` or `float` object in python to `double`.
|
||||
/// If successful, return true and set the value to `out`.
|
||||
/// Otherwise, return false and raise `TypeError`.
|
||||
bool py_castfloat(py_Ref, py_f64* out) PY_RAISE;
|
||||
PK_EXPORT bool py_castfloat(py_Ref, py_f64* out) PY_RAISE;
|
||||
/// Convert a `bool` object in python to `bool`.
|
||||
bool py_tobool(py_Ref);
|
||||
PK_EXPORT bool py_tobool(py_Ref);
|
||||
/// Convert a `type` object in python to `py_Type`.
|
||||
py_Type py_totype(py_Ref);
|
||||
PK_EXPORT py_Type py_totype(py_Ref);
|
||||
/// Convert a `str` object in python to null-terminated string.
|
||||
const char* py_tostr(py_Ref);
|
||||
PK_EXPORT const char* py_tostr(py_Ref);
|
||||
/// Convert a `str` object in python to char array.
|
||||
const char* py_tostrn(py_Ref, int* size);
|
||||
PK_EXPORT const char* py_tostrn(py_Ref, int* size);
|
||||
/// Convert a `str` object in python to `c11_sv`.
|
||||
c11_sv py_tosv(py_Ref);
|
||||
PK_EXPORT c11_sv py_tosv(py_Ref);
|
||||
/// Convert a `bytes` object in python to char array.
|
||||
unsigned char* py_tobytes(py_Ref, int* size);
|
||||
PK_EXPORT unsigned char* py_tobytes(py_Ref, int* size);
|
||||
/// Convert a user-defined object to its userdata.
|
||||
void* py_touserdata(py_Ref);
|
||||
PK_EXPORT void* py_touserdata(py_Ref);
|
||||
|
||||
#define py_isint(self) py_istype(self, tp_int)
|
||||
#define py_isfloat(self) py_istype(self, tp_float)
|
||||
@ -225,37 +228,37 @@ void* py_touserdata(py_Ref);
|
||||
#define py_isnone(self) py_istype(self, tp_NoneType)
|
||||
|
||||
/// Get the type of the object.
|
||||
py_Type py_typeof(py_Ref self);
|
||||
PK_EXPORT py_Type py_typeof(py_Ref self);
|
||||
/// Get type by module and name. e.g. `py_gettype("time", py_name("struct_time"))`.
|
||||
/// Return `0` if not found.
|
||||
py_Type py_gettype(const char* module, py_Name name);
|
||||
PK_EXPORT py_Type py_gettype(const char* module, py_Name name);
|
||||
/// Check if the object is exactly the given type.
|
||||
bool py_istype(py_Ref, py_Type);
|
||||
PK_EXPORT bool py_istype(py_Ref, py_Type);
|
||||
/// Check if the object is an instance of the given type.
|
||||
bool py_isinstance(py_Ref obj, py_Type type);
|
||||
PK_EXPORT bool py_isinstance(py_Ref obj, py_Type type);
|
||||
/// Check if the derived type is a subclass of the base type.
|
||||
bool py_issubclass(py_Type derived, py_Type base);
|
||||
PK_EXPORT bool py_issubclass(py_Type derived, py_Type base);
|
||||
|
||||
/// Search the magic method from the given type to the base type.
|
||||
/// Return `NULL` if not found.
|
||||
py_ItemRef py_tpfindmagic(py_Type, py_Name name);
|
||||
PK_EXPORT py_ItemRef py_tpfindmagic(py_Type, py_Name name);
|
||||
/// Search the name from the given type to the base type.
|
||||
/// Return `NULL` if not found.
|
||||
py_ItemRef py_tpfindname(py_Type, py_Name name);
|
||||
PK_EXPORT py_ItemRef py_tpfindname(py_Type, py_Name name);
|
||||
/// Get the magic method from the given type only.
|
||||
/// The returned reference is always valid. However, its value may be `nil`.
|
||||
py_ItemRef py_tpgetmagic(py_Type type, py_Name name);
|
||||
PK_EXPORT py_ItemRef py_tpgetmagic(py_Type type, py_Name name);
|
||||
|
||||
/// Get the type object of the given type.
|
||||
py_ItemRef py_tpobject(py_Type type);
|
||||
PK_EXPORT py_ItemRef py_tpobject(py_Type type);
|
||||
/// Get the type name.
|
||||
const char* py_tpname(py_Type type);
|
||||
PK_EXPORT const char* py_tpname(py_Type type);
|
||||
/// Call a type to create a new instance.
|
||||
bool py_tpcall(py_Type type, int argc, py_Ref argv) PY_RAISE PY_RETURN;
|
||||
PK_EXPORT bool py_tpcall(py_Type type, int argc, py_Ref argv) PY_RAISE PY_RETURN;
|
||||
|
||||
/// Check if the object is an instance of the given type.
|
||||
/// Raise `TypeError` if the check fails.
|
||||
bool py_checktype(py_Ref self, py_Type type) PY_RAISE;
|
||||
PK_EXPORT bool py_checktype(py_Ref self, py_Type type) PY_RAISE;
|
||||
|
||||
#define py_checkint(self) py_checktype(self, tp_int)
|
||||
#define py_checkfloat(self) py_checktype(self, tp_float)
|
||||
@ -266,47 +269,47 @@ bool py_checktype(py_Ref self, py_Type type) PY_RAISE;
|
||||
|
||||
/// Get the i-th register.
|
||||
/// All registers are located in a contiguous memory.
|
||||
py_GlobalRef py_getreg(int i);
|
||||
PK_EXPORT py_GlobalRef py_getreg(int i);
|
||||
/// Set the i-th register.
|
||||
void py_setreg(int i, py_Ref val);
|
||||
PK_EXPORT void py_setreg(int i, py_Ref val);
|
||||
|
||||
/// Get variable in the `__main__` module.
|
||||
py_ItemRef py_getglobal(py_Name name);
|
||||
PK_EXPORT py_ItemRef py_getglobal(py_Name name);
|
||||
/// Set variable in the `__main__` module.
|
||||
void py_setglobal(py_Name name, py_Ref val);
|
||||
PK_EXPORT void py_setglobal(py_Name name, py_Ref val);
|
||||
/// Get variable in the `builtins` module.
|
||||
py_ItemRef py_getbuiltin(py_Name name);
|
||||
PK_EXPORT py_ItemRef py_getbuiltin(py_Name name);
|
||||
|
||||
/// Equivalent to `*dst = *src`.
|
||||
void py_assign(py_Ref dst, py_Ref src);
|
||||
PK_EXPORT void py_assign(py_Ref dst, py_Ref src);
|
||||
/// Get the last return value.
|
||||
py_GlobalRef py_retval();
|
||||
PK_EXPORT py_GlobalRef py_retval();
|
||||
|
||||
/// Get an item from the object's `__dict__`.
|
||||
/// Return `NULL` if not found.
|
||||
py_ItemRef py_getdict(py_Ref self, py_Name name);
|
||||
PK_EXPORT py_ItemRef py_getdict(py_Ref self, py_Name name);
|
||||
/// Set an item to the object's `__dict__`.
|
||||
void py_setdict(py_Ref self, py_Name name, py_Ref val);
|
||||
PK_EXPORT void py_setdict(py_Ref self, py_Name name, py_Ref val);
|
||||
/// Delete an item from the object's `__dict__`.
|
||||
/// Return `true` if the deletion is successful.
|
||||
bool py_deldict(py_Ref self, py_Name name);
|
||||
PK_EXPORT bool py_deldict(py_Ref self, py_Name name);
|
||||
/// Prepare an insertion to the object's `__dict__`.
|
||||
py_ItemRef py_emplacedict(py_Ref self, py_Name name);
|
||||
PK_EXPORT py_ItemRef py_emplacedict(py_Ref self, py_Name name);
|
||||
|
||||
/// Get the i-th slot of the object.
|
||||
/// The object must have slots and `i` must be in valid range.
|
||||
py_ObjectRef py_getslot(py_Ref self, int i);
|
||||
PK_EXPORT py_ObjectRef py_getslot(py_Ref self, int i);
|
||||
/// Set the i-th slot of the object.
|
||||
void py_setslot(py_Ref self, int i, py_Ref val);
|
||||
PK_EXPORT void py_setslot(py_Ref self, int i, py_Ref val);
|
||||
|
||||
/************* Inspection *************/
|
||||
|
||||
/// Get the current `function` object from the stack.
|
||||
/// Return `NULL` if not available.
|
||||
py_StackRef py_inspect_currentfunction();
|
||||
PK_EXPORT py_StackRef py_inspect_currentfunction();
|
||||
/// Get the current `module` object where the code is executed.
|
||||
/// Return `NULL` if not available.
|
||||
py_GlobalRef py_inspect_currentmodule();
|
||||
PK_EXPORT py_GlobalRef py_inspect_currentmodule();
|
||||
|
||||
/************* Bindings *************/
|
||||
|
||||
@ -314,23 +317,24 @@ py_GlobalRef py_inspect_currentmodule();
|
||||
/// @param obj the target object.
|
||||
/// @param sig signature of the function. e.g. `add(x, y)`.
|
||||
/// @param f function to bind.
|
||||
void py_bind(py_Ref obj, const char* sig, py_CFunction f);
|
||||
PK_EXPORT void py_bind(py_Ref obj, const char* sig, py_CFunction f);
|
||||
/// Bind a method to type via "argc-based" style.
|
||||
/// @param type the target type.
|
||||
/// @param name name of the method.
|
||||
/// @param f function to bind.
|
||||
void py_bindmethod(py_Type type, const char* name, py_CFunction f);
|
||||
PK_EXPORT void py_bindmethod(py_Type type, const char* name, py_CFunction f);
|
||||
/// Bind a function to the object via "argc-based" style.
|
||||
/// @param obj the target object.
|
||||
/// @param name name of the function.
|
||||
/// @param f function to bind.
|
||||
void py_bindfunc(py_Ref obj, const char* name, py_CFunction f);
|
||||
PK_EXPORT void py_bindfunc(py_Ref obj, const char* name, py_CFunction f);
|
||||
/// Bind a property to type.
|
||||
/// @param type the target type.
|
||||
/// @param name name of the property.
|
||||
/// @param getter getter function.
|
||||
/// @param setter setter function. Use `NULL` if not needed.
|
||||
void py_bindproperty(py_Type type, const char* name, py_CFunction getter, py_CFunction setter);
|
||||
PK_EXPORT void
|
||||
py_bindproperty(py_Type type, const char* name, py_CFunction getter, py_CFunction setter);
|
||||
|
||||
#define py_bindmagic(type, __magic__, f) py_newnativefunc(py_tpgetmagic((type), __magic__), (f))
|
||||
|
||||
@ -346,22 +350,22 @@ void py_bindproperty(py_Type type, const char* name, py_CFunction getter, py_CFu
|
||||
/************* Python Equivalents *************/
|
||||
|
||||
/// Python equivalent to `getattr(self, name)`.
|
||||
bool py_getattr(py_Ref self, py_Name name) PY_RAISE PY_RETURN;
|
||||
PK_EXPORT bool py_getattr(py_Ref self, py_Name name) PY_RAISE PY_RETURN;
|
||||
/// Python equivalent to `setattr(self, name, val)`.
|
||||
bool py_setattr(py_Ref self, py_Name name, py_Ref val) PY_RAISE;
|
||||
PK_EXPORT bool py_setattr(py_Ref self, py_Name name, py_Ref val) PY_RAISE;
|
||||
/// Python equivalent to `delattr(self, name)`.
|
||||
bool py_delattr(py_Ref self, py_Name name) PY_RAISE;
|
||||
PK_EXPORT bool py_delattr(py_Ref self, py_Name name) PY_RAISE;
|
||||
/// Python equivalent to `self[key]`.
|
||||
bool py_getitem(py_Ref self, py_Ref key) PY_RAISE PY_RETURN;
|
||||
PK_EXPORT bool py_getitem(py_Ref self, py_Ref key) PY_RAISE PY_RETURN;
|
||||
/// Python equivalent to `self[key] = val`.
|
||||
bool py_setitem(py_Ref self, py_Ref key, py_Ref val) PY_RAISE;
|
||||
PK_EXPORT bool py_setitem(py_Ref self, py_Ref key, py_Ref val) PY_RAISE;
|
||||
/// Python equivalent to `del self[key]`.
|
||||
bool py_delitem(py_Ref self, py_Ref key) PY_RAISE;
|
||||
PK_EXPORT bool py_delitem(py_Ref self, py_Ref key) PY_RAISE;
|
||||
|
||||
/// Perform a binary operation.
|
||||
/// The result will be set to `py_retval()`.
|
||||
/// The stack remains unchanged after the operation.
|
||||
bool py_binaryop(py_Ref lhs, py_Ref rhs, py_Name op, py_Name rop) PY_RAISE PY_RETURN;
|
||||
PK_EXPORT bool py_binaryop(py_Ref lhs, py_Ref rhs, py_Name op, py_Name rop) PY_RAISE PY_RETURN;
|
||||
|
||||
#define py_binaryadd(lhs, rhs) py_binaryop(lhs, rhs, __add__, __radd__)
|
||||
#define py_binarysub(lhs, rhs) py_binaryop(lhs, rhs, __sub__, __rsub__)
|
||||
@ -382,68 +386,68 @@ bool py_binaryop(py_Ref lhs, py_Ref rhs, py_Name op, py_Name rop) PY_RAISE PY_RE
|
||||
|
||||
/// Get the i-th object from the top of the stack.
|
||||
/// `i` should be negative, e.g. (-1) means TOS.
|
||||
py_StackRef py_peek(int i);
|
||||
PK_EXPORT py_StackRef py_peek(int i);
|
||||
/// Push the object to the stack.
|
||||
void py_push(py_Ref src);
|
||||
PK_EXPORT void py_push(py_Ref src);
|
||||
/// Push a `nil` object to the stack.
|
||||
void py_pushnil();
|
||||
PK_EXPORT void py_pushnil();
|
||||
/// Push a `None` object to the stack.
|
||||
void py_pushnone();
|
||||
PK_EXPORT void py_pushnone();
|
||||
/// Push a `py_Name` to the stack. This is used for keyword arguments.
|
||||
void py_pushname(py_Name name);
|
||||
PK_EXPORT void py_pushname(py_Name name);
|
||||
/// Pop an object from the stack.
|
||||
void py_pop();
|
||||
PK_EXPORT void py_pop();
|
||||
/// Shrink the stack by n.
|
||||
void py_shrink(int n);
|
||||
PK_EXPORT void py_shrink(int n);
|
||||
/// Get a temporary variable from the stack.
|
||||
py_StackRef py_pushtmp();
|
||||
PK_EXPORT py_StackRef py_pushtmp();
|
||||
/// Get the unbound method of the object.
|
||||
/// Assume the object is located at the top of the stack.
|
||||
/// If return true: `[self] -> [unbound, self]`.
|
||||
/// If return false: `[self] -> [self]` (no change).
|
||||
bool py_pushmethod(py_Name name);
|
||||
PK_EXPORT bool py_pushmethod(py_Name name);
|
||||
/// Call a callable object.
|
||||
/// Assume `argc + kwargc` arguments are already pushed to the stack.
|
||||
/// The result will be set to `py_retval()`.
|
||||
/// The stack size will be reduced by `argc + kwargc`.
|
||||
bool py_vectorcall(uint16_t argc, uint16_t kwargc) PY_RAISE PY_RETURN;
|
||||
PK_EXPORT bool py_vectorcall(uint16_t argc, uint16_t kwargc) PY_RAISE PY_RETURN;
|
||||
/// Evaluate an expression and push the result to the stack.
|
||||
/// This function is used for testing.
|
||||
bool py_pusheval(const char* expr, py_GlobalRef module) PY_RAISE;
|
||||
PK_EXPORT bool py_pusheval(const char* expr, py_GlobalRef module) PY_RAISE;
|
||||
|
||||
/************* Modules *************/
|
||||
|
||||
/// Create a new module.
|
||||
py_GlobalRef py_newmodule(const char* path);
|
||||
PK_EXPORT py_GlobalRef py_newmodule(const char* path);
|
||||
/// Get a module by path.
|
||||
py_GlobalRef py_getmodule(const char* path);
|
||||
PK_EXPORT py_GlobalRef py_getmodule(const char* path);
|
||||
|
||||
/// Import a module.
|
||||
/// The result will be set to `py_retval()`.
|
||||
/// -1: error, 0: not found, 1: success
|
||||
int py_import(const char* path) PY_RAISE;
|
||||
PK_EXPORT int py_import(const char* path) PY_RAISE;
|
||||
|
||||
/************* Errors *************/
|
||||
|
||||
/// Raise an exception by type and message. Always return false.
|
||||
bool py_exception(py_Type type, const char* fmt, ...) PY_RAISE;
|
||||
PK_EXPORT bool py_exception(py_Type type, const char* fmt, ...) PY_RAISE;
|
||||
/// Raise an expection object. Always return false.
|
||||
bool py_raise(py_Ref) PY_RAISE;
|
||||
PK_EXPORT bool py_raise(py_Ref) PY_RAISE;
|
||||
/// Print the current exception.
|
||||
/// The exception will be set as handled.
|
||||
void py_printexc();
|
||||
PK_EXPORT void py_printexc();
|
||||
/// Format the current exception and return a null-terminated string.
|
||||
/// The result should be freed by the caller.
|
||||
/// The exception will be set as handled.
|
||||
char* py_formatexc();
|
||||
PK_EXPORT char* py_formatexc();
|
||||
/// Check if an exception is raised.
|
||||
bool py_checkexc(bool ignore_handled);
|
||||
PK_EXPORT bool py_checkexc(bool ignore_handled);
|
||||
/// Check if the exception is an instance of the given type.
|
||||
/// If match, the exception will be set as handled.
|
||||
bool py_matchexc(py_Type type);
|
||||
PK_EXPORT bool py_matchexc(py_Type type);
|
||||
/// Clear the current exception.
|
||||
/// @param p0 the unwinding point. Use `NULL` if not needed.
|
||||
void py_clearexc(py_StackRef p0);
|
||||
PK_EXPORT void py_clearexc(py_StackRef p0);
|
||||
|
||||
#define NameError(n) py_exception(tp_NameError, "name '%n' is not defined", (n))
|
||||
#define TypeError(...) py_exception(tp_TypeError, __VA_ARGS__)
|
||||
@ -457,21 +461,21 @@ void py_clearexc(py_StackRef p0);
|
||||
#define UnboundLocalError(n) \
|
||||
py_exception(tp_UnboundLocalError, "local variable '%n' referenced before assignment", (n))
|
||||
|
||||
bool StopIteration();
|
||||
bool KeyError(py_Ref key) PY_RAISE;
|
||||
PK_EXPORT bool StopIteration();
|
||||
PK_EXPORT bool KeyError(py_Ref key) PY_RAISE;
|
||||
|
||||
/************* Operators *************/
|
||||
|
||||
/// Python equivalent to `bool(val)`.
|
||||
/// 1: true, 0: false, -1: error
|
||||
int py_bool(py_Ref val) PY_RAISE PY_RETURN;
|
||||
PK_EXPORT int py_bool(py_Ref val) PY_RAISE PY_RETURN;
|
||||
|
||||
/// Compare two objects.
|
||||
/// 1: lhs == rhs, 0: lhs != rhs, -1: error
|
||||
int py_equal(py_Ref lhs, py_Ref rhs) PY_RAISE;
|
||||
PK_EXPORT int py_equal(py_Ref lhs, py_Ref rhs) PY_RAISE;
|
||||
/// Compare two objects.
|
||||
/// 1: lhs < rhs, 0: lhs >= rhs, -1: error
|
||||
int py_less(py_Ref lhs, py_Ref rhs) PY_RAISE;
|
||||
PK_EXPORT int py_less(py_Ref lhs, py_Ref rhs) PY_RAISE;
|
||||
|
||||
#define py_eq(lhs, rhs) py_binaryop(lhs, rhs, __eq__, __eq__)
|
||||
#define py_ne(lhs, rhs) py_binaryop(lhs, rhs, __ne__, __ne__)
|
||||
@ -481,74 +485,79 @@ int py_less(py_Ref lhs, py_Ref rhs) PY_RAISE;
|
||||
#define py_ge(lhs, rhs) py_binaryop(lhs, rhs, __ge__, __le__)
|
||||
|
||||
/// Get the hash value of the object.
|
||||
bool py_hash(py_Ref, py_i64* out) PY_RAISE;
|
||||
PK_EXPORT bool py_hash(py_Ref, py_i64* out) PY_RAISE;
|
||||
/// Get the iterator of the object.
|
||||
bool py_iter(py_Ref) PY_RAISE PY_RETURN;
|
||||
PK_EXPORT bool py_iter(py_Ref) PY_RAISE PY_RETURN;
|
||||
/// Get the next element from the iterator.
|
||||
/// 1: success, 0: StopIteration, -1: error
|
||||
int py_next(py_Ref) PY_RAISE PY_RETURN;
|
||||
PK_EXPORT int py_next(py_Ref) PY_RAISE PY_RETURN;
|
||||
/// Python equivalent to `lhs is rhs`.
|
||||
bool py_isidentical(py_Ref, py_Ref);
|
||||
PK_EXPORT bool py_isidentical(py_Ref, py_Ref);
|
||||
/// Call a function.
|
||||
/// It prepares the stack and then performs a `vectorcall(argc, 0, false)`.
|
||||
/// The result will be set to `py_retval()`.
|
||||
/// The stack remains unchanged after the operation.
|
||||
bool py_call(py_Ref f, int argc, py_Ref argv) PY_RAISE PY_RETURN;
|
||||
PK_EXPORT bool py_call(py_Ref f, int argc, py_Ref argv) PY_RAISE PY_RETURN;
|
||||
|
||||
#if PK_DEBUG
|
||||
/// Call a `py_CFunction` in a safe way.
|
||||
/// This function does extra checks to help you debug `py_CFunction`.
|
||||
bool py_callcfunc(py_CFunction f, int argc, py_Ref argv) PY_RAISE PY_RETURN;
|
||||
PK_EXPORT bool py_callcfunc(py_CFunction f, int argc, py_Ref argv) PY_RAISE PY_RETURN;
|
||||
#else
|
||||
#define py_callcfunc(f, argc, argv) (f((argc), (argv)))
|
||||
#endif
|
||||
|
||||
/// Python equivalent to `str(val)`.
|
||||
bool py_str(py_Ref val) PY_RAISE PY_RETURN;
|
||||
PK_EXPORT bool py_str(py_Ref val) PY_RAISE PY_RETURN;
|
||||
/// Python equivalent to `repr(val)`.
|
||||
bool py_repr(py_Ref val) PY_RAISE PY_RETURN;
|
||||
PK_EXPORT bool py_repr(py_Ref val) PY_RAISE PY_RETURN;
|
||||
/// Python equivalent to `len(val)`.
|
||||
bool py_len(py_Ref val) PY_RAISE PY_RETURN;
|
||||
PK_EXPORT bool py_len(py_Ref val) PY_RAISE PY_RETURN;
|
||||
/// Python equivalent to `json.dumps(val)`.
|
||||
bool py_json_dumps(py_Ref val) PY_RAISE PY_RETURN;
|
||||
PK_EXPORT bool py_json_dumps(py_Ref val) PY_RAISE PY_RETURN;
|
||||
/// Python equivalent to `json.loads(val)`.
|
||||
bool py_json_loads(const char* source) PY_RAISE PY_RETURN;
|
||||
PK_EXPORT bool py_json_loads(const char* source) PY_RAISE PY_RETURN;
|
||||
|
||||
/************* Unchecked Functions *************/
|
||||
|
||||
py_ObjectRef py_tuple_data(py_Ref self);
|
||||
py_ObjectRef py_tuple_getitem(py_Ref self, int i);
|
||||
void py_tuple_setitem(py_Ref self, int i, py_Ref val);
|
||||
int py_tuple_len(py_Ref self);
|
||||
PK_EXPORT py_ObjectRef py_tuple_data(py_Ref self);
|
||||
PK_EXPORT py_ObjectRef py_tuple_getitem(py_Ref self, int i);
|
||||
PK_EXPORT void py_tuple_setitem(py_Ref self, int i, py_Ref val);
|
||||
PK_EXPORT int py_tuple_len(py_Ref self);
|
||||
|
||||
py_ItemRef py_list_data(py_Ref self);
|
||||
py_ItemRef py_list_getitem(py_Ref self, int i);
|
||||
void py_list_setitem(py_Ref self, int i, py_Ref val);
|
||||
void py_list_delitem(py_Ref self, int i);
|
||||
int py_list_len(py_Ref self);
|
||||
void py_list_swap(py_Ref self, int i, int j);
|
||||
void py_list_append(py_Ref self, py_Ref val);
|
||||
py_ItemRef py_list_emplace(py_Ref self);
|
||||
void py_list_clear(py_Ref self);
|
||||
void py_list_insert(py_Ref self, int i, py_Ref val);
|
||||
PK_EXPORT py_ItemRef py_list_data(py_Ref self);
|
||||
PK_EXPORT py_ItemRef py_list_getitem(py_Ref self, int i);
|
||||
PK_EXPORT void py_list_setitem(py_Ref self, int i, py_Ref val);
|
||||
PK_EXPORT void py_list_delitem(py_Ref self, int i);
|
||||
PK_EXPORT int py_list_len(py_Ref self);
|
||||
PK_EXPORT void py_list_swap(py_Ref self, int i, int j);
|
||||
PK_EXPORT void py_list_append(py_Ref self, py_Ref val);
|
||||
PK_EXPORT py_ItemRef py_list_emplace(py_Ref self);
|
||||
PK_EXPORT void py_list_clear(py_Ref self);
|
||||
PK_EXPORT void py_list_insert(py_Ref self, int i, py_Ref val);
|
||||
|
||||
/// -1: error, 0: not found, 1: found
|
||||
int py_dict_getitem(py_Ref self, py_Ref key) PY_RAISE PY_RETURN;
|
||||
PK_EXPORT int py_dict_getitem(py_Ref self, py_Ref key) PY_RAISE PY_RETURN;
|
||||
/// true: success, false: error
|
||||
bool py_dict_setitem(py_Ref self, py_Ref key, py_Ref val) PY_RAISE;
|
||||
PK_EXPORT bool py_dict_setitem(py_Ref self, py_Ref key, py_Ref val) PY_RAISE;
|
||||
/// -1: error, 0: not found, 1: found (and deleted)
|
||||
int py_dict_delitem(py_Ref self, py_Ref key) PY_RAISE;
|
||||
PK_EXPORT int py_dict_delitem(py_Ref self, py_Ref key) PY_RAISE;
|
||||
/// -1: error, 0: not found, 1: found
|
||||
int py_dict_contains(py_Ref self, py_Ref key) PY_RAISE;
|
||||
PK_EXPORT int py_dict_getitem_by_str(py_Ref self, const char* key) PY_RAISE PY_RETURN;
|
||||
/// true: success, false: error
|
||||
bool py_dict_apply(py_Ref self, bool (*f)(py_Ref key, py_Ref val, void* ctx), void* ctx) PY_RAISE;
|
||||
PK_EXPORT bool py_dict_setitem_by_str(py_Ref self, const char* key, py_Ref val) PY_RAISE;
|
||||
/// -1: error, 0: not found, 1: found (and deleted)
|
||||
PK_EXPORT int py_dict_delitem_by_str(py_Ref self, const char* key) PY_RAISE;
|
||||
/// true: success, false: error
|
||||
PK_EXPORT bool
|
||||
py_dict_apply(py_Ref self, bool (*f)(py_Ref key, py_Ref val, void* ctx), void* ctx) PY_RAISE;
|
||||
/// noexcept
|
||||
int py_dict_len(py_Ref self);
|
||||
PK_EXPORT int py_dict_len(py_Ref self);
|
||||
|
||||
/************* Others *************/
|
||||
|
||||
/// An utility function to read a line from stdin for REPL.
|
||||
int py_replinput(char* buf, int max_size);
|
||||
PK_EXPORT int py_replinput(char* buf, int max_size);
|
||||
|
||||
/// Python favored string formatting.
|
||||
/// %d: int
|
||||
@ -606,6 +615,8 @@ enum py_PredefinedTypes {
|
||||
tp_ellipsis,
|
||||
tp_generator,
|
||||
/* builtin exceptions */
|
||||
tp_SystemExit,
|
||||
tp_KeyboardInterrupt,
|
||||
tp_StopIteration,
|
||||
tp_SyntaxError,
|
||||
tp_StackOverflowError,
|
||||
|
||||
@ -1,27 +1,27 @@
|
||||
#if !defined(SMALLMAP_T__HEADER) && !defined(SMALLMAP_T__SOURCE)
|
||||
#include "pocketpy/common/vector.h"
|
||||
#include "pocketpy/common/vector.h"
|
||||
|
||||
#define SMALLMAP_T__HEADER
|
||||
#define SMALLMAP_T__SOURCE
|
||||
/* Input */
|
||||
#define K int
|
||||
#define V float
|
||||
#define NAME c11_smallmap_i2f
|
||||
#define SMALLMAP_T__HEADER
|
||||
#define SMALLMAP_T__SOURCE
|
||||
/* Input */
|
||||
#define K int
|
||||
#define V float
|
||||
#define NAME c11_smallmap_i2f
|
||||
#endif
|
||||
|
||||
/* Optional Input */
|
||||
#ifndef less
|
||||
#define less(a, b) ((a) < (b))
|
||||
#define less(a, b) ((a) < (b))
|
||||
#endif
|
||||
|
||||
#ifndef equal
|
||||
#define equal(a, b) ((a) == (b))
|
||||
#define equal(a, b) ((a) == (b))
|
||||
#endif
|
||||
|
||||
/* Temprary macros */
|
||||
#define partial_less(a, b) less((a).key, (b))
|
||||
#define CONCAT(A, B) CONCAT_(A, B)
|
||||
#define CONCAT_(A, B) A##B
|
||||
#define partial_less(a, b) less((a).key, (b))
|
||||
#define CONCAT(A, B) CONCAT_(A, B)
|
||||
#define CONCAT_(A, B) A##B
|
||||
|
||||
#define KV CONCAT(NAME, _KV)
|
||||
#define METHOD(name) CONCAT(NAME, CONCAT(__, name))
|
||||
@ -56,9 +56,7 @@ void METHOD(ctor)(NAME* self) {
|
||||
c11_vector__reserve(self, 4);
|
||||
}
|
||||
|
||||
void METHOD(dtor)(NAME* self) {
|
||||
c11_vector__dtor(self);
|
||||
}
|
||||
void METHOD(dtor)(NAME* self) { c11_vector__dtor(self); }
|
||||
|
||||
NAME* METHOD(new)() {
|
||||
NAME* self = malloc(sizeof(NAME));
|
||||
@ -73,10 +71,10 @@ void METHOD(delete)(NAME* self) {
|
||||
|
||||
void METHOD(set)(NAME* self, K key, V value) {
|
||||
int index;
|
||||
c11__lower_bound(KV, self->data, self->count, key, partial_less, &index);
|
||||
if(index != self->count){
|
||||
c11__lower_bound(KV, self->data, self->length, key, partial_less, &index);
|
||||
if(index != self->length) {
|
||||
KV* it = c11__at(KV, self, index);
|
||||
if(equal(it->key, key)){
|
||||
if(equal(it->key, key)) {
|
||||
it->value = value;
|
||||
return;
|
||||
}
|
||||
@ -87,8 +85,8 @@ void METHOD(set)(NAME* self, K key, V value) {
|
||||
|
||||
V* METHOD(try_get)(const NAME* self, K key) {
|
||||
int index;
|
||||
c11__lower_bound(KV, self->data, self->count, key, partial_less, &index);
|
||||
if(index != self->count){
|
||||
c11__lower_bound(KV, self->data, self->length, key, partial_less, &index);
|
||||
if(index != self->length) {
|
||||
KV* it = c11__at(KV, self, index);
|
||||
if(equal(it->key, key)) return &it->value;
|
||||
}
|
||||
@ -100,16 +98,14 @@ V METHOD(get)(const NAME* self, K key, V default_value) {
|
||||
return p ? *p : default_value;
|
||||
}
|
||||
|
||||
bool METHOD(contains)(const NAME* self, K key) {
|
||||
return METHOD(try_get)(self, key) != NULL;
|
||||
}
|
||||
bool METHOD(contains)(const NAME* self, K key) { return METHOD(try_get)(self, key) != NULL; }
|
||||
|
||||
bool METHOD(del)(NAME* self, K key) {
|
||||
int index;
|
||||
c11__lower_bound(KV, self->data, self->count, key, partial_less, &index);
|
||||
if(index != self->count){
|
||||
c11__lower_bound(KV, self->data, self->length, key, partial_less, &index);
|
||||
if(index != self->length) {
|
||||
KV* it = c11__at(KV, self, index);
|
||||
if(equal(it->key, key)){
|
||||
if(equal(it->key, key)) {
|
||||
c11_vector__erase(KV, self, index);
|
||||
return true;
|
||||
}
|
||||
@ -117,9 +113,7 @@ bool METHOD(del)(NAME* self, K key) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void METHOD(clear)(NAME* self) {
|
||||
c11_vector__clear(self);
|
||||
}
|
||||
void METHOD(clear)(NAME* self) { c11_vector__clear(self); }
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@ -33,16 +33,16 @@ static bool merge(char* a,
|
||||
}
|
||||
|
||||
bool c11__stable_sort(void* ptr_,
|
||||
int count,
|
||||
int length,
|
||||
int elem_size,
|
||||
int (*f_lt)(const void* a, const void* b, void* extra),
|
||||
void* extra) {
|
||||
// merge sort
|
||||
char *ptr = ptr_, *tmp = malloc(count * elem_size);
|
||||
for(int seg = 1; seg < count; seg *= 2) {
|
||||
for(char* a = ptr; a < ptr + (count - seg) * elem_size; a += 2 * seg * elem_size) {
|
||||
char *ptr = ptr_, *tmp = malloc(length * elem_size);
|
||||
for(int seg = 1; seg < length; seg *= 2) {
|
||||
for(char* a = ptr; a < ptr + (length - seg) * elem_size; a += 2 * seg * elem_size) {
|
||||
char *b = a + seg * elem_size, *a_end = b, *b_end = b + seg * elem_size;
|
||||
if(b_end > ptr + count * elem_size) b_end = ptr + count * elem_size;
|
||||
if(b_end > ptr + length * elem_size) b_end = ptr + length * elem_size;
|
||||
bool ok = merge(a, a_end, b, b_end, tmp, elem_size, f_lt, extra);
|
||||
if(!ok) {
|
||||
free(tmp);
|
||||
|
||||
@ -13,13 +13,13 @@ typedef struct LinkedListNode {
|
||||
} LinkedListNode;
|
||||
|
||||
typedef struct LinkedList {
|
||||
int count;
|
||||
int length;
|
||||
LinkedListNode head;
|
||||
LinkedListNode tail;
|
||||
} LinkedList;
|
||||
|
||||
static void LinkedList__ctor(LinkedList* self) {
|
||||
self->count = 0;
|
||||
self->length = 0;
|
||||
self->head.prev = NULL;
|
||||
self->head.next = &self->tail;
|
||||
self->tail.prev = &self->head;
|
||||
@ -31,7 +31,7 @@ static void LinkedList__push_back(LinkedList* self, LinkedListNode* node) {
|
||||
node->next = &self->tail;
|
||||
self->tail.prev->next = node;
|
||||
self->tail.prev = node;
|
||||
self->count++;
|
||||
self->length++;
|
||||
}
|
||||
|
||||
static void LinkedList__push_front(LinkedList* self, LinkedListNode* node) {
|
||||
@ -39,25 +39,25 @@ static void LinkedList__push_front(LinkedList* self, LinkedListNode* node) {
|
||||
node->next = self->head.next;
|
||||
self->head.next->prev = node;
|
||||
self->head.next = node;
|
||||
self->count++;
|
||||
self->length++;
|
||||
}
|
||||
|
||||
static void LinkedList__pop_back(LinkedList* self) {
|
||||
assert(self->count > 0);
|
||||
assert(self->length > 0);
|
||||
self->tail.prev->prev->next = &self->tail;
|
||||
self->tail.prev = self->tail.prev->prev;
|
||||
self->count--;
|
||||
self->length--;
|
||||
}
|
||||
|
||||
static LinkedListNode* LinkedList__back(LinkedList* self) {
|
||||
assert(self->count > 0);
|
||||
assert(self->length > 0);
|
||||
return self->tail.prev;
|
||||
}
|
||||
|
||||
static void LinkedList__erase(LinkedList* self, LinkedListNode* node) {
|
||||
node->prev->next = node->next;
|
||||
node->next->prev = node->prev;
|
||||
self->count--;
|
||||
self->length--;
|
||||
}
|
||||
|
||||
#define LinkedList__apply(self, __STATEMENTS__) \
|
||||
@ -135,7 +135,7 @@ static void MemoryPool__ctor(MemoryPool* self) {
|
||||
|
||||
static void* MemoryPool__alloc(MemoryPool* self) {
|
||||
MemoryPoolArena* arena;
|
||||
if(self->_arenas.count == 0){
|
||||
if(self->_arenas.length == 0){
|
||||
arena = malloc(sizeof(MemoryPoolArena));
|
||||
MemoryPoolArena__ctor(arena);
|
||||
LinkedList__push_back(&self->_arenas, (LinkedListNode*)arena);
|
||||
@ -164,7 +164,7 @@ static void MemoryPool__dealloc(MemoryPool* self, void* p) {
|
||||
|
||||
static void MemoryPool__shrink_to_fit(MemoryPool* self) {
|
||||
const int MIN_ARENA_COUNT = PK_GC_MIN_THRESHOLD * 100 / (kPoolObjectArenaSize);
|
||||
if(self->_arenas.count < MIN_ARENA_COUNT) return;
|
||||
if(self->_arenas.length < MIN_ARENA_COUNT) return;
|
||||
LinkedList__apply(&self->_arenas,
|
||||
MemoryPoolArena* arena = (MemoryPoolArena*)node;
|
||||
if(MemoryPoolArena__full(arena)) {
|
||||
@ -301,8 +301,8 @@ void Pools_debug_info(char* buffer, int size) {
|
||||
);
|
||||
buffer += n; size -= n;
|
||||
// PoolObject
|
||||
int empty_arenas = PoolObject._empty_arenas.count;
|
||||
int arenas = PoolObject._arenas.count;
|
||||
int empty_arenas = PoolObject._empty_arenas.length;
|
||||
int arenas = PoolObject._arenas.length;
|
||||
// print empty arenas count
|
||||
n = snprintf(
|
||||
buffer, size, "PoolObject: %d empty arenas, %d arenas\n",
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
void c11_sbuf__ctor(c11_sbuf* self) {
|
||||
c11_vector__ctor(&self->data, sizeof(char));
|
||||
c11_vector__reserve(&self->data, sizeof(c11_string) + 100);
|
||||
self->data.count = sizeof(c11_string);
|
||||
self->data.length = sizeof(c11_string);
|
||||
}
|
||||
|
||||
void c11_sbuf__dtor(c11_sbuf* self) { c11_vector__dtor(&self->data); }
|
||||
@ -28,18 +28,18 @@ void c11_sbuf__write_pad(c11_sbuf* self, int count, char pad) {
|
||||
|
||||
void c11_sbuf__write_int(c11_sbuf* self, int i) {
|
||||
// len('-2147483648') == 11
|
||||
c11_vector__reserve(&self->data, self->data.count + 11 + 1);
|
||||
char* p = (char*)self->data.data + self->data.count;
|
||||
c11_vector__reserve(&self->data, self->data.length + 11 + 1);
|
||||
char* p = (char*)self->data.data + self->data.length;
|
||||
int n = snprintf(p, 11 + 1, "%d", i);
|
||||
self->data.count += n;
|
||||
self->data.length += n;
|
||||
}
|
||||
|
||||
void c11_sbuf__write_i64(c11_sbuf* self, int64_t val) {
|
||||
// len('-9223372036854775808') == 20
|
||||
c11_vector__reserve(&self->data, self->data.count + 20 + 1);
|
||||
char* p = (char*)self->data.data + self->data.count;
|
||||
c11_vector__reserve(&self->data, self->data.length + 20 + 1);
|
||||
char* p = (char*)self->data.data + self->data.length;
|
||||
int n = snprintf(p, 20 + 1, "%lld", (long long)val);
|
||||
self->data.count += n;
|
||||
self->data.length += n;
|
||||
}
|
||||
|
||||
void c11_sbuf__write_f64(c11_sbuf* self, double val, int precision) {
|
||||
@ -143,7 +143,7 @@ c11_string* c11_sbuf__submit(c11_sbuf* self) {
|
||||
c11_vector__push(char, &self->data, '\0');
|
||||
c11_array arr = c11_vector__submit(&self->data);
|
||||
c11_string* retval = arr.data;
|
||||
retval->size = arr.count - sizeof(c11_string) - 1;
|
||||
retval->size = arr.length - sizeof(c11_string) - 1;
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
@ -12,19 +12,20 @@ static c11_vector /*T=char* */ _r_interned;
|
||||
|
||||
void py_Name__initialize() {
|
||||
c11_smallmap_s2n__ctor(&_interned);
|
||||
for(int i = 0; i < _r_interned.count; i++) {
|
||||
for(int i = 0; i < _r_interned.length; i++) {
|
||||
free(c11__at(char*, &_r_interned, i));
|
||||
}
|
||||
c11_vector__ctor(&_r_interned, sizeof(c11_sv));
|
||||
|
||||
#define MAGIC_METHOD(x) if(x != py_name(#x)) abort();
|
||||
#define MAGIC_METHOD(x) \
|
||||
if(x != py_name(#x)) abort();
|
||||
#include "pocketpy/xmacros/magics.h"
|
||||
#undef MAGIC_METHOD
|
||||
}
|
||||
|
||||
void py_Name__finalize() {
|
||||
// free all char*
|
||||
for(int i = 0; i < _r_interned.count; i++) {
|
||||
for(int i = 0; i < _r_interned.length; i++) {
|
||||
free(c11__getitem(char*, &_r_interned, i));
|
||||
}
|
||||
c11_smallmap_s2n__dtor(&_interned);
|
||||
@ -38,27 +39,26 @@ py_Name py_namev(c11_sv name) {
|
||||
uint16_t index = c11_smallmap_s2n__get(&_interned, name, 0);
|
||||
if(index != 0) return index;
|
||||
// generate new index
|
||||
if(_interned.count > 65530) c11__abort("py_Name index overflow");
|
||||
if(_interned.length > 65530) c11__abort("py_Name index overflow");
|
||||
// NOTE: we must allocate the string in the heap so iterators are not invalidated
|
||||
char* p = malloc(name.size + 1);
|
||||
memcpy(p, name.data, name.size);
|
||||
p[name.size] = '\0';
|
||||
c11_vector__push(char*, &_r_interned, p);
|
||||
index = _r_interned.count; // 1-based
|
||||
index = _r_interned.length; // 1-based
|
||||
// save to _interned
|
||||
c11_smallmap_s2n__set(&_interned, (c11_sv){p, name.size}, index);
|
||||
assert(_interned.count == _r_interned.count);
|
||||
assert(_interned.length == _r_interned.length);
|
||||
return index;
|
||||
}
|
||||
|
||||
const char* py_name2str(py_Name index) {
|
||||
assert(index > 0 && index <= _interned.count);
|
||||
assert(index > 0 && index <= _interned.length);
|
||||
return c11__getitem(char*, &_r_interned, index - 1);
|
||||
}
|
||||
|
||||
c11_sv py_name2sv(py_Name index) {
|
||||
assert(index > 0 && index <= _interned.count);
|
||||
assert(index > 0 && index <= _interned.length);
|
||||
const char* p = py_name2str(index);
|
||||
return (c11_sv){p, strlen(p)};
|
||||
}
|
||||
|
||||
|
||||
@ -3,28 +3,28 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
void c11_array__ctor(c11_array* self, int elem_size, int count){
|
||||
self->data = malloc(elem_size * count);
|
||||
self->count = count;
|
||||
void c11_array__ctor(c11_array* self, int elem_size, int length){
|
||||
self->data = malloc(elem_size * length);
|
||||
self->length = length;
|
||||
self->elem_size = elem_size;
|
||||
}
|
||||
|
||||
void c11_array__dtor(c11_array* self){
|
||||
free(self->data);
|
||||
self->data = NULL;
|
||||
self->count = 0;
|
||||
self->length = 0;
|
||||
}
|
||||
|
||||
c11_array c11_array__copy(const c11_array* self){
|
||||
c11_array retval;
|
||||
c11_array__ctor(&retval, self->elem_size, self->count);
|
||||
memcpy(retval.data, self->data, self->elem_size * self->count);
|
||||
c11_array__ctor(&retval, self->elem_size, self->length);
|
||||
memcpy(retval.data, self->data, self->elem_size * self->length);
|
||||
return retval;
|
||||
}
|
||||
|
||||
void c11_vector__ctor(c11_vector* self, int elem_size){
|
||||
self->data = NULL;
|
||||
self->count = 0;
|
||||
self->length = 0;
|
||||
self->capacity = 0;
|
||||
self->elem_size = elem_size;
|
||||
}
|
||||
@ -32,7 +32,7 @@ void c11_vector__ctor(c11_vector* self, int elem_size){
|
||||
void c11_vector__dtor(c11_vector* self){
|
||||
if(self->data) free(self->data);
|
||||
self->data = NULL;
|
||||
self->count = 0;
|
||||
self->length = 0;
|
||||
self->capacity = 0;
|
||||
}
|
||||
|
||||
@ -40,8 +40,8 @@ c11_vector c11_vector__copy(const c11_vector* self){
|
||||
c11_vector retval;
|
||||
c11_vector__ctor(&retval, self->elem_size);
|
||||
c11_vector__reserve(&retval, self->capacity);
|
||||
memcpy(retval.data, self->data, self->elem_size * self->count);
|
||||
retval.count = self->count;
|
||||
memcpy(retval.data, self->data, self->elem_size * self->length);
|
||||
retval.length = self->length;
|
||||
return retval;
|
||||
}
|
||||
|
||||
@ -53,18 +53,18 @@ void c11_vector__reserve(c11_vector* self, int capacity){
|
||||
}
|
||||
|
||||
void c11_vector__clear(c11_vector* self){
|
||||
self->count = 0;
|
||||
self->length = 0;
|
||||
}
|
||||
|
||||
void* c11_vector__emplace(c11_vector* self){
|
||||
if(self->count == self->capacity) c11_vector__reserve(self, self->capacity*2);
|
||||
void* p = (char*)self->data + self->elem_size * self->count;
|
||||
self->count++;
|
||||
if(self->length == self->capacity) c11_vector__reserve(self, self->capacity*2);
|
||||
void* p = (char*)self->data + self->elem_size * self->length;
|
||||
self->length++;
|
||||
return p;
|
||||
}
|
||||
|
||||
bool c11_vector__contains(const c11_vector *self, void *elem){
|
||||
for(int i = 0; i < self->count; i++){
|
||||
for(int i = 0; i < self->length; i++){
|
||||
void* p = (char*)self->data + self->elem_size * i;
|
||||
if(memcmp(p, elem, self->elem_size) == 0) return true;
|
||||
}
|
||||
@ -74,11 +74,11 @@ bool c11_vector__contains(const c11_vector *self, void *elem){
|
||||
c11_array c11_vector__submit(c11_vector* self){
|
||||
c11_array retval = {
|
||||
.data = self->data,
|
||||
.count = self->count,
|
||||
.length = self->length,
|
||||
.elem_size = self->elem_size
|
||||
};
|
||||
self->data = NULL;
|
||||
self->count = 0;
|
||||
self->length = 0;
|
||||
self->capacity = 0;
|
||||
return retval;
|
||||
}
|
||||
|
||||
@ -454,11 +454,11 @@ typedef struct SequenceExpr {
|
||||
|
||||
static void SequenceExpr__emit_(Expr* self_, Ctx* ctx) {
|
||||
SequenceExpr* self = (SequenceExpr*)self_;
|
||||
for(int i = 0; i < self->items.count; i++) {
|
||||
for(int i = 0; i < self->items.length; i++) {
|
||||
Expr* item = c11__getitem(Expr*, &self->items, i);
|
||||
vtemit_(item, ctx);
|
||||
}
|
||||
Ctx__emit_(ctx, self->opcode, self->items.count, self->line);
|
||||
Ctx__emit_(ctx, self->opcode, self->items.length, self->line);
|
||||
}
|
||||
|
||||
void SequenceExpr__dtor(Expr* self_) {
|
||||
@ -472,7 +472,7 @@ bool TupleExpr__emit_store(Expr* self_, Ctx* ctx) {
|
||||
// TOS is an iterable
|
||||
// items may contain StarredExpr, we should check it
|
||||
int starred_i = -1;
|
||||
for(int i = 0; i < self->items.count; i++) {
|
||||
for(int i = 0; i < self->items.length; i++) {
|
||||
Expr* e = c11__getitem(Expr*, &self->items, i);
|
||||
if(e->vt->is_starred) {
|
||||
if(((StarredExpr*)e)->level > 0) {
|
||||
@ -485,24 +485,24 @@ bool TupleExpr__emit_store(Expr* self_, Ctx* ctx) {
|
||||
}
|
||||
|
||||
if(starred_i == -1) {
|
||||
Bytecode* prev = c11__at(Bytecode, &ctx->co->codes, ctx->co->codes.count - 1);
|
||||
if(prev->op == OP_BUILD_TUPLE && prev->arg == self->items.count) {
|
||||
Bytecode* prev = c11__at(Bytecode, &ctx->co->codes, ctx->co->codes.length - 1);
|
||||
if(prev->op == OP_BUILD_TUPLE && prev->arg == self->items.length) {
|
||||
// build tuple and unpack it is meaningless
|
||||
Ctx__revert_last_emit_(ctx);
|
||||
} else {
|
||||
Ctx__emit_(ctx, OP_UNPACK_SEQUENCE, self->items.count, self->line);
|
||||
Ctx__emit_(ctx, OP_UNPACK_SEQUENCE, self->items.length, self->line);
|
||||
}
|
||||
} else {
|
||||
// starred assignment target must be in a tuple
|
||||
if(self->items.count == 1) return false;
|
||||
if(self->items.length == 1) return false;
|
||||
// starred assignment target must be the last one (differ from cpython)
|
||||
if(starred_i != self->items.count - 1) return false;
|
||||
if(starred_i != self->items.length - 1) return false;
|
||||
// a,*b = [1,2,3]
|
||||
// stack is [1,2,3] -> [1,[2,3]]
|
||||
Ctx__emit_(ctx, OP_UNPACK_EX, self->items.count - 1, self->line);
|
||||
Ctx__emit_(ctx, OP_UNPACK_EX, self->items.length - 1, self->line);
|
||||
}
|
||||
// do reverse emit
|
||||
for(int i = self->items.count - 1; i >= 0; i--) {
|
||||
for(int i = self->items.length - 1; i >= 0; i--) {
|
||||
Expr* e = c11__getitem(Expr*, &self->items, i);
|
||||
bool ok = vtemit_store(e, ctx);
|
||||
if(!ok) return false;
|
||||
@ -822,7 +822,7 @@ static void BinaryExpr__emit_(Expr* self_, Ctx* ctx) {
|
||||
|
||||
Ctx__emit_(ctx, opcode, arg, self->line);
|
||||
|
||||
for(int i = 0; i < jmps.count; i++) {
|
||||
for(int i = 0; i < jmps.length; i++) {
|
||||
Ctx__patch_jump(ctx, c11__getitem(int, &jmps, i));
|
||||
}
|
||||
c11_vector__dtor(&jmps);
|
||||
@ -1069,8 +1069,8 @@ void CallExpr__emit_(Expr* self_, Ctx* ctx) {
|
||||
Ctx__emit_int(ctx, e->key, self->line);
|
||||
vtemit_(e->val, ctx);
|
||||
}
|
||||
int KWARGC = self->kwargs.count;
|
||||
int ARGC = self->args.count;
|
||||
int KWARGC = self->kwargs.length;
|
||||
int ARGC = self->args.length;
|
||||
assert(KWARGC < 256 && ARGC < 256);
|
||||
Ctx__emit_(ctx, opcode, (KWARGC << 8) | ARGC, self->line);
|
||||
}
|
||||
@ -1101,7 +1101,7 @@ static void Ctx__ctor(Ctx* self, CodeObject* co, FuncDecl* func, int level) {
|
||||
|
||||
static void Ctx__dtor(Ctx* self) {
|
||||
// clean the expr stack
|
||||
for(int i = 0; i < self->s_expr.count; i++) {
|
||||
for(int i = 0; i < self->s_expr.length; i++) {
|
||||
vtdelete(c11__getitem(Expr*, &self->s_expr, i));
|
||||
}
|
||||
c11_vector__dtor(&self->s_expr);
|
||||
@ -1123,16 +1123,16 @@ static int Ctx__get_loop(Ctx* self) {
|
||||
}
|
||||
|
||||
static CodeBlock* Ctx__enter_block(Ctx* self, CodeBlockType type) {
|
||||
CodeBlock block = {type, self->curr_iblock, self->co->codes.count, -1, -1};
|
||||
CodeBlock block = {type, self->curr_iblock, self->co->codes.length, -1, -1};
|
||||
c11_vector__push(CodeBlock, &self->co->blocks, block);
|
||||
self->curr_iblock = self->co->blocks.count - 1;
|
||||
self->curr_iblock = self->co->blocks.length - 1;
|
||||
return c11__at(CodeBlock, &self->co->blocks, self->curr_iblock);
|
||||
}
|
||||
|
||||
static void Ctx__exit_block(Ctx* self) {
|
||||
CodeBlock* block = c11__at(CodeBlock, &self->co->blocks, self->curr_iblock);
|
||||
CodeBlockType curr_type = block->type;
|
||||
block->end = self->co->codes.count;
|
||||
block->end = self->co->codes.length;
|
||||
self->curr_iblock = block->parent;
|
||||
assert(self->curr_iblock >= 0);
|
||||
if(curr_type == CodeBlockType_FOR_LOOP) {
|
||||
@ -1161,7 +1161,7 @@ static int Ctx__emit_virtual(Ctx* self, Opcode opcode, uint16_t arg, int line, b
|
||||
BytecodeEx bcx = {line, is_virtual, self->curr_iblock};
|
||||
c11_vector__push(Bytecode, &self->co->codes, bc);
|
||||
c11_vector__push(BytecodeEx, &self->co->codes_ex, bcx);
|
||||
int i = self->co->codes.count - 1;
|
||||
int i = self->co->codes.length - 1;
|
||||
BytecodeEx* codes_ex = (BytecodeEx*)self->co->codes_ex.data;
|
||||
if(line == BC_KEEPLINE) { codes_ex[i].lineno = i >= 1 ? codes_ex[i - 1].lineno : 1; }
|
||||
return i;
|
||||
@ -1188,14 +1188,14 @@ static int Ctx__emit_int(Ctx* self, int64_t value, int line) {
|
||||
|
||||
static void Ctx__patch_jump(Ctx* self, int index) {
|
||||
Bytecode* co_codes = (Bytecode*)self->co->codes.data;
|
||||
int target = self->co->codes.count;
|
||||
int target = self->co->codes.length;
|
||||
Bytecode__set_signed_arg(&co_codes[index], target - index);
|
||||
}
|
||||
|
||||
static bool Ctx__add_label(Ctx* self, py_Name name) {
|
||||
bool ok = c11_smallmap_n2i__contains(&self->co->labels, name);
|
||||
if(ok) return false;
|
||||
c11_smallmap_n2i__set(&self->co->labels, name, self->co->codes.count);
|
||||
c11_smallmap_n2i__set(&self->co->labels, name, self->co->codes.length);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1212,7 +1212,7 @@ static int Ctx__add_const_string(Ctx* self, c11_sv key) {
|
||||
py_TValue tmp;
|
||||
py_newstrn(&tmp, key.data, key.size);
|
||||
c11_vector__push(py_TValue, &self->co->consts, tmp);
|
||||
int index = self->co->consts.count - 1;
|
||||
int index = self->co->consts.length - 1;
|
||||
c11_smallmap_s2n__set(&self->co_consts_string_dedup_map,
|
||||
c11_string__sv(PyObject__userdata(tmp._obj)),
|
||||
index);
|
||||
@ -1223,7 +1223,7 @@ static int Ctx__add_const_string(Ctx* self, c11_sv key) {
|
||||
static int Ctx__add_const(Ctx* self, py_Ref v) {
|
||||
assert(v->type != tp_str);
|
||||
c11_vector__push(py_TValue, &self->co->consts, *v);
|
||||
return self->co->consts.count - 1;
|
||||
return self->co->consts.length - 1;
|
||||
}
|
||||
|
||||
static void Ctx__emit_store_name(Ctx* self, NameScope scope, py_Name name, int line) {
|
||||
@ -1237,7 +1237,7 @@ static void Ctx__emit_store_name(Ctx* self, NameScope scope, py_Name name, int l
|
||||
|
||||
// emit top -> pop -> delete
|
||||
static void Ctx__s_emit_top(Ctx* self) {
|
||||
assert(self->s_expr.count);
|
||||
assert(self->s_expr.length);
|
||||
Expr* top = c11_vector__back(Expr*, &self->s_expr);
|
||||
vtemit_(top, self);
|
||||
vtdelete(top);
|
||||
@ -1249,16 +1249,16 @@ static void Ctx__s_push(Ctx* self, Expr* expr) { c11_vector__push(Expr*, &self->
|
||||
|
||||
// top
|
||||
static Expr* Ctx__s_top(Ctx* self) {
|
||||
assert(self->s_expr.count);
|
||||
assert(self->s_expr.length);
|
||||
return c11_vector__back(Expr*, &self->s_expr);
|
||||
}
|
||||
|
||||
// size
|
||||
static int Ctx__s_size(Ctx* self) { return self->s_expr.count; }
|
||||
static int Ctx__s_size(Ctx* self) { return self->s_expr.length; }
|
||||
|
||||
// pop -> delete
|
||||
static void Ctx__s_pop(Ctx* self) {
|
||||
assert(self->s_expr.count);
|
||||
assert(self->s_expr.length);
|
||||
Expr* top = c11_vector__back(Expr*, &self->s_expr);
|
||||
vtdelete(top);
|
||||
c11_vector__pop(&self->s_expr);
|
||||
@ -1266,7 +1266,7 @@ static void Ctx__s_pop(Ctx* self) {
|
||||
|
||||
// pop move
|
||||
static Expr* Ctx__s_popx(Ctx* self) {
|
||||
assert(self->s_expr.count);
|
||||
assert(self->s_expr.length);
|
||||
Expr* top = c11_vector__back(Expr*, &self->s_expr);
|
||||
c11_vector__pop(&self->s_expr);
|
||||
return top;
|
||||
@ -1329,7 +1329,7 @@ static void Compiler__dtor(Compiler* self) {
|
||||
if((err = B)) return err
|
||||
|
||||
static NameScope name_scope(Compiler* self) {
|
||||
NameScope s = self->contexts.count > 1 ? NAME_LOCAL : NAME_GLOBAL;
|
||||
NameScope s = self->contexts.length > 1 ? NAME_LOCAL : NAME_GLOBAL;
|
||||
if(self->src->is_dynamic && s == NAME_GLOBAL) s = NAME_GLOBAL_UNKNOWN;
|
||||
return s;
|
||||
}
|
||||
@ -1338,7 +1338,7 @@ Error* SyntaxError(Compiler* self, const char* fmt, ...) {
|
||||
Error* err = malloc(sizeof(Error));
|
||||
err->src = self->src;
|
||||
PK_INCREF(self->src);
|
||||
Token* t = self->i == self->tokens.count ? prev() : curr();
|
||||
Token* t = self->i == self->tokens.length ? prev() : curr();
|
||||
err->lineno = t->line;
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
@ -1451,7 +1451,7 @@ static Error* EXPR_VARS(Compiler* self) {
|
||||
static void push_global_context(Compiler* self, CodeObject* co) {
|
||||
co->start_line = self->i == 0 ? 1 : prev()->line;
|
||||
Ctx* ctx = c11_vector__emplace(&self->contexts);
|
||||
Ctx__ctor(ctx, co, NULL, self->contexts.count);
|
||||
Ctx__ctor(ctx, co, NULL, self->contexts.length);
|
||||
}
|
||||
|
||||
static Error* pop_context(Compiler* self) {
|
||||
@ -1473,11 +1473,11 @@ static Error* pop_context(Compiler* self) {
|
||||
if(co->nlocals > PK_MAX_CO_VARNAMES) {
|
||||
return SyntaxError(self, "maximum number of local variables exceeded");
|
||||
}
|
||||
if(co->consts.count > 65530) {
|
||||
if(co->consts.length > 65530) {
|
||||
return SyntaxError(self, "maximum number of constants exceeded");
|
||||
}
|
||||
// pre-compute LOOP_BREAK and LOOP_CONTINUE
|
||||
for(int i = 0; i < codes->count; i++) {
|
||||
for(int i = 0; i < codes->length; i++) {
|
||||
Bytecode* bc = c11__at(Bytecode, codes, i);
|
||||
if(bc->op == OP_LOOP_CONTINUE) {
|
||||
CodeBlock* block = c11__at(CodeBlock, &ctx()->co->blocks, bc->arg);
|
||||
@ -1492,7 +1492,7 @@ static Error* pop_context(Compiler* self) {
|
||||
if(func) {
|
||||
// check generator
|
||||
Bytecode* codes = func->code.codes.data;
|
||||
int codes_length = func->code.codes.count;
|
||||
int codes_length = func->code.codes.length;
|
||||
|
||||
for(int i = 0; i < codes_length; i++) {
|
||||
if(codes[i].op == OP_YIELD_VALUE) {
|
||||
@ -1510,7 +1510,7 @@ static Error* pop_context(Compiler* self) {
|
||||
}
|
||||
if(func->type == FuncType_UNSET) {
|
||||
bool is_simple = true;
|
||||
if(func->kwargs.count > 0) is_simple = false;
|
||||
if(func->kwargs.length > 0) is_simple = false;
|
||||
if(func->starred_arg >= 0) is_simple = false;
|
||||
if(func->starred_kwarg >= 0) is_simple = false;
|
||||
|
||||
@ -1855,7 +1855,7 @@ static Error* exprCall(Compiler* self) {
|
||||
c11_vector__push(CallExprKwArg, &e->kwargs, kw);
|
||||
} else {
|
||||
// positional argument
|
||||
if(e->kwargs.count > 0) {
|
||||
if(e->kwargs.length > 0) {
|
||||
return SyntaxError(self, "positional argument follows keyword argument");
|
||||
}
|
||||
c11_vector__push(Expr*, &e->args, Ctx__s_popx(ctx()));
|
||||
@ -1994,7 +1994,7 @@ static Error* compile_while_loop(Compiler* self) {
|
||||
// optional else clause
|
||||
if(match(TK_ELSE)) {
|
||||
check(compile_block_body(self, compile_stmt));
|
||||
block->end2 = ctx()->co->codes.count;
|
||||
block->end2 = ctx()->co->codes.length;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@ -2021,7 +2021,7 @@ static Error* compile_for_loop(Compiler* self) {
|
||||
// optional else clause
|
||||
if(match(TK_ELSE)) {
|
||||
check(compile_block_body(self, compile_stmt));
|
||||
block->end2 = ctx()->co->codes.count;
|
||||
block->end2 = ctx()->co->codes.length;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@ -2097,10 +2097,10 @@ static FuncDecl_ push_f_context(Compiler* self, c11_sv name, int* out_index) {
|
||||
// add_func_decl
|
||||
Ctx* top_ctx = ctx();
|
||||
c11_vector__push(FuncDecl_, &top_ctx->co->func_decls, decl);
|
||||
*out_index = top_ctx->co->func_decls.count - 1;
|
||||
*out_index = top_ctx->co->func_decls.length - 1;
|
||||
// push new context
|
||||
top_ctx = c11_vector__emplace(&self->contexts);
|
||||
Ctx__ctor(top_ctx, &decl->code, decl, self->contexts.count);
|
||||
Ctx__ctor(top_ctx, &decl->code, decl, self->contexts.length);
|
||||
return decl;
|
||||
}
|
||||
|
||||
@ -2214,7 +2214,7 @@ static Error* compile_function(Compiler* self, int decorators) {
|
||||
check(compile_block_body(self, compile_stmt));
|
||||
check(pop_context(self));
|
||||
|
||||
if(decl->code.codes.count >= 2) {
|
||||
if(decl->code.codes.length >= 2) {
|
||||
Bytecode* codes = (Bytecode*)decl->code.codes.data;
|
||||
|
||||
if(codes[0].op == OP_LOAD_CONST && codes[1].op == OP_POP_TOP) {
|
||||
@ -2463,14 +2463,15 @@ static Error* compile_stmt(Compiler* self) {
|
||||
consume_end_stmt();
|
||||
break;
|
||||
case TK_YIELD:
|
||||
if(self->contexts.count <= 1) return SyntaxError(self, "'yield' outside function");
|
||||
if(self->contexts.length <= 1) return SyntaxError(self, "'yield' outside function");
|
||||
check(EXPR_TUPLE(self));
|
||||
Ctx__s_emit_top(ctx());
|
||||
Ctx__emit_(ctx(), OP_YIELD_VALUE, BC_NOARG, kw_line);
|
||||
consume_end_stmt();
|
||||
break;
|
||||
case TK_YIELD_FROM:
|
||||
if(self->contexts.count <= 1) return SyntaxError(self, "'yield from' outside function");
|
||||
if(self->contexts.length <= 1)
|
||||
return SyntaxError(self, "'yield from' outside function");
|
||||
check(EXPR_TUPLE(self));
|
||||
Ctx__s_emit_top(ctx());
|
||||
Ctx__emit_(ctx(), OP_GET_ITER, BC_NOARG, kw_line);
|
||||
@ -2482,7 +2483,7 @@ static Error* compile_stmt(Compiler* self) {
|
||||
consume_end_stmt();
|
||||
break;
|
||||
case TK_RETURN:
|
||||
if(self->contexts.count <= 1) return SyntaxError(self, "'return' outside function");
|
||||
if(self->contexts.length <= 1) return SyntaxError(self, "'return' outside function");
|
||||
if(match_end_stmt(self)) {
|
||||
Ctx__emit_(ctx(), OP_RETURN_VALUE, 1, kw_line);
|
||||
} else {
|
||||
@ -2672,7 +2673,7 @@ Error* pk_compile(SourceData_ src, CodeObject* out) {
|
||||
#if 0
|
||||
Token* data = (Token*)tokens.data;
|
||||
printf("%s\n", src->filename->data);
|
||||
for(int i = 0; i < tokens.count; i++) {
|
||||
for(int i = 0; i < tokens.length; i++) {
|
||||
Token* t = data + i;
|
||||
c11_string* tmp = c11_string__new2(t->start, t->length);
|
||||
if(t->value.index == TokenValue_STR) {
|
||||
|
||||
@ -125,7 +125,7 @@ static void add_token_with_value(Lexer* self, TokenIndex type, TokenValue value)
|
||||
self->brackets_level,
|
||||
value};
|
||||
// handle "not in", "is not", "yield from"
|
||||
if(self->nexts.count > 0) {
|
||||
if(self->nexts.length > 0) {
|
||||
Token* back = &c11_vector__back(Token, &self->nexts);
|
||||
if(back->type == TK_NOT_KW && type == TK_IN) {
|
||||
back->type = TK_NOT_IN;
|
||||
@ -336,12 +336,12 @@ static Error* _eat_string(Lexer* self, c11_sbuf* buff, char quote, enum StringTy
|
||||
|
||||
// submit {expr} tokens
|
||||
bool eof = false;
|
||||
int token_count = self->nexts.count;
|
||||
int token_count = self->nexts.length;
|
||||
while(!eof) {
|
||||
Error* err = lex_one_token(self, &eof, true);
|
||||
if(err) return err;
|
||||
}
|
||||
if(self->nexts.count == token_count) {
|
||||
if(self->nexts.length == token_count) {
|
||||
// f'{}' is not allowed
|
||||
return SyntaxError(self, "f-string: empty expression not allowed");
|
||||
}
|
||||
@ -353,7 +353,7 @@ static Error* _eat_string(Lexer* self, c11_sbuf* buff, char quote, enum StringTy
|
||||
} else {
|
||||
return SyntaxError(self, "f-string: single '}' is not allowed");
|
||||
}
|
||||
}else{
|
||||
} else {
|
||||
c11_sbuf__write_char(buff, c);
|
||||
}
|
||||
} else {
|
||||
@ -600,7 +600,7 @@ static Error* lex_one_token(Lexer* self, bool* eof, bool is_fstring) {
|
||||
if(is_fstring) return SyntaxError(self, "unterminated f-string expression");
|
||||
|
||||
self->token_start = self->curr_char;
|
||||
while(self->indents.count > 1) {
|
||||
while(self->indents.length > 1) {
|
||||
c11_vector__pop(&self->indents);
|
||||
add_token(self, TK_DEDENT);
|
||||
return NULL;
|
||||
@ -637,7 +637,7 @@ Error* Lexer__process(SourceData_ src, TokenArray* out_tokens) {
|
||||
|
||||
void TokenArray__dtor(TokenArray* self) {
|
||||
Token* data = self->data;
|
||||
for(int i = 0; i < self->count; i++) {
|
||||
for(int i = 0; i < self->length; i++) {
|
||||
if(data[i].value.index == TokenValue_STR) { c11_string__delete(data[i].value._str); }
|
||||
}
|
||||
c11_array__dtor(self);
|
||||
|
||||
@ -161,48 +161,13 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
DISPATCH();
|
||||
}
|
||||
case OP_LOAD_NAME: {
|
||||
assert(frame->is_dynamic);
|
||||
py_Name name = byte.arg;
|
||||
py_TValue* tmp;
|
||||
if(!frame->is_dynamic) {
|
||||
// locals
|
||||
tmp = Frame__f_locals_try_get(frame, name);
|
||||
if(tmp != NULL) {
|
||||
if(py_isnil(tmp)) {
|
||||
UnboundLocalError(name);
|
||||
goto __ERROR;
|
||||
}
|
||||
PUSH(tmp);
|
||||
DISPATCH();
|
||||
}
|
||||
// closure
|
||||
tmp = Frame__f_closure_try_get(frame, name);
|
||||
if(tmp != NULL) {
|
||||
PUSH(tmp);
|
||||
DISPATCH();
|
||||
}
|
||||
// globals
|
||||
tmp = py_getdict(frame->module, name);
|
||||
if(tmp != NULL) {
|
||||
PUSH(tmp);
|
||||
DISPATCH();
|
||||
}
|
||||
} else {
|
||||
py_newstr(SP()++, py_name2str(name));
|
||||
// locals
|
||||
if(!py_isnone(&frame->p0[1])) {
|
||||
if(py_getitem(&frame->p0[1], TOP())) {
|
||||
py_assign(TOP(), py_retval());
|
||||
DISPATCH();
|
||||
} else {
|
||||
if(py_matchexc(tp_KeyError)) {
|
||||
py_clearexc(NULL);
|
||||
} else {
|
||||
goto __ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
// globals
|
||||
if(py_getitem(&frame->p0[0], TOP())) {
|
||||
py_newstr(SP()++, py_name2str(name));
|
||||
// locals
|
||||
if(!py_isnone(&frame->p0[1])) {
|
||||
if(py_getitem(&frame->p0[1], TOP())) {
|
||||
py_assign(TOP(), py_retval());
|
||||
DISPATCH();
|
||||
} else {
|
||||
@ -213,6 +178,17 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
}
|
||||
}
|
||||
}
|
||||
// globals
|
||||
if(py_getitem(&frame->p0[0], TOP())) {
|
||||
py_assign(TOP(), py_retval());
|
||||
DISPATCH();
|
||||
} else {
|
||||
if(py_matchexc(tp_KeyError)) {
|
||||
py_clearexc(NULL);
|
||||
} else {
|
||||
goto __ERROR;
|
||||
}
|
||||
}
|
||||
// builtins
|
||||
tmp = py_getdict(&self->builtins, name);
|
||||
if(tmp != NULL) {
|
||||
@ -844,7 +820,7 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for(int i = 0; i < dict->count; i++) {
|
||||
for(int i = 0; i < dict->length; i++) {
|
||||
NameDict_KV* kv = c11__at(NameDict_KV, dict, i);
|
||||
if(!kv->key) continue;
|
||||
c11_sv name = py_name2sv(kv->key);
|
||||
@ -1124,21 +1100,21 @@ static bool stack_format_object(VM* self, c11_sv spec) {
|
||||
py_StackRef val = TOP();
|
||||
if(spec.size == 0) return py_str(val);
|
||||
|
||||
if(spec.data[0] == '!'){
|
||||
if(c11_sv__startswith(spec, (c11_sv){"!r", 2})){
|
||||
if(spec.data[0] == '!') {
|
||||
if(c11_sv__startswith(spec, (c11_sv){"!r", 2})) {
|
||||
spec.data += 2;
|
||||
spec.size -= 2;
|
||||
if(!py_repr(val)) return false;
|
||||
py_assign(val, py_retval());
|
||||
if(spec.size == 0) return true;
|
||||
}else{
|
||||
} else {
|
||||
return ValueError("invalid conversion specifier (only !r is supported)");
|
||||
}
|
||||
}
|
||||
|
||||
assert(spec.size > 0);
|
||||
|
||||
if(spec.data[0] == ':'){
|
||||
|
||||
if(spec.data[0] == ':') {
|
||||
spec.data++;
|
||||
spec.size--;
|
||||
}
|
||||
|
||||
@ -81,7 +81,7 @@ int Frame__prepare_jump_exception_handler(Frame* self, ValueStack* _s) {
|
||||
|
||||
void Frame__prepare_jump_break(Frame* self, ValueStack* _s, int target) {
|
||||
int iblock = Frame__iblock(self);
|
||||
if(target >= self->co->codes.count) {
|
||||
if(target >= self->co->codes.length) {
|
||||
while(iblock >= 0)
|
||||
iblock = Frame__exit_block(self, _s, iblock);
|
||||
} else {
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
#include "pocketpy/common/memorypool.h"
|
||||
#include "pocketpy/objects/base.h"
|
||||
|
||||
void ManagedHeap__ctor(ManagedHeap *self, VM *vm){
|
||||
void ManagedHeap__ctor(ManagedHeap* self, VM* vm) {
|
||||
c11_vector__ctor(&self->no_gc, sizeof(PyObject*));
|
||||
c11_vector__ctor(&self->gen, sizeof(PyObject*));
|
||||
|
||||
@ -13,12 +13,12 @@ void ManagedHeap__ctor(ManagedHeap *self, VM *vm){
|
||||
self->gc_on_delete = NULL;
|
||||
}
|
||||
|
||||
void ManagedHeap__dtor(ManagedHeap *self){
|
||||
for(int i = 0; i < self->gen.count; i++){
|
||||
void ManagedHeap__dtor(ManagedHeap* self) {
|
||||
for(int i = 0; i < self->gen.length; i++) {
|
||||
PyObject* obj = c11__getitem(PyObject*, &self->gen, i);
|
||||
PyObject__delete(obj);
|
||||
}
|
||||
for(int i = 0; i < self->no_gc.count; i++){
|
||||
for(int i = 0; i < self->no_gc.length; i++) {
|
||||
PyObject* obj = c11__getitem(PyObject*, &self->no_gc, i);
|
||||
PyObject__delete(obj);
|
||||
}
|
||||
@ -26,47 +26,43 @@ void ManagedHeap__dtor(ManagedHeap *self){
|
||||
c11_vector__dtor(&self->gen);
|
||||
}
|
||||
|
||||
void ManagedHeap__collect_if_needed(ManagedHeap *self){
|
||||
void ManagedHeap__collect_if_needed(ManagedHeap* self) {
|
||||
if(self->gc_counter < self->gc_threshold) return;
|
||||
self->gc_counter = 0;
|
||||
ManagedHeap__collect(self);
|
||||
self->gc_threshold = self->gen.count * 2;
|
||||
if(self->gc_threshold < PK_GC_MIN_THRESHOLD){
|
||||
self->gc_threshold = PK_GC_MIN_THRESHOLD;
|
||||
}
|
||||
self->gc_threshold = self->gen.length * 2;
|
||||
if(self->gc_threshold < PK_GC_MIN_THRESHOLD) { self->gc_threshold = PK_GC_MIN_THRESHOLD; }
|
||||
}
|
||||
|
||||
int ManagedHeap__collect(ManagedHeap *self){
|
||||
int ManagedHeap__collect(ManagedHeap* self) {
|
||||
ManagedHeap__mark(self);
|
||||
int freed = ManagedHeap__sweep(self);
|
||||
return freed;
|
||||
}
|
||||
|
||||
int ManagedHeap__sweep(ManagedHeap *self){
|
||||
int ManagedHeap__sweep(ManagedHeap* self) {
|
||||
c11_vector alive;
|
||||
c11_vector__ctor(&alive, sizeof(PyObject*));
|
||||
c11_vector__reserve(&alive, self->gen.count / 2);
|
||||
c11_vector__reserve(&alive, self->gen.length / 2);
|
||||
|
||||
for(int i = 0; i < self->gen.count; i++){
|
||||
for(int i = 0; i < self->gen.length; i++) {
|
||||
PyObject* obj = c11__getitem(PyObject*, &self->gen, i);
|
||||
if(obj->gc_marked) {
|
||||
obj->gc_marked = false;
|
||||
c11_vector__push(PyObject*, &alive, obj);
|
||||
} else {
|
||||
if(self->gc_on_delete){
|
||||
self->gc_on_delete(self->vm, obj);
|
||||
}
|
||||
if(self->gc_on_delete) { self->gc_on_delete(self->vm, obj); }
|
||||
PyObject__delete(obj);
|
||||
}
|
||||
}
|
||||
|
||||
// clear _no_gc marked flag
|
||||
for(int i=0; i<self->no_gc.count; i++){
|
||||
for(int i = 0; i < self->no_gc.length; i++) {
|
||||
PyObject* obj = c11__getitem(PyObject*, &self->no_gc, i);
|
||||
obj->gc_marked = false;
|
||||
}
|
||||
|
||||
int freed = self->gen.count - alive.count;
|
||||
int freed = self->gen.length - alive.length;
|
||||
|
||||
// destroy old gen
|
||||
c11_vector__dtor(&self->gen);
|
||||
@ -77,28 +73,28 @@ int ManagedHeap__sweep(ManagedHeap *self){
|
||||
return freed;
|
||||
}
|
||||
|
||||
PyObject* ManagedHeap__new(ManagedHeap *self, py_Type type, int slots, int udsize){
|
||||
PyObject* ManagedHeap__new(ManagedHeap* self, py_Type type, int slots, int udsize) {
|
||||
PyObject* obj = PyObject__new(type, slots, udsize);
|
||||
c11_vector__push(PyObject*, &self->no_gc, obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
PyObject* ManagedHeap__gcnew(ManagedHeap *self, py_Type type, int slots, int udsize){
|
||||
PyObject* ManagedHeap__gcnew(ManagedHeap* self, py_Type type, int slots, int udsize) {
|
||||
PyObject* obj = PyObject__new(type, slots, udsize);
|
||||
c11_vector__push(PyObject*, &self->gen, obj);
|
||||
self->gc_counter++;
|
||||
return obj;
|
||||
}
|
||||
|
||||
PyObject* PyObject__new(py_Type type, int slots, int size){
|
||||
PyObject* PyObject__new(py_Type type, int slots, int size) {
|
||||
assert(slots >= 0 || slots == -1);
|
||||
PyObject* self;
|
||||
// header + slots + udsize
|
||||
size = sizeof(PyObject) + PK_OBJ_SLOTS_SIZE(slots) + size;
|
||||
if(size <= kPoolObjectBlockSize){
|
||||
if(size <= kPoolObjectBlockSize) {
|
||||
self = PoolObject_alloc();
|
||||
self->gc_is_large = false;
|
||||
}else{
|
||||
} else {
|
||||
self = malloc(size);
|
||||
self->gc_is_large = true;
|
||||
}
|
||||
@ -108,9 +104,9 @@ PyObject* PyObject__new(py_Type type, int slots, int size){
|
||||
|
||||
// initialize slots or dict
|
||||
void* p = (char*)self + 8;
|
||||
if(slots >= 0){
|
||||
memset(p, 0, slots*sizeof(py_TValue));
|
||||
}else{
|
||||
if(slots >= 0) {
|
||||
memset(p, 0, slots * sizeof(py_TValue));
|
||||
} else {
|
||||
NameDict__ctor(p);
|
||||
}
|
||||
return self;
|
||||
|
||||
@ -136,30 +136,33 @@ void VM__ctor(VM* self) {
|
||||
self->builtins = pk_builtins__register();
|
||||
|
||||
// inject some builtin expections
|
||||
#define INJECT_BUILTIN_EXC(name) \
|
||||
#define INJECT_BUILTIN_EXC(name, TBase) \
|
||||
do { \
|
||||
py_Type type = pk_newtype(#name, tp_Exception, &self->builtins, NULL, false, true); \
|
||||
py_Type type = pk_newtype(#name, TBase, &self->builtins, NULL, false, true); \
|
||||
py_setdict(&self->builtins, py_name(#name), py_tpobject(type)); \
|
||||
validate(tp_##name, type); \
|
||||
} while(0)
|
||||
|
||||
INJECT_BUILTIN_EXC(StopIteration);
|
||||
INJECT_BUILTIN_EXC(SyntaxError);
|
||||
INJECT_BUILTIN_EXC(StackOverflowError);
|
||||
INJECT_BUILTIN_EXC(IOError);
|
||||
INJECT_BUILTIN_EXC(OSError);
|
||||
INJECT_BUILTIN_EXC(NotImplementedError);
|
||||
INJECT_BUILTIN_EXC(TypeError);
|
||||
INJECT_BUILTIN_EXC(IndexError);
|
||||
INJECT_BUILTIN_EXC(ValueError);
|
||||
INJECT_BUILTIN_EXC(RuntimeError);
|
||||
INJECT_BUILTIN_EXC(ZeroDivisionError);
|
||||
INJECT_BUILTIN_EXC(NameError);
|
||||
INJECT_BUILTIN_EXC(UnboundLocalError);
|
||||
INJECT_BUILTIN_EXC(AttributeError);
|
||||
INJECT_BUILTIN_EXC(ImportError);
|
||||
INJECT_BUILTIN_EXC(AssertionError);
|
||||
INJECT_BUILTIN_EXC(KeyError);
|
||||
INJECT_BUILTIN_EXC(SystemExit, tp_BaseException);
|
||||
INJECT_BUILTIN_EXC(KeyboardInterrupt, tp_BaseException);
|
||||
|
||||
INJECT_BUILTIN_EXC(StopIteration, tp_Exception);
|
||||
INJECT_BUILTIN_EXC(SyntaxError, tp_Exception);
|
||||
INJECT_BUILTIN_EXC(StackOverflowError, tp_Exception);
|
||||
INJECT_BUILTIN_EXC(IOError, tp_Exception);
|
||||
INJECT_BUILTIN_EXC(OSError, tp_Exception);
|
||||
INJECT_BUILTIN_EXC(NotImplementedError, tp_Exception);
|
||||
INJECT_BUILTIN_EXC(TypeError, tp_Exception);
|
||||
INJECT_BUILTIN_EXC(IndexError, tp_Exception);
|
||||
INJECT_BUILTIN_EXC(ValueError, tp_Exception);
|
||||
INJECT_BUILTIN_EXC(RuntimeError, tp_Exception);
|
||||
INJECT_BUILTIN_EXC(ZeroDivisionError, tp_Exception);
|
||||
INJECT_BUILTIN_EXC(NameError, tp_Exception);
|
||||
INJECT_BUILTIN_EXC(UnboundLocalError, tp_Exception);
|
||||
INJECT_BUILTIN_EXC(AttributeError, tp_Exception);
|
||||
INJECT_BUILTIN_EXC(ImportError, tp_Exception);
|
||||
INJECT_BUILTIN_EXC(AssertionError, tp_Exception);
|
||||
INJECT_BUILTIN_EXC(KeyError, tp_Exception);
|
||||
|
||||
#undef INJECT_BUILTIN_EXC
|
||||
#undef validate
|
||||
@ -317,7 +320,7 @@ py_Type pk_newtype(const char* name,
|
||||
bool is_python,
|
||||
bool is_sealed) {
|
||||
c11_vector* types = &pk_current_vm->types;
|
||||
py_Type index = types->count;
|
||||
py_Type index = types->length;
|
||||
py_TypeInfo* ti = c11_vector__emplace(types);
|
||||
py_TypeInfo* base_ti = base ? c11__at(py_TypeInfo, types, base) : NULL;
|
||||
if(base_ti && base_ti->is_sealed) {
|
||||
@ -340,7 +343,7 @@ py_Type py_newtype(const char* name, py_Type base, const py_GlobalRef module, vo
|
||||
static bool
|
||||
prepare_py_call(py_TValue* buffer, py_Ref argv, py_Ref p1, int kwargc, const FuncDecl* decl) {
|
||||
const CodeObject* co = &decl->code;
|
||||
int decl_argc = decl->args.count;
|
||||
int decl_argc = decl->args.length;
|
||||
|
||||
if(p1 - argv < decl_argc) {
|
||||
return TypeError("%s() takes %d positional arguments but %d were given",
|
||||
@ -392,11 +395,9 @@ static bool
|
||||
co->name->data);
|
||||
} else {
|
||||
// add to **kwargs
|
||||
py_Ref tmp = py_pushtmp();
|
||||
c11_sv key_sv = py_name2sv(key);
|
||||
py_newstrn(tmp, key_sv.data, key_sv.size);
|
||||
bool ok = py_dict_setitem(&buffer[decl->starred_kwarg], tmp, &p1[2 * j + 1]);
|
||||
py_pop();
|
||||
bool ok = py_dict_setitem_by_str(&buffer[decl->starred_kwarg],
|
||||
py_name2str(key),
|
||||
&p1[2 * j + 1]);
|
||||
if(!ok) return false;
|
||||
}
|
||||
}
|
||||
@ -452,9 +453,9 @@ FrameResult VM__vectorcall(VM* self, uint16_t argc, uint16_t kwargc, bool opcall
|
||||
}
|
||||
}
|
||||
case FuncType_SIMPLE:
|
||||
if(p1 - argv != fn->decl->args.count) {
|
||||
if(p1 - argv != fn->decl->args.length) {
|
||||
const char* fmt = "%s() takes %d positional arguments but %d were given";
|
||||
TypeError(fmt, co->name->data, fn->decl->args.count, p1 - argv);
|
||||
TypeError(fmt, co->name->data, fn->decl->args.length, p1 - argv);
|
||||
return RES_ERROR;
|
||||
}
|
||||
if(kwargc) {
|
||||
@ -552,7 +553,7 @@ void pk__mark_value(py_TValue* val) {
|
||||
}
|
||||
|
||||
void pk__mark_namedict(NameDict* dict) {
|
||||
for(int i = 0; i < dict->count; i++) {
|
||||
for(int i = 0; i < dict->length; i++) {
|
||||
NameDict_KV* kv = c11__at(NameDict_KV, dict, i);
|
||||
pk__mark_value(&kv->value);
|
||||
}
|
||||
@ -589,7 +590,7 @@ void CodeObject__gc_mark(const CodeObject* self) {
|
||||
void ManagedHeap__mark(ManagedHeap* self) {
|
||||
VM* vm = self->vm;
|
||||
// mark heap objects
|
||||
for(int i = 0; i < self->no_gc.count; i++) {
|
||||
for(int i = 0; i < self->no_gc.length; i++) {
|
||||
PyObject* obj = c11__getitem(PyObject*, &self->no_gc, i);
|
||||
mark_object(obj);
|
||||
}
|
||||
@ -599,7 +600,7 @@ void ManagedHeap__mark(ManagedHeap* self) {
|
||||
}
|
||||
// mark magic slots
|
||||
py_TypeInfo* types = vm->types.data;
|
||||
int types_length = vm->types.count;
|
||||
int types_length = vm->types.length;
|
||||
// 0-th type is placeholder
|
||||
for(int i = 1; i < types_length; i++) {
|
||||
for(int j = 0; j <= __missing__; j++) {
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
static void disassemble(CodeObject* co) {
|
||||
c11_vector /*T=int*/ jumpTargets;
|
||||
c11_vector__ctor(&jumpTargets, sizeof(int));
|
||||
for(int i = 0; i < co->codes.count; i++) {
|
||||
for(int i = 0; i < co->codes.length; i++) {
|
||||
Bytecode* bc = c11__at(Bytecode, &co->codes, i);
|
||||
if(Bytecode__is_forward_jump(bc)) {
|
||||
int target = (int16_t)bc->arg + i;
|
||||
@ -20,7 +20,7 @@ static void disassemble(CodeObject* co) {
|
||||
c11_sbuf__ctor(&ss);
|
||||
|
||||
int prev_line = -1;
|
||||
for(int i = 0; i < co->codes.count; i++) {
|
||||
for(int i = 0; i < co->codes.length; i++) {
|
||||
Bytecode byte = c11__getitem(Bytecode, &co->codes, i);
|
||||
BytecodeEx ex = c11__getitem(BytecodeEx, &co->codes_ex, i);
|
||||
|
||||
@ -101,7 +101,7 @@ static void disassemble(CodeObject* co) {
|
||||
}
|
||||
} while(0);
|
||||
|
||||
if(i != co->codes.count - 1) c11_sbuf__write_char(&ss, '\n');
|
||||
if(i != co->codes.length - 1) c11_sbuf__write_char(&ss, '\n');
|
||||
}
|
||||
|
||||
c11_string* output = c11_sbuf__submit(&ss);
|
||||
@ -115,12 +115,12 @@ static bool dis_dis(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
|
||||
CodeObject* code = NULL;
|
||||
if(py_istype(argv, tp_function)){
|
||||
if(py_istype(argv, tp_function)) {
|
||||
Function* ud = py_touserdata(argv);
|
||||
code = &ud->decl->code;
|
||||
}else if(py_istype(argv, tp_code)){
|
||||
} else if(py_istype(argv, tp_code)) {
|
||||
code = py_touserdata(argv);
|
||||
}else{
|
||||
} else {
|
||||
return TypeError("dis() expected a code object");
|
||||
}
|
||||
disassemble(code);
|
||||
|
||||
@ -152,7 +152,7 @@ void CodeObject__dtor(CodeObject* self) {
|
||||
|
||||
c11_vector__dtor(&self->blocks);
|
||||
|
||||
for(int i = 0; i < self->func_decls.count; i++) {
|
||||
for(int i = 0; i < self->func_decls.length; i++) {
|
||||
FuncDecl_ decl = c11__getitem(FuncDecl_, &self->func_decls, i);
|
||||
PK_DECREF(decl);
|
||||
}
|
||||
@ -173,7 +173,7 @@ int CodeObject__add_varname(CodeObject* self, py_Name name) {
|
||||
if(index >= 0) return index;
|
||||
c11_vector__push(uint16_t, &self->varnames, name);
|
||||
self->nlocals++;
|
||||
index = self->varnames.count - 1;
|
||||
index = self->varnames.length - 1;
|
||||
c11_smallmap_n2i__set(&self->varnames_inv, name, index);
|
||||
return index;
|
||||
}
|
||||
|
||||
@ -85,7 +85,7 @@ int py_import(const char* path_cstr) {
|
||||
|
||||
c11_vector /* T=c11_sv */ cpnts = c11_sv__split(package_sv, '.');
|
||||
for(int i = is_init; i < dot_count; i++) {
|
||||
if(cpnts.count == 0)
|
||||
if(cpnts.length == 0)
|
||||
return ImportError("attempted relative import beyond top-level package");
|
||||
c11_vector__pop(&cpnts);
|
||||
}
|
||||
@ -98,7 +98,7 @@ int py_import(const char* path_cstr) {
|
||||
// join cpnts
|
||||
c11_sbuf buf;
|
||||
c11_sbuf__ctor(&buf);
|
||||
for(int i = 0; i < cpnts.count; i++) {
|
||||
for(int i = 0; i < cpnts.length; i++) {
|
||||
if(i > 0) c11_sbuf__write_char(&buf, '.');
|
||||
c11_sbuf__write_sv(&buf, c11__getitem(c11_sv, &cpnts, i));
|
||||
}
|
||||
@ -169,9 +169,13 @@ static bool builtins_exit(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARG_TYPE(0, tp_int);
|
||||
code = py_toint(argv);
|
||||
}
|
||||
// return py_exception("SystemExit", "%d", code);
|
||||
exit(code);
|
||||
return false;
|
||||
// py_TValue sso_code;
|
||||
// py_newint(&sso_code, code);
|
||||
// bool ok = py_tpcall(tp_SystemExit, 1, &sso_code);
|
||||
// if(!ok) return false;
|
||||
// return py_raise(py_retval());
|
||||
}
|
||||
|
||||
static bool builtins_len(int argc, py_Ref argv) {
|
||||
@ -616,9 +620,9 @@ static void function__gc_mark(void* ud) {
|
||||
static bool function__doc__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
Function* func = py_touserdata(py_arg(0));
|
||||
if(func->decl->docstring){
|
||||
if(func->decl->docstring) {
|
||||
py_newstr(py_retval(), func->decl->docstring);
|
||||
}else{
|
||||
} else {
|
||||
py_newnone(py_retval());
|
||||
}
|
||||
return true;
|
||||
|
||||
@ -79,7 +79,7 @@ static void Dict__rehash_2x(Dict* self) {
|
||||
do {
|
||||
Dict__ctor(self, new_capacity);
|
||||
|
||||
for(int i = 0; i < old_dict.entries.count; i++) {
|
||||
for(int i = 0; i < old_dict.entries.length; i++) {
|
||||
DictEntry* entry = c11__at(DictEntry, &old_dict.entries, i);
|
||||
if(py_isnil(&entry->key)) continue;
|
||||
int idx = entry->hash & (new_capacity - 1);
|
||||
@ -89,7 +89,7 @@ static void Dict__rehash_2x(Dict* self) {
|
||||
if(idx2 == -1) {
|
||||
// insert new entry (empty slot)
|
||||
c11_vector__push(DictEntry, &self->entries, *entry);
|
||||
self->indices[idx]._[i] = self->entries.count - 1;
|
||||
self->indices[idx]._[i] = self->entries.length - 1;
|
||||
self->length++;
|
||||
success = true;
|
||||
break;
|
||||
@ -108,10 +108,10 @@ static void Dict__rehash_2x(Dict* self) {
|
||||
}
|
||||
|
||||
static void Dict__compact_entries(Dict* self) {
|
||||
int* mappings = malloc(self->entries.count * sizeof(int));
|
||||
int* mappings = malloc(self->entries.length * sizeof(int));
|
||||
|
||||
int n = 0;
|
||||
for(int i = 0; i < self->entries.count; i++) {
|
||||
for(int i = 0; i < self->entries.length; i++) {
|
||||
DictEntry* entry = c11__at(DictEntry, &self->entries, i);
|
||||
if(py_isnil(&entry->key)) continue;
|
||||
mappings[i] = n;
|
||||
@ -121,7 +121,7 @@ static void Dict__compact_entries(Dict* self) {
|
||||
}
|
||||
n++;
|
||||
}
|
||||
self->entries.count = n;
|
||||
self->entries.length = n;
|
||||
// update indices
|
||||
for(int i = 0; i < self->capacity; i++) {
|
||||
for(int j = 0; j < PK_DICT_MAX_COLLISION; j++) {
|
||||
@ -145,7 +145,7 @@ static bool Dict__set(Dict* self, py_TValue* key, py_TValue* val) {
|
||||
new_entry->hash = hash;
|
||||
new_entry->key = *key;
|
||||
new_entry->val = *val;
|
||||
self->indices[idx]._[i] = self->entries.count - 1;
|
||||
self->indices[idx]._[i] = self->entries.length - 1;
|
||||
self->length++;
|
||||
return true;
|
||||
}
|
||||
@ -179,7 +179,7 @@ static int Dict__pop(Dict* self, py_Ref key) {
|
||||
py_newnil(&entry->key);
|
||||
self->indices[idx]._[i] = -1;
|
||||
self->length--;
|
||||
if(self->length < self->entries.count / 2) Dict__compact_entries(self);
|
||||
if(self->length < self->entries.length / 2) Dict__compact_entries(self);
|
||||
return 1;
|
||||
}
|
||||
if(res == -1) return -1; // error
|
||||
@ -189,7 +189,7 @@ static int Dict__pop(Dict* self, py_Ref key) {
|
||||
|
||||
static void DictIterator__ctor(DictIterator* self, Dict* dict) {
|
||||
self->curr = dict->entries.data;
|
||||
self->end = self->curr + dict->entries.count;
|
||||
self->end = self->curr + dict->entries.length;
|
||||
}
|
||||
|
||||
static DictEntry* DictIterator__next(DictIterator* self) {
|
||||
@ -291,7 +291,7 @@ static bool dict__repr__(int argc, py_Ref argv) {
|
||||
c11_sbuf__ctor(&buf);
|
||||
c11_sbuf__write_char(&buf, '{');
|
||||
bool is_first = true;
|
||||
for(int i = 0; i < self->entries.count; i++) {
|
||||
for(int i = 0; i < self->entries.length; i++) {
|
||||
DictEntry* entry = c11__at(DictEntry, &self->entries, i);
|
||||
if(py_isnil(&entry->key)) continue;
|
||||
if(!is_first) c11_sbuf__write_cstr(&buf, ", ");
|
||||
@ -377,7 +377,7 @@ static bool dict_update(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARG_TYPE(1, tp_dict);
|
||||
Dict* self = py_touserdata(argv);
|
||||
Dict* other = py_touserdata(py_arg(1));
|
||||
for(int i = 0; i < other->entries.count; i++) {
|
||||
for(int i = 0; i < other->entries.length; i++) {
|
||||
DictEntry* entry = c11__at(DictEntry, &other->entries, i);
|
||||
if(py_isnil(&entry->key)) continue;
|
||||
if(!Dict__set(self, &entry->key, &entry->val)) return false;
|
||||
@ -449,7 +449,7 @@ static bool dict_values(int argc, py_Ref argv) {
|
||||
|
||||
static void dict__gc_mark(void* ud) {
|
||||
Dict* self = ud;
|
||||
for(int i = 0; i < self->entries.count; i++) {
|
||||
for(int i = 0; i < self->entries.length; i++) {
|
||||
DictEntry* entry = c11__at(DictEntry, &self->entries, i);
|
||||
if(py_isnil(&entry->key)) continue;
|
||||
pk__mark_value(&entry->key);
|
||||
@ -521,25 +521,40 @@ int py_dict_getitem(py_Ref self, py_Ref key) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int py_dict_delitem(py_Ref self, py_Ref key) {
|
||||
assert(py_isdict(self));
|
||||
Dict* ud = py_touserdata(self);
|
||||
return Dict__pop(ud, key);
|
||||
}
|
||||
|
||||
bool py_dict_setitem(py_Ref self, py_Ref key, py_Ref val) {
|
||||
assert(py_isdict(self));
|
||||
Dict* ud = py_touserdata(self);
|
||||
return Dict__set(ud, key, val);
|
||||
}
|
||||
|
||||
int py_dict_contains(py_Ref self, py_Ref key) {
|
||||
int py_dict_delitem(py_Ref self, py_Ref key) {
|
||||
assert(py_isdict(self));
|
||||
Dict* ud = py_touserdata(self);
|
||||
DictEntry* entry;
|
||||
bool ok = Dict__try_get(ud, key, &entry);
|
||||
if(!ok) return -1;
|
||||
return entry ? 1 : 0;
|
||||
return Dict__pop(ud, key);
|
||||
}
|
||||
|
||||
int py_dict_getitem_by_str(py_Ref self, const char *key){
|
||||
py_Ref tmp = py_pushtmp();
|
||||
py_newstr(tmp, key);
|
||||
int res = py_dict_getitem(self, tmp);
|
||||
py_pop();
|
||||
return res;
|
||||
}
|
||||
|
||||
bool py_dict_setitem_by_str(py_Ref self, const char *key, py_Ref val){
|
||||
py_Ref tmp = py_pushtmp();
|
||||
py_newstr(tmp, key);
|
||||
bool res = py_dict_setitem(self, tmp, val);
|
||||
py_pop();
|
||||
return res;
|
||||
}
|
||||
|
||||
int py_dict_delitem_by_str(py_Ref self, const char *key){
|
||||
py_Ref tmp = py_pushtmp();
|
||||
py_newstr(tmp, key);
|
||||
int res = py_dict_delitem(self, tmp);
|
||||
py_pop();
|
||||
return res;
|
||||
}
|
||||
|
||||
int py_dict_len(py_Ref self) {
|
||||
@ -550,7 +565,7 @@ int py_dict_len(py_Ref self) {
|
||||
|
||||
bool py_dict_apply(py_Ref self, bool (*f)(py_Ref, py_Ref, void*), void* ctx) {
|
||||
Dict* ud = py_touserdata(self);
|
||||
for(int i = 0; i < ud->entries.count; i++) {
|
||||
for(int i = 0; i < ud->entries.length; i++) {
|
||||
DictEntry* entry = c11__at(DictEntry, &ud->entries, i);
|
||||
if(py_isnil(&entry->key)) continue;
|
||||
if(!f(&entry->key, &entry->val, ctx)) return false;
|
||||
|
||||
@ -33,7 +33,7 @@ int py_BaseException__get_lineno(py_Ref self, const CodeObject* code) {
|
||||
|
||||
void py_BaseException__stpush(py_Ref self, SourceData_ src, int lineno, const char* func_name) {
|
||||
BaseException* ud = py_touserdata(self);
|
||||
if(ud->stacktrace.count >= 7) return;
|
||||
if(ud->stacktrace.length >= 7) return;
|
||||
BaseExceptionFrame* frame = c11_vector__emplace(&ud->stacktrace);
|
||||
PK_INCREF(src);
|
||||
frame->src = src;
|
||||
@ -156,7 +156,7 @@ static void c11_sbuf__write_exc(c11_sbuf* self, py_Ref exc) {
|
||||
|
||||
BaseException* ud = py_touserdata(exc);
|
||||
|
||||
for(int i = ud->stacktrace.count - 1; i >= 0; i--) {
|
||||
for(int i = ud->stacktrace.length - 1; i >= 0; i--) {
|
||||
BaseExceptionFrame* frame = c11__at(BaseExceptionFrame, &ud->stacktrace, i);
|
||||
SourceData__snapshot(frame->src,
|
||||
self,
|
||||
|
||||
@ -16,7 +16,7 @@ void py_newlistn(py_Ref out, int n) {
|
||||
py_newlist(out);
|
||||
List* ud = py_touserdata(out);
|
||||
c11_vector__reserve(ud, n);
|
||||
ud->count = n;
|
||||
ud->length = n;
|
||||
}
|
||||
|
||||
py_Ref py_list_data(py_Ref self) {
|
||||
@ -41,7 +41,7 @@ void py_list_delitem(py_Ref self, int i) {
|
||||
|
||||
int py_list_len(py_Ref self) {
|
||||
List* ud = py_touserdata(self);
|
||||
return ud->count;
|
||||
return ud->length;
|
||||
}
|
||||
|
||||
void py_list_swap(py_Ref self, int i, int j) {
|
||||
@ -137,12 +137,12 @@ static bool list__getitem__(int argc, py_Ref argv) {
|
||||
py_Ref _1 = py_arg(1);
|
||||
if(_1->type == tp_int) {
|
||||
int index = py_toint(py_arg(1));
|
||||
if(!pk__normalize_index(&index, self->count)) return false;
|
||||
if(!pk__normalize_index(&index, self->length)) return false;
|
||||
*py_retval() = c11__getitem(py_TValue, self, index);
|
||||
return true;
|
||||
} else if(_1->type == tp_slice) {
|
||||
int start, stop, step;
|
||||
bool ok = pk__parse_int_slice(_1, self->count, &start, &stop, &step);
|
||||
bool ok = pk__parse_int_slice(_1, self->length, &start, &stop, &step);
|
||||
if(!ok) return false;
|
||||
py_newlist(py_retval());
|
||||
List* list = py_touserdata(py_retval());
|
||||
@ -160,7 +160,7 @@ static bool list__setitem__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARG_TYPE(1, tp_int);
|
||||
List* self = py_touserdata(py_arg(0));
|
||||
int index = py_toint(py_arg(1));
|
||||
if(!pk__normalize_index(&index, self->count)) return false;
|
||||
if(!pk__normalize_index(&index, self->length)) return false;
|
||||
c11__setitem(py_TValue, self, index, *py_arg(2));
|
||||
py_newnone(py_retval());
|
||||
return true;
|
||||
@ -171,7 +171,7 @@ static bool list__delitem__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARG_TYPE(1, tp_int);
|
||||
List* self = py_touserdata(py_arg(0));
|
||||
int index = py_toint(py_arg(1));
|
||||
if(!pk__normalize_index(&index, self->count)) return false;
|
||||
if(!pk__normalize_index(&index, self->length)) return false;
|
||||
c11_vector__erase(py_TValue, self, index);
|
||||
py_newnone(py_retval());
|
||||
return true;
|
||||
@ -186,8 +186,8 @@ static bool list__add__(int argc, py_Ref argv) {
|
||||
List* list_1 = py_touserdata(_1);
|
||||
py_newlist(py_retval());
|
||||
List* list = py_touserdata(py_retval());
|
||||
c11_vector__extend(py_TValue, list, list_0->data, list_0->count);
|
||||
c11_vector__extend(py_TValue, list, list_1->data, list_1->count);
|
||||
c11_vector__extend(py_TValue, list, list_0->data, list_0->length);
|
||||
c11_vector__extend(py_TValue, list, list_1->data, list_1->length);
|
||||
} else {
|
||||
py_newnotimplemented(py_retval());
|
||||
}
|
||||
@ -204,7 +204,7 @@ static bool list__mul__(int argc, py_Ref argv) {
|
||||
List* list = py_touserdata(py_retval());
|
||||
List* list_0 = py_touserdata(_0);
|
||||
for(int i = 0; i < n; i++) {
|
||||
c11_vector__extend(py_TValue, list, list_0->data, list_0->count);
|
||||
c11_vector__extend(py_TValue, list, list_0->data, list_0->length);
|
||||
}
|
||||
} else {
|
||||
py_newnotimplemented(py_retval());
|
||||
@ -226,7 +226,7 @@ static bool list__repr__(int argc, py_Ref argv) {
|
||||
c11_sbuf buf;
|
||||
c11_sbuf__ctor(&buf);
|
||||
c11_sbuf__write_char(&buf, '[');
|
||||
for(int i = 0; i < self->count; i++) {
|
||||
for(int i = 0; i < self->length; i++) {
|
||||
py_TValue* val = c11__at(py_TValue, self, i);
|
||||
bool ok = py_repr(val);
|
||||
if(!ok) {
|
||||
@ -234,7 +234,7 @@ static bool list__repr__(int argc, py_Ref argv) {
|
||||
return false;
|
||||
}
|
||||
c11_sbuf__write_sv(&buf, py_tosv(py_retval()));
|
||||
if(i != self->count - 1) c11_sbuf__write_cstr(&buf, ", ");
|
||||
if(i != self->length - 1) c11_sbuf__write_cstr(&buf, ", ");
|
||||
}
|
||||
c11_sbuf__write_char(&buf, ']');
|
||||
c11_sbuf__py_submit(&buf, py_retval());
|
||||
@ -246,7 +246,7 @@ static bool list_extend(int argc, py_Ref argv) {
|
||||
List* self = py_touserdata(py_arg(0));
|
||||
PY_CHECK_ARG_TYPE(1, tp_list);
|
||||
List* other = py_touserdata(py_arg(1));
|
||||
c11_vector__extend(py_TValue, self, other->data, other->count);
|
||||
c11_vector__extend(py_TValue, self, other->data, other->length);
|
||||
py_newnone(py_retval());
|
||||
return true;
|
||||
}
|
||||
@ -275,7 +275,7 @@ static bool list_copy(int argc, py_Ref argv) {
|
||||
py_newlist(py_retval());
|
||||
List* self = py_touserdata(py_arg(0));
|
||||
List* list = py_touserdata(py_retval());
|
||||
c11_vector__extend(py_TValue, list, self->data, self->count);
|
||||
c11_vector__extend(py_TValue, list, self->data, self->length);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -330,8 +330,8 @@ static bool list_pop(int argc, py_Ref argv) {
|
||||
return TypeError("pop() takes at most 2 arguments");
|
||||
}
|
||||
List* self = py_touserdata(py_arg(0));
|
||||
if(self->count == 0) return IndexError("pop from empty list");
|
||||
if(!pk__normalize_index(&index, self->count)) return false;
|
||||
if(self->length == 0) return IndexError("pop from empty list");
|
||||
if(!pk__normalize_index(&index, self->length)) return false;
|
||||
*py_retval() = c11__getitem(py_TValue, self, index);
|
||||
c11_vector__erase(py_TValue, self, index);
|
||||
return true;
|
||||
@ -342,9 +342,9 @@ static bool list_insert(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARG_TYPE(1, tp_int);
|
||||
List* self = py_touserdata(py_arg(0));
|
||||
int index = py_toint(py_arg(1));
|
||||
if(index < 0) index += self->count;
|
||||
if(index < 0) index += self->length;
|
||||
if(index < 0) index = 0;
|
||||
if(index > self->count) index = self->count;
|
||||
if(index > self->length) index = self->length;
|
||||
c11_vector__insert(py_TValue, self, index, *py_arg(2));
|
||||
py_newnone(py_retval());
|
||||
return true;
|
||||
@ -380,7 +380,7 @@ static bool list_sort(int argc, py_Ref argv) {
|
||||
if(py_isnone(key)) key = NULL;
|
||||
|
||||
bool ok = c11__stable_sort(self->data,
|
||||
self->count,
|
||||
self->length,
|
||||
sizeof(py_TValue),
|
||||
(int (*)(const void*, const void*, void*))lt_with_key,
|
||||
key);
|
||||
@ -405,7 +405,7 @@ static bool list__contains__(int argc, py_Ref argv) {
|
||||
|
||||
static void list__gc_mark(void* ud) {
|
||||
List* self = ud;
|
||||
for(int i = 0; i < self->count; i++) {
|
||||
for(int i = 0; i < self->length; i++) {
|
||||
pk__mark_value(c11__at(py_TValue, self, i));
|
||||
}
|
||||
}
|
||||
|
||||
@ -52,8 +52,8 @@ static bool namedict_items(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
py_Ref object = py_getslot(argv, 0);
|
||||
NameDict* dict = PyObject__dict(object->_obj);
|
||||
py_newtuple(py_retval(), dict->count);
|
||||
for(int i = 0; i < dict->count; i++) {
|
||||
py_newtuple(py_retval(), dict->length);
|
||||
for(int i = 0; i < dict->length; i++) {
|
||||
py_Ref slot = py_tuple_getitem(py_retval(), i);
|
||||
py_newtuple(slot, 2);
|
||||
NameDict_KV* kv = c11__at(NameDict_KV, dict, i);
|
||||
|
||||
@ -318,8 +318,8 @@ static bool str_split(int argc, py_Ref argv) {
|
||||
c11_sv sep = c11_string__sv(py_touserdata(&argv[1]));
|
||||
res = c11_sv__split2(self, sep);
|
||||
}
|
||||
py_newlistn(py_retval(), res.count);
|
||||
for(int i = 0; i < res.count; i++) {
|
||||
py_newlistn(py_retval(), res.length);
|
||||
for(int i = 0; i < res.length; i++) {
|
||||
c11_sv item = c11__getitem(c11_sv, &res, i);
|
||||
py_newstrn(py_list_getitem(py_retval(), i), item.data, item.size);
|
||||
}
|
||||
@ -563,8 +563,8 @@ static bool bytes__getitem__(int argc, py_Ref argv) {
|
||||
for(int i = start; step > 0 ? i < stop : i > stop; i += step) {
|
||||
c11_vector__push(unsigned char, &res, data[i]);
|
||||
}
|
||||
unsigned char* p = py_newbytes(py_retval(), res.count);
|
||||
memcpy(p, res.data, res.count);
|
||||
unsigned char* p = py_newbytes(py_retval(), res.length);
|
||||
memcpy(p, res.data, res.length);
|
||||
c11_vector__dtor(&res);
|
||||
return true;
|
||||
} else {
|
||||
|
||||
@ -86,7 +86,7 @@ py_Name
|
||||
CodeObject code;
|
||||
SourceData_ source = SourceData__rcnew(buffer, "<bind>", EXEC_MODE, false);
|
||||
Error* err = pk_compile(source, &code);
|
||||
if(err || code.func_decls.count != 1) {
|
||||
if(err || code.func_decls.length != 1) {
|
||||
c11__abort("py_newfunction(): invalid signature '%s'", sig);
|
||||
}
|
||||
FuncDecl_ decl = c11__getitem(FuncDecl_, &code.func_decls, 0);
|
||||
|
||||
@ -127,4 +127,7 @@ assert f'{a:10}' == 'A '
|
||||
|
||||
assert f'{A()!r:10}' == 'A() '
|
||||
assert f'{A():10}' == 'A '
|
||||
assert f'{A():10}' == 'A '
|
||||
assert f'{A():10}' == 'A '
|
||||
|
||||
a = ['1', '2', '3']
|
||||
assert f'a = {'\n'.join(a)}' == 'a = 1\n2\n3'
|
||||
@ -1,22 +0,0 @@
|
||||
# @szdytom favored testing, set BUILD_TESTING to enable it
|
||||
# You can use scripts/run_tests.py as an alternative
|
||||
# Note: the CI uses scripts/run_tests.py to run the tests
|
||||
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
function(pkpy_add_test pyfile)
|
||||
get_filename_component(test_name ${pyfile} NAME_WE)
|
||||
add_test(
|
||||
NAME ${test_name}
|
||||
COMMAND $<TARGET_FILE:main> ${pyfile}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/..
|
||||
)
|
||||
endfunction()
|
||||
|
||||
message("Testing enabled")
|
||||
|
||||
file(GLOB PK_PYTHON_TESTCASES_FILES RELATIVE ${CMAKE_CURRENT_LIST_DIR}/.. "*.py")
|
||||
|
||||
foreach(pyfile ${PK_PYTHON_TESTCASES_FILES})
|
||||
pkpy_add_test(${pyfile})
|
||||
endforeach()
|
||||
Loading…
x
Reference in New Issue
Block a user