Compare commits

...

10 Commits

Author SHA1 Message Date
blueloveTH
0b649f3bef ... 2024-08-04 22:45:00 +08:00
blueloveTH
a87641c04d ... 2024-08-04 22:31:33 +08:00
blueloveTH
9c173fdada ... 2024-08-04 20:38:49 +08:00
blueloveTH
348bb2b7a5 ... 2024-08-04 20:35:33 +08:00
blueloveTH
39947e8f15 ... 2024-08-04 19:18:29 +08:00
blueloveTH
56763e05f9 ... 2024-08-04 19:09:50 +08:00
blueloveTH
cd9a9f7119 ... 2024-08-04 19:04:00 +08:00
blueloveTH
ea9dabdf99 ... 2024-08-04 18:51:58 +08:00
blueloveTH
b1a8c6db8e ... 2024-08-04 16:05:47 +08:00
blueloveTH
3c87bf8630 ... 2024-08-04 15:19:49 +08:00
66 changed files with 1258 additions and 859 deletions

BIN
backup/vfs.zip Normal file

Binary file not shown.

View File

@ -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[];

View File

@ -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

View File

@ -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*);

View File

@ -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_);

View File

@ -9,7 +9,7 @@
extern "C" {
#endif
Error* pk_compile(pk_SourceData_ src, CodeObject* out);
Error* pk_compile(SourceData_ src, CodeObject* out);
#ifdef __cplusplus
}

View File

@ -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}

View File

@ -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() ==

View File

@ -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
}

View 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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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
}

View File

@ -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

View File

@ -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);

View File

@ -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,

View File

@ -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

View File

@ -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__)

View File

@ -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")

View File

@ -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

View File

@ -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);

View File

@ -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) {

View File

@ -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;
}

View File

@ -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));

View File

@ -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);
// }

View File

@ -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",

View File

@ -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);

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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
View 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
View 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);
}

View File

@ -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);
}

View File

@ -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

View File

@ -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) {

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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
View 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;
}

View File

@ -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);
}

View File

@ -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
View 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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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); }

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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;

View File

@ -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();

View File

@ -23,7 +23,7 @@ class Task:
def __next__(self):
if self.i == self.n:
return StopIteration
raise StopIteration
self.i += 1
return self.i

View File

@ -4,6 +4,7 @@ except ImportError:
exit(0)
os.chdir('tests')
assert os.getcwd().endswith('tests')
import test1

View File

@ -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

View File

@ -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

View File

@ -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