mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 19:40:18 +00:00
some move
This commit is contained in:
parent
92fcc116af
commit
aea3b4758f
@ -1,5 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "stdio.h"
|
||||||
|
#include "stdlib.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
52
include/pocketpy/compiler/expr.h
Normal file
52
include/pocketpy/compiler/expr.h
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
// #pragma once
|
||||||
|
|
||||||
|
// #include <stdbool.h>
|
||||||
|
// #include "pocketpy/common/memorypool.h"
|
||||||
|
// #include "pocketpy/compiler/lexer.h"
|
||||||
|
|
||||||
|
// #ifdef __cplusplus
|
||||||
|
// extern "C" {
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// struct pk_Expr;
|
||||||
|
// struct pk_CodeEmitContext;
|
||||||
|
|
||||||
|
// struct pk_ExprVt{
|
||||||
|
// void (*dtor)(pk_Expr*);
|
||||||
|
// /* reflections */
|
||||||
|
// bool (*is_literal)(const pk_Expr*);
|
||||||
|
// bool (*is_json_object)(const pk_Expr*);
|
||||||
|
// bool (*is_attrib)(const pk_Expr*);
|
||||||
|
// bool (*is_subscr)(const pk_Expr*);
|
||||||
|
// bool (*is_compare)(const pk_Expr*);
|
||||||
|
// int (*star_level)(const pk_Expr*);
|
||||||
|
// bool (*is_tuple)(const pk_Expr*);
|
||||||
|
// bool (*is_name)(const pk_Expr*);
|
||||||
|
// /* emit */
|
||||||
|
// void (*emit_)(pk_Expr*, pk_CodeEmitContext*);
|
||||||
|
// bool (*emit_del)(pk_Expr*, pk_CodeEmitContext*);
|
||||||
|
// bool (*emit_store)(pk_Expr*, pk_CodeEmitContext*);
|
||||||
|
// void (*emit_inplace)(pk_Expr*, pk_CodeEmitContext*);
|
||||||
|
// bool (*emit_store_inplace)(pk_Expr*, pk_CodeEmitContext*);
|
||||||
|
// };
|
||||||
|
|
||||||
|
// typedef struct pk_Expr{
|
||||||
|
// pk_ExprVt* vt;
|
||||||
|
// int line;
|
||||||
|
// } pk_Expr;
|
||||||
|
|
||||||
|
// void pk_ExprVt__ctor(pk_ExprVt* vt);
|
||||||
|
// void pk_Expr__emit_(pk_Expr* self, pk_CodeEmitContext* ctx);
|
||||||
|
// bool pk_Expr__emit_del(pk_Expr* self, pk_CodeEmitContext* ctx);
|
||||||
|
// bool pk_Expr__emit_store(pk_Expr* self, pk_CodeEmitContext* ctx);
|
||||||
|
// void pk_Expr__emit_inplace(pk_Expr* self, pk_CodeEmitContext* ctx);
|
||||||
|
// bool pk_Expr__emit_store_inplace(pk_Expr* self, pk_CodeEmitContext* ctx);
|
||||||
|
// void pk_Expr__delete(pk_Expr* self);
|
||||||
|
|
||||||
|
// typedef struct pk_CodeEmitContext{
|
||||||
|
|
||||||
|
// } pk_CodeEmitContext;
|
||||||
|
|
||||||
|
// #ifdef __cplusplus
|
||||||
|
// }
|
||||||
|
// #endif
|
@ -10,48 +10,7 @@ struct Expr;
|
|||||||
|
|
||||||
typedef small_vector<Expr*, 4> Expr_vector;
|
typedef small_vector<Expr*, 4> Expr_vector;
|
||||||
|
|
||||||
static bool default_false(const Expr*) { return false; }
|
|
||||||
static int default_zero(const Expr*) { return 0; }
|
|
||||||
static void default_dtor(Expr*) {}
|
|
||||||
|
|
||||||
struct ExprVt{
|
|
||||||
void (*dtor)(Expr*);
|
|
||||||
/* reflections */
|
|
||||||
bool (*is_literal)(const Expr*);
|
|
||||||
bool (*is_json_object)(const Expr*);
|
|
||||||
bool (*is_attrib)(const Expr*);
|
|
||||||
bool (*is_subscr)(const Expr*);
|
|
||||||
bool (*is_compare)(const Expr*);
|
|
||||||
int (*star_level)(const Expr*);
|
|
||||||
bool (*is_tuple)(const Expr*);
|
|
||||||
bool (*is_name)(const Expr*);
|
|
||||||
/* emit */
|
|
||||||
void (*emit_)(Expr*, CodeEmitContext*);
|
|
||||||
bool (*emit_del)(Expr*, CodeEmitContext*);
|
|
||||||
bool (*emit_store)(Expr*, CodeEmitContext*);
|
|
||||||
void (*emit_inplace)(Expr*, CodeEmitContext*);
|
|
||||||
bool (*emit_store_inplace)(Expr*, CodeEmitContext*);
|
|
||||||
};
|
|
||||||
|
|
||||||
void ExprVt__ctor(ExprVt* vt){
|
|
||||||
vt->dtor = default_dtor;
|
|
||||||
vt->is_literal = default_false;
|
|
||||||
vt->is_json_object = default_false;
|
|
||||||
vt->is_attrib = default_false;
|
|
||||||
vt->is_subscr = default_false;
|
|
||||||
vt->is_compare = default_false;
|
|
||||||
vt->star_level = default_zero;
|
|
||||||
vt->is_tuple = default_false;
|
|
||||||
vt->is_name = default_false;
|
|
||||||
vt->emit_ = NULL; // must be set
|
|
||||||
vt->emit_del = NULL;
|
|
||||||
vt->emit_store = NULL;
|
|
||||||
vt->emit_inplace = NULL;
|
|
||||||
vt->emit_store_inplace = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Expr {
|
struct Expr {
|
||||||
ExprVt* vt;
|
|
||||||
int line = 0;
|
int line = 0;
|
||||||
virtual ~Expr() = default;
|
virtual ~Expr() = default;
|
||||||
virtual void emit_(CodeEmitContext* ctx) = 0;
|
virtual void emit_(CodeEmitContext* ctx) = 0;
|
||||||
@ -80,36 +39,6 @@ struct Expr {
|
|||||||
[[nodiscard]] virtual bool emit_store_inplace(CodeEmitContext* ctx) { return emit_store(ctx); }
|
[[nodiscard]] virtual bool emit_store_inplace(CodeEmitContext* ctx) { return emit_store(ctx); }
|
||||||
};
|
};
|
||||||
|
|
||||||
void pk_Expr__emit_(Expr* self, CodeEmitContext* ctx){
|
|
||||||
assert(self->vt->emit_);
|
|
||||||
self->vt->emit_(self, ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool pk_Expr__emit_del(Expr* self, CodeEmitContext* ctx){
|
|
||||||
if(!self->vt->emit_del) return false;
|
|
||||||
return self->vt->emit_del(self, ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool pk_Expr__emit_store(Expr* self, CodeEmitContext* ctx){
|
|
||||||
if(!self->vt->emit_store) return false;
|
|
||||||
return self->vt->emit_store(self, ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
void pk_Expr__emit_inplace(Expr* self, CodeEmitContext* ctx){
|
|
||||||
if(!self->vt->emit_inplace){
|
|
||||||
pk_Expr__emit_(self, ctx);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
self->vt->emit_inplace(self, ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool pk_Expr__emit_store_inplace(Expr* self, CodeEmitContext* ctx){
|
|
||||||
if(!self->vt->emit_store_inplace){
|
|
||||||
return pk_Expr__emit_store(self, ctx);
|
|
||||||
}
|
|
||||||
return self->vt->emit_store_inplace(self, ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void delete_expr(Expr* p) noexcept{
|
inline void delete_expr(Expr* p) noexcept{
|
||||||
if(!p) return;
|
if(!p) return;
|
||||||
p->~Expr();
|
p->~Expr();
|
||||||
|
@ -175,7 +175,7 @@ PyObject* VM::bind_field(PyObject* obj, const char* name, F T::*field) {
|
|||||||
return obj; \
|
return obj; \
|
||||||
}, \
|
}, \
|
||||||
{}, \
|
{}, \
|
||||||
BindType::STATICMETHOD); \
|
BindType_STATICMETHOD); \
|
||||||
vm->bind_func(type, "tostruct", 1, [](VM* vm, ArgsView args) { \
|
vm->bind_func(type, "tostruct", 1, [](VM* vm, ArgsView args) { \
|
||||||
wT& self = _CAST(wT&, args[0]); \
|
wT& self = _CAST(wT&, args[0]); \
|
||||||
return vm->new_user_object<Struct>(&self, sizeof(wT)); \
|
return vm->new_user_object<Struct>(&self, sizeof(wT)); \
|
||||||
|
@ -362,25 +362,25 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if PK_REGION("General Bindings")
|
#if PK_REGION("General Bindings")
|
||||||
PyObject* bind_func(PyObject* obj, StrName name, int argc, NativeFuncC fn, any userdata={}, BindType bt=BindType::DEFAULT);
|
PyObject* bind_func(PyObject* obj, StrName name, int argc, NativeFuncC fn, any userdata={}, BindType bt=BindType_FUNCTION);
|
||||||
PyObject* bind_func(Type type, StrName name, int argc, NativeFuncC fn, any userdata={}, BindType bt=BindType::DEFAULT){
|
PyObject* bind_func(Type type, StrName name, int argc, NativeFuncC fn, any userdata={}, BindType bt=BindType_FUNCTION){
|
||||||
return bind_func(_t(type), name, argc, fn, std::move(userdata), bt);
|
return bind_func(_t(type), name, argc, fn, std::move(userdata), bt);
|
||||||
}
|
}
|
||||||
PyObject* bind_property(PyObject*, const char*, NativeFuncC fget, NativeFuncC fset=nullptr);
|
PyObject* bind_property(PyObject*, const char*, NativeFuncC fget, NativeFuncC fset=nullptr);
|
||||||
template<typename T, typename F, bool ReadOnly=false>
|
template<typename T, typename F, bool ReadOnly=false>
|
||||||
PyObject* bind_field(PyObject*, const char*, F T::*);
|
PyObject* bind_field(PyObject*, const char*, F T::*);
|
||||||
|
|
||||||
PyObject* bind(PyObject*, const char*, NativeFuncC, any userdata={}, BindType bt=BindType::DEFAULT);
|
PyObject* bind(PyObject*, const char*, NativeFuncC, any userdata={}, BindType bt=BindType_FUNCTION);
|
||||||
template<typename Ret, typename... Params>
|
template<typename Ret, typename... Params>
|
||||||
PyObject* bind(PyObject*, const char*, Ret(*)(Params...), BindType bt=BindType::DEFAULT);
|
PyObject* bind(PyObject*, const char*, Ret(*)(Params...), BindType bt=BindType_FUNCTION);
|
||||||
template<typename Ret, typename T, typename... Params>
|
template<typename Ret, typename T, typename... Params>
|
||||||
PyObject* bind(PyObject*, const char*, Ret(T::*)(Params...), BindType bt=BindType::DEFAULT);
|
PyObject* bind(PyObject*, const char*, Ret(T::*)(Params...), BindType bt=BindType_FUNCTION);
|
||||||
|
|
||||||
PyObject* bind(PyObject*, const char*, const char*, NativeFuncC, any userdata={}, BindType bt=BindType::DEFAULT);
|
PyObject* bind(PyObject*, const char*, const char*, NativeFuncC, any userdata={}, BindType bt=BindType_FUNCTION);
|
||||||
template<typename Ret, typename... Params>
|
template<typename Ret, typename... Params>
|
||||||
PyObject* bind(PyObject*, const char*, const char*, Ret(*)(Params...), BindType bt=BindType::DEFAULT);
|
PyObject* bind(PyObject*, const char*, const char*, Ret(*)(Params...), BindType bt=BindType_FUNCTION);
|
||||||
template<typename Ret, typename T, typename... Params>
|
template<typename Ret, typename T, typename... Params>
|
||||||
PyObject* bind(PyObject*, const char*, const char*, Ret(T::*)(Params...), BindType bt=BindType::DEFAULT);
|
PyObject* bind(PyObject*, const char*, const char*, Ret(T::*)(Params...), BindType bt=BindType_FUNCTION);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if PK_REGION("Error Reporting Methods")
|
#if PK_REGION("Error Reporting Methods")
|
||||||
|
57
include/pocketpy/objects/codeobject.h
Normal file
57
include/pocketpy/objects/codeobject.h
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define BC_NOARG 0
|
||||||
|
#define BC_KEEPLINE -1
|
||||||
|
|
||||||
|
typedef enum BindType {
|
||||||
|
BindType_FUNCTION,
|
||||||
|
BindType_STATICMETHOD,
|
||||||
|
BindType_CLASSMETHOD,
|
||||||
|
} BindType;
|
||||||
|
|
||||||
|
typedef enum FuncType {
|
||||||
|
FuncType_UNSET,
|
||||||
|
FuncType_NORMAL,
|
||||||
|
FuncType_SIMPLE,
|
||||||
|
FuncType_EMPTY,
|
||||||
|
FuncType_GENERATOR,
|
||||||
|
} FuncType;
|
||||||
|
|
||||||
|
typedef enum NameScope {
|
||||||
|
NAME_LOCAL,
|
||||||
|
NAME_GLOBAL,
|
||||||
|
NAME_GLOBAL_UNKNOWN
|
||||||
|
} NameScope;
|
||||||
|
|
||||||
|
typedef enum CodeBlockType {
|
||||||
|
NO_BLOCK,
|
||||||
|
FOR_LOOP,
|
||||||
|
WHILE_LOOP,
|
||||||
|
CONTEXT_MANAGER,
|
||||||
|
TRY_EXCEPT,
|
||||||
|
} CodeBlockType;
|
||||||
|
|
||||||
|
typedef enum Opcode {
|
||||||
|
#define OPCODE(name) OP_##name,
|
||||||
|
#include "pocketpy/xmacros/opcodes.h"
|
||||||
|
#undef OPCODE
|
||||||
|
} Opcode;
|
||||||
|
|
||||||
|
typedef struct Bytecode {
|
||||||
|
uint8_t op;
|
||||||
|
uint16_t arg;
|
||||||
|
} Bytecode;
|
||||||
|
|
||||||
|
void Bytecode__set_signed_arg(Bytecode* self, int arg);
|
||||||
|
bool Bytecode__is_forward_jump(const Bytecode* self);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
@ -6,49 +6,12 @@
|
|||||||
#include "pocketpy/objects/namedict.hpp"
|
#include "pocketpy/objects/namedict.hpp"
|
||||||
#include "pocketpy/objects/sourcedata.h"
|
#include "pocketpy/objects/sourcedata.h"
|
||||||
#include "pocketpy/common/smallmap.h"
|
#include "pocketpy/common/smallmap.h"
|
||||||
|
#include "pocketpy/objects/codeobject.h"
|
||||||
|
|
||||||
namespace pkpy {
|
namespace pkpy {
|
||||||
|
|
||||||
typedef PyVar (*NativeFuncC)(VM*, ArgsView);
|
typedef PyVar (*NativeFuncC)(VM*, ArgsView);
|
||||||
|
|
||||||
enum class BindType {
|
|
||||||
DEFAULT,
|
|
||||||
STATICMETHOD,
|
|
||||||
CLASSMETHOD,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum NameScope { NAME_LOCAL, NAME_GLOBAL, NAME_GLOBAL_UNKNOWN };
|
|
||||||
|
|
||||||
enum Opcode : uint8_t {
|
|
||||||
|
|
||||||
#define OPCODE(name) OP_##name,
|
|
||||||
#include "pocketpy/xmacros/opcodes.h"
|
|
||||||
#undef OPCODE
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Bytecode {
|
|
||||||
uint8_t op;
|
|
||||||
uint16_t arg;
|
|
||||||
|
|
||||||
void set_signed_arg(int arg) {
|
|
||||||
assert(arg >= INT16_MIN && arg <= INT16_MAX);
|
|
||||||
this->arg = (int16_t)arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_forward_jump() const { return op >= OP_JUMP_FORWARD && op <= OP_LOOP_BREAK; }
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class CodeBlockType {
|
|
||||||
NO_BLOCK,
|
|
||||||
FOR_LOOP,
|
|
||||||
WHILE_LOOP,
|
|
||||||
CONTEXT_MANAGER,
|
|
||||||
TRY_EXCEPT,
|
|
||||||
};
|
|
||||||
|
|
||||||
const inline uint8_t BC_NOARG = 0;
|
|
||||||
const inline int BC_KEEPLINE = -1;
|
|
||||||
|
|
||||||
struct CodeBlock {
|
struct CodeBlock {
|
||||||
CodeBlockType type;
|
CodeBlockType type;
|
||||||
int parent; // parent index in blocks
|
int parent; // parent index in blocks
|
||||||
@ -116,14 +79,6 @@ struct CodeObject {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class FuncType {
|
|
||||||
UNSET,
|
|
||||||
NORMAL,
|
|
||||||
SIMPLE,
|
|
||||||
EMPTY,
|
|
||||||
GENERATOR,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FuncDecl {
|
struct FuncDecl {
|
||||||
struct KwArg {
|
struct KwArg {
|
||||||
int index; // index in co->varnames
|
int index; // index in co->varnames
|
||||||
@ -142,7 +97,7 @@ struct FuncDecl {
|
|||||||
|
|
||||||
const char* docstring; // docstring of this function (weak ref)
|
const char* docstring; // docstring of this function (weak ref)
|
||||||
|
|
||||||
FuncType type = FuncType::UNSET;
|
FuncType type = FuncType_UNSET;
|
||||||
c11_smallmap_n2i kw_to_index;
|
c11_smallmap_n2i kw_to_index;
|
||||||
|
|
||||||
void add_kwarg(int index, StrName key, PyVar value) {
|
void add_kwarg(int index, StrName key, PyVar value) {
|
||||||
|
@ -60,9 +60,9 @@ Error* Compiler::pop_context() noexcept{
|
|||||||
for(int i = 0; i < codes.size(); i++) {
|
for(int i = 0; i < codes.size(); i++) {
|
||||||
Bytecode& bc = codes[i];
|
Bytecode& bc = codes[i];
|
||||||
if(bc.op == OP_LOOP_CONTINUE) {
|
if(bc.op == OP_LOOP_CONTINUE) {
|
||||||
bc.set_signed_arg(ctx()->co->blocks[bc.arg].start - i);
|
Bytecode__set_signed_arg(&bc, ctx()->co->blocks[bc.arg].start - i);
|
||||||
} else if(bc.op == OP_LOOP_BREAK) {
|
} else if(bc.op == OP_LOOP_BREAK) {
|
||||||
bc.set_signed_arg(ctx()->co->blocks[bc.arg].get_break_end() - i);
|
Bytecode__set_signed_arg(&bc, ctx()->co->blocks[bc.arg].get_break_end() - i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// pre-compute func->is_simple
|
// pre-compute func->is_simple
|
||||||
@ -71,7 +71,7 @@ Error* Compiler::pop_context() noexcept{
|
|||||||
// check generator
|
// check generator
|
||||||
for(Bytecode bc: func->code->codes) {
|
for(Bytecode bc: func->code->codes) {
|
||||||
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) {
|
for(Bytecode bc: func->code->codes) {
|
||||||
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");
|
||||||
@ -80,26 +80,26 @@ Error* Compiler::pop_context() noexcept{
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(func->type == FuncType::UNSET) {
|
if(func->type == FuncType_UNSET) {
|
||||||
bool is_simple = true;
|
bool is_simple = true;
|
||||||
if(func->kwargs.size() > 0) is_simple = false;
|
if(func->kwargs.size() > 0) is_simple = false;
|
||||||
if(func->starred_arg >= 0) is_simple = false;
|
if(func->starred_arg >= 0) is_simple = false;
|
||||||
if(func->starred_kwarg >= 0) is_simple = false;
|
if(func->starred_kwarg >= 0) is_simple = false;
|
||||||
|
|
||||||
if(is_simple) {
|
if(is_simple) {
|
||||||
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.size() == 1) {
|
||||||
Bytecode bc = func->code->codes[0];
|
Bytecode bc = 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
|
||||||
func->type = FuncType::NORMAL;
|
func->type = FuncType_NORMAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(func->type != FuncType::UNSET);
|
assert(func->type != FuncType_UNSET);
|
||||||
}
|
}
|
||||||
contexts.back().s_clean();
|
contexts.back().s_clean();
|
||||||
contexts.pop_back();
|
contexts.pop_back();
|
||||||
@ -822,7 +822,7 @@ Error* Compiler::compile_try_except() noexcept{
|
|||||||
i64 target = ctx()->co->codes.size() + 2;
|
i64 target = ctx()->co->codes.size() + 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);
|
||||||
ctx()->co->codes[i].set_signed_arg(finally_entry - i);
|
Bytecode__set_signed_arg(&ctx()->co->codes[i], finally_entry - i);
|
||||||
}
|
}
|
||||||
ctx()->emit_(OP_RE_RAISE, BC_NOARG, BC_KEEPLINE);
|
ctx()->emit_(OP_RE_RAISE, BC_NOARG, BC_KEEPLINE);
|
||||||
|
|
||||||
@ -833,7 +833,7 @@ Error* Compiler::compile_try_except() noexcept{
|
|||||||
i64 target = ctx()->co->codes.size() + 2;
|
i64 target = ctx()->co->codes.size() + 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);
|
||||||
ctx()->co->codes[i].set_signed_arg(finally_entry - i);
|
Bytecode__set_signed_arg(&ctx()->co->codes[i], finally_entry - i);
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
59
src/compiler/expr.c
Normal file
59
src/compiler/expr.c
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
// #include "pocketpy/compiler/expr.h"
|
||||||
|
// #include "pocketpy/common/memorypool.h"
|
||||||
|
|
||||||
|
// static bool default_false(const pk_Expr*) { return false; }
|
||||||
|
// static int default_zero(const pk_Expr*) { return 0; }
|
||||||
|
// static void default_dtor(pk_Expr*) {}
|
||||||
|
|
||||||
|
// void pk_ExprVt__ctor(pk_ExprVt* vt){
|
||||||
|
// vt->dtor = default_dtor;
|
||||||
|
// vt->is_literal = default_false;
|
||||||
|
// vt->is_json_object = default_false;
|
||||||
|
// vt->is_attrib = default_false;
|
||||||
|
// vt->is_subscr = default_false;
|
||||||
|
// vt->is_compare = default_false;
|
||||||
|
// vt->star_level = default_zero;
|
||||||
|
// vt->is_tuple = default_false;
|
||||||
|
// vt->is_name = default_false;
|
||||||
|
// vt->emit_ = NULL; // must be set
|
||||||
|
// vt->emit_del = NULL;
|
||||||
|
// vt->emit_store = NULL;
|
||||||
|
// vt->emit_inplace = NULL;
|
||||||
|
// vt->emit_store_inplace = NULL;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// void pk_Expr__emit_(pk_Expr* self, pk_CodeEmitContext* ctx){
|
||||||
|
// assert(self->vt->emit_);
|
||||||
|
// self->vt->emit_(self, ctx);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// bool pk_Expr__emit_del(pk_Expr* self, pk_CodeEmitContext* ctx){
|
||||||
|
// if(!self->vt->emit_del) return false;
|
||||||
|
// return self->vt->emit_del(self, ctx);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// bool pk_Expr__emit_store(pk_Expr* self, pk_CodeEmitContext* ctx){
|
||||||
|
// if(!self->vt->emit_store) return false;
|
||||||
|
// return self->vt->emit_store(self, ctx);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// void pk_Expr__emit_inplace(pk_Expr* self, pk_CodeEmitContext* ctx){
|
||||||
|
// if(!self->vt->emit_inplace){
|
||||||
|
// pk_Expr__emit_(self, ctx);
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// self->vt->emit_inplace(self, ctx);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// bool pk_Expr__emit_store_inplace(pk_Expr* self, pk_CodeEmitContext* ctx){
|
||||||
|
// if(!self->vt->emit_store_inplace){
|
||||||
|
// return pk_Expr__emit_store(self, ctx);
|
||||||
|
// }
|
||||||
|
// return self->vt->emit_store_inplace(self, ctx);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// void pk_Expr__delete(pk_Expr* self){
|
||||||
|
// if(!self) return;
|
||||||
|
// self->vt->dtor(self);
|
||||||
|
// PoolExpr_dealloc(self);
|
||||||
|
// }
|
@ -101,7 +101,7 @@ 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();
|
int target = co->codes.size();
|
||||||
co->codes[index].set_signed_arg(target - index);
|
Bytecode__set_signed_arg(&co->codes[index], target - index);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CodeEmitContext::add_label(StrName name) noexcept{
|
bool CodeEmitContext::add_label(StrName name) noexcept{
|
||||||
|
@ -84,7 +84,7 @@ void Struct::_register(VM* vm, PyObject* mod, PyObject* type) {
|
|||||||
return vm->new_user_object<Struct>(std::move(buffer));
|
return vm->new_user_object<Struct>(std::move(buffer));
|
||||||
},
|
},
|
||||||
{},
|
{},
|
||||||
BindType::STATICMETHOD);
|
BindType_STATICMETHOD);
|
||||||
|
|
||||||
vm->bind__repr__(type->as<Type>(), [](VM* vm, PyVar obj) {
|
vm->bind__repr__(type->as<Type>(), [](VM* vm, PyVar obj) {
|
||||||
Struct& self = _CAST(Struct&, obj);
|
Struct& self = _CAST(Struct&, obj);
|
||||||
|
@ -738,7 +738,7 @@ PyObject* VM::new_module(Str name, Str package) {
|
|||||||
|
|
||||||
static std::string _opcode_argstr(VM* vm, int i, Bytecode byte, const CodeObject* co) {
|
static std::string _opcode_argstr(VM* vm, int i, Bytecode byte, const CodeObject* co) {
|
||||||
SStream ss;
|
SStream ss;
|
||||||
if(byte.is_forward_jump()) {
|
if(Bytecode__is_forward_jump(&byte)){
|
||||||
std::string argStr = std::to_string((int16_t)byte.arg);
|
std::string argStr = std::to_string((int16_t)byte.arg);
|
||||||
ss << (i64)(int16_t)byte.arg;
|
ss << (i64)(int16_t)byte.arg;
|
||||||
ss << " (to " << (i64)((int16_t)byte.arg + i) << ")";
|
ss << " (to " << (i64)((int16_t)byte.arg + i) << ")";
|
||||||
@ -784,7 +784,9 @@ 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.size(); i++) {
|
||||||
Bytecode byte = co->codes[i];
|
Bytecode byte = co->codes[i];
|
||||||
if(byte.is_forward_jump()) { jumpTargets.push_back((int16_t)byte.arg + i); }
|
if(Bytecode__is_forward_jump(&byte)) {
|
||||||
|
jumpTargets.push_back((int16_t)byte.arg + i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
SStream ss;
|
SStream ss;
|
||||||
int prev_line = -1;
|
int prev_line = -1;
|
||||||
@ -1070,14 +1072,14 @@ PyVar VM::vectorcall(int ARGC, int KWARGC, bool op_call) {
|
|||||||
const CodeObject* co = fn.decl->code.get();
|
const CodeObject* co = fn.decl->code.get();
|
||||||
|
|
||||||
switch(fn.decl->type) {
|
switch(fn.decl->type) {
|
||||||
case FuncType::NORMAL:
|
case FuncType_NORMAL:
|
||||||
__prepare_py_call(__vectorcall_buffer, args, kwargs, fn.decl);
|
__prepare_py_call(__vectorcall_buffer, args, kwargs, fn.decl);
|
||||||
// copy buffer back to stack
|
// copy buffer back to stack
|
||||||
s_data.reset(_base + co->nlocals);
|
s_data.reset(_base + co->nlocals);
|
||||||
for(int j = 0; j < co->nlocals; j++)
|
for(int j = 0; j < co->nlocals; j++)
|
||||||
_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.size())
|
||||||
TypeError(_S(co->name,
|
TypeError(_S(co->name,
|
||||||
"() takes ",
|
"() takes ",
|
||||||
@ -1092,7 +1094,7 @@ PyVar VM::vectorcall(int ARGC, int KWARGC, bool op_call) {
|
|||||||
// initialize local variables to PY_NULL
|
// initialize local variables to PY_NULL
|
||||||
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.size())
|
||||||
TypeError(_S(co->name,
|
TypeError(_S(co->name,
|
||||||
"() takes ",
|
"() takes ",
|
||||||
@ -1103,7 +1105,7 @@ PyVar VM::vectorcall(int ARGC, int KWARGC, bool op_call) {
|
|||||||
if(!kwargs.empty()) TypeError(_S(co->name, "() takes no keyword arguments"));
|
if(!kwargs.empty()) TypeError(_S(co->name, "() takes no keyword arguments"));
|
||||||
s_data.reset(p0);
|
s_data.reset(p0);
|
||||||
return None;
|
return None;
|
||||||
case FuncType::GENERATOR:
|
case FuncType_GENERATOR:
|
||||||
__prepare_py_call(__vectorcall_buffer, args, kwargs, fn.decl);
|
__prepare_py_call(__vectorcall_buffer, args, kwargs, fn.decl);
|
||||||
s_data.reset(p0);
|
s_data.reset(p0);
|
||||||
callstack.emplace(nullptr, co, fn._module, callable.get(), nullptr);
|
callstack.emplace(nullptr, co, fn._module, callable.get(), nullptr);
|
||||||
@ -1360,9 +1362,9 @@ void VM::setattr(PyVar obj, StrName name, PyVar value) {
|
|||||||
PyObject* VM::bind_func(PyObject* obj, StrName name, int argc, NativeFuncC fn, any userdata, BindType bt) {
|
PyObject* VM::bind_func(PyObject* obj, StrName name, int argc, NativeFuncC fn, any userdata, BindType bt) {
|
||||||
PyObject* nf = new_object<NativeFunc>(tp_native_func, fn, argc, std::move(userdata)).get();
|
PyObject* nf = new_object<NativeFunc>(tp_native_func, fn, argc, std::move(userdata)).get();
|
||||||
switch(bt) {
|
switch(bt) {
|
||||||
case BindType::DEFAULT: break;
|
case BindType_FUNCTION: break;
|
||||||
case BindType::STATICMETHOD: nf = new_object<StaticMethod>(tp_staticmethod, nf).get(); break;
|
case BindType_STATICMETHOD: nf = new_object<StaticMethod>(tp_staticmethod, nf).get(); break;
|
||||||
case BindType::CLASSMETHOD: nf = new_object<ClassMethod>(tp_classmethod, nf).get(); break;
|
case BindType_CLASSMETHOD: nf = new_object<ClassMethod>(tp_classmethod, nf).get(); break;
|
||||||
}
|
}
|
||||||
if(obj != nullptr) obj->attr().set(name, nf);
|
if(obj != nullptr) obj->attr().set(name, nf);
|
||||||
return nf;
|
return nf;
|
||||||
@ -1385,9 +1387,9 @@ PyObject* VM::bind(PyObject* obj, const char* sig, const char* docstring, Native
|
|||||||
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();
|
||||||
|
|
||||||
switch(bt) {
|
switch(bt) {
|
||||||
case BindType::STATICMETHOD: f_obj = new_object<StaticMethod>(tp_staticmethod, f_obj).get(); break;
|
case BindType_STATICMETHOD: f_obj = new_object<StaticMethod>(tp_staticmethod, f_obj).get(); break;
|
||||||
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::DEFAULT: break;
|
case BindType_FUNCTION: break;
|
||||||
}
|
}
|
||||||
if(obj != nullptr) obj->attr().set(decl->code->name, f_obj);
|
if(obj != nullptr) obj->attr().set(decl->code->name, f_obj);
|
||||||
return f_obj;
|
return f_obj;
|
||||||
|
@ -152,7 +152,7 @@ void Vec2::_register(VM* vm, PyObject* mod, PyObject* type) {
|
|||||||
return VAR(Tuple(VAR(ret), VAR(current_velocity_)));
|
return VAR(Tuple(VAR(ret), VAR(current_velocity_)));
|
||||||
},
|
},
|
||||||
{},
|
{},
|
||||||
BindType::STATICMETHOD);
|
BindType_STATICMETHOD);
|
||||||
|
|
||||||
// @staticmethod
|
// @staticmethod
|
||||||
vm->bind(
|
vm->bind(
|
||||||
@ -168,7 +168,7 @@ void Vec2::_register(VM* vm, PyObject* mod, PyObject* type) {
|
|||||||
return VAR(val);
|
return VAR(val);
|
||||||
},
|
},
|
||||||
{},
|
{},
|
||||||
BindType::STATICMETHOD);
|
BindType_STATICMETHOD);
|
||||||
|
|
||||||
vm->bind__repr__(type->as<Type>(), [](VM* vm, PyVar obj) -> Str {
|
vm->bind__repr__(type->as<Type>(), [](VM* vm, PyVar obj) -> Str {
|
||||||
Vec2 self = _CAST(Vec2, obj);
|
Vec2 self = _CAST(Vec2, obj);
|
||||||
@ -452,7 +452,7 @@ void Mat3x3::_register(VM* vm, PyObject* mod, PyObject* type) {
|
|||||||
return vm->new_user_object<Mat3x3>(Mat3x3::zeros());
|
return vm->new_user_object<Mat3x3>(Mat3x3::zeros());
|
||||||
},
|
},
|
||||||
{},
|
{},
|
||||||
BindType::STATICMETHOD);
|
BindType_STATICMETHOD);
|
||||||
|
|
||||||
// @staticmethod
|
// @staticmethod
|
||||||
vm->bind_func(
|
vm->bind_func(
|
||||||
@ -463,7 +463,7 @@ void Mat3x3::_register(VM* vm, PyObject* mod, PyObject* type) {
|
|||||||
return vm->new_user_object<Mat3x3>(Mat3x3::ones());
|
return vm->new_user_object<Mat3x3>(Mat3x3::ones());
|
||||||
},
|
},
|
||||||
{},
|
{},
|
||||||
BindType::STATICMETHOD);
|
BindType_STATICMETHOD);
|
||||||
|
|
||||||
// @staticmethod
|
// @staticmethod
|
||||||
vm->bind_func(
|
vm->bind_func(
|
||||||
@ -474,7 +474,7 @@ void Mat3x3::_register(VM* vm, PyObject* mod, PyObject* type) {
|
|||||||
return vm->new_user_object<Mat3x3>(Mat3x3::identity());
|
return vm->new_user_object<Mat3x3>(Mat3x3::identity());
|
||||||
},
|
},
|
||||||
{},
|
{},
|
||||||
BindType::STATICMETHOD);
|
BindType_STATICMETHOD);
|
||||||
|
|
||||||
/*************** affine transformations ***************/
|
/*************** affine transformations ***************/
|
||||||
// @staticmethod
|
// @staticmethod
|
||||||
@ -488,7 +488,7 @@ void Mat3x3::_register(VM* vm, PyObject* mod, PyObject* type) {
|
|||||||
return vm->new_user_object<Mat3x3>(Mat3x3::trs(t, r, s));
|
return vm->new_user_object<Mat3x3>(Mat3x3::trs(t, r, s));
|
||||||
},
|
},
|
||||||
{},
|
{},
|
||||||
BindType::STATICMETHOD);
|
BindType_STATICMETHOD);
|
||||||
|
|
||||||
vm->bind(type, "copy_trs_(self, t: vec2, r: float, s: vec2)", [](VM* vm, ArgsView args) {
|
vm->bind(type, "copy_trs_(self, t: vec2, r: float, s: vec2)", [](VM* vm, ArgsView args) {
|
||||||
Mat3x3& self = _CAST(Mat3x3&, args[0]);
|
Mat3x3& self = _CAST(Mat3x3&, args[0]);
|
||||||
|
13
src/objects/codeobject.c
Normal file
13
src/objects/codeobject.c
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#include "pocketpy/objects/codeobject.h"
|
||||||
|
#include "pocketpy/common/utils.h"
|
||||||
|
|
||||||
|
void Bytecode__set_signed_arg(Bytecode* self, int arg) {
|
||||||
|
if(arg < INT16_MIN || arg > INT16_MAX) {
|
||||||
|
PK_FATAL_ERROR("set_signed_arg: %d is out of range", arg);
|
||||||
|
}
|
||||||
|
self->arg = (int16_t)arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Bytecode__is_forward_jump(const Bytecode* self) {
|
||||||
|
return self->op >= OP_JUMP_FORWARD && self->op <= OP_LOOP_BREAK;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user