mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-30 08:20:16 +00:00
Compare commits
10 Commits
8e1e29ddd6
...
0b649f3bef
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0b649f3bef | ||
|
|
a87641c04d | ||
|
|
9c173fdada | ||
|
|
348bb2b7a5 | ||
|
|
39947e8f15 | ||
|
|
56763e05f9 | ||
|
|
cd9a9f7119 | ||
|
|
ea9dabdf99 | ||
|
|
b1a8c6db8e | ||
|
|
3c87bf8630 |
BIN
backup/vfs.zip
Normal file
BIN
backup/vfs.zip
Normal file
Binary file not shown.
@ -5,6 +5,8 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
const char* load_kPythonLib(const char* name);
|
||||
|
||||
extern const char kPythonLibs__enum[];
|
||||
extern const char kPythonLibs__long[];
|
||||
extern const char kPythonLibs__set[];
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
|
||||
// Whether to compile os-related modules or not
|
||||
#ifndef PK_ENABLE_OS // can be overridden by cmake
|
||||
#define PK_ENABLE_OS 0
|
||||
#define PK_ENABLE_OS 1
|
||||
#endif
|
||||
|
||||
// Enable `line_profiler` module and `breakpoint()` function
|
||||
|
||||
@ -11,8 +11,8 @@ extern "C" {
|
||||
#define kPoolObjectArenaSize (256*1024)
|
||||
#define kPoolObjectMaxBlocks (kPoolObjectArenaSize / kPoolObjectBlockSize)
|
||||
|
||||
void pk_MemoryPools__initialize();
|
||||
void pk_MemoryPools__finalize();
|
||||
void MemoryPools__initialize();
|
||||
void MemoryPools__finalize();
|
||||
|
||||
void* PoolExpr_alloc();
|
||||
void PoolExpr_dealloc(void*);
|
||||
|
||||
@ -49,6 +49,8 @@ int c11_sv__index(c11_sv self, char c);
|
||||
int c11_sv__rindex(c11_sv self, char c);
|
||||
int c11_sv__index2(c11_sv self, c11_sv sub, int start);
|
||||
int c11_sv__count(c11_sv self, c11_sv sub);
|
||||
bool c11_sv__startswith(c11_sv self, c11_sv prefix);
|
||||
bool c11_sv__endswith(c11_sv self, c11_sv suffix);
|
||||
|
||||
c11_string* c11_sv__replace(c11_sv self, char old, char new_);
|
||||
c11_string* c11_sv__replace2(c11_sv self, c11_sv old, c11_sv new_);
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
Error* pk_compile(pk_SourceData_ src, CodeObject* out);
|
||||
Error* pk_compile(SourceData_ src, CodeObject* out);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern const char* pk_TokenSymbols[];
|
||||
extern const char* TokenSymbols[];
|
||||
|
||||
typedef enum TokenIndex{
|
||||
TK_EOF, TK_EOL, TK_SOF,
|
||||
@ -88,11 +88,11 @@ enum Precedence {
|
||||
PREC_HIGHEST,
|
||||
};
|
||||
|
||||
typedef c11_array pk_TokenArray;
|
||||
typedef c11_array TokenArray;
|
||||
|
||||
Error* pk_Lexer__process(pk_SourceData_ src, pk_TokenArray* out_tokens);
|
||||
Error* pk_Lexer__process_and_dump(pk_SourceData_ src, c11_string** out_string);
|
||||
void pk_TokenArray__dtor(pk_TokenArray* self);
|
||||
Error* Lexer__process(SourceData_ src, TokenArray* out_tokens);
|
||||
Error* Lexer__process_and_dump(SourceData_ src, c11_string** out_string);
|
||||
void TokenArray__dtor(TokenArray* self);
|
||||
|
||||
#define Token__sv(self) (c11_sv){(self)->start, (self)->length}
|
||||
|
||||
|
||||
@ -12,7 +12,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
py_TValue* FastLocals__try_get_by_name(py_TValue* locals, const CodeObject* co, py_Name name);
|
||||
pk_NameDict* FastLocals__to_namedict(py_TValue* locals, const CodeObject* co);
|
||||
NameDict* FastLocals__to_namedict(py_TValue* locals, const CodeObject* co);
|
||||
|
||||
typedef struct ValueStack {
|
||||
// We allocate extra PK_VM_STACK_SIZE/128 places to keep `_sp` valid when `is_overflow() ==
|
||||
|
||||
@ -5,29 +5,29 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct pk_ManagedHeap{
|
||||
typedef struct ManagedHeap{
|
||||
c11_vector no_gc;
|
||||
c11_vector gen;
|
||||
|
||||
int gc_threshold;
|
||||
int gc_counter;
|
||||
pk_VM* vm;
|
||||
VM* vm;
|
||||
|
||||
void (*gc_on_delete)(pk_VM*, PyObject*);
|
||||
} pk_ManagedHeap;
|
||||
void (*gc_on_delete)(VM*, PyObject*);
|
||||
} ManagedHeap;
|
||||
|
||||
void pk_ManagedHeap__ctor(pk_ManagedHeap* self, pk_VM* vm);
|
||||
void pk_ManagedHeap__dtor(pk_ManagedHeap* self);
|
||||
void ManagedHeap__ctor(ManagedHeap* self, VM* vm);
|
||||
void ManagedHeap__dtor(ManagedHeap* self);
|
||||
|
||||
void pk_ManagedHeap__collect_if_needed(pk_ManagedHeap* self);
|
||||
int pk_ManagedHeap__collect(pk_ManagedHeap* self);
|
||||
int pk_ManagedHeap__sweep(pk_ManagedHeap* self);
|
||||
void ManagedHeap__collect_if_needed(ManagedHeap* self);
|
||||
int ManagedHeap__collect(ManagedHeap* self);
|
||||
int ManagedHeap__sweep(ManagedHeap* self);
|
||||
|
||||
PyObject* pk_ManagedHeap__new(pk_ManagedHeap* self, py_Type type, int slots, int udsize);
|
||||
PyObject* pk_ManagedHeap__gcnew(pk_ManagedHeap* self, py_Type type, int slots, int udsize);
|
||||
PyObject* ManagedHeap__new(ManagedHeap* self, py_Type type, int slots, int udsize);
|
||||
PyObject* ManagedHeap__gcnew(ManagedHeap* self, py_Type type, int slots, int udsize);
|
||||
|
||||
// external implementation
|
||||
void pk_ManagedHeap__mark(pk_ManagedHeap* self);
|
||||
void ManagedHeap__mark(ManagedHeap* self);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
13
include/pocketpy/interpreter/modules.h
Normal file
13
include/pocketpy/interpreter/modules.h
Normal file
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void pk__add_module_pkpy();
|
||||
void pk__add_module_os();
|
||||
void pk__add_module_math();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@ -1,44 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "pocketpy/common/vector.h"
|
||||
#include "pocketpy/common/str.h"
|
||||
#include "pocketpy/pocketpy.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct VfsEntry {
|
||||
bool is_file;
|
||||
|
||||
union {
|
||||
struct {
|
||||
int size;
|
||||
unsigned char* data;
|
||||
} _file;
|
||||
|
||||
c11_vector _dir;
|
||||
};
|
||||
} VfsEntry;
|
||||
|
||||
#define SMALLMAP_T__HEADER
|
||||
#define K c11_sv
|
||||
#define V VfsEntry
|
||||
#define NAME VfsDir
|
||||
#define less(a, b) (c11_sv__cmp((a), (b)) < 0)
|
||||
#define equal(a, b) (c11_sv__cmp((a), (b)) == 0)
|
||||
#include "pocketpy/xmacros/smallmap.h"
|
||||
#undef SMALLMAP_T__HEADER
|
||||
|
||||
typedef struct Vfs {
|
||||
VfsEntry root;
|
||||
} Vfs;
|
||||
|
||||
void Vfs__ctor(Vfs* self);
|
||||
void Vfs__dtor(Vfs* self);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@ -4,13 +4,13 @@
|
||||
#include "pocketpy/pocketpy.h"
|
||||
#include "pocketpy/interpreter/gc.h"
|
||||
#include "pocketpy/interpreter/frame.h"
|
||||
#include "pocketpy/interpreter/vfs.h"
|
||||
#include "pocketpy/interpreter/modules.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct pk_TypeInfo {
|
||||
typedef struct py_TypeInfo {
|
||||
py_Name name;
|
||||
py_Type base;
|
||||
|
||||
@ -24,23 +24,23 @@ typedef struct pk_TypeInfo {
|
||||
|
||||
c11_vector /*T=py_Name*/ annotated_fields;
|
||||
|
||||
void (*on_end_subclass)(struct pk_TypeInfo*); // backdoor for enum module
|
||||
void (*on_end_subclass)(struct py_TypeInfo*); // backdoor for enum module
|
||||
|
||||
/* Magic Slots */
|
||||
py_TValue magic[64];
|
||||
} pk_TypeInfo;
|
||||
} py_TypeInfo;
|
||||
|
||||
typedef struct pk_VM {
|
||||
typedef struct VM {
|
||||
Frame* top_frame;
|
||||
|
||||
pk_NameDict modules;
|
||||
c11_vector /*T=pk_TypeInfo*/ types;
|
||||
NameDict modules;
|
||||
c11_vector /*T=py_TypeInfo*/ types;
|
||||
|
||||
py_TValue builtins; // builtins module
|
||||
py_TValue main; // __main__ module
|
||||
|
||||
void (*ceval_on_step)(Frame*, Bytecode);
|
||||
unsigned char* (*import_file)(const char*, int*);
|
||||
char* (*import_file)(const char*);
|
||||
void (*print)(const char*);
|
||||
|
||||
py_TValue last_retval;
|
||||
@ -49,20 +49,19 @@ typedef struct pk_VM {
|
||||
|
||||
py_TValue reg[8]; // users' registers
|
||||
|
||||
Vfs __vfs;
|
||||
py_TValue* __curr_class;
|
||||
FuncDecl_ __dynamic_func_decl;
|
||||
py_TValue __vectorcall_buffer[PK_MAX_CO_VARNAMES];
|
||||
|
||||
pk_ManagedHeap heap;
|
||||
ManagedHeap heap;
|
||||
ValueStack stack; // put `stack` at the end for better cache locality
|
||||
} pk_VM;
|
||||
} VM;
|
||||
|
||||
void pk_VM__ctor(pk_VM* self);
|
||||
void pk_VM__dtor(pk_VM* self);
|
||||
void VM__ctor(VM* self);
|
||||
void VM__dtor(VM* self);
|
||||
|
||||
void pk_VM__push_frame(pk_VM* self, Frame* frame);
|
||||
void pk_VM__pop_frame(pk_VM* self);
|
||||
void VM__push_frame(VM* self, Frame* frame);
|
||||
void VM__pop_frame(VM* self);
|
||||
|
||||
bool pk__parse_int_slice(py_Ref slice, int length, int* start, int* stop, int* step);
|
||||
bool pk__normalize_index(int* index, int length);
|
||||
@ -70,14 +69,14 @@ bool pk__normalize_index(int* index, int length);
|
||||
void pk_list__mark(void* ud, void (*marker)(py_TValue*));
|
||||
void pk_dict__mark(void* ud, void (*marker)(py_TValue*));
|
||||
|
||||
typedef enum pk_FrameResult {
|
||||
typedef enum FrameResult {
|
||||
RES_RETURN,
|
||||
RES_CALL,
|
||||
RES_YIELD,
|
||||
RES_ERROR,
|
||||
} pk_FrameResult;
|
||||
} FrameResult;
|
||||
|
||||
pk_FrameResult pk_VM__run_top_frame(pk_VM* self);
|
||||
FrameResult VM__run_top_frame(VM* self);
|
||||
|
||||
py_Type pk_newtype(const char* name,
|
||||
py_Type base,
|
||||
@ -86,7 +85,7 @@ py_Type pk_newtype(const char* name,
|
||||
bool is_python,
|
||||
bool is_sealed);
|
||||
|
||||
pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t argc, uint16_t kwargc, bool opcall);
|
||||
FrameResult VM__vectorcall(VM* self, uint16_t argc, uint16_t kwargc, bool opcall);
|
||||
|
||||
const char* pk_opname(Opcode op);
|
||||
|
||||
@ -101,9 +100,9 @@ bool pk_callmagic(py_Name name, int argc, py_Ref argv);
|
||||
/// Assumes [a, b] are on the stack, performs a binary op.
|
||||
/// The result is stored in `self->last_retval`.
|
||||
/// The stack remains unchanged.
|
||||
bool pk_stack_binaryop(pk_VM* self, py_Name op, py_Name rop);
|
||||
bool pk_stack_binaryop(VM* self, py_Name op, py_Name rop);
|
||||
|
||||
void pk_print_stack(pk_VM* self, Frame* frame, Bytecode byte);
|
||||
void pk_print_stack(VM* self, Frame* frame, Bytecode byte);
|
||||
|
||||
// type registration
|
||||
void pk_object__register();
|
||||
@ -123,11 +122,13 @@ py_Type pk_range__register();
|
||||
py_Type pk_range_iterator__register();
|
||||
py_Type pk_BaseException__register();
|
||||
py_Type pk_Exception__register();
|
||||
py_Type pk_super__register();
|
||||
py_Type pk_property__register();
|
||||
py_Type pk_staticmethod__register();
|
||||
py_Type pk_classmethod__register();
|
||||
|
||||
py_TValue pk_builtins__register();
|
||||
|
||||
void pk__add_module_pkpy();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@ -14,8 +14,8 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct PyObject PyObject;
|
||||
typedef struct pk_VM pk_VM;
|
||||
extern pk_VM* pk_current_vm;
|
||||
typedef struct VM VM;
|
||||
extern VM* pk_current_vm;
|
||||
|
||||
typedef struct py_TValue {
|
||||
py_Type type;
|
||||
|
||||
@ -68,7 +68,7 @@ typedef struct BytecodeEx {
|
||||
} BytecodeEx;
|
||||
|
||||
typedef struct CodeObject {
|
||||
pk_SourceData_ src;
|
||||
SourceData_ src;
|
||||
c11_string* name;
|
||||
|
||||
c11_vector /*T=Bytecode*/ codes;
|
||||
@ -88,7 +88,7 @@ typedef struct CodeObject {
|
||||
int end_line;
|
||||
} CodeObject;
|
||||
|
||||
void CodeObject__ctor(CodeObject* self, pk_SourceData_ src, c11_sv name);
|
||||
void CodeObject__ctor(CodeObject* self, SourceData_ src, c11_sv name);
|
||||
void CodeObject__dtor(CodeObject* self);
|
||||
int CodeObject__add_varname(CodeObject* self, py_Name name);
|
||||
void CodeObject__gc_mark(const CodeObject* self);
|
||||
@ -118,7 +118,7 @@ typedef struct FuncDecl {
|
||||
|
||||
typedef FuncDecl* FuncDecl_;
|
||||
|
||||
FuncDecl_ FuncDecl__rcnew(pk_SourceData_ src, c11_sv name);
|
||||
FuncDecl_ FuncDecl__rcnew(SourceData_ src, c11_sv name);
|
||||
bool FuncDecl__is_duplicated_arg(const FuncDecl* self, py_Name name);
|
||||
void FuncDecl__add_arg(FuncDecl* self, py_Name name);
|
||||
void FuncDecl__add_kwarg(FuncDecl* self, py_Name name, const py_TValue* value);
|
||||
@ -139,7 +139,7 @@ typedef struct Function {
|
||||
FuncDecl_ decl;
|
||||
py_TValue module; // weak ref
|
||||
PyObject* clazz; // weak ref
|
||||
pk_NameDict* closure; // strong ref
|
||||
NameDict* closure; // strong ref
|
||||
py_CFunction cfunc; // wrapped C function
|
||||
} Function;
|
||||
|
||||
|
||||
@ -12,14 +12,14 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct{
|
||||
pk_SourceData_ src;
|
||||
SourceData_ src;
|
||||
int lineno;
|
||||
char msg[100];
|
||||
} Error;
|
||||
|
||||
void py_BaseException__set_lineno(py_Ref, int lineno, const CodeObject* code);
|
||||
int py_BaseException__get_lineno(py_Ref, const CodeObject* code);
|
||||
void py_BaseException__stpush(py_Ref, pk_SourceData_ src, int lineno, const char* func_name);
|
||||
void py_BaseException__stpush(py_Ref, SourceData_ src, int lineno, const char* func_name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@ -12,7 +12,7 @@ extern "C" {
|
||||
#define SMALLMAP_T__HEADER
|
||||
#define K uint16_t
|
||||
#define V py_TValue
|
||||
#define NAME pk_NameDict
|
||||
#define NAME NameDict
|
||||
#include "pocketpy/xmacros/smallmap.h"
|
||||
#undef SMALLMAP_T__HEADER
|
||||
|
||||
|
||||
@ -22,10 +22,10 @@ typedef struct PyObject {
|
||||
// | HEADER | <dict> | <userdata>
|
||||
|
||||
py_TValue* PyObject__slots(PyObject* self);
|
||||
pk_NameDict* PyObject__dict(PyObject* self);
|
||||
NameDict* PyObject__dict(PyObject* self);
|
||||
void* PyObject__userdata(PyObject* self);
|
||||
|
||||
#define PK_OBJ_SLOTS_SIZE(slots) ((slots) >= 0 ? sizeof(py_TValue) * (slots) : sizeof(pk_NameDict))
|
||||
#define PK_OBJ_SLOTS_SIZE(slots) ((slots) >= 0 ? sizeof(py_TValue) * (slots) : sizeof(NameDict))
|
||||
|
||||
PyObject* PyObject__new(py_Type type, int slots, int size);
|
||||
void PyObject__delete(PyObject* self);
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct pk_SourceData {
|
||||
struct SourceData {
|
||||
RefCounted rc;
|
||||
enum py_CompileMode mode;
|
||||
bool is_precompiled;
|
||||
@ -23,17 +23,17 @@ struct pk_SourceData {
|
||||
c11_vector /*T=c11_string* */ _precompiled_tokens;
|
||||
};
|
||||
|
||||
typedef struct pk_SourceData* pk_SourceData_;
|
||||
typedef struct SourceData* SourceData_;
|
||||
|
||||
pk_SourceData_ pk_SourceData__rcnew(const char* source,
|
||||
SourceData_ SourceData__rcnew(const char* source,
|
||||
const char* filename,
|
||||
enum py_CompileMode mode,
|
||||
bool is_dynamic);
|
||||
bool pk_SourceData__get_line(const struct pk_SourceData* self,
|
||||
bool SourceData__get_line(const struct SourceData* self,
|
||||
int lineno,
|
||||
const char** st,
|
||||
const char** ed);
|
||||
void pk_SourceData__snapshot(const struct pk_SourceData* self,
|
||||
void SourceData__snapshot(const struct SourceData* self,
|
||||
c11_sbuf* ss,
|
||||
int lineno,
|
||||
const char* cursor,
|
||||
|
||||
@ -7,6 +7,10 @@
|
||||
#include "pocketpy/common/config.h"
|
||||
#include "pocketpy/common/export.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/************* Public Types *************/
|
||||
typedef struct py_TValue py_TValue;
|
||||
typedef uint16_t py_Name;
|
||||
@ -94,6 +98,7 @@ void py_newslice(py_Ref);
|
||||
void py_newnativefunc(py_Ref out, py_CFunction);
|
||||
py_Name
|
||||
py_newfunction(py_Ref out, const char* sig, py_CFunction f, const char* docstring, int slots);
|
||||
void py_newboundmethod(py_Ref out, py_Ref self, py_Ref func);
|
||||
|
||||
/************* Name Convertions *************/
|
||||
py_Name py_name(const char*);
|
||||
@ -121,7 +126,7 @@ void* py_newobject(py_Ref out, py_Type type, int slots, int udsize);
|
||||
/************* Type Cast *************/
|
||||
py_i64 py_toint(py_Ref);
|
||||
py_f64 py_tofloat(py_Ref);
|
||||
bool py_castfloat(py_Ref, py_f64* out);
|
||||
bool py_castfloat(py_Ref, py_f64* out) PY_RAISE;
|
||||
bool py_tobool(py_Ref);
|
||||
py_Type py_totype(py_Ref);
|
||||
const char* py_tostr(py_Ref);
|
||||
@ -186,6 +191,7 @@ py_GlobalRef py_retval();
|
||||
py_ObjectRef py_getdict(py_Ref self, py_Name name);
|
||||
void py_setdict(py_Ref self, py_Name name, py_Ref val);
|
||||
bool py_deldict(py_Ref self, py_Name name);
|
||||
py_ObjectRef py_emplacedict(py_Ref self, py_Name name);
|
||||
|
||||
/// Get the reference of the i-th slot of the object.
|
||||
/// The object must have slots and `i` must be in range.
|
||||
@ -198,6 +204,7 @@ void py_bind(py_Ref obj, const char* sig, py_CFunction f);
|
||||
// old style argc-based bindings
|
||||
void py_bindmethod(py_Type type, const char* name, py_CFunction f);
|
||||
void py_bindfunc(py_Ref obj, const char* name, py_CFunction f);
|
||||
void py_bindproperty(py_Type type, const char* name, py_CFunction getter, py_CFunction setter);
|
||||
|
||||
#define py_bindmagic(type, __magic__, f) py_newnativefunc(py_tpmagic((type), __magic__), (f))
|
||||
|
||||
@ -257,6 +264,11 @@ py_StackRef py_pushtmp();
|
||||
/// If returns true: [self] -> [unbound, self]
|
||||
/// If returns false: [self] -> [self] (no change)
|
||||
bool py_pushmethod(py_Name name);
|
||||
/// A stack operation that calls a function.
|
||||
/// It assumes `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;
|
||||
|
||||
/************* Modules *************/
|
||||
py_TmpRef py_newmodule(const char* path);
|
||||
@ -264,20 +276,25 @@ py_TmpRef py_getmodule(const char* path);
|
||||
|
||||
/// Import a module.
|
||||
/// The result will be set to `py_retval()`.
|
||||
bool py_import(const char* path) PY_RAISE;
|
||||
/// -1: error, 0: not found, 1: success
|
||||
int py_import(const char* path) PY_RAISE;
|
||||
|
||||
/************* Errors *************/
|
||||
/// Raise an exception by name and message. Always returns false.
|
||||
bool py_exception(const char* name, const char* fmt, ...) PY_RAISE;
|
||||
/// Raise an expection object. Always returns false.
|
||||
bool py_raise(py_Ref) PY_RAISE;
|
||||
/// Print the last error to the console.
|
||||
/// Print the current exception.
|
||||
void py_printexc();
|
||||
/// Format the last error to a string.
|
||||
/// Format the current exception.
|
||||
char* py_formatexc();
|
||||
/// Check if an exception is raised.
|
||||
bool py_checkexc();
|
||||
/// Clear the current exception.
|
||||
void py_clearexc(py_StackRef p0);
|
||||
|
||||
#define IOError(...) py_exception("IOError", __VA_ARGS__)
|
||||
#define OSError(...) py_exception("OSError", __VA_ARGS__)
|
||||
#define NameError(n) py_exception("NameError", "name '%n' is not defined", (n))
|
||||
#define TypeError(...) py_exception("TypeError", __VA_ARGS__)
|
||||
#define RuntimeError(...) py_exception("RuntimeError", __VA_ARGS__)
|
||||
@ -317,11 +334,6 @@ bool py_iter(py_Ref) PY_RAISE;
|
||||
int py_next(py_Ref) PY_RAISE;
|
||||
/// Python equivalent to `lhs is rhs`.
|
||||
bool py_isidentical(py_Ref, py_Ref);
|
||||
/// A stack operation that calls a function.
|
||||
/// It assumes `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;
|
||||
/// Call a function.
|
||||
/// It prepares the stack and then performs a `vectorcall(argc, 0, false)`.
|
||||
/// The result will be set to `py_retval()`.
|
||||
@ -360,13 +372,8 @@ bool py_dict__contains(py_Ref self, py_Ref key);
|
||||
int py_dict__len(py_Ref self);
|
||||
bool py_dict__apply(py_Ref self, bool (*f)(py_Ref key, py_Ref val, void* ctx), void* ctx);
|
||||
|
||||
/************* Virtual File System *************/
|
||||
unsigned char* py_vfsread(const char* path, int* size);
|
||||
bool py_vfswrite(const char* path, unsigned char* data, int size);
|
||||
char** py_vfslist(const char* path, int* length);
|
||||
|
||||
/************* Others *************/
|
||||
int py_replinput(char* buf);
|
||||
int py_replinput(char* buf, int max_size);
|
||||
|
||||
/// Python favored string formatting. (just put here, not for users)
|
||||
/// %d: int
|
||||
|
||||
@ -56,7 +56,6 @@ MAGIC_METHOD(__exit__)
|
||||
MAGIC_METHOD(__name__)
|
||||
MAGIC_METHOD(__all__)
|
||||
MAGIC_METHOD(__package__)
|
||||
MAGIC_METHOD(__module_is_pending__)
|
||||
MAGIC_METHOD(__path__)
|
||||
MAGIC_METHOD(__class__)
|
||||
MAGIC_METHOD(__abs__)
|
||||
|
||||
15
prebuild.py
15
prebuild.py
@ -31,6 +31,8 @@ with open("include/pocketpy/common/_generated.h", "wt", encoding='utf-8', newlin
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
const char* load_kPythonLib(const char* name);
|
||||
|
||||
'''
|
||||
for key in sorted(sources.keys()):
|
||||
value = sources[key]
|
||||
@ -45,9 +47,20 @@ extern "C" {
|
||||
with open("src/common/_generated.c", "wt", encoding='utf-8', newline='\n') as f:
|
||||
data = '''// generated by prebuild.py
|
||||
#include "pocketpy/common/_generated.h"
|
||||
|
||||
#include <string.h>
|
||||
'''
|
||||
for key in sorted(sources.keys()):
|
||||
value = sources[key]
|
||||
data += f'const char kPythonLibs_{key}[] = {value};\n'
|
||||
f.write(data)
|
||||
|
||||
f.write("\n")
|
||||
f.write("const char* load_kPythonLib(const char* name) {\n")
|
||||
f.write(" if (strchr(name, '.') != NULL) return NULL;\n")
|
||||
for key in sorted(sources.keys()):
|
||||
if key.startswith('_'):
|
||||
continue
|
||||
f.write(f' if (strcmp(name, "{key}") == 0) return kPythonLibs_{key};\n')
|
||||
f.write(" return NULL;\n")
|
||||
f.write("}\n")
|
||||
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
from pkpy import next
|
||||
|
||||
class cache:
|
||||
def __init__(self, f):
|
||||
self.f = f
|
||||
@ -13,9 +11,10 @@ class cache:
|
||||
def reduce(function, sequence, initial=...):
|
||||
it = iter(sequence)
|
||||
if initial is ...:
|
||||
value = next(it)
|
||||
if value is StopIteration:
|
||||
raise TypeError("reduce() of empty iterable with no initial value")
|
||||
try:
|
||||
value = next(it)
|
||||
except StopIteration:
|
||||
raise TypeError("reduce() of empty sequence with no initial value")
|
||||
else:
|
||||
value = initial
|
||||
for element in it:
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -242,13 +242,13 @@ static FixedMemoryPool PoolExpr;
|
||||
static FixedMemoryPool PoolFrame;
|
||||
static MemoryPool PoolObject;
|
||||
|
||||
void pk_MemoryPools__initialize(){
|
||||
void MemoryPools__initialize(){
|
||||
FixedMemoryPool__ctor(&PoolExpr, kPoolExprBlockSize, 64);
|
||||
FixedMemoryPool__ctor(&PoolFrame, kPoolFrameBlockSize, 128);
|
||||
MemoryPool__ctor(&PoolObject);
|
||||
}
|
||||
|
||||
void pk_MemoryPools__finalize(){
|
||||
void MemoryPools__finalize(){
|
||||
FixedMemoryPool__dtor(&PoolExpr);
|
||||
FixedMemoryPool__dtor(&PoolFrame);
|
||||
MemoryPool__dtor(&PoolObject);
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static void pk_SourceData__ctor(struct pk_SourceData* self,
|
||||
static void SourceData__ctor(struct SourceData* self,
|
||||
const char* source,
|
||||
const char* filename,
|
||||
enum py_CompileMode mode,
|
||||
@ -31,7 +31,7 @@ static void pk_SourceData__ctor(struct pk_SourceData* self,
|
||||
c11_vector__push(const char*, &self->line_starts, self->source->data);
|
||||
}
|
||||
|
||||
static void pk_SourceData__dtor(struct pk_SourceData* self) {
|
||||
static void SourceData__dtor(struct SourceData* self) {
|
||||
c11_string__delete(self->filename);
|
||||
c11_string__delete(self->source);
|
||||
|
||||
@ -43,18 +43,18 @@ static void pk_SourceData__dtor(struct pk_SourceData* self) {
|
||||
c11_vector__dtor(&self->_precompiled_tokens);
|
||||
}
|
||||
|
||||
pk_SourceData_ pk_SourceData__rcnew(const char* source,
|
||||
SourceData_ SourceData__rcnew(const char* source,
|
||||
const char* filename,
|
||||
enum py_CompileMode mode,
|
||||
bool is_dynamic) {
|
||||
pk_SourceData_ self = malloc(sizeof(struct pk_SourceData));
|
||||
pk_SourceData__ctor(self, source, filename, mode, is_dynamic);
|
||||
SourceData_ self = malloc(sizeof(struct SourceData));
|
||||
SourceData__ctor(self, source, filename, mode, is_dynamic);
|
||||
self->rc.count = 1;
|
||||
self->rc.dtor = (void (*)(void*))pk_SourceData__dtor;
|
||||
self->rc.dtor = (void (*)(void*))SourceData__dtor;
|
||||
return self;
|
||||
}
|
||||
|
||||
bool pk_SourceData__get_line(const struct pk_SourceData* self,
|
||||
bool SourceData__get_line(const struct SourceData* self,
|
||||
int lineno,
|
||||
const char** st,
|
||||
const char** ed) {
|
||||
@ -71,7 +71,7 @@ bool pk_SourceData__get_line(const struct pk_SourceData* self,
|
||||
return true;
|
||||
}
|
||||
|
||||
void pk_SourceData__snapshot(const struct pk_SourceData* self,
|
||||
void SourceData__snapshot(const struct SourceData* self,
|
||||
c11_sbuf* ss,
|
||||
int lineno,
|
||||
const char* cursor,
|
||||
@ -86,7 +86,7 @@ void pk_SourceData__snapshot(const struct pk_SourceData* self,
|
||||
if(!self->is_precompiled) {
|
||||
c11_sbuf__write_char(ss, '\n');
|
||||
const char *st = NULL, *ed;
|
||||
if(pk_SourceData__get_line(self, lineno, &st, &ed)) {
|
||||
if(SourceData__get_line(self, lineno, &st, &ed)) {
|
||||
while(st < ed && isblank(*st))
|
||||
++st;
|
||||
if(st < ed) {
|
||||
|
||||
@ -147,7 +147,7 @@ c11_string* c11_sbuf__submit(c11_sbuf* self) {
|
||||
return retval;
|
||||
}
|
||||
|
||||
void c11_sbuf__py_submit(c11_sbuf *self, py_Ref out){
|
||||
void c11_sbuf__py_submit(c11_sbuf* self, py_Ref out) {
|
||||
c11_string* res = c11_sbuf__submit(self);
|
||||
py_newstrn(out, res->data, res->size);
|
||||
c11_string__delete(res);
|
||||
@ -233,7 +233,9 @@ void pk_sprintf(c11_sbuf* ss, const char* fmt, ...) {
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
int py_replinput(char* buf) {
|
||||
int py_replinput(char* buf, int max_size) {
|
||||
buf[0] = '\0';
|
||||
|
||||
int size = 0;
|
||||
bool multiline = false;
|
||||
printf(">>> ");
|
||||
@ -252,7 +254,7 @@ int py_replinput(char* buf) {
|
||||
printf("... ");
|
||||
}
|
||||
} else {
|
||||
if(last == ':' || last == '(' || last == '[' || last == '{') {
|
||||
if(last == ':' || last == '(' || last == '[' || last == '{' || buf[0] == '@') {
|
||||
printf("... ");
|
||||
multiline = true;
|
||||
} else {
|
||||
@ -261,6 +263,11 @@ int py_replinput(char* buf) {
|
||||
}
|
||||
}
|
||||
|
||||
if(size == max_size - 1) {
|
||||
buf[size] = '\0';
|
||||
return size;
|
||||
}
|
||||
|
||||
buf[size++] = c;
|
||||
}
|
||||
|
||||
|
||||
@ -165,6 +165,16 @@ int c11_sv__count(c11_sv self, c11_sv sub) {
|
||||
return cnt;
|
||||
}
|
||||
|
||||
bool c11_sv__startswith(c11_sv self, c11_sv prefix) {
|
||||
if(prefix.size > self.size) return false;
|
||||
return memcmp(self.data, prefix.data, prefix.size) == 0;
|
||||
}
|
||||
|
||||
bool c11_sv__endswith(c11_sv self, c11_sv suffix) {
|
||||
if(suffix.size > self.size) return false;
|
||||
return memcmp(self.data + self.size - suffix.size, suffix.data, suffix.size) == 0;
|
||||
}
|
||||
|
||||
c11_vector /* T=c11_sv */ c11_sv__split(c11_sv self, char sep) {
|
||||
c11_vector retval;
|
||||
c11_vector__ctor(&retval, sizeof(c11_sv));
|
||||
|
||||
@ -1435,13 +1435,13 @@ typedef struct PrattRule {
|
||||
const static PrattRule rules[TK__COUNT__];
|
||||
|
||||
typedef struct Compiler {
|
||||
pk_SourceData_ src; // weakref
|
||||
pk_TokenArray tokens;
|
||||
SourceData_ src; // weakref
|
||||
TokenArray tokens;
|
||||
int i;
|
||||
c11_vector /*T=CodeEmitContext*/ contexts;
|
||||
} Compiler;
|
||||
|
||||
static void Compiler__ctor(Compiler* self, pk_SourceData_ src, pk_TokenArray tokens) {
|
||||
static void Compiler__ctor(Compiler* self, SourceData_ src, TokenArray tokens) {
|
||||
self->src = src;
|
||||
self->tokens = tokens;
|
||||
self->i = 0;
|
||||
@ -1449,7 +1449,7 @@ static void Compiler__ctor(Compiler* self, pk_SourceData_ src, pk_TokenArray tok
|
||||
}
|
||||
|
||||
static void Compiler__dtor(Compiler* self) {
|
||||
pk_TokenArray__dtor(&self->tokens);
|
||||
TokenArray__dtor(&self->tokens);
|
||||
c11__foreach(Ctx, &self->contexts, ctx) Ctx__dtor(ctx);
|
||||
c11_vector__dtor(&self->contexts);
|
||||
}
|
||||
@ -1470,8 +1470,8 @@ static void Compiler__dtor(Compiler* self) {
|
||||
if(!match(expected)) \
|
||||
return SyntaxError(self, \
|
||||
"expected '%s', got '%s'", \
|
||||
pk_TokenSymbols[expected], \
|
||||
pk_TokenSymbols[curr()->type]);
|
||||
TokenSymbols[expected], \
|
||||
TokenSymbols[curr()->type]);
|
||||
#define consume_end_stmt() \
|
||||
if(!match_end_stmt(self)) return SyntaxError(self, "expected statement end")
|
||||
|
||||
@ -1531,7 +1531,7 @@ static bool match_end_stmt(Compiler* self) {
|
||||
static Error* parse_expression(Compiler* self, int precedence, bool allow_slice) {
|
||||
PrattCallback prefix = rules[curr()->type].prefix;
|
||||
if(!prefix || (curr()->type == TK_COLON && !allow_slice)) {
|
||||
return SyntaxError(self, "expected an expression, got %s", pk_TokenSymbols[curr()->type]);
|
||||
return SyntaxError(self, "expected an expression, got %s", TokenSymbols[curr()->type]);
|
||||
}
|
||||
advance();
|
||||
Error* err;
|
||||
@ -2477,6 +2477,7 @@ __EAT_DOTS_END:
|
||||
OP_IMPORT_PATH,
|
||||
Ctx__add_const_string(ctx(), c11_string__sv(path)),
|
||||
prev()->line);
|
||||
c11_string__delete(path);
|
||||
consume(TK_IMPORT);
|
||||
|
||||
if(match(TK_MUL)) {
|
||||
@ -2781,9 +2782,9 @@ Error* Compiler__compile(Compiler* self, CodeObject* out) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Error* pk_compile(pk_SourceData_ src, CodeObject* out) {
|
||||
pk_TokenArray tokens;
|
||||
Error* err = pk_Lexer__process(src, &tokens);
|
||||
Error* pk_compile(SourceData_ src, CodeObject* out) {
|
||||
TokenArray tokens;
|
||||
Error* err = Lexer__process(src, &tokens);
|
||||
if(err) return err;
|
||||
|
||||
// Token* data = (Token*)tokens.data;
|
||||
@ -2791,7 +2792,7 @@ Error* pk_compile(pk_SourceData_ src, CodeObject* out) {
|
||||
// for(int i = 0; i < tokens.count; i++) {
|
||||
// Token* t = data + i;
|
||||
// c11_string* tmp = c11_string__new2(t->start, t->length);
|
||||
// printf("[%d] %s: %s\n", t->line, pk_TokenSymbols[t->type], tmp->data);
|
||||
// printf("[%d] %s: %s\n", t->line, TokenSymbols[t->type], tmp->data);
|
||||
// c11_string__delete(tmp);
|
||||
// }
|
||||
|
||||
|
||||
@ -10,8 +10,8 @@
|
||||
|
||||
#define is_raw_string_used(t) ((t) == TK_ID || (t) == TK_LONG)
|
||||
|
||||
typedef struct pk_Lexer{
|
||||
pk_SourceData_ src;
|
||||
typedef struct Lexer{
|
||||
SourceData_ src;
|
||||
const char* token_start;
|
||||
const char* curr_char;
|
||||
int current_line;
|
||||
@ -19,7 +19,7 @@ typedef struct pk_Lexer{
|
||||
|
||||
c11_vector/*T=Token*/ nexts;
|
||||
c11_vector/*T=int*/ indents;
|
||||
} pk_Lexer;
|
||||
} Lexer;
|
||||
|
||||
typedef struct TokenDeserializer {
|
||||
const char* curr;
|
||||
@ -37,7 +37,7 @@ double TokenDeserializer__read_float(TokenDeserializer* self, char c);
|
||||
|
||||
const static TokenValue EmptyTokenValue;
|
||||
|
||||
static void pk_Lexer__ctor(pk_Lexer* self, pk_SourceData_ src){
|
||||
static void Lexer__ctor(Lexer* self, SourceData_ src){
|
||||
PK_INCREF(src);
|
||||
self->src = src;
|
||||
self->curr_char = self->token_start = src->source->data;
|
||||
@ -47,20 +47,20 @@ static void pk_Lexer__ctor(pk_Lexer* self, pk_SourceData_ src){
|
||||
c11_vector__ctor(&self->indents, sizeof(int));
|
||||
}
|
||||
|
||||
static void pk_Lexer__dtor(pk_Lexer* self){
|
||||
static void Lexer__dtor(Lexer* self){
|
||||
PK_DECREF(self->src);
|
||||
c11_vector__dtor(&self->nexts);
|
||||
c11_vector__dtor(&self->indents);
|
||||
}
|
||||
|
||||
static char eatchar(pk_Lexer* self){
|
||||
static char eatchar(Lexer* self){
|
||||
char c = *self->curr_char;
|
||||
assert(c != '\n'); // eatchar() cannot consume a newline
|
||||
self->curr_char++;
|
||||
return c;
|
||||
}
|
||||
|
||||
static char eatchar_include_newline(pk_Lexer* self){
|
||||
static char eatchar_include_newline(Lexer* self){
|
||||
char c = *self->curr_char;
|
||||
self->curr_char++;
|
||||
if(c == '\n') {
|
||||
@ -70,7 +70,7 @@ static char eatchar_include_newline(pk_Lexer* self){
|
||||
return c;
|
||||
}
|
||||
|
||||
static int eat_spaces(pk_Lexer* self){
|
||||
static int eat_spaces(Lexer* self){
|
||||
int count = 0;
|
||||
while(true) {
|
||||
switch(*self->curr_char) {
|
||||
@ -82,13 +82,13 @@ static int eat_spaces(pk_Lexer* self){
|
||||
}
|
||||
}
|
||||
|
||||
static bool matchchar(pk_Lexer* self, char c){
|
||||
static bool matchchar(Lexer* self, char c){
|
||||
if(*self->curr_char != c) return false;
|
||||
eatchar_include_newline(self);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool match_n_chars(pk_Lexer* self, int n, char c0){
|
||||
static bool match_n_chars(Lexer* self, int n, char c0){
|
||||
const char* c = self->curr_char;
|
||||
for(int i = 0; i < n; i++) {
|
||||
if(*c == '\0') return false;
|
||||
@ -100,14 +100,14 @@ static bool match_n_chars(pk_Lexer* self, int n, char c0){
|
||||
return true;
|
||||
}
|
||||
|
||||
static void skip_line_comment(pk_Lexer* self){
|
||||
static void skip_line_comment(Lexer* self){
|
||||
while(*self->curr_char) {
|
||||
if(*self->curr_char == '\n') return;
|
||||
eatchar(self);
|
||||
}
|
||||
}
|
||||
|
||||
static void add_token_with_value(pk_Lexer* self, TokenIndex type, TokenValue value){
|
||||
static void add_token_with_value(Lexer* self, TokenIndex type, TokenValue value){
|
||||
switch(type) {
|
||||
case TK_LBRACE:
|
||||
case TK_LBRACKET:
|
||||
@ -142,18 +142,18 @@ static void add_token_with_value(pk_Lexer* self, TokenIndex type, TokenValue val
|
||||
}
|
||||
}
|
||||
|
||||
static void add_token(pk_Lexer* self, TokenIndex type){
|
||||
static void add_token(Lexer* self, TokenIndex type){
|
||||
add_token_with_value(self, type, EmptyTokenValue);
|
||||
}
|
||||
|
||||
static void add_token_2(pk_Lexer* self, char c, TokenIndex one, TokenIndex two){
|
||||
static void add_token_2(Lexer* self, char c, TokenIndex one, TokenIndex two){
|
||||
if(matchchar(self, c))
|
||||
add_token(self, two);
|
||||
else
|
||||
add_token(self, one);
|
||||
}
|
||||
|
||||
static bool eat_indentation(pk_Lexer* self){
|
||||
static bool eat_indentation(Lexer* self){
|
||||
if(self->brackets_level > 0) return true;
|
||||
int spaces = eat_spaces(self);
|
||||
if(*self->curr_char == '#') skip_line_comment(self);
|
||||
@ -192,7 +192,7 @@ static bool is_possible_number_char(char c){
|
||||
}
|
||||
|
||||
/******************************/
|
||||
static Error* SyntaxError(pk_Lexer* self, const char* fmt, ...){
|
||||
static Error* SyntaxError(Lexer* self, const char* fmt, ...){
|
||||
Error* err = malloc(sizeof(Error));
|
||||
err->src = self->src;
|
||||
PK_INCREF(self->src);
|
||||
@ -207,7 +207,7 @@ static Error* SyntaxError(pk_Lexer* self, const char* fmt, ...){
|
||||
return err;
|
||||
}
|
||||
|
||||
static Error* eat_name(pk_Lexer* self){
|
||||
static Error* eat_name(Lexer* self){
|
||||
self->curr_char--;
|
||||
while(true) {
|
||||
unsigned char c = *self->curr_char;
|
||||
@ -247,7 +247,7 @@ static Error* eat_name(pk_Lexer* self){
|
||||
if(length == 0) return SyntaxError(self, "@id contains invalid char");
|
||||
c11_sv name = {self->token_start, length};
|
||||
|
||||
const char** KW_BEGIN = pk_TokenSymbols + TK_FALSE;
|
||||
const char** KW_BEGIN = TokenSymbols + TK_FALSE;
|
||||
int KW_COUNT = TK__COUNT__ - TK_FALSE;
|
||||
#define less(a, b) (c11_sv__cmp2(b, a) > 0)
|
||||
int out;
|
||||
@ -262,7 +262,7 @@ static Error* eat_name(pk_Lexer* self){
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static Error* eat_string_until(pk_Lexer* self, char quote, bool raw, c11_string** out) {
|
||||
static Error* eat_string_until(Lexer* self, char quote, bool raw, c11_string** out) {
|
||||
// previous char is quote
|
||||
bool quote3 = match_n_chars(self, 2, quote);
|
||||
c11_sbuf buff;
|
||||
@ -321,7 +321,7 @@ enum StringType {
|
||||
NORMAL_BYTES
|
||||
};
|
||||
|
||||
static Error* eat_string(pk_Lexer* self, char quote, enum StringType type){
|
||||
static Error* eat_string(Lexer* self, char quote, enum StringType type){
|
||||
c11_string* s;
|
||||
Error* err = eat_string_until(self, quote, type == RAW_STRING, &s);
|
||||
if(err) return err;
|
||||
@ -336,7 +336,7 @@ static Error* eat_string(pk_Lexer* self, char quote, enum StringType type){
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static Error* eat_number(pk_Lexer* self){
|
||||
static Error* eat_number(Lexer* self){
|
||||
const char* i = self->token_start;
|
||||
while(is_possible_number_char(*i)) i++;
|
||||
|
||||
@ -389,7 +389,7 @@ static Error* eat_number(pk_Lexer* self){
|
||||
return SyntaxError(self, "invalid number literal");
|
||||
}
|
||||
|
||||
static Error* lex_one_token(pk_Lexer* self, bool* eof){
|
||||
static Error* lex_one_token(Lexer* self, bool* eof){
|
||||
*eof = false;
|
||||
while(*self->curr_char) {
|
||||
self->token_start = self->curr_char;
|
||||
@ -532,7 +532,7 @@ static Error* lex_one_token(pk_Lexer* self, bool* eof){
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static Error* from_precompiled(pk_Lexer* self) {
|
||||
static Error* from_precompiled(Lexer* self) {
|
||||
TokenDeserializer deserializer;
|
||||
TokenDeserializer__ctor(&deserializer, self->src->source->data);
|
||||
|
||||
@ -603,14 +603,14 @@ static Error* from_precompiled(pk_Lexer* self) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Error* pk_Lexer__process(pk_SourceData_ src, pk_TokenArray* out_tokens){
|
||||
pk_Lexer lexer;
|
||||
pk_Lexer__ctor(&lexer, src);
|
||||
Error* Lexer__process(SourceData_ src, TokenArray* out_tokens){
|
||||
Lexer lexer;
|
||||
Lexer__ctor(&lexer, src);
|
||||
|
||||
if(src->is_precompiled) {
|
||||
Error* err = from_precompiled(&lexer);
|
||||
// TODO: set out tokens
|
||||
pk_Lexer__dtor(&lexer);
|
||||
Lexer__dtor(&lexer);
|
||||
return err;
|
||||
}
|
||||
// push initial tokens
|
||||
@ -622,21 +622,21 @@ Error* pk_Lexer__process(pk_SourceData_ src, pk_TokenArray* out_tokens){
|
||||
while(!eof) {
|
||||
void* err = lex_one_token(&lexer, &eof);
|
||||
if(err){
|
||||
pk_Lexer__dtor(&lexer);
|
||||
Lexer__dtor(&lexer);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
// set out_tokens
|
||||
*out_tokens = c11_vector__submit(&lexer.nexts);
|
||||
|
||||
pk_Lexer__dtor(&lexer);
|
||||
Lexer__dtor(&lexer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Error* pk_Lexer__process_and_dump(pk_SourceData_ src, c11_string** out) {
|
||||
Error* Lexer__process_and_dump(SourceData_ src, c11_string** out) {
|
||||
assert(!src->is_precompiled);
|
||||
pk_TokenArray nexts; // output tokens
|
||||
Error* err = pk_Lexer__process(src, &nexts);
|
||||
TokenArray nexts; // output tokens
|
||||
Error* err = Lexer__process(src, &nexts);
|
||||
if(err) return err;
|
||||
|
||||
c11_sbuf ss;
|
||||
@ -729,7 +729,7 @@ Error* pk_Lexer__process_and_dump(pk_SourceData_ src, c11_string** out) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void pk_TokenArray__dtor(pk_TokenArray *self){
|
||||
void TokenArray__dtor(TokenArray *self){
|
||||
Token* data = self->data;
|
||||
for(int i=0; i<self->count; i++){
|
||||
if(data[i].value.index == TokenValue_STR){
|
||||
@ -739,7 +739,7 @@ void pk_TokenArray__dtor(pk_TokenArray *self){
|
||||
c11_array__dtor(self);
|
||||
}
|
||||
|
||||
const char* pk_TokenSymbols[] = {
|
||||
const char* TokenSymbols[] = {
|
||||
"@eof", "@eol", "@sof",
|
||||
"@id", "@num", "@str", "@fstr", "@long", "@bytes", "@imag",
|
||||
"@indent", "@dedent",
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
#include "pocketpy/objects/error.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
static bool stack_unpack_sequence(pk_VM* self, uint16_t arg);
|
||||
static bool stack_unpack_sequence(VM* self, uint16_t arg);
|
||||
static bool format_object(py_Ref obj, c11_sv spec);
|
||||
|
||||
#define DISPATCH() \
|
||||
@ -54,7 +54,7 @@ static bool format_object(py_Ref obj, c11_sv spec);
|
||||
|
||||
#define vectorcall_opcall(argc, kwargc) \
|
||||
do { \
|
||||
pk_FrameResult res = pk_VM__vectorcall(self, (argc), (kwargc), true); \
|
||||
FrameResult res = VM__vectorcall(self, (argc), (kwargc), true); \
|
||||
switch(res) { \
|
||||
case RES_RETURN: PUSH(&self->last_retval); break; \
|
||||
case RES_CALL: frame = self->top_frame; goto __NEXT_FRAME; \
|
||||
@ -75,7 +75,7 @@ static bool unpack_dict_to_buffer(py_Ref key, py_Ref val, void* ctx) {
|
||||
return TypeError("keywords must be strings, not '%t'", key->type);
|
||||
}
|
||||
|
||||
pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
||||
FrameResult VM__run_top_frame(VM* self) {
|
||||
Frame* frame = self->top_frame;
|
||||
const Frame* base_frame = frame;
|
||||
|
||||
@ -139,7 +139,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
||||
ud->closure = FastLocals__to_namedict(frame->locals, frame->locals_co);
|
||||
py_Name name = py_namev(c11_string__sv(decl->code.name));
|
||||
// capture itself to allow recursion
|
||||
pk_NameDict__set(ud->closure, name, *SP());
|
||||
NameDict__set(ud->closure, name, *SP());
|
||||
}
|
||||
SP()++;
|
||||
DISPATCH();
|
||||
@ -257,6 +257,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
||||
// fallback to getattr
|
||||
if(py_getattr(TOP(), byte.arg)) {
|
||||
py_assign(TOP(), py_retval());
|
||||
py_newnil(SP()++);
|
||||
} else {
|
||||
goto __ERROR;
|
||||
}
|
||||
@ -618,7 +619,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
||||
DISPATCH();
|
||||
}
|
||||
case OP_CALL: {
|
||||
pk_ManagedHeap__collect_if_needed(&self->heap);
|
||||
ManagedHeap__collect_if_needed(&self->heap);
|
||||
vectorcall_opcall(byte.arg & 0xFF, byte.arg >> 8);
|
||||
DISPATCH();
|
||||
}
|
||||
@ -683,7 +684,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
||||
} else {
|
||||
py_newnone(&self->last_retval);
|
||||
}
|
||||
pk_VM__pop_frame(self);
|
||||
VM__pop_frame(self);
|
||||
if(frame == base_frame) { // [ frameBase<- ]
|
||||
return RES_RETURN;
|
||||
} else {
|
||||
@ -757,15 +758,20 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
||||
////////
|
||||
case OP_IMPORT_PATH: {
|
||||
py_Ref path_object = c11__at(py_TValue, &frame->co->consts, byte.arg);
|
||||
bool ok = py_import(py_tostr(path_object));
|
||||
if(!ok) goto __ERROR;
|
||||
const char* path = py_tostr(path_object);
|
||||
int res = py_import(path);
|
||||
if(res == -1) goto __ERROR;
|
||||
if(res == 0) {
|
||||
ImportError("module '%s' not found", path);
|
||||
goto __ERROR;
|
||||
}
|
||||
PUSH(py_retval());
|
||||
DISPATCH();
|
||||
}
|
||||
case OP_POP_IMPORT_STAR: {
|
||||
// [module]
|
||||
pk_NameDict* dict = PyObject__dict(TOP()->_obj);
|
||||
py_Ref all = pk_NameDict__try_get(dict, __all__);
|
||||
NameDict* dict = PyObject__dict(TOP()->_obj);
|
||||
py_Ref all = NameDict__try_get(dict, __all__);
|
||||
if(all) {
|
||||
int length;
|
||||
py_TValue* p = pk_arrayview(all, &length);
|
||||
@ -775,7 +781,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
||||
}
|
||||
for(int i = 0; i < length; i++) {
|
||||
py_Name name = py_namev(py_tosv(p + i));
|
||||
py_Ref value = pk_NameDict__try_get(dict, name);
|
||||
py_Ref value = NameDict__try_get(dict, name);
|
||||
if(value == NULL) {
|
||||
ImportError("cannot import name '%n'", name);
|
||||
goto __ERROR;
|
||||
@ -785,7 +791,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
||||
}
|
||||
} else {
|
||||
for(int i = 0; i < dict->count; i++) {
|
||||
pk_NameDict_KV* kv = c11__at(pk_NameDict_KV, dict, i);
|
||||
NameDict_KV* kv = c11__at(NameDict_KV, dict, i);
|
||||
if(!kv->key) continue;
|
||||
c11_sv name = py_name2sv(kv->key);
|
||||
if(name.size == 0 || name.data[0] == '_') continue;
|
||||
@ -848,10 +854,10 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
||||
|
||||
if(py_istype(TOP(), tp_type)) {
|
||||
// call on_end_subclass
|
||||
pk_TypeInfo* ti = c11__at(pk_TypeInfo, &self->types, py_totype(TOP()));
|
||||
py_TypeInfo* ti = c11__at(py_TypeInfo, &self->types, py_totype(TOP()));
|
||||
if(ti->base != tp_object) {
|
||||
// PyTypeInfo* base_ti = &_all_types[ti->base];
|
||||
pk_TypeInfo* base_ti = c11__at(pk_TypeInfo, &self->types, ti->base);
|
||||
py_TypeInfo* base_ti = c11__at(py_TypeInfo, &self->types, ti->base);
|
||||
if(base_ti->on_end_subclass) base_ti->on_end_subclass(ti);
|
||||
}
|
||||
}
|
||||
@ -871,7 +877,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
||||
}
|
||||
case OP_ADD_CLASS_ANNOTATION: {
|
||||
py_Type type = py_totype(self->__curr_class);
|
||||
pk_TypeInfo* ti = c11__at(pk_TypeInfo, &self->types, type);
|
||||
py_TypeInfo* ti = c11__at(py_TypeInfo, &self->types, type);
|
||||
c11_vector__push(py_Name, &ti->annotated_fields, byte.arg);
|
||||
DISPATCH();
|
||||
}
|
||||
@ -920,7 +926,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
||||
}
|
||||
case OP_POP_EXCEPTION: {
|
||||
assert(self->curr_exception.type);
|
||||
self->curr_exception = *py_NIL;
|
||||
py_clearexc(NULL);
|
||||
DISPATCH();
|
||||
}
|
||||
//////////////////
|
||||
@ -964,7 +970,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
||||
} else {
|
||||
// 2. Exception need to be propagated to the upper frame
|
||||
bool is_base_frame_to_be_popped = frame == base_frame;
|
||||
pk_VM__pop_frame(self);
|
||||
VM__pop_frame(self);
|
||||
if(self->top_frame == NULL || is_base_frame_to_be_popped) {
|
||||
// propagate to the top level
|
||||
return RES_ERROR;
|
||||
@ -977,7 +983,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
||||
return RES_RETURN;
|
||||
}
|
||||
|
||||
bool pk_stack_binaryop(pk_VM* self, py_Name op, py_Name rop) {
|
||||
bool pk_stack_binaryop(VM* self, py_Name op, py_Name rop) {
|
||||
// [a, b]
|
||||
py_Ref magic = py_tpfindmagic(SECOND()->type, op);
|
||||
if(magic) {
|
||||
@ -1008,7 +1014,7 @@ bool pk_stack_binaryop(pk_VM* self, py_Name op, py_Name rop) {
|
||||
}
|
||||
|
||||
bool py_binaryop(py_Ref lhs, py_Ref rhs, py_Name op, py_Name rop) {
|
||||
pk_VM* self = pk_current_vm;
|
||||
VM* self = pk_current_vm;
|
||||
PUSH(lhs);
|
||||
PUSH(rhs);
|
||||
bool ok = pk_stack_binaryop(self, op, rop);
|
||||
@ -1016,7 +1022,7 @@ bool py_binaryop(py_Ref lhs, py_Ref rhs, py_Name op, py_Name rop) {
|
||||
return ok;
|
||||
}
|
||||
|
||||
static bool stack_unpack_sequence(pk_VM* self, uint16_t arg) {
|
||||
static bool stack_unpack_sequence(VM* self, uint16_t arg) {
|
||||
int length;
|
||||
py_TValue* p = pk_arrayview(TOP(), &length);
|
||||
if(!p) return TypeError("expected list or tuple to unpack, got '%t'", TOP()->type);
|
||||
|
||||
@ -14,11 +14,11 @@ py_TValue* FastLocals__try_get_by_name(py_TValue* locals, const CodeObject* co,
|
||||
return &locals[index];
|
||||
}
|
||||
|
||||
pk_NameDict* FastLocals__to_namedict(py_TValue* locals, const CodeObject* co) {
|
||||
pk_NameDict* dict = pk_NameDict__new();
|
||||
NameDict* FastLocals__to_namedict(py_TValue* locals, const CodeObject* co) {
|
||||
NameDict* dict = NameDict__new();
|
||||
c11__foreach(c11_smallmap_n2i_KV, &co->varnames_inv, entry) {
|
||||
py_TValue value = locals[entry->value];
|
||||
if(!py_isnil(&value)) { pk_NameDict__set(dict, entry->key, value); }
|
||||
if(!py_isnil(&value)) { NameDict__set(dict, entry->key, value); }
|
||||
}
|
||||
return dict;
|
||||
}
|
||||
@ -134,6 +134,6 @@ py_TValue* Frame__f_closure_try_get(Frame* self, py_Name name) {
|
||||
// if(self->function == NULL) return NULL;
|
||||
// pkpy::Function* fn = PyObject__as(pkpy::Function, self->function);
|
||||
// if(fn->_closure == nullptr) return nullptr;
|
||||
// return pk_NameDict__try_get(fn->_closure, name);
|
||||
// return NameDict__try_get(fn->_closure, name);
|
||||
return NULL;
|
||||
}
|
||||
@ -2,7 +2,7 @@
|
||||
#include "pocketpy/common/memorypool.h"
|
||||
#include "pocketpy/objects/base.h"
|
||||
|
||||
void pk_ManagedHeap__ctor(pk_ManagedHeap *self, pk_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,7 +13,7 @@ void pk_ManagedHeap__ctor(pk_ManagedHeap *self, pk_VM *vm){
|
||||
self->gc_on_delete = NULL;
|
||||
}
|
||||
|
||||
void pk_ManagedHeap__dtor(pk_ManagedHeap *self){
|
||||
void ManagedHeap__dtor(ManagedHeap *self){
|
||||
for(int i = 0; i < self->gen.count; i++){
|
||||
PyObject* obj = c11__getitem(PyObject*, &self->gen, i);
|
||||
PyObject__delete(obj);
|
||||
@ -26,23 +26,23 @@ void pk_ManagedHeap__dtor(pk_ManagedHeap *self){
|
||||
c11_vector__dtor(&self->gen);
|
||||
}
|
||||
|
||||
void pk_ManagedHeap__collect_if_needed(pk_ManagedHeap *self){
|
||||
void ManagedHeap__collect_if_needed(ManagedHeap *self){
|
||||
if(self->gc_counter < self->gc_threshold) return;
|
||||
self->gc_counter = 0;
|
||||
pk_ManagedHeap__collect(self);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
int pk_ManagedHeap__collect(pk_ManagedHeap *self){
|
||||
pk_ManagedHeap__mark(self);
|
||||
int freed = pk_ManagedHeap__sweep(self);
|
||||
int ManagedHeap__collect(ManagedHeap *self){
|
||||
ManagedHeap__mark(self);
|
||||
int freed = ManagedHeap__sweep(self);
|
||||
return freed;
|
||||
}
|
||||
|
||||
int pk_ManagedHeap__sweep(pk_ManagedHeap *self){
|
||||
int ManagedHeap__sweep(ManagedHeap *self){
|
||||
c11_vector alive;
|
||||
c11_vector__ctor(&alive, sizeof(PyObject*));
|
||||
c11_vector__reserve(&alive, self->gen.count / 2);
|
||||
@ -77,13 +77,13 @@ int pk_ManagedHeap__sweep(pk_ManagedHeap *self){
|
||||
return freed;
|
||||
}
|
||||
|
||||
PyObject* pk_ManagedHeap__new(pk_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* pk_ManagedHeap__gcnew(pk_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++;
|
||||
@ -111,7 +111,7 @@ PyObject* PyObject__new(py_Type type, int slots, int size){
|
||||
if(slots >= 0){
|
||||
memset(p, 0, slots*sizeof(py_TValue));
|
||||
}else{
|
||||
pk_NameDict__ctor(p);
|
||||
NameDict__ctor(p);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@ -1,131 +0,0 @@
|
||||
#include "pocketpy/interpreter/vfs.h"
|
||||
#include "pocketpy/interpreter/vm.h"
|
||||
|
||||
#define SMALLMAP_T__SOURCE
|
||||
#define K c11_sv
|
||||
#define V VfsEntry
|
||||
#define NAME VfsDir
|
||||
#define less(a, b) (c11_sv__cmp((a), (b)) < 0)
|
||||
#define equal(a, b) (c11_sv__cmp((a), (b)) == 0)
|
||||
#include "pocketpy/xmacros/smallmap.h"
|
||||
#undef SMALLMAP_T__SOURCE
|
||||
|
||||
static VfsEntry* Vfs__get(const char* path) {
|
||||
c11_vector /*T=c11_sv*/ cpnts = c11_sv__split((c11_sv){path, strlen(path)}, '/');
|
||||
|
||||
VfsEntry* root = &pk_current_vm->__vfs.root;
|
||||
for(int i = 0; i < cpnts.count; i++) {
|
||||
c11_sv cpnt = c11__getitem(c11_sv, &cpnts, i);
|
||||
VfsEntry* entry = VfsDir__try_get(&root->_dir, cpnt);
|
||||
if(entry == NULL) {
|
||||
c11_vector__dtor(&cpnts);
|
||||
return NULL;
|
||||
}
|
||||
if(entry->is_file) {
|
||||
VfsEntry* retval = i == cpnts.count - 1 ? entry : NULL;
|
||||
c11_vector__dtor(&cpnts);
|
||||
return retval;
|
||||
} else {
|
||||
root = entry;
|
||||
}
|
||||
}
|
||||
c11_vector__dtor(&cpnts);
|
||||
return root;
|
||||
}
|
||||
|
||||
static void VfsDir__delete_recursively(VfsDir* self) {
|
||||
for(int i = 0; i < self->count; i++) {
|
||||
VfsDir_KV* kv = c11__at(VfsDir_KV, self, i);
|
||||
free((char*)kv->key.data);
|
||||
if(kv->value.is_file) {
|
||||
free(kv->value._file.data);
|
||||
} else {
|
||||
VfsDir__delete_recursively(&kv->value._dir);
|
||||
}
|
||||
}
|
||||
VfsDir__dtor(self);
|
||||
}
|
||||
|
||||
void Vfs__ctor(Vfs* self) {
|
||||
self->root.is_file = false;
|
||||
VfsDir__ctor(&self->root._dir);
|
||||
}
|
||||
|
||||
void Vfs__dtor(Vfs* self) { VfsDir__delete_recursively(&self->root._dir); }
|
||||
|
||||
unsigned char* py_vfsread(const char* path, int* size) {
|
||||
VfsEntry* entry = Vfs__get(path);
|
||||
if(entry == NULL || !entry->is_file) return NULL;
|
||||
*size = entry->_file.size;
|
||||
unsigned char* retval = malloc(*size);
|
||||
memcpy(retval, entry->_file.data, *size);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void VfsDir__dupset(VfsDir* self, c11_sv key, VfsEntry value) {
|
||||
char* p = malloc(key.size);
|
||||
memcpy(p, key.data, key.size);
|
||||
VfsDir__set(self, (c11_sv){p, key.size}, value);
|
||||
}
|
||||
|
||||
bool py_vfswrite(const char* path, unsigned char* data, int size) {
|
||||
c11_vector /*T=c11_sv*/ cpnts = c11_sv__split((c11_sv){path, strlen(path)}, '/');
|
||||
VfsEntry* root = &pk_current_vm->__vfs.root;
|
||||
for(int i = 0; i < cpnts.count; i++) {
|
||||
c11_sv cpnt = c11__getitem(c11_sv, &cpnts, i);
|
||||
VfsEntry* entry = VfsDir__try_get(&root->_dir, cpnt);
|
||||
if(entry == NULL) {
|
||||
if(i == cpnts.count - 1) {
|
||||
// create file
|
||||
VfsEntry entry = {
|
||||
.is_file = true,
|
||||
._file.size = size,
|
||||
._file.data = data,
|
||||
};
|
||||
VfsDir__dupset(&root->_dir, cpnt, entry);
|
||||
c11_vector__dtor(&cpnts);
|
||||
return true;
|
||||
} else {
|
||||
// create missing directory
|
||||
VfsEntry entry = {
|
||||
.is_file = false,
|
||||
};
|
||||
VfsDir__ctor(&entry._dir);
|
||||
VfsDir__dupset(&root->_dir, cpnt, entry);
|
||||
}
|
||||
} else {
|
||||
if(i == cpnts.count - 1) {
|
||||
if(!entry->is_file) break;
|
||||
// update file
|
||||
free(entry->_file.data);
|
||||
entry->_file.size = size;
|
||||
entry->_file.data = data;
|
||||
c11_vector__dtor(&cpnts);
|
||||
return true;
|
||||
} else {
|
||||
if(entry->is_file) break;
|
||||
root = entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
c11_vector__dtor(&cpnts);
|
||||
return false;
|
||||
}
|
||||
|
||||
char** py_vfslist(const char* path, int* length) {
|
||||
VfsEntry* entry = Vfs__get(path);
|
||||
if(entry == NULL || entry->is_file) return NULL;
|
||||
*length = 0;
|
||||
char** ret = malloc(sizeof(char*) * entry->_dir.count);
|
||||
for(int i = 0; i < entry->_dir.count; i++) {
|
||||
VfsDir_KV* child = c11__at(VfsDir_KV, &entry->_dir, i);
|
||||
if(child->value.is_file) {
|
||||
int size = child->key.size;
|
||||
ret[i] = malloc(size + 1);
|
||||
memcpy(ret[i], child->key.data, size);
|
||||
ret[i][size] = '\0';
|
||||
(*length)++;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -6,23 +6,38 @@
|
||||
#include "pocketpy/common/_generated.h"
|
||||
#include "pocketpy/pocketpy.h"
|
||||
|
||||
static unsigned char* pk_default_import_file(const char* path, int* size) { return NULL; }
|
||||
static char* pk_default_import_file(const char* path) {
|
||||
#if PK_ENABLE_OS
|
||||
FILE* f = fopen(path, "rb");
|
||||
if(f == NULL) return NULL;
|
||||
fseek(f, 0, SEEK_END);
|
||||
long size = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
char* buffer = malloc(size + 1);
|
||||
fread(buffer, 1, size, f);
|
||||
buffer[size] = 0;
|
||||
fclose(f);
|
||||
return buffer;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void pk_default_print(const char* data) { printf("%s", data); }
|
||||
|
||||
static void pk_TypeInfo__ctor(pk_TypeInfo* self,
|
||||
static void py_TypeInfo__ctor(py_TypeInfo* self,
|
||||
py_Name name,
|
||||
py_Type index,
|
||||
py_Type base,
|
||||
py_TValue module) {
|
||||
memset(self, 0, sizeof(pk_TypeInfo));
|
||||
memset(self, 0, sizeof(py_TypeInfo));
|
||||
|
||||
self->name = name;
|
||||
self->base = base;
|
||||
|
||||
// create type object with __dict__
|
||||
pk_ManagedHeap* heap = &pk_current_vm->heap;
|
||||
PyObject* typeobj = pk_ManagedHeap__new(heap, tp_type, -1, sizeof(py_Type));
|
||||
ManagedHeap* heap = &pk_current_vm->heap;
|
||||
PyObject* typeobj = ManagedHeap__new(heap, tp_type, -1, sizeof(py_Type));
|
||||
*(py_Type*)PyObject__userdata(typeobj) = index;
|
||||
self->self = (py_TValue){
|
||||
.type = typeobj->type,
|
||||
@ -34,20 +49,13 @@ static void pk_TypeInfo__ctor(pk_TypeInfo* self,
|
||||
c11_vector__ctor(&self->annotated_fields, sizeof(py_Name));
|
||||
}
|
||||
|
||||
static void pk_TypeInfo__dtor(pk_TypeInfo* self) { c11_vector__dtor(&self->annotated_fields); }
|
||||
static void py_TypeInfo__dtor(py_TypeInfo* self) { c11_vector__dtor(&self->annotated_fields); }
|
||||
|
||||
static void save_site_package_to_vfs(const char* name, const char* source) {
|
||||
char buf[512];
|
||||
snprintf(buf, sizeof(buf), "site-packages/%s", name);
|
||||
bool ok = py_vfswrite(buf, (unsigned char*)source, strlen(source) + 1);
|
||||
if(!ok) c11__abort("failed to save '%s' to vfs", name);
|
||||
}
|
||||
|
||||
void pk_VM__ctor(pk_VM* self) {
|
||||
void VM__ctor(VM* self) {
|
||||
self->top_frame = NULL;
|
||||
|
||||
pk_NameDict__ctor(&self->modules);
|
||||
c11_vector__ctor(&self->types, sizeof(pk_TypeInfo));
|
||||
NameDict__ctor(&self->modules);
|
||||
c11_vector__ctor(&self->types, sizeof(py_TypeInfo));
|
||||
|
||||
self->builtins = *py_NIL;
|
||||
self->main = *py_NIL;
|
||||
@ -60,17 +68,16 @@ void pk_VM__ctor(pk_VM* self) {
|
||||
self->curr_exception = *py_NIL;
|
||||
self->is_stopiteration = false;
|
||||
|
||||
Vfs__ctor(&self->__vfs);
|
||||
self->__curr_class = NULL;
|
||||
self->__dynamic_func_decl = NULL;
|
||||
|
||||
pk_ManagedHeap__ctor(&self->heap, self);
|
||||
ManagedHeap__ctor(&self->heap, self);
|
||||
ValueStack__ctor(&self->stack);
|
||||
|
||||
/* Init Builtin Types */
|
||||
// 0: unused
|
||||
void* placeholder = c11_vector__emplace(&self->types);
|
||||
memset(placeholder, 0, sizeof(pk_TypeInfo));
|
||||
memset(placeholder, 0, sizeof(py_TypeInfo));
|
||||
|
||||
#define validate(t, expr) \
|
||||
if(t != (expr)) abort()
|
||||
@ -100,7 +107,7 @@ void pk_VM__ctor(pk_VM* self) {
|
||||
validate(tp_nativefunc, pk_nativefunc__register());
|
||||
validate(tp_boundmethod, pk_newtype("boundmethod", tp_object, NULL, NULL, false, true));
|
||||
|
||||
validate(tp_super, pk_newtype("super", tp_object, NULL, NULL, false, true));
|
||||
validate(tp_super, pk_super__register());
|
||||
validate(tp_BaseException, pk_BaseException__register());
|
||||
validate(tp_Exception, pk_Exception__register());
|
||||
validate(tp_bytes, pk_bytes__register());
|
||||
@ -109,11 +116,11 @@ void pk_VM__ctor(pk_VM* self) {
|
||||
validate(tp_dict, pk_dict__register());
|
||||
validate(tp_dict_items, pk_dict_items__register());
|
||||
|
||||
validate(tp_property, pk_newtype("property", tp_object, NULL, NULL, false, true));
|
||||
validate(tp_property, pk_property__register());
|
||||
validate(tp_star_wrapper, pk_newtype("star_wrapper", tp_object, NULL, NULL, false, true));
|
||||
|
||||
validate(tp_staticmethod, pk_newtype("staticmethod", tp_object, NULL, NULL, false, true));
|
||||
validate(tp_classmethod, pk_newtype("classmethod", tp_object, NULL, NULL, false, true));
|
||||
validate(tp_staticmethod, pk_staticmethod__register());
|
||||
validate(tp_classmethod, pk_classmethod__register());
|
||||
|
||||
validate(tp_NoneType, pk_newtype("NoneType", tp_object, NULL, NULL, false, true));
|
||||
validate(tp_NotImplementedType,
|
||||
@ -127,27 +134,15 @@ void pk_VM__ctor(pk_VM* self) {
|
||||
self->builtins = pk_builtins__register();
|
||||
|
||||
/* Setup Public Builtin Types */
|
||||
py_Type public_types[] = {tp_object,
|
||||
tp_type,
|
||||
tp_int,
|
||||
tp_float,
|
||||
tp_bool,
|
||||
tp_str,
|
||||
tp_list,
|
||||
tp_tuple,
|
||||
tp_slice,
|
||||
tp_range,
|
||||
tp_bytes,
|
||||
tp_dict,
|
||||
tp_property,
|
||||
tp_BaseException,
|
||||
tp_Exception,
|
||||
tp_StopIteration,
|
||||
tp_SyntaxError};
|
||||
py_Type public_types[] = {tp_object, tp_type, tp_int, tp_float,
|
||||
tp_bool, tp_str, tp_list, tp_tuple,
|
||||
tp_slice, tp_range, tp_bytes, tp_dict,
|
||||
tp_property, tp_staticmethod, tp_classmethod, tp_super,
|
||||
tp_BaseException, tp_Exception, tp_StopIteration, tp_SyntaxError};
|
||||
|
||||
for(int i = 0; i < c11__count_array(public_types); i++) {
|
||||
py_Type t = public_types[i];
|
||||
pk_TypeInfo* ti = c11__at(pk_TypeInfo, &self->types, t);
|
||||
py_TypeInfo* ti = c11__at(py_TypeInfo, &self->types, t);
|
||||
py_setdict(&self->builtins, ti->name, py_tpobject(t));
|
||||
}
|
||||
|
||||
@ -155,6 +150,7 @@ void pk_VM__ctor(pk_VM* self) {
|
||||
const char** builtin_exceptions = (const char*[]){
|
||||
"StackOverflowError",
|
||||
"IOError",
|
||||
"OSError",
|
||||
"NotImplementedError",
|
||||
"TypeError",
|
||||
"IndexError",
|
||||
@ -182,45 +178,35 @@ void pk_VM__ctor(pk_VM* self) {
|
||||
|
||||
// add modules
|
||||
pk__add_module_pkpy();
|
||||
pk__add_module_os();
|
||||
pk__add_module_math();
|
||||
|
||||
self->main = *py_newmodule("__main__");
|
||||
|
||||
save_site_package_to_vfs("bisect.py", kPythonLibs_bisect);
|
||||
save_site_package_to_vfs("cmath.py", kPythonLibs_cmath);
|
||||
save_site_package_to_vfs("collections.py", kPythonLibs_collections);
|
||||
save_site_package_to_vfs("colorsys.py", kPythonLibs_colorsys);
|
||||
save_site_package_to_vfs("datetime.py", kPythonLibs_datetime);
|
||||
save_site_package_to_vfs("functools.py", kPythonLibs_functools);
|
||||
save_site_package_to_vfs("heapq.py", kPythonLibs_heapq);
|
||||
save_site_package_to_vfs("itertools.py", kPythonLibs_itertools);
|
||||
save_site_package_to_vfs("operator.py", kPythonLibs_operator);
|
||||
save_site_package_to_vfs("pickle.py", kPythonLibs_pickle);
|
||||
save_site_package_to_vfs("this.py", kPythonLibs_this);
|
||||
save_site_package_to_vfs("typing.py", kPythonLibs_typing);
|
||||
}
|
||||
|
||||
void pk_VM__dtor(pk_VM* self) {
|
||||
void VM__dtor(VM* self) {
|
||||
if(self->__dynamic_func_decl) { PK_DECREF(self->__dynamic_func_decl); }
|
||||
// destroy all objects
|
||||
pk_ManagedHeap__dtor(&self->heap);
|
||||
ManagedHeap__dtor(&self->heap);
|
||||
// clear frames
|
||||
// ...
|
||||
pk_NameDict__dtor(&self->modules);
|
||||
c11__foreach(pk_TypeInfo, &self->types, ti) pk_TypeInfo__dtor(ti);
|
||||
while(self->top_frame)
|
||||
VM__pop_frame(self);
|
||||
NameDict__dtor(&self->modules);
|
||||
c11__foreach(py_TypeInfo, &self->types, ti) py_TypeInfo__dtor(ti);
|
||||
c11_vector__dtor(&self->types);
|
||||
ValueStack__clear(&self->stack);
|
||||
Vfs__dtor(&self->__vfs);
|
||||
}
|
||||
|
||||
void pk_VM__push_frame(pk_VM* self, Frame* frame) {
|
||||
void VM__push_frame(VM* self, Frame* frame) {
|
||||
frame->f_back = self->top_frame;
|
||||
self->top_frame = frame;
|
||||
}
|
||||
|
||||
void pk_VM__pop_frame(pk_VM* self) {
|
||||
void VM__pop_frame(VM* self) {
|
||||
assert(self->top_frame);
|
||||
Frame* frame = self->top_frame;
|
||||
// reset stack pointer
|
||||
|
||||
self->stack.sp = frame->p0;
|
||||
// pop frame and delete
|
||||
self->top_frame = frame->f_back;
|
||||
@ -297,9 +283,9 @@ py_Type pk_newtype(const char* name,
|
||||
bool is_sealed) {
|
||||
c11_vector* types = &pk_current_vm->types;
|
||||
py_Type index = types->count;
|
||||
pk_TypeInfo* ti = c11_vector__emplace(types);
|
||||
pk_TypeInfo__ctor(ti, py_name(name), index, base, module ? *module : *py_NIL);
|
||||
if(!dtor && base) { dtor = c11__at(pk_TypeInfo, types, base)->dtor; }
|
||||
py_TypeInfo* ti = c11_vector__emplace(types);
|
||||
py_TypeInfo__ctor(ti, py_name(name), index, base, module ? *module : *py_NIL);
|
||||
if(!dtor && base) { dtor = c11__at(py_TypeInfo, types, base)->dtor; }
|
||||
ti->dtor = dtor;
|
||||
ti->is_python = is_python;
|
||||
ti->is_sealed = is_sealed;
|
||||
@ -377,7 +363,7 @@ static bool
|
||||
return true;
|
||||
}
|
||||
|
||||
pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t argc, uint16_t kwargc, bool opcall) {
|
||||
FrameResult VM__vectorcall(VM* self, uint16_t argc, uint16_t kwargc, bool opcall) {
|
||||
pk_print_stack(self, self->top_frame, (Bytecode){0});
|
||||
|
||||
py_Ref p1 = self->stack.sp - kwargc * 2;
|
||||
@ -385,18 +371,14 @@ pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t argc, uint16_t kwargc, bo
|
||||
// [callable, <self>, args..., kwargs...]
|
||||
// ^p0 ^p1 ^_sp
|
||||
|
||||
#if 0
|
||||
// handle boundmethod, do a patch
|
||||
if(p0->type == tp_boundmethod) {
|
||||
assert(py_isnil(p0 + 1)); // self must be NULL
|
||||
// BoundMethod& bm = PK_OBJ_GET(BoundMethod, callable);
|
||||
// callable = bm.func; // get unbound method
|
||||
// callable_t = _tp(callable);
|
||||
// p1[-(ARGC + 2)] = bm.func;
|
||||
// p1[-(ARGC + 1)] = bm.self;
|
||||
py_TValue* slots = PyObject__slots(p0->_obj);
|
||||
p0[0] = slots[1]; // callable
|
||||
p0[1] = slots[0]; // self
|
||||
// [unbound, self, args..., kwargs...]
|
||||
}
|
||||
#endif
|
||||
|
||||
py_Ref argv = py_isnil(p0 + 1) ? p0 + 2 : p0 + 1;
|
||||
|
||||
@ -420,8 +402,8 @@ pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t argc, uint16_t kwargc, bo
|
||||
memcpy(argv, self->__vectorcall_buffer, co->nlocals * sizeof(py_TValue));
|
||||
// submit the call
|
||||
if(!fn->cfunc) {
|
||||
pk_VM__push_frame(self, Frame__new(co, &fn->module, p0, p0, argv, co));
|
||||
return opcall ? RES_CALL : pk_VM__run_top_frame(self);
|
||||
VM__push_frame(self, Frame__new(co, &fn->module, p0, p0, argv, co));
|
||||
return opcall ? RES_CALL : VM__run_top_frame(self);
|
||||
} else {
|
||||
bool ok = fn->cfunc(co->nlocals, argv);
|
||||
self->stack.sp = p0;
|
||||
@ -444,8 +426,8 @@ pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t argc, uint16_t kwargc, bo
|
||||
// initialize local variables to py_NIL
|
||||
memset(p1, 0, (char*)self->stack.sp - (char*)p1);
|
||||
// submit the call
|
||||
pk_VM__push_frame(self, Frame__new(co, &fn->module, p0, p0, argv, co));
|
||||
return opcall ? RES_CALL : pk_VM__run_top_frame(self);
|
||||
VM__push_frame(self, Frame__new(co, &fn->module, p0, p0, argv, co));
|
||||
return opcall ? RES_CALL : VM__run_top_frame(self);
|
||||
case FuncType_GENERATOR:
|
||||
assert(false);
|
||||
break;
|
||||
@ -480,7 +462,7 @@ pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t argc, uint16_t kwargc, bo
|
||||
memcpy(self->stack.sp, argv, span * sizeof(py_TValue));
|
||||
self->stack.sp += span;
|
||||
// [new_f, cls, args..., kwargs...]
|
||||
if(pk_VM__vectorcall(self, argc, kwargc, false) == RES_ERROR) return RES_ERROR;
|
||||
if(VM__vectorcall(self, argc, kwargc, false) == RES_ERROR) return RES_ERROR;
|
||||
// by recursively using vectorcall, args and kwargs are consumed
|
||||
|
||||
// try __init__
|
||||
@ -493,7 +475,7 @@ pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t argc, uint16_t kwargc, bo
|
||||
*p0 = *init_f; // __init__
|
||||
p0[1] = self->last_retval; // self
|
||||
// [__init__, self, args..., kwargs...]
|
||||
if(pk_VM__vectorcall(self, argc, kwargc, false) == RES_ERROR) return RES_ERROR;
|
||||
if(VM__vectorcall(self, argc, kwargc, false) == RES_ERROR) return RES_ERROR;
|
||||
*py_retval() = p0[1]; // restore the new instance
|
||||
}
|
||||
// reset the stack
|
||||
@ -504,18 +486,18 @@ pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t argc, uint16_t kwargc, bo
|
||||
// handle `__call__` overload
|
||||
if(pk_pushmethod(p0, __call__)) {
|
||||
// [__call__, self, args..., kwargs...]
|
||||
return pk_VM__vectorcall(self, argc, kwargc, opcall);
|
||||
return VM__vectorcall(self, argc, kwargc, opcall);
|
||||
}
|
||||
|
||||
TypeError("'%t' object is not callable", p0->type);
|
||||
c11__unreachedable();
|
||||
return RES_ERROR;
|
||||
}
|
||||
|
||||
/****************************************/
|
||||
void PyObject__delete(PyObject* self) {
|
||||
pk_TypeInfo* ti = c11__at(pk_TypeInfo, &pk_current_vm->types, self->type);
|
||||
py_TypeInfo* ti = c11__at(py_TypeInfo, &pk_current_vm->types, self->type);
|
||||
if(ti->dtor) ti->dtor(PyObject__userdata(self));
|
||||
if(self->slots == -1) pk_NameDict__dtor(PyObject__dict(self));
|
||||
if(self->slots == -1) NameDict__dtor(PyObject__dict(self));
|
||||
if(self->gc_is_large) {
|
||||
free(self);
|
||||
} else {
|
||||
@ -541,9 +523,9 @@ static void mark_object(PyObject* obj) {
|
||||
}
|
||||
|
||||
if(obj->slots == -1) {
|
||||
pk_NameDict* dict = PyObject__dict(obj);
|
||||
NameDict* dict = PyObject__dict(obj);
|
||||
for(int j = 0; j < dict->count; j++) {
|
||||
pk_NameDict_KV* kv = c11__at(pk_NameDict_KV, dict, j);
|
||||
NameDict_KV* kv = c11__at(NameDict_KV, dict, j);
|
||||
mark_value(&kv->value);
|
||||
}
|
||||
return;
|
||||
@ -556,8 +538,8 @@ static void mark_object(PyObject* obj) {
|
||||
}
|
||||
}
|
||||
|
||||
void pk_ManagedHeap__mark(pk_ManagedHeap* self) {
|
||||
pk_VM* vm = self->vm;
|
||||
void ManagedHeap__mark(ManagedHeap* self) {
|
||||
VM* vm = self->vm;
|
||||
// mark heap objects
|
||||
for(int i = 0; i < self->no_gc.count; i++) {
|
||||
PyObject* obj = c11__getitem(PyObject*, &self->no_gc, i);
|
||||
@ -580,8 +562,8 @@ void pk_ManagedHeap__mark(pk_ManagedHeap* self) {
|
||||
}
|
||||
}
|
||||
|
||||
void pk_print_stack(pk_VM* self, Frame* frame, Bytecode byte) {
|
||||
// return;
|
||||
void pk_print_stack(VM* self, Frame* frame, Bytecode byte) {
|
||||
return;
|
||||
if(frame == NULL) return;
|
||||
|
||||
py_TValue* sp = self->stack.sp;
|
||||
@ -616,6 +598,11 @@ void pk_print_stack(pk_VM* self, Frame* frame, Bytecode byte) {
|
||||
pk_sprintf(&buf, "%q", py_tosv(p));
|
||||
break;
|
||||
}
|
||||
case tp_module: {
|
||||
py_Ref path = py_getdict(p, __path__);
|
||||
pk_sprintf(&buf, "<module '%v'>", py_tosv(path));
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
pk_sprintf(&buf, "(%t)", p->type);
|
||||
break;
|
||||
|
||||
202
src/modules/math.c
Normal file
202
src/modules/math.c
Normal file
@ -0,0 +1,202 @@
|
||||
#include "pocketpy/pocketpy.h"
|
||||
|
||||
#include "pocketpy/common/utils.h"
|
||||
#include "pocketpy/objects/object.h"
|
||||
#include "pocketpy/common/sstream.h"
|
||||
#include "pocketpy/interpreter/vm.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#define ONE_ARG_FUNC(name, func) \
|
||||
static bool math_##name(int argc, py_Ref argv) { \
|
||||
PY_CHECK_ARGC(1); \
|
||||
double x; \
|
||||
if(!py_castfloat(py_arg(0), &x)) return false; \
|
||||
py_newfloat(py_retval(), func(x)); \
|
||||
return true; \
|
||||
}
|
||||
|
||||
#define TWO_ARG_FUNC(name, func) \
|
||||
static bool math_##name(int argc, py_Ref argv) { \
|
||||
PY_CHECK_ARGC(2); \
|
||||
double x, y; \
|
||||
if(!py_castfloat(py_arg(0), &x)) return false; \
|
||||
if(!py_castfloat(py_arg(1), &y)) return false; \
|
||||
py_newfloat(py_retval(), func(x, y)); \
|
||||
return true; \
|
||||
}
|
||||
|
||||
ONE_ARG_FUNC(ceil, ceil)
|
||||
ONE_ARG_FUNC(fabs, fabs)
|
||||
ONE_ARG_FUNC(floor, floor)
|
||||
ONE_ARG_FUNC(trunc, trunc)
|
||||
|
||||
static bool math_fsum(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
PY_CHECK_ARG_TYPE(0, tp_list);
|
||||
py_Ref list = py_arg(0);
|
||||
double sum = 0;
|
||||
double c = 0;
|
||||
for(int i = 0; i < py_list__len(list); i++) {
|
||||
py_Ref item = py_list__getitem(list, i);
|
||||
double x;
|
||||
if(!py_castfloat(item, &x)) return false;
|
||||
double y = x - c;
|
||||
double t = sum + y;
|
||||
c = (t - sum) - y;
|
||||
sum = t;
|
||||
}
|
||||
py_newfloat(py_retval(), sum);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool math_gcd(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
PY_CHECK_ARG_TYPE(0, tp_int);
|
||||
PY_CHECK_ARG_TYPE(1, tp_int);
|
||||
py_i64 a = py_toint(py_arg(0));
|
||||
py_i64 b = py_toint(py_arg(1));
|
||||
if(a < 0) a = -a;
|
||||
if(b < 0) b = -b;
|
||||
while(b != 0) {
|
||||
py_i64 t = b;
|
||||
b = a % b;
|
||||
a = t;
|
||||
}
|
||||
py_newint(py_retval(), a);
|
||||
return true;
|
||||
}
|
||||
|
||||
ONE_ARG_FUNC(isfinite, isfinite)
|
||||
ONE_ARG_FUNC(isinf, isinf)
|
||||
ONE_ARG_FUNC(isnan, isnan)
|
||||
|
||||
static bool math_isclose(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
double a, b;
|
||||
if(!py_castfloat(py_arg(0), &a)) return false;
|
||||
if(!py_castfloat(py_arg(1), &b)) return false;
|
||||
py_newbool(py_retval(), fabs(a - b) < 1e-9);
|
||||
return true;
|
||||
}
|
||||
|
||||
ONE_ARG_FUNC(exp, exp)
|
||||
|
||||
static bool math_log(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARG_TYPE(0, tp_float);
|
||||
double x;
|
||||
if(!py_castfloat(py_arg(0), &x)) return false;
|
||||
if(argc == 1) {
|
||||
py_newfloat(py_retval(), log(x));
|
||||
} else if(argc == 2) {
|
||||
double base;
|
||||
if(!py_castfloat(py_arg(1), &base)) return false;
|
||||
py_newfloat(py_retval(), log(x) / log(base));
|
||||
} else {
|
||||
return TypeError("log() takes 1 or 2 arguments");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ONE_ARG_FUNC(log2, log2)
|
||||
ONE_ARG_FUNC(log10, log10)
|
||||
|
||||
TWO_ARG_FUNC(pow, pow)
|
||||
|
||||
ONE_ARG_FUNC(sqrt, sqrt)
|
||||
|
||||
ONE_ARG_FUNC(acos, acos)
|
||||
ONE_ARG_FUNC(asin, asin)
|
||||
ONE_ARG_FUNC(atan, atan)
|
||||
|
||||
ONE_ARG_FUNC(cos, cos)
|
||||
ONE_ARG_FUNC(sin, sin)
|
||||
ONE_ARG_FUNC(tan, tan)
|
||||
|
||||
TWO_ARG_FUNC(atan2, atan2)
|
||||
|
||||
static bool math_degrees(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
double x;
|
||||
if(!py_castfloat(py_arg(0), &x)) return false;
|
||||
py_newfloat(py_retval(), x * 180 / 3.1415926535897932384);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool math_radians(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
double x;
|
||||
if(!py_castfloat(py_arg(0), &x)) return false;
|
||||
py_newfloat(py_retval(), x * 3.1415926535897932384 / 180);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool math_modf(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
double i;
|
||||
double f = modf(py_tofloat(py_arg(0)), &i);
|
||||
py_newtuple(py_retval(), 2);
|
||||
py_Ref _0 = py_tuple__getitem(py_retval(), 0);
|
||||
py_Ref _1 = py_tuple__getitem(py_retval(), 1);
|
||||
py_newfloat(_0, f);
|
||||
py_newfloat(_1, i);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool math_factorial(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
PY_CHECK_ARG_TYPE(0, tp_int);
|
||||
py_i64 n = py_toint(py_arg(0));
|
||||
if(n < 0) return ValueError("factorial() not defined for negative values");
|
||||
py_i64 r = 1;
|
||||
for(py_i64 i = 2; i <= n; i++)
|
||||
r *= i;
|
||||
py_newint(py_retval(), r);
|
||||
return true;
|
||||
}
|
||||
|
||||
void pk__add_module_math() {
|
||||
py_Ref mod = py_newmodule("math");
|
||||
|
||||
py_newfloat(py_emplacedict(mod, py_name("pi")), 3.1415926535897932384);
|
||||
py_newfloat(py_emplacedict(mod, py_name("e")), 2.7182818284590452354);
|
||||
py_newfloat(py_emplacedict(mod, py_name("inf")), 1.0 / 0.0);
|
||||
py_newfloat(py_emplacedict(mod, py_name("nan")), 0.0 / 0.0);
|
||||
|
||||
py_bindfunc(mod, "ceil", math_ceil);
|
||||
py_bindfunc(mod, "fabs", math_fabs);
|
||||
py_bindfunc(mod, "floor", math_floor);
|
||||
py_bindfunc(mod, "trunc", math_trunc);
|
||||
|
||||
py_bindfunc(mod, "fsum", math_fsum);
|
||||
py_bindfunc(mod, "gcd", math_gcd);
|
||||
|
||||
py_bindfunc(mod, "isfinite", math_isfinite);
|
||||
py_bindfunc(mod, "isinf", math_isinf);
|
||||
py_bindfunc(mod, "isnan", math_isnan);
|
||||
py_bindfunc(mod, "isclose", math_isclose);
|
||||
|
||||
py_bindfunc(mod, "exp", math_exp);
|
||||
py_bindfunc(mod, "log", math_log);
|
||||
py_bindfunc(mod, "log2", math_log2);
|
||||
py_bindfunc(mod, "log10", math_log10);
|
||||
|
||||
py_bindfunc(mod, "pow", math_pow);
|
||||
py_bindfunc(mod, "sqrt", math_sqrt);
|
||||
|
||||
py_bindfunc(mod, "acos", math_acos);
|
||||
py_bindfunc(mod, "asin", math_asin);
|
||||
py_bindfunc(mod, "atan", math_atan);
|
||||
|
||||
py_bindfunc(mod, "cos", math_cos);
|
||||
py_bindfunc(mod, "sin", math_sin);
|
||||
py_bindfunc(mod, "tan", math_tan);
|
||||
|
||||
py_bindfunc(mod, "atan2", math_atan2);
|
||||
|
||||
py_bindfunc(mod, "degrees", math_degrees);
|
||||
py_bindfunc(mod, "radians", math_radians);
|
||||
|
||||
py_bindfunc(mod, "modf", math_modf);
|
||||
py_bindfunc(mod, "factorial", math_factorial);
|
||||
}
|
||||
49
src/modules/os.c
Normal file
49
src/modules/os.c
Normal file
@ -0,0 +1,49 @@
|
||||
#include "pocketpy/pocketpy.h"
|
||||
|
||||
#include "pocketpy/common/utils.h"
|
||||
#include "pocketpy/objects/object.h"
|
||||
#include "pocketpy/common/sstream.h"
|
||||
#include "pocketpy/interpreter/vm.h"
|
||||
|
||||
#if _WIN32
|
||||
#include <direct.h>
|
||||
|
||||
int platform_chdir(const char* path) { return _chdir(path); }
|
||||
|
||||
bool platform_getcwd(char* buf, size_t size) { return _getcwd(buf, size) != NULL; }
|
||||
|
||||
#elif __linux__
|
||||
#include <unistd.h>
|
||||
|
||||
int platform_chdir(const char* path) { return chdir(path); }
|
||||
|
||||
bool platform_getcwd(char* buf, size_t size) { return getcwd(buf, size) != NULL; }
|
||||
#else
|
||||
|
||||
int platform_chdir(const char* path) { return -1; }
|
||||
|
||||
bool platform_getcwd(char* buf, size_t size) { return false; }
|
||||
|
||||
#endif
|
||||
|
||||
static bool os_chdir(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
PY_CHECK_ARG_TYPE(0, tp_str);
|
||||
const char* path = py_tostr(py_arg(0));
|
||||
int code = platform_chdir(path);
|
||||
if(code != 0) return OSError("chdir() failed: %d", code);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool os_getcwd(int argc, py_Ref argv) {
|
||||
char buf[1024];
|
||||
if(!platform_getcwd(buf, sizeof(buf))) return OSError("getcwd() failed");
|
||||
py_newstr(py_retval(), buf);
|
||||
return true;
|
||||
}
|
||||
|
||||
void pk__add_module_os() {
|
||||
py_Ref mod = py_newmodule("os");
|
||||
py_bindfunc(mod, "chdir", os_chdir);
|
||||
py_bindfunc(mod, "getcwd", os_getcwd);
|
||||
}
|
||||
@ -20,7 +20,7 @@ static void FuncDecl__dtor(FuncDecl* self) {
|
||||
c11_smallmap_n2i__dtor(&self->kw_to_index);
|
||||
}
|
||||
|
||||
FuncDecl_ FuncDecl__rcnew(pk_SourceData_ src, c11_sv name) {
|
||||
FuncDecl_ FuncDecl__rcnew(SourceData_ src, c11_sv name) {
|
||||
FuncDecl* self = malloc(sizeof(FuncDecl));
|
||||
self->rc.count = 1;
|
||||
self->rc.dtor = (void (*)(void*))FuncDecl__dtor;
|
||||
@ -94,7 +94,7 @@ FuncDecl_ FuncDecl__build(c11_sv name,
|
||||
py_Ref kwdefaults, // a tuple contains default values
|
||||
c11_sv starred_kwarg,
|
||||
const char* docstring) {
|
||||
pk_SourceData_ source = pk_SourceData__rcnew("pass", "<bind>", EXEC_MODE, false);
|
||||
SourceData_ source = SourceData__rcnew("pass", "<bind>", EXEC_MODE, false);
|
||||
FuncDecl_ decl = FuncDecl__rcnew(source, name);
|
||||
for(int i = 0; i < argc; i++) {
|
||||
FuncDecl__add_arg(decl, py_namev(args[i]));
|
||||
@ -111,7 +111,7 @@ FuncDecl_ FuncDecl__build(c11_sv name,
|
||||
return decl;
|
||||
}
|
||||
|
||||
void CodeObject__ctor(CodeObject* self, pk_SourceData_ src, c11_sv name) {
|
||||
void CodeObject__ctor(CodeObject* self, SourceData_ src, c11_sv name) {
|
||||
self->src = src;
|
||||
PK_INCREF(src);
|
||||
self->name = c11_string__new2(name.data, name.size);
|
||||
@ -179,5 +179,5 @@ int CodeObject__add_varname(CodeObject* self, py_Name name) {
|
||||
|
||||
void Function__dtor(Function* self) {
|
||||
PK_DECREF(self->decl);
|
||||
if(self->closure) pk_NameDict__delete(self->closure);
|
||||
if(self->closure) NameDict__delete(self->closure);
|
||||
}
|
||||
@ -3,6 +3,6 @@
|
||||
#define SMALLMAP_T__SOURCE
|
||||
#define K uint16_t
|
||||
#define V py_TValue
|
||||
#define NAME pk_NameDict
|
||||
#define NAME NameDict
|
||||
#include "pocketpy/xmacros/smallmap.h"
|
||||
#undef SMALLMAP_T__SOURCE
|
||||
|
||||
@ -4,9 +4,9 @@
|
||||
|
||||
void* PyObject__userdata(PyObject* self) { return self->flex + PK_OBJ_SLOTS_SIZE(self->slots); }
|
||||
|
||||
pk_NameDict* PyObject__dict(PyObject* self) {
|
||||
NameDict* PyObject__dict(PyObject* self) {
|
||||
assert(self->slots == -1);
|
||||
return (pk_NameDict*)(self->flex);
|
||||
return (NameDict*)(self->flex);
|
||||
}
|
||||
|
||||
py_TValue* PyObject__slots(PyObject* self) {
|
||||
|
||||
@ -19,7 +19,7 @@ bool py_castfloat(py_Ref self, double* out) {
|
||||
switch(self->type) {
|
||||
case tp_int: *out = (double)self->_i64; return true;
|
||||
case tp_float: *out = self->_f64; return true;
|
||||
default: return false;
|
||||
default: return TypeError("expected int or float, got %t", self->type);
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,12 +46,10 @@ bool py_checktype(py_Ref self, py_Type type) {
|
||||
return TypeError("expected %t, got %t", type, self->type);
|
||||
}
|
||||
|
||||
bool py_isinstance(py_Ref obj, py_Type type){
|
||||
return py_issubclass(obj->type, type);
|
||||
}
|
||||
bool py_isinstance(py_Ref obj, py_Type type) { return py_issubclass(obj->type, type); }
|
||||
|
||||
bool py_issubclass(py_Type derived, py_Type base){
|
||||
pk_TypeInfo* types = pk_current_vm->types.data;
|
||||
bool py_issubclass(py_Type derived, py_Type base) {
|
||||
py_TypeInfo* types = pk_current_vm->types.data;
|
||||
do {
|
||||
if(derived == base) return true;
|
||||
derived = types[derived].base;
|
||||
|
||||
@ -9,18 +9,18 @@
|
||||
#include "pocketpy/compiler/compiler.h"
|
||||
#include <stdint.h>
|
||||
|
||||
pk_VM* pk_current_vm;
|
||||
VM* pk_current_vm;
|
||||
|
||||
py_GlobalRef py_True;
|
||||
py_GlobalRef py_False;
|
||||
py_GlobalRef py_None;
|
||||
py_GlobalRef py_NIL;
|
||||
|
||||
static pk_VM pk_default_vm;
|
||||
static pk_VM* pk_all_vm[16];
|
||||
static VM pk_default_vm;
|
||||
static VM* pk_all_vm[16];
|
||||
|
||||
void py_initialize() {
|
||||
pk_MemoryPools__initialize();
|
||||
MemoryPools__initialize();
|
||||
py_Name__initialize();
|
||||
|
||||
pk_current_vm = pk_all_vm[0] = &pk_default_vm;
|
||||
@ -35,28 +35,28 @@ void py_initialize() {
|
||||
py_False = &_False;
|
||||
py_None = &_None;
|
||||
py_NIL = &_NIL;
|
||||
pk_VM__ctor(&pk_default_vm);
|
||||
VM__ctor(&pk_default_vm);
|
||||
}
|
||||
|
||||
void py_finalize() {
|
||||
for(int i = 1; i < 16; i++) {
|
||||
pk_VM* vm = pk_all_vm[i];
|
||||
VM* vm = pk_all_vm[i];
|
||||
if(vm) {
|
||||
pk_VM__dtor(vm);
|
||||
VM__dtor(vm);
|
||||
free(vm);
|
||||
}
|
||||
}
|
||||
pk_VM__dtor(&pk_default_vm);
|
||||
VM__dtor(&pk_default_vm);
|
||||
pk_current_vm = NULL;
|
||||
py_Name__finalize();
|
||||
pk_MemoryPools__finalize();
|
||||
MemoryPools__finalize();
|
||||
}
|
||||
|
||||
void py_switchvm(int index) {
|
||||
if(index < 0 || index >= 16) c11__abort("invalid vm index");
|
||||
if(!pk_all_vm[index]) {
|
||||
pk_all_vm[index] = malloc(sizeof(pk_VM));
|
||||
pk_VM__ctor(pk_all_vm[index]);
|
||||
pk_all_vm[index] = malloc(sizeof(VM));
|
||||
VM__ctor(pk_all_vm[index]);
|
||||
}
|
||||
pk_current_vm = pk_all_vm[index];
|
||||
}
|
||||
@ -184,9 +184,9 @@ static void disassemble(CodeObject* co) {
|
||||
}
|
||||
|
||||
bool py_exec(const char* source, const char* filename, enum py_CompileMode mode, py_Ref module) {
|
||||
pk_VM* vm = pk_current_vm;
|
||||
VM* vm = pk_current_vm;
|
||||
CodeObject co;
|
||||
pk_SourceData_ src = pk_SourceData__rcnew(source, filename, mode, false);
|
||||
SourceData_ src = SourceData__rcnew(source, filename, mode, false);
|
||||
Error* err = pk_compile(src, &co);
|
||||
if(err) {
|
||||
py_exception("SyntaxError", err->msg);
|
||||
@ -201,8 +201,8 @@ bool py_exec(const char* source, const char* filename, enum py_CompileMode mode,
|
||||
if(!module) module = &vm->main;
|
||||
|
||||
Frame* frame = Frame__new(&co, module, NULL, vm->stack.sp, vm->stack.sp, &co);
|
||||
pk_VM__push_frame(vm, frame);
|
||||
pk_FrameResult res = pk_VM__run_top_frame(vm);
|
||||
VM__push_frame(vm, frame);
|
||||
FrameResult res = VM__run_top_frame(vm);
|
||||
CodeObject__dtor(&co);
|
||||
PK_DECREF(src);
|
||||
if(res == RES_ERROR) return false;
|
||||
@ -225,8 +225,8 @@ bool py_call(py_Ref f, int argc, py_Ref argv) {
|
||||
bool py_callmethod(py_Ref self, py_Name name, int argc, py_Ref argv) { return -1; }
|
||||
|
||||
bool py_vectorcall(uint16_t argc, uint16_t kwargc) {
|
||||
pk_VM* vm = pk_current_vm;
|
||||
return pk_VM__vectorcall(vm, argc, kwargc, false) != RES_ERROR;
|
||||
VM* vm = pk_current_vm;
|
||||
return VM__vectorcall(vm, argc, kwargc, false) != RES_ERROR;
|
||||
}
|
||||
|
||||
py_Ref py_retval() { return &pk_current_vm->last_retval; }
|
||||
@ -238,8 +238,8 @@ bool pk_pushmethod(py_StackRef self, py_Name name) {
|
||||
py_Type type;
|
||||
// handle super() proxy
|
||||
if(py_istype(self, tp_super)) {
|
||||
self = py_getslot(self, 0);
|
||||
type = *(py_Type*)py_touserdata(self);
|
||||
*self = *py_getslot(self, 0);
|
||||
} else {
|
||||
type = self->type;
|
||||
}
|
||||
@ -262,19 +262,18 @@ bool pk_pushmethod(py_StackRef self, py_Name name) {
|
||||
break;
|
||||
case tp_classmethod:
|
||||
self[0] = *py_getslot(cls_var, 0);
|
||||
self[1] = c11__getitem(pk_TypeInfo, &pk_current_vm->types, type).self;
|
||||
self[1] = c11__getitem(py_TypeInfo, &pk_current_vm->types, type).self;
|
||||
break;
|
||||
default: c11__unreachedable();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// TODO: __getattr__ fallback
|
||||
return false;
|
||||
}
|
||||
|
||||
py_Ref py_tpfindmagic(py_Type t, py_Name name) {
|
||||
assert(py_ismagicname(name));
|
||||
pk_TypeInfo* types = (pk_TypeInfo*)pk_current_vm->types.data;
|
||||
py_TypeInfo* types = (py_TypeInfo*)pk_current_vm->types.data;
|
||||
do {
|
||||
py_Ref f = &types[t].magic[name];
|
||||
if(!py_isnil(f)) return f;
|
||||
@ -284,7 +283,7 @@ py_Ref py_tpfindmagic(py_Type t, py_Name name) {
|
||||
}
|
||||
|
||||
py_Ref py_tpfindname(py_Type t, py_Name name) {
|
||||
pk_TypeInfo* types = (pk_TypeInfo*)pk_current_vm->types.data;
|
||||
py_TypeInfo* types = (py_TypeInfo*)pk_current_vm->types.data;
|
||||
do {
|
||||
py_Ref res = py_getdict(&types[t].self, name);
|
||||
if(res) return res;
|
||||
@ -295,20 +294,20 @@ py_Ref py_tpfindname(py_Type t, py_Name name) {
|
||||
|
||||
py_Ref py_tpmagic(py_Type type, py_Name name) {
|
||||
assert(py_ismagicname(name));
|
||||
pk_VM* vm = pk_current_vm;
|
||||
return &c11__at(pk_TypeInfo, &vm->types, type)->magic[name];
|
||||
VM* vm = pk_current_vm;
|
||||
return &c11__at(py_TypeInfo, &vm->types, type)->magic[name];
|
||||
}
|
||||
|
||||
py_Ref py_tpobject(py_Type type) {
|
||||
assert(type);
|
||||
pk_VM* vm = pk_current_vm;
|
||||
return &c11__at(pk_TypeInfo, &vm->types, type)->self;
|
||||
VM* vm = pk_current_vm;
|
||||
return &c11__at(py_TypeInfo, &vm->types, type)->self;
|
||||
}
|
||||
|
||||
const char* py_tpname(py_Type type) {
|
||||
if(!type) return "nil";
|
||||
pk_VM* vm = pk_current_vm;
|
||||
py_Name name = c11__at(pk_TypeInfo, &vm->types, type)->name;
|
||||
VM* vm = pk_current_vm;
|
||||
py_Name name = c11__at(py_TypeInfo, &vm->types, type)->name;
|
||||
return py_name2str(name);
|
||||
}
|
||||
|
||||
@ -325,7 +324,7 @@ bool pk_callmagic(py_Name name, int argc, py_Ref argv) {
|
||||
}
|
||||
|
||||
bool StopIteration() {
|
||||
pk_VM* vm = pk_current_vm;
|
||||
VM* vm = pk_current_vm;
|
||||
assert(!vm->is_stopiteration); // flag is already set
|
||||
vm->is_stopiteration = true;
|
||||
return false;
|
||||
|
||||
@ -4,15 +4,16 @@
|
||||
#include "pocketpy/objects/object.h"
|
||||
#include "pocketpy/common/sstream.h"
|
||||
#include "pocketpy/interpreter/vm.h"
|
||||
#include "pocketpy/common/_generated.h"
|
||||
|
||||
py_Ref py_getmodule(const char* path) {
|
||||
pk_VM* vm = pk_current_vm;
|
||||
return pk_NameDict__try_get(&vm->modules, py_name(path));
|
||||
VM* vm = pk_current_vm;
|
||||
return NameDict__try_get(&vm->modules, py_name(path));
|
||||
}
|
||||
|
||||
py_Ref py_newmodule(const char* path) {
|
||||
pk_ManagedHeap* heap = &pk_current_vm->heap;
|
||||
PyObject* obj = pk_ManagedHeap__new(heap, tp_module, -1, 0);
|
||||
ManagedHeap* heap = &pk_current_vm->heap;
|
||||
PyObject* obj = ManagedHeap__new(heap, tp_module, -1, 0);
|
||||
|
||||
py_Ref r0 = py_pushtmp();
|
||||
py_Ref r1 = py_pushtmp();
|
||||
@ -43,28 +44,61 @@ py_Ref py_newmodule(const char* path) {
|
||||
// we do not allow override in order to avoid memory leak
|
||||
// it is because Module objects are not garbage collected
|
||||
py_Name path_name = py_name(path);
|
||||
bool exists = pk_NameDict__contains(&pk_current_vm->modules, path_name);
|
||||
bool exists = NameDict__contains(&pk_current_vm->modules, path_name);
|
||||
if(exists) c11__abort("module '%s' already exists", path);
|
||||
pk_NameDict__set(&pk_current_vm->modules, path_name, *r0);
|
||||
NameDict__set(&pk_current_vm->modules, path_name, *r0);
|
||||
|
||||
py_shrink(2);
|
||||
return py_getmodule(path);
|
||||
}
|
||||
|
||||
bool py_import(const char* path_cstr) {
|
||||
pk_VM* vm = pk_current_vm;
|
||||
int py_import(const char* path_cstr) {
|
||||
// printf("importing %s\n", path_cstr);
|
||||
|
||||
VM* vm = pk_current_vm;
|
||||
c11_sv path = {path_cstr, strlen(path_cstr)};
|
||||
if(path.size == 0) return ValueError("empty module name");
|
||||
|
||||
if(path.data[0] == '.') {
|
||||
// try relative import
|
||||
py_Ref package = py_getdict(&vm->top_frame->module, __package__);
|
||||
int dot_count = 1;
|
||||
while(dot_count < path.size && path.data[dot_count] == '.')
|
||||
dot_count++;
|
||||
|
||||
c11_sv top_filename = c11_string__sv(vm->top_frame->co->src->filename);
|
||||
int is_init = c11_sv__endswith(top_filename, (c11_sv){"__init__.py", 11});
|
||||
|
||||
py_Ref package = py_getdict(&vm->top_frame->module, __path__);
|
||||
c11_sv package_sv = py_tosv(package);
|
||||
if(package_sv.size == 0) return ImportError("relative import %q with no known parent package", path);
|
||||
c11_string* new_path = c11_string__new3("%v.%v", package_sv, path);
|
||||
bool ok = py_import(new_path->data);
|
||||
if(package_sv.size == 0) {
|
||||
return ImportError("attempted relative import with no known parent package");
|
||||
}
|
||||
|
||||
c11_vector /* T=c11_sv */ cpnts = c11_sv__split(package_sv, '.');
|
||||
for(int i = is_init; i < dot_count; i++) {
|
||||
if(cpnts.count == 0)
|
||||
return ImportError("attempted relative import beyond top-level package");
|
||||
c11_vector__pop(&cpnts);
|
||||
}
|
||||
|
||||
if(dot_count < path.size) {
|
||||
c11_sv last_cpnt = c11_sv__slice(path, dot_count);
|
||||
c11_vector__push(c11_sv, &cpnts, last_cpnt);
|
||||
}
|
||||
|
||||
// join cpnts
|
||||
c11_sbuf buf;
|
||||
c11_sbuf__ctor(&buf);
|
||||
for(int i = 0; i < cpnts.count; i++) {
|
||||
if(i > 0) c11_sbuf__write_char(&buf, '.');
|
||||
c11_sbuf__write_sv(&buf, c11__getitem(c11_sv, &cpnts, i));
|
||||
}
|
||||
|
||||
c11_vector__dtor(&cpnts);
|
||||
c11_string* new_path = c11_sbuf__submit(&buf);
|
||||
int res = py_import(new_path->data);
|
||||
c11_string__delete(new_path);
|
||||
return ok;
|
||||
return res;
|
||||
}
|
||||
|
||||
assert(path.data[0] != '.' && path.data[path.size - 1] != '.');
|
||||
@ -72,67 +106,54 @@ bool py_import(const char* path_cstr) {
|
||||
// check existing module
|
||||
py_TmpRef ext_mod = py_getmodule(path.data);
|
||||
if(ext_mod) {
|
||||
py_Ref is_pending = py_getdict(ext_mod, __module_is_pending__);
|
||||
if(is_pending) return ImportError("circular import detected");
|
||||
py_assign(py_retval(), ext_mod);
|
||||
return true;
|
||||
}
|
||||
|
||||
// vector<std::string_view> path_cpnts = path.split('.');
|
||||
// // check circular import
|
||||
// if(__import_context.pending.size() > 128) { ImportError("maximum recursion depth exceeded
|
||||
// while importing"); }
|
||||
|
||||
// try import
|
||||
c11_string* slashed_path = c11_sv__replace(path, '.', PK_PLATFORM_SEP);
|
||||
c11_string* filename = c11_string__new3("%s.py", slashed_path->data);
|
||||
|
||||
c11_string* filename = c11_string__new3("site-packages/%s.py", slashed_path->data);
|
||||
int size;
|
||||
unsigned char* data = py_vfsread(filename->data, &size);
|
||||
if(data != NULL) goto __SUCCESS;
|
||||
bool need_free = true;
|
||||
const char* data = load_kPythonLib(path_cstr);
|
||||
if(data != NULL) {
|
||||
need_free = false;
|
||||
goto __SUCCESS;
|
||||
}
|
||||
|
||||
c11_string__delete(filename);
|
||||
filename = c11_string__new3("site-packages/%s/__init__.py", slashed_path->data);
|
||||
data = py_vfsread(filename->data, &size);
|
||||
if(data != NULL) goto __SUCCESS;
|
||||
|
||||
c11_string__delete(filename);
|
||||
filename = c11_string__new3("%s.py", slashed_path->data);
|
||||
data = vm->import_file(slashed_path->data, &size);
|
||||
data = vm->import_file(filename->data);
|
||||
if(data != NULL) goto __SUCCESS;
|
||||
|
||||
c11_string__delete(filename);
|
||||
filename = c11_string__new3("%s/__init__.py", slashed_path->data);
|
||||
data = vm->import_file(slashed_path->data, &size);
|
||||
data = vm->import_file(filename->data);
|
||||
if(data != NULL) goto __SUCCESS;
|
||||
|
||||
c11_string__delete(filename);
|
||||
c11_string__delete(slashed_path);
|
||||
return ImportError("module %q not found", path);
|
||||
return 0;
|
||||
|
||||
__SUCCESS:
|
||||
py_push(py_newmodule(path_cstr));
|
||||
py_Ref mod = py_peek(-1);
|
||||
py_setdict(mod, __module_is_pending__, py_True);
|
||||
bool ok = py_exec((const char*)data, filename->data, EXEC_MODE, mod);
|
||||
py_deldict(mod, __module_is_pending__);
|
||||
py_assign(py_retval(), mod);
|
||||
py_pop();
|
||||
|
||||
c11_string__delete(filename);
|
||||
c11_string__delete(slashed_path);
|
||||
free(data);
|
||||
return ok;
|
||||
if(need_free) free((void*)data);
|
||||
return ok ? 1 : -1;
|
||||
}
|
||||
|
||||
//////////////////////////
|
||||
|
||||
static bool _py_builtins__repr(int argc, py_Ref argv) {
|
||||
static bool builtins__repr(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
return py_repr(argv);
|
||||
}
|
||||
|
||||
static bool _py_builtins__exit(int argc, py_Ref argv) {
|
||||
static bool builtins__exit(int argc, py_Ref argv) {
|
||||
int code = 0;
|
||||
if(argc > 1) return TypeError("exit() takes at most 1 argument");
|
||||
if(argc == 1) {
|
||||
@ -144,12 +165,12 @@ static bool _py_builtins__exit(int argc, py_Ref argv) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool _py_builtins__len(int argc, py_Ref argv) {
|
||||
static bool builtins__len(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
return py_len(argv);
|
||||
}
|
||||
|
||||
static bool _py_builtins__reversed(int argc, py_Ref argv) {
|
||||
static bool builtins__reversed(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
// convert _0 to list object
|
||||
if(!py_tpcall(tp_list, 1, argv)) return false;
|
||||
@ -157,7 +178,7 @@ static bool _py_builtins__reversed(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_builtins__hex(int argc, py_Ref argv) {
|
||||
static bool builtins__hex(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
PY_CHECK_ARG_TYPE(0, tp_int);
|
||||
|
||||
@ -187,12 +208,12 @@ static bool _py_builtins__hex(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_builtins__iter(int argc, py_Ref argv) {
|
||||
static bool builtins__iter(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
return py_iter(argv);
|
||||
}
|
||||
|
||||
static bool _py_builtins__next(int argc, py_Ref argv) {
|
||||
static bool builtins__next(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
int res = py_next(argv);
|
||||
if(res == -1) return false;
|
||||
@ -200,7 +221,7 @@ static bool _py_builtins__next(int argc, py_Ref argv) {
|
||||
return py_exception("StopIteration", "");
|
||||
}
|
||||
|
||||
static bool _py_builtins__sorted(int argc, py_Ref argv) {
|
||||
static bool builtins__sorted(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(3);
|
||||
// convert _0 to list object
|
||||
if(!py_tpcall(tp_list, 1, py_arg(0))) return false;
|
||||
@ -217,7 +238,7 @@ static bool _py_builtins__sorted(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_builtins__hash(int argc, py_Ref argv) {
|
||||
static bool builtins__hash(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
py_i64 val;
|
||||
if(!py_hash(argv, &val)) return false;
|
||||
@ -225,28 +246,36 @@ static bool _py_builtins__hash(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_builtins__abs(int argc, py_Ref argv) {
|
||||
static bool builtins__abs(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
return pk_callmagic(__abs__, 1, argv);
|
||||
}
|
||||
|
||||
static bool _py_builtins__sum(int argc, py_Ref argv) {
|
||||
static bool builtins__sum(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
int length;
|
||||
py_TValue* p = pk_arrayview(argv, &length);
|
||||
if(!p) return TypeError("sum() expects a list or tuple");
|
||||
|
||||
if(!py_iter(py_arg(0))) return false;
|
||||
py_push(py_retval()); // iter
|
||||
|
||||
py_i64 total_i64 = 0;
|
||||
py_f64 total_f64 = 0.0;
|
||||
bool is_float = false;
|
||||
for(int i = 0; i < length; i++) {
|
||||
switch(p[i].type) {
|
||||
case tp_int: total_i64 += p[i]._i64; break;
|
||||
while(true) {
|
||||
int res = py_next(py_peek(-1));
|
||||
if(res == -1) {
|
||||
py_pop();
|
||||
return false;
|
||||
}
|
||||
if(res == 0) break;
|
||||
|
||||
py_Ref item = py_retval();
|
||||
switch(item->type) {
|
||||
case tp_int: total_i64 += item->_i64; break;
|
||||
case tp_float:
|
||||
is_float = true;
|
||||
total_f64 += p[i]._f64;
|
||||
total_f64 += item->_f64;
|
||||
break;
|
||||
default: return TypeError("sum() expects a list of numbers");
|
||||
default: return TypeError("sum() expects an iterable of numbers");
|
||||
}
|
||||
}
|
||||
|
||||
@ -255,10 +284,11 @@ static bool _py_builtins__sum(int argc, py_Ref argv) {
|
||||
} else {
|
||||
py_newint(py_retval(), total_i64);
|
||||
}
|
||||
py_pop();
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_builtins__print(int argc, py_Ref argv) {
|
||||
static bool builtins__print(int argc, py_Ref argv) {
|
||||
int length;
|
||||
py_TValue* args = pk_arrayview(argv, &length);
|
||||
assert(args != NULL);
|
||||
@ -279,44 +309,76 @@ static bool _py_builtins__print(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_NoneType__repr__(int argc, py_Ref argv) {
|
||||
static bool NoneType__repr__(int argc, py_Ref argv) {
|
||||
py_newstr(py_retval(), "None");
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_builtins__exec(int argc, py_Ref argv) {
|
||||
static bool builtins__exec(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
PY_CHECK_ARG_TYPE(0, tp_str);
|
||||
return py_exec(py_tostr(argv), "<exec>", EXEC_MODE, NULL);
|
||||
}
|
||||
|
||||
static bool _py_builtins__eval(int argc, py_Ref argv) {
|
||||
static bool builtins__eval(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
PY_CHECK_ARG_TYPE(0, tp_str);
|
||||
return py_exec(py_tostr(argv), "<eval>", EVAL_MODE, NULL);
|
||||
}
|
||||
|
||||
static bool builtins__isinstance(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
if(py_istuple(py_arg(1))) {
|
||||
int length = py_tuple__len(py_arg(1));
|
||||
for(int i = 0; i < length; i++) {
|
||||
py_Ref item = py_tuple__getitem(py_arg(1), i);
|
||||
if(!py_checktype(item, tp_type)) return false;
|
||||
if(py_isinstance(py_arg(0), py_totype(item))) {
|
||||
py_newbool(py_retval(), true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
py_newbool(py_retval(), false);
|
||||
return true;
|
||||
}
|
||||
|
||||
if(!py_checktype(py_arg(1), tp_type)) return false;
|
||||
py_newbool(py_retval(), py_isinstance(py_arg(0), py_totype(py_arg(1))));
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool builtins__issubclass(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
if(!py_checktype(py_arg(0), tp_type)) return false;
|
||||
if(!py_checktype(py_arg(1), tp_type)) return false;
|
||||
py_newbool(py_retval(), py_issubclass(py_totype(py_arg(0)), py_totype(py_arg(1))));
|
||||
return true;
|
||||
}
|
||||
|
||||
py_TValue pk_builtins__register() {
|
||||
py_Ref builtins = py_newmodule("builtins");
|
||||
py_bindfunc(builtins, "repr", _py_builtins__repr);
|
||||
py_bindfunc(builtins, "exit", _py_builtins__exit);
|
||||
py_bindfunc(builtins, "len", _py_builtins__len);
|
||||
py_bindfunc(builtins, "reversed", _py_builtins__reversed);
|
||||
py_bindfunc(builtins, "hex", _py_builtins__hex);
|
||||
py_bindfunc(builtins, "iter", _py_builtins__iter);
|
||||
py_bindfunc(builtins, "next", _py_builtins__next);
|
||||
py_bindfunc(builtins, "hash", _py_builtins__hash);
|
||||
py_bindfunc(builtins, "abs", _py_builtins__abs);
|
||||
py_bindfunc(builtins, "sum", _py_builtins__sum);
|
||||
py_bindfunc(builtins, "repr", builtins__repr);
|
||||
py_bindfunc(builtins, "exit", builtins__exit);
|
||||
py_bindfunc(builtins, "len", builtins__len);
|
||||
py_bindfunc(builtins, "reversed", builtins__reversed);
|
||||
py_bindfunc(builtins, "hex", builtins__hex);
|
||||
py_bindfunc(builtins, "iter", builtins__iter);
|
||||
py_bindfunc(builtins, "next", builtins__next);
|
||||
py_bindfunc(builtins, "hash", builtins__hash);
|
||||
py_bindfunc(builtins, "abs", builtins__abs);
|
||||
py_bindfunc(builtins, "sum", builtins__sum);
|
||||
|
||||
py_bindfunc(builtins, "exec", _py_builtins__exec);
|
||||
py_bindfunc(builtins, "eval", _py_builtins__eval);
|
||||
py_bindfunc(builtins, "exec", builtins__exec);
|
||||
py_bindfunc(builtins, "eval", builtins__eval);
|
||||
|
||||
py_bind(builtins, "print(*args, sep=' ', end='\\n')", _py_builtins__print);
|
||||
py_bind(builtins, "sorted(iterable, key=None, reverse=False)", _py_builtins__sorted);
|
||||
py_bind(builtins, "print(*args, sep=' ', end='\\n')", builtins__print);
|
||||
py_bind(builtins, "sorted(iterable, key=None, reverse=False)", builtins__sorted);
|
||||
|
||||
py_bindfunc(builtins, "isinstance", builtins__isinstance);
|
||||
py_bindfunc(builtins, "issubclass", builtins__issubclass);
|
||||
|
||||
// None __repr__
|
||||
py_bindmagic(tp_NoneType, __repr__, _py_NoneType__repr__);
|
||||
py_bindmagic(tp_NoneType, __repr__, NoneType__repr__);
|
||||
return *builtins;
|
||||
}
|
||||
|
||||
@ -326,7 +388,7 @@ py_Type pk_function__register() {
|
||||
return type;
|
||||
}
|
||||
|
||||
static bool _py_nativefunc__repr(int argc, py_Ref argv) {
|
||||
static bool nativefunc__repr(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
py_newstr(py_retval(), "<nativefunc object>");
|
||||
return true;
|
||||
@ -334,6 +396,46 @@ static bool _py_nativefunc__repr(int argc, py_Ref argv) {
|
||||
|
||||
py_Type pk_nativefunc__register() {
|
||||
py_Type type = pk_newtype("nativefunc", tp_object, NULL, NULL, false, true);
|
||||
py_bindmagic(type, __repr__, _py_nativefunc__repr);
|
||||
py_bindmagic(type, __repr__, nativefunc__repr);
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
static bool super__new__(int argc, py_Ref argv) {
|
||||
py_Type* class_arg = py_newobject(py_retval(), tp_super, 1, sizeof(py_Type));
|
||||
Frame* frame = pk_current_vm->top_frame;
|
||||
*class_arg = 0;
|
||||
py_Ref self_arg = NULL;
|
||||
if(argc == 1) {
|
||||
// super()
|
||||
if(frame->function) {
|
||||
// class_arg = PK_OBJ_GET(Function, frame->_callable)._class;
|
||||
Function* func = PyObject__userdata(frame->function);
|
||||
*class_arg = *(py_Type*)PyObject__userdata(func->clazz);
|
||||
if(frame->locals_co->nlocals > 0) self_arg = &frame->locals[0];
|
||||
}
|
||||
if(class_arg == 0 || self_arg == NULL) return RuntimeError("super(): no arguments");
|
||||
} else if(argc == 3) {
|
||||
// super(type, obj)
|
||||
PY_CHECK_ARG_TYPE(1, tp_type);
|
||||
*class_arg = py_totype(py_arg(1));
|
||||
self_arg = py_arg(2);
|
||||
if(!py_isinstance(self_arg, *class_arg)) {
|
||||
return TypeError("super(type, obj): obj must be an instance of type");
|
||||
}
|
||||
} else {
|
||||
return TypeError("super() takes 0 or 2 arguments");
|
||||
}
|
||||
|
||||
py_TypeInfo* types = pk_current_vm->types.data;
|
||||
*class_arg = types[*class_arg].base;
|
||||
if(*class_arg == 0) return RuntimeError("super(): base class is invalid");
|
||||
|
||||
py_setslot(py_retval(), 0, self_arg);
|
||||
return true;
|
||||
}
|
||||
|
||||
py_Type pk_super__register() {
|
||||
py_Type type = pk_newtype("super", tp_object, NULL, NULL, false, true);
|
||||
py_bindmagic(type, __new__, super__new__);
|
||||
return type;
|
||||
}
|
||||
|
||||
@ -61,13 +61,13 @@ bool pk_arraycontains(py_Ref self, py_Ref val) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_array_iterator__iter__(int argc, py_Ref argv) {
|
||||
static bool array_iterator__iter__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
*py_retval() = *argv;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_array_iterator__next__(int argc, py_Ref argv) {
|
||||
static bool array_iterator__next__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
array_iterator* ud = py_touserdata(argv);
|
||||
if(ud->index < ud->length) {
|
||||
@ -79,7 +79,7 @@ static bool _py_array_iterator__next__(int argc, py_Ref argv) {
|
||||
|
||||
py_Type pk_array_iterator__register() {
|
||||
py_Type type = pk_newtype("array_iterator", tp_object, NULL, NULL, false, true);
|
||||
py_bindmagic(type, __iter__, _py_array_iterator__iter__);
|
||||
py_bindmagic(type, __next__, _py_array_iterator__next__);
|
||||
py_bindmagic(type, __iter__, array_iterator__iter__);
|
||||
py_bindmagic(type, __next__, array_iterator__next__);
|
||||
return type;
|
||||
}
|
||||
|
||||
@ -204,12 +204,12 @@ static DictEntry* DictIterator__next(DictIterator* self) {
|
||||
}
|
||||
|
||||
///////////////////////////////
|
||||
static bool _py_dict__new__(int argc, py_Ref argv) {
|
||||
static bool dict__new__(int argc, py_Ref argv) {
|
||||
py_newdict(py_retval());
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_dict__init__(int argc, py_Ref argv) {
|
||||
static bool dict__init__(int argc, py_Ref argv) {
|
||||
if(argc > 2) return TypeError("dict.__init__() takes at most 2 arguments (%d given)", argc);
|
||||
if(argc == 1) return true;
|
||||
assert(argc == 2);
|
||||
@ -228,7 +228,7 @@ static bool _py_dict__init__(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_dict__getitem__(int argc, py_Ref argv) {
|
||||
static bool dict__getitem__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
Dict* self = py_touserdata(argv);
|
||||
DictEntry* entry;
|
||||
@ -240,20 +240,20 @@ static bool _py_dict__getitem__(int argc, py_Ref argv) {
|
||||
return KeyError(py_arg(1));
|
||||
}
|
||||
|
||||
static bool _py_dict__setitem__(int argc, py_Ref argv) {
|
||||
static bool dict__setitem__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(3);
|
||||
Dict* self = py_touserdata(argv);
|
||||
return Dict__set(self, py_arg(1), py_arg(2));
|
||||
}
|
||||
|
||||
static bool _py_dict__delitem__(int argc, py_Ref argv) {
|
||||
static bool dict__delitem__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
Dict* self = py_touserdata(argv);
|
||||
if(!Dict__pop(self, py_arg(1))) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_dict__contains__(int argc, py_Ref argv) {
|
||||
static bool dict__contains__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
Dict* self = py_touserdata(argv);
|
||||
DictEntry* entry;
|
||||
@ -262,14 +262,14 @@ static bool _py_dict__contains__(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_dict__len__(int argc, py_Ref argv) {
|
||||
static bool dict__len__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
Dict* self = py_touserdata(argv);
|
||||
py_newint(py_retval(), self->length);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_dict__repr__(int argc, py_Ref argv) {
|
||||
static bool dict__repr__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
Dict* self = py_touserdata(argv);
|
||||
c11_sbuf buf;
|
||||
@ -292,7 +292,7 @@ static bool _py_dict__repr__(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_dict__eq__(int argc, py_Ref argv) {
|
||||
static bool dict__eq__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
Dict* self = py_touserdata(py_arg(0));
|
||||
if(!py_isdict(py_arg(1))) {
|
||||
@ -326,8 +326,8 @@ static bool _py_dict__eq__(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_dict__ne__(int argc, py_Ref argv) {
|
||||
if(!_py_dict__eq__(argc, argv)) return false;
|
||||
static bool dict__ne__(int argc, py_Ref argv) {
|
||||
if(!dict__eq__(argc, argv)) return false;
|
||||
if(py_isbool(py_retval())) {
|
||||
bool res = py_tobool(py_retval());
|
||||
py_newbool(py_retval(), !res);
|
||||
@ -335,14 +335,14 @@ static bool _py_dict__ne__(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_dict__clear(int argc, py_Ref argv) {
|
||||
static bool dict__clear(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
Dict* self = py_touserdata(argv);
|
||||
Dict__clear(self);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_dict__copy(int argc, py_Ref argv) {
|
||||
static bool dict__copy(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
Dict* self = py_touserdata(argv);
|
||||
Dict* new_dict = py_newobject(py_retval(), tp_dict, 0, sizeof(Dict));
|
||||
@ -355,7 +355,7 @@ static bool _py_dict__copy(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_dict__update(int argc, py_Ref argv) {
|
||||
static bool dict__update(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
PY_CHECK_ARG_TYPE(1, tp_dict);
|
||||
Dict* self = py_touserdata(argv);
|
||||
@ -368,7 +368,7 @@ static bool _py_dict__update(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_dict__get(int argc, py_Ref argv) {
|
||||
static bool dict__get(int argc, py_Ref argv) {
|
||||
Dict* self = py_touserdata(argv);
|
||||
if(argc > 3) return TypeError("get() takes at most 3 arguments (%d given)", argc);
|
||||
py_Ref default_val = argc == 3 ? py_arg(2) : py_None;
|
||||
@ -378,7 +378,7 @@ static bool _py_dict__get(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_dict__pop(int argc, py_Ref argv) {
|
||||
static bool dict__pop(int argc, py_Ref argv) {
|
||||
Dict* self = py_touserdata(argv);
|
||||
if(argc < 2 || argc > 3) return TypeError("pop() takes 2 or 3 arguments (%d given)", argc);
|
||||
py_Ref default_val = argc == 3 ? py_arg(2) : py_None;
|
||||
@ -387,7 +387,7 @@ static bool _py_dict__pop(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_dict__items(int argc, py_Ref argv) {
|
||||
static bool dict__items(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
Dict* self = py_touserdata(argv);
|
||||
DictIterator* ud = py_newobject(py_retval(), tp_dict_items, 1, sizeof(DictIterator));
|
||||
@ -396,7 +396,7 @@ static bool _py_dict__items(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_dict__keys(int argc, py_Ref argv) {
|
||||
static bool dict__keys(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
Dict* self = py_touserdata(argv);
|
||||
py_newtuple(py_retval(), self->length);
|
||||
@ -412,7 +412,7 @@ static bool _py_dict__keys(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_dict__values(int argc, py_Ref argv) {
|
||||
static bool dict__values(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
Dict* self = py_touserdata(argv);
|
||||
py_newtuple(py_retval(), self->length);
|
||||
@ -431,38 +431,38 @@ static bool _py_dict__values(int argc, py_Ref argv) {
|
||||
py_Type pk_dict__register() {
|
||||
py_Type type = pk_newtype("dict", tp_object, NULL, (void (*)(void*))Dict__dtor, false, false);
|
||||
|
||||
py_bindmagic(type, __new__, _py_dict__new__);
|
||||
py_bindmagic(type, __init__, _py_dict__init__);
|
||||
py_bindmagic(type, __getitem__, _py_dict__getitem__);
|
||||
py_bindmagic(type, __setitem__, _py_dict__setitem__);
|
||||
py_bindmagic(type, __delitem__, _py_dict__delitem__);
|
||||
py_bindmagic(type, __contains__, _py_dict__contains__);
|
||||
py_bindmagic(type, __len__, _py_dict__len__);
|
||||
py_bindmagic(type, __repr__, _py_dict__repr__);
|
||||
py_bindmagic(type, __eq__, _py_dict__eq__);
|
||||
py_bindmagic(type, __ne__, _py_dict__ne__);
|
||||
py_bindmagic(type, __new__, dict__new__);
|
||||
py_bindmagic(type, __init__, dict__init__);
|
||||
py_bindmagic(type, __getitem__, dict__getitem__);
|
||||
py_bindmagic(type, __setitem__, dict__setitem__);
|
||||
py_bindmagic(type, __delitem__, dict__delitem__);
|
||||
py_bindmagic(type, __contains__, dict__contains__);
|
||||
py_bindmagic(type, __len__, dict__len__);
|
||||
py_bindmagic(type, __repr__, dict__repr__);
|
||||
py_bindmagic(type, __eq__, dict__eq__);
|
||||
py_bindmagic(type, __ne__, dict__ne__);
|
||||
|
||||
py_bindmethod(type, "clear", _py_dict__clear);
|
||||
py_bindmethod(type, "copy", _py_dict__copy);
|
||||
py_bindmethod(type, "update", _py_dict__update);
|
||||
py_bindmethod(type, "get", _py_dict__get);
|
||||
py_bindmethod(type, "pop", _py_dict__pop);
|
||||
py_bindmethod(type, "items", _py_dict__items);
|
||||
py_bindmethod(type, "keys", _py_dict__keys);
|
||||
py_bindmethod(type, "values", _py_dict__values);
|
||||
py_bindmethod(type, "clear", dict__clear);
|
||||
py_bindmethod(type, "copy", dict__copy);
|
||||
py_bindmethod(type, "update", dict__update);
|
||||
py_bindmethod(type, "get", dict__get);
|
||||
py_bindmethod(type, "pop", dict__pop);
|
||||
py_bindmethod(type, "items", dict__items);
|
||||
py_bindmethod(type, "keys", dict__keys);
|
||||
py_bindmethod(type, "values", dict__values);
|
||||
|
||||
py_setdict(py_tpobject(type), __hash__, py_None);
|
||||
return type;
|
||||
}
|
||||
|
||||
//////////////////////////
|
||||
static bool _py_dict_items__iter__(int argc, py_Ref argv) {
|
||||
static bool dict_items__iter__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
*py_retval() = *argv;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_dict_items__next__(int argc, py_Ref argv) {
|
||||
static bool dict_items__next__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
DictIterator* iter = py_touserdata(py_arg(0));
|
||||
DictEntry* entry = (DictIterator__next(iter));
|
||||
@ -477,8 +477,8 @@ static bool _py_dict_items__next__(int argc, py_Ref argv) {
|
||||
|
||||
py_Type pk_dict_items__register() {
|
||||
py_Type type = pk_newtype("dict_items", tp_object, NULL, NULL, false, true);
|
||||
py_bindmagic(type, __iter__, _py_dict_items__iter__);
|
||||
py_bindmagic(type, __next__, _py_dict_items__next__);
|
||||
py_bindmagic(type, __iter__, dict_items__iter__);
|
||||
py_bindmagic(type, __next__, dict_items__next__);
|
||||
return type;
|
||||
}
|
||||
|
||||
@ -524,7 +524,7 @@ int py_dict__len(py_Ref self) {
|
||||
return ud->length;
|
||||
}
|
||||
|
||||
bool py_dict__apply(py_Ref self, bool (*f)(py_Ref, py_Ref, void *), void *ctx){
|
||||
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++) {
|
||||
DictEntry* entry = c11__at(DictEntry, &ud->entries, i);
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
#include "pocketpy/common/sstream.h"
|
||||
|
||||
typedef struct BaseExceptionFrame {
|
||||
pk_SourceData_ src;
|
||||
SourceData_ src;
|
||||
int lineno;
|
||||
c11_string* name;
|
||||
} BaseExceptionFrame;
|
||||
@ -31,7 +31,7 @@ int py_BaseException__get_lineno(py_Ref self, const CodeObject* code) {
|
||||
return ud->lineno_backup;
|
||||
}
|
||||
|
||||
void py_BaseException__stpush(py_Ref self, pk_SourceData_ src, int lineno, const char* func_name) {
|
||||
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;
|
||||
BaseExceptionFrame* frame = c11_vector__emplace(&ud->stacktrace);
|
||||
@ -111,10 +111,19 @@ py_Type pk_Exception__register() {
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
bool py_checkexc() {
|
||||
pk_VM* vm = pk_current_vm;
|
||||
VM* vm = pk_current_vm;
|
||||
return !py_isnil(&vm->curr_exception);
|
||||
}
|
||||
|
||||
void py_clearexc(py_StackRef p0) {
|
||||
VM* vm = pk_current_vm;
|
||||
vm->last_retval = *py_NIL;
|
||||
vm->curr_exception = *py_NIL;
|
||||
vm->is_stopiteration = false;
|
||||
vm->__curr_class = NULL;
|
||||
if(p0) vm->stack.sp = p0;
|
||||
}
|
||||
|
||||
void py_printexc() {
|
||||
char* msg = py_formatexc();
|
||||
if(!msg) return;
|
||||
@ -124,7 +133,7 @@ void py_printexc() {
|
||||
}
|
||||
|
||||
char* py_formatexc() {
|
||||
pk_VM* vm = pk_current_vm;
|
||||
VM* vm = pk_current_vm;
|
||||
if(py_isnil(&vm->curr_exception)) return NULL;
|
||||
c11_sbuf ss;
|
||||
c11_sbuf__ctor(&ss);
|
||||
@ -135,7 +144,7 @@ char* py_formatexc() {
|
||||
|
||||
for(int i = ud->stacktrace.count - 1; i >= 0; i--) {
|
||||
BaseExceptionFrame* frame = c11__at(BaseExceptionFrame, &ud->stacktrace, i);
|
||||
pk_SourceData__snapshot(frame->src,
|
||||
SourceData__snapshot(frame->src,
|
||||
&ss,
|
||||
frame->lineno,
|
||||
NULL,
|
||||
@ -182,7 +191,7 @@ bool py_exception(const char* name, const char* fmt, ...) {
|
||||
|
||||
bool py_raise(py_Ref exc) {
|
||||
assert(py_isinstance(exc, tp_BaseException));
|
||||
pk_VM* vm = pk_current_vm;
|
||||
VM* vm = pk_current_vm;
|
||||
vm->curr_exception = *exc;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -65,14 +65,14 @@ void py_list__reverse(py_Ref self) {
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
static bool _py_list__len__(int argc, py_Ref argv) {
|
||||
static bool list__len__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
py_i64 res = py_list__len(py_arg(0));
|
||||
py_newint(py_retval(), res);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_list__eq__(int argc, py_Ref argv) {
|
||||
static bool list__eq__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
if(py_istype(py_arg(1), tp_list)) {
|
||||
int length0, length1;
|
||||
@ -87,8 +87,8 @@ static bool _py_list__eq__(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_list__ne__(int argc, py_Ref argv) {
|
||||
if(!_py_list__eq__(argc, argv)) return false;
|
||||
static bool list__ne__(int argc, py_Ref argv) {
|
||||
if(!list__eq__(argc, argv)) return false;
|
||||
if(py_isbool(py_retval())) {
|
||||
bool res = py_tobool(py_retval());
|
||||
py_newbool(py_retval(), !res);
|
||||
@ -96,7 +96,7 @@ static bool _py_list__ne__(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_list__new__(int argc, py_Ref argv) {
|
||||
static bool list__new__(int argc, py_Ref argv) {
|
||||
if(argc == 1) {
|
||||
py_newlist(py_retval());
|
||||
return true;
|
||||
@ -120,7 +120,7 @@ static bool _py_list__new__(int argc, py_Ref argv) {
|
||||
py_newlist(list);
|
||||
while(true) {
|
||||
int res = py_next(iter);
|
||||
if(res == -1){
|
||||
if(res == -1) {
|
||||
py_shrink(2);
|
||||
return false;
|
||||
}
|
||||
@ -134,7 +134,7 @@ static bool _py_list__new__(int argc, py_Ref argv) {
|
||||
return TypeError("list() takes at most 1 argument");
|
||||
}
|
||||
|
||||
static bool _py_list__getitem__(int argc, py_Ref argv) {
|
||||
static bool list__getitem__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
List* self = py_touserdata(py_arg(0));
|
||||
py_Ref _1 = py_arg(1);
|
||||
@ -158,7 +158,7 @@ static bool _py_list__getitem__(int argc, py_Ref argv) {
|
||||
}
|
||||
}
|
||||
|
||||
static bool _py_list__setitem__(int argc, py_Ref argv) {
|
||||
static bool list__setitem__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(3);
|
||||
PY_CHECK_ARG_TYPE(1, tp_int);
|
||||
List* self = py_touserdata(py_arg(0));
|
||||
@ -168,7 +168,7 @@ static bool _py_list__setitem__(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_list__delitem__(int argc, py_Ref argv) {
|
||||
static bool list__delitem__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
PY_CHECK_ARG_TYPE(1, tp_int);
|
||||
List* self = py_touserdata(py_arg(0));
|
||||
@ -179,7 +179,7 @@ static bool _py_list__delitem__(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_list__add__(int argc, py_Ref argv) {
|
||||
static bool list__add__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
py_Ref _0 = py_arg(0);
|
||||
py_Ref _1 = py_arg(1);
|
||||
@ -196,7 +196,7 @@ static bool _py_list__add__(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_list__mul__(int argc, py_Ref argv) {
|
||||
static bool list__mul__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
py_Ref _0 = py_arg(0);
|
||||
py_Ref _1 = py_arg(1);
|
||||
@ -214,16 +214,16 @@ static bool _py_list__mul__(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_list__rmul__(int argc, py_Ref argv) { return _py_list__mul__(argc, argv); }
|
||||
static bool list__rmul__(int argc, py_Ref argv) { return list__mul__(argc, argv); }
|
||||
|
||||
static bool _py_list__append(int argc, py_Ref argv) {
|
||||
static bool list__append(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
py_list__append(py_arg(0), py_arg(1));
|
||||
py_newnone(py_retval());
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_list__repr__(int argc, py_Ref argv) {
|
||||
static bool list__repr__(int argc, py_Ref argv) {
|
||||
List* self = py_touserdata(py_arg(0));
|
||||
c11_sbuf buf;
|
||||
c11_sbuf__ctor(&buf);
|
||||
@ -243,7 +243,7 @@ static bool _py_list__repr__(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_list__extend(int argc, py_Ref argv) {
|
||||
static bool list__extend(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
List* self = py_touserdata(py_arg(0));
|
||||
PY_CHECK_ARG_TYPE(1, tp_list);
|
||||
@ -253,7 +253,7 @@ static bool _py_list__extend(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_list__count(int argc, py_Ref argv) {
|
||||
static bool list__count(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
int count = 0;
|
||||
for(int i = 0; i < py_list__len(py_arg(0)); i++) {
|
||||
@ -265,14 +265,14 @@ static bool _py_list__count(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_list__clear(int argc, py_Ref argv) {
|
||||
static bool list__clear(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
py_list__clear(py_arg(0));
|
||||
py_newnone(py_retval());
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_list__copy(int argc, py_Ref argv) {
|
||||
static bool list__copy(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
py_newlist(py_retval());
|
||||
List* self = py_touserdata(py_arg(0));
|
||||
@ -281,7 +281,7 @@ static bool _py_list__copy(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_list__index(int argc, py_Ref argv) {
|
||||
static bool list__index(int argc, py_Ref argv) {
|
||||
if(argc > 3) return TypeError("index() takes at most 3 arguments");
|
||||
int start = 0;
|
||||
if(argc == 3) {
|
||||
@ -299,7 +299,7 @@ static bool _py_list__index(int argc, py_Ref argv) {
|
||||
return ValueError("list.index(x): x not in list");
|
||||
}
|
||||
|
||||
static bool _py_list__reverse(int argc, py_Ref argv) {
|
||||
static bool list__reverse(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
List* self = py_touserdata(py_arg(0));
|
||||
c11__reverse(py_TValue, self);
|
||||
@ -307,7 +307,7 @@ static bool _py_list__reverse(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_list__remove(int argc, py_Ref argv) {
|
||||
static bool list__remove(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
for(int i = 0; i < py_list__len(py_arg(0)); i++) {
|
||||
int res = py_equal(py_list__getitem(py_arg(0), i), py_arg(1));
|
||||
@ -321,7 +321,7 @@ static bool _py_list__remove(int argc, py_Ref argv) {
|
||||
return ValueError("list.remove(x): x not in list");
|
||||
}
|
||||
|
||||
static bool _py_list__pop(int argc, py_Ref argv) {
|
||||
static bool list__pop(int argc, py_Ref argv) {
|
||||
int index;
|
||||
if(argc == 1) {
|
||||
index = -1;
|
||||
@ -339,7 +339,7 @@ static bool _py_list__pop(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_list__insert(int argc, py_Ref argv) {
|
||||
static bool list__insert(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(3);
|
||||
PY_CHECK_ARG_TYPE(1, tp_int);
|
||||
List* self = py_touserdata(py_arg(0));
|
||||
@ -352,9 +352,9 @@ static bool _py_list__insert(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static int _py_lt_with_key(py_TValue* a, py_TValue* b, py_TValue* key) {
|
||||
static int lt_with_key(py_TValue* a, py_TValue* b, py_TValue* key) {
|
||||
if(!key) return py_less(a, b);
|
||||
pk_VM* vm = pk_current_vm;
|
||||
VM* vm = pk_current_vm;
|
||||
// project a
|
||||
py_push(key);
|
||||
py_pushnil();
|
||||
@ -375,7 +375,7 @@ static int _py_lt_with_key(py_TValue* a, py_TValue* b, py_TValue* key) {
|
||||
}
|
||||
|
||||
// sort(self, key=None, reverse=False)
|
||||
static bool _py_list__sort(int argc, py_Ref argv) {
|
||||
static bool list__sort(int argc, py_Ref argv) {
|
||||
List* self = py_touserdata(py_arg(0));
|
||||
|
||||
py_Ref key = py_arg(1);
|
||||
@ -384,7 +384,7 @@ static bool _py_list__sort(int argc, py_Ref argv) {
|
||||
bool ok = c11__stable_sort(self->data,
|
||||
self->count,
|
||||
sizeof(py_TValue),
|
||||
(int (*)(const void*, const void*, void*))_py_lt_with_key,
|
||||
(int (*)(const void*, const void*, void*))lt_with_key,
|
||||
key);
|
||||
if(!ok) return false;
|
||||
|
||||
@ -395,12 +395,12 @@ static bool _py_list__sort(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_list__iter__(int argc, py_Ref argv) {
|
||||
static bool list__iter__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
return pk_arrayiter(argv);
|
||||
}
|
||||
|
||||
static bool _py_list__contains__(int argc, py_Ref argv) {
|
||||
static bool list__contains__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
return pk_arraycontains(py_arg(0), py_arg(1));
|
||||
}
|
||||
@ -409,33 +409,33 @@ py_Type pk_list__register() {
|
||||
py_Type type =
|
||||
pk_newtype("list", tp_object, NULL, (void (*)(void*))c11_vector__dtor, false, true);
|
||||
|
||||
py_bindmagic(type, __len__, _py_list__len__);
|
||||
py_bindmagic(type, __eq__, _py_list__eq__);
|
||||
py_bindmagic(type, __ne__, _py_list__ne__);
|
||||
py_bindmagic(type, __new__, _py_list__new__);
|
||||
py_bindmagic(type, __getitem__, _py_list__getitem__);
|
||||
py_bindmagic(type, __setitem__, _py_list__setitem__);
|
||||
py_bindmagic(type, __delitem__, _py_list__delitem__);
|
||||
py_bindmagic(type, __add__, _py_list__add__);
|
||||
py_bindmagic(type, __mul__, _py_list__mul__);
|
||||
py_bindmagic(type, __rmul__, _py_list__rmul__);
|
||||
py_bindmagic(type, __repr__, _py_list__repr__);
|
||||
py_bindmagic(type, __iter__, _py_list__iter__);
|
||||
py_bindmagic(type, __contains__, _py_list__contains__);
|
||||
py_bindmagic(type, __len__, list__len__);
|
||||
py_bindmagic(type, __eq__, list__eq__);
|
||||
py_bindmagic(type, __ne__, list__ne__);
|
||||
py_bindmagic(type, __new__, list__new__);
|
||||
py_bindmagic(type, __getitem__, list__getitem__);
|
||||
py_bindmagic(type, __setitem__, list__setitem__);
|
||||
py_bindmagic(type, __delitem__, list__delitem__);
|
||||
py_bindmagic(type, __add__, list__add__);
|
||||
py_bindmagic(type, __mul__, list__mul__);
|
||||
py_bindmagic(type, __rmul__, list__rmul__);
|
||||
py_bindmagic(type, __repr__, list__repr__);
|
||||
py_bindmagic(type, __iter__, list__iter__);
|
||||
py_bindmagic(type, __contains__, list__contains__);
|
||||
|
||||
py_bindmethod(type, "append", _py_list__append);
|
||||
py_bindmethod(type, "extend", _py_list__extend);
|
||||
py_bindmethod(type, "count", _py_list__count);
|
||||
py_bindmethod(type, "clear", _py_list__clear);
|
||||
py_bindmethod(type, "copy", _py_list__copy);
|
||||
py_bindmethod(type, "index", _py_list__index);
|
||||
py_bindmethod(type, "reverse", _py_list__reverse);
|
||||
py_bindmethod(type, "remove", _py_list__remove);
|
||||
py_bindmethod(type, "pop", _py_list__pop);
|
||||
py_bindmethod(type, "insert", _py_list__insert);
|
||||
py_bindmethod(type, "sort", _py_list__sort);
|
||||
py_bindmethod(type, "append", list__append);
|
||||
py_bindmethod(type, "extend", list__extend);
|
||||
py_bindmethod(type, "count", list__count);
|
||||
py_bindmethod(type, "clear", list__clear);
|
||||
py_bindmethod(type, "copy", list__copy);
|
||||
py_bindmethod(type, "index", list__index);
|
||||
py_bindmethod(type, "reverse", list__reverse);
|
||||
py_bindmethod(type, "remove", list__remove);
|
||||
py_bindmethod(type, "pop", list__pop);
|
||||
py_bindmethod(type, "insert", list__insert);
|
||||
py_bindmethod(type, "sort", list__sort);
|
||||
|
||||
py_bind(py_tpobject(type), "sort(self, key=None, reverse=False)", _py_list__sort);
|
||||
py_bind(py_tpobject(type), "sort(self, key=None, reverse=False)", list__sort);
|
||||
|
||||
py_setdict(py_tpobject(type), __hash__, py_None);
|
||||
return type;
|
||||
|
||||
62
src/public/py_method.c
Normal file
62
src/public/py_method.c
Normal file
@ -0,0 +1,62 @@
|
||||
#include "pocketpy/pocketpy.h"
|
||||
|
||||
#include "pocketpy/common/utils.h"
|
||||
#include "pocketpy/objects/object.h"
|
||||
#include "pocketpy/interpreter/vm.h"
|
||||
|
||||
/* staticmethod */
|
||||
|
||||
static bool staticmethod__new__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
py_newobject(py_retval(), tp_staticmethod, 1, 0);
|
||||
py_setslot(py_retval(), 0, py_arg(1));
|
||||
return true;
|
||||
}
|
||||
|
||||
py_Type pk_staticmethod__register(){
|
||||
py_Type type = pk_newtype("staticmethod", tp_object, NULL, NULL, false, true);
|
||||
|
||||
py_bindmagic(type, __new__, staticmethod__new__);
|
||||
return type;
|
||||
}
|
||||
|
||||
/* classmethod */
|
||||
static bool classmethod__new__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
py_newobject(py_retval(), tp_classmethod, 1, 0);
|
||||
py_setslot(py_retval(), 0, py_arg(1));
|
||||
return true;
|
||||
}
|
||||
|
||||
py_Type pk_classmethod__register(){
|
||||
py_Type type = pk_newtype("classmethod", tp_object, NULL, NULL, false, true);
|
||||
|
||||
py_bindmagic(type, __new__, classmethod__new__);
|
||||
return type;
|
||||
}
|
||||
|
||||
/* boundmethod */
|
||||
static bool boundmethod__new__(int argc, py_Ref argv) {
|
||||
return NotImplementedError();
|
||||
}
|
||||
|
||||
static bool boundmethod__self__getter(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
py_assign(py_retval(), py_getslot(argv, 0));
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool boundmethod__func__getter(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
py_assign(py_retval(), py_getslot(argv, 1));
|
||||
return true;
|
||||
}
|
||||
|
||||
py_Type pk_boundmethod__register(){
|
||||
py_Type type = pk_newtype("boundmethod", tp_object, NULL, NULL, false, true);
|
||||
|
||||
py_bindmagic(type, __new__, boundmethod__new__);
|
||||
py_bindproperty(type, "__self__", boundmethod__self__getter, NULL);
|
||||
py_bindproperty(type, "__func__", boundmethod__func__getter, NULL);
|
||||
return type;
|
||||
}
|
||||
@ -2,10 +2,10 @@
|
||||
#include "pocketpy/common/sstream.h"
|
||||
#include "pocketpy/pocketpy.h"
|
||||
|
||||
static bool _py_object__new__(int argc, py_Ref argv) {
|
||||
static bool object__new__(int argc, py_Ref argv) {
|
||||
if(argc == 0) return TypeError("object.__new__(): not enough arguments");
|
||||
py_Type cls = py_totype(py_arg(0));
|
||||
pk_TypeInfo* ti = c11__at(pk_TypeInfo, &pk_current_vm->types, cls);
|
||||
py_TypeInfo* ti = c11__at(py_TypeInfo, &pk_current_vm->types, cls);
|
||||
if(!ti->is_python) {
|
||||
return TypeError("object.__new__(%t) is not safe, use %t.__new__()", cls, cls);
|
||||
}
|
||||
@ -13,28 +13,28 @@ static bool _py_object__new__(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_object__hash__(int argc, py_Ref argv) {
|
||||
static bool object__hash__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
assert(argv->is_ptr);
|
||||
py_newint(py_retval(), (py_i64)argv->_obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_object__eq__(int argc, py_Ref argv) {
|
||||
static bool object__eq__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
bool res = py_isidentical(py_arg(0), py_arg(1));
|
||||
py_newbool(py_retval(), res);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_object__ne__(int argc, py_Ref argv) {
|
||||
static bool object__ne__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
bool res = py_isidentical(py_arg(0), py_arg(1));
|
||||
py_newbool(py_retval(), !res);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_object__repr__(int argc, py_Ref argv) {
|
||||
static bool object__repr__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
assert(argv->is_ptr);
|
||||
c11_sbuf buf;
|
||||
@ -44,7 +44,7 @@ static bool _py_object__repr__(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_type__repr__(int argc, py_Ref argv) {
|
||||
static bool type__repr__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
c11_sbuf buf;
|
||||
c11_sbuf__ctor(&buf);
|
||||
@ -53,23 +53,41 @@ static bool _py_type__repr__(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_type__new__(int argc, py_Ref argv){
|
||||
static bool type__new__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
py_Type type = py_typeof(py_arg(1));
|
||||
py_assign(py_retval(), py_tpobject(type));
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool type__base__getter(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
py_Type type = py_totype(argv);
|
||||
py_TypeInfo* ti = c11__at(py_TypeInfo, &pk_current_vm->types, type);
|
||||
py_assign(py_retval(), py_tpobject(ti->base));
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool type__name__getter(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
py_Type type = py_totype(argv);
|
||||
py_TypeInfo* ti = c11__at(py_TypeInfo, &pk_current_vm->types, type);
|
||||
py_newstr(py_retval(), py_name2str(ti->name));
|
||||
return true;
|
||||
}
|
||||
|
||||
void pk_object__register() {
|
||||
// use staticmethod
|
||||
py_bindmagic(tp_object, __new__, _py_object__new__);
|
||||
// TODO: use staticmethod
|
||||
py_bindmagic(tp_object, __new__, object__new__);
|
||||
|
||||
py_bindmagic(tp_object, __hash__, _py_object__hash__);
|
||||
py_bindmagic(tp_object, __eq__, _py_object__eq__);
|
||||
py_bindmagic(tp_object, __ne__, _py_object__ne__);
|
||||
py_bindmagic(tp_object, __repr__, _py_object__repr__);
|
||||
py_bindmagic(tp_object, __hash__, object__hash__);
|
||||
py_bindmagic(tp_object, __eq__, object__eq__);
|
||||
py_bindmagic(tp_object, __ne__, object__ne__);
|
||||
py_bindmagic(tp_object, __repr__, object__repr__);
|
||||
|
||||
// type patch...
|
||||
py_bindmagic(tp_type, __repr__, _py_type__repr__);
|
||||
py_bindmagic(tp_type, __new__, _py_type__new__);
|
||||
py_bindmagic(tp_type, __repr__, type__repr__);
|
||||
py_bindmagic(tp_type, __new__, type__new__);
|
||||
|
||||
py_bindproperty(tp_type, "__base__", type__base__getter, NULL);
|
||||
py_bindproperty(tp_type, "__name__", type__name__getter, NULL);
|
||||
}
|
||||
@ -45,7 +45,7 @@ int py_bool(py_Ref val) {
|
||||
|
||||
bool py_hash(py_Ref val, int64_t* out) {
|
||||
py_Type t = val->type;
|
||||
pk_TypeInfo* types = (pk_TypeInfo*)pk_current_vm->types.data;
|
||||
py_TypeInfo* types = (py_TypeInfo*)pk_current_vm->types.data;
|
||||
do {
|
||||
py_Ref _hash = &types[t].magic[__hash__];
|
||||
if(py_isnone(_hash)) break;
|
||||
@ -68,11 +68,16 @@ bool py_iter(py_Ref val) {
|
||||
}
|
||||
|
||||
int py_next(py_Ref val) {
|
||||
pk_VM* vm = pk_current_vm;
|
||||
VM* vm = pk_current_vm;
|
||||
vm->is_stopiteration = false;
|
||||
py_Ref tmp = py_tpfindmagic(val->type, __next__);
|
||||
if(!tmp) return TypeError("'%t' object is not an iterator", val->type);
|
||||
py_StackRef p0 = py_peek(0);
|
||||
if(py_call(tmp, 1, val)) return true;
|
||||
if(vm->curr_exception.type == tp_StopIteration) {
|
||||
py_clearexc(p0);
|
||||
vm->is_stopiteration = true;
|
||||
}
|
||||
return vm->is_stopiteration ? 0 : -1;
|
||||
}
|
||||
|
||||
@ -108,8 +113,9 @@ bool py_getattr(py_Ref self, py_Name name) {
|
||||
if(py_istype(res, tp_staticmethod)) {
|
||||
res = py_getslot(res, 0);
|
||||
} else if(py_istype(res, tp_classmethod)) {
|
||||
// TODO: make a closure
|
||||
assert(false);
|
||||
res = py_getslot(res, 0);
|
||||
py_newboundmethod(py_retval(), self, res);
|
||||
return true;
|
||||
}
|
||||
py_assign(py_retval(), res);
|
||||
return true;
|
||||
@ -120,10 +126,22 @@ bool py_getattr(py_Ref self, py_Name name) {
|
||||
if(cls_var) {
|
||||
// bound method is non-data descriptor
|
||||
switch(cls_var->type) {
|
||||
case tp_function: assert(false);
|
||||
case tp_nativefunc: assert(false);
|
||||
case tp_staticmethod: assert(false);
|
||||
case tp_classmethod: assert(false);
|
||||
case tp_function: {
|
||||
py_newboundmethod(py_retval(), self, cls_var);
|
||||
return true;
|
||||
}
|
||||
case tp_nativefunc: {
|
||||
py_newboundmethod(py_retval(), self, cls_var);
|
||||
return true;
|
||||
}
|
||||
case tp_staticmethod: {
|
||||
py_assign(py_retval(), py_getslot(cls_var, 0));
|
||||
return true;
|
||||
}
|
||||
case tp_classmethod: {
|
||||
py_newboundmethod(py_retval(), py_tpobject(type), py_getslot(cls_var, 0));
|
||||
return true;
|
||||
}
|
||||
default: {
|
||||
py_assign(py_retval(), cls_var);
|
||||
return true;
|
||||
@ -131,6 +149,21 @@ bool py_getattr(py_Ref self, py_Name name) {
|
||||
}
|
||||
}
|
||||
|
||||
if(self->type == tp_module) {
|
||||
py_Ref path = py_getdict(self, __path__);
|
||||
c11_sbuf buf;
|
||||
c11_sbuf__ctor(&buf);
|
||||
pk_sprintf(&buf, "%v.%n", py_tosv(path), name);
|
||||
c11_string* new_path = c11_sbuf__submit(&buf);
|
||||
int res = py_import(new_path->data);
|
||||
c11_string__delete(new_path);
|
||||
if(res == -1) {
|
||||
return false;
|
||||
} else if(res == 1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return AttributeError(self, name);
|
||||
}
|
||||
|
||||
@ -200,12 +233,12 @@ bool py_delitem(py_Ref self, py_Ref key) {
|
||||
return ok;
|
||||
}
|
||||
|
||||
int py_equal(py_Ref lhs, py_Ref rhs){
|
||||
int py_equal(py_Ref lhs, py_Ref rhs) {
|
||||
if(!py_eq(lhs, rhs)) return -1;
|
||||
return py_bool(py_retval());
|
||||
}
|
||||
|
||||
int py_less(py_Ref lhs, py_Ref rhs){
|
||||
int py_less(py_Ref lhs, py_Ref rhs) {
|
||||
if(!py_lt(lhs, rhs)) return -1;
|
||||
return py_bool(py_retval());
|
||||
}
|
||||
26
src/public/py_property.c
Normal file
26
src/public/py_property.c
Normal file
@ -0,0 +1,26 @@
|
||||
#include "pocketpy/pocketpy.h"
|
||||
|
||||
#include "pocketpy/common/utils.h"
|
||||
#include "pocketpy/objects/object.h"
|
||||
#include "pocketpy/interpreter/vm.h"
|
||||
|
||||
static bool property__new__(int argc, py_Ref argv) {
|
||||
py_newobject(py_retval(), tp_property, 2, 0);
|
||||
if(argc == 1 + 1) {
|
||||
py_setslot(py_retval(), 0, py_arg(1));
|
||||
py_setslot(py_retval(), 1, py_None);
|
||||
} else if(argc == 1 + 2) {
|
||||
py_setslot(py_retval(), 0, py_arg(1));
|
||||
py_setslot(py_retval(), 1, py_arg(2));
|
||||
} else {
|
||||
return TypeError("property() expected 1 or 2 arguments, got %d", argc);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
py_Type pk_property__register() {
|
||||
py_Type type = pk_newtype("property", tp_object, NULL, NULL, false, true);
|
||||
|
||||
py_bindmagic(type, __new__, property__new__);
|
||||
return type;
|
||||
}
|
||||
@ -10,7 +10,7 @@ typedef struct Range {
|
||||
py_i64 step;
|
||||
} Range;
|
||||
|
||||
static bool _py_range__new__(int argc, py_Ref argv) {
|
||||
static bool range__new__(int argc, py_Ref argv) {
|
||||
Range* ud = py_newobject(py_retval(), tp_range, 0, sizeof(Range));
|
||||
switch(argc - 1) { // skip cls
|
||||
case 1: {
|
||||
@ -41,7 +41,7 @@ static bool _py_range__new__(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_range__iter__(int argc, py_Ref argv) {
|
||||
static bool range__iter__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
return py_tpcall(tp_range_iterator, 1, argv);
|
||||
}
|
||||
@ -49,8 +49,8 @@ static bool _py_range__iter__(int argc, py_Ref argv) {
|
||||
py_Type pk_range__register() {
|
||||
py_Type type = pk_newtype("range", tp_object, NULL, NULL, false, true);
|
||||
|
||||
py_bindmagic(type, __new__, _py_range__new__);
|
||||
py_bindmagic(type, __iter__, _py_range__iter__);
|
||||
py_bindmagic(type, __new__, range__new__);
|
||||
py_bindmagic(type, __iter__, range__iter__);
|
||||
return type;
|
||||
}
|
||||
|
||||
@ -59,7 +59,7 @@ typedef struct RangeIterator {
|
||||
py_i64 current;
|
||||
} RangeIterator;
|
||||
|
||||
static bool _py_range_iterator__new__(int argc, py_Ref argv) {
|
||||
static bool range_iterator__new__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
PY_CHECK_ARG_TYPE(1, tp_range);
|
||||
RangeIterator* ud = py_newobject(py_retval(), tp_range_iterator, 0, sizeof(RangeIterator));
|
||||
@ -68,13 +68,13 @@ static bool _py_range_iterator__new__(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_range_iterator__iter__(int argc, py_Ref argv) {
|
||||
static bool range_iterator__iter__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
*py_retval() = *py_arg(0);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_range_iterator__next__(int argc, py_Ref argv) {
|
||||
static bool range_iterator__next__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
RangeIterator* ud = py_touserdata(py_arg(0));
|
||||
if(ud->range.step > 0) {
|
||||
@ -90,8 +90,8 @@ static bool _py_range_iterator__next__(int argc, py_Ref argv) {
|
||||
py_Type pk_range_iterator__register() {
|
||||
py_Type type = pk_newtype("range_iterator", tp_object, NULL, NULL, false, true);
|
||||
|
||||
py_bindmagic(type, __new__, _py_range_iterator__new__);
|
||||
py_bindmagic(type, __iter__, _py_range_iterator__iter__);
|
||||
py_bindmagic(type, __next__, _py_range_iterator__next__);
|
||||
py_bindmagic(type, __new__, range_iterator__new__);
|
||||
py_bindmagic(type, __iter__, range_iterator__iter__);
|
||||
py_bindmagic(type, __next__, range_iterator__next__);
|
||||
return type;
|
||||
}
|
||||
@ -6,14 +6,14 @@
|
||||
#include "pocketpy/interpreter/vm.h"
|
||||
|
||||
void py_newslice(py_Ref out) {
|
||||
pk_VM* vm = pk_current_vm;
|
||||
PyObject* obj = pk_ManagedHeap__gcnew(&vm->heap, tp_slice, 3, 0);
|
||||
VM* vm = pk_current_vm;
|
||||
PyObject* obj = ManagedHeap__gcnew(&vm->heap, tp_slice, 3, 0);
|
||||
out->type = tp_slice;
|
||||
out->is_ptr = true;
|
||||
out->_obj = obj;
|
||||
}
|
||||
|
||||
static bool _py_slice__new__(int argc, py_Ref argv) {
|
||||
static bool slice__new__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1 + 3);
|
||||
py_Ref slice = py_retval();
|
||||
py_newslice(slice);
|
||||
@ -23,7 +23,7 @@ static bool _py_slice__new__(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_slice__repr__(int argc, py_Ref argv) {
|
||||
static bool slice__repr__(int argc, py_Ref argv) {
|
||||
c11_sbuf buf;
|
||||
c11_sbuf__ctor(&buf);
|
||||
c11_sbuf__write_cstr(&buf, "slice(");
|
||||
@ -45,7 +45,7 @@ static bool _py_slice__repr__(int argc, py_Ref argv) {
|
||||
py_Type pk_slice__register() {
|
||||
py_Type type = pk_newtype("slice", tp_object, NULL, NULL, false, true);
|
||||
|
||||
py_bindmagic(type, __new__, _py_slice__new__);
|
||||
py_bindmagic(type, __repr__, _py_slice__repr__);
|
||||
py_bindmagic(type, __new__, slice__new__);
|
||||
py_bindmagic(type, __repr__, slice__repr__);
|
||||
return type;
|
||||
}
|
||||
@ -9,9 +9,9 @@
|
||||
void py_newstr(py_Ref out, const char* data) { py_newstrn(out, data, strlen(data)); }
|
||||
|
||||
void py_newstrn(py_Ref out, const char* data, int size) {
|
||||
pk_ManagedHeap* heap = &pk_current_vm->heap;
|
||||
ManagedHeap* heap = &pk_current_vm->heap;
|
||||
int total_size = sizeof(c11_string) + size + 1;
|
||||
PyObject* obj = pk_ManagedHeap__gcnew(heap, tp_str, 0, total_size);
|
||||
PyObject* obj = ManagedHeap__gcnew(heap, tp_str, 0, total_size);
|
||||
c11_string* ud = PyObject__userdata(obj);
|
||||
c11_string__ctor2(ud, data, size);
|
||||
out->type = tp_str;
|
||||
@ -20,9 +20,9 @@ void py_newstrn(py_Ref out, const char* data, int size) {
|
||||
}
|
||||
|
||||
unsigned char* py_newbytes(py_Ref out, int size) {
|
||||
pk_ManagedHeap* heap = &pk_current_vm->heap;
|
||||
ManagedHeap* heap = &pk_current_vm->heap;
|
||||
// 4 bytes size + data
|
||||
PyObject* obj = pk_ManagedHeap__gcnew(heap, tp_bytes, 0, sizeof(c11_bytes) + size);
|
||||
PyObject* obj = ManagedHeap__gcnew(heap, tp_bytes, 0, sizeof(c11_bytes) + size);
|
||||
c11_bytes* ud = PyObject__userdata(obj);
|
||||
ud->size = size;
|
||||
out->type = tp_bytes;
|
||||
@ -58,7 +58,7 @@ unsigned char* py_tobytes(py_Ref self, int* size) {
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
static bool _py_str__new__(int argc, py_Ref argv) {
|
||||
static bool str__new__(int argc, py_Ref argv) {
|
||||
assert(argc >= 1);
|
||||
if(argc == 1) {
|
||||
py_newstr(py_retval(), "");
|
||||
@ -68,7 +68,7 @@ static bool _py_str__new__(int argc, py_Ref argv) {
|
||||
return py_str(py_arg(1));
|
||||
}
|
||||
|
||||
static bool _py_str__hash__(int argc, py_Ref argv) {
|
||||
static bool str__hash__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
int size;
|
||||
const char* data = py_tostrn(&argv[0], &size);
|
||||
@ -80,14 +80,14 @@ static bool _py_str__hash__(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_str__len__(int argc, py_Ref argv) {
|
||||
static bool str__len__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
c11_string* self = py_touserdata(&argv[0]);
|
||||
py_newint(py_retval(), c11_sv__u8_length((c11_sv){self->data, self->size}));
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_str__add__(int argc, py_Ref argv) {
|
||||
static bool str__add__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
c11_string* self = py_touserdata(&argv[0]);
|
||||
if(py_arg(1)->type != tp_str) {
|
||||
@ -105,7 +105,7 @@ static bool _py_str__add__(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_str__mul__(int argc, py_Ref argv) {
|
||||
static bool str__mul__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
c11_string* self = py_touserdata(&argv[0]);
|
||||
if(py_arg(1)->type != tp_int) {
|
||||
@ -128,9 +128,9 @@ static bool _py_str__mul__(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_str__rmul__(int argc, py_Ref argv) { return _py_str__mul__(argc, argv); }
|
||||
static bool str__rmul__(int argc, py_Ref argv) { return str__mul__(argc, argv); }
|
||||
|
||||
static bool _py_str__contains__(int argc, py_Ref argv) {
|
||||
static bool str__contains__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
c11_string* self = py_touserdata(&argv[0]);
|
||||
if(py_arg(1)->type != tp_str) {
|
||||
@ -143,13 +143,13 @@ static bool _py_str__contains__(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_str__str__(int argc, py_Ref argv) {
|
||||
static bool str__str__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
*py_retval() = argv[0];
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_str__repr__(int argc, py_Ref argv) {
|
||||
static bool str__repr__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
c11_sbuf buf;
|
||||
c11_sbuf__ctor(&buf);
|
||||
@ -158,7 +158,7 @@ static bool _py_str__repr__(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_str__iter__(int argc, py_Ref argv) {
|
||||
static bool str__iter__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
int* ud = py_newobject(py_retval(), tp_str_iterator, 1, sizeof(int));
|
||||
*ud = 0;
|
||||
@ -166,7 +166,7 @@ static bool _py_str__iter__(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_str__getitem__(int argc, py_Ref argv) {
|
||||
static bool str__getitem__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
c11_sv self = c11_string__sv(py_touserdata(&argv[0]));
|
||||
py_Ref _1 = py_arg(1);
|
||||
@ -190,7 +190,7 @@ static bool _py_str__getitem__(int argc, py_Ref argv) {
|
||||
}
|
||||
|
||||
#define DEF_STR_CMP_OP(op, __f, __cond) \
|
||||
static bool _py_str##op(int argc, py_Ref argv) { \
|
||||
static bool str##op(int argc, py_Ref argv) { \
|
||||
PY_CHECK_ARGC(2); \
|
||||
c11_string* self = py_touserdata(&argv[0]); \
|
||||
if(py_arg(1)->type != tp_str) { \
|
||||
@ -212,7 +212,7 @@ DEF_STR_CMP_OP(__ge__, c11_sv__cmp, res >= 0)
|
||||
|
||||
#undef DEF_STR_CMP_OP
|
||||
|
||||
static bool _py_str__lower(int argc, py_Ref argv) {
|
||||
static bool str__lower(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
c11_string* self = py_touserdata(&argv[0]);
|
||||
int total_size = sizeof(c11_string) + self->size + 1;
|
||||
@ -227,7 +227,7 @@ static bool _py_str__lower(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_str__upper(int argc, py_Ref argv) {
|
||||
static bool str__upper(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
c11_string* self = py_touserdata(&argv[0]);
|
||||
int total_size = sizeof(c11_string) + self->size + 1;
|
||||
@ -242,29 +242,25 @@ static bool _py_str__upper(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_str__startswith(int argc, py_Ref argv) {
|
||||
static bool str__startswith(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
c11_string* self = py_touserdata(&argv[0]);
|
||||
PY_CHECK_ARG_TYPE(1, tp_str);
|
||||
c11_string* other = py_touserdata(&argv[1]);
|
||||
c11_sv _0 = c11_sv__slice2(c11_string__sv(self), 0, other->size);
|
||||
c11_sv _1 = c11_string__sv(other);
|
||||
py_newbool(py_retval(), c11__sveq(_0, _1));
|
||||
py_newbool(py_retval(), c11_sv__startswith(c11_string__sv(self), c11_string__sv(other)));
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_str__endswith(int argc, py_Ref argv) {
|
||||
static bool str__endswith(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
c11_string* self = py_touserdata(&argv[0]);
|
||||
PY_CHECK_ARG_TYPE(1, tp_str);
|
||||
c11_string* other = py_touserdata(&argv[1]);
|
||||
c11_sv _0 = c11_sv__slice2(c11_string__sv(self), self->size - other->size, self->size);
|
||||
c11_sv _1 = c11_string__sv(other);
|
||||
py_newbool(py_retval(), c11__sveq(_0, _1));
|
||||
py_newbool(py_retval(), c11_sv__endswith(c11_string__sv(self), c11_string__sv(other)));
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_str__join(int argc, py_Ref argv) {
|
||||
static bool str__join(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
c11_sv self = c11_string__sv(py_touserdata(&argv[0]));
|
||||
py_Ref _1 = py_arg(1);
|
||||
@ -296,7 +292,7 @@ static bool _py_str__join(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_str__replace(int argc, py_Ref argv) {
|
||||
static bool str__replace(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(3);
|
||||
c11_string* self = py_touserdata(&argv[0]);
|
||||
PY_CHECK_ARG_TYPE(1, tp_str);
|
||||
@ -310,7 +306,7 @@ static bool _py_str__replace(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_str__split(int argc, py_Ref argv) {
|
||||
static bool str__split(int argc, py_Ref argv) {
|
||||
c11_sv self = c11_string__sv(py_touserdata(&argv[0]));
|
||||
c11_vector res;
|
||||
if(argc > 2) return TypeError("split() takes at most 2 arguments");
|
||||
@ -333,7 +329,7 @@ static bool _py_str__split(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_str__count(int argc, py_Ref argv) {
|
||||
static bool str__count(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
c11_string* self = py_touserdata(&argv[0]);
|
||||
PY_CHECK_ARG_TYPE(1, tp_str);
|
||||
@ -343,7 +339,7 @@ static bool _py_str__count(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_str__strip_impl(bool left, bool right, int argc, py_Ref argv) {
|
||||
static bool str__strip_impl(bool left, bool right, int argc, py_Ref argv) {
|
||||
c11_sv self = c11_string__sv(py_touserdata(&argv[0]));
|
||||
c11_sv chars;
|
||||
if(argc == 1) {
|
||||
@ -359,19 +355,19 @@ static bool _py_str__strip_impl(bool left, bool right, int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_str__strip(int argc, py_Ref argv) {
|
||||
return _py_str__strip_impl(true, true, argc, argv);
|
||||
static bool str__strip(int argc, py_Ref argv) {
|
||||
return str__strip_impl(true, true, argc, argv);
|
||||
}
|
||||
|
||||
static bool _py_str__lstrip(int argc, py_Ref argv) {
|
||||
return _py_str__strip_impl(true, false, argc, argv);
|
||||
static bool str__lstrip(int argc, py_Ref argv) {
|
||||
return str__strip_impl(true, false, argc, argv);
|
||||
}
|
||||
|
||||
static bool _py_str__rstrip(int argc, py_Ref argv) {
|
||||
return _py_str__strip_impl(false, true, argc, argv);
|
||||
static bool str__rstrip(int argc, py_Ref argv) {
|
||||
return str__strip_impl(false, true, argc, argv);
|
||||
}
|
||||
|
||||
static bool _py_str__zfill(int argc, py_Ref argv) {
|
||||
static bool str__zfill(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
c11_sv self = c11_string__sv(py_touserdata(&argv[0]));
|
||||
PY_CHECK_ARG_TYPE(1, tp_int);
|
||||
@ -391,7 +387,7 @@ static bool _py_str__zfill(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_str__widthjust_impl(bool left, int argc, py_Ref argv) {
|
||||
static bool str__widthjust_impl(bool left, int argc, py_Ref argv) {
|
||||
if(argc > 1 + 2) return TypeError("expected at most 2 arguments");
|
||||
char pad;
|
||||
if(argc == 1 + 1) {
|
||||
@ -427,15 +423,15 @@ static bool _py_str__widthjust_impl(bool left, int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_str__ljust(int argc, py_Ref argv) {
|
||||
return _py_str__widthjust_impl(true, argc, argv);
|
||||
static bool str__ljust(int argc, py_Ref argv) {
|
||||
return str__widthjust_impl(true, argc, argv);
|
||||
}
|
||||
|
||||
static bool _py_str__rjust(int argc, py_Ref argv) {
|
||||
return _py_str__widthjust_impl(false, argc, argv);
|
||||
static bool str__rjust(int argc, py_Ref argv) {
|
||||
return str__widthjust_impl(false, argc, argv);
|
||||
}
|
||||
|
||||
static bool _py_str__find(int argc, py_Ref argv) {
|
||||
static bool str__find(int argc, py_Ref argv) {
|
||||
if(argc > 3) return TypeError("find() takes at most 3 arguments");
|
||||
int start = 0;
|
||||
if(argc == 3) {
|
||||
@ -450,8 +446,8 @@ static bool _py_str__find(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_str__index(int argc, py_Ref argv) {
|
||||
bool ok = _py_str__find(argc, argv);
|
||||
static bool str__index(int argc, py_Ref argv) {
|
||||
bool ok = str__find(argc, argv);
|
||||
if(!ok) return false;
|
||||
if(py_toint(py_retval()) == -1) return ValueError("substring not found");
|
||||
return true;
|
||||
@ -461,51 +457,51 @@ py_Type pk_str__register() {
|
||||
py_Type type = pk_newtype("str", tp_object, NULL, NULL, false, true);
|
||||
// no need to dtor because the memory is controlled by the object
|
||||
|
||||
py_bindmagic(tp_str, __new__, _py_str__new__);
|
||||
py_bindmagic(tp_str, __hash__, _py_str__hash__);
|
||||
py_bindmagic(tp_str, __len__, _py_str__len__);
|
||||
py_bindmagic(tp_str, __add__, _py_str__add__);
|
||||
py_bindmagic(tp_str, __mul__, _py_str__mul__);
|
||||
py_bindmagic(tp_str, __rmul__, _py_str__rmul__);
|
||||
py_bindmagic(tp_str, __contains__, _py_str__contains__);
|
||||
py_bindmagic(tp_str, __str__, _py_str__str__);
|
||||
py_bindmagic(tp_str, __repr__, _py_str__repr__);
|
||||
py_bindmagic(tp_str, __iter__, _py_str__iter__);
|
||||
py_bindmagic(tp_str, __getitem__, _py_str__getitem__);
|
||||
py_bindmagic(tp_str, __new__, str__new__);
|
||||
py_bindmagic(tp_str, __hash__, str__hash__);
|
||||
py_bindmagic(tp_str, __len__, str__len__);
|
||||
py_bindmagic(tp_str, __add__, str__add__);
|
||||
py_bindmagic(tp_str, __mul__, str__mul__);
|
||||
py_bindmagic(tp_str, __rmul__, str__rmul__);
|
||||
py_bindmagic(tp_str, __contains__, str__contains__);
|
||||
py_bindmagic(tp_str, __str__, str__str__);
|
||||
py_bindmagic(tp_str, __repr__, str__repr__);
|
||||
py_bindmagic(tp_str, __iter__, str__iter__);
|
||||
py_bindmagic(tp_str, __getitem__, str__getitem__);
|
||||
|
||||
py_bindmagic(tp_str, __eq__, _py_str__eq__);
|
||||
py_bindmagic(tp_str, __ne__, _py_str__ne__);
|
||||
py_bindmagic(tp_str, __lt__, _py_str__lt__);
|
||||
py_bindmagic(tp_str, __le__, _py_str__le__);
|
||||
py_bindmagic(tp_str, __gt__, _py_str__gt__);
|
||||
py_bindmagic(tp_str, __ge__, _py_str__ge__);
|
||||
py_bindmagic(tp_str, __eq__, str__eq__);
|
||||
py_bindmagic(tp_str, __ne__, str__ne__);
|
||||
py_bindmagic(tp_str, __lt__, str__lt__);
|
||||
py_bindmagic(tp_str, __le__, str__le__);
|
||||
py_bindmagic(tp_str, __gt__, str__gt__);
|
||||
py_bindmagic(tp_str, __ge__, str__ge__);
|
||||
|
||||
py_bindmethod(tp_str, "lower", _py_str__lower);
|
||||
py_bindmethod(tp_str, "upper", _py_str__upper);
|
||||
py_bindmethod(tp_str, "startswith", _py_str__startswith);
|
||||
py_bindmethod(tp_str, "endswith", _py_str__endswith);
|
||||
py_bindmethod(tp_str, "join", _py_str__join);
|
||||
py_bindmethod(tp_str, "replace", _py_str__replace);
|
||||
py_bindmethod(tp_str, "split", _py_str__split);
|
||||
py_bindmethod(tp_str, "count", _py_str__count);
|
||||
py_bindmethod(tp_str, "strip", _py_str__strip);
|
||||
py_bindmethod(tp_str, "lstrip", _py_str__lstrip);
|
||||
py_bindmethod(tp_str, "rstrip", _py_str__rstrip);
|
||||
py_bindmethod(tp_str, "zfill", _py_str__zfill);
|
||||
py_bindmethod(tp_str, "ljust", _py_str__ljust);
|
||||
py_bindmethod(tp_str, "rjust", _py_str__rjust);
|
||||
py_bindmethod(tp_str, "find", _py_str__find);
|
||||
py_bindmethod(tp_str, "index", _py_str__index);
|
||||
py_bindmethod(tp_str, "lower", str__lower);
|
||||
py_bindmethod(tp_str, "upper", str__upper);
|
||||
py_bindmethod(tp_str, "startswith", str__startswith);
|
||||
py_bindmethod(tp_str, "endswith", str__endswith);
|
||||
py_bindmethod(tp_str, "join", str__join);
|
||||
py_bindmethod(tp_str, "replace", str__replace);
|
||||
py_bindmethod(tp_str, "split", str__split);
|
||||
py_bindmethod(tp_str, "count", str__count);
|
||||
py_bindmethod(tp_str, "strip", str__strip);
|
||||
py_bindmethod(tp_str, "lstrip", str__lstrip);
|
||||
py_bindmethod(tp_str, "rstrip", str__rstrip);
|
||||
py_bindmethod(tp_str, "zfill", str__zfill);
|
||||
py_bindmethod(tp_str, "ljust", str__ljust);
|
||||
py_bindmethod(tp_str, "rjust", str__rjust);
|
||||
py_bindmethod(tp_str, "find", str__find);
|
||||
py_bindmethod(tp_str, "index", str__index);
|
||||
return type;
|
||||
}
|
||||
|
||||
static bool _py_str_iterator__iter__(int argc, py_Ref argv) {
|
||||
static bool str_iterator__iter__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
*py_retval() = argv[0];
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_str_iterator__next__(int argc, py_Ref argv) {
|
||||
static bool str_iterator__next__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
int* ud = py_touserdata(&argv[0]);
|
||||
int size;
|
||||
@ -521,8 +517,8 @@ static bool _py_str_iterator__next__(int argc, py_Ref argv) {
|
||||
py_Type pk_str_iterator__register() {
|
||||
py_Type type = pk_newtype("str_iterator", tp_object, NULL, NULL, false, true);
|
||||
|
||||
py_bindmagic(type, __iter__, _py_str_iterator__iter__);
|
||||
py_bindmagic(type, __next__, _py_str_iterator__next__);
|
||||
py_bindmagic(type, __iter__, str_iterator__iter__);
|
||||
py_bindmagic(type, __next__, str_iterator__next__);
|
||||
return type;
|
||||
}
|
||||
|
||||
@ -538,10 +534,6 @@ bool py_str(py_Ref val) {
|
||||
return py_call(tmp, 1, val);
|
||||
}
|
||||
|
||||
bool py_repr(py_Ref val) {
|
||||
return pk_callmagic(__repr__, 1, val);
|
||||
}
|
||||
bool py_repr(py_Ref val) { return pk_callmagic(__repr__, 1, val); }
|
||||
|
||||
bool py_len(py_Ref val){
|
||||
return pk_callmagic(__len__, 1, val);
|
||||
}
|
||||
bool py_len(py_Ref val) { return pk_callmagic(__len__, 1, val); }
|
||||
@ -6,8 +6,8 @@
|
||||
#include "pocketpy/interpreter/vm.h"
|
||||
|
||||
void py_newtuple(py_Ref out, int n) {
|
||||
pk_VM* vm = pk_current_vm;
|
||||
PyObject* obj = pk_ManagedHeap__gcnew(&vm->heap, tp_tuple, n, 0);
|
||||
VM* vm = pk_current_vm;
|
||||
PyObject* obj = ManagedHeap__gcnew(&vm->heap, tp_tuple, n, 0);
|
||||
out->type = tp_tuple;
|
||||
out->is_ptr = true;
|
||||
out->_obj = obj;
|
||||
@ -22,12 +22,12 @@ void py_tuple__setitem(py_Ref self, int i, py_Ref val) { py_setslot(self, i, val
|
||||
int py_tuple__len(py_Ref self) { return self->_obj->slots; }
|
||||
|
||||
//////////////
|
||||
static bool _py_tuple__len__(int argc, py_Ref argv) {
|
||||
static bool tuple__len__(int argc, py_Ref argv) {
|
||||
py_newint(py_retval(), py_tuple__len(argv));
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_tuple__repr__(int argc, py_Ref argv) {
|
||||
static bool tuple__repr__(int argc, py_Ref argv) {
|
||||
c11_sbuf buf;
|
||||
c11_sbuf__ctor(&buf);
|
||||
c11_sbuf__write_char(&buf, '(');
|
||||
@ -48,7 +48,7 @@ static bool _py_tuple__repr__(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_tuple__new__(int argc, py_Ref argv) {
|
||||
static bool tuple__new__(int argc, py_Ref argv) {
|
||||
if(argc == 1 + 0) {
|
||||
py_newtuple(py_retval(), 0);
|
||||
return true;
|
||||
@ -69,7 +69,7 @@ static bool _py_tuple__new__(int argc, py_Ref argv) {
|
||||
return TypeError("tuple() takes at most 1 argument");
|
||||
}
|
||||
|
||||
static bool _py_tuple__getitem__(int argc, py_Ref argv) {
|
||||
static bool tuple__getitem__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
int length = py_tuple__len(argv);
|
||||
py_Ref _1 = py_arg(1);
|
||||
@ -97,7 +97,7 @@ static bool _py_tuple__getitem__(int argc, py_Ref argv) {
|
||||
}
|
||||
}
|
||||
|
||||
static bool _py_tuple__eq__(int argc, py_Ref argv) {
|
||||
static bool tuple__eq__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
if(py_istype(py_arg(1), tp_tuple)) {
|
||||
int length0, length1;
|
||||
@ -112,8 +112,8 @@ static bool _py_tuple__eq__(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_tuple__ne__(int argc, py_Ref argv) {
|
||||
if(!_py_tuple__eq__(argc, argv)) return false;
|
||||
static bool tuple__ne__(int argc, py_Ref argv) {
|
||||
if(!tuple__eq__(argc, argv)) return false;
|
||||
if(py_isbool(py_retval())) {
|
||||
bool res = py_tobool(py_retval());
|
||||
py_newbool(py_retval(), !res);
|
||||
@ -121,12 +121,12 @@ static bool _py_tuple__ne__(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_tuple__iter__(int argc, py_Ref argv) {
|
||||
static bool tuple__iter__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
return pk_arrayiter(argv);
|
||||
}
|
||||
|
||||
static bool _py_tuple__contains__(int argc, py_Ref argv) {
|
||||
static bool tuple__contains__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
return pk_arraycontains(py_arg(0), py_arg(1));
|
||||
}
|
||||
@ -134,13 +134,13 @@ static bool _py_tuple__contains__(int argc, py_Ref argv) {
|
||||
py_Type pk_tuple__register() {
|
||||
py_Type type = pk_newtype("tuple", tp_object, NULL, NULL, false, true);
|
||||
|
||||
py_bindmagic(type, __len__, _py_tuple__len__);
|
||||
py_bindmagic(type, __repr__, _py_tuple__repr__);
|
||||
py_bindmagic(type, __new__, _py_tuple__new__);
|
||||
py_bindmagic(type, __getitem__, _py_tuple__getitem__);
|
||||
py_bindmagic(type, __eq__, _py_tuple__eq__);
|
||||
py_bindmagic(type, __ne__, _py_tuple__ne__);
|
||||
py_bindmagic(type, __iter__, _py_tuple__iter__);
|
||||
py_bindmagic(type, __contains__, _py_tuple__contains__);
|
||||
py_bindmagic(type, __len__, tuple__len__);
|
||||
py_bindmagic(type, __repr__, tuple__repr__);
|
||||
py_bindmagic(type, __new__, tuple__new__);
|
||||
py_bindmagic(type, __getitem__, tuple__getitem__);
|
||||
py_bindmagic(type, __eq__, tuple__eq__);
|
||||
py_bindmagic(type, __ne__, tuple__ne__);
|
||||
py_bindmagic(type, __iter__, tuple__iter__);
|
||||
py_bindmagic(type, __contains__, tuple__contains__);
|
||||
return type;
|
||||
}
|
||||
|
||||
@ -11,7 +11,7 @@ void py_setreg(int i, py_Ref val) { pk_current_vm->reg[i] = *val; }
|
||||
py_Ref py_getdict(py_Ref self, py_Name name) {
|
||||
assert(self && self->is_ptr);
|
||||
if(!py_ismagicname(name) || self->type != tp_type) {
|
||||
return pk_NameDict__try_get(PyObject__dict(self->_obj), name);
|
||||
return NameDict__try_get(PyObject__dict(self->_obj), name);
|
||||
} else {
|
||||
py_Type* ud = py_touserdata(self);
|
||||
py_Ref slot = py_tpmagic(*ud, name);
|
||||
@ -22,17 +22,22 @@ py_Ref py_getdict(py_Ref self, py_Name name) {
|
||||
void py_setdict(py_Ref self, py_Name name, py_Ref val) {
|
||||
assert(self && self->is_ptr);
|
||||
if(!py_ismagicname(name) || self->type != tp_type) {
|
||||
pk_NameDict__set(PyObject__dict(self->_obj), name, *val);
|
||||
NameDict__set(PyObject__dict(self->_obj), name, *val);
|
||||
} else {
|
||||
py_Type* ud = py_touserdata(self);
|
||||
*py_tpmagic(*ud, name) = *val;
|
||||
}
|
||||
}
|
||||
|
||||
py_TmpRef py_emplacedict(py_Ref self, py_Name name){
|
||||
py_setdict(self, name, py_NIL);
|
||||
return py_getdict(self, name);
|
||||
}
|
||||
|
||||
bool py_deldict(py_Ref self, py_Name name) {
|
||||
assert(self && self->is_ptr);
|
||||
if(!py_ismagicname(name) || self->type != tp_type) {
|
||||
return pk_NameDict__del(PyObject__dict(self->_obj), name);
|
||||
return NameDict__del(PyObject__dict(self->_obj), name);
|
||||
|
||||
} else {
|
||||
py_Type* ud = py_touserdata(self);
|
||||
@ -57,32 +62,32 @@ void py_assign(py_Ref dst, py_Ref src) { *dst = *src; }
|
||||
|
||||
/* Stack References */
|
||||
py_Ref py_peek(int i) {
|
||||
assert(i < 0);
|
||||
assert(i <= 0);
|
||||
return pk_current_vm->stack.sp + i;
|
||||
}
|
||||
|
||||
void py_pop() {
|
||||
pk_VM* vm = pk_current_vm;
|
||||
VM* vm = pk_current_vm;
|
||||
vm->stack.sp--;
|
||||
}
|
||||
|
||||
void py_shrink(int n) {
|
||||
pk_VM* vm = pk_current_vm;
|
||||
VM* vm = pk_current_vm;
|
||||
vm->stack.sp -= n;
|
||||
}
|
||||
|
||||
void py_push(py_Ref src) {
|
||||
pk_VM* vm = pk_current_vm;
|
||||
VM* vm = pk_current_vm;
|
||||
*vm->stack.sp++ = *src;
|
||||
}
|
||||
|
||||
void py_pushnil() {
|
||||
pk_VM* vm = pk_current_vm;
|
||||
VM* vm = pk_current_vm;
|
||||
py_newnil(vm->stack.sp++);
|
||||
}
|
||||
|
||||
py_Ref py_pushtmp() {
|
||||
pk_VM* vm = pk_current_vm;
|
||||
VM* vm = pk_current_vm;
|
||||
py_newnil(vm->stack.sp++);
|
||||
return py_peek(-1);
|
||||
}
|
||||
@ -60,22 +60,31 @@ void py_bindfunc(py_Ref obj, const char* name, py_CFunction f) {
|
||||
py_setdict(obj, py_name(name), &tmp);
|
||||
}
|
||||
|
||||
void py_bindproperty(py_Type type, const char* name, py_CFunction getter, py_CFunction setter) {
|
||||
py_TValue tmp;
|
||||
py_newobject(&tmp, tp_property, 2, 0);
|
||||
py_newnativefunc(py_getslot(&tmp, 0), getter);
|
||||
if(setter) {
|
||||
py_newnativefunc(py_getslot(&tmp, 1), setter);
|
||||
} else {
|
||||
py_setslot(&tmp, 1, py_None);
|
||||
}
|
||||
py_setdict(py_tpobject(type), py_name(name), &tmp);
|
||||
}
|
||||
|
||||
void py_bind(py_Ref obj, const char* sig, py_CFunction f) {
|
||||
py_TValue tmp;
|
||||
py_Name name = py_newfunction(&tmp, sig, f, NULL, 0);
|
||||
py_setdict(obj, name, &tmp);
|
||||
}
|
||||
|
||||
py_Name py_newfunction(py_Ref out,
|
||||
const char* sig,
|
||||
py_CFunction f,
|
||||
const char* docstring,
|
||||
int slots) {
|
||||
py_Name
|
||||
py_newfunction(py_Ref out, const char* sig, py_CFunction f, const char* docstring, int slots) {
|
||||
char buffer[256];
|
||||
snprintf(buffer, sizeof(buffer), "def %s: pass", sig);
|
||||
// fn(a, b, *c, d=1) -> None
|
||||
CodeObject code;
|
||||
pk_SourceData_ source = pk_SourceData__rcnew(buffer, "<bind>", EXEC_MODE, false);
|
||||
SourceData_ source = SourceData__rcnew(buffer, "<bind>", EXEC_MODE, false);
|
||||
Error* err = pk_compile(source, &code);
|
||||
if(err || code.func_decls.count != 1) {
|
||||
c11__abort("py_newfunction(): invalid signature '%s'", sig);
|
||||
@ -92,9 +101,15 @@ py_Name py_newfunction(py_Ref out,
|
||||
return py_name(ud->decl->code.name->data);
|
||||
}
|
||||
|
||||
void py_newboundmethod(py_Ref out, py_Ref self, py_Ref func){
|
||||
py_newobject(out, tp_boundmethod, 2, 0);
|
||||
py_setslot(out, 0, self);
|
||||
py_setslot(out, 1, func);
|
||||
}
|
||||
|
||||
void* py_newobject(py_Ref out, py_Type type, int slots, int udsize) {
|
||||
pk_ManagedHeap* heap = &pk_current_vm->heap;
|
||||
PyObject* obj = pk_ManagedHeap__gcnew(heap, type, slots, udsize);
|
||||
ManagedHeap* heap = &pk_current_vm->heap;
|
||||
PyObject* obj = ManagedHeap__gcnew(heap, type, slots, udsize);
|
||||
out->type = type;
|
||||
out->is_ptr = true;
|
||||
out->_obj = obj;
|
||||
|
||||
@ -46,7 +46,7 @@ int main(int argc, char** argv) {
|
||||
printf("Type \"exit()\" to exit.\n");
|
||||
|
||||
while(true) {
|
||||
int size = py_replinput(buf);
|
||||
int size = py_replinput(buf, sizeof(buf));
|
||||
assert(size < sizeof(buf));
|
||||
if(size >= 0) {
|
||||
if(!py_exec(buf, "<stdin>", REPL_MODE, NULL)) py_printexc();
|
||||
|
||||
@ -23,7 +23,7 @@ class Task:
|
||||
|
||||
def __next__(self):
|
||||
if self.i == self.n:
|
||||
return StopIteration
|
||||
raise StopIteration
|
||||
self.i += 1
|
||||
return self.i
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@ except ImportError:
|
||||
exit(0)
|
||||
|
||||
os.chdir('tests')
|
||||
assert os.getcwd().endswith('tests')
|
||||
|
||||
import test1
|
||||
|
||||
|
||||
@ -1,7 +1,11 @@
|
||||
class A:
|
||||
def __init__(self, a, b):
|
||||
def __init__(self, a, __b):
|
||||
self.a = a
|
||||
self.b = b
|
||||
self.__b = __b
|
||||
|
||||
@property
|
||||
def b(self):
|
||||
return self.__b
|
||||
|
||||
def add(self):
|
||||
return self.a + self.b
|
||||
@ -110,14 +114,6 @@ class B(A):
|
||||
assert B.b == 3
|
||||
assert B.c == 4
|
||||
|
||||
import c
|
||||
|
||||
class A(c.void_p):
|
||||
pass
|
||||
|
||||
a = A(0)
|
||||
assert repr(a).startswith('<void* at')
|
||||
|
||||
if 1:
|
||||
class TrueClass:
|
||||
pass
|
||||
@ -1,8 +0,0 @@
|
||||
def f(n):
|
||||
def g(x):
|
||||
if x==n:
|
||||
return n
|
||||
return g(x+1)
|
||||
return g(0)
|
||||
|
||||
assert f(10) == 10
|
||||
@ -24,4 +24,14 @@ def f3(x, y):
|
||||
return lambda z: x + y + z
|
||||
|
||||
a = f3(1, 2)
|
||||
assert a(3) == 6
|
||||
assert a(3) == 6
|
||||
|
||||
# closure ex
|
||||
def f(n):
|
||||
def g(x):
|
||||
if x==n:
|
||||
return n
|
||||
return g(x+1)
|
||||
return g(0)
|
||||
|
||||
assert f(10) == 10
|
||||
Loading…
x
Reference in New Issue
Block a user