mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 11:30:18 +00:00
backup
This commit is contained in:
parent
28c3b35d39
commit
8b8552d54b
@ -5,7 +5,7 @@ python prebuild.py
|
|||||||
SRC_C=$(find src/ -name "*.c")
|
SRC_C=$(find src/ -name "*.c")
|
||||||
SRC_CPP=$(find src/ -name "*.cpp")
|
SRC_CPP=$(find src/ -name "*.cpp")
|
||||||
|
|
||||||
COMMON_FLAGS="-Iinclude -O0 -Wfatal-errors -g -DDEBUG -DPK_ENABLE_OS=1"
|
COMMON_FLAGS="-Iinclude -O0 -Wfatal-errors -g -DDEBUG -DPK_ENABLE_OS=1" # -fsanitize=address,leak,undefined"
|
||||||
|
|
||||||
FLAGS_C="-std=c11 $COMMON_FLAGS"
|
FLAGS_C="-std=c11 $COMMON_FLAGS"
|
||||||
FLAGS_CPP="-std=c++17 -stdlib=libc++ -frtti $COMMON_FLAGS"
|
FLAGS_CPP="-std=c++17 -stdlib=libc++ -frtti $COMMON_FLAGS"
|
||||||
|
@ -10,11 +10,11 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct pkpy_SStream {
|
typedef struct pk_SStream {
|
||||||
c11_vector data;
|
c11_vector data;
|
||||||
} pkpy_SStream;
|
} pk_SStream;
|
||||||
|
|
||||||
typedef struct pkpy_AnyStr {
|
typedef struct pk_AnyStr {
|
||||||
int type;
|
int type;
|
||||||
union {
|
union {
|
||||||
int _int;
|
int _int;
|
||||||
@ -27,59 +27,62 @@ typedef struct pkpy_AnyStr {
|
|||||||
const char* _cstr;
|
const char* _cstr;
|
||||||
void* _ptr;
|
void* _ptr;
|
||||||
};
|
};
|
||||||
} pkpy_AnyStr;
|
} pk_AnyStr;
|
||||||
|
|
||||||
PK_INLINE pkpy_AnyStr pkpy_AnyStr__int(int x) { pkpy_AnyStr s; s.type = 1; s._int = x; return s; }
|
PK_INLINE pk_AnyStr pk_AnyStr__int(int x) { pk_AnyStr s; s.type = 1; s._int = x; return s; }
|
||||||
PK_INLINE pkpy_AnyStr pkpy_AnyStr__i64(int64_t x) { pkpy_AnyStr s; s.type = 2; s._i64 = x; return s; }
|
PK_INLINE pk_AnyStr pk_AnyStr__i64(int64_t x) { pk_AnyStr s; s.type = 2; s._i64 = x; return s; }
|
||||||
PK_INLINE pkpy_AnyStr pkpy_AnyStr__float(float x) { pkpy_AnyStr s; s.type = 3; s._float = x; return s; }
|
PK_INLINE pk_AnyStr pk_AnyStr__float(float x) { pk_AnyStr s; s.type = 3; s._float = x; return s; }
|
||||||
PK_INLINE pkpy_AnyStr pkpy_AnyStr__double(double x) { pkpy_AnyStr s; s.type = 4; s._double = x; return s; }
|
PK_INLINE pk_AnyStr pk_AnyStr__double(double x) { pk_AnyStr s; s.type = 4; s._double = x; return s; }
|
||||||
PK_INLINE pkpy_AnyStr pkpy_AnyStr__char(char x) { pkpy_AnyStr s; s.type = 5; s._char = x; return s; }
|
PK_INLINE pk_AnyStr pk_AnyStr__char(char x) { pk_AnyStr s; s.type = 5; s._char = x; return s; }
|
||||||
PK_INLINE pkpy_AnyStr pkpy_AnyStr__str(const pkpy_Str* x) { pkpy_AnyStr s; s.type = 6; s._str = x; return s; }
|
PK_INLINE pk_AnyStr pk_AnyStr__str(const pkpy_Str* x) { pk_AnyStr s; s.type = 6; s._str = x; return s; }
|
||||||
PK_INLINE pkpy_AnyStr pkpy_AnyStr__sv(c11_string x) { pkpy_AnyStr s; s.type = 7; s._sv = x; return s; }
|
PK_INLINE pk_AnyStr pk_AnyStr__sv(c11_string x) { pk_AnyStr s; s.type = 7; s._sv = x; return s; }
|
||||||
PK_INLINE pkpy_AnyStr pkpy_AnyStr__cstr(const char* x) { pkpy_AnyStr s; s.type = 8; s._cstr = x; return s; }
|
PK_INLINE pk_AnyStr pk_AnyStr__cstr(const char* x) { pk_AnyStr s; s.type = 8; s._cstr = x; return s; }
|
||||||
PK_INLINE pkpy_AnyStr pkpy_AnyStr__ptr(void* x) { pkpy_AnyStr s; s.type = 9; s._ptr = x; return s; }
|
PK_INLINE pk_AnyStr pk_AnyStr__ptr(void* x) { pk_AnyStr s; s.type = 9; s._ptr = x; return s; }
|
||||||
|
|
||||||
void pkpy_SStream__ctor(pkpy_SStream* self);
|
void pk_SStream__ctor(pk_SStream* self);
|
||||||
void pkpy_SStream__ctor2(pkpy_SStream* self, int capacity);
|
void pk_SStream__ctor2(pk_SStream* self, int capacity);
|
||||||
void pkpy_SStream__dtor(pkpy_SStream* self);
|
void pk_SStream__dtor(pk_SStream* self);
|
||||||
|
|
||||||
void pkpy_SStream__write_int(pkpy_SStream* self, int);
|
void pk_SStream__write_int(pk_SStream* self, int);
|
||||||
void pkpy_SStream__write_i64(pkpy_SStream* self, int64_t);
|
void pk_SStream__write_i64(pk_SStream* self, int64_t);
|
||||||
void pkpy_SStream__write_float(pkpy_SStream* self, float, int precision);
|
void pk_SStream__write_float(pk_SStream* self, float, int precision);
|
||||||
void pkpy_SStream__write_double(pkpy_SStream* self, double, int precision);
|
void pk_SStream__write_double(pk_SStream* self, double, int precision);
|
||||||
void pkpy_SStream__write_char(pkpy_SStream* self, char);
|
void pk_SStream__write_char(pk_SStream* self, char);
|
||||||
void pkpy_SStream__write_Str(pkpy_SStream* self, const pkpy_Str*);
|
void pk_SStream__write_Str(pk_SStream* self, const pkpy_Str*);
|
||||||
void pkpy_SStream__write_sv(pkpy_SStream* self, c11_string);
|
void pk_SStream__write_sv(pk_SStream* self, c11_string);
|
||||||
void pkpy_SStream__write_cstr(pkpy_SStream* self, const char*);
|
void pk_SStream__write_cstr(pk_SStream* self, const char*);
|
||||||
void pkpy_SStream__write_cstrn(pkpy_SStream* self, const char*, int);
|
void pk_SStream__write_cstrn(pk_SStream* self, const char*, int);
|
||||||
void pkpy_SStream__write_hex(pkpy_SStream* self, unsigned char, bool non_zero);
|
void pk_SStream__write_hex(pk_SStream* self, unsigned char, bool non_zero);
|
||||||
void pkpy_SStream__write_ptr(pkpy_SStream* self, void*);
|
void pk_SStream__write_ptr(pk_SStream* self, void*);
|
||||||
void pkpy_SStream__write_any(pkpy_SStream* self, const char* fmt, const pkpy_AnyStr* args, int n);
|
|
||||||
|
void pk_SStream__write_any(pk_SStream* self, const char* fmt, const pk_AnyStr* args, int n);
|
||||||
|
const char* pk_format_any(const char* fmt, const pk_AnyStr* args, int n);
|
||||||
|
|
||||||
// Submit the stream and return the final string. The stream becomes invalid after this call
|
// Submit the stream and return the final string. The stream becomes invalid after this call
|
||||||
pkpy_Str pkpy_SStream__submit(pkpy_SStream* self);
|
pkpy_Str pk_SStream__submit(pk_SStream* self);
|
||||||
|
|
||||||
#define pkpy__anystr(x) _Generic((x), \
|
#define pk__anystr(x) _Generic((x), \
|
||||||
int: pkpy_AnyStr__int, \
|
int: pk_AnyStr__int, \
|
||||||
int64_t: pkpy_AnyStr__i64, \
|
int64_t: pk_AnyStr__i64, \
|
||||||
float: pkpy_AnyStr__float, \
|
float: pk_AnyStr__float, \
|
||||||
double: pkpy_AnyStr__double, \
|
double: pk_AnyStr__double, \
|
||||||
char: pkpy_AnyStr__char, \
|
char: pk_AnyStr__char, \
|
||||||
const pkpy_Str*: pkpy_AnyStr__str, \
|
const pkpy_Str*: pk_AnyStr__str, \
|
||||||
c11_string: pkpy_AnyStr__sv, \
|
c11_string: pk_AnyStr__sv, \
|
||||||
const char*: pkpy_AnyStr__cstr, \
|
const char*: pk_AnyStr__cstr, \
|
||||||
void*: pkpy_AnyStr__ptr \
|
void*: pk_AnyStr__ptr \
|
||||||
)(x)
|
)(x)
|
||||||
|
|
||||||
#define pkpy__anystr_list_1(a) (pkpy_AnyStr[]){pkpy__anystr(a)}, 1
|
#define pk__anystr_list_1(a) (pk_AnyStr[]){pk__anystr(a)}, 1
|
||||||
#define pkpy__anystr_list_2(a, b) (pkpy_AnyStr[]){pkpy__anystr(a), pkpy__anystr(b)}, 2
|
#define pk__anystr_list_2(a, b) (pk_AnyStr[]){pk__anystr(a), pk__anystr(b)}, 2
|
||||||
#define pkpy__anystr_list_3(a, b, c) (pkpy_AnyStr[]){pkpy__anystr(a), pkpy__anystr(b), pkpy__anystr(c)}, 3
|
#define pk__anystr_list_3(a, b, c) (pk_AnyStr[]){pk__anystr(a), pk__anystr(b), pk__anystr(c)}, 3
|
||||||
#define pkpy__anystr_list_4(a, b, c, d) (pkpy_AnyStr[]){pkpy__anystr(a), pkpy__anystr(b), pkpy__anystr(c), pkpy__anystr(d)}, 4
|
#define pk__anystr_list_4(a, b, c, d) (pk_AnyStr[]){pk__anystr(a), pk__anystr(b), pk__anystr(c), pk__anystr(d)}, 4
|
||||||
|
|
||||||
#define pkpy__anystr_list_dispatcher(...) PK_NARGS_SEQ(__VA_ARGS__, pkpy__anystr_list_4, pkpy__anystr_list_3, pkpy__anystr_list_2, pkpy__anystr_list_1, 0)
|
#define pk__anystr_list_dispatcher(...) PK_NARGS_SEQ(__VA_ARGS__, pk__anystr_list_4, pk__anystr_list_3, pk__anystr_list_2, pk__anystr_list_1, 0)
|
||||||
#define pkpy__anystr_list(...) pkpy__anystr_list_dispatcher(__VA_ARGS__)(__VA_ARGS__)
|
#define pk__anystr_list(...) pk__anystr_list_dispatcher(__VA_ARGS__)(__VA_ARGS__)
|
||||||
|
|
||||||
#define pkpy_SStream__write(self, fmt, ...) pkpy_SStream__write_any(self, fmt, pkpy__anystr_list(__VA_ARGS__))
|
#define pk_SStream__write(self, fmt, ...) pk_SStream__write_any(self, fmt, pk__anystr_list(__VA_ARGS__))
|
||||||
|
#define pk_format(fmt, ...) pk_format_any(fmt, pk__anystr_list(__VA_ARGS__))
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -288,7 +288,7 @@ struct StrName {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SStream: pkpy_SStream {
|
struct SStream: pk_SStream {
|
||||||
PK_ALWAYS_PASS_BY_POINTER(SStream)
|
PK_ALWAYS_PASS_BY_POINTER(SStream)
|
||||||
|
|
||||||
int _precision = -1;
|
int _precision = -1;
|
||||||
@ -298,85 +298,85 @@ struct SStream: pkpy_SStream {
|
|||||||
void setprecision(int precision) { _precision = precision; }
|
void setprecision(int precision) { _precision = precision; }
|
||||||
|
|
||||||
SStream() {
|
SStream() {
|
||||||
pkpy_SStream__ctor(this);
|
pk_SStream__ctor(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
SStream(int guess_size) { c11_vector__reserve(&data, guess_size); }
|
SStream(int guess_size) { c11_vector__reserve(&data, guess_size); }
|
||||||
|
|
||||||
~SStream() {
|
~SStream() {
|
||||||
// in case of error
|
// in case of error
|
||||||
if(!_submited) pkpy_SStream__dtor(this);
|
if(!_submited) pk_SStream__dtor(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
Str str(){
|
Str str(){
|
||||||
assert(!_submited);
|
assert(!_submited);
|
||||||
_submited = true;
|
_submited = true;
|
||||||
return pkpy_SStream__submit(this);
|
return pk_SStream__submit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
SStream& operator<< (const Str& val){
|
SStream& operator<< (const Str& val){
|
||||||
pkpy_SStream__write_Str(this, &val);
|
pk_SStream__write_Str(this, &val);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
SStream& operator<< (const char* val){
|
SStream& operator<< (const char* val){
|
||||||
pkpy_SStream__write_cstr(this, val);
|
pk_SStream__write_cstr(this, val);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
SStream& operator<< (int val){
|
SStream& operator<< (int val){
|
||||||
pkpy_SStream__write_int(this, val);
|
pk_SStream__write_int(this, val);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
SStream& operator<< (size_t val){
|
SStream& operator<< (size_t val){
|
||||||
// size_t could overflow int64, but nevermind...
|
// size_t could overflow int64, but nevermind...
|
||||||
pkpy_SStream__write_i64(this, val);
|
pk_SStream__write_i64(this, val);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
SStream& operator<< (i64 val){
|
SStream& operator<< (i64 val){
|
||||||
pkpy_SStream__write_i64(this, val);
|
pk_SStream__write_i64(this, val);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
SStream& operator<< (f64 val){
|
SStream& operator<< (f64 val){
|
||||||
pkpy_SStream__write_double(this, val, _precision);
|
pk_SStream__write_double(this, val, _precision);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
SStream& operator<< (const std::string& val){
|
SStream& operator<< (const std::string& val){
|
||||||
pkpy_SStream__write_cstrn(this, val.data(), val.size());
|
pk_SStream__write_cstrn(this, val.data(), val.size());
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
SStream& operator<< (std::string_view val){
|
SStream& operator<< (std::string_view val){
|
||||||
pkpy_SStream__write_cstrn(this, val.data(), val.size());
|
pk_SStream__write_cstrn(this, val.data(), val.size());
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
SStream& operator<< (c11_string val){
|
SStream& operator<< (c11_string val){
|
||||||
pkpy_SStream__write_cstrn(this, val.data, val.size);
|
pk_SStream__write_cstrn(this, val.data, val.size);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
SStream& operator<< (char val){
|
SStream& operator<< (char val){
|
||||||
pkpy_SStream__write_char(this, val);
|
pk_SStream__write_char(this, val);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
SStream& operator<< (StrName name){
|
SStream& operator<< (StrName name){
|
||||||
std::string_view sv = name.sv();
|
std::string_view sv = name.sv();
|
||||||
pkpy_SStream__write_cstrn(this, sv.data(), sv.size());
|
pk_SStream__write_cstrn(this, sv.data(), sv.size());
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_hex(unsigned char val, bool non_zero = false){
|
void write_hex(unsigned char val, bool non_zero = false){
|
||||||
pkpy_SStream__write_hex(this, val, non_zero);
|
pk_SStream__write_hex(this, val, non_zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_ptr(void* p){
|
void write_ptr(void* p){
|
||||||
pkpy_SStream__write_ptr(this, p);
|
pk_SStream__write_ptr(this, p);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ struct Compiler {
|
|||||||
|
|
||||||
NameScope name_scope() const noexcept;
|
NameScope name_scope() const noexcept;
|
||||||
CodeObject* push_global_context() noexcept;
|
CodeObject* push_global_context() noexcept;
|
||||||
FuncDecl_ push_f_context(Str name) noexcept;
|
FuncDecl_ push_f_context(c11_string name, int* out_index) noexcept;
|
||||||
|
|
||||||
static void init_pratt_rules() noexcept;
|
static void init_pratt_rules() noexcept;
|
||||||
|
|
||||||
@ -118,7 +118,7 @@ struct Compiler {
|
|||||||
[[nodiscard]] Error* try_compile_assignment(bool* is_assign) noexcept;
|
[[nodiscard]] Error* try_compile_assignment(bool* is_assign) noexcept;
|
||||||
[[nodiscard]] Error* compile_stmt() noexcept;
|
[[nodiscard]] Error* compile_stmt() noexcept;
|
||||||
[[nodiscard]] Error* consume_type_hints() noexcept;
|
[[nodiscard]] Error* consume_type_hints() noexcept;
|
||||||
[[nodiscard]] Error* _compile_f_args(FuncDecl_ decl, bool enable_type_hints) noexcept;
|
[[nodiscard]] Error* _compile_f_args(FuncDecl* decl, bool enable_type_hints) noexcept;
|
||||||
[[nodiscard]] Error* compile_function(int decorators = 0) noexcept;
|
[[nodiscard]] Error* compile_function(int decorators = 0) noexcept;
|
||||||
[[nodiscard]] Error* compile_class(int decorators = 0) noexcept;
|
[[nodiscard]] Error* compile_class(int decorators = 0) noexcept;
|
||||||
|
|
||||||
|
@ -47,13 +47,14 @@ inline void delete_expr(Expr* p) noexcept{
|
|||||||
|
|
||||||
struct CodeEmitContext{
|
struct CodeEmitContext{
|
||||||
VM* vm;
|
VM* vm;
|
||||||
FuncDecl_ func; // optional
|
FuncDecl* func; // optional, weakref
|
||||||
CodeObject* co; // 1 CodeEmitContext <=> 1 CodeObject*
|
CodeObject* co; // 1 CodeEmitContext <=> 1 CodeObject*
|
||||||
vector<Expr*> _s_expr;
|
vector<Expr*> _s_expr;
|
||||||
int level;
|
int level;
|
||||||
vector<StrName> global_names;
|
vector<StrName> global_names;
|
||||||
|
|
||||||
CodeEmitContext(VM* vm, CodeObject* co, int level) : vm(vm), co(co), level(level) {
|
CodeEmitContext(VM* vm, CodeObject* co, int level) : vm(vm), co(co), level(level) {
|
||||||
|
func = NULL;
|
||||||
c11_smallmap_s2n__ctor(&_co_consts_string_dedup_map);
|
c11_smallmap_s2n__ctor(&_co_consts_string_dedup_map);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,7 +74,6 @@ struct CodeEmitContext{
|
|||||||
int add_varname(StrName name) noexcept;
|
int add_varname(StrName name) noexcept;
|
||||||
int add_const(PyVar) noexcept;
|
int add_const(PyVar) noexcept;
|
||||||
int add_const_string(std::string_view) noexcept;
|
int add_const_string(std::string_view) noexcept;
|
||||||
int add_func_decl(FuncDecl_ decl) noexcept;
|
|
||||||
void emit_store_name(NameScope scope, StrName name, int line) noexcept;
|
void emit_store_name(NameScope scope, StrName name, int line) noexcept;
|
||||||
void try_merge_for_iter_store(int) noexcept;
|
void try_merge_for_iter_store(int) noexcept;
|
||||||
// emit top -> pop -> delete
|
// emit top -> pop -> delete
|
||||||
@ -366,12 +366,11 @@ struct CompExpr : Expr {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct LambdaExpr : Expr {
|
struct LambdaExpr : Expr {
|
||||||
FuncDecl_ decl;
|
int index;
|
||||||
|
|
||||||
LambdaExpr(FuncDecl_ decl) : decl(decl) {}
|
LambdaExpr(int index) : index(index) {}
|
||||||
|
|
||||||
void emit_(CodeEmitContext* ctx) override {
|
void emit_(CodeEmitContext* ctx) override {
|
||||||
int index = ctx->add_func_decl(decl);
|
|
||||||
ctx->emit_(OP_LOAD_FUNCTION, index, line);
|
ctx->emit_(OP_LOAD_FUNCTION, index, line);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "pocketpy/objects/codeobject.h"
|
||||||
#include "pocketpy/objects/codeobject.hpp"
|
#include "pocketpy/objects/codeobject.hpp"
|
||||||
|
|
||||||
namespace pkpy {
|
namespace pkpy {
|
||||||
@ -117,21 +118,21 @@ struct Frame {
|
|||||||
|
|
||||||
PyVar* f_closure_try_get(StrName name);
|
PyVar* f_closure_try_get(StrName name);
|
||||||
|
|
||||||
int ip() const { return _ip - co->codes.data(); }
|
int ip() const { return _ip - (Bytecode*)co->codes.data; }
|
||||||
|
|
||||||
// function scope
|
// function scope
|
||||||
Frame(PyVar* p0, const CodeObject* co, PyObject* _module, PyObject* _callable, PyVar* _locals_base) :
|
Frame(PyVar* p0, const CodeObject* co, PyObject* _module, PyObject* _callable, PyVar* _locals_base) :
|
||||||
_ip(co->codes.data() - 1), _sp_base(p0), co(co), _module(_module), _callable(_callable),
|
_ip((Bytecode*)co->codes.data - 1), _sp_base(p0), co(co), _module(_module), _callable(_callable),
|
||||||
_locals(co, _locals_base), _uw_list(nullptr) {}
|
_locals(co, _locals_base), _uw_list(nullptr) {}
|
||||||
|
|
||||||
// exec/eval
|
// exec/eval
|
||||||
Frame(PyVar* p0, const CodeObject* co, PyObject* _module, PyObject* _callable, FastLocals _locals) :
|
Frame(PyVar* p0, const CodeObject* co, PyObject* _module, PyObject* _callable, FastLocals _locals) :
|
||||||
_ip(co->codes.data() - 1), _sp_base(p0), co(co), _module(_module), _callable(_callable), _locals(_locals),
|
_ip((Bytecode*)co->codes.data - 1), _sp_base(p0), co(co), _module(_module), _callable(_callable), _locals(_locals),
|
||||||
_uw_list(nullptr) {}
|
_uw_list(nullptr) {}
|
||||||
|
|
||||||
// global scope
|
// global scope
|
||||||
Frame(PyVar* p0, const CodeObject* co, PyObject* _module) :
|
Frame(PyVar* p0, const CodeObject* co, PyObject* _module) :
|
||||||
_ip(co->codes.data() - 1), _sp_base(p0), co(co), _module(_module), _callable(nullptr),
|
_ip((Bytecode*)co->codes.data - 1), _sp_base(p0), co(co), _module(_module), _callable(nullptr),
|
||||||
_locals(co, p0), _uw_list(nullptr) {}
|
_locals(co, p0), _uw_list(nullptr) {}
|
||||||
|
|
||||||
PyVar* actual_sp_base() const { return _locals.a; }
|
PyVar* actual_sp_base() const { return _locals.a; }
|
||||||
@ -143,12 +144,15 @@ struct Frame {
|
|||||||
int _exit_block(ValueStack*, int);
|
int _exit_block(ValueStack*, int);
|
||||||
|
|
||||||
[[nodiscard]] int prepare_loop_break(ValueStack* s_data) {
|
[[nodiscard]] int prepare_loop_break(ValueStack* s_data) {
|
||||||
int target = co->blocks[co->lines[ip()].iblock].end;
|
int iblock = c11__getitem(BytecodeEx, &co->codes_ex, ip()).iblock;
|
||||||
|
int target = c11__getitem(CodeBlock, &co->blocks, iblock).end;
|
||||||
prepare_jump_break(s_data, target);
|
prepare_jump_break(s_data, target);
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
int curr_lineno() const { return co->lines[ip()].lineno; }
|
int curr_lineno() const {
|
||||||
|
return c11__getitem(BytecodeEx, &co->codes_ex, ip()).lineno;
|
||||||
|
}
|
||||||
|
|
||||||
void set_unwind_target(PyVar* _sp);
|
void set_unwind_target(PyVar* _sp);
|
||||||
UnwindTarget* find_unwind_target(int iblock);
|
UnwindTarget* find_unwind_target(int iblock);
|
||||||
|
@ -501,7 +501,7 @@ public:
|
|||||||
void __pop_frame();
|
void __pop_frame();
|
||||||
PyVar __py_generator(LinkedFrame* frame, ArgsView buffer);
|
PyVar __py_generator(LinkedFrame* frame, ArgsView buffer);
|
||||||
void __op_unpack_sequence(uint16_t arg);
|
void __op_unpack_sequence(uint16_t arg);
|
||||||
void __prepare_py_call(PyVar*, ArgsView, ArgsView, const FuncDecl_&);
|
void __prepare_py_call(PyVar*, ArgsView, ArgsView, const FuncDecl*);
|
||||||
void __unpack_as_list(ArgsView args, List& list);
|
void __unpack_as_list(ArgsView args, List& list);
|
||||||
void __unpack_as_dict(ArgsView args, Dict& dict);
|
void __unpack_as_dict(ArgsView args, Dict& dict);
|
||||||
[[noreturn]] void __raise_exc(bool re_raise = false);
|
[[noreturn]] void __raise_exc(bool re_raise = false);
|
||||||
|
@ -3,6 +3,12 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "pocketpy/common/vector.h"
|
||||||
|
#include "pocketpy/common/smallmap.h"
|
||||||
|
#include "pocketpy/objects/base.h"
|
||||||
|
#include "pocketpy/objects/sourcedata.h"
|
||||||
|
#include "pocketpy/common/refcount.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
@ -52,7 +58,6 @@ typedef struct Bytecode {
|
|||||||
void Bytecode__set_signed_arg(Bytecode* self, int arg);
|
void Bytecode__set_signed_arg(Bytecode* self, int arg);
|
||||||
bool Bytecode__is_forward_jump(const Bytecode* self);
|
bool Bytecode__is_forward_jump(const Bytecode* self);
|
||||||
|
|
||||||
|
|
||||||
typedef struct CodeBlock {
|
typedef struct CodeBlock {
|
||||||
CodeBlockType type;
|
CodeBlockType type;
|
||||||
int parent; // parent index in blocks
|
int parent; // parent index in blocks
|
||||||
@ -61,6 +66,67 @@ typedef struct CodeBlock {
|
|||||||
int end2; // ...
|
int end2; // ...
|
||||||
} CodeBlock;
|
} CodeBlock;
|
||||||
|
|
||||||
|
typedef struct BytecodeEx {
|
||||||
|
int lineno; // line number for each bytecode
|
||||||
|
bool is_virtual; // whether this bytecode is virtual (not in source code)
|
||||||
|
int iblock; // block index
|
||||||
|
} BytecodeEx;
|
||||||
|
|
||||||
|
typedef struct CodeObject {
|
||||||
|
pkpy_SourceData_ src;
|
||||||
|
pkpy_Str name;
|
||||||
|
|
||||||
|
c11_vector/*T=Bytecode*/ codes;
|
||||||
|
c11_vector/*T=CodeObjectByteCodeEx*/ codes_ex;
|
||||||
|
|
||||||
|
c11_vector/*T=PyVar*/ consts; // constants
|
||||||
|
c11_vector/*T=StrName*/ varnames; // local variables
|
||||||
|
int nlocals; // cached varnames.size()
|
||||||
|
|
||||||
|
c11_smallmap_n2i varnames_inv;
|
||||||
|
c11_smallmap_n2i labels;
|
||||||
|
|
||||||
|
c11_vector/*T=CodeBlock*/ blocks;
|
||||||
|
c11_vector/*T=FuncDecl_*/ func_decls;
|
||||||
|
|
||||||
|
int start_line;
|
||||||
|
int end_line;
|
||||||
|
} CodeObject;
|
||||||
|
|
||||||
|
CodeObject* CodeObject__new(pkpy_SourceData_ src, c11_string name);
|
||||||
|
void CodeObject__delete(CodeObject* self);
|
||||||
|
void CodeObject__gc_mark(const CodeObject* self);
|
||||||
|
|
||||||
|
typedef struct FuncDeclKwArg{
|
||||||
|
int index; // index in co->varnames
|
||||||
|
uint16_t key; // name of this argument
|
||||||
|
PyVar value; // default value
|
||||||
|
} FuncDeclKwArg;
|
||||||
|
|
||||||
|
typedef struct FuncDecl {
|
||||||
|
RefCounted rc;
|
||||||
|
CodeObject* code; // strong ref
|
||||||
|
|
||||||
|
c11_vector/*T=int*/ args; // indices in co->varnames
|
||||||
|
c11_vector/*T=KwArg*/ kwargs; // indices in co->varnames
|
||||||
|
|
||||||
|
int starred_arg; // index in co->varnames, -1 if no *arg
|
||||||
|
int starred_kwarg; // index in co->varnames, -1 if no **kwarg
|
||||||
|
bool nested; // whether this function is nested
|
||||||
|
|
||||||
|
const char* docstring; // docstring of this function (weak ref)
|
||||||
|
|
||||||
|
FuncType type;
|
||||||
|
c11_smallmap_n2i kw_to_index;
|
||||||
|
} FuncDecl;
|
||||||
|
|
||||||
|
typedef FuncDecl* FuncDecl_;
|
||||||
|
|
||||||
|
FuncDecl_ FuncDecl__rcnew(pkpy_SourceData_ src, c11_string name);
|
||||||
|
void FuncDecl__dtor(FuncDecl* self);
|
||||||
|
void FuncDecl__add_kwarg(FuncDecl* self, int index, uint16_t key, const PyVar* value);
|
||||||
|
void FuncDecl__gc_mark(const FuncDecl* self);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
@ -12,96 +12,6 @@ namespace pkpy {
|
|||||||
|
|
||||||
typedef PyVar (*NativeFuncC)(VM*, ArgsView);
|
typedef PyVar (*NativeFuncC)(VM*, ArgsView);
|
||||||
|
|
||||||
struct CodeObject;
|
|
||||||
struct FuncDecl;
|
|
||||||
using FuncDecl_ = std::shared_ptr<FuncDecl>;
|
|
||||||
|
|
||||||
struct CodeObject {
|
|
||||||
PK_ALWAYS_PASS_BY_POINTER(CodeObject)
|
|
||||||
|
|
||||||
struct LineInfo {
|
|
||||||
int lineno; // line number for each bytecode
|
|
||||||
bool is_virtual; // whether this bytecode is virtual (not in source code)
|
|
||||||
int iblock; // block index
|
|
||||||
};
|
|
||||||
|
|
||||||
pkpy_SourceData_ src;
|
|
||||||
Str name;
|
|
||||||
|
|
||||||
vector<Bytecode> codes;
|
|
||||||
vector<LineInfo> lines;
|
|
||||||
|
|
||||||
small_vector_2<PyVar, 8> consts; // constants
|
|
||||||
small_vector_2<StrName, 8> varnames; // local variables
|
|
||||||
int nlocals; // varnames.size()
|
|
||||||
|
|
||||||
c11_smallmap_n2i varnames_inv;
|
|
||||||
vector<CodeBlock> blocks;
|
|
||||||
c11_smallmap_n2i labels;
|
|
||||||
vector<FuncDecl_> func_decls;
|
|
||||||
|
|
||||||
int start_line;
|
|
||||||
int end_line;
|
|
||||||
|
|
||||||
void _gc_mark(VM*) const;
|
|
||||||
|
|
||||||
CodeObject(pkpy_SourceData_ src, const Str& name) :
|
|
||||||
src(src), name(name), nlocals(0), start_line(-1), end_line(-1) {
|
|
||||||
blocks.push_back(CodeBlock{CodeBlockType_NO_BLOCK, -1, 0, -1, -1});
|
|
||||||
c11_smallmap_n2i__ctor(&varnames_inv);
|
|
||||||
c11_smallmap_n2i__ctor(&labels);
|
|
||||||
PK_INCREF(src);
|
|
||||||
}
|
|
||||||
|
|
||||||
~CodeObject() {
|
|
||||||
c11_smallmap_n2i__dtor(&varnames_inv);
|
|
||||||
c11_smallmap_n2i__dtor(&labels);
|
|
||||||
PK_DECREF(src);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FuncDecl {
|
|
||||||
PK_ALWAYS_PASS_BY_POINTER(FuncDecl)
|
|
||||||
struct KwArg {
|
|
||||||
int index; // index in co->varnames
|
|
||||||
StrName key; // name of this argument
|
|
||||||
PyVar value; // default value
|
|
||||||
};
|
|
||||||
|
|
||||||
CodeObject* code; // strong ref
|
|
||||||
|
|
||||||
small_vector_2<int, 8> args; // indices in co->varnames
|
|
||||||
c11_vector/*T=KwArg*/ kwargs; // indices in co->varnames
|
|
||||||
|
|
||||||
int starred_arg = -1; // index in co->varnames, -1 if no *arg
|
|
||||||
int starred_kwarg = -1; // index in co->varnames, -1 if no **kwarg
|
|
||||||
bool nested = false; // whether this function is nested
|
|
||||||
|
|
||||||
const char* docstring; // docstring of this function (weak ref)
|
|
||||||
|
|
||||||
FuncType type = FuncType_UNSET;
|
|
||||||
c11_smallmap_n2i kw_to_index;
|
|
||||||
|
|
||||||
void add_kwarg(int index, StrName key, PyVar value) {
|
|
||||||
c11_smallmap_n2i__set(&kw_to_index, key.index, index);
|
|
||||||
c11_vector__push(KwArg, &kwargs, (KwArg{index, key.index, value}));
|
|
||||||
}
|
|
||||||
|
|
||||||
void _gc_mark(VM*) const;
|
|
||||||
|
|
||||||
FuncDecl(CodeObject* code){
|
|
||||||
this->code = code;
|
|
||||||
c11_vector__ctor(&kwargs, sizeof(KwArg));
|
|
||||||
c11_smallmap_n2i__ctor(&kw_to_index);
|
|
||||||
}
|
|
||||||
|
|
||||||
~FuncDecl(){
|
|
||||||
delete code;
|
|
||||||
c11_vector__dtor(&kwargs);
|
|
||||||
c11_smallmap_n2i__dtor(&kw_to_index);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct NativeFunc {
|
struct NativeFunc {
|
||||||
NativeFuncC f;
|
NativeFuncC f;
|
||||||
int argc; // old style argc-based call
|
int argc; // old style argc-based call
|
||||||
@ -117,6 +27,10 @@ struct NativeFunc {
|
|||||||
PyVar call(VM* vm, ArgsView args) const { return f(vm, args); }
|
PyVar call(VM* vm, ArgsView args) const { return f(vm, args); }
|
||||||
|
|
||||||
void _gc_mark(VM*) const;
|
void _gc_mark(VM*) const;
|
||||||
|
|
||||||
|
~NativeFunc() {
|
||||||
|
if(decl) PK_DECREF(decl);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Function {
|
struct Function {
|
||||||
@ -128,11 +42,14 @@ struct Function {
|
|||||||
NameDict* _closure; // strong ref
|
NameDict* _closure; // strong ref
|
||||||
|
|
||||||
Function(FuncDecl_ decl, PyObject* _module, PyObject* _class, NameDict* _closure) :
|
Function(FuncDecl_ decl, PyObject* _module, PyObject* _class, NameDict* _closure) :
|
||||||
decl(decl), _module(_module), _class(_class), _closure(_closure) {}
|
decl(decl), _module(_module), _class(_class), _closure(_closure) {
|
||||||
|
PK_INCREF(decl);
|
||||||
|
}
|
||||||
|
|
||||||
void _gc_mark(VM*) const;
|
void _gc_mark(VM*) const;
|
||||||
|
|
||||||
~Function() {
|
~Function() {
|
||||||
|
PK_DECREF(decl);
|
||||||
delete _closure;
|
delete _closure;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -25,14 +25,14 @@ void pkpy_SourceData__ctor(struct pkpy_SourceData* self,
|
|||||||
// Skip utf8 BOM if there is any.
|
// Skip utf8 BOM if there is any.
|
||||||
if (source.size >= 3 && strncmp(source.data, "\xEF\xBB\xBF", 3) == 0) index += 3;
|
if (source.size >= 3 && strncmp(source.data, "\xEF\xBB\xBF", 3) == 0) index += 3;
|
||||||
// Drop all '\r'
|
// Drop all '\r'
|
||||||
pkpy_SStream ss;
|
pk_SStream ss;
|
||||||
pkpy_SStream__ctor2(&ss, source.size + 1);
|
pk_SStream__ctor2(&ss, source.size + 1);
|
||||||
while(index < source.size){
|
while(index < source.size){
|
||||||
char c = source.data[index];
|
char c = source.data[index];
|
||||||
if(c != '\r') pkpy_SStream__write_char(&ss, c);
|
if(c != '\r') pk_SStream__write_char(&ss, c);
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
self->source = pkpy_SStream__submit(&ss);
|
self->source = pk_SStream__submit(&ss);
|
||||||
self->is_precompiled = (strncmp(pkpy_Str__data(&self->source), "pkpy:", 5) == 0);
|
self->is_precompiled = (strncmp(pkpy_Str__data(&self->source), "pkpy:", 5) == 0);
|
||||||
c11_vector__push(const char*, &self->line_starts, pkpy_Str__data(&self->source));
|
c11_vector__push(const char*, &self->line_starts, pkpy_Str__data(&self->source));
|
||||||
}
|
}
|
||||||
@ -63,46 +63,46 @@ bool pkpy_SourceData__get_line(const struct pkpy_SourceData* self, int lineno, c
|
|||||||
}
|
}
|
||||||
|
|
||||||
pkpy_Str pkpy_SourceData__snapshot(const struct pkpy_SourceData* self, int lineno, const char* cursor, const char* name) {
|
pkpy_Str pkpy_SourceData__snapshot(const struct pkpy_SourceData* self, int lineno, const char* cursor, const char* name) {
|
||||||
pkpy_SStream ss;
|
pk_SStream ss;
|
||||||
pkpy_SStream__ctor(&ss);
|
pk_SStream__ctor(&ss);
|
||||||
|
|
||||||
// pkpy_SStream__write_cstr(&ss, " File \"");
|
// pk_SStream__write_cstr(&ss, " File \"");
|
||||||
// pkpy_SStream__write_Str(&ss, &self->filename);
|
// pk_SStream__write_Str(&ss, &self->filename);
|
||||||
// pkpy_SStream__write_cstr(&ss, "\", line ");
|
// pk_SStream__write_cstr(&ss, "\", line ");
|
||||||
// pkpy_SStream__write_int(&ss, lineno);
|
// pk_SStream__write_int(&ss, lineno);
|
||||||
|
|
||||||
pkpy_SStream__write(&ss,
|
pk_SStream__write(&ss,
|
||||||
" File \"{}\", line {}",
|
" File \"{}\", line {}",
|
||||||
&self->filename,
|
&self->filename,
|
||||||
lineno
|
lineno
|
||||||
);
|
);
|
||||||
|
|
||||||
if(name && *name) {
|
if(name && *name) {
|
||||||
pkpy_SStream__write_cstr(&ss, ", in ");
|
pk_SStream__write_cstr(&ss, ", in ");
|
||||||
pkpy_SStream__write_cstr(&ss, name);
|
pk_SStream__write_cstr(&ss, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!self->is_precompiled) {
|
if(!self->is_precompiled) {
|
||||||
pkpy_SStream__write_char(&ss, '\n');
|
pk_SStream__write_char(&ss, '\n');
|
||||||
const char *st = NULL, *ed;
|
const char *st = NULL, *ed;
|
||||||
if(pkpy_SourceData__get_line(self, lineno, &st, &ed)) {
|
if(pkpy_SourceData__get_line(self, lineno, &st, &ed)) {
|
||||||
while(st < ed && isblank(*st))
|
while(st < ed && isblank(*st))
|
||||||
++st;
|
++st;
|
||||||
if(st < ed) {
|
if(st < ed) {
|
||||||
pkpy_SStream__write_cstr(&ss, " ");
|
pk_SStream__write_cstr(&ss, " ");
|
||||||
pkpy_SStream__write_cstrn(&ss, st, ed - st);
|
pk_SStream__write_cstrn(&ss, st, ed - st);
|
||||||
if(cursor && st <= cursor && cursor <= ed) {
|
if(cursor && st <= cursor && cursor <= ed) {
|
||||||
pkpy_SStream__write_cstr(&ss, "\n ");
|
pk_SStream__write_cstr(&ss, "\n ");
|
||||||
for(int i = 0; i < (cursor - st); ++i)
|
for(int i = 0; i < (cursor - st); ++i)
|
||||||
pkpy_SStream__write_char(&ss, ' ');
|
pk_SStream__write_char(&ss, ' ');
|
||||||
pkpy_SStream__write_cstr(&ss, "^");
|
pk_SStream__write_cstr(&ss, "^");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
st = NULL;
|
st = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!st) { pkpy_SStream__write_cstr(&ss, " <?>"); }
|
if(!st) { pk_SStream__write_cstr(&ss, " <?>"); }
|
||||||
}
|
}
|
||||||
return pkpy_SStream__submit(&ss);
|
return pk_SStream__submit(&ss);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "pocketpy/common/sstream.h"
|
#include "pocketpy/common/sstream.h"
|
||||||
|
#include "pocketpy/common/config.h"
|
||||||
#include "pocketpy/common/utils.h"
|
#include "pocketpy/common/utils.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -6,39 +7,39 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
void pkpy_SStream__ctor(pkpy_SStream* self) {
|
void pk_SStream__ctor(pk_SStream* self) {
|
||||||
c11_vector__ctor(&self->data, sizeof(char));
|
c11_vector__ctor(&self->data, sizeof(char));
|
||||||
}
|
}
|
||||||
|
|
||||||
void pkpy_SStream__ctor2(pkpy_SStream* self, int capacity) {
|
void pk_SStream__ctor2(pk_SStream* self, int capacity) {
|
||||||
c11_vector__ctor(&self->data, sizeof(char));
|
c11_vector__ctor(&self->data, sizeof(char));
|
||||||
c11_vector__reserve(&self->data, capacity);
|
c11_vector__reserve(&self->data, capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pkpy_SStream__dtor(pkpy_SStream* self) {
|
void pk_SStream__dtor(pk_SStream* self) {
|
||||||
c11_vector__dtor(&self->data);
|
c11_vector__dtor(&self->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pkpy_SStream__write_char(pkpy_SStream* self, char c) {
|
void pk_SStream__write_char(pk_SStream* self, char c) {
|
||||||
c11_vector__push(char, &self->data, c);
|
c11_vector__push(char, &self->data, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pkpy_SStream__write_int(pkpy_SStream* self, int i) {
|
void pk_SStream__write_int(pk_SStream* self, int i) {
|
||||||
char buf[12]; // sign + 10 digits + null terminator
|
char buf[12]; // sign + 10 digits + null terminator
|
||||||
snprintf(buf, sizeof(buf), "%d", i);
|
snprintf(buf, sizeof(buf), "%d", i);
|
||||||
pkpy_SStream__write_cstr(self, buf);
|
pk_SStream__write_cstr(self, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pkpy_SStream__write_i64(pkpy_SStream* self, int64_t val) {
|
void pk_SStream__write_i64(pk_SStream* self, int64_t val) {
|
||||||
// sign + 21 digits + null terminator
|
// sign + 21 digits + null terminator
|
||||||
// str(-2**64).__len__() == 21
|
// str(-2**64).__len__() == 21
|
||||||
c11_vector__reserve(&self->data, self->data.count + 23);
|
c11_vector__reserve(&self->data, self->data.count + 23);
|
||||||
if(val == 0){
|
if(val == 0){
|
||||||
pkpy_SStream__write_char(self, '0');
|
pk_SStream__write_char(self, '0');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(val < 0){
|
if(val < 0){
|
||||||
pkpy_SStream__write_char(self, '-');
|
pk_SStream__write_char(self, '-');
|
||||||
val = -val;
|
val = -val;
|
||||||
}
|
}
|
||||||
int start = self->data.count;
|
int start = self->data.count;
|
||||||
@ -50,17 +51,17 @@ void pkpy_SStream__write_i64(pkpy_SStream* self, int64_t val) {
|
|||||||
c11_vector__reverse(char, &self->data, start, end);
|
c11_vector__reverse(char, &self->data, start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pkpy_SStream__write_float(pkpy_SStream* self, float val, int precision){
|
void pk_SStream__write_float(pk_SStream* self, float val, int precision){
|
||||||
pkpy_SStream__write_double(self, val, precision);
|
pk_SStream__write_double(self, val, precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pkpy_SStream__write_double(pkpy_SStream* self, double val, int precision){
|
void pk_SStream__write_double(pk_SStream* self, double val, int precision){
|
||||||
if(isinf(val)) {
|
if(isinf(val)) {
|
||||||
pkpy_SStream__write_cstr(self, val > 0 ? "inf" : "-inf");
|
pk_SStream__write_cstr(self, val > 0 ? "inf" : "-inf");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(isnan(val)) {
|
if(isnan(val)) {
|
||||||
pkpy_SStream__write_cstr(self, "nan");
|
pk_SStream__write_cstr(self, "nan");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
char b[32];
|
char b[32];
|
||||||
@ -72,90 +73,102 @@ void pkpy_SStream__write_double(pkpy_SStream* self, double val, int precision){
|
|||||||
int prec = precision;
|
int prec = precision;
|
||||||
size = snprintf(b, sizeof(b), "%.*f", prec, val);
|
size = snprintf(b, sizeof(b), "%.*f", prec, val);
|
||||||
}
|
}
|
||||||
pkpy_SStream__write_cstr(self, b);
|
pk_SStream__write_cstr(self, b);
|
||||||
bool all_is_digit = true;
|
bool all_is_digit = true;
|
||||||
for(int i = 1; i < size; i++){
|
for(int i = 1; i < size; i++){
|
||||||
if(!isdigit(b[i])){ all_is_digit = false; break; }
|
if(!isdigit(b[i])){ all_is_digit = false; break; }
|
||||||
}
|
}
|
||||||
if(all_is_digit) pkpy_SStream__write_cstr(self, ".0");
|
if(all_is_digit) pk_SStream__write_cstr(self, ".0");
|
||||||
}
|
}
|
||||||
|
|
||||||
void pkpy_SStream__write_Str(pkpy_SStream* self, const pkpy_Str* str) {
|
void pk_SStream__write_Str(pk_SStream* self, const pkpy_Str* str) {
|
||||||
pkpy_SStream__write_cstrn(self, pkpy_Str__data(str), str->size);
|
pk_SStream__write_cstrn(self, pkpy_Str__data(str), str->size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pkpy_SStream__write_sv(pkpy_SStream* self, c11_string sv) {
|
void pk_SStream__write_sv(pk_SStream* self, c11_string sv) {
|
||||||
pkpy_SStream__write_cstrn(self, sv.data, sv.size);
|
pk_SStream__write_cstrn(self, sv.data, sv.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pkpy_SStream__write_cstr(pkpy_SStream* self, const char* str) {
|
void pk_SStream__write_cstr(pk_SStream* self, const char* str) {
|
||||||
pkpy_SStream__write_cstrn(self, str, strlen(str));
|
pk_SStream__write_cstrn(self, str, strlen(str));
|
||||||
}
|
}
|
||||||
|
|
||||||
void pkpy_SStream__write_cstrn(pkpy_SStream* self, const char* str, int n) {
|
void pk_SStream__write_cstrn(pk_SStream* self, const char* str, int n) {
|
||||||
c11_vector__extend(char, &self->data, str, n);
|
c11_vector__extend(char, &self->data, str, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pkpy_SStream__write_hex(pkpy_SStream* self, unsigned char c, bool non_zero) {
|
void pk_SStream__write_hex(pk_SStream* self, unsigned char c, bool non_zero) {
|
||||||
unsigned char high = c >> 4;
|
unsigned char high = c >> 4;
|
||||||
unsigned char low = c & 0xf;
|
unsigned char low = c & 0xf;
|
||||||
if(non_zero) {
|
if(non_zero) {
|
||||||
if(high) pkpy_SStream__write_char(self, PK_HEX_TABLE[high]);
|
if(high) pk_SStream__write_char(self, PK_HEX_TABLE[high]);
|
||||||
if(high || low) pkpy_SStream__write_char(self, PK_HEX_TABLE[low]);
|
if(high || low) pk_SStream__write_char(self, PK_HEX_TABLE[low]);
|
||||||
} else {
|
} else {
|
||||||
pkpy_SStream__write_char(self, PK_HEX_TABLE[high]);
|
pk_SStream__write_char(self, PK_HEX_TABLE[high]);
|
||||||
pkpy_SStream__write_char(self, PK_HEX_TABLE[low]);
|
pk_SStream__write_char(self, PK_HEX_TABLE[low]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pkpy_SStream__write_ptr(pkpy_SStream* self, void* p) {
|
void pk_SStream__write_ptr(pk_SStream* self, void* p) {
|
||||||
if(p == NULL) {
|
if(p == NULL) {
|
||||||
pkpy_SStream__write_cstr(self, "0x0");
|
pk_SStream__write_cstr(self, "0x0");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pkpy_SStream__write_cstr(self, "0x");
|
pk_SStream__write_cstr(self, "0x");
|
||||||
uintptr_t p_t = (uintptr_t)(p);
|
uintptr_t p_t = (uintptr_t)(p);
|
||||||
bool non_zero = true;
|
bool non_zero = true;
|
||||||
for(int i = sizeof(void*) - 1; i >= 0; i--) {
|
for(int i = sizeof(void*) - 1; i >= 0; i--) {
|
||||||
unsigned char cpnt = (p_t >> (i * 8)) & 0xff;
|
unsigned char cpnt = (p_t >> (i * 8)) & 0xff;
|
||||||
pkpy_SStream__write_hex(self, cpnt, non_zero);
|
pk_SStream__write_hex(self, cpnt, non_zero);
|
||||||
if(cpnt != 0) non_zero = false;
|
if(cpnt != 0) non_zero = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pkpy_SStream__write_any(pkpy_SStream* self, const char* fmt, const pkpy_AnyStr* args, int n){
|
void pk_SStream__write_any(pk_SStream* self, const char* fmt, const pk_AnyStr* args, int n){
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while(*fmt){
|
while(*fmt){
|
||||||
if(*fmt == '{' && fmt[1] == '}'){
|
if(*fmt == '{' && fmt[1] == '}'){
|
||||||
assert(i < n);
|
assert(i < n);
|
||||||
switch(args[i].type){
|
switch(args[i].type){
|
||||||
case 1: pkpy_SStream__write_int(self, args[i]._int); break;
|
case 1: pk_SStream__write_int(self, args[i]._int); break;
|
||||||
case 2: pkpy_SStream__write_i64(self, args[i]._i64); break;
|
case 2: pk_SStream__write_i64(self, args[i]._i64); break;
|
||||||
case 3: pkpy_SStream__write_float(self, args[i]._float, -1); break;
|
case 3: pk_SStream__write_float(self, args[i]._float, -1); break;
|
||||||
case 4: pkpy_SStream__write_double(self, args[i]._double, -1); break;
|
case 4: pk_SStream__write_double(self, args[i]._double, -1); break;
|
||||||
case 5: pkpy_SStream__write_char(self, args[i]._char); break;
|
case 5: pk_SStream__write_char(self, args[i]._char); break;
|
||||||
case 6: pkpy_SStream__write_Str(self, args[i]._str); break;
|
case 6: pk_SStream__write_Str(self, args[i]._str); break;
|
||||||
case 7: pkpy_SStream__write_sv(self, args[i]._sv); break;
|
case 7: pk_SStream__write_sv(self, args[i]._sv); break;
|
||||||
case 8: pkpy_SStream__write_cstr(self, args[i]._cstr); break;
|
case 8: pk_SStream__write_cstr(self, args[i]._cstr); break;
|
||||||
case 9: assert(0); break;
|
case 9: pk_SStream__write_ptr(self, args[i]._ptr); break;
|
||||||
default: assert(0); break;
|
default: assert(0); break;
|
||||||
}
|
}
|
||||||
fmt += 2;
|
fmt += 2;
|
||||||
i++;
|
i++;
|
||||||
}else{
|
}else{
|
||||||
pkpy_SStream__write_char(self, *fmt);
|
pk_SStream__write_char(self, *fmt);
|
||||||
fmt++;
|
fmt++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pkpy_Str pkpy_SStream__submit(pkpy_SStream* self) {
|
pkpy_Str pk_SStream__submit(pk_SStream* self) {
|
||||||
c11_vector__push(char, &self->data, '\0');
|
c11_vector__push(char, &self->data, '\0');
|
||||||
pkpy_Str retval = {
|
pkpy_Str retval = {
|
||||||
.size = self->data.count - 1,
|
.size = self->data.count - 1,
|
||||||
.is_ascii = false, // need to check
|
.is_ascii = c11__isascii((char*)self->data.data, self->data.count),
|
||||||
.is_sso = false,
|
.is_sso = false,
|
||||||
._ptr = (char*)self->data.data
|
._ptr = (char*)self->data.data
|
||||||
};
|
};
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* pk_format_any(const char* fmt, const pk_AnyStr* args, int n){
|
||||||
|
PK_THREAD_LOCAL pk_SStream ss;
|
||||||
|
if(ss.data.elem_size == 0){
|
||||||
|
pk_SStream__ctor2(&ss, 128);
|
||||||
|
}else{
|
||||||
|
c11_vector__clear(&ss.data);
|
||||||
|
}
|
||||||
|
pk_SStream__write_any(&ss, fmt, args, n);
|
||||||
|
pk_SStream__write_char(&ss, '\0');
|
||||||
|
return (const char*)ss.data.data;
|
||||||
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "pocketpy/compiler/compiler.hpp"
|
#include "pocketpy/compiler/compiler.hpp"
|
||||||
#include "pocketpy/common/config.h"
|
#include "pocketpy/common/config.h"
|
||||||
|
#include "pocketpy/compiler/expr.hpp"
|
||||||
#include "pocketpy/interpreter/vm.hpp"
|
#include "pocketpy/interpreter/vm.hpp"
|
||||||
#include "pocketpy/objects/codeobject.hpp"
|
#include "pocketpy/objects/codeobject.hpp"
|
||||||
|
|
||||||
@ -21,17 +22,21 @@ NameScope Compiler::name_scope() const noexcept{
|
|||||||
}
|
}
|
||||||
|
|
||||||
CodeObject* Compiler::push_global_context() noexcept{
|
CodeObject* Compiler::push_global_context() noexcept{
|
||||||
CodeObject* co = new CodeObject(lexer.src, static_cast<const Str&>(lexer.src->filename));
|
CodeObject* co = CodeObject__new(lexer.src, pkpy_Str__sv(&lexer.src->filename));
|
||||||
co->start_line = __i == 0 ? 1 : prev().line;
|
co->start_line = __i == 0 ? 1 : prev().line;
|
||||||
contexts.push_back(CodeEmitContext(vm, co, contexts.size()));
|
contexts.push_back(CodeEmitContext(vm, co, contexts.size()));
|
||||||
return co;
|
return co;
|
||||||
}
|
}
|
||||||
|
|
||||||
FuncDecl_ Compiler::push_f_context(Str name) noexcept{
|
FuncDecl_ Compiler::push_f_context(c11_string name, int* out_index) noexcept{
|
||||||
CodeObject* co = new CodeObject(lexer.src, name);
|
FuncDecl_ decl = FuncDecl__rcnew(lexer.src, name);
|
||||||
FuncDecl_ decl = std::make_shared<FuncDecl>(co);
|
|
||||||
decl->code->start_line = __i == 0 ? 1 : prev().line;
|
decl->code->start_line = __i == 0 ? 1 : prev().line;
|
||||||
decl->nested = name_scope() == NAME_LOCAL;
|
decl->nested = name_scope() == NAME_LOCAL;
|
||||||
|
// add_func_decl
|
||||||
|
CodeEmitContext* ctx = &contexts.back();
|
||||||
|
c11_vector__push(FuncDecl_, &ctx->co->func_decls, decl);
|
||||||
|
*out_index = ctx->co->func_decls.count - 1;
|
||||||
|
// push new context
|
||||||
contexts.push_back(CodeEmitContext(vm, decl->code, contexts.size()));
|
contexts.push_back(CodeEmitContext(vm, decl->code, contexts.size()));
|
||||||
contexts.back().func = decl;
|
contexts.back().func = decl;
|
||||||
return decl;
|
return decl;
|
||||||
@ -54,29 +59,29 @@ Error* Compiler::pop_context() noexcept{
|
|||||||
if(ctx()->co->nlocals > PK_MAX_CO_VARNAMES) {
|
if(ctx()->co->nlocals > PK_MAX_CO_VARNAMES) {
|
||||||
return SyntaxError("maximum number of local variables exceeded");
|
return SyntaxError("maximum number of local variables exceeded");
|
||||||
}
|
}
|
||||||
if(ctx()->co->consts.size() > 65530) {
|
if(ctx()->co->consts.count > 65530) {
|
||||||
return SyntaxError("maximum number of constants exceeded");
|
return SyntaxError("maximum number of constants exceeded");
|
||||||
}
|
}
|
||||||
// pre-compute LOOP_BREAK and LOOP_CONTINUE
|
// pre-compute LOOP_BREAK and LOOP_CONTINUE
|
||||||
for(int i = 0; i < codes.size(); i++) {
|
for(int i = 0; i < codes.count; i++) {
|
||||||
Bytecode& bc = codes[i];
|
Bytecode bc = c11__getitem(Bytecode, &codes, i);
|
||||||
if(bc.op == OP_LOOP_CONTINUE) {
|
if(bc.op == OP_LOOP_CONTINUE) {
|
||||||
CodeBlock* block = &ctx()->co->blocks[bc.arg];
|
CodeBlock* block = c11__at(CodeBlock, &ctx()->co->blocks, bc.arg);
|
||||||
Bytecode__set_signed_arg(&bc, block->start - i);
|
Bytecode__set_signed_arg(&bc, block->start - i);
|
||||||
} else if(bc.op == OP_LOOP_BREAK) {
|
} else if(bc.op == OP_LOOP_BREAK) {
|
||||||
CodeBlock* block = &ctx()->co->blocks[bc.arg];
|
CodeBlock* block = c11__at(CodeBlock, &ctx()->co->blocks, bc.arg);
|
||||||
Bytecode__set_signed_arg(&bc, (block->end2 != -1 ? block->end2 : block->end) - i);
|
Bytecode__set_signed_arg(&bc, (block->end2 != -1 ? block->end2 : block->end) - i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// pre-compute func->is_simple
|
// pre-compute func->is_simple
|
||||||
FuncDecl_ func = contexts.back().func;
|
FuncDecl* func = contexts.back().func;
|
||||||
if(func) {
|
if(func) {
|
||||||
// check generator
|
// check generator
|
||||||
for(Bytecode bc: func->code->codes) {
|
c11_vector__foreach(Bytecode, &func->code->codes, bc) {
|
||||||
if(bc.op == OP_YIELD_VALUE || bc.op == OP_FOR_ITER_YIELD_VALUE) {
|
if(bc->op == OP_YIELD_VALUE || bc->op == OP_FOR_ITER_YIELD_VALUE) {
|
||||||
func->type = FuncType_GENERATOR;
|
func->type = FuncType_GENERATOR;
|
||||||
for(Bytecode bc: func->code->codes) {
|
c11_vector__foreach(Bytecode, &func->code->codes, bc) {
|
||||||
if(bc.op == OP_RETURN_VALUE && bc.arg == BC_NOARG) {
|
if(bc->op == OP_RETURN_VALUE && bc->arg == BC_NOARG) {
|
||||||
return SyntaxError("'return' with argument inside generator function");
|
return SyntaxError("'return' with argument inside generator function");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -93,9 +98,11 @@ Error* Compiler::pop_context() noexcept{
|
|||||||
func->type = FuncType_SIMPLE;
|
func->type = FuncType_SIMPLE;
|
||||||
|
|
||||||
bool is_empty = false;
|
bool is_empty = false;
|
||||||
if(func->code->codes.size() == 1) {
|
if(func->code->codes.count == 1) {
|
||||||
Bytecode bc = func->code->codes[0];
|
Bytecode bc = c11__getitem(Bytecode, &func->code->codes, 0);
|
||||||
if(bc.op == OP_RETURN_VALUE && bc.arg == 1) { is_empty = true; }
|
if(bc.op == OP_RETURN_VALUE && bc.arg == 1) {
|
||||||
|
is_empty = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(is_empty) func->type = FuncType_EMPTY;
|
if(is_empty) func->type = FuncType_EMPTY;
|
||||||
} else
|
} else
|
||||||
@ -261,7 +268,8 @@ Error* Compiler::exprFString() noexcept{
|
|||||||
|
|
||||||
Error* Compiler::exprLambda() noexcept{
|
Error* Compiler::exprLambda() noexcept{
|
||||||
Error* err;
|
Error* err;
|
||||||
FuncDecl_ decl = push_f_context("<lambda>");
|
int decl_index;
|
||||||
|
FuncDecl_ decl = push_f_context({"<lambda>", 8}, &decl_index);
|
||||||
int line = prev().line; // backup line
|
int line = prev().line; // backup line
|
||||||
if(!match(TK_COLON)) {
|
if(!match(TK_COLON)) {
|
||||||
check(_compile_f_args(decl, false));
|
check(_compile_f_args(decl, false));
|
||||||
@ -272,7 +280,7 @@ Error* Compiler::exprLambda() noexcept{
|
|||||||
ctx()->s_emit_top();
|
ctx()->s_emit_top();
|
||||||
ctx()->emit_(OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE);
|
ctx()->emit_(OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE);
|
||||||
check(pop_context());
|
check(pop_context());
|
||||||
LambdaExpr* e = make_expr<LambdaExpr>(decl);
|
LambdaExpr* e = make_expr<LambdaExpr>(decl_index);
|
||||||
e->line = line;
|
e->line = line;
|
||||||
ctx()->s_push(e);
|
ctx()->s_push(e);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -744,7 +752,7 @@ Error* Compiler::compile_while_loop() noexcept{
|
|||||||
// optional else clause
|
// optional else clause
|
||||||
if(match(TK_ELSE)) {
|
if(match(TK_ELSE)) {
|
||||||
check(compile_block_body());
|
check(compile_block_body());
|
||||||
block->end2 = ctx()->co->codes.size();
|
block->end2 = ctx()->co->codes.count;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -769,7 +777,7 @@ Error* Compiler::compile_for_loop() noexcept{
|
|||||||
// optional else clause
|
// optional else clause
|
||||||
if(match(TK_ELSE)) {
|
if(match(TK_ELSE)) {
|
||||||
check(compile_block_body());
|
check(compile_block_body());
|
||||||
block->end2 = ctx()->co->codes.size();
|
block->end2 = ctx()->co->codes.count;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -815,17 +823,18 @@ Error* Compiler::compile_try_except() noexcept{
|
|||||||
|
|
||||||
if(match(TK_FINALLY)) {
|
if(match(TK_FINALLY)) {
|
||||||
int patch = ctx()->emit_(OP_JUMP_FORWARD, BC_NOARG, BC_KEEPLINE);
|
int patch = ctx()->emit_(OP_JUMP_FORWARD, BC_NOARG, BC_KEEPLINE);
|
||||||
finally_entry = ctx()->co->codes.size();
|
finally_entry = ctx()->co->codes.count;
|
||||||
check(compile_block_body());
|
check(compile_block_body());
|
||||||
ctx()->emit_(OP_JUMP_ABSOLUTE_TOP, BC_NOARG, BC_KEEPLINE);
|
ctx()->emit_(OP_JUMP_ABSOLUTE_TOP, BC_NOARG, BC_KEEPLINE);
|
||||||
ctx()->patch_jump(patch);
|
ctx()->patch_jump(patch);
|
||||||
}
|
}
|
||||||
// no match, re-raise
|
// no match, re-raise
|
||||||
if(finally_entry != -1) {
|
if(finally_entry != -1) {
|
||||||
i64 target = ctx()->co->codes.size() + 2;
|
i64 target = ctx()->co->codes.count + 2;
|
||||||
ctx()->emit_(OP_LOAD_CONST, ctx()->add_const(VAR(target)), BC_KEEPLINE);
|
ctx()->emit_(OP_LOAD_CONST, ctx()->add_const(VAR(target)), BC_KEEPLINE);
|
||||||
int i = ctx()->emit_(OP_JUMP_FORWARD, BC_NOARG, BC_KEEPLINE);
|
int i = ctx()->emit_(OP_JUMP_FORWARD, BC_NOARG, BC_KEEPLINE);
|
||||||
Bytecode__set_signed_arg(&ctx()->co->codes[i], finally_entry - i);
|
Bytecode* bc = c11__at(Bytecode, &ctx()->co->codes, i);
|
||||||
|
Bytecode__set_signed_arg(bc, finally_entry - i);
|
||||||
}
|
}
|
||||||
ctx()->emit_(OP_RE_RAISE, BC_NOARG, BC_KEEPLINE);
|
ctx()->emit_(OP_RE_RAISE, BC_NOARG, BC_KEEPLINE);
|
||||||
|
|
||||||
@ -833,10 +842,11 @@ Error* Compiler::compile_try_except() noexcept{
|
|||||||
for(int patch: patches)
|
for(int patch: patches)
|
||||||
ctx()->patch_jump(patch);
|
ctx()->patch_jump(patch);
|
||||||
if(finally_entry != -1) {
|
if(finally_entry != -1) {
|
||||||
i64 target = ctx()->co->codes.size() + 2;
|
i64 target = ctx()->co->codes.count + 2;
|
||||||
ctx()->emit_(OP_LOAD_CONST, ctx()->add_const(VAR(target)), BC_KEEPLINE);
|
ctx()->emit_(OP_LOAD_CONST, ctx()->add_const(VAR(target)), BC_KEEPLINE);
|
||||||
int i = ctx()->emit_(OP_JUMP_FORWARD, BC_NOARG, BC_KEEPLINE);
|
int i = ctx()->emit_(OP_JUMP_FORWARD, BC_NOARG, BC_KEEPLINE);
|
||||||
Bytecode__set_signed_arg(&ctx()->co->codes[i], finally_entry - i);
|
Bytecode* bc = c11__at(Bytecode, &ctx()->co->codes, i);
|
||||||
|
Bytecode__set_signed_arg(bc, finally_entry - i);
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -1144,7 +1154,7 @@ Error* Compiler::compile_class(int decorators) noexcept{
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Error* Compiler::_compile_f_args(FuncDecl_ decl, bool enable_type_hints) noexcept{
|
Error* Compiler::_compile_f_args(FuncDecl* decl, bool enable_type_hints) noexcept{
|
||||||
int state = 0; // 0 for args, 1 for *args, 2 for k=v, 3 for **kwargs
|
int state = 0; // 0 for args, 1 for *args, 2 for k=v, 3 for **kwargs
|
||||||
Error* err;
|
Error* err;
|
||||||
do {
|
do {
|
||||||
@ -1163,17 +1173,23 @@ Error* Compiler::_compile_f_args(FuncDecl_ decl, bool enable_type_hints) noexcep
|
|||||||
StrName name(prev().sv());
|
StrName name(prev().sv());
|
||||||
|
|
||||||
// check duplicate argument name
|
// check duplicate argument name
|
||||||
for(int j: decl->args) {
|
uint16_t tmp_name;
|
||||||
if(decl->code->varnames[j] == name) return SyntaxError("duplicate argument name");
|
c11_vector__foreach(int, &decl->args, j) {
|
||||||
|
tmp_name = c11__getitem(uint16_t, &decl->args, *j);
|
||||||
|
if(tmp_name == name.index) return SyntaxError("duplicate argument name");
|
||||||
}
|
}
|
||||||
c11_vector__foreach(FuncDecl::KwArg, &decl->kwargs, kv) {
|
c11_vector__foreach(FuncDeclKwArg, &decl->kwargs, kv) {
|
||||||
if(decl->code->varnames[kv->index] == name) return SyntaxError("duplicate argument name");
|
tmp_name = c11__getitem(uint16_t, &decl->code->varnames, kv->index);
|
||||||
|
if(tmp_name == name.index) return SyntaxError("duplicate argument name");
|
||||||
}
|
}
|
||||||
if(decl->starred_arg != -1 && decl->code->varnames[decl->starred_arg] == name) {
|
|
||||||
return SyntaxError("duplicate argument name");
|
if(decl->starred_arg != -1) {
|
||||||
|
tmp_name = c11__getitem(uint16_t, &decl->code->varnames, decl->starred_arg);
|
||||||
|
if(tmp_name == name.index) return SyntaxError("duplicate argument name");
|
||||||
}
|
}
|
||||||
if(decl->starred_kwarg != -1 && decl->code->varnames[decl->starred_kwarg] == name) {
|
if(decl->starred_kwarg != -1) {
|
||||||
return SyntaxError("duplicate argument name");
|
tmp_name = c11__getitem(uint16_t, &decl->code->varnames, decl->starred_kwarg);
|
||||||
|
if(tmp_name == name.index) return SyntaxError("duplicate argument name");
|
||||||
}
|
}
|
||||||
|
|
||||||
// eat type hints
|
// eat type hints
|
||||||
@ -1181,7 +1197,9 @@ Error* Compiler::_compile_f_args(FuncDecl_ decl, bool enable_type_hints) noexcep
|
|||||||
if(state == 0 && curr().type == TK_ASSIGN) state = 2;
|
if(state == 0 && curr().type == TK_ASSIGN) state = 2;
|
||||||
int index = ctx()->add_varname(name);
|
int index = ctx()->add_varname(name);
|
||||||
switch(state) {
|
switch(state) {
|
||||||
case 0: decl->args.push_back(index); break;
|
case 0:
|
||||||
|
c11_vector__push(int, &decl->args, index);
|
||||||
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
decl->starred_arg = index;
|
decl->starred_arg = index;
|
||||||
state += 1;
|
state += 1;
|
||||||
@ -1191,7 +1209,7 @@ Error* Compiler::_compile_f_args(FuncDecl_ decl, bool enable_type_hints) noexcep
|
|||||||
PyVar value;
|
PyVar value;
|
||||||
check(read_literal(&value));
|
check(read_literal(&value));
|
||||||
if(value == nullptr) return SyntaxError("default argument must be a literal");
|
if(value == nullptr) return SyntaxError("default argument must be a literal");
|
||||||
decl->add_kwarg(index, name, value);
|
FuncDecl__add_kwarg(decl, index, name.index, (const ::PyVar*)&value);
|
||||||
} break;
|
} break;
|
||||||
case 3:
|
case 3:
|
||||||
decl->starred_kwarg = index;
|
decl->starred_kwarg = index;
|
||||||
@ -1205,8 +1223,9 @@ Error* Compiler::_compile_f_args(FuncDecl_ decl, bool enable_type_hints) noexcep
|
|||||||
Error* Compiler::compile_function(int decorators) noexcept{
|
Error* Compiler::compile_function(int decorators) noexcept{
|
||||||
Error* err;
|
Error* err;
|
||||||
consume(TK_ID);
|
consume(TK_ID);
|
||||||
Str decl_name = prev().str();
|
std::string_view decl_name = prev().sv();
|
||||||
FuncDecl_ decl = push_f_context(decl_name);
|
int decl_index;
|
||||||
|
FuncDecl_ decl = push_f_context({decl_name.data(), (int)decl_name.size()}, &decl_index);
|
||||||
consume(TK_LPAREN);
|
consume(TK_LPAREN);
|
||||||
if(!match(TK_RPAREN)) {
|
if(!match(TK_RPAREN)) {
|
||||||
check(_compile_f_args(decl, true));
|
check(_compile_f_args(decl, true));
|
||||||
@ -1216,22 +1235,24 @@ Error* Compiler::compile_function(int decorators) noexcept{
|
|||||||
check(compile_block_body());
|
check(compile_block_body());
|
||||||
check(pop_context());
|
check(pop_context());
|
||||||
|
|
||||||
decl->docstring = nullptr;
|
if(decl->code->codes.count >= 2) {
|
||||||
if(decl->code->codes.size() >= 2 && decl->code->codes[0].op == OP_LOAD_CONST &&
|
Bytecode* codes = (Bytecode*)decl->code->codes.data;
|
||||||
decl->code->codes[1].op == OP_POP_TOP) {
|
if(codes[0].op == OP_LOAD_CONST && codes[1].op == OP_POP_TOP) {
|
||||||
PyVar c = decl->code->consts[decl->code->codes[0].arg];
|
// handle optional docstring
|
||||||
if(is_type(c, vm->tp_str)) {
|
PyVar* c = c11__at(PyVar, &decl->code->consts, codes[0].arg);
|
||||||
decl->code->codes[0].op = OP_NO_OP;
|
if(is_type(*c, vm->tp_str)) {
|
||||||
decl->code->codes[1].op = OP_NO_OP;
|
codes[0].op = OP_NO_OP;
|
||||||
decl->docstring = PK_OBJ_GET(Str, c).c_str();
|
codes[1].op = OP_NO_OP;
|
||||||
|
decl->docstring = PK_OBJ_GET(Str, *c).c_str();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ctx()->emit_(OP_LOAD_FUNCTION, ctx()->add_func_decl(decl), prev().line);
|
}
|
||||||
|
ctx()->emit_(OP_LOAD_FUNCTION, decl_index, prev().line);
|
||||||
|
|
||||||
ctx()->s_emit_decorators(decorators);
|
ctx()->s_emit_decorators(decorators);
|
||||||
|
|
||||||
if(!ctx()->is_compiling_class) {
|
if(!ctx()->is_compiling_class) {
|
||||||
NameExpr* e = make_expr<NameExpr>(decl_name, name_scope());
|
NameExpr* e = make_expr<NameExpr>(StrName(decl_name), name_scope());
|
||||||
e->emit_store(ctx());
|
e->emit_store(ctx());
|
||||||
delete_expr(e);
|
delete_expr(e);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "pocketpy/compiler/expr.hpp"
|
#include "pocketpy/compiler/expr.hpp"
|
||||||
#include "pocketpy/interpreter/vm.hpp"
|
#include "pocketpy/interpreter/vm.hpp"
|
||||||
|
#include "pocketpy/objects/codeobject.h"
|
||||||
|
#include "pocketpy/objects/public.h"
|
||||||
|
|
||||||
namespace pkpy {
|
namespace pkpy {
|
||||||
|
|
||||||
@ -16,23 +18,26 @@ inline bool is_small_int(i64 value) { return value >= INT16_MIN && value <= INT1
|
|||||||
int CodeEmitContext::get_loop() const noexcept{
|
int CodeEmitContext::get_loop() const noexcept{
|
||||||
int index = curr_iblock;
|
int index = curr_iblock;
|
||||||
while(index >= 0) {
|
while(index >= 0) {
|
||||||
if(co->blocks[index].type == CodeBlockType_FOR_LOOP) break;
|
CodeBlock* block = c11__at(CodeBlock, &co->blocks, index);
|
||||||
if(co->blocks[index].type == CodeBlockType_WHILE_LOOP) break;
|
if(block->type == CodeBlockType_FOR_LOOP) break;
|
||||||
index = co->blocks[index].parent;
|
if(block->type == CodeBlockType_WHILE_LOOP) break;
|
||||||
|
index = block->parent;
|
||||||
}
|
}
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
CodeBlock* CodeEmitContext::enter_block(CodeBlockType type) noexcept{
|
CodeBlock* CodeEmitContext::enter_block(CodeBlockType type) noexcept{
|
||||||
co->blocks.push_back(CodeBlock{type, curr_iblock, (int)co->codes.size(), -1, -1});
|
CodeBlock block = {type, curr_iblock, co->codes.count, -1, -1};
|
||||||
curr_iblock = co->blocks.size() - 1;
|
c11_vector__push(CodeBlock, &co->blocks, block);
|
||||||
return &co->blocks[curr_iblock];
|
curr_iblock = co->blocks.count - 1;
|
||||||
|
return c11__at(CodeBlock, &co->blocks, curr_iblock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeEmitContext::exit_block() noexcept{
|
void CodeEmitContext::exit_block() noexcept{
|
||||||
auto curr_type = co->blocks[curr_iblock].type;
|
CodeBlock* block = c11__at(CodeBlock, &co->blocks, curr_iblock);
|
||||||
co->blocks[curr_iblock].end = co->codes.size();
|
CodeBlockType curr_type = block->type;
|
||||||
curr_iblock = co->blocks[curr_iblock].parent;
|
block->end = co->codes.count;
|
||||||
|
curr_iblock = block->parent;
|
||||||
assert(curr_iblock >= 0);
|
assert(curr_iblock >= 0);
|
||||||
if(curr_type == CodeBlockType_FOR_LOOP) {
|
if(curr_type == CodeBlockType_FOR_LOOP) {
|
||||||
// add a no op here to make block check work
|
// add a no op here to make block check work
|
||||||
@ -55,38 +60,37 @@ void CodeEmitContext::s_emit_decorators(int count) noexcept{
|
|||||||
}
|
}
|
||||||
|
|
||||||
int CodeEmitContext::emit_(Opcode opcode, uint16_t arg, int line, bool is_virtual) noexcept{
|
int CodeEmitContext::emit_(Opcode opcode, uint16_t arg, int line, bool is_virtual) noexcept{
|
||||||
co->codes.push_back(Bytecode{(uint8_t)opcode, arg});
|
c11_vector__push(Bytecode, &co->codes, (Bytecode{(uint8_t)opcode, arg}));
|
||||||
co->lines.push_back(CodeObject::LineInfo{line, is_virtual, curr_iblock});
|
c11_vector__push(BytecodeEx, &co->codes_ex, (BytecodeEx{line, is_virtual, curr_iblock}));
|
||||||
int i = co->codes.size() - 1;
|
int i = co->codes.count - 1;
|
||||||
|
BytecodeEx* codes_ex = (BytecodeEx*)co->codes_ex.data;
|
||||||
if(line == BC_KEEPLINE) {
|
if(line == BC_KEEPLINE) {
|
||||||
if(i >= 1)
|
codes_ex[i].lineno = i>=1 ? codes_ex[i-1].lineno : 1;
|
||||||
co->lines[i].lineno = co->lines[i - 1].lineno;
|
|
||||||
else
|
|
||||||
co->lines[i].lineno = 1;
|
|
||||||
}
|
}
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeEmitContext::revert_last_emit_() noexcept{
|
void CodeEmitContext::revert_last_emit_() noexcept{
|
||||||
co->codes.pop_back();
|
c11_vector__pop(Bytecode, &co->codes);
|
||||||
co->lines.pop_back();
|
c11_vector__pop(BytecodeEx, &co->codes_ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeEmitContext::try_merge_for_iter_store(int i) noexcept{
|
void CodeEmitContext::try_merge_for_iter_store(int i) noexcept{
|
||||||
// [FOR_ITER, STORE_?, ]
|
// [FOR_ITER, STORE_?, ]
|
||||||
if(co->codes[i].op != OP_FOR_ITER) return;
|
Bytecode* co_codes = (Bytecode*)co->codes.data;
|
||||||
if(co->codes.size() - i != 2) return;
|
if(co_codes[i].op != OP_FOR_ITER) return;
|
||||||
uint16_t arg = co->codes[i + 1].arg;
|
if(co->codes.count - i != 2) return;
|
||||||
if(co->codes[i + 1].op == OP_STORE_FAST) {
|
uint16_t arg = co_codes[i + 1].arg;
|
||||||
|
if(co_codes[i + 1].op == OP_STORE_FAST) {
|
||||||
revert_last_emit_();
|
revert_last_emit_();
|
||||||
co->codes[i].op = OP_FOR_ITER_STORE_FAST;
|
co_codes[i].op = OP_FOR_ITER_STORE_FAST;
|
||||||
co->codes[i].arg = arg;
|
co_codes[i].arg = arg;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(co->codes[i + 1].op == OP_STORE_GLOBAL) {
|
if(co_codes[i + 1].op == OP_STORE_GLOBAL) {
|
||||||
revert_last_emit_();
|
revert_last_emit_();
|
||||||
co->codes[i].op = OP_FOR_ITER_STORE_GLOBAL;
|
co_codes[i].op = OP_FOR_ITER_STORE_GLOBAL;
|
||||||
co->codes[i].arg = arg;
|
co_codes[i].arg = arg;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -100,14 +104,15 @@ int CodeEmitContext::emit_int(i64 value, int line) noexcept{
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CodeEmitContext::patch_jump(int index) noexcept{
|
void CodeEmitContext::patch_jump(int index) noexcept{
|
||||||
int target = co->codes.size();
|
Bytecode* co_codes = (Bytecode*)co->codes.data;
|
||||||
Bytecode__set_signed_arg(&co->codes[index], target - index);
|
int target = co->codes.count;
|
||||||
|
Bytecode__set_signed_arg(&co_codes[index], target - index);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CodeEmitContext::add_label(StrName name) noexcept{
|
bool CodeEmitContext::add_label(StrName name) noexcept{
|
||||||
bool ok = c11_smallmap_n2i__contains(&co->labels, name.index);
|
bool ok = c11_smallmap_n2i__contains(&co->labels, name.index);
|
||||||
if(ok) return false;
|
if(ok) return false;
|
||||||
c11_smallmap_n2i__set(&co->labels, name.index, co->codes.size());
|
c11_smallmap_n2i__set(&co->labels, name.index, co->codes.count);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,9 +120,9 @@ int CodeEmitContext::add_varname(StrName name) noexcept{
|
|||||||
// PK_MAX_CO_VARNAMES will be checked when pop_context(), not here
|
// PK_MAX_CO_VARNAMES will be checked when pop_context(), not here
|
||||||
int index = c11_smallmap_n2i__get(&co->varnames_inv, name.index, -1);
|
int index = c11_smallmap_n2i__get(&co->varnames_inv, name.index, -1);
|
||||||
if(index >= 0) return index;
|
if(index >= 0) return index;
|
||||||
co->varnames.push_back(name);
|
c11_vector__push(uint16_t, &co->varnames, name.index);
|
||||||
co->nlocals++;
|
co->nlocals++;
|
||||||
index = co->varnames.size() - 1;
|
index = co->varnames.count - 1;
|
||||||
c11_smallmap_n2i__set(&co->varnames_inv, name.index, index);
|
c11_smallmap_n2i__set(&co->varnames_inv, name.index, index);
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
@ -127,9 +132,10 @@ int CodeEmitContext::add_const_string(std::string_view key) noexcept{
|
|||||||
if(val) {
|
if(val) {
|
||||||
return *val;
|
return *val;
|
||||||
} else {
|
} else {
|
||||||
co->consts.push_back(VAR(key));
|
// co->consts.push_back(VAR(key));
|
||||||
int index = co->consts.size() - 1;
|
c11_vector__push(PyVar, &co->consts, VAR(key));
|
||||||
key = co->consts.back().obj_get<Str>().sv();
|
int index = co->consts.count - 1;
|
||||||
|
key = c11__getitem(PyVar, &co->consts, index).obj_get<Str>().sv();
|
||||||
c11_smallmap_s2n__set(&_co_consts_string_dedup_map, {key.data(), (int)key.size()}, index);
|
c11_smallmap_s2n__set(&_co_consts_string_dedup_map, {key.data(), (int)key.size()}, index);
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
@ -137,14 +143,8 @@ int CodeEmitContext::add_const_string(std::string_view key) noexcept{
|
|||||||
|
|
||||||
int CodeEmitContext::add_const(PyVar v) noexcept{
|
int CodeEmitContext::add_const(PyVar v) noexcept{
|
||||||
assert(!is_type(v, VM::tp_str));
|
assert(!is_type(v, VM::tp_str));
|
||||||
co->consts.push_back(v);
|
c11_vector__push(PyVar, &co->consts, v);
|
||||||
int index = co->consts.size() - 1;
|
return co->consts.count - 1;
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
int CodeEmitContext::add_func_decl(FuncDecl_ decl) noexcept{
|
|
||||||
co->func_decls.push_back(decl);
|
|
||||||
return co->func_decls.size() - 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeEmitContext::emit_store_name(NameScope scope, StrName name, int line) noexcept{
|
void CodeEmitContext::emit_store_name(NameScope scope, StrName name, int line) noexcept{
|
||||||
@ -340,14 +340,14 @@ bool TupleExpr::emit_store(CodeEmitContext* ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(starred_i == -1) {
|
if(starred_i == -1) {
|
||||||
Bytecode& prev = ctx->co->codes.back();
|
Bytecode* prev = c11__at(Bytecode, &ctx->co->codes, ctx->co->codes.count - 1);
|
||||||
if(prev.op == OP_BUILD_TUPLE && prev.arg == items.size()) {
|
if(prev->op == OP_BUILD_TUPLE && prev->arg == items.size()) {
|
||||||
// build tuple and unpack it is meaningless
|
// build tuple and unpack it is meaningless
|
||||||
ctx->revert_last_emit_();
|
ctx->revert_last_emit_();
|
||||||
} else {
|
} else {
|
||||||
if(prev.op == OP_FOR_ITER) {
|
if(prev->op == OP_FOR_ITER) {
|
||||||
prev.op = OP_FOR_ITER_UNPACK;
|
prev->op = OP_FOR_ITER_UNPACK;
|
||||||
prev.arg = items.size();
|
prev->arg = items.size();
|
||||||
} else {
|
} else {
|
||||||
ctx->emit_(OP_UNPACK_SEQUENCE, items.size(), line);
|
ctx->emit_(OP_UNPACK_SEQUENCE, items.size(), line);
|
||||||
}
|
}
|
||||||
@ -543,7 +543,7 @@ void FStringExpr::emit_(CodeEmitContext* ctx) {
|
|||||||
void SubscrExpr::emit_(CodeEmitContext* ctx) {
|
void SubscrExpr::emit_(CodeEmitContext* ctx) {
|
||||||
lhs->emit_(ctx);
|
lhs->emit_(ctx);
|
||||||
rhs->emit_(ctx);
|
rhs->emit_(ctx);
|
||||||
Bytecode last_bc = ctx->co->codes.back();
|
Bytecode last_bc = c11__getitem(Bytecode, &ctx->co->codes, ctx->co->codes.count-1);
|
||||||
if(rhs->is_name() && last_bc.op == OP_LOAD_FAST) {
|
if(rhs->is_name() && last_bc.op == OP_LOAD_FAST) {
|
||||||
ctx->revert_last_emit_();
|
ctx->revert_last_emit_();
|
||||||
ctx->emit_(OP_LOAD_SUBSCR_FAST, last_bc.arg, line);
|
ctx->emit_(OP_LOAD_SUBSCR_FAST, last_bc.arg, line);
|
||||||
@ -558,7 +558,7 @@ void SubscrExpr::emit_(CodeEmitContext* ctx) {
|
|||||||
bool SubscrExpr::emit_store(CodeEmitContext* ctx) {
|
bool SubscrExpr::emit_store(CodeEmitContext* ctx) {
|
||||||
lhs->emit_(ctx);
|
lhs->emit_(ctx);
|
||||||
rhs->emit_(ctx);
|
rhs->emit_(ctx);
|
||||||
Bytecode last_bc = ctx->co->codes.back();
|
Bytecode last_bc = c11__getitem(Bytecode, &ctx->co->codes, ctx->co->codes.count-1);
|
||||||
if(rhs->is_name() && last_bc.op == OP_LOAD_FAST) {
|
if(rhs->is_name() && last_bc.op == OP_LOAD_FAST) {
|
||||||
ctx->revert_last_emit_();
|
ctx->revert_last_emit_();
|
||||||
ctx->emit_(OP_STORE_SUBSCR_FAST, last_bc.arg, line);
|
ctx->emit_(OP_STORE_SUBSCR_FAST, last_bc.arg, line);
|
||||||
|
18
src/error.c
18
src/error.c
@ -34,26 +34,26 @@ void pkpy_Exception__stpush(pkpy_Exception* self, pkpy_SourceData_ src, int line
|
|||||||
}
|
}
|
||||||
|
|
||||||
pkpy_Str pkpy_Exception__summary(pkpy_Exception* self){
|
pkpy_Str pkpy_Exception__summary(pkpy_Exception* self){
|
||||||
pkpy_SStream ss;
|
pk_SStream ss;
|
||||||
pkpy_SStream__ctor(&ss);
|
pk_SStream__ctor(&ss);
|
||||||
|
|
||||||
if(self->is_re){
|
if(self->is_re){
|
||||||
pkpy_SStream__write_cstr(&ss, "Traceback (most recent call last):\n");
|
pk_SStream__write_cstr(&ss, "Traceback (most recent call last):\n");
|
||||||
}
|
}
|
||||||
for(int i=self->stacktrace.count-1; i >= 0; i--) {
|
for(int i=self->stacktrace.count-1; i >= 0; i--) {
|
||||||
pkpy_ExceptionFrame* frame = c11__at(pkpy_ExceptionFrame, &self->stacktrace, i);
|
pkpy_ExceptionFrame* frame = c11__at(pkpy_ExceptionFrame, &self->stacktrace, i);
|
||||||
pkpy_Str s = pkpy_SourceData__snapshot(frame->src, frame->lineno, frame->cursor, pkpy_Str__data(&frame->name));
|
pkpy_Str s = pkpy_SourceData__snapshot(frame->src, frame->lineno, frame->cursor, pkpy_Str__data(&frame->name));
|
||||||
pkpy_SStream__write_Str(&ss, &s);
|
pk_SStream__write_Str(&ss, &s);
|
||||||
pkpy_Str__dtor(&s);
|
pkpy_Str__dtor(&s);
|
||||||
pkpy_SStream__write_cstr(&ss, "\n");
|
pk_SStream__write_cstr(&ss, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* name = pkpy_StrName__rmap(self->type);
|
const char* name = pkpy_StrName__rmap(self->type);
|
||||||
pkpy_SStream__write_cstr(&ss, name);
|
pk_SStream__write_cstr(&ss, name);
|
||||||
|
|
||||||
if(self->msg.size > 0){
|
if(self->msg.size > 0){
|
||||||
pkpy_SStream__write_cstr(&ss, ": ");
|
pk_SStream__write_cstr(&ss, ": ");
|
||||||
pkpy_SStream__write_Str(&ss, &self->msg);
|
pk_SStream__write_Str(&ss, &self->msg);
|
||||||
}
|
}
|
||||||
return pkpy_SStream__submit(&ss);
|
return pk_SStream__submit(&ss);
|
||||||
}
|
}
|
@ -115,7 +115,7 @@ bool VM::py_ge(PyVar _0, PyVar _1) {
|
|||||||
}
|
}
|
||||||
#define DISPATCH_JUMP_ABSOLUTE(__target) \
|
#define DISPATCH_JUMP_ABSOLUTE(__target) \
|
||||||
{ \
|
{ \
|
||||||
frame->_ip = &frame->co->codes[__target]; \
|
frame->_ip = c11__at(Bytecode, &frame->co->codes, __target); \
|
||||||
goto __NEXT_STEP; \
|
goto __NEXT_STEP; \
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,7 +136,7 @@ PyVar VM::__run_top_frame() {
|
|||||||
frame->_ip++;
|
frame->_ip++;
|
||||||
} else if(__internal_exception.type == InternalExceptionType::Handled) {
|
} else if(__internal_exception.type == InternalExceptionType::Handled) {
|
||||||
// HandledException + continue
|
// HandledException + continue
|
||||||
frame->_ip = &frame->co->codes[__internal_exception.arg];
|
frame->_ip = c11__at(Bytecode, &frame->co->codes, __internal_exception.arg);
|
||||||
__internal_exception = {};
|
__internal_exception = {};
|
||||||
} else {
|
} else {
|
||||||
// UnhandledException + continue (need_raise = true)
|
// UnhandledException + continue (need_raise = true)
|
||||||
@ -176,7 +176,9 @@ PyVar VM::__run_top_frame() {
|
|||||||
POP();
|
POP();
|
||||||
DISPATCH()
|
DISPATCH()
|
||||||
/*****************************************/
|
/*****************************************/
|
||||||
case OP_LOAD_CONST: PUSH(frame->co->consts[byte.arg]); DISPATCH()
|
case OP_LOAD_CONST:
|
||||||
|
PUSH(c11__getitem(PyVar, &frame->co->consts, byte.arg));
|
||||||
|
DISPATCH()
|
||||||
case OP_LOAD_NONE: PUSH(None); DISPATCH()
|
case OP_LOAD_NONE: PUSH(None); DISPATCH()
|
||||||
case OP_LOAD_TRUE: PUSH(True); DISPATCH()
|
case OP_LOAD_TRUE: PUSH(True); DISPATCH()
|
||||||
case OP_LOAD_FALSE: PUSH(False); DISPATCH()
|
case OP_LOAD_FALSE: PUSH(False); DISPATCH()
|
||||||
@ -185,12 +187,13 @@ PyVar VM::__run_top_frame() {
|
|||||||
/*****************************************/
|
/*****************************************/
|
||||||
case OP_LOAD_ELLIPSIS: PUSH(Ellipsis); DISPATCH()
|
case OP_LOAD_ELLIPSIS: PUSH(Ellipsis); DISPATCH()
|
||||||
case OP_LOAD_FUNCTION: {
|
case OP_LOAD_FUNCTION: {
|
||||||
const FuncDecl_& decl = frame->co->func_decls[byte.arg];
|
FuncDecl_ decl = c11__getitem(FuncDecl_, &frame->co->func_decls, byte.arg);
|
||||||
PyVar obj;
|
PyVar obj;
|
||||||
if(decl->nested) {
|
if(decl->nested) {
|
||||||
NameDict* captured = frame->_locals.to_namedict();
|
NameDict* captured = frame->_locals.to_namedict();
|
||||||
obj = new_object<Function>(tp_function, decl, frame->_module, nullptr, captured);
|
obj = new_object<Function>(tp_function, decl, frame->_module, nullptr, captured);
|
||||||
captured->set(decl->code->name, obj);
|
uint16_t name = pkpy_StrName__map2(pkpy_Str__sv(&decl->code->name));
|
||||||
|
captured->set(name, obj);
|
||||||
} else {
|
} else {
|
||||||
obj = new_object<Function>(tp_function, decl, frame->_module, nullptr, nullptr);
|
obj = new_object<Function>(tp_function, decl, frame->_module, nullptr, nullptr);
|
||||||
}
|
}
|
||||||
@ -201,7 +204,7 @@ PyVar VM::__run_top_frame() {
|
|||||||
/*****************************************/
|
/*****************************************/
|
||||||
case OP_LOAD_FAST: {
|
case OP_LOAD_FAST: {
|
||||||
PyVar _0 = frame->_locals[byte.arg];
|
PyVar _0 = frame->_locals[byte.arg];
|
||||||
if(_0 == PY_NULL) vm->UnboundLocalError(frame->co->varnames[byte.arg]);
|
if(_0 == PY_NULL) vm->UnboundLocalError(c11__getitem(uint16_t, &frame->co->varnames, byte.arg));
|
||||||
PUSH(_0);
|
PUSH(_0);
|
||||||
}
|
}
|
||||||
DISPATCH()
|
DISPATCH()
|
||||||
@ -311,7 +314,7 @@ PyVar VM::__run_top_frame() {
|
|||||||
DISPATCH()
|
DISPATCH()
|
||||||
case OP_LOAD_SUBSCR_FAST: {
|
case OP_LOAD_SUBSCR_FAST: {
|
||||||
PyVar _1 = frame->_locals[byte.arg];
|
PyVar _1 = frame->_locals[byte.arg];
|
||||||
if(_1 == PY_NULL) vm->UnboundLocalError(frame->co->varnames[byte.arg]);
|
if(_1 == PY_NULL) vm->UnboundLocalError(c11__getitem(uint16_t, &frame->co->varnames, byte.arg));
|
||||||
PyVar _0 = TOP(); // a
|
PyVar _0 = TOP(); // a
|
||||||
auto _ti = _tp_info(_0);
|
auto _ti = _tp_info(_0);
|
||||||
if(_ti->m__getitem__) {
|
if(_ti->m__getitem__) {
|
||||||
@ -376,7 +379,7 @@ PyVar VM::__run_top_frame() {
|
|||||||
DISPATCH()
|
DISPATCH()
|
||||||
case OP_STORE_SUBSCR_FAST: {
|
case OP_STORE_SUBSCR_FAST: {
|
||||||
PyVar _2 = frame->_locals[byte.arg]; // b
|
PyVar _2 = frame->_locals[byte.arg]; // b
|
||||||
if(_2 == PY_NULL) vm->UnboundLocalError(frame->co->varnames[byte.arg]);
|
if(_2 == PY_NULL) vm->UnboundLocalError(c11__getitem(uint16_t, &frame->co->varnames, byte.arg));
|
||||||
PyVar _1 = POPX(); // a
|
PyVar _1 = POPX(); // a
|
||||||
PyVar _0 = POPX(); // val
|
PyVar _0 = POPX(); // val
|
||||||
auto _ti = _tp_info(_1);
|
auto _ti = _tp_info(_1);
|
||||||
@ -389,7 +392,7 @@ PyVar VM::__run_top_frame() {
|
|||||||
DISPATCH()
|
DISPATCH()
|
||||||
case OP_DELETE_FAST: {
|
case OP_DELETE_FAST: {
|
||||||
PyVar _0 = frame->_locals[byte.arg];
|
PyVar _0 = frame->_locals[byte.arg];
|
||||||
if(_0 == PY_NULL) vm->UnboundLocalError(frame->co->varnames[byte.arg]);
|
if(_0 == PY_NULL) vm->UnboundLocalError(c11__getitem(uint16_t, &frame->co->varnames, byte.arg));
|
||||||
frame->_locals[byte.arg].set_null();
|
frame->_locals[byte.arg].set_null();
|
||||||
}
|
}
|
||||||
DISPATCH()
|
DISPATCH()
|
||||||
@ -792,12 +795,12 @@ PyVar VM::__run_top_frame() {
|
|||||||
}
|
}
|
||||||
/*****************************************/
|
/*****************************************/
|
||||||
case OP_FSTRING_EVAL: {
|
case OP_FSTRING_EVAL: {
|
||||||
PyVar _0 = frame->co->consts[byte.arg];
|
PyVar _0 = c11__getitem(PyVar, &frame->co->consts, byte.arg);
|
||||||
std::string_view string = CAST(Str&, _0).sv();
|
std::string_view string = CAST(Str&, _0).sv();
|
||||||
// TODO: optimize this
|
// TODO: optimize this
|
||||||
CodeObject* code = vm->compile(string, "<eval>", EVAL_MODE, true);
|
CodeObject* code = vm->compile(string, "<eval>", EVAL_MODE, true);
|
||||||
_0 = vm->_exec(code, frame->_module, frame->_callable, frame->_locals);
|
_0 = vm->_exec(code, frame->_module, frame->_callable, frame->_locals);
|
||||||
delete code; // leak on error
|
CodeObject__delete(code);
|
||||||
PUSH(_0);
|
PUSH(_0);
|
||||||
}
|
}
|
||||||
DISPATCH()
|
DISPATCH()
|
||||||
@ -968,7 +971,7 @@ PyVar VM::__run_top_frame() {
|
|||||||
DISPATCH()
|
DISPATCH()
|
||||||
/*****************************************/
|
/*****************************************/
|
||||||
case OP_IMPORT_PATH: {
|
case OP_IMPORT_PATH: {
|
||||||
PyVar _0 = frame->co->consts[byte.arg];
|
PyVar _0 = c11__getitem(PyVar, &frame->co->consts, byte.arg);
|
||||||
PUSH(py_import(CAST(Str&, _0)));
|
PUSH(py_import(CAST(Str&, _0)));
|
||||||
}
|
}
|
||||||
DISPATCH()
|
DISPATCH()
|
||||||
@ -1103,7 +1106,7 @@ PyVar VM::__run_top_frame() {
|
|||||||
/*****************************************/
|
/*****************************************/
|
||||||
case OP_FORMAT_STRING: {
|
case OP_FORMAT_STRING: {
|
||||||
PyVar _0 = POPX();
|
PyVar _0 = POPX();
|
||||||
const Str& spec = CAST(Str&, frame->co->consts[byte.arg]);
|
const Str& spec = CAST(Str&, c11__getitem(PyVar, &frame->co->consts, byte.arg));
|
||||||
PUSH(__format_object(_0, spec));
|
PUSH(__format_object(_0, spec));
|
||||||
}
|
}
|
||||||
DISPATCH()
|
DISPATCH()
|
||||||
|
@ -27,32 +27,33 @@ PyVar* Frame::f_closure_try_get(StrName name) {
|
|||||||
|
|
||||||
int Frame::prepare_jump_exception_handler(ValueStack* _s) {
|
int Frame::prepare_jump_exception_handler(ValueStack* _s) {
|
||||||
// try to find a parent try block
|
// try to find a parent try block
|
||||||
int i = co->lines[ip()].iblock;
|
int i = c11__at(BytecodeEx, &co->codes_ex, ip())->iblock;
|
||||||
while(i >= 0) {
|
while(i >= 0) {
|
||||||
if(co->blocks[i].type == CodeBlockType_TRY_EXCEPT) break;
|
CodeBlock* block = c11__at(CodeBlock, &co->blocks, i);
|
||||||
i = co->blocks[i].parent;
|
if(block->type == CodeBlockType_TRY_EXCEPT) break;
|
||||||
|
i = block->parent;
|
||||||
}
|
}
|
||||||
if(i < 0) return -1;
|
if(i < 0) return -1;
|
||||||
PyVar obj = _s->popx(); // pop exception object
|
PyVar obj = _s->popx(); // pop exception object
|
||||||
UnwindTarget* uw = find_unwind_target(i);
|
UnwindTarget* uw = find_unwind_target(i);
|
||||||
_s->reset(actual_sp_base() + uw->offset); // unwind the stack
|
_s->reset(actual_sp_base() + uw->offset); // unwind the stack
|
||||||
_s->push(obj); // push it back
|
_s->push(obj); // push it back
|
||||||
return co->blocks[i].end;
|
return c11__at(CodeBlock, &co->blocks, i)->end;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Frame::_exit_block(ValueStack* _s, int i) {
|
int Frame::_exit_block(ValueStack* _s, int i) {
|
||||||
auto type = co->blocks[i].type;
|
CodeBlock* block = c11__at(CodeBlock, &co->blocks, i);
|
||||||
if(type == CodeBlockType_FOR_LOOP) {
|
if(block->type == CodeBlockType_FOR_LOOP) {
|
||||||
_s->pop(); // pop the iterator
|
_s->pop(); // pop the iterator
|
||||||
} else if(type == CodeBlockType_CONTEXT_MANAGER) {
|
} else if(block->type == CodeBlockType_CONTEXT_MANAGER) {
|
||||||
_s->pop();
|
_s->pop();
|
||||||
}
|
}
|
||||||
return co->blocks[i].parent;
|
return block->parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Frame::prepare_jump_break(ValueStack* _s, int target) {
|
void Frame::prepare_jump_break(ValueStack* _s, int target) {
|
||||||
int i = co->lines[ip()].iblock;
|
int i = c11__at(BytecodeEx, &co->codes_ex, ip())->iblock;
|
||||||
if(target >= co->codes.size()) {
|
if(target >= co->codes.count) {
|
||||||
while(i >= 0)
|
while(i >= 0)
|
||||||
i = _exit_block(_s, i);
|
i = _exit_block(_s, i);
|
||||||
} else {
|
} else {
|
||||||
@ -61,7 +62,7 @@ void Frame::prepare_jump_break(ValueStack* _s, int target) {
|
|||||||
// _ = 0
|
// _ = 0
|
||||||
// # if there is no op here, the block check will fail
|
// # if there is no op here, the block check will fail
|
||||||
// while i: --i
|
// while i: --i
|
||||||
int next_block = co->lines[target].iblock;
|
int next_block = c11__at(BytecodeEx, &co->codes_ex, target)->iblock;
|
||||||
while(i >= 0 && i != next_block)
|
while(i >= 0 && i != next_block)
|
||||||
i = _exit_block(_s, i);
|
i = _exit_block(_s, i);
|
||||||
assert(i == next_block);
|
assert(i == next_block);
|
||||||
@ -69,7 +70,7 @@ void Frame::prepare_jump_break(ValueStack* _s, int target) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Frame::set_unwind_target(PyVar* _sp) {
|
void Frame::set_unwind_target(PyVar* _sp) {
|
||||||
int iblock = co->lines[ip()].iblock;
|
int iblock = c11__at(BytecodeEx, &co->codes_ex, ip())->iblock;
|
||||||
UnwindTarget* existing = find_unwind_target(iblock);
|
UnwindTarget* existing = find_unwind_target(iblock);
|
||||||
if(existing) {
|
if(existing) {
|
||||||
existing->offset = _sp - actual_sp_base();
|
existing->offset = _sp - actual_sp_base();
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "pocketpy/interpreter/vm.hpp"
|
#include "pocketpy/interpreter/vm.hpp"
|
||||||
#include "pocketpy/common/memorypool.h"
|
#include "pocketpy/common/memorypool.h"
|
||||||
#include "pocketpy/objects/base.h"
|
#include "pocketpy/objects/base.h"
|
||||||
|
#include "pocketpy/objects/codeobject.h"
|
||||||
#include "pocketpy/objects/public.h"
|
#include "pocketpy/objects/public.h"
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
@ -209,7 +210,7 @@ PyVar VM::exec(std::string_view source, Str filename, CompileMode mode, PyObject
|
|||||||
#endif
|
#endif
|
||||||
code = compile(source, filename, mode);
|
code = compile(source, filename, mode);
|
||||||
PyVar retval = _exec(code, _module);
|
PyVar retval = _exec(code, _module);
|
||||||
delete code; // leak if exception occurs
|
CodeObject__delete(code);
|
||||||
return retval;
|
return retval;
|
||||||
} catch(TopLevelException e) {
|
} catch(TopLevelException e) {
|
||||||
stderr_write(e.summary() + "\n");
|
stderr_write(e.summary() + "\n");
|
||||||
@ -221,7 +222,7 @@ PyVar VM::exec(std::string_view source, Str filename, CompileMode mode, PyObject
|
|||||||
Str msg = "An unknown exception occurred! It could be a bug. Please report it to @blueloveTH on GitHub.\n";
|
Str msg = "An unknown exception occurred! It could be a bug. Please report it to @blueloveTH on GitHub.\n";
|
||||||
stderr_write(msg);
|
stderr_write(msg);
|
||||||
}
|
}
|
||||||
delete code;
|
CodeObject__delete(code);
|
||||||
callstack.clear();
|
callstack.clear();
|
||||||
s_data.clear();
|
s_data.clear();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -419,11 +420,12 @@ PyObject* VM::py_import(Str path, bool throw_err) {
|
|||||||
PyObject* new_mod = new_module(name_cpnt, f_join(path_cpnts));
|
PyObject* new_mod = new_module(name_cpnt, f_join(path_cpnts));
|
||||||
CodeObject* code = compile(source, filename, EXEC_MODE);
|
CodeObject* code = compile(source, filename, EXEC_MODE);
|
||||||
_exec(code, new_mod);
|
_exec(code, new_mod);
|
||||||
delete code; // leak if exception occurs
|
CodeObject__delete(code);
|
||||||
return new_mod;
|
return new_mod;
|
||||||
}
|
}
|
||||||
|
|
||||||
VM::~VM() {
|
VM::~VM() {
|
||||||
|
PK_DECREF(__dynamic_func_decl);
|
||||||
// destroy all objects
|
// destroy all objects
|
||||||
pk_ManagedHeap__dtor(&heap);
|
pk_ManagedHeap__dtor(&heap);
|
||||||
// clear everything
|
// clear everything
|
||||||
@ -628,11 +630,14 @@ PyVar VM::__py_exec_internal(const CodeObject* code, PyVar globals, PyVar locals
|
|||||||
void VM::py_exec(std::string_view source, PyVar globals, PyVar locals) {
|
void VM::py_exec(std::string_view source, PyVar globals, PyVar locals) {
|
||||||
CodeObject* code = vm->compile(source, "<exec>", EXEC_MODE, true);
|
CodeObject* code = vm->compile(source, "<exec>", EXEC_MODE, true);
|
||||||
__py_exec_internal(code, globals, locals);
|
__py_exec_internal(code, globals, locals);
|
||||||
|
CodeObject__delete(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyVar VM::py_eval(std::string_view source, PyVar globals, PyVar locals) {
|
PyVar VM::py_eval(std::string_view source, PyVar globals, PyVar locals) {
|
||||||
CodeObject* code = vm->compile(source, "<eval>", EVAL_MODE, true);
|
CodeObject* code = vm->compile(source, "<eval>", EVAL_MODE, true);
|
||||||
return __py_exec_internal(code, globals, locals);
|
PyVar retval = __py_exec_internal(code, globals, locals);
|
||||||
|
CodeObject__delete(code);
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyVar VM::__format_object(PyVar obj, Str spec) {
|
PyVar VM::__format_object(PyVar obj, Str spec) {
|
||||||
@ -752,9 +757,11 @@ static std::string _opcode_argstr(VM* vm, int i, Bytecode byte, const CodeObject
|
|||||||
switch(byte.op) {
|
switch(byte.op) {
|
||||||
case OP_LOAD_CONST:
|
case OP_LOAD_CONST:
|
||||||
case OP_FORMAT_STRING:
|
case OP_FORMAT_STRING:
|
||||||
case OP_IMPORT_PATH:
|
case OP_IMPORT_PATH: {
|
||||||
if(vm != nullptr) ss << " (" << vm->py_repr(co->consts[byte.arg]) << ")";
|
PyVar obj = c11__getitem(PyVar, &co->consts, byte.arg);
|
||||||
|
if(vm != nullptr) ss << " (" << vm->py_repr(obj) << ")";
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case OP_LOAD_NAME:
|
case OP_LOAD_NAME:
|
||||||
case OP_LOAD_GLOBAL:
|
case OP_LOAD_GLOBAL:
|
||||||
case OP_LOAD_NONLOCAL:
|
case OP_LOAD_NONLOCAL:
|
||||||
@ -773,8 +780,16 @@ static std::string _opcode_argstr(VM* vm, int i, Bytecode byte, const CodeObject
|
|||||||
case OP_DELETE_FAST:
|
case OP_DELETE_FAST:
|
||||||
case OP_FOR_ITER_STORE_FAST:
|
case OP_FOR_ITER_STORE_FAST:
|
||||||
case OP_LOAD_SUBSCR_FAST:
|
case OP_LOAD_SUBSCR_FAST:
|
||||||
case OP_STORE_SUBSCR_FAST: ss << " (" << co->varnames[byte.arg].sv() << ")"; break;
|
case OP_STORE_SUBSCR_FAST:{
|
||||||
case OP_LOAD_FUNCTION: ss << " (" << co->func_decls[byte.arg]->code->name << ")"; break;
|
StrName name = c11__getitem(StrName, &co->varnames, byte.arg);
|
||||||
|
ss << " (" << name.sv() << ")";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OP_LOAD_FUNCTION: {
|
||||||
|
const FuncDecl* decl = c11__getitem(FuncDecl*, &co->func_decls, byte.arg);
|
||||||
|
ss << " (" << pkpy_Str__data(&decl->code->name) << ")";
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ss.str().str();
|
return ss.str().str();
|
||||||
}
|
}
|
||||||
@ -786,22 +801,23 @@ Str VM::disassemble(CodeObject* co) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
vector<int> jumpTargets;
|
vector<int> jumpTargets;
|
||||||
for(int i = 0; i < co->codes.size(); i++) {
|
for(int i=0; i<co->codes.count; i++) {
|
||||||
Bytecode byte = co->codes[i];
|
Bytecode* bc = c11__at(Bytecode, &co->codes, i);
|
||||||
if(Bytecode__is_forward_jump(&byte)) {
|
if(Bytecode__is_forward_jump(bc)) {
|
||||||
jumpTargets.push_back((int16_t)byte.arg + i);
|
jumpTargets.push_back((int16_t)bc->arg + i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SStream ss;
|
SStream ss;
|
||||||
int prev_line = -1;
|
int prev_line = -1;
|
||||||
for(int i = 0; i < co->codes.size(); i++) {
|
for(int i = 0; i < co->codes.count; i++) {
|
||||||
const Bytecode& byte = co->codes[i];
|
Bytecode byte = c11__getitem(Bytecode, &co->codes, i);
|
||||||
Str line = std::to_string(co->lines[i].lineno);
|
BytecodeEx ex = c11__getitem(BytecodeEx, &co->codes_ex, i);
|
||||||
if(co->lines[i].lineno == prev_line)
|
Str line = std::to_string(ex.lineno);
|
||||||
|
if(ex.lineno == prev_line)
|
||||||
line = "";
|
line = "";
|
||||||
else {
|
else {
|
||||||
if(prev_line != -1) ss << "\n";
|
if(prev_line != -1) ss << "\n";
|
||||||
prev_line = co->lines[i].lineno;
|
prev_line = ex.lineno;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string pointer;
|
std::string pointer;
|
||||||
@ -812,16 +828,17 @@ Str VM::disassemble(CodeObject* co) {
|
|||||||
}
|
}
|
||||||
ss << pad(line, 8) << pointer << pad(std::to_string(i), 3);
|
ss << pad(line, 8) << pointer << pad(std::to_string(i), 3);
|
||||||
std::string bc_name(OP_NAMES[byte.op]);
|
std::string bc_name(OP_NAMES[byte.op]);
|
||||||
if(co->lines[i].is_virtual) bc_name += '*';
|
if(ex.is_virtual) bc_name += '*';
|
||||||
ss << " " << pad(bc_name, 25) << " ";
|
ss << " " << pad(bc_name, 25) << " ";
|
||||||
std::string argStr = _opcode_argstr(this, i, byte, co);
|
std::string argStr = _opcode_argstr(this, i, byte, co);
|
||||||
ss << argStr;
|
ss << argStr;
|
||||||
if(i != co->codes.size() - 1) ss << '\n';
|
if(i != co->codes.count - 1) ss << '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto& decl: co->func_decls) {
|
c11_vector__foreach(FuncDecl*, &co->func_decls, it) {
|
||||||
|
FuncDecl* decl = *it;
|
||||||
ss << "\n\n"
|
ss << "\n\n"
|
||||||
<< "Disassembly of " << decl->code->name << ":\n";
|
<< "Disassembly of " << pkpy_Str__data(&decl->code->name) << ":\n";
|
||||||
ss << disassemble(decl->code);
|
ss << disassemble(decl->code);
|
||||||
}
|
}
|
||||||
ss << "\n";
|
ss << "\n";
|
||||||
@ -986,21 +1003,22 @@ void VM::__unpack_as_dict(ArgsView args, Dict& dict) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VM::__prepare_py_call(PyVar* buffer, ArgsView args, ArgsView kwargs, const FuncDecl_& decl) {
|
void VM::__prepare_py_call(PyVar* buffer, ArgsView args, ArgsView kwargs, const FuncDecl* decl) {
|
||||||
const CodeObject* co = decl->code;
|
const CodeObject* co = decl->code;
|
||||||
int decl_argc = decl->args.size();
|
int decl_argc = decl->args.count;
|
||||||
|
|
||||||
if(args.size() < decl_argc) {
|
if(args.size() < decl_argc) {
|
||||||
vm->TypeError(_S(co->name, "() takes ", decl_argc, " positional arguments but ", args.size(), " were given"));
|
vm->TypeError(_S(pkpy_Str__data(&co->name), "() takes ", decl_argc, " positional arguments but ", args.size(), " were given"));
|
||||||
}
|
}
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
// prepare args
|
// prepare args
|
||||||
std::memset(buffer, 0, co->nlocals * sizeof(PyVar));
|
std::memset(buffer, 0, co->nlocals * sizeof(PyVar));
|
||||||
for(int index: decl->args)
|
c11_vector__foreach(int, &decl->args, index) {
|
||||||
buffer[index] = args[i++];
|
buffer[*index] = args[i++];
|
||||||
|
}
|
||||||
// prepare kwdefaults
|
// prepare kwdefaults
|
||||||
c11_vector__foreach(FuncDecl::KwArg, &decl->kwargs, kv) {
|
c11_vector__foreach(FuncDeclKwArg, &decl->kwargs, kv) {
|
||||||
buffer[kv->index] = kv->value;
|
buffer[kv->index] = kv->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1011,11 +1029,11 @@ void VM::__prepare_py_call(PyVar* buffer, ArgsView args, ArgsView kwargs, const
|
|||||||
i += vargs.size();
|
i += vargs.size();
|
||||||
} else {
|
} else {
|
||||||
// kwdefaults override
|
// kwdefaults override
|
||||||
c11_vector__foreach(FuncDecl::KwArg, &decl->kwargs, kv) {
|
c11_vector__foreach(FuncDeclKwArg, &decl->kwargs, kv) {
|
||||||
if(i >= args.size()) break;
|
if(i >= args.size()) break;
|
||||||
buffer[kv->index] = args[i++];
|
buffer[kv->index] = args[i++];
|
||||||
}
|
}
|
||||||
if(i < args.size()) TypeError(_S("too many arguments", " (", decl->code->name, ')'));
|
if(i < args.size()) TypeError(_S("too many arguments", " (", pkpy_Str__data(&decl->code->name), ')'));
|
||||||
}
|
}
|
||||||
|
|
||||||
PyVar vkwargs;
|
PyVar vkwargs;
|
||||||
@ -1035,7 +1053,7 @@ void VM::__prepare_py_call(PyVar* buffer, ArgsView args, ArgsView kwargs, const
|
|||||||
} else {
|
} else {
|
||||||
// otherwise, set as **kwargs if possible
|
// otherwise, set as **kwargs if possible
|
||||||
if(!vkwargs) {
|
if(!vkwargs) {
|
||||||
TypeError(_S(key.escape(), " is an invalid keyword argument for ", co->name, "()"));
|
TypeError(_S(key.escape(), " is an invalid keyword argument for ", pkpy_Str__data(&co->name), "()"));
|
||||||
} else {
|
} else {
|
||||||
Dict& dict = _CAST(Dict&, vkwargs);
|
Dict& dict = _CAST(Dict&, vkwargs);
|
||||||
dict.set(this, VAR(key.sv()), kwargs[j + 1]);
|
dict.set(this, VAR(key.sv()), kwargs[j + 1]);
|
||||||
@ -1085,14 +1103,15 @@ PyVar VM::vectorcall(int ARGC, int KWARGC, bool op_call) {
|
|||||||
_base[j] = __vectorcall_buffer[j];
|
_base[j] = __vectorcall_buffer[j];
|
||||||
break;
|
break;
|
||||||
case FuncType_SIMPLE:
|
case FuncType_SIMPLE:
|
||||||
if(args.size() != fn.decl->args.size())
|
if(args.size() != fn.decl->args.count){
|
||||||
TypeError(_S(co->name,
|
TypeError(pk_format(
|
||||||
"() takes ",
|
"{} takes {} positional arguments but {} were given",
|
||||||
fn.decl->args.size(),
|
&co->name, fn.decl->args.count, args.size()
|
||||||
" positional arguments but ",
|
));
|
||||||
args.size(),
|
}
|
||||||
" were given"));
|
if(!kwargs.empty()){
|
||||||
if(!kwargs.empty()) TypeError(_S(co->name, "() takes no keyword arguments"));
|
TypeError(pk_format("{} takes no keyword arguments", &co->name));
|
||||||
|
}
|
||||||
// [callable, <self>, args..., local_vars...]
|
// [callable, <self>, args..., local_vars...]
|
||||||
// ^p0 ^p1 ^_sp
|
// ^p0 ^p1 ^_sp
|
||||||
s_data.reset(_base + co->nlocals);
|
s_data.reset(_base + co->nlocals);
|
||||||
@ -1100,14 +1119,15 @@ PyVar VM::vectorcall(int ARGC, int KWARGC, bool op_call) {
|
|||||||
std::memset(p1, 0, (char*)s_data._sp - (char*)p1);
|
std::memset(p1, 0, (char*)s_data._sp - (char*)p1);
|
||||||
break;
|
break;
|
||||||
case FuncType_EMPTY:
|
case FuncType_EMPTY:
|
||||||
if(args.size() != fn.decl->args.size())
|
if(args.size() != fn.decl->args.count){
|
||||||
TypeError(_S(co->name,
|
TypeError(pk_format(
|
||||||
"() takes ",
|
"{} takes {} positional arguments but {} were given",
|
||||||
fn.decl->args.size(),
|
&co->name, fn.decl->args.count, args.size()
|
||||||
" positional arguments but ",
|
));
|
||||||
args.size(),
|
}
|
||||||
" were given"));
|
if(!kwargs.empty()){
|
||||||
if(!kwargs.empty()) TypeError(_S(co->name, "() takes no keyword arguments"));
|
TypeError(pk_format("{} takes no keyword arguments", &co->name));
|
||||||
|
}
|
||||||
s_data.reset(p0);
|
s_data.reset(p0);
|
||||||
return None;
|
return None;
|
||||||
case FuncType_GENERATOR:
|
case FuncType_GENERATOR:
|
||||||
@ -1385,9 +1405,10 @@ PyObject* VM::bind(PyObject* obj, const char* sig, const char* docstring, Native
|
|||||||
std::string_view source(buffer, length);
|
std::string_view source(buffer, length);
|
||||||
// fn(a, b, *c, d=1) -> None
|
// fn(a, b, *c, d=1) -> None
|
||||||
CodeObject* code = compile(source, "<bind>", EXEC_MODE);
|
CodeObject* code = compile(source, "<bind>", EXEC_MODE);
|
||||||
assert(code->func_decls.size() == 1);
|
assert(code->func_decls.count == 1);
|
||||||
FuncDecl_ decl = code->func_decls[0];
|
FuncDecl_ decl = c11__getitem(FuncDecl_, &code->func_decls, 0);
|
||||||
delete code; // may leak if exception occurs
|
c11_vector__clear(&code->func_decls); // move decl
|
||||||
|
CodeObject__delete(code); // may leak if exception occurs
|
||||||
decl->docstring = docstring;
|
decl->docstring = docstring;
|
||||||
PyObject* f_obj = new_object<NativeFunc>(tp_native_func, fn, decl, std::move(userdata)).get();
|
PyObject* f_obj = new_object<NativeFunc>(tp_native_func, fn, decl, std::move(userdata)).get();
|
||||||
|
|
||||||
@ -1396,7 +1417,10 @@ PyObject* VM::bind(PyObject* obj, const char* sig, const char* docstring, Native
|
|||||||
case BindType_CLASSMETHOD: f_obj = new_object<ClassMethod>(tp_classmethod, f_obj).get(); break;
|
case BindType_CLASSMETHOD: f_obj = new_object<ClassMethod>(tp_classmethod, f_obj).get(); break;
|
||||||
case BindType_FUNCTION: break;
|
case BindType_FUNCTION: break;
|
||||||
}
|
}
|
||||||
if(obj != nullptr) obj->attr().set(decl->code->name, f_obj);
|
if(obj != nullptr){
|
||||||
|
StrName name = pkpy_Str__data(&decl->code->name);
|
||||||
|
obj->attr().set(name, f_obj);
|
||||||
|
}
|
||||||
return f_obj;
|
return f_obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1459,8 +1483,8 @@ void VM::__raise_exc(bool re_raise) {
|
|||||||
|
|
||||||
int actual_ip = frame->ip();
|
int actual_ip = frame->ip();
|
||||||
if(e._ip_on_error >= 0 && e._code_on_error == (void*)frame->co) actual_ip = e._ip_on_error;
|
if(e._ip_on_error >= 0 && e._code_on_error == (void*)frame->co) actual_ip = e._ip_on_error;
|
||||||
int current_line = frame->co->lines[actual_ip].lineno; // current line
|
int current_line = c11__at(BytecodeEx, &frame->co->codes_ex, actual_ip)->lineno;
|
||||||
const char* current_f_name = frame->co->name.c_str(); // current function name
|
const char* current_f_name = pkpy_Str__data(&frame->co->name); // current function name
|
||||||
if(frame->_callable == nullptr) current_f_name = ""; // not in a function
|
if(frame->_callable == nullptr) current_f_name = ""; // not in a function
|
||||||
e.stpush(frame->co->src, current_line, nullptr, current_f_name);
|
e.stpush(frame->co->src, current_line, nullptr, current_f_name);
|
||||||
|
|
||||||
@ -1802,13 +1826,13 @@ void VM::__breakpoint() {
|
|||||||
if(cmd == "p" || cmd == "print") {
|
if(cmd == "p" || cmd == "print") {
|
||||||
CodeObject* code = compile(arg, "<stdin>", EVAL_MODE, true);
|
CodeObject* code = compile(arg, "<stdin>", EVAL_MODE, true);
|
||||||
PyVar retval = vm->_exec(code, frame_0->_module, frame_0->_callable, frame_0->_locals);
|
PyVar retval = vm->_exec(code, frame_0->_module, frame_0->_callable, frame_0->_locals);
|
||||||
delete code;
|
CodeObject__delete(code);
|
||||||
stdout_write(vm->py_repr(retval));
|
stdout_write(vm->py_repr(retval));
|
||||||
stdout_write("\n");
|
stdout_write("\n");
|
||||||
} else if(cmd == "!") {
|
} else if(cmd == "!") {
|
||||||
CodeObject* code = compile(arg, "<stdin>", EXEC_MODE, true);
|
CodeObject* code = compile(arg, "<stdin>", EXEC_MODE, true);
|
||||||
vm->_exec(code, frame_0->_module, frame_0->_callable, frame_0->_locals);
|
vm->_exec(code, frame_0->_module, frame_0->_callable, frame_0->_locals);
|
||||||
delete code;
|
CodeObject__delete(code);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -1822,7 +1846,7 @@ PyVar PyObject::attr(StrName name) const{
|
|||||||
|
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
void Function::_gc_mark(VM* vm) const {
|
void Function::_gc_mark(VM* vm) const {
|
||||||
decl->_gc_mark(vm);
|
FuncDecl__gc_mark(decl);
|
||||||
if(_closure) {
|
if(_closure) {
|
||||||
_closure->apply([](StrName _, PyVar obj, void* userdata) {
|
_closure->apply([](StrName _, PyVar obj, void* userdata) {
|
||||||
VM* vm = (VM*)userdata;
|
VM* vm = (VM*)userdata;
|
||||||
@ -1832,16 +1856,31 @@ void Function::_gc_mark(VM* vm) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void NativeFunc::_gc_mark(VM* vm) const {
|
void NativeFunc::_gc_mark(VM* vm) const {
|
||||||
if(decl) decl->_gc_mark(vm);
|
if(decl){
|
||||||
|
FuncDecl__gc_mark(decl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FuncDecl::_gc_mark(VM* vm) const {
|
extern "C"{
|
||||||
code->_gc_mark(vm);
|
void FuncDecl__gc_mark(const FuncDecl *self){
|
||||||
c11_vector__foreach(FuncDecl::KwArg, &kwargs, kv) {
|
VM* vm = (VM*)pkpy_g.vm;
|
||||||
|
CodeObject__gc_mark(self->code);
|
||||||
|
c11_vector__foreach(FuncDeclKwArg, &self->kwargs, kv) {
|
||||||
vm->obj_gc_mark(kv->value);
|
vm->obj_gc_mark(kv->value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CodeObject__gc_mark(const CodeObject* self) {
|
||||||
|
VM* vm = (VM*)pkpy_g.vm;
|
||||||
|
c11_vector__foreach(PyVar, &self->consts, v) {
|
||||||
|
vm->obj_gc_mark(*v);
|
||||||
|
}
|
||||||
|
c11_vector__foreach(FuncDecl*, &self->func_decls, decl) {
|
||||||
|
FuncDecl__gc_mark(*decl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void List::_gc_mark(VM* vm) const {
|
void List::_gc_mark(VM* vm) const {
|
||||||
for(PyVar obj: *this)
|
for(PyVar obj: *this)
|
||||||
vm->obj_gc_mark(obj);
|
vm->obj_gc_mark(obj);
|
||||||
@ -1880,7 +1919,7 @@ void Super::_gc_mark(VM* vm) const { vm->obj_gc_mark(first); }
|
|||||||
|
|
||||||
void Frame::_gc_mark(VM* vm) const {
|
void Frame::_gc_mark(VM* vm) const {
|
||||||
vm->obj_gc_mark(_module);
|
vm->obj_gc_mark(_module);
|
||||||
co->_gc_mark(vm);
|
CodeObject__gc_mark(co);
|
||||||
// Frame could be stored in a generator, so mark _callable for safety
|
// Frame could be stored in a generator, so mark _callable for safety
|
||||||
vm->obj_gc_mark(_callable);
|
vm->obj_gc_mark(_callable);
|
||||||
}
|
}
|
||||||
@ -1924,11 +1963,4 @@ void Dict::_gc_mark(VM* vm) const {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeObject::_gc_mark(VM* vm) const {
|
|
||||||
for(PyVar v: consts)
|
|
||||||
vm->obj_gc_mark(v);
|
|
||||||
for(auto& decl: func_decls)
|
|
||||||
decl->_gc_mark(vm);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace pkpy
|
} // namespace pkpy
|
||||||
|
@ -108,7 +108,7 @@ void add_module_json(VM* vm) {
|
|||||||
}
|
}
|
||||||
CodeObject* code = vm->compile(sv, "<json>", JSON_MODE);
|
CodeObject* code = vm->compile(sv, "<json>", JSON_MODE);
|
||||||
PyVar retval = vm->_exec(code, vm->callstack.top()._module);
|
PyVar retval = vm->_exec(code, vm->callstack.top()._module);
|
||||||
delete code; // leak on error
|
CodeObject__delete(code);
|
||||||
return retval;
|
return retval;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -238,7 +238,7 @@ void add_module_dis(VM* vm) {
|
|||||||
if(is_type(f, vm->tp_bound_method)) f = CAST(BoundMethod, obj).func;
|
if(is_type(f, vm->tp_bound_method)) f = CAST(BoundMethod, obj).func;
|
||||||
code = CAST(Function&, f).decl->code;
|
code = CAST(Function&, f).decl->code;
|
||||||
vm->stdout_write(vm->disassemble(code));
|
vm->stdout_write(vm->disassemble(code));
|
||||||
if(need_delete) delete code;
|
if(need_delete) CodeObject__delete(code);
|
||||||
return vm->None;
|
return vm->None;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -252,7 +252,7 @@ void add_module_enum(VM* vm) {
|
|||||||
PyObject* mod = vm->new_module("enum");
|
PyObject* mod = vm->new_module("enum");
|
||||||
CodeObject* code = vm->compile(kPythonLibs__enum, "enum.py", EXEC_MODE);
|
CodeObject* code = vm->compile(kPythonLibs__enum, "enum.py", EXEC_MODE);
|
||||||
vm->_exec(code, mod);
|
vm->_exec(code, mod);
|
||||||
delete code; // leak on error
|
CodeObject__delete(code);
|
||||||
PyVar Enum = mod->attr("Enum");
|
PyVar Enum = mod->attr("Enum");
|
||||||
vm->_all_types[PK_OBJ_GET(Type, Enum)].on_end_subclass = [](VM* vm, PyTypeInfo* new_ti) {
|
vm->_all_types[PK_OBJ_GET(Type, Enum)].on_end_subclass = [](VM* vm, PyTypeInfo* new_ti) {
|
||||||
new_ti->subclass_enabled = false; // Enum class cannot be subclassed twice
|
new_ti->subclass_enabled = false; // Enum class cannot be subclassed twice
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "pocketpy/objects/codeobject.h"
|
#include "pocketpy/objects/codeobject.h"
|
||||||
#include "pocketpy/common/utils.h"
|
#include "pocketpy/common/utils.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
void Bytecode__set_signed_arg(Bytecode* self, int arg) {
|
void Bytecode__set_signed_arg(Bytecode* self, int arg) {
|
||||||
if(arg < INT16_MIN || arg > INT16_MAX) {
|
if(arg < INT16_MIN || arg > INT16_MAX) {
|
||||||
@ -11,3 +12,86 @@ void Bytecode__set_signed_arg(Bytecode* self, int arg) {
|
|||||||
bool Bytecode__is_forward_jump(const Bytecode* self) {
|
bool Bytecode__is_forward_jump(const Bytecode* self) {
|
||||||
return self->op >= OP_JUMP_FORWARD && self->op <= OP_LOOP_BREAK;
|
return self->op >= OP_JUMP_FORWARD && self->op <= OP_LOOP_BREAK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FuncDecl_ FuncDecl__rcnew(pkpy_SourceData_ src, c11_string name){
|
||||||
|
FuncDecl* self = malloc(sizeof(FuncDecl));
|
||||||
|
self->rc.count = 1;
|
||||||
|
self->rc.dtor = (void (*)(void*))FuncDecl__dtor;
|
||||||
|
self->code = CodeObject__new(src, name);
|
||||||
|
|
||||||
|
c11_vector__ctor(&self->args, sizeof(int));
|
||||||
|
c11_vector__ctor(&self->kwargs, sizeof(FuncDeclKwArg));
|
||||||
|
|
||||||
|
self->starred_arg = -1;
|
||||||
|
self->starred_kwarg = -1;
|
||||||
|
self->nested = false;
|
||||||
|
|
||||||
|
self->docstring = NULL;
|
||||||
|
self->type = FuncType_UNSET;
|
||||||
|
|
||||||
|
c11_smallmap_n2i__ctor(&self->kw_to_index);
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FuncDecl__dtor(FuncDecl* self){
|
||||||
|
CodeObject__delete(self->code);
|
||||||
|
c11_vector__dtor(&self->args);
|
||||||
|
c11_vector__dtor(&self->kwargs);
|
||||||
|
c11_smallmap_n2i__dtor(&self->kw_to_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FuncDecl__add_kwarg(FuncDecl* self, int index, uint16_t key, const PyVar* value){
|
||||||
|
c11_smallmap_n2i__set(&self->kw_to_index, key, index);
|
||||||
|
FuncDeclKwArg item = {index, key, *value};
|
||||||
|
c11_vector__push(FuncDeclKwArg, &self->kwargs, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
CodeObject* CodeObject__new(pkpy_SourceData_ src, c11_string name){
|
||||||
|
CodeObject* self = malloc(sizeof(CodeObject));
|
||||||
|
self->src = src; PK_INCREF(src);
|
||||||
|
pkpy_Str__ctor2(&self->name, name.data, name.size);
|
||||||
|
|
||||||
|
c11_vector__ctor(&self->codes, sizeof(Bytecode));
|
||||||
|
c11_vector__ctor(&self->codes_ex, sizeof(BytecodeEx));
|
||||||
|
|
||||||
|
c11_vector__ctor(&self->consts, sizeof(PyVar));
|
||||||
|
c11_vector__ctor(&self->varnames, sizeof(uint16_t));
|
||||||
|
self->nlocals = 0;
|
||||||
|
|
||||||
|
c11_smallmap_n2i__ctor(&self->varnames_inv);
|
||||||
|
c11_smallmap_n2i__ctor(&self->labels);
|
||||||
|
|
||||||
|
c11_vector__ctor(&self->blocks, sizeof(CodeBlock));
|
||||||
|
c11_vector__ctor(&self->func_decls, sizeof(FuncDecl_));
|
||||||
|
|
||||||
|
self->start_line = -1;
|
||||||
|
self->end_line = -1;
|
||||||
|
|
||||||
|
CodeBlock root_block = {CodeBlockType_NO_BLOCK, -1, 0, -1, -1};
|
||||||
|
c11_vector__push(CodeBlock, &self->blocks, root_block);
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CodeObject__delete(CodeObject* self){
|
||||||
|
PK_DECREF(self->src);
|
||||||
|
pkpy_Str__dtor(&self->name);
|
||||||
|
|
||||||
|
c11_vector__dtor(&self->codes);
|
||||||
|
c11_vector__dtor(&self->codes_ex);
|
||||||
|
|
||||||
|
c11_vector__dtor(&self->consts);
|
||||||
|
c11_vector__dtor(&self->varnames);
|
||||||
|
|
||||||
|
c11_smallmap_n2i__dtor(&self->varnames_inv);
|
||||||
|
c11_smallmap_n2i__dtor(&self->labels);
|
||||||
|
|
||||||
|
c11_vector__dtor(&self->blocks);
|
||||||
|
|
||||||
|
for(int i=0; i<self->func_decls.count; i++){
|
||||||
|
FuncDecl_ decl = c11__getitem(FuncDecl_, &self->func_decls, i);
|
||||||
|
PK_DECREF(decl);
|
||||||
|
}
|
||||||
|
c11_vector__dtor(&self->func_decls);
|
||||||
|
|
||||||
|
free(self);
|
||||||
|
}
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "pocketpy/common/_generated.h"
|
#include "pocketpy/common/_generated.h"
|
||||||
|
|
||||||
|
#include "pocketpy/common/refcount.h"
|
||||||
#include "pocketpy/modules/array2d.hpp"
|
#include "pocketpy/modules/array2d.hpp"
|
||||||
#include "pocketpy/modules/base64.hpp"
|
#include "pocketpy/modules/base64.hpp"
|
||||||
#include "pocketpy/modules/csv.hpp"
|
#include "pocketpy/modules/csv.hpp"
|
||||||
@ -12,6 +13,7 @@
|
|||||||
#include "pocketpy/modules/random.hpp"
|
#include "pocketpy/modules/random.hpp"
|
||||||
#include "pocketpy/modules/modules.hpp"
|
#include "pocketpy/modules/modules.hpp"
|
||||||
#include "pocketpy/objects/base.h"
|
#include "pocketpy/objects/base.h"
|
||||||
|
#include "pocketpy/objects/codeobject.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@ -1692,15 +1694,16 @@ void VM::__post_init_builtin_types() {
|
|||||||
try {
|
try {
|
||||||
// initialize dummy func_decl for exec/eval
|
// initialize dummy func_decl for exec/eval
|
||||||
CodeObject* code = compile("def _(): pass", "<dynamic>", EXEC_MODE);
|
CodeObject* code = compile("def _(): pass", "<dynamic>", EXEC_MODE);
|
||||||
__dynamic_func_decl = code->func_decls[0];
|
__dynamic_func_decl = c11__getitem(FuncDecl_, &code->func_decls, 0);
|
||||||
delete code; // may leak on error
|
PK_INCREF(__dynamic_func_decl);
|
||||||
|
CodeObject__delete(code);
|
||||||
// initialize builtins
|
// initialize builtins
|
||||||
code = compile(kPythonLibs_builtins, "<builtins>", EXEC_MODE);
|
code = compile(kPythonLibs_builtins, "<builtins>", EXEC_MODE);
|
||||||
this->_exec(code, this->builtins);
|
this->_exec(code, this->builtins);
|
||||||
delete code; // may leak on error
|
CodeObject__delete(code);
|
||||||
code = compile(kPythonLibs__set, "<set>", EXEC_MODE);
|
code = compile(kPythonLibs__set, "<set>", EXEC_MODE);
|
||||||
this->_exec(code, this->builtins);
|
this->_exec(code, this->builtins);
|
||||||
delete code; // may leak on error
|
CodeObject__delete(code);
|
||||||
} catch(TopLevelException e) {
|
} catch(TopLevelException e) {
|
||||||
std::cerr << e.summary() << std::endl;
|
std::cerr << e.summary() << std::endl;
|
||||||
std::cerr << "failed to load builtins module!!" << std::endl;
|
std::cerr << "failed to load builtins module!!" << std::endl;
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#include "pocketpy/objects/codeobject.h"
|
||||||
#ifndef PK_NO_EXPORT_C_API
|
#ifndef PK_NO_EXPORT_C_API
|
||||||
|
|
||||||
#include "pocketpy/pocketpy.hpp"
|
#include "pocketpy/pocketpy.hpp"
|
||||||
@ -62,7 +63,7 @@ bool pkpy_exec(pkpy_vm* vm_handle, const char* source) {
|
|||||||
PK_PROTECTED(
|
PK_PROTECTED(
|
||||||
CodeObject* code = vm->compile(source, "main.py", EXEC_MODE);
|
CodeObject* code = vm->compile(source, "main.py", EXEC_MODE);
|
||||||
res = vm->_exec(code, vm->_main);
|
res = vm->_exec(code, vm->_main);
|
||||||
delete code; // TODO: _exec may raise, so code may leak
|
CodeObject__delete(code);
|
||||||
)
|
)
|
||||||
return res != nullptr;
|
return res != nullptr;
|
||||||
}
|
}
|
||||||
@ -79,7 +80,7 @@ bool pkpy_exec_2(pkpy_vm* vm_handle, const char* source, const char* filename, i
|
|||||||
}
|
}
|
||||||
CodeObject* code = vm->compile(source, filename, (CompileMode)mode);
|
CodeObject* code = vm->compile(source, filename, (CompileMode)mode);
|
||||||
res = vm->_exec(code, mod);
|
res = vm->_exec(code, mod);
|
||||||
delete code; // TODO: _exec may raise, so code may leak
|
CodeObject__delete(code); // TODO: _exec may raise, so code may leak
|
||||||
)
|
)
|
||||||
return res != nullptr;
|
return res != nullptr;
|
||||||
}
|
}
|
||||||
@ -419,10 +420,10 @@ bool pkpy_eval(pkpy_vm* vm_handle, const char* source) {
|
|||||||
VM* vm = (VM*)vm_handle;
|
VM* vm = (VM*)vm_handle;
|
||||||
PK_ASSERT_NO_ERROR()
|
PK_ASSERT_NO_ERROR()
|
||||||
PK_PROTECTED(
|
PK_PROTECTED(
|
||||||
CodeObject* co = vm->compile(source, "<eval>", EVAL_MODE);
|
CodeObject* code = vm->compile(source, "<eval>", EVAL_MODE);
|
||||||
PyVar ret = vm->_exec(co, vm->_main);
|
PyVar ret = vm->_exec(code, vm->_main);
|
||||||
vm->s_data.push(ret);
|
vm->s_data.push(ret);
|
||||||
delete co; // TODO: _exec may raise, so code may leak
|
CodeObject__delete(code);
|
||||||
)
|
)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user