Compare commits

...

13 Commits

Author SHA1 Message Date
blueloveTH
5be3300554 fix initial demo 2024-06-29 21:14:11 +08:00
blueloveTH
f53ae5e459 some fix 2024-06-29 19:44:38 +08:00
blueloveTH
6c46705e98 some fix 2024-06-29 19:39:28 +08:00
blueloveTH
455aa576e5 some fix 2024-06-29 19:35:11 +08:00
blueloveTH
4a5f74b2d2 some move 2024-06-29 18:54:05 +08:00
blueloveTH
a55d3a5340 global replace 2024-06-29 18:34:38 +08:00
blueloveTH
773a05e25c some fix 2024-06-29 17:31:42 +08:00
blueloveTH
c4897ea0fb Update compiler.c 2024-06-29 17:21:43 +08:00
blueloveTH
0963929a30 some up 2024-06-29 17:01:09 +08:00
blueloveTH
23b523b788 some fix 2024-06-29 16:36:30 +08:00
blueloveTH
14a01c0e6d Update compiler.c 2024-06-29 14:38:52 +08:00
blueloveTH
a03a3bdbf8 some fix 2024-06-29 14:34:38 +08:00
blueloveTH
3610e87244 merge to compiler.c 2024-06-29 14:16:12 +08:00
40 changed files with 3648 additions and 3183 deletions

View File

@ -5,8 +5,8 @@ python prebuild.py
SRC=$(find src/ -name "*.c")
FLAGS="-std=c11 -lm -Iinclude -O0 -Wfatal-errors -g -DDEBUG -DPK_ENABLE_OS=1"
# SANITIZE_FLAGS="-fsanitize=address,leak,undefined"
SANITIZE_FLAGS=""
SANITIZE_FLAGS="-fsanitize=address,leak,undefined"
# SANITIZE_FLAGS=""
echo "Compiling C files..."
clang $FLAGS $SANITIZE_FLAGS $SRC src2/main.c -o main

View File

@ -43,8 +43,8 @@
/*************** internal settings ***************/
// This is the maximum size of the value stack in PyVar units
// The actual size in bytes equals `sizeof(PyVar) * PK_VM_STACK_SIZE`
// This is the maximum size of the value stack in py_TValue units
// The actual size in bytes equals `sizeof(py_TValue) * PK_VM_STACK_SIZE`
#define PK_VM_STACK_SIZE 16384
// This is the maximum number of local variables in a function

View File

@ -14,6 +14,7 @@ typedef uint16_t StrName;
uint16_t pk_StrName__map(const char*);
uint16_t pk_StrName__map2(c11_string);
const char* pk_StrName__rmap(uint16_t index);
c11_string pk_StrName__rmap2(uint16_t index);
void pk_StrName__initialize();
void pk_StrName__finalize();

View File

@ -1,141 +0,0 @@
#pragma once
#include "pocketpy/compiler/expr.hpp"
#include "pocketpy/objects/error.hpp"
namespace pkpy {
struct Compiler;
typedef Error* (Compiler::*PrattCallback)() noexcept;
struct PrattRule {
PrattCallback prefix;
PrattCallback infix;
Precedence precedence;
};
struct Compiler {
PK_ALWAYS_PASS_BY_POINTER(Compiler)
static PrattRule rules[TK__COUNT__];
Lexer lexer;
vector<CodeEmitContext> contexts;
VM* vm;
bool unknown_global_scope; // for eval/exec() call
// for parsing token stream
int __i = 0;
const Token& tk(int i) const noexcept{ return lexer.nexts[i]; }
const Token& prev() const noexcept{ return tk(__i - 1); }
const Token& curr() const noexcept{ return tk(__i); }
const Token& next() const noexcept{ return tk(__i + 1); }
const Token& err() const noexcept{
if(__i >= lexer.nexts.size()) return prev();
return curr();
}
void advance(int delta = 1) noexcept{
__i += delta;
#if PK_DEBUG_COMPILER
if(__i>=0 && __i<lexer.nexts.size()){
printf("%s:%d %s %s\n",
lexer.src.filename().c_str(),
curr().line,
pk_TokenSymbols(curr().type),
curr().str().escape().c_str()
);
}
#endif
}
CodeEmitContext* ctx() noexcept{ return &contexts.back(); }
CompileMode mode() const noexcept{ return lexer.src->mode; }
NameScope name_scope() const noexcept;
CodeObject* push_global_context() noexcept;
FuncDecl_ push_f_context(c11_string name, int* out_index) noexcept;
static void init_pratt_rules() noexcept;
bool match(TokenIndex expected) noexcept;
bool match_end_stmt() noexcept;
bool match_newlines(bool* need_more_lines = NULL) noexcept;
/*************************************************/
[[nodiscard]] Error* EXPR() noexcept{ return parse_expression(PREC_LOWEST + 1); }
[[nodiscard]] Error* EXPR_TUPLE(bool allow_slice = false) noexcept;
[[nodiscard]] Error* EXPR_VARS() noexcept; // special case for `for loop` and `comp`
template <typename T, typename... Args>
T* make_expr(Args&&... args) noexcept{
static_assert(sizeof(T) <= kPoolExprBlockSize);
static_assert(std::is_base_of_v<Expr, T>);
void* p = PoolExpr_alloc();
T* expr = new (p) T(std::forward<Args>(args)...);
expr->line = prev().line;
return expr;
}
[[nodiscard]] Error* consume_comp(Opcode op0, Opcode op1) noexcept;
[[nodiscard]] Error* pop_context() noexcept;
Error* exprLiteral() noexcept;
Error* exprLong() noexcept;
Error* exprImag() noexcept;
Error* exprBytes() noexcept;
Error* exprFString() noexcept;
Error* exprLambda() noexcept;
Error* exprOr() noexcept;
Error* exprAnd() noexcept;
Error* exprTernary() noexcept;
Error* exprBinaryOp() noexcept;
Error* exprNot() noexcept;
Error* exprUnaryOp() noexcept;
Error* exprGroup() noexcept;
Error* exprList() noexcept;
Error* exprMap() noexcept;
Error* exprCall() noexcept;
Error* exprName() noexcept;
Error* exprAttrib() noexcept;
Error* exprSlice0() noexcept;
Error* exprSlice1() noexcept;
Error* exprSubscr() noexcept;
Error* exprLiteral0() noexcept;
bool is_expression(bool allow_slice = false) noexcept;
[[nodiscard]] Error* compile_block_body(PrattCallback callback = NULL) noexcept;
[[nodiscard]] Error* compile_normal_import() noexcept;
[[nodiscard]] Error* compile_from_import() noexcept;
[[nodiscard]] Error* parse_expression(int precedence, bool allow_slice = false) noexcept;
[[nodiscard]] Error* compile_if_stmt() noexcept;
[[nodiscard]] Error* compile_while_loop() noexcept;
[[nodiscard]] Error* compile_for_loop() noexcept;
[[nodiscard]] Error* compile_try_except() noexcept;
[[nodiscard]] Error* compile_decorated() noexcept;
[[nodiscard]] Error* try_compile_assignment(bool* is_assign) noexcept;
[[nodiscard]] Error* compile_stmt() noexcept;
[[nodiscard]] Error* consume_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_class(int decorators = 0) noexcept;
PyVar to_object(const TokenValue& value) noexcept;
[[nodiscard]] Error* read_literal(PyVar* out) noexcept;
[[nodiscard]] Error* SyntaxError(const char* msg = "invalid syntax", ...) noexcept;
[[nodiscard]] Error* IndentationError(const char* msg) noexcept{ return lexer._error(false, "IndentationError", msg, {}); }
[[nodiscard]] Error* NeedMoreLines() noexcept{
return lexer._error(false, "NeedMoreLines", "", {}, (i64)ctx()->is_compiling_class);
}
public:
Compiler(VM* vm, std::string_view source, const Str& filename, CompileMode mode, bool unknown_global_scope = false) noexcept;
[[nodiscard]] Error* compile(CodeObject** out) noexcept;
~Compiler();
};
} // namespace pkpy

View File

@ -1,60 +0,0 @@
#pragma once
#include "pocketpy/objects/codeobject.h"
#include "pocketpy/common/strname.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct pk_CodeEmitContext{
CodeObject* co; // 1 CodeEmitContext <=> 1 CodeObject*
FuncDecl* func; // optional, weakref
int level;
int curr_iblock;
bool is_compiling_class;
c11_vector/*T=Expr* */ s_expr;
c11_vector/*T=StrName*/ global_names;
c11_smallmap_s2n co_consts_string_dedup_map;
} pk_CodeEmitContext;
typedef struct pk_Expr pk_Expr;
void pk_CodeEmitContext__ctor(pk_CodeEmitContext* self, CodeObject* co, FuncDecl* func, int level);
void pk_CodeEmitContext__dtor(pk_CodeEmitContext* self);
int pk_CodeEmitContext__get_loop(pk_CodeEmitContext* self);
CodeBlock* pk_CodeEmitContext__enter_block(pk_CodeEmitContext* self, CodeBlockType type);
void pk_CodeEmitContext__exit_block(pk_CodeEmitContext* self);
int pk_CodeEmitContext__emit_(pk_CodeEmitContext* self, Opcode opcode, uint16_t arg, int line);
int pk_CodeEmitContext__emit_virtual(pk_CodeEmitContext* self, Opcode opcode, uint16_t arg, int line);
void pk_CodeEmitContext__revert_last_emit_(pk_CodeEmitContext* self);
int pk_CodeEmitContext__emit_int(pk_CodeEmitContext* self, int64_t value, int line);
void pk_CodeEmitContext__patch_jump(pk_CodeEmitContext* self, int index);
bool pk_CodeEmitContext__add_label(pk_CodeEmitContext* self, StrName name);
int pk_CodeEmitContext__add_varname(pk_CodeEmitContext* self, StrName name);
int pk_CodeEmitContext__add_const(pk_CodeEmitContext* self, py_Ref);
int pk_CodeEmitContext__add_const_string(pk_CodeEmitContext* self, c11_string);
void pk_CodeEmitContext__emit_store_name(pk_CodeEmitContext* self, NameScope scope, StrName name, int line);
void pk_CodeEmitContext__try_merge_for_iter_store(pk_CodeEmitContext* self, int);
// emit top -> pop -> delete
void pk_CodeEmitContext__s_emit_top(pk_CodeEmitContext*);
// push
void pk_CodeEmitContext__s_push(pk_CodeEmitContext*, pk_Expr*);
// top
pk_Expr* pk_CodeEmitContext__s_top(pk_CodeEmitContext*);
// size
int pk_CodeEmitContext__s_size(pk_CodeEmitContext*);
// pop -> delete
void pk_CodeEmitContext__s_pop(pk_CodeEmitContext*);
// pop move
pk_Expr* pk_CodeEmitContext__s_popx(pk_CodeEmitContext*);
// clean
void pk_CodeEmitContext__s_clean(pk_CodeEmitContext*);
// emit decorators
void pk_CodeEmitContext__s_emit_decorators(pk_CodeEmitContext*, int count);
#ifdef __cplusplus
}
#endif

View File

@ -1,151 +0,0 @@
#pragma once
#include <stdbool.h>
#include "pocketpy/common/memorypool.h"
#include "pocketpy/compiler/lexer.h"
#include "pocketpy/common/strname.h"
#include "pocketpy/objects/codeobject.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct pk_Expr pk_Expr;
typedef struct pk_CodeEmitContext pk_CodeEmitContext;
typedef struct pk_ExprVt{
void (*dtor)(pk_Expr*);
/* reflections */
bool is_literal;
bool is_json_object;
bool is_name;
bool is_tuple;
bool is_attrib;
bool is_subscr;
bool (*is_compare)(const pk_Expr*);
int (*star_level)(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*);
} pk_ExprVt;
#define COMMON_HEADER \
pk_ExprVt* vt; \
int line;
typedef struct pk_Expr{
COMMON_HEADER
} pk_Expr;
void pk_ExprVt__ctor(pk_ExprVt* vt);
void pk_Expr__delete(pk_Expr* self);
void pk_Expr__initialize();
#define pk_Expr__finalize() // do nothing
typedef struct pk_NameExpr{
COMMON_HEADER
StrName name;
NameScope scope;
} pk_NameExpr;
typedef struct pk_StarredExpr{
COMMON_HEADER
pk_Expr* child;
int level;
} pk_StarredExpr;
// InvertExpr, NotExpr, NegatedExpr
// NOTE: NegatedExpr always contains a non-const child. Should not generate -1 or -0.1
typedef struct pk_UnaryExpr{
COMMON_HEADER
pk_Expr* child;
Opcode opcode;
} pk_UnaryExpr;
// LongExpr, BytesExpr
typedef struct pk_RawStringExpr{
COMMON_HEADER
c11_string value;
Opcode opcode;
} pk_RawStringExpr;
typedef struct pk_ImagExpr{
COMMON_HEADER
double value;
} pk_ImagExpr;
typedef struct pk_LiteralExpr{
COMMON_HEADER
const TokenValue* value;
} pk_LiteralExpr;
typedef struct pk_SliceExpr{
COMMON_HEADER
pk_Expr* start;
pk_Expr* stop;
pk_Expr* step;
} pk_SliceExpr;
// ListExpr, DictExpr, SetExpr, TupleExpr
typedef struct pk_SequenceExpr{
COMMON_HEADER
c11_array/*T=Expr* */ items;
Opcode opcode;
} pk_SequenceExpr;
typedef struct pk_CompExpr{
COMMON_HEADER
pk_Expr* expr; // loop expr
pk_Expr* vars; // loop vars
pk_Expr* iter; // loop iter
pk_Expr* cond; // optional if condition
Opcode op0;
Opcode op1;
} pk_CompExpr;
typedef struct pk_LambdaExpr{
COMMON_HEADER
int index;
} pk_LambdaExpr;
typedef struct pk_FStringExpr{
COMMON_HEADER
c11_string src;
} pk_FStringExpr;
// AndExpr, OrExpr
typedef struct pk_LogicBinaryExpr{
COMMON_HEADER
pk_Expr* lhs;
pk_Expr* rhs;
Opcode opcode;
} pk_LogicBinaryExpr;
typedef struct pk_GroupedExpr{
COMMON_HEADER
pk_Expr* child;
} pk_GroupedExpr;
typedef struct pk_BinaryExpr{
COMMON_HEADER
pk_Expr* lhs;
pk_Expr* rhs;
TokenIndex op;
bool inplace;
} pk_BinaryExpr;
typedef struct pk_TernaryExpr{
COMMON_HEADER
pk_Expr* cond;
pk_Expr* true_expr;
pk_Expr* false_expr;
} pk_TernaryExpr;
#ifdef __cplusplus
}
#endif

View File

@ -1,464 +0,0 @@
#pragma once
#include "pocketpy/objects/codeobject.hpp"
#include "pocketpy/compiler/lexer.hpp"
namespace pkpy {
struct CodeEmitContext;
struct Expr;
typedef small_vector<Expr*, 4> Expr_vector;
struct Expr {
int line = 0;
virtual ~Expr() = default;
virtual void emit_(CodeEmitContext* ctx) = 0;
Expr() = default;
Expr(const Expr&) = delete;
Expr(Expr&&) = delete;
Expr& operator=(const Expr&) = delete;
Expr& operator=(Expr&&) = delete;
virtual bool is_literal() const { return false; }
virtual bool is_json_object() const { return false; }
virtual bool is_attrib() const { return false; }
virtual bool is_subscr() const { return false; }
virtual bool is_compare() const { return false; }
virtual int star_level() const { return 0; }
virtual bool is_tuple() const { return false; }
virtual bool is_name() const { return false; }
bool is_starred() const { return star_level() > 0; }
// for OP_DELETE_XXX
[[nodiscard]] virtual bool emit_del(CodeEmitContext* ctx) { return false; }
// for OP_STORE_XXX
[[nodiscard]] virtual bool emit_store(CodeEmitContext* ctx) { return false; }
virtual void emit_inplace(CodeEmitContext* ctx) { emit_(ctx); }
[[nodiscard]] virtual bool emit_store_inplace(CodeEmitContext* ctx) { return emit_store(ctx); }
};
inline void delete_expr(Expr* p) noexcept{
if(!p) return;
p->~Expr();
PoolExpr_dealloc(p);
}
struct CodeEmitContext{
VM* vm;
FuncDecl* func; // optional, weakref
CodeObject* co; // 1 CodeEmitContext <=> 1 CodeObject*
vector<Expr*> _s_expr;
int level;
vector<StrName> global_names;
int curr_iblock = 0;
bool is_compiling_class = false;
c11_smallmap_s2n _co_consts_string_dedup_map;
CodeEmitContext(VM* vm, CodeObject* co, int level) : vm(vm), co(co), level(level) {
func = NULL;
c11_smallmap_s2n__ctor(&_co_consts_string_dedup_map);
}
int get_loop() const noexcept;
CodeBlock* enter_block(CodeBlockType type) noexcept;
void exit_block() noexcept;
int emit_(Opcode opcode, uint16_t arg, int line, bool is_virtual = false) noexcept;
void revert_last_emit_() noexcept;
int emit_int(i64 value, int line) noexcept;
void patch_jump(int index) noexcept;
bool add_label(StrName name) noexcept;
int add_varname(StrName name) noexcept;
int add_const(PyVar) noexcept;
int add_const_string(std::string_view) noexcept;
void emit_store_name(NameScope scope, StrName name, int line) noexcept;
void try_merge_for_iter_store(int) noexcept;
// emit top -> pop -> delete
void s_emit_top() noexcept{
s_debug_info("s_emit_top");
Expr* e = _s_expr.popx_back();
e->emit_(this);
delete_expr(e);
}
// push
void s_push(Expr* expr) noexcept{
s_debug_info("s_push");
_s_expr.push_back(expr);
}
// top
Expr* s_top() noexcept{
return _s_expr.back();
}
// size
int s_size() const noexcept{
return _s_expr.size();
}
// pop -> delete
void s_pop() noexcept{
s_debug_info("s_pop");
Expr* e = _s_expr.popx_back();
delete_expr(e);
}
// pop move
Expr* s_popx() noexcept{
s_debug_info("s_popx");
return _s_expr.popx_back();
}
// clean
void s_clean() noexcept{
s_debug_info("s_clean");
c11_smallmap_s2n__dtor(&_co_consts_string_dedup_map);
for(Expr* e: _s_expr) delete_expr(e);
_s_expr.clear();
}
// emit decorators
void s_emit_decorators(int count) noexcept;
// debug stack
#if PK_DEBUG_COMPILER
void s_debug_info(const char* op) noexcept{
SStream ss;
for(int i=0; i<s_size(); i++) {
Expr* e = _s_expr[i];
ss << typeid(*e).name();
if(i != s_size() - 1) ss << ", ";
}
printf("[%s] %s\n", ss.str().c_str(), op);
}
#else
void s_debug_info(const char*) noexcept{}
#endif
};
struct NameExpr : Expr {
StrName name;
NameScope scope;
NameExpr(StrName name, NameScope scope) : name(name), scope(scope) {}
void emit_(CodeEmitContext* ctx) override;
bool emit_del(CodeEmitContext* ctx) override;
bool emit_store(CodeEmitContext* ctx) override;
bool is_name() const override { return true; }
};
struct _UnaryExpr : Expr {
Expr* child;
_UnaryExpr(Expr* child) : child(child) {}
_UnaryExpr() : child(nullptr) {}
~_UnaryExpr() { delete_expr(child); }
};
struct _BinaryExpr : Expr {
Expr* lhs;
Expr* rhs;
_BinaryExpr(Expr* lhs, Expr* rhs) : lhs(lhs), rhs(rhs) {}
_BinaryExpr() : lhs(nullptr), rhs(nullptr) {}
~_BinaryExpr() {
delete_expr(lhs);
delete_expr(rhs);
}
};
struct InvertExpr : _UnaryExpr {
using _UnaryExpr::_UnaryExpr;
void emit_(CodeEmitContext* ctx) override;
};
struct StarredExpr : _UnaryExpr {
int level;
StarredExpr(Expr* child, int level) : _UnaryExpr(child), level(level) {}
int star_level() const override { return level; }
void emit_(CodeEmitContext* ctx) override;
bool emit_store(CodeEmitContext* ctx) override;
};
struct NotExpr : _UnaryExpr {
using _UnaryExpr::_UnaryExpr;
void emit_(CodeEmitContext* ctx) override;
};
struct AndExpr : _BinaryExpr {
using _BinaryExpr::_BinaryExpr;
void emit_(CodeEmitContext* ctx) override;
};
struct OrExpr : _BinaryExpr {
using _BinaryExpr::_BinaryExpr;
void emit_(CodeEmitContext* ctx) override;
};
// [None, True, False, ...]
struct Literal0Expr : Expr {
TokenIndex token;
Literal0Expr(TokenIndex token) : token(token) {}
bool is_json_object() const override { return true; }
void emit_(CodeEmitContext* ctx) override;
};
struct LongExpr : Expr {
Str s;
LongExpr(const Str& s) : s(s) {}
void emit_(CodeEmitContext* ctx) override;
};
struct BytesExpr : Expr {
Str s;
BytesExpr(const Str& s) : s(s) {}
void emit_(CodeEmitContext* ctx) override;
};
struct ImagExpr : Expr {
f64 value;
ImagExpr(f64 value) : value(value) {}
void emit_(CodeEmitContext* ctx) override;
};
// @num, @str which needs to invoke OP_LOAD_CONST
struct LiteralExpr : Expr {
TokenValue value;
LiteralExpr(TokenValue value) : value(value) {}
void emit_(CodeEmitContext* ctx) override;
bool is_literal() const override { return true; }
bool is_json_object() const override { return true; }
};
struct NegatedExpr : _UnaryExpr {
using _UnaryExpr::_UnaryExpr;
void emit_(CodeEmitContext* ctx) override;
bool is_json_object() const override { return child->is_literal(); }
};
struct SliceExpr : Expr {
Expr* start = nullptr;
Expr* stop = nullptr;
Expr* step = nullptr;
void emit_(CodeEmitContext* ctx) override;
~SliceExpr() {
delete_expr(start);
delete_expr(stop);
delete_expr(step);
}
};
struct DictItemExpr : Expr {
Expr* key; // maybe nullptr if it is **kwargs
Expr* value;
DictItemExpr(): key(nullptr), value(nullptr) {}
int star_level() const override { return value->star_level(); }
void emit_(CodeEmitContext* ctx) override;
~DictItemExpr() {
delete_expr(key);
delete_expr(value);
}
};
struct SequenceExpr : Expr {
array<Expr*> items;
SequenceExpr(int count) : items(count) {}
virtual Opcode opcode() const = 0;
void emit_(CodeEmitContext* ctx) override {
for(auto& item: items) item->emit_(ctx);
ctx->emit_(opcode(), items.size(), line);
}
~SequenceExpr() {
for(Expr* item: items) delete_expr(item);
}
};
struct ListExpr : SequenceExpr {
using SequenceExpr::SequenceExpr;
Opcode opcode() const override {
for(auto& e: items)
if(e->is_starred()) return OP_BUILD_LIST_UNPACK;
return OP_BUILD_LIST;
}
bool is_json_object() const override { return true; }
};
struct DictExpr : SequenceExpr {
using SequenceExpr::SequenceExpr;
Opcode opcode() const override {
for(auto& e: items)
if(e->is_starred()) return OP_BUILD_DICT_UNPACK;
return OP_BUILD_DICT;
}
bool is_json_object() const override { return true; }
};
struct SetExpr : SequenceExpr {
using SequenceExpr::SequenceExpr;
Opcode opcode() const override {
for(auto& e: items)
if(e->is_starred()) return OP_BUILD_SET_UNPACK;
return OP_BUILD_SET;
}
};
struct TupleExpr : SequenceExpr {
using SequenceExpr::SequenceExpr;
bool is_tuple() const override { return true; }
Opcode opcode() const override {
for(auto& e: items)
if(e->is_starred()) return OP_BUILD_TUPLE_UNPACK;
return OP_BUILD_TUPLE;
}
bool emit_store(CodeEmitContext* ctx) override;
bool emit_del(CodeEmitContext* ctx) override;
};
struct CompExpr : Expr {
Expr* expr = nullptr; // loop expr
Expr* vars = nullptr; // loop vars
Expr* iter = nullptr; // loop iter
Expr* cond = nullptr; // optional if condition
Opcode op0;
Opcode op1;
CompExpr(Opcode op0, Opcode op1) : op0(op0), op1(op1) {}
void emit_(CodeEmitContext* ctx) override;
~CompExpr() {
delete_expr(expr);
delete_expr(vars);
delete_expr(iter);
delete_expr(cond);
}
};
struct LambdaExpr : Expr {
int index;
LambdaExpr(int index) : index(index) {}
void emit_(CodeEmitContext* ctx) override {
ctx->emit_(OP_LOAD_FUNCTION, index, line);
}
};
struct FStringExpr : Expr {
Str src;
FStringExpr(const Str& src) : src(src) {}
void _load_simple_expr(CodeEmitContext* ctx, Str expr);
void emit_(CodeEmitContext* ctx) override;
};
struct SubscrExpr : _BinaryExpr {
using _BinaryExpr::_BinaryExpr;
bool is_subscr() const override { return true; }
void emit_(CodeEmitContext* ctx) override;
bool emit_del(CodeEmitContext* ctx) override;
bool emit_store(CodeEmitContext* ctx) override;
void emit_inplace(CodeEmitContext* ctx) override;
bool emit_store_inplace(CodeEmitContext* ctx) override;
};
struct AttribExpr : _UnaryExpr {
StrName name;
AttribExpr(Expr* child, StrName name) : _UnaryExpr(child), name(name) {}
void emit_(CodeEmitContext* ctx) override;
bool emit_del(CodeEmitContext* ctx) override;
bool emit_store(CodeEmitContext* ctx) override;
void emit_method(CodeEmitContext* ctx);
bool is_attrib() const override { return true; }
void emit_inplace(CodeEmitContext* ctx) override;
bool emit_store_inplace(CodeEmitContext* ctx) override;
};
struct CallExpr : Expr {
Expr* callable;
Expr_vector args;
// **a will be interpreted as a special keyword argument: {"**": a}
vector<pair<StrName, Expr*>> kwargs;
void emit_(CodeEmitContext* ctx) override;
~CallExpr() {
delete_expr(callable);
for(Expr* arg: args) delete_expr(arg);
for(auto [_, arg]: kwargs) delete_expr(arg);
}
};
struct GroupedExpr : _UnaryExpr {
using _UnaryExpr::_UnaryExpr;
void emit_(CodeEmitContext* ctx) override { child->emit_(ctx); }
bool emit_del(CodeEmitContext* ctx) override { return child->emit_del(ctx); }
bool emit_store(CodeEmitContext* ctx) override { return child->emit_store(ctx); }
};
struct BinaryExpr : _BinaryExpr {
TokenIndex op;
bool inplace;
BinaryExpr(TokenIndex op, bool inplace = false)
: _BinaryExpr(), op(op), inplace(inplace) {}
bool is_compare() const override;
void _emit_compare(CodeEmitContext*, small_vector_2<int, 8>&);
void emit_(CodeEmitContext* ctx) override;
};
struct TernaryExpr : Expr {
Expr* cond = nullptr;
Expr* true_expr = nullptr;
Expr* false_expr = nullptr;
void emit_(CodeEmitContext* ctx) override;
~TernaryExpr() {
delete_expr(cond);
delete_expr(true_expr);
delete_expr(false_expr);
}
};
} // namespace pkpy

View File

@ -103,6 +103,8 @@ Error* pk_Lexer__process(pk_SourceData_ src, pk_TokenArray* out_tokens);
Error* pk_Lexer__process_and_dump(pk_SourceData_ src, py_Str* out_string);
void pk_TokenArray__dtor(pk_TokenArray* self);
#define Token__sv(self) (c11_string){(self)->start, (self)->length}
#ifdef __cplusplus
}
#endif

View File

@ -11,14 +11,14 @@
extern "C" {
#endif
PyVar* FastLocals__try_get_by_name(PyVar* locals, const CodeObject* co, py_Name name);
pk_NameDict* FastLocals__to_namedict(PyVar* locals, const CodeObject* co);
py_TValue* FastLocals__try_get_by_name(py_TValue* locals, const CodeObject* co, py_Name name);
pk_NameDict* FastLocals__to_namedict(py_TValue* locals, const CodeObject* co);
typedef struct ValueStack {
// We allocate extra PK_VM_STACK_SIZE/128 places to keep `_sp` valid when `is_overflow() == true`.
PyVar* sp;
PyVar* end;
PyVar begin[PK_VM_STACK_SIZE + PK_VM_STACK_SIZE / 128];
py_TValue* sp;
py_TValue* end;
py_TValue begin[PK_VM_STACK_SIZE + PK_VM_STACK_SIZE / 128];
} ValueStack;
void ValueStack__ctor(ValueStack* self);
@ -39,14 +39,14 @@ typedef struct Frame {
const CodeObject* co;
PyObject* module;
PyObject* function; // a function object or NULL (global scope)
PyVar* p0; // unwinding base
PyVar* locals; // locals base
py_TValue* p0; // unwinding base
py_TValue* locals; // locals base
const CodeObject* locals_co;
UnwindTarget* uw_list;
} Frame;
Frame* Frame__new(const CodeObject* co, const PyVar* module, const PyVar* function, PyVar* p0, PyVar* locals, const CodeObject* locals_co);
Frame* Frame__new(const CodeObject* co, const py_TValue* module, const py_TValue* function, py_TValue* p0, py_TValue* locals, const CodeObject* locals_co);
void Frame__delete(Frame* self);
PK_INLINE int Frame__ip(const Frame* self){
@ -67,11 +67,15 @@ PK_INLINE pk_NameDict* Frame__f_globals(Frame* self){
return PyObject__dict(self->module);
}
PK_INLINE PyVar* Frame__f_globals_try_get(Frame* self, py_Name name){
PK_INLINE py_TValue* Frame__f_globals_try_get(Frame* self, py_Name name){
return pk_NameDict__try_get(Frame__f_globals(self), name);
}
PyVar* Frame__f_closure_try_get(Frame* self, py_Name name);
PK_INLINE py_TValue* Frame__f_locals_try_get(Frame* self, py_Name name){
return FastLocals__try_get_by_name(self->locals, self->locals_co, name);
}
py_TValue* Frame__f_closure_try_get(Frame* self, py_Name name);
int Frame__prepare_jump_exception_handler(Frame* self, ValueStack*);
void Frame__prepare_jump_break(Frame* self, ValueStack*, int);
@ -80,23 +84,8 @@ int Frame__exit_block(Frame* self, ValueStack*, int);
void Frame__gc_mark(Frame* self);
UnwindTarget* Frame__find_unwind_target(Frame* self, int iblock);
void Frame__set_unwind_target(Frame* self, PyVar* sp);
void Frame__set_unwind_target(Frame* self, py_TValue* sp);
#ifdef __cplusplus
}
#endif
// some patch here
#ifdef __cplusplus
#include "pocketpy/objects/codeobject.hpp"
extern "C"{
inline PyVar* Frame__f_closure_try_get(Frame* self, StrName name){
if(self->function == NULL) return NULL;
pkpy::Function* fn = PyObject__as(pkpy::Function, self->function);
if(fn->_closure == nullptr) return nullptr;
return pk_NameDict__try_get(fn->_closure, name);
}
}
#endif

View File

@ -12,8 +12,8 @@ typedef struct pk_TypeInfo{
py_Name name;
py_Type base;
PyVar self; // the type object itself
PyVar module; // the module where the type is defined
py_TValue self; // the type object itself
py_TValue module; // the module where the type is defined
bool subclass_enabled;
void (*dtor)(void*);
@ -38,7 +38,7 @@ typedef struct pk_TypeInfo{
py_CFunction on_end_subclass; // for enum module
} pk_TypeInfo;
void pk_TypeInfo__ctor(pk_TypeInfo* self, py_Name name, py_Type base, PyObject* obj, const PyVar* module, bool subclass_enabled);
void pk_TypeInfo__ctor(pk_TypeInfo* self, py_Name name, py_Type base, PyObject* obj, const py_TValue* module, bool subclass_enabled);
void pk_TypeInfo__dtor(pk_TypeInfo* self);
typedef struct pk_VM {
@ -47,24 +47,26 @@ typedef struct pk_VM {
pk_NameDict modules;
c11_vector/*T=pk_TypeInfo*/ types;
PyVar StopIteration; // a special Exception class
PyVar builtins; // builtins module
PyVar main; // __main__ module
py_TValue StopIteration; // a special Exception class
py_TValue builtins; // builtins module
py_TValue main; // __main__ module
void (*_ceval_on_step)(Frame*, Bytecode);
unsigned char* (*_import_file)(const char*);
void (*_stdout)(const char*);
void (*_stderr)(const char*);
void (*_stdout)(const char*, ...);
void (*_stderr)(const char*, ...);
// singleton objects
PyVar True, False, None, NotImplemented, Ellipsis;
// last error
py_TValue True, False, None, NotImplemented, Ellipsis;
py_Error* last_error;
py_TValue last_retval;
py_TValue reg[8]; // users' registers
PyObject* __curr_class;
PyObject* __cached_object_new;
FuncDecl_ __dynamic_func_decl;
PyVar __vectorcall_buffer[PK_MAX_CO_VARNAMES];
py_TValue __vectorcall_buffer[PK_MAX_CO_VARNAMES];
pk_ManagedHeap heap;
ValueStack stack; // put `stack` at the end for better cache locality
@ -87,7 +89,7 @@ typedef enum pk_FrameResult{
pk_FrameResult pk_VM__run_top_frame(pk_VM* self);
py_Type pk_VM__new_type(pk_VM* self, const char* name, py_Type base, const PyVar* module, bool subclass_enabled);
py_Type pk_VM__new_type(pk_VM* self, const char* name, py_Type base, const py_TValue* module, bool subclass_enabled);
#ifdef __cplusplus
}

View File

@ -14,8 +14,9 @@ extern "C" {
#endif
typedef int16_t py_Type;
typedef struct PyObject PyObject;
typedef struct PyVar{
typedef struct py_TValue{
py_Type type;
bool is_ptr;
int extra;
@ -26,9 +27,9 @@ typedef struct PyVar{
void* _ptr;
// Vec2
};
} PyVar;
} py_TValue;
static_assert(sizeof(PyVar) <= 16, "!sizeof(PyVar) <= 16");
static_assert(sizeof(py_TValue) <= 16, "!sizeof(py_TValue) <= 16");
/* predefined vars */
static const py_Type tp_object = {1}, tp_type = {2};
@ -44,7 +45,7 @@ static const py_Type tp_ellipsis = {26};
static const py_Type tp_op_call = {27}, tp_op_yield = {28};
static const py_Type tp_syntax_error = {29}, tp_stop_iteration = {30};
extern PyVar PY_NULL, PY_OP_CALL, PY_OP_YIELD;
extern py_TValue PY_NULL, PY_OP_CALL, PY_OP_YIELD;
#ifdef __cplusplus
}

View File

@ -74,7 +74,7 @@ typedef struct CodeObject {
c11_vector/*T=Bytecode*/ codes;
c11_vector/*T=CodeObjectByteCodeEx*/ codes_ex;
c11_vector/*T=PyVar*/ consts; // constants
c11_vector/*T=py_TValue*/ consts; // constants
c11_vector/*T=StrName*/ varnames; // local variables
int nlocals; // cached varnames.size()
@ -95,7 +95,7 @@ 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
py_TValue value; // default value
} FuncDeclKwArg;
typedef struct FuncDecl {
@ -119,7 +119,7 @@ typedef FuncDecl* FuncDecl_;
FuncDecl_ FuncDecl__rcnew(pk_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__add_kwarg(FuncDecl* self, int index, uint16_t key, const py_TValue* value);
void FuncDecl__gc_mark(const FuncDecl* self);
#ifdef __cplusplus

View File

@ -49,7 +49,7 @@ pkpy_Dict pkpy_Dict__copy(const pkpy_Dict* self);
* @param val value to set
* @return `true` if the key is newly added, `false` if the key already exists
*/
bool pkpy_Dict__set(pkpy_Dict* self, PyVar key, PyVar val);
bool pkpy_Dict__set(pkpy_Dict* self, py_TValue key, py_TValue val);
/**
* @brief Check if a key exists in the `pkpy_Dict`
@ -58,7 +58,7 @@ bool pkpy_Dict__set(pkpy_Dict* self, PyVar key, PyVar val);
* @param key key to check
* @return `true` if the key exists, `false` otherwise
*/
bool pkpy_Dict__contains(const pkpy_Dict* self, PyVar key);
bool pkpy_Dict__contains(const pkpy_Dict* self, py_TValue key);
/**
* @brief Remove a key from the `pkpy_Dict`
@ -67,7 +67,7 @@ bool pkpy_Dict__contains(const pkpy_Dict* self, PyVar key);
* @param key key to remove
* @return `true` if the key was found and removed, `false` if the key doesn't exist
*/
bool pkpy_Dict__del(pkpy_Dict* self, PyVar key);
bool pkpy_Dict__del(pkpy_Dict* self, py_TValue key);
/**
* @brief Try to get a value from the `pkpy_Dict`
@ -76,7 +76,7 @@ bool pkpy_Dict__del(pkpy_Dict* self, PyVar key);
* @param key key to get
* @return the value associated with the key, `NULL` if the key doesn't exist
*/
const PyVar* pkpy_Dict__try_get(const pkpy_Dict* self, PyVar key);
const py_TValue* pkpy_Dict__try_get(const pkpy_Dict* self, py_TValue key);
/**
* @brief Update the `pkpy_Dict` with another one
@ -106,7 +106,7 @@ pkpy_DictIter pkpy_Dict__iter(const pkpy_Dict* self);
* @param value value will be filled with the current value, can be `NULL` if not needed
* @return `true` if the iteration is still valid, `false` otherwise
*/
bool pkpy_DictIter__next(pkpy_DictIter* self, PyVar* key, PyVar* value);
bool pkpy_DictIter__next(pkpy_DictIter* self, py_TValue* key, py_TValue* value);
#ifdef __cplusplus
}

View File

@ -11,7 +11,7 @@ extern "C" {
#define SMALLMAP_T__HEADER
#define K uint16_t
#define V PyVar
#define V py_TValue
#define NAME pk_NameDict
#include "pocketpy/xmacros/smallmap.h"
#undef SMALLMAP_T__HEADER

View File

@ -22,18 +22,18 @@ typedef struct PyObject{
static_assert(sizeof(PyObject) <= 8, "!(sizeof(PyObject) <= 8)");
PyVar* PyObject__slots(PyObject* self);
py_TValue* PyObject__slots(PyObject* self);
pk_NameDict* PyObject__dict(PyObject* self);
void* PyObject__value(PyObject* self);
#define PK_OBJ_HEADER_SIZE(slots) ((slots)>=0 ? 8+sizeof(PyVar)*(slots) : 8+sizeof(pk_NameDict))
#define PK_OBJ_HEADER_SIZE(slots) ((slots)>=0 ? 8+sizeof(py_TValue)*(slots) : 8+sizeof(pk_NameDict))
PyObject* PyObject__new(py_Type type, int slots, int size);
void PyObject__delete(PyObject* self);
PK_INLINE PyVar PyVar__fromobj(PyObject* obj){
PK_INLINE py_TValue PyVar__fromobj(PyObject* obj){
if(!obj) return PY_NULL;
PyVar retval = {
py_TValue retval = {
.type = obj->type,
.is_ptr = true,
._obj = obj

View File

@ -4,15 +4,15 @@
#include <stdbool.h>
/************* Public Types *************/
typedef struct PyObject PyObject;
typedef struct PyVar PyVar;
typedef struct py_TValue py_TValue;
typedef struct pk_VM pk_VM;
typedef uint16_t py_Name;
typedef int16_t py_Type;
typedef PyVar* py_Ref;
typedef py_TValue* py_Ref;
typedef struct py_Str py_Str;
typedef int (*py_CFunction)(int argc, py_Ref argv);
typedef struct py_Error{
typedef struct py_Error {
py_Type type;
} py_Error;
@ -30,8 +30,8 @@ void py_finalize();
/// Run a simple source string. Do not change the stack.
int py_exec(const char*);
/// Eval a simple expression. If succeed, the result will be pushed onto the stack.
int py_eval(const char*);
/// Eval a simple expression. The result is pushed to the stack.
int py_eval(const char*, py_Ref out);
/************* Values Creation *************/
void py_newint(py_Ref, int64_t);
@ -49,10 +49,20 @@ void py_newtuple(py_Ref, int);
// new style decl-based function
void py_newfunction(py_Ref out, py_CFunction, const char* sig);
void py_newfunction2(py_Ref out, py_CFunction, const char* sig, BindType bt, const char* docstring, const py_Ref upvalue);
void py_newfunction2(py_Ref out,
py_CFunction,
const char* sig,
BindType bt,
const char* docstring,
const py_Ref upvalue);
// old style argc-based function
void py_newnativefunc(py_Ref out, py_CFunction, int argc);
void py_newnativefunc2(py_Ref out, py_CFunction, int argc, BindType bt, const char* docstring, const py_Ref upvalue);
void py_newnativefunc2(py_Ref out,
py_CFunction,
int argc,
BindType bt,
const char* docstring,
const py_Ref upvalue);
/// Create a new object.
/// @param out output reference.
@ -91,6 +101,9 @@ bool py_istype(const py_Ref, py_Type);
// bool py_issubclass(py_Type derived, py_Type base);
/************* References *************/
py_Ref py_getreg(int i);
void py_setreg(int i, const py_Ref val);
py_Ref py_getdict(const py_Ref self, py_Name name);
void py_setdict(py_Ref self, py_Name name, const py_Ref val);
@ -146,6 +159,13 @@ int py_eq(const py_Ref, const py_Ref);
int py_le(const py_Ref, const py_Ref);
int py_hash(const py_Ref, int64_t* out);
int py_str(const py_Ref);
int py_repr(const py_Ref);
int py_vectorcall(int argc, int kwargc);
int py_call(py_Ref f, ...);
int py_callmethod(py_Ref self, py_Name name, ...);
#define py_isnull(self) ((self)->type == 0)
/* tuple */
@ -154,14 +174,12 @@ int py_hash(const py_Ref, int64_t* out);
py_Ref py_tuple__getitem(const py_Ref self, int i);
void py_tuple__setitem(py_Ref self, int i, const py_Ref val);
int py_tuple__len(const py_Ref self);
bool py_tuple__contains(const py_Ref self, const py_Ref val);
// unchecked functions, if self is not a list, the behavior is undefined
py_Ref py_list__getitem(const py_Ref self, int i);
void py_list__setitem(py_Ref self, int i, const py_Ref val);
void py_list__delitem(py_Ref self, int i);
int py_list__len(const py_Ref self);
bool py_list__contains(const py_Ref self, const py_Ref val);
void py_list__append(py_Ref self, const py_Ref val);
void py_list__extend(py_Ref self, const py_Ref begin, const py_Ref end);
void py_list__clear(py_Ref self);
@ -175,9 +193,6 @@ void py_dict__setitem(py_Ref self, const py_Ref key, const py_Ref val);
void py_dict__delitem(py_Ref self, const py_Ref key);
void py_dict__clear(py_Ref self);
int py_str(const py_Ref, char* out);
int py_repr(const py_Ref, char* out);
#ifdef __cplusplus
}
#endif

View File

@ -30,7 +30,6 @@ OPCODE(LOAD_CLASS_GLOBAL)
OPCODE(LOAD_METHOD)
OPCODE(LOAD_SUBSCR)
OPCODE(LOAD_SUBSCR_FAST)
OPCODE(LOAD_SUBSCR_SMALL_INT)
OPCODE(STORE_FAST)
OPCODE(STORE_NAME)
@ -86,7 +85,8 @@ OPCODE(BINARY_MATMUL)
OPCODE(IS_OP)
OPCODE(IS_NOT_OP)
OPCODE(CONTAINS_OP)
OPCODE(IN_OP)
OPCODE(NOT_IN_OP)
/**************************/
OPCODE(JUMP_FORWARD)
OPCODE(POP_JUMP_IF_FALSE)

View File

@ -243,7 +243,7 @@ PK_THREAD_LOCAL FixedMemoryPool PoolFrame;
PK_THREAD_LOCAL MemoryPool PoolObject;
PK_THREAD_LOCAL bool _Pools_initialized = false;
void Pools_initialize(){
void pk_MemoryPools__initialize(){
if(_Pools_initialized) return;
FixedMemoryPool__ctor(&PoolExpr, kPoolExprBlockSize, 64);
FixedMemoryPool__ctor(&PoolFrame, kPoolFrameBlockSize, 128);
@ -251,7 +251,7 @@ void Pools_initialize(){
_Pools_initialized = true;
}
void Pools_finalize(){
void pk_MemoryPools__finalize(){
if(!_Pools_initialized) return;
FixedMemoryPool__dtor(&PoolExpr);
FixedMemoryPool__dtor(&PoolFrame);

View File

@ -79,6 +79,10 @@ void pk_StrName__initialize(){
void pk_StrName__finalize(){
if(!_initialized) return;
// free all char*
for(int i=0; i<_r_interned.count; i++){
free(c11__getitem(char*, &_r_interned, i));
}
c11_smallmap_s2n__dtor(&_interned);
c11_vector__dtor(&_r_interned);
}
@ -116,6 +120,11 @@ const char* pk_StrName__rmap(uint16_t index){
return c11__getitem(char*, &_r_interned, index - 1);
}
c11_string pk_StrName__rmap2(uint16_t index){
const char* p = pk_StrName__rmap(index);
return (c11_string){p, strlen(p)};
}
// unary operators

File diff suppressed because it is too large Load Diff

View File

@ -1,58 +0,0 @@
#include "pocketpy/compiler/context.h"
#include "pocketpy/compiler/expr.h"
void pk_CodeEmitContext__ctor(pk_CodeEmitContext* self, CodeObject* co, FuncDecl* func, int level){
self->co = co;
self->func = func;
self->level = level;
self->curr_iblock = 0;
self->is_compiling_class = false;
c11_vector__ctor(&self->s_expr, sizeof(pk_Expr*));
c11_vector__ctor(&self->global_names, sizeof(StrName));
c11_smallmap_s2n__ctor(&self->co_consts_string_dedup_map);
}
void pk_CodeEmitContext__dtor(pk_CodeEmitContext* self){
c11_vector__dtor(&self->s_expr);
c11_vector__dtor(&self->global_names);
c11_smallmap_s2n__dtor(&self->co_consts_string_dedup_map);
}
// emit top -> pop -> delete
void pk_CodeEmitContext__s_emit_top(pk_CodeEmitContext* self) {
pk_Expr* top = c11_vector__back(pk_Expr*, &self->s_expr);
top->vt->emit_(top, self);
c11_vector__pop(&self->s_expr);
pk_Expr__delete(top);
}
// push
void pk_CodeEmitContext__s_push(pk_CodeEmitContext* self, pk_Expr* expr) {
c11_vector__push(pk_Expr*, &self->s_expr, expr);
}
// top
pk_Expr* pk_CodeEmitContext__s_top(pk_CodeEmitContext* self){
return c11_vector__back(pk_Expr*, &self->s_expr);
}
// size
int pk_CodeEmitContext__s_size(pk_CodeEmitContext* self) {
return self->s_expr.count;
}
// pop -> delete
void pk_CodeEmitContext__s_pop(pk_CodeEmitContext* self){
pk_Expr__delete(c11_vector__back(pk_Expr*, &self->s_expr));
c11_vector__pop(&self->s_expr);
}
// pop move
pk_Expr* pk_CodeEmitContext__s_popx(pk_CodeEmitContext* self){
pk_Expr* e = c11_vector__back(pk_Expr*, &self->s_expr);
c11_vector__pop(&self->s_expr);
return e;
}
// clean
void pk_CodeEmitContext__s_clean(pk_CodeEmitContext* self){
c11_smallmap_s2n__dtor(&self->co_consts_string_dedup_map); // ??
for(int i=0; i<self->s_expr.count; i++){
pk_Expr__delete(c11__getitem(pk_Expr*, &self->s_expr, i));
}
c11_vector__clear(&self->s_expr);
}

View File

@ -1,837 +0,0 @@
#include "pocketpy/compiler/expr.h"
#include "pocketpy/compiler/context.h"
#include "pocketpy/common/memorypool.h"
#include "pocketpy/common/strname.h"
#include <ctype.h>
static bool default_false(const pk_Expr* e) { return false; }
static int default_zero(const pk_Expr* e) { return 0; }
static void default_dtor(pk_Expr* e) {}
static bool default_emit_del(pk_Expr* e, pk_CodeEmitContext* ctx) { return false; }
static bool default_emit_store(pk_Expr* e, pk_CodeEmitContext* ctx) { return false; }
static void default_emit_inplace(pk_Expr* e, pk_CodeEmitContext* ctx) { e->vt->emit_(e, ctx); }
static bool default_emit_store_inplace(pk_Expr* e, pk_CodeEmitContext* ctx) { return e->vt->emit_store(e, ctx); }
void pk_ExprVt__ctor(pk_ExprVt* vt){
vt->dtor = default_dtor;
vt->star_level = default_zero;
vt->is_compare = default_false;
vt->emit_ = NULL; // must be set
vt->emit_del = default_emit_del;
vt->emit_store = default_emit_store;
vt->emit_inplace = default_emit_inplace;
vt->emit_store_inplace = default_emit_store_inplace;
}
void pk_Expr__delete(pk_Expr* self){
if(!self) return;
self->vt->dtor(self);
PoolExpr_dealloc(self);
}
/* Implementations */
#define static_assert_expr_size(T) static_assert(sizeof(T) <= kPoolExprBlockSize, "size is too large")
static pk_ExprVt NameExprVt;
void pk_NameExpr__emit_(pk_Expr* self_, pk_CodeEmitContext* ctx) {
pk_NameExpr* self = (pk_NameExpr*)self_;
int index = c11_smallmap_n2i__get(&ctx->co->varnames_inv, self->name, -1);
if(self->scope == NAME_LOCAL && index >= 0) {
pk_CodeEmitContext__emit_(ctx, OP_LOAD_FAST, index, self->line);
} else {
Opcode op = ctx->level <= 1 ? OP_LOAD_GLOBAL : OP_LOAD_NONLOCAL;
if(ctx->is_compiling_class && self->scope == NAME_GLOBAL) {
// if we are compiling a class, we should use OP_LOAD_ATTR_GLOBAL instead of OP_LOAD_GLOBAL
// this supports @property.setter
op = OP_LOAD_CLASS_GLOBAL;
// exec()/eval() won't work with OP_LOAD_ATTR_GLOBAL in class body
} else {
// we cannot determine the scope when calling exec()/eval()
if(self->scope == NAME_GLOBAL_UNKNOWN) op = OP_LOAD_NAME;
}
pk_CodeEmitContext__emit_(ctx, op, self->name, self->line);
}
}
bool pk_NameExpr__emit_del(pk_Expr* self_, pk_CodeEmitContext* ctx) {
pk_NameExpr* self = (pk_NameExpr*)self_;
switch(self->scope) {
case NAME_LOCAL:
pk_CodeEmitContext__emit_(
ctx, OP_DELETE_FAST,
pk_CodeEmitContext__add_varname(ctx, self->name),
self->line
);
break;
case NAME_GLOBAL:
pk_CodeEmitContext__emit_(ctx, OP_DELETE_GLOBAL, self->name, self->line);
break;
case NAME_GLOBAL_UNKNOWN:
pk_CodeEmitContext__emit_(ctx, OP_DELETE_NAME, self->name, self->line);
break;
default: PK_UNREACHABLE();
}
return true;
}
bool pk_NameExpr__emit_store(pk_Expr* self_, pk_CodeEmitContext* ctx) {
pk_NameExpr* self = (pk_NameExpr*)self_;
if(ctx->is_compiling_class) {
pk_CodeEmitContext__emit_(ctx, OP_STORE_CLASS_ATTR, self->name, self->line);
return true;
}
pk_CodeEmitContext__emit_store_name(ctx, self->scope, self->name, self->line);
return true;
}
pk_NameExpr* pk_NameExpr__new(StrName name, NameScope scope){
static_assert_expr_size(pk_NameExpr);
pk_NameExpr* self = PoolExpr_alloc();
self->vt = &NameExprVt;
self->line = -1;
self->name = name;
self->scope = scope;
return self;
}
static pk_ExprVt StarredExprVt;
int pk_ExprVt__star_level(const pk_Expr* self) {
return ((pk_StarredExpr*)self)->level;
}
void pk_StarredExpr__emit_(pk_Expr* self_, pk_CodeEmitContext* ctx) {
pk_StarredExpr* self = (pk_StarredExpr*)self_;
self->child->vt->emit_(self->child, ctx);
pk_CodeEmitContext__emit_(ctx, OP_UNARY_STAR, self->level, self->line);
}
bool pk_StarredExpr__emit_store(pk_Expr* self_, pk_CodeEmitContext* ctx) {
pk_StarredExpr* self = (pk_StarredExpr*)self_;
if(self->level != 1) return false;
// simply proxy to child
return self->child->vt->emit_store(self->child, ctx);
}
pk_StarredExpr* pk_StarredExpr__new(pk_Expr* child, int level){
static_assert_expr_size(pk_StarredExpr);
pk_StarredExpr* self = PoolExpr_alloc();
self->vt = &StarredExprVt;
self->line = -1;
self->child = child;
self->level = level;
return self;
}
static pk_ExprVt UnaryExprVt;
void pk_UnaryExpr__dtor(pk_Expr* self_){
pk_UnaryExpr* self = (pk_UnaryExpr*)self_;
pk_Expr__delete(self->child);
}
static void pk_UnaryExpr__emit_(pk_Expr* self_, pk_CodeEmitContext* ctx) {
pk_UnaryExpr* self = (pk_UnaryExpr*)self_;
self->child->vt->emit_(self->child, ctx);
pk_CodeEmitContext__emit_(ctx, self->opcode, BC_NOARG, self->line);
}
pk_UnaryExpr* pk_UnaryExpr__new(pk_Expr* child, Opcode opcode){
static_assert_expr_size(pk_UnaryExpr);
pk_UnaryExpr* self = PoolExpr_alloc();
self->vt = &UnaryExprVt;
self->line = -1;
self->child = child;
self->opcode = opcode;
return self;
}
static pk_ExprVt RawStringExprVt;
void pk_RawStringExpr__emit_(pk_Expr* self_, pk_CodeEmitContext* ctx) {
pk_RawStringExpr* self = (pk_RawStringExpr*)self_;
int index = pk_CodeEmitContext__add_const_string(ctx, self->value);
pk_CodeEmitContext__emit_(ctx, OP_LOAD_CONST, index, self->line);
pk_CodeEmitContext__emit_(ctx, self->opcode, BC_NOARG, self->line);
}
pk_RawStringExpr* pk_RawStringExpr__new(c11_string value, Opcode opcode){
static_assert_expr_size(pk_RawStringExpr);
pk_RawStringExpr* self = PoolExpr_alloc();
self->vt = &RawStringExprVt;
self->line = -1;
self->value = value;
self->opcode = opcode;
return self;
}
static pk_ExprVt ImagExprVt;
void pk_ImagExpr__emit_(pk_Expr* self_, pk_CodeEmitContext* ctx) {
pk_ImagExpr* self = (pk_ImagExpr*)self_;
PyVar value;
py_newfloat(&value, self->value);
int index = pk_CodeEmitContext__add_const(ctx, &value);
pk_CodeEmitContext__emit_(ctx, OP_LOAD_CONST, index, self->line);
pk_CodeEmitContext__emit_(ctx, OP_BUILD_IMAG, BC_NOARG, self->line);
}
pk_ImagExpr* pk_ImagExpr__new(double value){
static_assert_expr_size(pk_ImagExpr);
pk_ImagExpr* self = PoolExpr_alloc();
self->vt = &ImagExprVt;
self->line = -1;
self->value = value;
return self;
}
static pk_ExprVt LiteralExprVt;
void pk_LiteralExpr__emit_(pk_Expr* self_, pk_CodeEmitContext* ctx) {
pk_LiteralExpr* self = (pk_LiteralExpr*)self_;
switch(self->value->index){
case TokenValue_I64: {
int64_t val = self->value->_i64;
pk_CodeEmitContext__emit_int(ctx, val, self->line);
break;
}
case TokenValue_F64: {
PyVar value;
py_newfloat(&value, self->value->_f64);
int index = pk_CodeEmitContext__add_const(ctx, &value);
pk_CodeEmitContext__emit_(ctx, OP_LOAD_CONST, index, self->line);
break;
}
case TokenValue_STR: {
c11_string sv = py_Str__sv(&self->value->_str);
int index = pk_CodeEmitContext__add_const_string(ctx, sv);
pk_CodeEmitContext__emit_(ctx, OP_LOAD_CONST, index, self->line);
break;
}
default: PK_UNREACHABLE();
}
}
pk_LiteralExpr* pk_LiteralExpr__new(const TokenValue* value){
static_assert_expr_size(pk_LiteralExpr);
pk_LiteralExpr* self = PoolExpr_alloc();
self->vt = &LiteralExprVt;
self->line = -1;
self->value = value;
return self;
}
static pk_ExprVt SliceExprVt;
void pk_SliceExpr__dtor(pk_Expr* self_){
pk_SliceExpr* self = (pk_SliceExpr*)self_;
pk_Expr__delete(self->start);
pk_Expr__delete(self->stop);
pk_Expr__delete(self->step);
}
void pk_SliceExpr__emit_(pk_Expr* self_, pk_CodeEmitContext* ctx) {
pk_SliceExpr* self = (pk_SliceExpr*)self_;
if(self->start) self->start->vt->emit_(self->start, ctx);
else pk_CodeEmitContext__emit_(ctx, OP_LOAD_NONE, BC_NOARG, self->line);
if(self->stop) self->stop->vt->emit_(self->stop, ctx);
else pk_CodeEmitContext__emit_(ctx, OP_LOAD_NONE, BC_NOARG, self->line);
if(self->step) self->step->vt->emit_(self->step, ctx);
else pk_CodeEmitContext__emit_(ctx, OP_LOAD_NONE, BC_NOARG, self->line);
pk_CodeEmitContext__emit_(ctx, OP_BUILD_SLICE, BC_NOARG, self->line);
}
pk_SliceExpr* pk_SliceExpr__new(){
static_assert_expr_size(pk_SliceExpr);
pk_SliceExpr* self = PoolExpr_alloc();
self->vt = &SliceExprVt;
self->line = -1;
self->start = NULL;
self->stop = NULL;
self->step = NULL;
return self;
}
static pk_ExprVt ListExprVt;
static pk_ExprVt DictExprVt;
static pk_ExprVt SetExprVt;
static pk_ExprVt TupleExprVt;
pk_SequenceExpr* pk_SequenceExpr__new(pk_ExprVt* vt, int count, Opcode opcode){
static_assert_expr_size(pk_SequenceExpr);
pk_SequenceExpr* self = PoolExpr_alloc();
self->vt = vt;
self->line = -1;
self->opcode = opcode;
c11_array__ctor(&self->items, count, sizeof(pk_Expr*));
return self;
}
static void pk_SequenceExpr__emit_(pk_Expr* self_, pk_CodeEmitContext* ctx) {
pk_SequenceExpr* self = (pk_SequenceExpr*)self_;
for(int i=0; i<self->items.count; i++){
pk_Expr* item = c11__getitem(pk_Expr*, &self->items, i);
item->vt->emit_(item, ctx);
}
pk_CodeEmitContext__emit_(ctx, self->opcode, self->items.count, self->line);
}
void pk_SequenceExpr__dtor(pk_Expr* self_){
pk_SequenceExpr* self = (pk_SequenceExpr*)self_;
c11__foreach(pk_Expr*, &self->items, e){
pk_Expr__delete(*e);
}
c11_array__dtor(&self->items);
}
bool pk_TupleExpr__emit_store(pk_Expr* self_, pk_CodeEmitContext* ctx) {
pk_SequenceExpr* self = (pk_SequenceExpr*)self_;
// TOS is an iterable
// items may contain StarredExpr, we should check it
int starred_i = -1;
for(int i = 0; i < self->items.count; i++) {
pk_Expr* e = c11__getitem(pk_Expr*, &self->items, i);
if(e->vt->star_level(e) == 0) continue;
if(starred_i == -1) starred_i = i;
else return false; // multiple StarredExpr not allowed
}
if(starred_i == -1) {
Bytecode* prev = c11__at(Bytecode, &ctx->co->codes, ctx->co->codes.count - 1);
if(prev->op == OP_BUILD_TUPLE && prev->arg == self->items.count) {
// build tuple and unpack it is meaningless
pk_CodeEmitContext__revert_last_emit_(ctx);
} else {
if(prev->op == OP_FOR_ITER) {
prev->op = OP_FOR_ITER_UNPACK;
prev->arg = self->items.count;
} else {
pk_CodeEmitContext__emit_(ctx, OP_UNPACK_SEQUENCE, self->items.count, self->line);
}
}
} else {
// starred assignment target must be in a tuple
if(self->items.count == 1) return false;
// starred assignment target must be the last one (differ from cpython)
if(starred_i != self->items.count - 1) return false;
// a,*b = [1,2,3]
// stack is [1,2,3] -> [1,[2,3]]
pk_CodeEmitContext__emit_(ctx, OP_UNPACK_EX, self->items.count - 1, self->line);
}
// do reverse emit
for(int i = self->items.count - 1; i >= 0; i--) {
pk_Expr* e = c11__getitem(pk_Expr*, &self->items, i);
bool ok = e->vt->emit_store(e, ctx);
if(!ok) return false;
}
return true;
}
bool pk_TupleExpr__emit_del(pk_Expr* self_, pk_CodeEmitContext* ctx) {
pk_SequenceExpr* self = (pk_SequenceExpr*)self_;
c11__foreach(pk_Expr*, &self->items, e){
bool ok = (*e)->vt->emit_del(*e, ctx);
if(!ok) return false;
}
return true;
}
static pk_ExprVt CompExprVt;
void pk_CompExpr__dtor(pk_Expr* self_){
pk_CompExpr* self = (pk_CompExpr*)self_;
pk_Expr__delete(self->expr);
pk_Expr__delete(self->vars);
pk_Expr__delete(self->iter);
pk_Expr__delete(self->cond);
}
void pk_CompExpr__emit_(pk_Expr* self_, pk_CodeEmitContext* ctx) {
pk_CompExpr* self = (pk_CompExpr*)self_;
pk_CodeEmitContext__emit_(ctx, self->op0, 0, self->line);
self->iter->vt->emit_(self->iter, ctx);
pk_CodeEmitContext__emit_(ctx, OP_GET_ITER, BC_NOARG, BC_KEEPLINE);
pk_CodeEmitContext__enter_block(ctx, CodeBlockType_FOR_LOOP);
int curr_iblock = ctx->curr_iblock;
int for_codei = pk_CodeEmitContext__emit_(ctx, OP_FOR_ITER, curr_iblock, BC_KEEPLINE);
bool ok = self->vars->vt->emit_store(self->vars, ctx);
// this error occurs in `vars` instead of this line, but...nevermind
assert(ok); // this should raise a SyntaxError, but we just assert it
pk_CodeEmitContext__try_merge_for_iter_store(ctx, for_codei);
if(self->cond) {
self->cond->vt->emit_(self->cond, ctx);
int patch = pk_CodeEmitContext__emit_(ctx, OP_POP_JUMP_IF_FALSE, BC_NOARG, BC_KEEPLINE);
self->expr->vt->emit_(self->expr, ctx);
pk_CodeEmitContext__emit_(ctx, self->op1, BC_NOARG, BC_KEEPLINE);
pk_CodeEmitContext__patch_jump(ctx, patch);
} else {
self->expr->vt->emit_(self->expr, ctx);
pk_CodeEmitContext__emit_(ctx, self->op1, BC_NOARG, BC_KEEPLINE);
}
pk_CodeEmitContext__emit_(ctx, OP_LOOP_CONTINUE, curr_iblock, BC_KEEPLINE);
pk_CodeEmitContext__exit_block(ctx);
}
pk_CompExpr* pk_CompExpr__new(Opcode op0, Opcode op1){
static_assert_expr_size(pk_CompExpr);
pk_CompExpr* self = PoolExpr_alloc();
self->vt = &CompExprVt;
self->line = -1;
self->op0 = op0;
self->op1 = op1;
self->expr = NULL;
self->vars = NULL;
self->iter = NULL;
self->cond = NULL;
return self;
}
static pk_ExprVt LambdaExprVt;
pk_LambdaExpr* pk_LambdaExpr__new(int index){
static_assert_expr_size(pk_LambdaExpr);
pk_LambdaExpr* self = PoolExpr_alloc();
self->vt = &LambdaExprVt;
self->line = -1;
self->index = index;
return self;
}
static void pk_LambdaExpr__emit_(pk_Expr* self_, pk_CodeEmitContext* ctx) {
pk_LambdaExpr* self = (pk_LambdaExpr*)self_;
pk_CodeEmitContext__emit_(ctx, OP_LOAD_FUNCTION, self->index, self->line);
}
static pk_ExprVt FStringExprVt;
static bool is_fmt_valid_char(char c) {
switch(c) {
// clang-format off
case '-': case '=': case '*': case '#': case '@': case '!': case '~':
case '<': case '>': case '^':
case '.': case 'f': case 'd': case 's':
case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
return true;
default: return false;
// clang-format on
}
}
static bool is_identifier(c11_string s) {
if(s.size == 0) return false;
if(!isalpha(s.data[0]) && s.data[0] != '_') return false;
for(int i=0; i<s.size; i++){
char c = s.data[i];
if(!isalnum(c) && c != '_') return false;
}
return true;
}
static void _load_simple_expr(pk_CodeEmitContext* ctx, c11_string expr, int line) {
bool repr = false;
const char* expr_end = expr.data + expr.size;
if(expr.size >= 2 && expr_end[-2] == '!') {
switch(expr_end[-1]) {
case 'r':
repr = true;
expr.size -= 2; // expr[:-2]
break;
case 's':
repr = false;
expr.size -= 2; // expr[:-2]
break;
default: break; // nothing happens
}
}
// name or name.name
bool is_fastpath = false;
if(is_identifier(expr)) {
// ctx->emit_(OP_LOAD_NAME, StrName(expr.sv()).index, line);
pk_CodeEmitContext__emit_(
ctx,
OP_LOAD_NAME,
pk_StrName__map2(expr),
line
);
is_fastpath = true;
} else {
int dot = c11_string__index(expr, '.');
if(dot > 0) {
// std::string_view a = expr.sv().substr(0, dot);
// std::string_view b = expr.sv().substr(dot + 1);
c11_string a = {expr.data, dot}; // expr[:dot]
c11_string b = {expr.data+(dot+1), expr.size-(dot+1)}; // expr[dot+1:]
if(is_identifier(a) && is_identifier(b)) {
pk_CodeEmitContext__emit_(ctx, OP_LOAD_NAME, pk_StrName__map2(a), line);
pk_CodeEmitContext__emit_(ctx, OP_LOAD_ATTR, pk_StrName__map2(b), line);
is_fastpath = true;
}
}
}
if(!is_fastpath) {
int index = pk_CodeEmitContext__add_const_string(ctx, expr);
pk_CodeEmitContext__emit_(ctx, OP_FSTRING_EVAL, index, line);
}
if(repr) {
pk_CodeEmitContext__emit_(ctx, OP_REPR, BC_NOARG, line);
}
}
static void pk_FStringExpr__emit_(pk_Expr* self_, pk_CodeEmitContext* ctx) {
pk_FStringExpr* self = (pk_FStringExpr*)self_;
int i = 0; // left index
int j = 0; // right index
int count = 0; // how many string parts
bool flag = false; // true if we are in a expression
const char* src = self->src.data;
while(j < self->src.size) {
if(flag) {
if(src[j] == '}') {
// add expression
c11_string expr = {src+i, j-i}; // src[i:j]
// BUG: ':' is not a format specifier in f"{stack[2:]}"
int conon = c11_string__index(expr, ':');
if(conon >= 0) {
c11_string spec = {expr.data+(conon+1), expr.size-(conon+1)}; // expr[conon+1:]
// filter some invalid spec
bool ok = true;
for(int k = 0; k < spec.size; k++) {
char c = spec.data[k];
if(!is_fmt_valid_char(c)) {
ok = false;
break;
}
}
if(ok) {
expr.size = conon; // expr[:conon]
_load_simple_expr(ctx, expr, self->line);
// ctx->emit_(OP_FORMAT_STRING, ctx->add_const_string(spec.sv()), line);
pk_CodeEmitContext__emit_(ctx, OP_FORMAT_STRING, pk_CodeEmitContext__add_const_string(ctx, spec), self->line);
} else {
// ':' is not a spec indicator
_load_simple_expr(ctx, expr, self->line);
}
} else {
_load_simple_expr(ctx, expr, self->line);
}
flag = false;
count++;
}
} else {
if(src[j] == '{') {
// look at next char
if(j + 1 < self->src.size && src[j + 1] == '{') {
// {{ -> {
j++;
pk_CodeEmitContext__emit_(
ctx,
OP_LOAD_CONST,
pk_CodeEmitContext__add_const_string(ctx, (c11_string){"{", 1}),
self->line
);
count++;
} else {
// { -> }
flag = true;
i = j + 1;
}
} else if(src[j] == '}') {
// look at next char
if(j + 1 < self->src.size && src[j + 1] == '}') {
// }} -> }
j++;
pk_CodeEmitContext__emit_(
ctx,
OP_LOAD_CONST,
pk_CodeEmitContext__add_const_string(ctx, (c11_string){"}", 1}),
self->line
);
count++;
} else {
// } -> error
// throw std::runtime_error("f-string: unexpected }");
// just ignore
}
} else {
// literal
i = j;
while(j < self->src.size && src[j] != '{' && src[j] != '}')
j++;
c11_string literal = {src+i, j-i}; // src[i:j]
pk_CodeEmitContext__emit_(
ctx,
OP_LOAD_CONST,
pk_CodeEmitContext__add_const_string(ctx, literal),
self->line
);
count++;
continue; // skip j++
}
}
j++;
}
if(flag) {
// literal
c11_string literal = {src+i, self->src.size-i}; // src[i:]
pk_CodeEmitContext__emit_(ctx, OP_LOAD_CONST, pk_CodeEmitContext__add_const_string(ctx, literal), self->line);
count++;
}
pk_CodeEmitContext__emit_(ctx, OP_BUILD_STRING, count, self->line);
}
pk_FStringExpr* pk_FStringExpr__new(c11_string src){
static_assert_expr_size(pk_FStringExpr);
pk_FStringExpr* self = PoolExpr_alloc();
self->vt = &FStringExprVt;
self->line = -1;
self->src = src;
return self;
}
static pk_ExprVt LogicBinaryExpr;
pk_LogicBinaryExpr* pk_LogicBinaryExpr__new(pk_Expr* lhs, pk_Expr* rhs, Opcode opcode){
static_assert_expr_size(pk_LogicBinaryExpr);
pk_LogicBinaryExpr* self = PoolExpr_alloc();
self->vt = &LogicBinaryExpr;
self->line = -1;
self->lhs = lhs;
self->rhs = rhs;
self->opcode = opcode;
return self;
}
void pk_LogicBinaryExpr__dtor(pk_Expr* self_){
pk_LogicBinaryExpr* self = (pk_LogicBinaryExpr*)self_;
pk_Expr__delete(self->lhs);
pk_Expr__delete(self->rhs);
}
void pk_LogicBinaryExpr__emit_(pk_Expr* self_, pk_CodeEmitContext* ctx) {
pk_LogicBinaryExpr* self = (pk_LogicBinaryExpr*)self_;
self->lhs->vt->emit_(self->lhs, ctx);
int patch = pk_CodeEmitContext__emit_(ctx, self->opcode, BC_NOARG, self->line);
self->rhs->vt->emit_(self->rhs, ctx);
pk_CodeEmitContext__patch_jump(ctx, patch);
}
static pk_ExprVt GroupedExprVt;
void pk_GroupedExpr__dtor(pk_Expr* self_){
pk_GroupedExpr* self = (pk_GroupedExpr*)self_;
pk_Expr__delete(self->child);
}
void pk_GroupedExpr__emit_(pk_Expr* self_, pk_CodeEmitContext* ctx) {
pk_GroupedExpr* self = (pk_GroupedExpr*)self_;
self->child->vt->emit_(self->child, ctx);
}
bool pk_GroupedExpr__emit_del(pk_Expr* self_, pk_CodeEmitContext* ctx) {
pk_GroupedExpr* self = (pk_GroupedExpr*)self_;
return self->child->vt->emit_del(self->child, ctx);
}
bool pk_GroupedExpr__emit_store(pk_Expr* self_, pk_CodeEmitContext* ctx) {
pk_GroupedExpr* self = (pk_GroupedExpr*)self_;
return self->child->vt->emit_store(self->child, ctx);
}
pk_GroupedExpr* pk_GroupedExpr__new(pk_Expr* child){
static_assert_expr_size(pk_GroupedExpr);
pk_GroupedExpr* self = PoolExpr_alloc();
self->vt = &GroupedExprVt;
self->line = -1;
self->child = child;
return self;
}
static pk_ExprVt BinaryExprVt;
static void pk_BinaryExpr__dtor(pk_Expr* self_){
pk_BinaryExpr* self = (pk_BinaryExpr*)self_;
pk_Expr__delete(self->lhs);
pk_Expr__delete(self->rhs);
}
static pk_BinaryExpr__is_compare(pk_Expr* self_){
pk_BinaryExpr* self = (pk_BinaryExpr*)self_;
switch(self->op) {
case TK_LT:
case TK_LE:
case TK_EQ:
case TK_NE:
case TK_GT:
case TK_GE: return true;
default: return false;
}
}
static void _emit_compare(pk_BinaryExpr* self, pk_CodeEmitContext* ctx, c11_vector* jmps) {
if(self->lhs->vt->is_compare(self->lhs)) {
pk_BinaryExpr* lhs = (pk_BinaryExpr*)lhs;
_emit_compare(lhs, ctx, jmps);
} else {
self->lhs->vt->emit_(self->lhs, ctx); // [a]
}
self->rhs->vt->emit_(self->rhs, ctx); // [a, b]
pk_CodeEmitContext__emit_(ctx, OP_DUP_TOP, BC_NOARG, self->line); // [a, b, b]
pk_CodeEmitContext__emit_(ctx, OP_ROT_THREE, BC_NOARG, self->line); // [b, a, b]
Opcode opcode;
switch(self->op) {
case TK_LT: opcode = OP_COMPARE_LT; break;
case TK_LE: opcode = OP_COMPARE_LE; break;
case TK_EQ: opcode = OP_COMPARE_EQ; break;
case TK_NE: opcode = OP_COMPARE_NE; break;
case TK_GT: opcode = OP_COMPARE_GT; break;
case TK_GE: opcode = OP_COMPARE_GE; break;
default: PK_UNREACHABLE()
}
pk_CodeEmitContext__emit_(ctx, opcode, BC_NOARG, self->line);
// [b, RES]
int index = pk_CodeEmitContext__emit_(ctx, OP_JUMP_IF_FALSE_OR_POP, BC_NOARG, self->line);
c11_vector__push(int, jmps, index);
}
static void pk_BinaryExpr__emit_(pk_Expr* self_, pk_CodeEmitContext* ctx) {
pk_BinaryExpr* self = (pk_BinaryExpr*)self_;
c11_vector/*T=int*/ jmps;
c11_vector__ctor(&jmps, sizeof(int));
if(self->vt->is_compare(self_) && self->lhs->vt->is_compare(self->lhs)) {
// (a < b) < c
pk_BinaryExpr* e = (pk_BinaryExpr*)self->lhs;
_emit_compare(e, ctx, &jmps);
// [b, RES]
} else {
// (1 + 2) < c
if(self->inplace) {
self->lhs->vt->emit_inplace(self->lhs, ctx);
} else {
self->lhs->vt->emit_(self->lhs, ctx);
}
}
self->rhs->vt->emit_(self->rhs, ctx);
Opcode opcode;
switch(self->op) {
case TK_ADD: opcode = OP_BINARY_ADD; break;
case TK_SUB: opcode = OP_BINARY_SUB; break;
case TK_MUL: opcode = OP_BINARY_MUL; break;
case TK_DIV: opcode = OP_BINARY_TRUEDIV; break;
case TK_FLOORDIV: opcode = OP_BINARY_FLOORDIV; break;
case TK_MOD: opcode = OP_BINARY_MOD; break;
case TK_POW: opcode = OP_BINARY_POW; break;
case TK_LT: opcode = OP_COMPARE_LT; break;
case TK_LE: opcode = OP_COMPARE_LE; break;
case TK_EQ: opcode = OP_COMPARE_EQ; break;
case TK_NE: opcode = OP_COMPARE_NE; break;
case TK_GT: opcode = OP_COMPARE_GT; break;
case TK_GE: opcode = OP_COMPARE_GE; break;
// case TK_IN: ctx->emit_(OP_CONTAINS_OP, 0, line); break;
// case TK_NOT_IN: ctx->emit_(OP_CONTAINS_OP, 1, line); break;
// case TK_IS: ctx->emit_(OP_IS_OP, BC_NOARG, line); break;
// case TK_IS_NOT: ctx->emit_(OP_IS_NOT_OP, BC_NOARG, line); break;
case TK_LSHIFT: ctx->emit_(OP_BITWISE_LSHIFT, BC_NOARG, line); break;
case TK_RSHIFT: ctx->emit_(OP_BITWISE_RSHIFT, BC_NOARG, line); break;
case TK_AND: ctx->emit_(OP_BITWISE_AND, BC_NOARG, line); break;
case TK_OR: ctx->emit_(OP_BITWISE_OR, BC_NOARG, line); break;
case TK_XOR: ctx->emit_(OP_BITWISE_XOR, BC_NOARG, line); break;
case TK_DECORATOR: ctx->emit_(OP_BINARY_MATMUL, BC_NOARG, line); break;
default: PK_FATAL_ERROR("unknown binary operator: %s\n", pk_TokenSymbols[op]);
}
for(int i: jmps)
ctx->patch_jump(i);
}
static pk_ExprVt TernaryExprVt;
/////////////////////////////////////////////
void pk_Expr__initialize(){
pk_ExprVt__ctor(&NameExprVt);
pk_ExprVt* vt = &NameExprVt;
vt->emit_ = pk_NameExpr__emit_;
vt->emit_del = pk_NameExpr__emit_del;
vt->emit_store = pk_NameExpr__emit_store;
pk_ExprVt__ctor(&StarredExprVt);
vt = &StarredExprVt;
vt->dtor = pk_UnaryExpr__dtor;
vt->star_level = pk_ExprVt__star_level;
vt->emit_ = pk_StarredExpr__emit_;
vt->emit_store = pk_StarredExpr__emit_store;
pk_ExprVt__ctor(&UnaryExprVt);
vt = &UnaryExprVt;
vt->dtor = pk_UnaryExpr__dtor;
vt->emit_ = pk_UnaryExpr__emit_;
pk_ExprVt__ctor(&RawStringExprVt);
vt = &RawStringExprVt;
vt->emit_ = pk_RawStringExpr__emit_;
pk_ExprVt__ctor(&ImagExprVt);
vt = &ImagExprVt;
vt->emit_ = pk_ImagExpr__emit_;
pk_ExprVt__ctor(&LiteralExprVt);
vt = &LiteralExprVt;
vt->emit_ = pk_LiteralExpr__emit_;
vt->is_literal = true;
vt->is_json_object = true;
pk_ExprVt__ctor(&SliceExprVt);
vt = &SliceExprVt;
vt->dtor = pk_SliceExpr__dtor;
vt->emit_ = pk_SliceExpr__emit_;
pk_ExprVt* seqVt[] = {&ListExprVt, &DictExprVt, &SetExprVt, &TupleExprVt};
for(int i=0; i<4; i++){
pk_ExprVt__ctor(seqVt[i]);
vt = seqVt[i];
vt->dtor = pk_SequenceExpr__dtor;
vt->emit_ = pk_SequenceExpr__emit_;
}
ListExprVt.is_json_object = true;
DictExprVt.is_json_object = true;
TupleExprVt.is_tuple = true;
TupleExprVt.emit_store = pk_TupleExpr__emit_store;
TupleExprVt.emit_del = pk_TupleExpr__emit_del;
pk_ExprVt__ctor(&CompExprVt);
vt = &CompExprVt;
vt->dtor = pk_CompExpr__dtor;
vt->emit_ = pk_CompExpr__emit_;
pk_ExprVt__ctor(&LambdaExprVt);
vt = &LambdaExprVt;
vt->emit_ = pk_LambdaExpr__emit_;
pk_ExprVt__ctor(&FStringExprVt);
vt = &FStringExprVt;
vt->emit_ = pk_FStringExpr__emit_;
pk_ExprVt__ctor(&LogicBinaryExpr);
vt = &LogicBinaryExpr;
vt->dtor = pk_LogicBinaryExpr__dtor;
vt->emit_ = pk_LogicBinaryExpr__emit_;
pk_ExprVt__ctor(&GroupedExprVt);
vt = &GroupedExprVt;
vt->dtor = pk_GroupedExpr__dtor;
vt->emit_ = pk_GroupedExpr__emit_;
vt->emit_del = pk_GroupedExpr__emit_del;
vt->emit_store = pk_GroupedExpr__emit_store;
}

View File

@ -21,18 +21,18 @@ typedef struct pk_Lexer{
c11_vector/*T=int*/ indents;
} pk_Lexer;
typedef struct pk_TokenDeserializer {
typedef struct TokenDeserializer {
const char* curr;
const char* source;
} pk_TokenDeserializer;
} TokenDeserializer;
void pk_TokenDeserializer__ctor(pk_TokenDeserializer* self, const char* source);
bool pk_TokenDeserializer__match_char(pk_TokenDeserializer* self, char c);
c11_string pk_TokenDeserializer__read_string(pk_TokenDeserializer* self, char c);
py_Str pk_TokenDeserializer__read_string_from_hex(pk_TokenDeserializer* self, char c);
int pk_TokenDeserializer__read_count(pk_TokenDeserializer* self);
int64_t pk_TokenDeserializer__read_uint(pk_TokenDeserializer* self, char c);
double pk_TokenDeserializer__read_float(pk_TokenDeserializer* self, char c);
void TokenDeserializer__ctor(TokenDeserializer* self, const char* source);
bool TokenDeserializer__match_char(TokenDeserializer* self, char c);
c11_string TokenDeserializer__read_string(TokenDeserializer* self, char c);
py_Str TokenDeserializer__read_string_from_hex(TokenDeserializer* self, char c);
int TokenDeserializer__read_count(TokenDeserializer* self);
int64_t TokenDeserializer__read_uint(TokenDeserializer* self, char c);
double TokenDeserializer__read_float(TokenDeserializer* self, char c);
const static TokenValue EmptyTokenValue;
@ -376,7 +376,7 @@ static Error* eat_number(pk_Lexer* self){
return NULL;
}
// try integer
TokenValue value = {.index = TokenValue_EMPTY};
TokenValue value = {.index = TokenValue_I64};
switch(parse_uint(text, &value._i64, -1)) {
case IntParsing_SUCCESS:
add_token_with_value(self, TK_NUM, value);
@ -553,34 +553,34 @@ static Error* lex_one_token(pk_Lexer* self, bool* eof){
}
static Error* from_precompiled(pk_Lexer* self) {
pk_TokenDeserializer deserializer;
pk_TokenDeserializer__ctor(&deserializer, py_Str__data(&self->src->source));
TokenDeserializer deserializer;
TokenDeserializer__ctor(&deserializer, py_Str__data(&self->src->source));
deserializer.curr += 5; // skip "pkpy:"
c11_string version = pk_TokenDeserializer__read_string(&deserializer, '\n');
c11_string version = TokenDeserializer__read_string(&deserializer, '\n');
if(c11_string__cmp3(version, PK_VERSION) != 0) {
return SyntaxError("precompiled version mismatch");
}
if(pk_TokenDeserializer__read_uint(&deserializer, '\n') != (int64_t)self->src->mode){
if(TokenDeserializer__read_uint(&deserializer, '\n') != (int64_t)self->src->mode){
return SyntaxError("precompiled mode mismatch");
}
int count = pk_TokenDeserializer__read_count(&deserializer);
int count = TokenDeserializer__read_count(&deserializer);
c11_vector* precompiled_tokens = &self->src->_precompiled_tokens;
for(int i = 0; i < count; i++) {
c11_string item = pk_TokenDeserializer__read_string(&deserializer, '\n');
c11_string item = TokenDeserializer__read_string(&deserializer, '\n');
py_Str copied_item;
py_Str__ctor2(&copied_item, item.data, item.size);
c11_vector__push(py_Str, precompiled_tokens, copied_item);
}
count = pk_TokenDeserializer__read_count(&deserializer);
count = TokenDeserializer__read_count(&deserializer);
for(int i = 0; i < count; i++) {
Token t;
t.type = (TokenIndex)pk_TokenDeserializer__read_uint(&deserializer, ',');
t.type = (TokenIndex)TokenDeserializer__read_uint(&deserializer, ',');
if(is_raw_string_used(t.type)) {
int64_t index = pk_TokenDeserializer__read_uint(&deserializer, ',');
int64_t index = TokenDeserializer__read_uint(&deserializer, ',');
py_Str* p = c11__at(py_Str, precompiled_tokens, index);
t.start = py_Str__data(p);
t.length = c11__getitem(py_Str, precompiled_tokens, index).size;
@ -589,30 +589,30 @@ static Error* from_precompiled(pk_Lexer* self) {
t.length = 0;
}
if(pk_TokenDeserializer__match_char(&deserializer, ',')) {
if(TokenDeserializer__match_char(&deserializer, ',')) {
t.line = c11_vector__back(Token, &self->nexts).line;
} else {
t.line = (int)pk_TokenDeserializer__read_uint(&deserializer, ',');
t.line = (int)TokenDeserializer__read_uint(&deserializer, ',');
}
if(pk_TokenDeserializer__match_char(&deserializer, ',')) {
if(TokenDeserializer__match_char(&deserializer, ',')) {
t.brackets_level = c11_vector__back(Token, &self->nexts).brackets_level;
} else {
t.brackets_level = (int)pk_TokenDeserializer__read_uint(&deserializer, ',');
t.brackets_level = (int)TokenDeserializer__read_uint(&deserializer, ',');
}
char type = (*deserializer.curr++); // read_char
switch(type) {
case 'I': {
int64_t res = pk_TokenDeserializer__read_uint(&deserializer, '\n');
int64_t res = TokenDeserializer__read_uint(&deserializer, '\n');
t.value = (TokenValue){TokenValue_I64, ._i64 = res};
} break;
case 'F': {
double res = pk_TokenDeserializer__read_float(&deserializer, '\n');
double res = TokenDeserializer__read_float(&deserializer, '\n');
t.value = (TokenValue){TokenValue_F64, ._f64 = res};
} break;
case 'S': {
py_Str res = pk_TokenDeserializer__read_string_from_hex(&deserializer, '\n');
py_Str res = TokenDeserializer__read_string_from_hex(&deserializer, '\n');
t.value = (TokenValue){TokenValue_STR, ._str = res};
} break;
default:
@ -875,12 +875,12 @@ const char* pk_TokenSymbols[] = {
"try", "while", "with", "yield",
};
void pk_TokenDeserializer__ctor(pk_TokenDeserializer* self, const char* source){
void TokenDeserializer__ctor(TokenDeserializer* self, const char* source){
self->curr = source;
self->source = source;
}
bool pk_TokenDeserializer__match_char(pk_TokenDeserializer* self, char c){
bool TokenDeserializer__match_char(TokenDeserializer* self, char c){
if(*self->curr == c) {
self->curr++;
return true;
@ -888,7 +888,7 @@ bool pk_TokenDeserializer__match_char(pk_TokenDeserializer* self, char c){
return false;
}
c11_string pk_TokenDeserializer__read_string(pk_TokenDeserializer* self, char c){
c11_string TokenDeserializer__read_string(TokenDeserializer* self, char c){
const char* start = self->curr;
while(*self->curr != c)
self->curr++;
@ -897,8 +897,8 @@ c11_string pk_TokenDeserializer__read_string(pk_TokenDeserializer* self, char c)
return retval;
}
py_Str pk_TokenDeserializer__read_string_from_hex(pk_TokenDeserializer* self, char c){
c11_string sv = pk_TokenDeserializer__read_string(self, c);
py_Str TokenDeserializer__read_string_from_hex(TokenDeserializer* self, char c){
c11_string sv = TokenDeserializer__read_string(self, c);
const char* s = sv.data;
char* buffer = (char*)malloc(sv.size / 2 + 1);
for(int i = 0; i < sv.size; i += 2) {
@ -927,13 +927,13 @@ py_Str pk_TokenDeserializer__read_string_from_hex(pk_TokenDeserializer* self, ch
};
}
int pk_TokenDeserializer__read_count(pk_TokenDeserializer* self){
int TokenDeserializer__read_count(TokenDeserializer* self){
assert(*self->curr == '=');
self->curr++;
return pk_TokenDeserializer__read_uint(self, '\n');
return TokenDeserializer__read_uint(self, '\n');
}
int64_t pk_TokenDeserializer__read_uint(pk_TokenDeserializer* self, char c){
int64_t TokenDeserializer__read_uint(TokenDeserializer* self, char c){
int64_t out = 0;
while(*self->curr != c) {
out = out * 10 + (*self->curr - '0');
@ -943,8 +943,8 @@ int64_t pk_TokenDeserializer__read_uint(pk_TokenDeserializer* self, char c){
return out;
}
double pk_TokenDeserializer__read_float(pk_TokenDeserializer* self, char c){
c11_string sv = pk_TokenDeserializer__read_string(self, c);
double TokenDeserializer__read_float(TokenDeserializer* self, char c){
c11_string sv = TokenDeserializer__read_string(self, c);
py_Str nullterm;
py_Str__ctor2(&nullterm, sv.data, sv.size);
char* end;

File diff suppressed because it is too large Load Diff

1151
src/interpreter/ceval.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -10,16 +10,16 @@ void ValueStack__clear(ValueStack* self) {
self->sp = self->begin;
}
PyVar* FastLocals__try_get_by_name(PyVar* locals, const CodeObject* co, py_Name name){
py_TValue* FastLocals__try_get_by_name(py_TValue* locals, const CodeObject* co, py_Name name){
int index = c11_smallmap_n2i__get(&co->varnames_inv, name, -1);
if(index == -1) return NULL;
return &locals[index];
}
pk_NameDict* FastLocals__to_namedict(PyVar* locals, const CodeObject* co) {
pk_NameDict* FastLocals__to_namedict(py_TValue* locals, const CodeObject* co) {
pk_NameDict* dict = pk_NameDict__new();
c11__foreach(c11_smallmap_n2i_KV, &co->varnames_inv, entry) {
PyVar value = locals[entry->value];
py_TValue value = locals[entry->value];
if(!py_isnull(&value)){
pk_NameDict__set(dict, entry->key, value);
}
@ -39,14 +39,14 @@ void UnwindTarget__delete(UnwindTarget* self){
free(self);
}
Frame* Frame__new(const CodeObject* co, const PyVar* module, const PyVar* function, PyVar* p0, PyVar* locals, const CodeObject* locals_co){
Frame* Frame__new(const CodeObject* co, const py_TValue* module, const py_TValue* function, py_TValue* p0, py_TValue* locals, const CodeObject* locals_co){
static_assert(sizeof(Frame) <= kPoolFrameBlockSize, "!(sizeof(Frame) <= kPoolFrameBlockSize)");
Frame* self = PoolFrame_alloc();
self->f_back = NULL;
self->ip = (Bytecode*)co->codes.data - 1;
self->co = co;
self->module = module->_obj;
self->function = function->_obj;
self->function = function ? function->_obj : NULL;
self->p0 = p0;
self->locals = locals;
self->locals_co = locals_co;
@ -72,7 +72,7 @@ int Frame__prepare_jump_exception_handler(Frame* self, ValueStack* _s){
iblock = block->parent;
}
if(iblock < 0) return -1;
PyVar obj = *--_s->sp; // pop exception object
py_TValue obj = *--_s->sp; // pop exception object
UnwindTarget* uw = Frame__find_unwind_target(self, iblock);
_s->sp = (self->locals + uw->offset); // unwind the stack
*(_s->sp++) = obj; // push it back
@ -121,7 +121,7 @@ UnwindTarget* Frame__find_unwind_target(Frame* self, int iblock){
return NULL;
}
void Frame__set_unwind_target(Frame* self, PyVar* sp) {
void Frame__set_unwind_target(Frame* self, py_TValue* sp) {
int iblock = Frame__iblock(self);
UnwindTarget* existing = Frame__find_unwind_target(self, iblock);
if(existing) {
@ -131,3 +131,11 @@ void Frame__set_unwind_target(Frame* self, PyVar* sp) {
self->uw_list = UnwindTarget__new(prev, iblock, sp - self->locals);
}
}
py_TValue* Frame__f_closure_try_get(Frame* self, StrName name){
// if(self->function == NULL) return NULL;
// pkpy::Function* fn = PyObject__as(pkpy::Function, self->function);
// if(fn->_closure == nullptr) return nullptr;
// return pk_NameDict__try_get(fn->_closure, name);
return NULL;
}

View File

@ -119,7 +119,7 @@ PyObject* PyObject__new(py_Type type, int slots, int size){
// initialize slots or dict
void* p = (char*)self + 8;
if(slots >= 0){
memset(p, 0, slots*sizeof(PyVar));
memset(p, 0, slots*sizeof(py_TValue));
}else{
pk_NameDict__ctor(p);
}

View File

@ -1,14 +0,0 @@
#include "pocketpy/interpreter/vm.h"
#include "pocketpy/pocketpy.h"
int py_eq(const py_Ref lhs, const py_Ref rhs){
return 0;
}
int py_le(const py_Ref lhs, const py_Ref rhs){
return 0;
}
int py_hash(const py_Ref self, int64_t* out){
return 0;
}

View File

@ -7,17 +7,23 @@ static unsigned char* pk_default_import_file(const char* path){
return NULL;
}
static void pk_default_stdout(const char* s){
fprintf(stdout, "%s", s);
static void pk_default_stdout(const char* fmt, ...){
va_list args;
va_start(args, fmt);
vfprintf(stdout, fmt, args);
va_end(args);
fflush(stdout);
}
static void pk_default_stderr(const char* s){
fprintf(stderr, "%s", s);
static void pk_default_stderr(const char* fmt, ...){
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
fflush(stderr);
}
void pk_TypeInfo__ctor(pk_TypeInfo *self, py_Name name, py_Type base, PyObject* obj, const PyVar* module, bool subclass_enabled){
void pk_TypeInfo__ctor(pk_TypeInfo *self, py_Name name, py_Type base, PyObject* obj, const py_TValue* module, bool subclass_enabled){
memset(self, 0, sizeof(pk_TypeInfo));
self->name = name;
@ -50,6 +56,7 @@ void pk_VM__ctor(pk_VM* self){
self->_stderr = pk_default_stderr;
self->last_error = NULL;
self->last_retval = PY_NULL;
self->__curr_class = NULL;
self->__cached_object_new = NULL;
@ -58,19 +65,19 @@ void pk_VM__ctor(pk_VM* self){
pk_ManagedHeap__ctor(&self->heap, self);
ValueStack__ctor(&self->stack);
self->True = (PyVar){.type=tp_bool, .is_ptr=true, .extra=1,
self->True = (py_TValue){.type=tp_bool, .is_ptr=true, .extra=1,
._obj=pk_ManagedHeap__gcnew(&self->heap, tp_bool, 0, 0),
};
self->False = (PyVar){.type=tp_bool, .is_ptr=true, .extra=0,
self->False = (py_TValue){.type=tp_bool, .is_ptr=true, .extra=0,
._obj=pk_ManagedHeap__gcnew(&self->heap, tp_bool, 0, 0),
};
self->None = (PyVar){.type=tp_none_type, .is_ptr=true,
self->None = (py_TValue){.type=tp_none_type, .is_ptr=true,
._obj=pk_ManagedHeap__gcnew(&self->heap, tp_none_type, 0, 0),
};
self->NotImplemented = (PyVar){.type=tp_not_implemented_type, .is_ptr=true,
self->NotImplemented = (py_TValue){.type=tp_not_implemented_type, .is_ptr=true,
._obj=pk_ManagedHeap__gcnew(&self->heap, tp_not_implemented_type, 0, 0),
};
self->Ellipsis = (PyVar){.type=tp_ellipsis, .is_ptr=true,
self->Ellipsis = (py_TValue){.type=tp_ellipsis, .is_ptr=true,
._obj=pk_ManagedHeap__gcnew(&self->heap, tp_ellipsis, 0, 0),
};
@ -147,7 +154,9 @@ void pk_VM__ctor(pk_VM* self){
}
void pk_VM__dtor(pk_VM* self){
PK_DECREF(self->__dynamic_func_decl);
if(self->__dynamic_func_decl){
PK_DECREF(self->__dynamic_func_decl);
}
// destroy all objects
pk_ManagedHeap__dtor(&self->heap);
// clear frames
@ -165,15 +174,14 @@ void pk_VM__push_frame(pk_VM* self, Frame* frame){
void pk_VM__pop_frame(pk_VM* self){
assert(self->top_frame);
Frame* frame = self->top_frame;
// reset stack pointer
self->stack.sp = frame->p0;
// pop frame and delete
self->top_frame = frame->f_back;
Frame__delete(frame);
}
pk_FrameResult pk_VM__run_top_frame(pk_VM* self){
return RES_RETURN;
}
py_Type pk_VM__new_type(pk_VM* self, const char* name, py_Type base, const PyVar* module, bool subclass_enabled){
py_Type pk_VM__new_type(pk_VM* self, const char* name, py_Type base, const py_TValue* module, bool subclass_enabled){
py_Type type = self->types.count;
pk_TypeInfo* ti = c11_vector__emplace(&self->types);
PyObject* typeobj = pk_ManagedHeap__gcnew(&self->heap, tp_type, -1, sizeof(py_Type));
@ -185,7 +193,7 @@ py_Type pk_VM__new_type(pk_VM* self, const char* name, py_Type base, const PyVar
/****************************************/
void PyObject__delete(PyObject *self){
pk_TypeInfo* ti = c11__getitem(pk_TypeInfo*, &pk_current_vm->types, self->type);
pk_TypeInfo* ti = c11__at(pk_TypeInfo, &pk_current_vm->types, self->type);
if(ti->dtor) ti->dtor(PyObject__value(self));
if(self->slots == -1) pk_NameDict__dtor(PyObject__dict(self));
if(self->gc_is_large){

View File

@ -1,6 +1,6 @@
#include "pocketpy/objects/base.h"
PyVar PY_NULL = {.type=0, .is_ptr=false, .extra=0, ._i64=0};
PyVar PY_OP_CALL = {.type=27, .is_ptr=false, .extra=0, ._i64=0};
PyVar PY_OP_YIELD = {.type=28, .is_ptr=false, .extra=0, ._i64=0};
py_TValue PY_NULL = {.type=0, .is_ptr=false, .extra=0, ._i64=0};
py_TValue PY_OP_CALL = {.type=27, .is_ptr=false, .extra=0, ._i64=0};
py_TValue PY_OP_YIELD = {.type=28, .is_ptr=false, .extra=0, ._i64=0};

View File

@ -13,7 +13,7 @@ bool Bytecode__is_forward_jump(const Bytecode* self) {
return self->op >= OP_JUMP_FORWARD && self->op <= OP_LOOP_BREAK;
}
FuncDecl_ FuncDecl__rcnew(pk_SourceData_ src, c11_string name){
FuncDecl_ FuncDecl__rcnew(pk_SourceData_ src, c11_string name) {
FuncDecl* self = malloc(sizeof(FuncDecl));
self->rc.count = 1;
self->rc.dtor = (void (*)(void*))FuncDecl__dtor;
@ -33,27 +33,28 @@ FuncDecl_ FuncDecl__rcnew(pk_SourceData_ src, c11_string name){
return self;
}
void FuncDecl__dtor(FuncDecl* self){
void FuncDecl__dtor(FuncDecl* self) {
CodeObject__dtor(&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){
void FuncDecl__add_kwarg(FuncDecl* self, int index, uint16_t key, const py_TValue* value) {
c11_smallmap_n2i__set(&self->kw_to_index, key, index);
FuncDeclKwArg item = {index, key, *value};
c11_vector__push(FuncDeclKwArg, &self->kwargs, item);
}
void CodeObject__ctor(CodeObject* self, pk_SourceData_ src, c11_string name){
self->src = src; PK_INCREF(src);
void CodeObject__ctor(CodeObject* self, pk_SourceData_ src, c11_string name) {
self->src = src;
PK_INCREF(src);
py_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->consts, sizeof(py_TValue));
c11_vector__ctor(&self->varnames, sizeof(uint16_t));
self->nlocals = 0;
@ -70,10 +71,10 @@ void CodeObject__ctor(CodeObject* self, pk_SourceData_ src, c11_string name){
c11_vector__push(CodeBlock, &self->blocks, root_block);
}
void CodeObject__dtor(CodeObject* self){
void CodeObject__dtor(CodeObject* self) {
PK_DECREF(self->src);
py_Str__dtor(&self->name);
c11_vector__dtor(&self->codes);
c11_vector__dtor(&self->codes_ex);
@ -85,7 +86,7 @@ void CodeObject__dtor(CodeObject* self){
c11_vector__dtor(&self->blocks);
for(int i=0; i<self->func_decls.count; i++){
for(int i = 0; i < self->func_decls.count; i++) {
FuncDecl_ decl = c11__getitem(FuncDecl_, &self->func_decls, i);
PK_DECREF(decl);
}

View File

@ -13,8 +13,8 @@
#define pkpy_Var__set_null(self) do { (self)->type = 0; } while(0)
struct pkpy_DictEntry {
PyVar key;
PyVar val;
py_TValue key;
py_TValue val;
};
inline extern int pkpy_Dict__idx_size(const pkpy_Dict* self) {
@ -79,7 +79,7 @@ static void pkpy_Dict__htset(pkpy_Dict* self, int h, int v) {
#endif
}
static int pkpy_Dict__probe0(const pkpy_Dict* self, PyVar key, int hash) {
static int pkpy_Dict__probe0(const pkpy_Dict* self, py_TValue key, int hash) {
const int null = pkpy_Dict__idx_null(self);
const int mask = self->_htcap - 1;
for(int h = hash & mask;; h = DICT_HASH_NEXT(h) & mask) {
@ -92,7 +92,7 @@ static int pkpy_Dict__probe0(const pkpy_Dict* self, PyVar key, int hash) {
PK_UNREACHABLE();
}
static int pkpy_Dict__probe1(const pkpy_Dict* self, PyVar key, int hash) {
static int pkpy_Dict__probe1(const pkpy_Dict* self, py_TValue key, int hash) {
const int null = pkpy_Dict__idx_null(self);
const int mask = self->_htcap - 1;
for(int h = hash & mask;; h = DICT_HASH_NEXT(h) & mask) {
@ -124,7 +124,7 @@ static void pkpy_Dict__extendht(pkpy_Dict* self) {
}
}
bool pkpy_Dict__set(pkpy_Dict* self, PyVar key, PyVar val) {
bool pkpy_Dict__set(pkpy_Dict* self, py_TValue key, py_TValue val) {
int64_t out;
int err = py_hash(&key, &out);
int hash = DICT_HASH_TRANS(out);
@ -161,7 +161,7 @@ bool pkpy_Dict__set(pkpy_Dict* self, PyVar key, PyVar val) {
return false;
}
bool pkpy_Dict__contains(const pkpy_Dict* self, PyVar key) {
bool pkpy_Dict__contains(const pkpy_Dict* self, py_TValue key) {
int64_t out;
int err = py_hash(&key, &out);
int hash = DICT_HASH_TRANS(out);
@ -205,7 +205,7 @@ static bool pkpy_Dict__refactor(pkpy_Dict* self) {
return true;
}
bool pkpy_Dict__del(pkpy_Dict* self, PyVar key) {
bool pkpy_Dict__del(pkpy_Dict* self, py_TValue key) {
int64_t out;
int err = py_hash(&key, &out);
int hash = DICT_HASH_TRANS(out);
@ -220,7 +220,7 @@ bool pkpy_Dict__del(pkpy_Dict* self, PyVar key) {
return true;
}
const PyVar *pkpy_Dict__try_get(const pkpy_Dict* self, PyVar key) {
const py_TValue *pkpy_Dict__try_get(const pkpy_Dict* self, py_TValue key) {
int64_t out;
int err = py_hash(&key, &out);
int hash = DICT_HASH_TRANS(out);
@ -263,7 +263,7 @@ pkpy_DictIter pkpy_Dict__iter(const pkpy_Dict *self) {
};
}
bool pkpy_DictIter__next(pkpy_DictIter *self, PyVar *key, PyVar *val) {
bool pkpy_DictIter__next(pkpy_DictIter *self, py_TValue *key, py_TValue *val) {
if(self->_index >= self->_dict->_entries.count) return false;
struct pkpy_DictEntry* entry = &c11__getitem(struct pkpy_DictEntry, &self->_dict->_entries, self->_index);

View File

@ -2,7 +2,7 @@
#define SMALLMAP_T__SOURCE
#define K uint16_t
#define V PyVar
#define V py_TValue
#define NAME pk_NameDict
#include "pocketpy/xmacros/smallmap.h"
#undef SMALLMAP_T__SOURCE

View File

@ -11,7 +11,7 @@ pk_NameDict* PyObject__dict(PyObject* self){
return (pk_NameDict*)((char*)self + 8);
}
PyVar* PyObject__slots(PyObject* self){
py_TValue* PyObject__slots(PyObject* self){
assert(self->slots >= 0);
return (PyVar*)((char*)self + 8);
return (py_TValue*)((char*)self + 8);
}

28
src/public/py_ops.c Normal file
View File

@ -0,0 +1,28 @@
#include "pocketpy/interpreter/vm.h"
#include "pocketpy/pocketpy.h"
int py_eq(const py_Ref lhs, const py_Ref rhs) { return 0; }
int py_le(const py_Ref lhs, const py_Ref rhs) { return 0; }
int py_hash(const py_Ref val, int64_t* out) { return 0; }
int py_str(const py_Ref val) { return 0; }
int py_repr(const py_Ref val) {
const pk_TypeInfo* ti = c11__at(pk_TypeInfo, &pk_current_vm->types, val->type);
if(ti->m__repr__) return ti->m__repr__(1, val);
return py_callmethod(val, __repr__);
}
int py_getattr(const py_Ref self, py_Name name, py_Ref out){
return -1;
}
int py_setattr(py_Ref self, py_Name name, const py_Ref val){
return -1;
}
int py_callmethod(py_Ref self, py_Name name, ...){
return -1;
}

25
src/public/py_tuple.c Normal file
View File

@ -0,0 +1,25 @@
#include "pocketpy/pocketpy.h"
#include "pocketpy/common/utils.h"
#include "pocketpy/objects/object.h"
#include "pocketpy/interpreter/vm.h"
void py_newtuple(py_Ref out, int n) {
pk_VM* vm = pk_current_vm;
PyObject* obj = pk_ManagedHeap__gcnew(&vm->heap, tp_tuple, n, 0);
out->type = tp_tuple;
out->is_ptr = true;
out->_obj = obj;
}
py_Ref py_tuple__getitem(const py_Ref self, int i){
return py_getslot(self, i);
}
void py_tuple__setitem(py_Ref self, int i, const py_Ref val){
py_setslot(self, i, val);
}
int py_tuple__len(const py_Ref self){
return self->_obj->slots;
}

View File

@ -4,6 +4,13 @@
#include "pocketpy/objects/object.h"
#include "pocketpy/interpreter/vm.h"
py_Ref py_getreg(int i){
return pk_current_vm->reg + i;
}
void py_setreg(int i, const py_Ref val){
pk_current_vm->reg[i] = *val;
}
py_Ref py_getdict(const py_Ref self, py_Name name){
assert(self && self->is_ptr);

View File

@ -46,14 +46,6 @@ void py_newnone(py_Ref out) {
void py_newnull(py_Ref out) { out->type = 0; }
void py_newtuple(py_Ref out, int n) {
pk_VM* vm = pk_current_vm;
PyObject* obj = pk_ManagedHeap__gcnew(&vm->heap, tp_tuple, n, 0);
out->type = tp_tuple;
out->is_ptr = true;
out->_obj = obj;
}
void py_newfunction(py_Ref out, py_CFunction f, const char* sig) {
py_newfunction2(out, f, sig, BindType_FUNCTION, NULL, NULL);
}
@ -95,9 +87,9 @@ void py_pushstr(const char* val) { py_newstr(pk_current_vm->stack.sp++, val); }
void py_pushstrn(const char* val, int size) { py_newstrn(pk_current_vm->stack.sp++, val, size); }
void py_push_none() { py_newnone(pk_current_vm->stack.sp++); }
void py_pushnone() { py_newnone(pk_current_vm->stack.sp++); }
void py_push_null() { py_newnull(pk_current_vm->stack.sp++); }
void py_pushnull() { py_newnull(pk_current_vm->stack.sp++); }
void py_push_notimplemented() {
pk_VM* vm = pk_current_vm;

View File

@ -23,29 +23,26 @@ void py_finalize() {
pk_MemoryPools__finalize();
}
int py_exec(const char* source) {
pk_SourceData_ src = pk_SourceData__rcnew(source, "main.py", EXEC_MODE, false);
CodeObject co;
Error* err = pk_compile(src, &co);
PK_DECREF(src);
if(err) abort();
int py_exec(const char* source) { PK_UNREACHABLE(); }
int py_eval(const char* source, py_Ref out) {
CodeObject co;
pk_SourceData_ src = pk_SourceData__rcnew(source, "main.py", EVAL_MODE, false);
Error* err = pk_compile(src, &co);
if(err) {
PK_DECREF(src);
return -1;
}
pk_VM* vm = pk_current_vm;
Frame* frame = Frame__new(&co, &vm->main, NULL, vm->stack.sp, vm->stack.sp, &co);
pk_VM__push_frame(vm, frame);
pk_FrameResult res = pk_VM__run_top_frame(vm);
CodeObject__dtor(&co);
PK_DECREF(src);
if(res == RES_ERROR) return vm->last_error->type;
if(res == RES_RETURN) return 0;
PK_UNREACHABLE();
}
int py_eval(const char* source) {
CodeObject* co = NULL;
pk_VM* vm = pk_current_vm;
Frame* frame = Frame__new(co, &vm->main, NULL, vm->stack.sp, vm->stack.sp, co);
pk_VM__push_frame(vm, frame);
pk_FrameResult res = pk_VM__run_top_frame(vm);
if(res == RES_ERROR) return vm->last_error->type;
if(res == RES_RETURN) return 0;
if(res == RES_RETURN){
*out = vm->last_retval;
return 0;
}
PK_UNREACHABLE();
}

View File

@ -24,19 +24,38 @@ int main(int argc, char** argv) {
SetConsoleOutputCP(CP_UTF8);
#endif
if(argc != 2) goto __HELP;
char* source = read_file(argv[1]);
py_initialize();
const char* source = "1, 'a'";
if(py_exec(source)){
py_Ref r0 = py_getreg(0);
if(py_eval(source, r0)){
py_Error* err = py_getlasterror();
py_Error__print(err);
}else{
// handle the result
py_Ref _0 = py_tuple__getitem(r0, 0);
py_Ref _1 = py_tuple__getitem(r0, 1);
int _L0 = py_toint(_0);
const char* _L1 = py_tostr(_1);
printf("%d, %s\n", _L0, _L1);
}
py_finalize();
free(source);
__HELP:
printf("Usage: pocketpy [filename]\n");
py_finalize();
return 0;
// if(argc != 2) goto __HELP;
// char* source = read_file(argv[1]);
// py_initialize();
// if(py_exec(source)){
// py_Error* err = py_getlasterror();
// py_Error__print(err);
// }
// py_finalize();
// free(source);
// __HELP:
// printf("Usage: pocketpy [filename]\n");
// return 0;
}