a bunch of rename

This commit is contained in:
blueloveTH 2023-02-10 16:28:08 +08:00
parent 1c6ea53050
commit b20e9b49c0
11 changed files with 388 additions and 382 deletions

View File

@ -23,7 +23,7 @@ struct Bytecode{
uint16_t block; uint16_t block;
}; };
_Str pad(const _Str& s, const int n){ Str pad(const Str& s, const int n){
if(s.size() >= n) return s.substr(0, n); if(s.size() >= n) return s.substr(0, n);
return s + std::string(n - s.size(), ' '); return s + std::string(n - s.size(), ' ');
} }
@ -50,27 +50,27 @@ struct CodeBlock {
struct CodeObject { struct CodeObject {
pkpy::shared_ptr<SourceData> src; pkpy::shared_ptr<SourceData> src;
_Str name; Str name;
CodeObject(pkpy::shared_ptr<SourceData> src, _Str name) { CodeObject(pkpy::shared_ptr<SourceData> src, Str name) {
this->src = src; this->src = src;
this->name = name; this->name = name;
} }
std::vector<Bytecode> codes; std::vector<Bytecode> codes;
PyVarList consts; pkpy::List consts;
std::vector<std::pair<_Str, NameScope>> names; std::vector<std::pair<Str, NameScope>> names;
emhash8::HashMap<_Str, int> global_names; emhash8::HashMap<Str, int> global_names;
std::vector<CodeBlock> blocks = { CodeBlock{NO_BLOCK, -1} }; std::vector<CodeBlock> blocks = { CodeBlock{NO_BLOCK, -1} };
emhash8::HashMap<_Str, int> labels; emhash8::HashMap<Str, int> labels;
bool add_label(const _Str& label){ bool add_label(const Str& label){
if(labels.contains(label)) return false; if(labels.contains(label)) return false;
labels[label] = codes.size(); labels[label] = codes.size();
return true; return true;
} }
int add_name(_Str name, NameScope scope){ int add_name(Str name, NameScope scope){
if(scope == NAME_LOCAL && global_names.contains(name)) scope = NAME_GLOBAL; if(scope == NAME_LOCAL && global_names.contains(name)) scope = NAME_GLOBAL;
auto p = std::make_pair(name, scope); auto p = std::make_pair(name, scope);
for(int i=0; i<names.size(); i++){ for(int i=0; i<names.size(); i++){
@ -116,16 +116,16 @@ struct Frame {
int _ip = -1; int _ip = -1;
int _next_ip = 0; int _next_ip = 0;
const _Code co; const CodeObject_ co;
PyVar _module; PyVar _module;
pkpy::shared_ptr<PyVarDict> _locals; pkpy::shared_ptr<pkpy::NameDict> _locals;
const i64 id; const i64 id;
std::stack<std::pair<int, std::vector<PyVar>>> s_try_block; std::stack<std::pair<int, std::vector<PyVar>>> s_try_block;
inline PyVarDict& f_locals() noexcept { return *_locals; } inline pkpy::NameDict& f_locals() noexcept { return *_locals; }
inline PyVarDict& f_globals() noexcept { return _module->attribs; } inline pkpy::NameDict& f_globals() noexcept { return _module->attribs; }
Frame(const _Code co, PyVar _module, pkpy::shared_ptr<PyVarDict> _locals) Frame(const CodeObject_ co, PyVar _module, pkpy::shared_ptr<pkpy::NameDict> _locals)
: co(co), _module(_module), _locals(_locals), id(kFrameGlobalId++) { } : co(co), _module(_module), _locals(_locals), id(kFrameGlobalId++) { }
inline const Bytecode& next_bytecode() { inline const Bytecode& next_bytecode() {
@ -134,12 +134,12 @@ struct Frame {
return co->codes[_ip]; return co->codes[_ip];
} }
_Str snapshot(){ Str snapshot(){
int line = co->codes[_ip].line; int line = co->codes[_ip].line;
return co->src->snapshot(line); return co->src->snapshot(line);
} }
_Str stack_info(){ Str stack_info(){
_StrStream ss; _StrStream ss;
ss << "["; ss << "[";
for(int i=0; i<_data.size(); i++){ for(int i=0; i<_data.size(); i++){

View File

@ -19,18 +19,18 @@ enum StringType { NORMAL_STRING, RAW_STRING, F_STRING };
class Compiler { class Compiler {
std::unique_ptr<Parser> parser; std::unique_ptr<Parser> parser;
std::stack<_Code> codes; std::stack<CodeObject_> codes;
bool is_compiling_class = false; bool is_compiling_class = false;
int lexing_count = 0; int lexing_count = 0;
bool used = false; bool used = false;
VM* vm; VM* vm;
emhash8::HashMap<TokenIndex, GrammarRule> rules; emhash8::HashMap<TokenIndex, GrammarRule> rules;
_Code co() const{ return codes.top(); } CodeObject_ co() const{ return codes.top(); }
CompileMode mode() const{ return parser->src->mode; } CompileMode mode() const{ return parser->src->mode; }
public: public:
Compiler(VM* vm, const char* source, _Str filename, CompileMode mode){ Compiler(VM* vm, const char* source, Str filename, CompileMode mode){
this->vm = vm; this->vm = vm;
this->parser = std::make_unique<Parser>( this->parser = std::make_unique<Parser>(
pkpy::make_shared<SourceData>(source, filename, mode) pkpy::make_shared<SourceData>(source, filename, mode)
@ -99,7 +99,7 @@ public:
} }
private: private:
_Str eat_string_until(char quote, bool raw) { Str eat_string_until(char quote, bool raw) {
bool quote3 = parser->match_n_chars(2, quote); bool quote3 = parser->match_n_chars(2, quote);
std::vector<char> buff; std::vector<char> buff;
while (true) { while (true) {
@ -138,11 +138,11 @@ private:
buff.push_back(c); buff.push_back(c);
} }
} }
return _Str(buff.data(), buff.size()); return Str(buff.data(), buff.size());
} }
void eat_string(char quote, StringType type) { void eat_string(char quote, StringType type) {
_Str s = eat_string_until(quote, type == RAW_STRING); Str s = eat_string_until(quote, type == RAW_STRING);
if(type == F_STRING){ if(type == F_STRING){
parser->set_next_token(TK("@fstr"), vm->PyStr(s)); parser->set_next_token(TK("@fstr"), vm->PyStr(s));
}else{ }else{
@ -190,7 +190,7 @@ private:
parser->prev = parser->curr; parser->prev = parser->curr;
parser->curr = parser->next_token(); parser->curr = parser->next_token();
//_Str _info = parser->curr.info(); std::cout << _info << '[' << parser->current_line << ']' << std::endl; //Str _info = parser->curr.info(); std::cout << _info << '[' << parser->current_line << ']' << std::endl;
while (parser->peekchar() != '\0') { while (parser->peekchar() != '\0') {
parser->token_start = parser->curr_char; parser->token_start = parser->curr_char;
@ -357,7 +357,7 @@ private:
void exprFString() { void exprFString() {
static const std::regex pattern(R"(\{(.*?)\})"); static const std::regex pattern(R"(\{(.*?)\})");
PyVar value = parser->prev.value; PyVar value = parser->prev.value;
_Str s = vm->PyStr_AS_C(value); Str s = vm->PyStr_AS_C(value);
std::sregex_iterator begin(s.begin(), s.end(), pattern); std::sregex_iterator begin(s.begin(), s.end(), pattern);
std::sregex_iterator end; std::sregex_iterator end;
int size = 0; int size = 0;
@ -384,7 +384,7 @@ private:
} }
void exprLambda() { void exprLambda() {
_Func func = pkpy::make_shared<Function>(); pkpy::Function_ func = pkpy::make_shared<pkpy::Function>();
func->name = "<lambda>"; func->name = "<lambda>";
if(!match(TK(":"))){ if(!match(TK(":"))){
_compile_f_args(func, false); _compile_f_args(func, false);
@ -594,7 +594,7 @@ __LISTCOMP:
if (peek() == TK(")")) break; if (peek() == TK(")")) break;
if(peek() == TK("@id") && peek_next() == TK("=")) { if(peek() == TK("@id") && peek_next() == TK("=")) {
consume(TK("@id")); consume(TK("@id"));
const _Str& key = parser->prev.str(); const Str& key = parser->prev.str();
emit(OP_LOAD_CONST, co()->add_const(vm->PyStr(key))); emit(OP_LOAD_CONST, co()->add_const(vm->PyStr(key)));
consume(TK("=")); consume(TK("="));
co()->_rvalue=true; EXPR(); co()->_rvalue=false; co()->_rvalue=true; EXPR(); co()->_rvalue=false;
@ -624,7 +624,7 @@ __LISTCOMP:
void exprAttrib() { void exprAttrib() {
consume(TK("@id")); consume(TK("@id"));
const _Str& name = parser->prev.str(); const Str& name = parser->prev.str();
int index = co()->add_name(name, NAME_ATTR); int index = co()->add_name(name, NAME_ATTR);
emit(OP_BUILD_ATTR_REF, index); emit(OP_BUILD_ATTR_REF, index);
} }
@ -745,7 +745,7 @@ __LISTCOMP:
void parse_expression(Precedence precedence) { void parse_expression(Precedence precedence) {
lex_token(); lex_token();
GrammarFn prefix = rules[parser->prev.type].prefix; GrammarFn prefix = rules[parser->prev.type].prefix;
if (prefix == nullptr) SyntaxError(_Str("expected an expression, but got ") + TK_STR(parser->prev.type)); if (prefix == nullptr) SyntaxError(Str("expected an expression, but got ") + TK_STR(parser->prev.type));
(this->*prefix)(); (this->*prefix)();
while (rules[peek()].precedence >= precedence) { while (rules[peek()].precedence >= precedence) {
lex_token(); lex_token();
@ -887,7 +887,7 @@ __LISTCOMP:
} else if(match(TK("label"))){ } else if(match(TK("label"))){
if(mode() != EXEC_MODE) SyntaxError("'label' is only available in EXEC_MODE"); if(mode() != EXEC_MODE) SyntaxError("'label' is only available in EXEC_MODE");
consume(TK(".")); consume(TK("@id")); consume(TK(".")); consume(TK("@id"));
_Str label = parser->prev.str(); Str label = parser->prev.str();
bool ok = co()->add_label(label); bool ok = co()->add_label(label);
if(!ok) SyntaxError("label '" + label + "' already exists"); if(!ok) SyntaxError("label '" + label + "' already exists");
consume_end_stmt(); consume_end_stmt();
@ -947,7 +947,7 @@ __LISTCOMP:
emit(OP_BUILD_CLASS, cls_name_idx); emit(OP_BUILD_CLASS, cls_name_idx);
} }
void _compile_f_args(_Func func, bool enable_type_hints){ void _compile_f_args(pkpy::Function_ func, bool enable_type_hints){
int state = 0; // 0 for args, 1 for *args, 2 for k=v, 3 for **kwargs int state = 0; // 0 for args, 1 for *args, 2 for k=v, 3 for **kwargs
do { do {
if(state == 3) SyntaxError("**kwargs should be the last argument"); if(state == 3) SyntaxError("**kwargs should be the last argument");
@ -961,7 +961,7 @@ __LISTCOMP:
} }
consume(TK("@id")); consume(TK("@id"));
const _Str& name = parser->prev.str(); const Str& name = parser->prev.str();
if(func->hasName(name)) SyntaxError("duplicate argument name"); if(func->hasName(name)) SyntaxError("duplicate argument name");
// eat type hints // eat type hints
@ -977,7 +977,7 @@ __LISTCOMP:
consume(TK("=")); consume(TK("="));
PyVarOrNull value = read_literal(); PyVarOrNull value = read_literal();
if(value == nullptr){ if(value == nullptr){
SyntaxError(_Str("expect a literal, not ") + TK_STR(parser->curr.type)); SyntaxError(Str("expect a literal, not ") + TK_STR(parser->curr.type));
} }
func->kwArgs[name] = value; func->kwArgs[name] = value;
func->kwArgsOrder.push_back(name); func->kwArgsOrder.push_back(name);
@ -992,7 +992,7 @@ __LISTCOMP:
if(match(TK("pass"))) return; if(match(TK("pass"))) return;
consume(TK("def")); consume(TK("def"));
} }
_Func func = pkpy::make_shared<Function>(); pkpy::Function_ func = pkpy::make_shared<pkpy::Function>();
consume(TK("@id")); consume(TK("@id"));
func->name = parser->prev.str(); func->name = parser->prev.str();
@ -1029,7 +1029,7 @@ __LISTCOMP:
} }
/***** Error Reporter *****/ /***** Error Reporter *****/
void throw_err(_Str type, _Str msg){ void throw_err(Str type, Str msg){
int lineno = parser->curr.line; int lineno = parser->curr.line;
const char* cursor = parser->curr.start; const char* cursor = parser->curr.start;
// if error occurs in lexing, lineno should be `parser->current_line` // if error occurs in lexing, lineno should be `parser->current_line`
@ -1038,20 +1038,20 @@ __LISTCOMP:
cursor = parser->curr_char; cursor = parser->curr_char;
} }
if(parser->peekchar() == '\n') lineno--; if(parser->peekchar() == '\n') lineno--;
auto e = _Exception("SyntaxError", msg); auto e = pkpy::Exception("SyntaxError", msg);
e.st_push(parser->src->snapshot(lineno, cursor)); e.st_push(parser->src->snapshot(lineno, cursor));
throw e; throw e;
} }
void SyntaxError(_Str msg){ throw_err("SyntaxError", msg); } void SyntaxError(Str msg){ throw_err("SyntaxError", msg); }
void IndentationError(_Str msg){ throw_err("IndentationError", msg); } void IndentationError(Str msg){ throw_err("IndentationError", msg); }
public: public:
_Code compile(){ CodeObject_ compile(){
// can only be called once // can only be called once
if(used) UNREACHABLE(); if(used) UNREACHABLE();
used = true; used = true;
_Code code = pkpy::make_shared<CodeObject>(parser->src, _Str("<module>")); CodeObject_ code = pkpy::make_shared<CodeObject>(parser->src, Str("<module>"));
codes.push(code); codes.push(code);
lex_token(); lex_token(); lex_token(); lex_token();

View File

@ -20,7 +20,7 @@ enum CompileMode {
struct SourceData { struct SourceData {
const char* source; const char* source;
_Str filename; Str filename;
std::vector<const char*> line_starts; std::vector<const char*> line_starts;
CompileMode mode; CompileMode mode;
@ -34,7 +34,7 @@ struct SourceData {
return {_start, i}; return {_start, i};
} }
SourceData(const char* source, _Str filename, CompileMode mode) { SourceData(const char* source, Str filename, CompileMode mode) {
source = strdup(source); source = strdup(source);
// Skip utf8 BOM if there is any. // Skip utf8 BOM if there is any.
if (strncmp(source, "\xEF\xBB\xBF", 3) == 0) source += 3; if (strncmp(source, "\xEF\xBB\xBF", 3) == 0) source += 3;
@ -44,14 +44,14 @@ struct SourceData {
this->mode = mode; this->mode = mode;
} }
_Str snapshot(int lineno, const char* cursor=nullptr){ Str snapshot(int lineno, const char* cursor=nullptr){
_StrStream ss; _StrStream ss;
ss << " " << "File \"" << filename << "\", line " << lineno << '\n'; ss << " " << "File \"" << filename << "\", line " << lineno << '\n';
std::pair<const char*,const char*> pair = get_line(lineno); std::pair<const char*,const char*> pair = get_line(lineno);
_Str line = "<?>"; Str line = "<?>";
int removed_spaces = 0; int removed_spaces = 0;
if(pair.first && pair.second){ if(pair.first && pair.second){
line = _Str(pair.first, pair.second-pair.first).lstrip(); line = Str(pair.first, pair.second-pair.first).lstrip();
removed_spaces = pair.second - pair.first - line.size(); removed_spaces = pair.second - pair.first - line.size();
if(line.empty()) line = "<?>"; if(line.empty()) line = "<?>";
} }
@ -66,22 +66,23 @@ struct SourceData {
~SourceData() { free((void*)source); } ~SourceData() { free((void*)source); }
}; };
class _Exception { namespace pkpy{
_Str type; class Exception {
_Str msg; Str type;
std::stack<_Str> stacktrace; Str msg;
std::stack<Str> stacktrace;
public: public:
_Exception(_Str type, _Str msg): type(type), msg(msg) {} Exception(Str type, Str msg): type(type), msg(msg) {}
bool match_type(const _Str& type) const { return this->type == type;} bool match_type(const Str& type) const { return this->type == type;}
bool is_re = true; bool is_re = true;
void st_push(_Str snapshot){ void st_push(Str snapshot){
if(stacktrace.size() >= 8) return; if(stacktrace.size() >= 8) return;
stacktrace.push(snapshot); stacktrace.push(snapshot);
} }
_Str summary() const { Str summary() const {
std::stack<_Str> st(stacktrace); std::stack<Str> st(stacktrace);
_StrStream ss; _StrStream ss;
if(is_re) ss << "Traceback (most recent call last):\n"; if(is_re) ss << "Traceback (most recent call last):\n";
while(!st.empty()) { ss << st.top() << '\n'; st.pop(); } while(!st.empty()) { ss << st.top() << '\n'; st.pop(); }
@ -89,3 +90,4 @@ public:
return ss.str(); return ss.str();
} }
}; };
}

View File

@ -4,10 +4,10 @@
class RangeIter : public BaseIter { class RangeIter : public BaseIter {
i64 current; i64 current;
_Range r; pkpy::Range r;
public: public:
RangeIter(VM* vm, PyVar _ref) : BaseIter(vm, _ref) { RangeIter(VM* vm, PyVar _ref) : BaseIter(vm, _ref) {
this->r = OBJ_GET(_Range, _ref); this->r = OBJ_GET(pkpy::Range, _ref);
this->current = r.start; this->current = r.start;
} }
@ -33,10 +33,10 @@ public:
class StringIter : public BaseIter { class StringIter : public BaseIter {
int index = 0; int index = 0;
_Str str; Str str;
public: public:
StringIter(VM* vm, PyVar _ref) : BaseIter(vm, _ref) { StringIter(VM* vm, PyVar _ref) : BaseIter(vm, _ref) {
str = OBJ_GET(_Str, _ref); str = OBJ_GET(Str, _ref);
} }
bool has_next(){ return index < str.u8_length(); } bool has_next(){ return index < str.u8_length(); }

View File

@ -7,28 +7,28 @@ struct Frame;
struct BaseRef; struct BaseRef;
class VM; class VM;
//typedef PyVar (*_CppFuncRaw)(VM*, const pkpy::Args&); typedef std::function<PyVar(VM*, const pkpy::Args&)> NativeFuncRaw;
typedef std::function<PyVar(VM*, const pkpy::Args&)> _CppFuncRaw; typedef pkpy::shared_ptr<CodeObject> CodeObject_;
typedef pkpy::shared_ptr<CodeObject> _Code;
struct _CppFunc { namespace pkpy{
_CppFuncRaw f; struct NativeFunc {
NativeFuncRaw f;
int argc; // DONOT include self int argc; // DONOT include self
bool method; bool method;
_CppFunc(_CppFuncRaw f, int argc, bool method) : f(f), argc(argc), method(method) {} NativeFunc(NativeFuncRaw f, int argc, bool method) : f(f), argc(argc), method(method) {}
inline PyVar operator()(VM* vm, const pkpy::Args& args) const; inline PyVar operator()(VM* vm, const pkpy::Args& args) const;
}; };
struct Function { struct Function {
_Str name; Str name;
_Code code; CodeObject_ code;
std::vector<_Str> args; std::vector<Str> args;
_Str starredArg; // empty if no *arg Str starredArg; // empty if no *arg
PyVarDict kwArgs; // empty if no k=v pkpy::NameDict kwArgs; // empty if no k=v
std::vector<_Str> kwArgsOrder; std::vector<Str> kwArgsOrder;
bool hasName(const _Str& val) const { bool hasName(const Str& val) const {
bool _0 = std::find(args.begin(), args.end(), val) != args.end(); bool _0 = std::find(args.begin(), args.end(), val) != args.end();
bool _1 = starredArg == val; bool _1 = starredArg == val;
bool _2 = kwArgs.find(val) != kwArgs.end(); bool _2 = kwArgs.find(val) != kwArgs.end();
@ -36,18 +36,18 @@ struct Function {
} }
}; };
struct _BoundMethod { struct BoundMethod {
PyVar obj; PyVar obj;
PyVar method; PyVar method;
}; };
struct _Range { struct Range {
i64 start = 0; i64 start = 0;
i64 stop = -1; i64 stop = -1;
i64 step = 1; i64 step = 1;
}; };
struct _Slice { struct Slice {
int start = 0; int start = 0;
int stop = 0x7fffffff; int stop = 0x7fffffff;
@ -59,6 +59,9 @@ struct _Slice {
} }
}; };
typedef shared_ptr<Function> Function_;
}
class BaseIter { class BaseIter {
protected: protected:
VM* vm; VM* vm;
@ -71,11 +74,9 @@ public:
virtual ~BaseIter() = default; virtual ~BaseIter() = default;
}; };
typedef pkpy::shared_ptr<Function> _Func;
struct PyObject { struct PyObject {
PyVar type; PyVar type;
PyVarDict attribs; pkpy::NameDict attribs;
void* _tid; void* _tid;
inline bool is_type(const PyVar& type) const noexcept{ return this->type == type; } inline bool is_type(const PyVar& type) const noexcept{ return this->type == type; }
@ -94,15 +95,15 @@ struct Py_ : PyObject {
}; };
#define OBJ_GET(T, obj) (((Py_<T>*)((obj).get()))->_value) #define OBJ_GET(T, obj) (((Py_<T>*)((obj).get()))->_value)
#define OBJ_NAME(obj) OBJ_GET(_Str, (obj)->attribs[__name__]) #define OBJ_NAME(obj) OBJ_GET(Str, (obj)->attribs[__name__])
#define OBJ_TP_NAME(obj) OBJ_GET(_Str, (obj)->type->attribs[__name__]) #define OBJ_TP_NAME(obj) OBJ_GET(Str, (obj)->type->attribs[__name__])
#define PY_CLASS(mod, name) \ #define PY_CLASS(mod, name) \
inline static PyVar _type(VM* vm) { return vm->_modules[#mod]->attribs[#name]; } \ inline static PyVar _type(VM* vm) { return vm->_modules[#mod]->attribs[#name]; } \
inline static const char* _mod() { return #mod; } \ inline static const char* _mod() { return #mod; } \
inline static const char* _name() { return #name; } inline static const char* _name() { return #name; }
#define PY_BUILTIN_CLASS(name) inline static PyVar _type(VM* vm) { return vm->_tp_##name; } #define PY_BUILTIN_CLASS(name) inline static PyVar _type(VM* vm) { return vm->tp_##name; }
static thread_local emhash8::HashMap<void*, std::vector<int*>> _obj_pool; static thread_local emhash8::HashMap<void*, std::vector<int*>> _obj_pool;

View File

@ -53,12 +53,12 @@ struct Token{
int line; //< Line number of the token (1 based). int line; //< Line number of the token (1 based).
PyVar value; //< Literal value of the token. PyVar value; //< Literal value of the token.
const _Str str() const { return _Str(start, length);} const Str str() const { return Str(start, length);}
const _Str info() const { const Str info() const {
_StrStream ss; _StrStream ss;
_Str raw = str(); Str raw = str();
if (raw == _Str("\n")) raw = "\\n"; if (raw == Str("\n")) raw = "\\n";
ss << line << ": " << TK_STR(type) << " '" << raw << "'"; ss << line << ": " << TK_STR(type) << " '" << raw << "'";
return ss.str(); return ss.str();
} }

View File

@ -8,11 +8,11 @@
#define CPP_LAMBDA(x) ([](VM* vm, const pkpy::Args& args) { return x; }) #define CPP_LAMBDA(x) ([](VM* vm, const pkpy::Args& args) { return x; })
#define CPP_NOT_IMPLEMENTED() ([](VM* vm, const pkpy::Args& args) { vm->NotImplementedError(); return vm->None; }) #define CPP_NOT_IMPLEMENTED() ([](VM* vm, const pkpy::Args& args) { vm->NotImplementedError(); return vm->None; })
_Code VM::compile(_Str source, _Str filename, CompileMode mode) { CodeObject_ VM::compile(Str source, Str filename, CompileMode mode) {
Compiler compiler(this, source.c_str(), filename, mode); Compiler compiler(this, source.c_str(), filename, mode);
try{ try{
return compiler.compile(); return compiler.compile();
}catch(_Exception& e){ }catch(pkpy::Exception& e){
_error(e); _error(e);
return nullptr; return nullptr;
} }
@ -20,7 +20,7 @@ _Code VM::compile(_Str source, _Str filename, CompileMode mode) {
#define BIND_NUM_ARITH_OPT(name, op) \ #define BIND_NUM_ARITH_OPT(name, op) \
_vm->_bind_methods<1>({"int","float"}, #name, [](VM* vm, const pkpy::Args& args){ \ _vm->_bind_methods<1>({"int","float"}, #name, [](VM* vm, const pkpy::Args& args){ \
if(args[0]->is_type(vm->_tp_int) && args[1]->is_type(vm->_tp_int)){ \ if(args[0]->is_type(vm->tp_int) && args[1]->is_type(vm->tp_int)){ \
return vm->PyInt(vm->PyInt_AS_C(args[0]) op vm->PyInt_AS_C(args[1])); \ return vm->PyInt(vm->PyInt_AS_C(args[0]) op vm->PyInt_AS_C(args[1])); \
}else{ \ }else{ \
return vm->PyFloat(vm->num_to_float(args[0]) op vm->num_to_float(args[1])); \ return vm->PyFloat(vm->num_to_float(args[0]) op vm->num_to_float(args[1])); \
@ -29,8 +29,8 @@ _Code VM::compile(_Str source, _Str filename, CompileMode mode) {
#define BIND_NUM_LOGICAL_OPT(name, op, is_eq) \ #define BIND_NUM_LOGICAL_OPT(name, op, is_eq) \
_vm->_bind_methods<1>({"int","float"}, #name, [](VM* vm, const pkpy::Args& args){ \ _vm->_bind_methods<1>({"int","float"}, #name, [](VM* vm, const pkpy::Args& args){ \
bool _0 = args[0]->is_type(vm->_tp_int) || args[0]->is_type(vm->_tp_float); \ bool _0 = args[0]->is_type(vm->tp_int) || args[0]->is_type(vm->tp_float); \
bool _1 = args[1]->is_type(vm->_tp_int) || args[1]->is_type(vm->_tp_float); \ bool _1 = args[1]->is_type(vm->tp_int) || args[1]->is_type(vm->tp_float); \
if(!_0 || !_1){ \ if(!_0 || !_1){ \
if constexpr(is_eq) return vm->PyBool(args[0].get() op args[1].get()); \ if constexpr(is_eq) return vm->PyBool(args[0].get() op args[1].get()); \
vm->TypeError("unsupported operand type(s) for " #op ); \ vm->TypeError("unsupported operand type(s) for " #op ); \
@ -62,16 +62,16 @@ void init_builtins(VM* _vm) {
_vm->bind_builtin_func<0>("super", [](VM* vm, const pkpy::Args& args) { _vm->bind_builtin_func<0>("super", [](VM* vm, const pkpy::Args& args) {
auto it = vm->top_frame()->f_locals().find(m_self); auto it = vm->top_frame()->f_locals().find(m_self);
if(it == vm->top_frame()->f_locals().end()) vm->TypeError("super() can only be called in a class method"); if(it == vm->top_frame()->f_locals().end()) vm->TypeError("super() can only be called in a class method");
return vm->new_object(vm->_tp_super, it->second); return vm->new_object(vm->tp_super, it->second);
}); });
_vm->bind_builtin_func<1>("eval", [](VM* vm, const pkpy::Args& args) { _vm->bind_builtin_func<1>("eval", [](VM* vm, const pkpy::Args& args) {
_Code code = vm->compile(vm->PyStr_AS_C(args[0]), "<eval>", EVAL_MODE); CodeObject_ code = vm->compile(vm->PyStr_AS_C(args[0]), "<eval>", EVAL_MODE);
return vm->_exec(code, vm->top_frame()->_module, vm->top_frame()->_locals); return vm->_exec(code, vm->top_frame()->_module, vm->top_frame()->_locals);
}); });
_vm->bind_builtin_func<1>("exec", [](VM* vm, const pkpy::Args& args) { _vm->bind_builtin_func<1>("exec", [](VM* vm, const pkpy::Args& args) {
_Code code = vm->compile(vm->PyStr_AS_C(args[0]), "<exec>", EXEC_MODE); CodeObject_ code = vm->compile(vm->PyStr_AS_C(args[0]), "<exec>", EXEC_MODE);
vm->_exec(code, vm->top_frame()->_module, vm->top_frame()->_locals); vm->_exec(code, vm->top_frame()->_module, vm->top_frame()->_locals);
return vm->None; return vm->None;
}); });
@ -94,7 +94,7 @@ void init_builtins(VM* _vm) {
}); });
_vm->bind_builtin_func<1>("ord", [](VM* vm, const pkpy::Args& args) { _vm->bind_builtin_func<1>("ord", [](VM* vm, const pkpy::Args& args) {
_Str s = vm->PyStr_AS_C(args[0]); Str s = vm->PyStr_AS_C(args[0]);
if (s.size() != 1) vm->TypeError("ord() expected an ASCII character"); if (s.size() != 1) vm->TypeError("ord() expected an ASCII character");
return vm->PyInt((i64)(s.c_str()[0])); return vm->PyInt((i64)(s.c_str()[0]));
}); });
@ -110,7 +110,7 @@ void init_builtins(VM* _vm) {
}); });
_vm->bind_builtin_func<2>("getattr", [](VM* vm, const pkpy::Args& args) { _vm->bind_builtin_func<2>("getattr", [](VM* vm, const pkpy::Args& args) {
_Str name = vm->PyStr_AS_C(args[1]); Str name = vm->PyStr_AS_C(args[1]);
return vm->getattr(args[0], name); return vm->getattr(args[0], name);
}); });
@ -121,13 +121,13 @@ void init_builtins(VM* _vm) {
}); });
_vm->bind_builtin_func<1>("dir", [](VM* vm, const pkpy::Args& args) { _vm->bind_builtin_func<1>("dir", [](VM* vm, const pkpy::Args& args) {
std::vector<_Str> names; std::vector<Str> names;
for (auto& [k, _] : args[0]->attribs) names.push_back(k); for (auto& [k, _] : args[0]->attribs) names.push_back(k);
for (auto& [k, _] : args[0]->type->attribs) { for (auto& [k, _] : args[0]->type->attribs) {
if (k.find("__") == 0) continue; if (k.find("__") == 0) continue;
if (std::find(names.begin(), names.end(), k) == names.end()) names.push_back(k); if (std::find(names.begin(), names.end(), k) == names.end()) names.push_back(k);
} }
PyVarList ret; pkpy::List ret;
for (const auto& name : names) ret.push_back(vm->PyStr(name)); for (const auto& name : names) ret.push_back(vm->PyStr(name));
std::sort(ret.begin(), ret.end(), [vm](const PyVar& a, const PyVar& b) { std::sort(ret.begin(), ret.end(), [vm](const PyVar& a, const PyVar& b) {
return vm->PyStr_AS_C(a) < vm->PyStr_AS_C(b); return vm->PyStr_AS_C(a) < vm->PyStr_AS_C(b);
@ -139,7 +139,7 @@ void init_builtins(VM* _vm) {
PyVar _self = args[0]; PyVar _self = args[0];
std::stringstream ss; std::stringstream ss;
ss << std::hex << (uintptr_t)_self.get(); ss << std::hex << (uintptr_t)_self.get();
_Str s = "<" + OBJ_TP_NAME(_self) + " object at 0x" + ss.str() + ">"; Str s = "<" + OBJ_TP_NAME(_self) + " object at 0x" + ss.str() + ">";
return vm->PyStr(s); return vm->PyStr(s);
}); });
@ -149,7 +149,7 @@ void init_builtins(VM* _vm) {
_vm->bind_static_method<1>("type", "__new__", CPP_LAMBDA(args[0]->type)); _vm->bind_static_method<1>("type", "__new__", CPP_LAMBDA(args[0]->type));
_vm->bind_static_method<-1>("range", "__new__", [](VM* vm, const pkpy::Args& args) { _vm->bind_static_method<-1>("range", "__new__", [](VM* vm, const pkpy::Args& args) {
_Range r; pkpy::Range r;
switch (args.size()) { switch (args.size()) {
case 1: r.stop = vm->PyInt_AS_C(args[0]); break; case 1: r.stop = vm->PyInt_AS_C(args[0]); break;
case 2: r.start = vm->PyInt_AS_C(args[0]); r.stop = vm->PyInt_AS_C(args[1]); break; case 2: r.start = vm->PyInt_AS_C(args[0]); r.stop = vm->PyInt_AS_C(args[1]); break;
@ -173,7 +173,7 @@ void init_builtins(VM* _vm) {
}); });
_vm->_bind_methods<1>({"int", "float"}, "__pow__", [](VM* vm, const pkpy::Args& args) { _vm->_bind_methods<1>({"int", "float"}, "__pow__", [](VM* vm, const pkpy::Args& args) {
if(args[0]->is_type(vm->_tp_int) && args[1]->is_type(vm->_tp_int)){ if(args[0]->is_type(vm->tp_int) && args[1]->is_type(vm->tp_int)){
return vm->PyInt((i64)round(pow(vm->PyInt_AS_C(args[0]), vm->PyInt_AS_C(args[1])))); return vm->PyInt((i64)round(pow(vm->PyInt_AS_C(args[0]), vm->PyInt_AS_C(args[1]))));
}else{ }else{
return vm->PyFloat((f64)pow(vm->num_to_float(args[0]), vm->num_to_float(args[1]))); return vm->PyFloat((f64)pow(vm->num_to_float(args[0]), vm->num_to_float(args[1])));
@ -182,11 +182,11 @@ void init_builtins(VM* _vm) {
/************ PyInt ************/ /************ PyInt ************/
_vm->bind_static_method<1>("int", "__new__", [](VM* vm, const pkpy::Args& args) { _vm->bind_static_method<1>("int", "__new__", [](VM* vm, const pkpy::Args& args) {
if (args[0]->is_type(vm->_tp_int)) return args[0]; if (args[0]->is_type(vm->tp_int)) return args[0];
if (args[0]->is_type(vm->_tp_float)) return vm->PyInt((i64)vm->PyFloat_AS_C(args[0])); if (args[0]->is_type(vm->tp_float)) return vm->PyInt((i64)vm->PyFloat_AS_C(args[0]));
if (args[0]->is_type(vm->_tp_bool)) return vm->PyInt(vm->PyBool_AS_C(args[0]) ? 1 : 0); if (args[0]->is_type(vm->tp_bool)) return vm->PyInt(vm->PyBool_AS_C(args[0]) ? 1 : 0);
if (args[0]->is_type(vm->_tp_str)) { if (args[0]->is_type(vm->tp_str)) {
const _Str& s = vm->PyStr_AS_C(args[0]); const Str& s = vm->PyStr_AS_C(args[0]);
try{ try{
size_t parsed = 0; size_t parsed = 0;
i64 val = std::stoll(s, &parsed, 10); i64 val = std::stoll(s, &parsed, 10);
@ -235,11 +235,11 @@ void init_builtins(VM* _vm) {
/************ PyFloat ************/ /************ PyFloat ************/
_vm->bind_static_method<1>("float", "__new__", [](VM* vm, const pkpy::Args& args) { _vm->bind_static_method<1>("float", "__new__", [](VM* vm, const pkpy::Args& args) {
if (args[0]->is_type(vm->_tp_int)) return vm->PyFloat((f64)vm->PyInt_AS_C(args[0])); if (args[0]->is_type(vm->tp_int)) return vm->PyFloat((f64)vm->PyInt_AS_C(args[0]));
if (args[0]->is_type(vm->_tp_float)) return args[0]; if (args[0]->is_type(vm->tp_float)) return args[0];
if (args[0]->is_type(vm->_tp_bool)) return vm->PyFloat(vm->PyBool_AS_C(args[0]) ? 1.0 : 0.0); if (args[0]->is_type(vm->tp_bool)) return vm->PyFloat(vm->PyBool_AS_C(args[0]) ? 1.0 : 0.0);
if (args[0]->is_type(vm->_tp_str)) { if (args[0]->is_type(vm->tp_str)) {
const _Str& s = vm->PyStr_AS_C(args[0]); const Str& s = vm->PyStr_AS_C(args[0]);
if(s == "inf") return vm->PyFloat(INFINITY); if(s == "inf") return vm->PyFloat(INFINITY);
if(s == "-inf") return vm->PyFloat(-INFINITY); if(s == "-inf") return vm->PyFloat(-INFINITY);
try{ try{
@ -273,20 +273,20 @@ void init_builtins(VM* _vm) {
_vm->bind_static_method<1>("str", "__new__", CPP_LAMBDA(vm->asStr(args[0]))); _vm->bind_static_method<1>("str", "__new__", CPP_LAMBDA(vm->asStr(args[0])));
_vm->bind_method<1>("str", "__add__", [](VM* vm, const pkpy::Args& args) { _vm->bind_method<1>("str", "__add__", [](VM* vm, const pkpy::Args& args) {
const _Str& lhs = vm->PyStr_AS_C(args[0]); const Str& lhs = vm->PyStr_AS_C(args[0]);
const _Str& rhs = vm->PyStr_AS_C(args[1]); const Str& rhs = vm->PyStr_AS_C(args[1]);
return vm->PyStr(lhs + rhs); return vm->PyStr(lhs + rhs);
}); });
_vm->bind_method<0>("str", "__len__", [](VM* vm, const pkpy::Args& args) { _vm->bind_method<0>("str", "__len__", [](VM* vm, const pkpy::Args& args) {
const _Str& _self = vm->PyStr_AS_C(args[0]); const Str& _self = vm->PyStr_AS_C(args[0]);
return vm->PyInt(_self.u8_length()); return vm->PyInt(_self.u8_length());
}); });
_vm->bind_method<1>("str", "__contains__", [](VM* vm, const pkpy::Args& args) { _vm->bind_method<1>("str", "__contains__", [](VM* vm, const pkpy::Args& args) {
const _Str& _self = vm->PyStr_AS_C(args[0]); const Str& _self = vm->PyStr_AS_C(args[0]);
const _Str& _other = vm->PyStr_AS_C(args[1]); const Str& _other = vm->PyStr_AS_C(args[1]);
return vm->PyBool(_self.find(_other) != _Str::npos); return vm->PyBool(_self.find(_other) != Str::npos);
}); });
_vm->bind_method<0>("str", "__str__", CPP_LAMBDA(args[0])); _vm->bind_method<0>("str", "__str__", CPP_LAMBDA(args[0]));
@ -296,32 +296,32 @@ void init_builtins(VM* _vm) {
)); ));
_vm->bind_method<0>("str", "__repr__", [](VM* vm, const pkpy::Args& args) { _vm->bind_method<0>("str", "__repr__", [](VM* vm, const pkpy::Args& args) {
const _Str& _self = vm->PyStr_AS_C(args[0]); const Str& _self = vm->PyStr_AS_C(args[0]);
return vm->PyStr(_self.escape(true)); return vm->PyStr(_self.escape(true));
}); });
_vm->bind_method<0>("str", "__json__", [](VM* vm, const pkpy::Args& args) { _vm->bind_method<0>("str", "__json__", [](VM* vm, const pkpy::Args& args) {
const _Str& _self = vm->PyStr_AS_C(args[0]); const Str& _self = vm->PyStr_AS_C(args[0]);
return vm->PyStr(_self.escape(false)); return vm->PyStr(_self.escape(false));
}); });
_vm->bind_method<1>("str", "__eq__", [](VM* vm, const pkpy::Args& args) { _vm->bind_method<1>("str", "__eq__", [](VM* vm, const pkpy::Args& args) {
if(args[0]->is_type(vm->_tp_str) && args[1]->is_type(vm->_tp_str)) if(args[0]->is_type(vm->tp_str) && args[1]->is_type(vm->tp_str))
return vm->PyBool(vm->PyStr_AS_C(args[0]) == vm->PyStr_AS_C(args[1])); return vm->PyBool(vm->PyStr_AS_C(args[0]) == vm->PyStr_AS_C(args[1]));
return vm->PyBool(args[0] == args[1]); return vm->PyBool(args[0] == args[1]);
}); });
_vm->bind_method<1>("str", "__ne__", [](VM* vm, const pkpy::Args& args) { _vm->bind_method<1>("str", "__ne__", [](VM* vm, const pkpy::Args& args) {
if(args[0]->is_type(vm->_tp_str) && args[1]->is_type(vm->_tp_str)) if(args[0]->is_type(vm->tp_str) && args[1]->is_type(vm->tp_str))
return vm->PyBool(vm->PyStr_AS_C(args[0]) != vm->PyStr_AS_C(args[1])); return vm->PyBool(vm->PyStr_AS_C(args[0]) != vm->PyStr_AS_C(args[1]));
return vm->PyBool(args[0] != args[1]); return vm->PyBool(args[0] != args[1]);
}); });
_vm->bind_method<1>("str", "__getitem__", [](VM* vm, const pkpy::Args& args) { _vm->bind_method<1>("str", "__getitem__", [](VM* vm, const pkpy::Args& args) {
const _Str& _self (vm->PyStr_AS_C(args[0])); const Str& _self (vm->PyStr_AS_C(args[0]));
if(args[1]->is_type(vm->_tp_slice)){ if(args[1]->is_type(vm->tp_slice)){
_Slice s = vm->PySlice_AS_C(args[1]); pkpy::Slice s = vm->PySlice_AS_C(args[1]);
s.normalize(_self.u8_length()); s.normalize(_self.u8_length());
return vm->PyStr(_self.u8_substr(s.start, s.stop)); return vm->PyStr(_self.u8_substr(s.start, s.stop));
} }
@ -332,22 +332,22 @@ void init_builtins(VM* _vm) {
}); });
_vm->bind_method<1>("str", "__gt__", [](VM* vm, const pkpy::Args& args) { _vm->bind_method<1>("str", "__gt__", [](VM* vm, const pkpy::Args& args) {
const _Str& _self (vm->PyStr_AS_C(args[0])); const Str& _self (vm->PyStr_AS_C(args[0]));
const _Str& _obj (vm->PyStr_AS_C(args[1])); const Str& _obj (vm->PyStr_AS_C(args[1]));
return vm->PyBool(_self > _obj); return vm->PyBool(_self > _obj);
}); });
_vm->bind_method<1>("str", "__lt__", [](VM* vm, const pkpy::Args& args) { _vm->bind_method<1>("str", "__lt__", [](VM* vm, const pkpy::Args& args) {
const _Str& _self (vm->PyStr_AS_C(args[0])); const Str& _self (vm->PyStr_AS_C(args[0]));
const _Str& _obj (vm->PyStr_AS_C(args[1])); const Str& _obj (vm->PyStr_AS_C(args[1]));
return vm->PyBool(_self < _obj); return vm->PyBool(_self < _obj);
}); });
_vm->bind_method<2>("str", "replace", [](VM* vm, const pkpy::Args& args) { _vm->bind_method<2>("str", "replace", [](VM* vm, const pkpy::Args& args) {
const _Str& _self = vm->PyStr_AS_C(args[0]); const Str& _self = vm->PyStr_AS_C(args[0]);
const _Str& _old = vm->PyStr_AS_C(args[1]); const Str& _old = vm->PyStr_AS_C(args[1]);
const _Str& _new = vm->PyStr_AS_C(args[2]); const Str& _new = vm->PyStr_AS_C(args[2]);
_Str _copy = _self; Str _copy = _self;
// replace all occurences of _old with _new in _copy // replace all occurences of _old with _new in _copy
size_t pos = 0; size_t pos = 0;
while ((pos = _copy.find(_old, pos)) != std::string::npos) { while ((pos = _copy.find(_old, pos)) != std::string::npos) {
@ -358,28 +358,28 @@ void init_builtins(VM* _vm) {
}); });
_vm->bind_method<1>("str", "startswith", [](VM* vm, const pkpy::Args& args) { _vm->bind_method<1>("str", "startswith", [](VM* vm, const pkpy::Args& args) {
const _Str& _self = vm->PyStr_AS_C(args[0]); const Str& _self = vm->PyStr_AS_C(args[0]);
const _Str& _prefix = vm->PyStr_AS_C(args[1]); const Str& _prefix = vm->PyStr_AS_C(args[1]);
return vm->PyBool(_self.find(_prefix) == 0); return vm->PyBool(_self.find(_prefix) == 0);
}); });
_vm->bind_method<1>("str", "endswith", [](VM* vm, const pkpy::Args& args) { _vm->bind_method<1>("str", "endswith", [](VM* vm, const pkpy::Args& args) {
const _Str& _self = vm->PyStr_AS_C(args[0]); const Str& _self = vm->PyStr_AS_C(args[0]);
const _Str& _suffix = vm->PyStr_AS_C(args[1]); const Str& _suffix = vm->PyStr_AS_C(args[1]);
return vm->PyBool(_self.rfind(_suffix) == _self.length() - _suffix.length()); return vm->PyBool(_self.rfind(_suffix) == _self.length() - _suffix.length());
}); });
_vm->bind_method<1>("str", "join", [](VM* vm, const pkpy::Args& args) { _vm->bind_method<1>("str", "join", [](VM* vm, const pkpy::Args& args) {
const _Str& self = vm->PyStr_AS_C(args[0]); const Str& self = vm->PyStr_AS_C(args[0]);
_StrStream ss; _StrStream ss;
if(args[1]->is_type(vm->_tp_list)){ if(args[1]->is_type(vm->tp_list)){
const PyVarList& a = vm->PyList_AS_C(args[1]); const pkpy::List& a = vm->PyList_AS_C(args[1]);
for(int i = 0; i < a.size(); i++){ for(int i = 0; i < a.size(); i++){
if(i > 0) ss << self; if(i > 0) ss << self;
ss << vm->PyStr_AS_C(vm->asStr(a[i])); ss << vm->PyStr_AS_C(vm->asStr(a[i]));
} }
}else if(args[1]->is_type(vm->_tp_tuple)){ }else if(args[1]->is_type(vm->tp_tuple)){
const _Tuple& a = vm->PyTuple_AS_C(args[1]); const pkpy::Tuple& a = vm->PyTuple_AS_C(args[1]);
for(int i = 0; i < a.size(); i++){ for(int i = 0; i < a.size(); i++){
if(i > 0) ss << self; if(i > 0) ss << self;
ss << vm->PyStr_AS_C(vm->asStr(a[i])); ss << vm->PyStr_AS_C(vm->asStr(a[i]));
@ -392,13 +392,13 @@ void init_builtins(VM* _vm) {
/************ PyList ************/ /************ PyList ************/
_vm->bind_method<1>("list", "append", [](VM* vm, const pkpy::Args& args) { _vm->bind_method<1>("list", "append", [](VM* vm, const pkpy::Args& args) {
PyVarList& _self = vm->PyList_AS_C(args[0]); pkpy::List& _self = vm->PyList_AS_C(args[0]);
_self.push_back(args[1]); _self.push_back(args[1]);
return vm->None; return vm->None;
}); });
_vm->bind_method<2>("list", "insert", [](VM* vm, const pkpy::Args& args) { _vm->bind_method<2>("list", "insert", [](VM* vm, const pkpy::Args& args) {
PyVarList& _self = vm->PyList_AS_C(args[0]); pkpy::List& _self = vm->PyList_AS_C(args[0]);
int _index = (int)vm->PyInt_AS_C(args[1]); int _index = (int)vm->PyInt_AS_C(args[1]);
if(_index < 0) _index += _self.size(); if(_index < 0) _index += _self.size();
if(_index < 0) _index = 0; if(_index < 0) _index = 0;
@ -417,29 +417,29 @@ void init_builtins(VM* _vm) {
}); });
_vm->bind_method<1>("list", "__add__", [](VM* vm, const pkpy::Args& args) { _vm->bind_method<1>("list", "__add__", [](VM* vm, const pkpy::Args& args) {
const PyVarList& _self = vm->PyList_AS_C(args[0]); const pkpy::List& _self = vm->PyList_AS_C(args[0]);
const PyVarList& _obj = vm->PyList_AS_C(args[1]); const pkpy::List& _obj = vm->PyList_AS_C(args[1]);
PyVarList _new_list = _self; pkpy::List _new_list = _self;
_new_list.insert(_new_list.end(), _obj.begin(), _obj.end()); _new_list.insert(_new_list.end(), _obj.begin(), _obj.end());
return vm->PyList(_new_list); return vm->PyList(_new_list);
}); });
_vm->bind_method<0>("list", "__len__", [](VM* vm, const pkpy::Args& args) { _vm->bind_method<0>("list", "__len__", [](VM* vm, const pkpy::Args& args) {
const PyVarList& _self = vm->PyList_AS_C(args[0]); const pkpy::List& _self = vm->PyList_AS_C(args[0]);
return vm->PyInt(_self.size()); return vm->PyInt(_self.size());
}); });
_vm->bind_method<0>("list", "__iter__", [](VM* vm, const pkpy::Args& args) { _vm->bind_method<0>("list", "__iter__", [](VM* vm, const pkpy::Args& args) {
return vm->PyIter(pkpy::make_shared<BaseIter, ArrayIter<PyVarList>>(vm, args[0])); return vm->PyIter(pkpy::make_shared<BaseIter, ArrayIter<pkpy::List>>(vm, args[0]));
}); });
_vm->bind_method<1>("list", "__getitem__", [](VM* vm, const pkpy::Args& args) { _vm->bind_method<1>("list", "__getitem__", [](VM* vm, const pkpy::Args& args) {
const PyVarList& self = vm->PyList_AS_C(args[0]); const pkpy::List& self = vm->PyList_AS_C(args[0]);
if(args[1]->is_type(vm->_tp_slice)){ if(args[1]->is_type(vm->tp_slice)){
_Slice s = vm->PySlice_AS_C(args[1]); pkpy::Slice s = vm->PySlice_AS_C(args[1]);
s.normalize(self.size()); s.normalize(self.size());
PyVarList new_list; pkpy::List new_list;
for(size_t i = s.start; i < s.stop; i++) new_list.push_back(self[i]); for(size_t i = s.start; i < s.stop; i++) new_list.push_back(self[i]);
return vm->PyList(std::move(new_list)); return vm->PyList(std::move(new_list));
} }
@ -450,7 +450,7 @@ void init_builtins(VM* _vm) {
}); });
_vm->bind_method<2>("list", "__setitem__", [](VM* vm, const pkpy::Args& args) { _vm->bind_method<2>("list", "__setitem__", [](VM* vm, const pkpy::Args& args) {
PyVarList& _self = vm->PyList_AS_C(args[0]); pkpy::List& _self = vm->PyList_AS_C(args[0]);
int _index = (int)vm->PyInt_AS_C(args[1]); int _index = (int)vm->PyInt_AS_C(args[1]);
_index = vm->normalized_index(_index, _self.size()); _index = vm->normalized_index(_index, _self.size());
_self[_index] = args[2]; _self[_index] = args[2];
@ -458,7 +458,7 @@ void init_builtins(VM* _vm) {
}); });
_vm->bind_method<1>("list", "__delitem__", [](VM* vm, const pkpy::Args& args) { _vm->bind_method<1>("list", "__delitem__", [](VM* vm, const pkpy::Args& args) {
PyVarList& _self = vm->PyList_AS_C(args[0]); pkpy::List& _self = vm->PyList_AS_C(args[0]);
int _index = (int)vm->PyInt_AS_C(args[1]); int _index = (int)vm->PyInt_AS_C(args[1]);
_index = vm->normalized_index(_index, _self.size()); _index = vm->normalized_index(_index, _self.size());
_self.erase(_self.begin() + _index); _self.erase(_self.begin() + _index);
@ -467,7 +467,7 @@ void init_builtins(VM* _vm) {
/************ PyTuple ************/ /************ PyTuple ************/
_vm->bind_static_method<1>("tuple", "__new__", [](VM* vm, const pkpy::Args& args) { _vm->bind_static_method<1>("tuple", "__new__", [](VM* vm, const pkpy::Args& args) {
PyVarList _list = vm->PyList_AS_C(vm->call(vm->builtins->attribs["list"], args)); pkpy::List _list = vm->PyList_AS_C(vm->call(vm->builtins->attribs["list"], args));
return vm->PyTuple(std::move(_list)); return vm->PyTuple(std::move(_list));
}); });
@ -476,12 +476,12 @@ void init_builtins(VM* _vm) {
}); });
_vm->bind_method<1>("tuple", "__getitem__", [](VM* vm, const pkpy::Args& args) { _vm->bind_method<1>("tuple", "__getitem__", [](VM* vm, const pkpy::Args& args) {
const _Tuple& self = vm->PyTuple_AS_C(args[0]); const pkpy::Tuple& self = vm->PyTuple_AS_C(args[0]);
if(args[1]->is_type(vm->_tp_slice)){ if(args[1]->is_type(vm->tp_slice)){
_Slice s = vm->PySlice_AS_C(args[1]); pkpy::Slice s = vm->PySlice_AS_C(args[1]);
s.normalize(self.size()); s.normalize(self.size());
PyVarList new_list; pkpy::List new_list;
for(size_t i = s.start; i < s.stop; i++) new_list.push_back(self[i]); for(size_t i = s.start; i < s.stop; i++) new_list.push_back(self[i]);
return vm->PyTuple(std::move(new_list)); return vm->PyTuple(std::move(new_list));
} }
@ -492,7 +492,7 @@ void init_builtins(VM* _vm) {
}); });
_vm->bind_method<0>("tuple", "__len__", [](VM* vm, const pkpy::Args& args) { _vm->bind_method<0>("tuple", "__len__", [](VM* vm, const pkpy::Args& args) {
const _Tuple& self = vm->PyTuple_AS_C(args[0]); const pkpy::Tuple& self = vm->PyTuple_AS_C(args[0]);
return vm->PyInt(self.size()); return vm->PyInt(self.size());
}); });
@ -556,8 +556,8 @@ void add_module_sys(VM* vm){
void add_module_json(VM* vm){ void add_module_json(VM* vm){
PyVar mod = vm->new_module("json"); PyVar mod = vm->new_module("json");
vm->bind_func<1>(mod, "loads", [](VM* vm, const pkpy::Args& args) { vm->bind_func<1>(mod, "loads", [](VM* vm, const pkpy::Args& args) {
const _Str& expr = vm->PyStr_AS_C(args[0]); const Str& expr = vm->PyStr_AS_C(args[0]);
_Code code = vm->compile(expr, "<json>", JSON_MODE); CodeObject_ code = vm->compile(expr, "<json>", JSON_MODE);
return vm->_exec(code, vm->top_frame()->_module, vm->top_frame()->_locals); return vm->_exec(code, vm->top_frame()->_module, vm->top_frame()->_locals);
}); });
@ -582,7 +582,7 @@ void add_module_math(VM* vm){
void add_module_dis(VM* vm){ void add_module_dis(VM* vm){
PyVar mod = vm->new_module("dis"); PyVar mod = vm->new_module("dis");
vm->bind_func<1>(mod, "dis", [](VM* vm, const pkpy::Args& args) { vm->bind_func<1>(mod, "dis", [](VM* vm, const pkpy::Args& args) {
_Code code = vm->PyFunction_AS_C(args[0])->code; CodeObject_ code = vm->PyFunction_AS_C(args[0])->code;
(*vm->_stdout) << vm->disassemble(code); (*vm->_stdout) << vm->disassemble(code);
return vm->None; return vm->None;
}); });
@ -615,7 +615,7 @@ struct ReMatch {
} }
}; };
PyVar _regex_search(const _Str& pattern, const _Str& string, bool fromStart, VM* vm){ PyVar _regex_search(const Str& pattern, const Str& string, bool fromStart, VM* vm){
std::regex re(pattern); std::regex re(pattern);
std::smatch m; std::smatch m;
if(std::regex_search(string, m, re)){ if(std::regex_search(string, m, re)){
@ -632,32 +632,32 @@ void add_module_re(VM* vm){
vm->register_class<ReMatch>(mod); vm->register_class<ReMatch>(mod);
vm->bind_func<2>(mod, "match", [](VM* vm, const pkpy::Args& args) { vm->bind_func<2>(mod, "match", [](VM* vm, const pkpy::Args& args) {
const _Str& pattern = vm->PyStr_AS_C(args[0]); const Str& pattern = vm->PyStr_AS_C(args[0]);
const _Str& string = vm->PyStr_AS_C(args[1]); const Str& string = vm->PyStr_AS_C(args[1]);
return _regex_search(pattern, string, true, vm); return _regex_search(pattern, string, true, vm);
}); });
vm->bind_func<2>(mod, "search", [](VM* vm, const pkpy::Args& args) { vm->bind_func<2>(mod, "search", [](VM* vm, const pkpy::Args& args) {
const _Str& pattern = vm->PyStr_AS_C(args[0]); const Str& pattern = vm->PyStr_AS_C(args[0]);
const _Str& string = vm->PyStr_AS_C(args[1]); const Str& string = vm->PyStr_AS_C(args[1]);
return _regex_search(pattern, string, false, vm); return _regex_search(pattern, string, false, vm);
}); });
vm->bind_func<3>(mod, "sub", [](VM* vm, const pkpy::Args& args) { vm->bind_func<3>(mod, "sub", [](VM* vm, const pkpy::Args& args) {
const _Str& pattern = vm->PyStr_AS_C(args[0]); const Str& pattern = vm->PyStr_AS_C(args[0]);
const _Str& repl = vm->PyStr_AS_C(args[1]); const Str& repl = vm->PyStr_AS_C(args[1]);
const _Str& string = vm->PyStr_AS_C(args[2]); const Str& string = vm->PyStr_AS_C(args[2]);
std::regex re(pattern); std::regex re(pattern);
return vm->PyStr(std::regex_replace(string, re, repl)); return vm->PyStr(std::regex_replace(string, re, repl));
}); });
vm->bind_func<2>(mod, "split", [](VM* vm, const pkpy::Args& args) { vm->bind_func<2>(mod, "split", [](VM* vm, const pkpy::Args& args) {
const _Str& pattern = vm->PyStr_AS_C(args[0]); const Str& pattern = vm->PyStr_AS_C(args[0]);
const _Str& string = vm->PyStr_AS_C(args[1]); const Str& string = vm->PyStr_AS_C(args[1]);
std::regex re(pattern); std::regex re(pattern);
std::sregex_token_iterator it(string.begin(), string.end(), re, -1); std::sregex_token_iterator it(string.begin(), string.end(), re, -1);
std::sregex_token_iterator end; std::sregex_token_iterator end;
PyVarList vec; pkpy::List vec;
for(; it != end; ++it){ for(; it != end; ++it){
vec.push_back(vm->PyStr(it->str())); vec.push_back(vm->PyStr(it->str()));
} }
@ -725,7 +725,7 @@ extern "C" {
auto it = vm->_main->attribs.find(name); auto it = vm->_main->attribs.find(name);
if(it == vm->_main->attribs.end()) return nullptr; if(it == vm->_main->attribs.end()) return nullptr;
try{ try{
_Str _repr = vm->PyStr_AS_C(vm->asRepr(it->second)); Str _repr = vm->PyStr_AS_C(vm->asRepr(it->second));
return strdup(_repr.c_str()); return strdup(_repr.c_str());
}catch(...){ }catch(...){
return nullptr; return nullptr;
@ -741,7 +741,7 @@ extern "C" {
PyVarOrNull ret = vm->exec(source, "<eval>", EVAL_MODE); PyVarOrNull ret = vm->exec(source, "<eval>", EVAL_MODE);
if(ret == nullptr) return nullptr; if(ret == nullptr) return nullptr;
try{ try{
_Str _repr = vm->PyStr_AS_C(vm->asRepr(ret)); Str _repr = vm->PyStr_AS_C(vm->asRepr(ret));
return strdup(_repr.c_str()); return strdup(_repr.c_str());
}catch(...){ }catch(...){
return nullptr; return nullptr;
@ -778,8 +778,8 @@ extern "C" {
add_module_re(vm); add_module_re(vm);
add_module_dis(vm); add_module_dis(vm);
_Code code = vm->compile(kBuiltinsCode, "<builtins>", EXEC_MODE); CodeObject_ code = vm->compile(kBuiltinsCode, "<builtins>", EXEC_MODE);
vm->_exec(code, vm->builtins, pkpy::make_shared<PyVarDict>()); vm->_exec(code, vm->builtins, pkpy::make_shared<pkpy::NameDict>());
pkpy_vm_add_module(vm, "random", kRandomCode); pkpy_vm_add_module(vm, "random", kRandomCode);
return vm; return vm;
@ -795,8 +795,8 @@ extern "C" {
if(vm->use_stdio) return nullptr; if(vm->use_stdio) return nullptr;
_StrStream* s_out = (_StrStream*)(vm->_stdout); _StrStream* s_out = (_StrStream*)(vm->_stdout);
_StrStream* s_err = (_StrStream*)(vm->_stderr); _StrStream* s_err = (_StrStream*)(vm->_stderr);
_Str _stdout = s_out->str(); Str _stdout = s_out->str();
_Str _stderr = s_err->str(); Str _stderr = s_err->str();
_StrStream ss; _StrStream ss;
ss << '{' << "\"stdout\": " << _stdout.escape(false); ss << '{' << "\"stdout\": " << _stdout.escape(false);
ss << ", " << "\"stderr\": " << _stderr.escape(false) << '}'; ss << ", " << "\"stderr\": " << _stderr.escape(false) << '}';

View File

@ -17,10 +17,10 @@ enum NameScope {
}; };
struct NameRef : BaseRef { struct NameRef : BaseRef {
std::pair<_Str, NameScope>* _pair; std::pair<Str, NameScope>* _pair;
inline const _Str& name() const { return _pair->first; } inline const Str& name() const { return _pair->first; }
inline NameScope scope() const { return _pair->second; } inline NameScope scope() const { return _pair->second; }
NameRef(std::pair<_Str, NameScope>& pair) : _pair(&pair) {} NameRef(std::pair<Str, NameScope>& pair) : _pair(&pair) {}
PyVar get(VM* vm, Frame* frame) const; PyVar get(VM* vm, Frame* frame) const;
void set(VM* vm, Frame* frame, PyVar val) const; void set(VM* vm, Frame* frame, PyVar val) const;
@ -48,8 +48,8 @@ struct IndexRef : BaseRef {
}; };
struct TupleRef : BaseRef { struct TupleRef : BaseRef {
_Tuple objs; pkpy::Tuple objs;
TupleRef(_Tuple&& objs) : objs(std::move(objs)) {} TupleRef(pkpy::Tuple&& objs) : objs(std::move(objs)) {}
PyVar get(VM* vm, Frame* frame) const; PyVar get(VM* vm, Frame* frame) const;
void set(VM* vm, Frame* frame, PyVar val) const; void set(VM* vm, Frame* frame, PyVar val) const;

View File

@ -9,7 +9,8 @@ typedef pkpy::shared_ptr<PyObject> PyVar;
typedef PyVar PyVarOrNull; typedef PyVar PyVarOrNull;
typedef PyVar PyVarRef; typedef PyVar PyVarRef;
class PyVarList: public std::vector<PyVar> { namespace pkpy{
class List: public std::vector<PyVar> {
PyVar& at(size_t) = delete; PyVar& at(size_t) = delete;
inline void _check_index(size_t i) const { inline void _check_index(size_t i) const {
@ -32,7 +33,9 @@ public:
using std::vector<PyVar>::vector; using std::vector<PyVar>::vector;
}; };
typedef emhash8::HashMap<_Str, PyVar> PyVarDict; typedef emhash8::HashMap<Str, PyVar> NameDict;
}
namespace pkpy { namespace pkpy {
const int kMaxPoolSize = 10; const int kMaxPoolSize = 10;
@ -89,7 +92,7 @@ namespace pkpy {
other._size = 0; other._size = 0;
} }
Args(PyVarList&& other) noexcept { Args(pkpy::List&& other) noexcept {
_alloc(other.size()); _alloc(other.size());
for(int i=0; i<_size; i++) _args[i] = std::move(other[i]); for(int i=0; i<_size; i++) _args[i] = std::move(other[i]);
other.clear(); other.clear();
@ -109,8 +112,8 @@ namespace pkpy {
inline int size() const { return _size; } inline int size() const { return _size; }
PyVarList to_list() const { pkpy::List to_list() const {
PyVarList ret(_size); pkpy::List ret(_size);
for(int i=0; i<_size; i++) ret[i] = _args[i]; for(int i=0; i<_size; i++) ret[i] = _args[i];
return ret; return ret;
} }
@ -152,6 +155,6 @@ namespace pkpy {
ret[1] = std::forward<T2>(b); ret[1] = std::forward<T2>(b);
return ret; return ret;
} }
}
typedef pkpy::Args _Tuple; typedef Args Tuple;
}

View File

@ -4,7 +4,7 @@
typedef std::stringstream _StrStream; typedef std::stringstream _StrStream;
class _Str : public std::string { class Str : public std::string {
mutable std::vector<uint16_t>* _u8_index = nullptr; mutable std::vector<uint16_t>* _u8_index = nullptr;
mutable bool hash_initialized = false; mutable bool hash_initialized = false;
mutable size_t _hash; mutable size_t _hash;
@ -21,11 +21,11 @@ class _Str : public std::string {
} }
} }
public: public:
_Str() : std::string() {} Str() : std::string() {}
_Str(const char* s) : std::string(s) {} Str(const char* s) : std::string(s) {}
_Str(const char* s, size_t n) : std::string(s, n) {} Str(const char* s, size_t n) : std::string(s, n) {}
_Str(const std::string& s) : std::string(s) {} Str(const std::string& s) : std::string(s) {}
_Str(const _Str& s) : std::string(s) { Str(const Str& s) : std::string(s) {
if(s._u8_index != nullptr){ if(s._u8_index != nullptr){
_u8_index = new std::vector<uint16_t>(*s._u8_index); _u8_index = new std::vector<uint16_t>(*s._u8_index);
} }
@ -34,7 +34,7 @@ public:
hash_initialized = true; hash_initialized = true;
} }
} }
_Str(_Str&& s) : std::string(std::move(s)) { Str(Str&& s) : std::string(std::move(s)) {
if(_u8_index != nullptr) delete _u8_index; if(_u8_index != nullptr) delete _u8_index;
_u8_index = s._u8_index; _u8_index = s._u8_index;
s._u8_index = nullptr; s._u8_index = nullptr;
@ -64,27 +64,27 @@ public:
return _u8_index->size(); return _u8_index->size();
} }
_Str u8_getitem(int i) const{ Str u8_getitem(int i) const{
return u8_substr(i, i+1); return u8_substr(i, i+1);
} }
_Str u8_substr(int start, int end) const{ Str u8_substr(int start, int end) const{
utf8_lazy_init(); utf8_lazy_init();
if(start >= end) return _Str(); if(start >= end) return Str();
int c_end = end >= _u8_index->size() ? size() : _u8_index->at(end); int c_end = end >= _u8_index->size() ? size() : _u8_index->at(end);
return substr(_u8_index->at(start), c_end - _u8_index->at(start)); return substr(_u8_index->at(start), c_end - _u8_index->at(start));
} }
_Str lstrip() const { Str lstrip() const {
_Str copy(*this); Str copy(*this);
copy.erase(copy.begin(), std::find_if(copy.begin(), copy.end(), [](char c) { copy.erase(copy.begin(), std::find_if(copy.begin(), copy.end(), [](char c) {
// std::isspace(c) does not working on windows (Debug) // std::isspace(c) does not working on windows (Debug)
return c != ' ' && c != '\t' && c != '\r' && c != '\n'; return c != ' ' && c != '\t' && c != '\r' && c != '\n';
})); }));
return _Str(copy); return Str(copy);
} }
_Str escape(bool single_quote) const { Str escape(bool single_quote) const {
_StrStream ss; _StrStream ss;
ss << (single_quote ? '\'' : '"'); ss << (single_quote ? '\'' : '"');
for (int i=0; i<length(); i++) { for (int i=0; i<length(); i++) {
@ -115,7 +115,7 @@ public:
return ss.str(); return ss.str();
} }
_Str& operator=(const _Str& s){ Str& operator=(const Str& s){
this->std::string::operator=(s); this->std::string::operator=(s);
if(_u8_index != nullptr){ if(_u8_index != nullptr){
delete _u8_index; delete _u8_index;
@ -126,7 +126,7 @@ public:
return *this; return *this;
} }
_Str& operator=(_Str&& s){ Str& operator=(Str&& s){
this->std::string::operator=(std::move(s)); this->std::string::operator=(std::move(s));
if(_u8_index != nullptr) delete _u8_index; if(_u8_index != nullptr) delete _u8_index;
this->_u8_index = s._u8_index; this->_u8_index = s._u8_index;
@ -136,51 +136,51 @@ public:
return *this; return *this;
} }
~_Str(){ ~Str(){
if(_u8_index != nullptr) delete _u8_index; if(_u8_index != nullptr) delete _u8_index;
} }
}; };
namespace std { namespace std {
template<> template<>
struct hash<_Str> { struct hash<Str> {
inline std::size_t operator()(const _Str& s) const { inline std::size_t operator()(const Str& s) const {
return s.hash(); return s.hash();
} }
}; };
} }
const _Str __class__ = _Str("__class__"); const Str __class__ = Str("__class__");
const _Str __base__ = _Str("__base__"); const Str __base__ = Str("__base__");
const _Str __new__ = _Str("__new__"); const Str __new__ = Str("__new__");
const _Str __iter__ = _Str("__iter__"); const Str __iter__ = Str("__iter__");
const _Str __str__ = _Str("__str__"); const Str __str__ = Str("__str__");
const _Str __repr__ = _Str("__repr__"); const Str __repr__ = Str("__repr__");
const _Str __module__ = _Str("__module__"); const Str __module__ = Str("__module__");
const _Str __getitem__ = _Str("__getitem__"); const Str __getitem__ = Str("__getitem__");
const _Str __setitem__ = _Str("__setitem__"); const Str __setitem__ = Str("__setitem__");
const _Str __delitem__ = _Str("__delitem__"); const Str __delitem__ = Str("__delitem__");
const _Str __contains__ = _Str("__contains__"); const Str __contains__ = Str("__contains__");
const _Str __init__ = _Str("__init__"); const Str __init__ = Str("__init__");
const _Str __json__ = _Str("__json__"); const Str __json__ = Str("__json__");
const _Str __name__ = _Str("__name__"); const Str __name__ = Str("__name__");
const _Str __len__ = _Str("__len__"); const Str __len__ = Str("__len__");
const _Str m_append = _Str("append"); const Str m_append = Str("append");
const _Str m_eval = _Str("eval"); const Str m_eval = Str("eval");
const _Str m_self = _Str("self"); const Str m_self = Str("self");
const _Str __enter__ = _Str("__enter__"); const Str __enter__ = Str("__enter__");
const _Str __exit__ = _Str("__exit__"); const Str __exit__ = Str("__exit__");
const _Str CMP_SPECIAL_METHODS[] = { const Str CMP_SPECIAL_METHODS[] = {
"__lt__", "__le__", "__eq__", "__ne__", "__gt__", "__ge__" "__lt__", "__le__", "__eq__", "__ne__", "__gt__", "__ge__"
}; };
const _Str BINARY_SPECIAL_METHODS[] = { const Str BINARY_SPECIAL_METHODS[] = {
"__add__", "__sub__", "__mul__", "__truediv__", "__floordiv__", "__mod__", "__pow__" "__add__", "__sub__", "__mul__", "__truediv__", "__floordiv__", "__mod__", "__pow__"
}; };
const _Str BITWISE_SPECIAL_METHODS[] = { const Str BITWISE_SPECIAL_METHODS[] = {
"__lshift__", "__rshift__", "__and__", "__or__", "__xor__" "__lshift__", "__rshift__", "__and__", "__or__", "__xor__"
}; };

300
src/vm.h
View File

@ -65,7 +65,7 @@ class VM {
pkpy::Args items = frame->pop_n_reversed(byte.arg); pkpy::Args items = frame->pop_n_reversed(byte.arg);
bool done = false; bool done = false;
for(int i=0; i<items.size(); i++){ for(int i=0; i<items.size(); i++){
if(!items[i]->is_type(_tp_ref)) { if(!items[i]->is_type(tp_ref)) {
done = true; done = true;
for(int j=i; j<items.size(); j++) frame->try_deref(this, items[j]); for(int j=i; j<items.size(); j++) frame->try_deref(this, items[j]);
frame->push(PyTuple(std::move(items))); frame->push(PyTuple(std::move(items)));
@ -94,21 +94,21 @@ class VM {
case OP_STORE_FUNCTION: case OP_STORE_FUNCTION:
{ {
PyVar obj = frame->pop_value(this); PyVar obj = frame->pop_value(this);
const _Func& fn = PyFunction_AS_C(obj); const pkpy::Function_& fn = PyFunction_AS_C(obj);
setattr(obj, __module__, frame->_module); setattr(obj, __module__, frame->_module);
frame->f_globals()[fn->name] = obj; frame->f_globals()[fn->name] = obj;
} break; } break;
case OP_BUILD_CLASS: case OP_BUILD_CLASS:
{ {
const _Str& clsName = frame->co->names[byte.arg].first; const Str& clsName = frame->co->names[byte.arg].first;
PyVar clsBase = frame->pop_value(this); PyVar clsBase = frame->pop_value(this);
if(clsBase == None) clsBase = _tp_object; if(clsBase == None) clsBase = tp_object;
check_type(clsBase, _tp_type); check_type(clsBase, tp_type);
PyVar cls = new_type_object(frame->_module, clsName, clsBase); PyVar cls = new_type_object(frame->_module, clsName, clsBase);
while(true){ while(true){
PyVar fn = frame->pop_value(this); PyVar fn = frame->pop_value(this);
if(fn == None) break; if(fn == None) break;
const _Func& f = PyFunction_AS_C(fn); const pkpy::Function_& f = PyFunction_AS_C(fn);
setattr(fn, __module__, frame->_module); setattr(fn, __module__, frame->_module);
setattr(cls, f->name, fn); setattr(cls, f->name, fn);
} }
@ -180,14 +180,14 @@ class VM {
case OP_EXCEPTION_MATCH: case OP_EXCEPTION_MATCH:
{ {
const auto& _e = PyException_AS_C(frame->top()); const auto& _e = PyException_AS_C(frame->top());
_Str name = frame->co->names[byte.arg].first; Str name = frame->co->names[byte.arg].first;
frame->push(PyBool(_e.match_type(name))); frame->push(PyBool(_e.match_type(name)));
} break; } break;
case OP_RAISE: case OP_RAISE:
{ {
PyVar obj = frame->pop_value(this); PyVar obj = frame->pop_value(this);
_Str msg = obj == None ? "" : PyStr_AS_C(asStr(obj)); Str msg = obj == None ? "" : PyStr_AS_C(asStr(obj));
_Str type = frame->co->names[byte.arg].first; Str type = frame->co->names[byte.arg].first;
_error(type, msg); _error(type, msg);
} break; } break;
case OP_RE_RAISE: _raise(); break; case OP_RE_RAISE: _raise(); break;
@ -228,7 +228,7 @@ class VM {
case OP_JUMP_ABSOLUTE: frame->jump_abs(byte.arg); break; case OP_JUMP_ABSOLUTE: frame->jump_abs(byte.arg); break;
case OP_SAFE_JUMP_ABSOLUTE: frame->jump_abs_safe(byte.arg); break; case OP_SAFE_JUMP_ABSOLUTE: frame->jump_abs_safe(byte.arg); break;
case OP_GOTO: { case OP_GOTO: {
const _Str& label = frame->co->names[byte.arg].first; const Str& label = frame->co->names[byte.arg].first;
int* target = frame->co->labels.try_get(label); int* target = frame->co->labels.try_get(label);
if(target == nullptr) _error("KeyError", "label '" + label + "' not found"); if(target == nullptr) _error("KeyError", "label '" + label + "' not found");
frame->jump_abs_safe(*target); frame->jump_abs_safe(*target);
@ -240,7 +240,7 @@ class VM {
if(iter_fn != nullptr){ if(iter_fn != nullptr){
PyVar tmp = call(iter_fn); PyVar tmp = call(iter_fn);
PyVarRef var = frame->pop(); PyVarRef var = frame->pop();
check_type(var, _tp_ref); check_type(var, tp_ref);
PyIter_AS_C(tmp)->var = var; PyIter_AS_C(tmp)->var = var;
frame->push(std::move(tmp)); frame->push(std::move(tmp));
}else{ }else{
@ -284,24 +284,24 @@ class VM {
{ {
PyVar stop = frame->pop_value(this); PyVar stop = frame->pop_value(this);
PyVar start = frame->pop_value(this); PyVar start = frame->pop_value(this);
_Slice s; pkpy::Slice s;
if(start != None) {check_type(start, _tp_int); s.start = (int)PyInt_AS_C(start);} if(start != None) {check_type(start, tp_int); s.start = (int)PyInt_AS_C(start);}
if(stop != None) {check_type(stop, _tp_int); s.stop = (int)PyInt_AS_C(stop);} if(stop != None) {check_type(stop, tp_int); s.stop = (int)PyInt_AS_C(stop);}
frame->push(PySlice(s)); frame->push(PySlice(s));
} break; } break;
case OP_IMPORT_NAME: case OP_IMPORT_NAME:
{ {
const _Str& name = frame->co->names[byte.arg].first; const Str& name = frame->co->names[byte.arg].first;
auto it = _modules.find(name); auto it = _modules.find(name);
if(it == _modules.end()){ if(it == _modules.end()){
auto it2 = _lazy_modules.find(name); auto it2 = _lazy_modules.find(name);
if(it2 == _lazy_modules.end()){ if(it2 == _lazy_modules.end()){
_error("ImportError", "module '" + name + "' not found"); _error("ImportError", "module '" + name + "' not found");
}else{ }else{
const _Str& source = it2->second; const Str& source = it2->second;
_Code code = compile(source, name, EXEC_MODE); CodeObject_ code = compile(source, name, EXEC_MODE);
PyVar _m = new_module(name); PyVar _m = new_module(name);
_exec(code, _m, pkpy::make_shared<PyVarDict>()); _exec(code, _m, pkpy::make_shared<pkpy::NameDict>());
frame->push(_m); frame->push(_m);
_lazy_modules.erase(it2); _lazy_modules.erase(it2);
} }
@ -315,7 +315,7 @@ class VM {
case OP_TRY_BLOCK_ENTER: frame->on_try_block_enter(); break; case OP_TRY_BLOCK_ENTER: frame->on_try_block_enter(); break;
case OP_TRY_BLOCK_EXIT: frame->on_try_block_exit(); break; case OP_TRY_BLOCK_EXIT: frame->on_try_block_exit(); break;
default: default:
throw std::runtime_error(_Str("opcode ") + OP_NAMES[byte.op] + " is not implemented"); throw std::runtime_error(Str("opcode ") + OP_NAMES[byte.op] + " is not implemented");
break; break;
} }
} }
@ -330,9 +330,9 @@ class VM {
} }
public: public:
PyVarDict _types; pkpy::NameDict _types;
PyVarDict _modules; // loaded modules pkpy::NameDict _modules; // loaded modules
emhash8::HashMap<_Str, _Str> _lazy_modules; // lazy loaded modules emhash8::HashMap<Str, Str> _lazy_modules; // lazy loaded modules
PyVar None, True, False, Ellipsis; PyVar None, True, False, Ellipsis;
bool use_stdio; bool use_stdio;
@ -371,15 +371,15 @@ public:
} }
PyVar asRepr(const PyVar& obj){ PyVar asRepr(const PyVar& obj){
if(obj->is_type(_tp_type)) return PyStr("<class '" + OBJ_GET(_Str, obj->attribs[__name__]) + "'>"); if(obj->is_type(tp_type)) return PyStr("<class '" + OBJ_GET(Str, obj->attribs[__name__]) + "'>");
return call(obj, __repr__); return call(obj, __repr__);
} }
const PyVar& asBool(const PyVar& obj){ const PyVar& asBool(const PyVar& obj){
if(obj->is_type(_tp_bool)) return obj; if(obj->is_type(tp_bool)) return obj;
if(obj == None) return False; if(obj == None) return False;
if(obj->is_type(_tp_int)) return PyBool(PyInt_AS_C(obj) != 0); if(obj->is_type(tp_int)) return PyBool(PyInt_AS_C(obj) != 0);
if(obj->is_type(_tp_float)) return PyBool(PyFloat_AS_C(obj) != 0.0); if(obj->is_type(tp_float)) return PyBool(PyFloat_AS_C(obj) != 0.0);
PyVarOrNull len_fn = getattr(obj, __len__, false); PyVarOrNull len_fn = getattr(obj, __len__, false);
if(len_fn != nullptr){ if(len_fn != nullptr){
PyVar ret = call(len_fn); PyVar ret = call(len_fn);
@ -388,7 +388,7 @@ public:
return True; return True;
} }
PyVar fast_call(const _Str& name, pkpy::Args&& args){ PyVar fast_call(const Str& name, pkpy::Args&& args){
PyObject* cls = args[0]->type.get(); PyObject* cls = args[0]->type.get();
while(cls != None.get()) { while(cls != None.get()) {
PyVar* val = cls->attribs.try_get(name); PyVar* val = cls->attribs.try_get(name);
@ -411,16 +411,16 @@ public:
template<typename ArgT> template<typename ArgT>
inline std::enable_if_t<std::is_same_v<std::remove_const_t<std::remove_reference_t<ArgT>>, pkpy::Args>, PyVar> inline std::enable_if_t<std::is_same_v<std::remove_const_t<std::remove_reference_t<ArgT>>, pkpy::Args>, PyVar>
call(const PyVar& obj, const _Str& func, ArgT&& args){ call(const PyVar& obj, const Str& func, ArgT&& args){
return call(getattr(obj, func), std::forward<ArgT>(args), pkpy::no_arg(), false); return call(getattr(obj, func), std::forward<ArgT>(args), pkpy::no_arg(), false);
} }
inline PyVar call(const PyVar& obj, const _Str& func){ inline PyVar call(const PyVar& obj, const Str& func){
return call(getattr(obj, func), pkpy::no_arg(), pkpy::no_arg(), false); return call(getattr(obj, func), pkpy::no_arg(), pkpy::no_arg(), false);
} }
PyVar call(const PyVar& _callable, pkpy::Args args, const pkpy::Args& kwargs, bool opCall){ PyVar call(const PyVar& _callable, pkpy::Args args, const pkpy::Args& kwargs, bool opCall){
if(_callable->is_type(_tp_type)){ if(_callable->is_type(tp_type)){
auto it = _callable->attribs.find(__new__); auto it = _callable->attribs.find(__new__);
PyVar obj; PyVar obj;
if(it != _callable->attribs.end()){ if(it != _callable->attribs.end()){
@ -434,20 +434,20 @@ public:
} }
const PyVar* callable = &_callable; const PyVar* callable = &_callable;
if((*callable)->is_type(_tp_bound_method)){ if((*callable)->is_type(tp_bound_method)){
auto& bm = PyBoundMethod_AS_C((*callable)); auto& bm = PyBoundMethod_AS_C((*callable));
callable = &bm.method; // get unbound method callable = &bm.method; // get unbound method
args.extend_self(bm.obj); args.extend_self(bm.obj);
} }
if((*callable)->is_type(_tp_native_function)){ if((*callable)->is_type(tp_native_function)){
const auto& f = OBJ_GET(_CppFunc, *callable); const auto& f = OBJ_GET(pkpy::NativeFunc, *callable);
if(kwargs.size() != 0) TypeError("native_function does not accept keyword arguments"); if(kwargs.size() != 0) TypeError("native_function does not accept keyword arguments");
return f(this, args); return f(this, args);
} else if((*callable)->is_type(_tp_function)){ } else if((*callable)->is_type(tp_function)){
const _Func& fn = PyFunction_AS_C((*callable)); const pkpy::Function_& fn = PyFunction_AS_C((*callable));
pkpy::shared_ptr<PyVarDict> _locals = pkpy::make_shared<PyVarDict>(); pkpy::shared_ptr<pkpy::NameDict> _locals = pkpy::make_shared<pkpy::NameDict>();
PyVarDict& locals = *_locals; pkpy::NameDict& locals = *_locals;
int i = 0; int i = 0;
for(const auto& name : fn->args){ for(const auto& name : fn->args){
@ -460,9 +460,9 @@ public:
locals.insert(fn->kwArgs.begin(), fn->kwArgs.end()); locals.insert(fn->kwArgs.begin(), fn->kwArgs.end());
std::vector<_Str> positional_overrided_keys; std::vector<Str> positional_overrided_keys;
if(!fn->starredArg.empty()){ if(!fn->starredArg.empty()){
PyVarList vargs; // handle *args pkpy::List vargs; // handle *args
while(i < args.size()) vargs.push_back(args[i++]); while(i < args.size()) vargs.push_back(args[i++]);
locals.emplace(fn->starredArg, PyTuple(std::move(vargs))); locals.emplace(fn->starredArg, PyTuple(std::move(vargs)));
}else{ }else{
@ -478,7 +478,7 @@ public:
} }
for(int i=0; i<kwargs.size(); i+=2){ for(int i=0; i<kwargs.size(); i+=2){
const _Str& key = PyStr_AS_C(kwargs[i]); const Str& key = PyStr_AS_C(kwargs[i]);
if(!fn->kwArgs.contains(key)){ if(!fn->kwArgs.contains(key)){
TypeError(key.escape(true) + " is an invalid keyword argument for " + fn->name + "()"); TypeError(key.escape(true) + " is an invalid keyword argument for " + fn->name + "()");
} }
@ -506,12 +506,12 @@ public:
// repl mode is only for setting `frame->id` to 0 // repl mode is only for setting `frame->id` to 0
PyVarOrNull exec(_Str source, _Str filename, CompileMode mode, PyVar _module=nullptr){ PyVarOrNull exec(Str source, Str filename, CompileMode mode, PyVar _module=nullptr){
if(_module == nullptr) _module = _main; if(_module == nullptr) _module = _main;
try { try {
_Code code = compile(source, filename, mode); CodeObject_ code = compile(source, filename, mode);
return _exec(code, _module, pkpy::make_shared<PyVarDict>()); return _exec(code, _module, pkpy::make_shared<pkpy::NameDict>());
}catch (const _Exception& e){ }catch (const pkpy::Exception& e){
*_stderr << e.summary() << '\n'; *_stderr << e.summary() << '\n';
} }
catch (const std::exception& e) { catch (const std::exception& e) {
@ -560,7 +560,7 @@ public:
continue; continue;
}catch(UnhandledException& e){ }catch(UnhandledException& e){
PyVar obj = frame->pop(); PyVar obj = frame->pop();
_Exception& _e = PyException_AS_C(obj); pkpy::Exception& _e = PyException_AS_C(obj);
_e.st_push(frame->snapshot()); _e.st_push(frame->snapshot());
callstack.pop(); callstack.pop();
if(callstack.empty()) throw _e; if(callstack.empty()) throw _e;
@ -574,20 +574,20 @@ public:
} }
} }
PyVar new_type_object(PyVar mod, _Str name, PyVar base){ PyVar new_type_object(PyVar mod, Str name, PyVar base){
if(!base->is_type(_tp_type)) UNREACHABLE(); if(!base->is_type(tp_type)) UNREACHABLE();
PyVar obj = pkpy::make_shared<PyObject, Py_<Dummy>>(_tp_type, DUMMY_VAL); PyVar obj = pkpy::make_shared<PyObject, Py_<Dummy>>(tp_type, DUMMY_VAL);
setattr(obj, __base__, base); setattr(obj, __base__, base);
_Str fullName = name; Str fullName = name;
if(mod != builtins) fullName = OBJ_NAME(mod) + "." + name; if(mod != builtins) fullName = OBJ_NAME(mod) + "." + name;
setattr(obj, __name__, PyStr(fullName)); setattr(obj, __name__, PyStr(fullName));
setattr(mod, name, obj); setattr(mod, name, obj);
return obj; return obj;
} }
PyVar _new_type_object(_Str name, PyVar base=nullptr) { PyVar _new_type_object(Str name, PyVar base=nullptr) {
if(base == nullptr) base = _tp_object; if(base == nullptr) base = tp_object;
PyVar obj = pkpy::make_shared<PyObject, Py_<Dummy>>(_tp_type, DUMMY_VAL); PyVar obj = pkpy::make_shared<PyObject, Py_<Dummy>>(tp_type, DUMMY_VAL);
setattr(obj, __base__, base); setattr(obj, __base__, base);
_types[name] = obj; _types[name] = obj;
return obj; return obj;
@ -595,7 +595,7 @@ public:
template<typename T> template<typename T>
inline PyVar new_object(PyVar type, T _value) { inline PyVar new_object(PyVar type, T _value) {
if(!type->is_type(_tp_type)) UNREACHABLE(); if(!type->is_type(tp_type)) UNREACHABLE();
if constexpr (std::is_same_v<T, Dummy>) return pkpy::make_shared<PyObject, Py_<T>>(type, _value); if constexpr (std::is_same_v<T, Dummy>) return pkpy::make_shared<PyObject, Py_<T>>(type, _value);
std::vector<int*>& pool = _obj_pool[tid<T>()]; std::vector<int*>& pool = _obj_pool[tid<T>()];
if(pool.empty()) return pkpy::make_shared<PyObject, Py_<T>>(type, _value); if(pool.empty()) return pkpy::make_shared<PyObject, Py_<T>>(type, _value);
@ -612,23 +612,23 @@ public:
return new_object(T::_type(this), T(std::forward<Args>(args)...)); return new_object(T::_type(this), T(std::forward<Args>(args)...));
} }
PyVar new_module(const _Str& name) { PyVar new_module(const Str& name) {
PyVar obj = new_object(_tp_module, DUMMY_VAL); PyVar obj = new_object(tp_module, DUMMY_VAL);
setattr(obj, __name__, PyStr(name)); setattr(obj, __name__, PyStr(name));
_modules[name] = obj; _modules[name] = obj;
return obj; return obj;
} }
PyVarOrNull getattr(const PyVar& obj, const _Str& name, bool throw_err=true) { PyVarOrNull getattr(const PyVar& obj, const Str& name, bool throw_err=true) {
PyVarDict::iterator it; pkpy::NameDict::iterator it;
PyObject* cls; PyObject* cls;
if(obj->is_type(_tp_super)){ if(obj->is_type(tp_super)){
const PyVar* root = &obj; const PyVar* root = &obj;
int depth = 1; int depth = 1;
while(true){ while(true){
root = &OBJ_GET(PyVar, *root); root = &OBJ_GET(PyVar, *root);
if(!(*root)->is_type(_tp_super)) break; if(!(*root)->is_type(tp_super)) break;
depth++; depth++;
} }
cls = (*root)->type.get(); cls = (*root)->type.get();
@ -646,7 +646,7 @@ public:
it = cls->attribs.find(name); it = cls->attribs.find(name);
if(it != cls->attribs.end()){ if(it != cls->attribs.end()){
PyVar valueFromCls = it->second; PyVar valueFromCls = it->second;
if(valueFromCls->is_type(_tp_function) || valueFromCls->is_type(_tp_native_function)){ if(valueFromCls->is_type(tp_function) || valueFromCls->is_type(tp_native_function)){
return PyBoundMethod({obj, std::move(valueFromCls)}); return PyBoundMethod({obj, std::move(valueFromCls)});
}else{ }else{
return valueFromCls; return valueFromCls;
@ -659,47 +659,47 @@ public:
} }
template<typename T> template<typename T>
inline void setattr(PyVar& obj, const _Str& name, T&& value) { inline void setattr(PyVar& obj, const Str& name, T&& value) {
PyObject* p = obj.get(); PyObject* p = obj.get();
while(p->is_type(_tp_super)) p = static_cast<PyVar*>(p->value())->get(); while(p->is_type(tp_super)) p = static_cast<PyVar*>(p->value())->get();
p->attribs[name] = std::forward<T>(value); p->attribs[name] = std::forward<T>(value);
} }
template<int ARGC> template<int ARGC>
void bind_method(PyVar obj, _Str funcName, _CppFuncRaw fn) { void bind_method(PyVar obj, Str funcName, NativeFuncRaw fn) {
check_type(obj, _tp_type); check_type(obj, tp_type);
setattr(obj, funcName, PyNativeFunction(_CppFunc(fn, ARGC, true))); setattr(obj, funcName, PyNativeFunc(pkpy::NativeFunc(fn, ARGC, true)));
} }
template<int ARGC> template<int ARGC>
void bind_func(PyVar obj, _Str funcName, _CppFuncRaw fn) { void bind_func(PyVar obj, Str funcName, NativeFuncRaw fn) {
setattr(obj, funcName, PyNativeFunction(_CppFunc(fn, ARGC, false))); setattr(obj, funcName, PyNativeFunc(pkpy::NativeFunc(fn, ARGC, false)));
} }
template<int ARGC> template<int ARGC>
void bind_method(_Str typeName, _Str funcName, _CppFuncRaw fn) { void bind_method(Str typeName, Str funcName, NativeFuncRaw fn) {
bind_method<ARGC>(_types[typeName], funcName, fn); bind_method<ARGC>(_types[typeName], funcName, fn);
} }
template<int ARGC> template<int ARGC>
void bind_static_method(_Str typeName, _Str funcName, _CppFuncRaw fn) { void bind_static_method(Str typeName, Str funcName, NativeFuncRaw fn) {
bind_func<ARGC>(_types[typeName], funcName, fn); bind_func<ARGC>(_types[typeName], funcName, fn);
} }
template<int ARGC> template<int ARGC>
void _bind_methods(std::vector<_Str> typeNames, _Str funcName, _CppFuncRaw fn) { void _bind_methods(std::vector<Str> typeNames, Str funcName, NativeFuncRaw fn) {
for(auto& typeName : typeNames) bind_method<ARGC>(typeName, funcName, fn); for(auto& typeName : typeNames) bind_method<ARGC>(typeName, funcName, fn);
} }
template<int ARGC> template<int ARGC>
void bind_builtin_func(_Str funcName, _CppFuncRaw fn) { void bind_builtin_func(Str funcName, NativeFuncRaw fn) {
bind_func<ARGC>(builtins, funcName, fn); bind_func<ARGC>(builtins, funcName, fn);
} }
inline f64 num_to_float(const PyVar& obj){ inline f64 num_to_float(const PyVar& obj){
if (obj->is_type(_tp_int)){ if (obj->is_type(tp_int)){
return (f64)PyInt_AS_C(obj); return (f64)PyInt_AS_C(obj);
}else if(obj->is_type(_tp_float)){ }else if(obj->is_type(tp_float)){
return PyFloat_AS_C(obj); return PyFloat_AS_C(obj);
} }
TypeError("expected 'int' or 'float', got " + OBJ_TP_NAME(obj).escape(true)); TypeError("expected 'int' or 'float', got " + OBJ_TP_NAME(obj).escape(true));
@ -707,9 +707,9 @@ public:
} }
PyVar num_negated(const PyVar& obj){ PyVar num_negated(const PyVar& obj){
if (obj->is_type(_tp_int)){ if (obj->is_type(tp_int)){
return PyInt(-PyInt_AS_C(obj)); return PyInt(-PyInt_AS_C(obj));
}else if(obj->is_type(_tp_float)){ }else if(obj->is_type(tp_float)){
return PyFloat(-PyFloat_AS_C(obj)); return PyFloat(-PyFloat_AS_C(obj));
} }
TypeError("unsupported operand type(s) for -"); TypeError("unsupported operand type(s) for -");
@ -724,7 +724,7 @@ public:
return index; return index;
} }
_Str disassemble(_Code co){ Str disassemble(CodeObject_ co){
std::vector<int> jumpTargets; std::vector<int> jumpTargets;
for(auto byte : co->codes){ for(auto byte : co->codes){
if(byte.op == OP_JUMP_ABSOLUTE || byte.op == OP_SAFE_JUMP_ABSOLUTE || byte.op == OP_POP_JUMP_IF_FALSE){ if(byte.op == OP_JUMP_ABSOLUTE || byte.op == OP_SAFE_JUMP_ABSOLUTE || byte.op == OP_POP_JUMP_IF_FALSE){
@ -737,7 +737,7 @@ public:
int prev_line = -1; int prev_line = -1;
for(int i=0; i<co->codes.size(); i++){ for(int i=0; i<co->codes.size(); i++){
const Bytecode& byte = co->codes[i]; const Bytecode& byte = co->codes[i];
_Str line = std::to_string(byte.line); Str line = std::to_string(byte.line);
if(byte.line == prev_line) line = ""; if(byte.line == prev_line) line = "";
else{ else{
if(prev_line != -1) ss << "\n"; if(prev_line != -1) ss << "\n";
@ -770,7 +770,7 @@ public:
_StrStream names; _StrStream names;
names << "co_names: "; names << "co_names: ";
PyVarList list; pkpy::List list;
for(int i=0; i<co->names.size(); i++){ for(int i=0; i<co->names.size(); i++){
list.push_back(PyStr(co->names[i].first)); list.push_back(PyStr(co->names[i].first));
} }
@ -779,109 +779,109 @@ public:
for(int i=0; i<co->consts.size(); i++){ for(int i=0; i<co->consts.size(); i++){
PyVar obj = co->consts[i]; PyVar obj = co->consts[i];
if(obj->is_type(_tp_function)){ if(obj->is_type(tp_function)){
const auto& f = PyFunction_AS_C(obj); const auto& f = PyFunction_AS_C(obj);
ss << disassemble(f->code); ss << disassemble(f->code);
} }
} }
return _Str(ss.str()); return Str(ss.str());
} }
// for quick access // for quick access
PyVar _tp_object, _tp_type, _tp_int, _tp_float, _tp_bool, _tp_str; PyVar tp_object, tp_type, tp_int, tp_float, tp_bool, tp_str;
PyVar _tp_list, _tp_tuple; PyVar tp_list, tp_tuple;
PyVar _tp_function, _tp_native_function, _tp_native_iterator, _tp_bound_method; PyVar tp_function, tp_native_function, tp_native_iterator, tp_bound_method;
PyVar _tp_slice, _tp_range, _tp_module, _tp_ref; PyVar tp_slice, tp_range, tp_module, tp_ref;
PyVar _tp_super, _tp_exception; PyVar tp_super, tp_exception;
template<typename P> template<typename P>
inline PyVarRef PyRef(P&& value) { inline PyVarRef PyRef(P&& value) {
static_assert(std::is_base_of<BaseRef, P>::value, "P should derive from BaseRef"); static_assert(std::is_base_of<BaseRef, P>::value, "P should derive from BaseRef");
return new_object(_tp_ref, std::forward<P>(value)); return new_object(tp_ref, std::forward<P>(value));
} }
inline const BaseRef* PyRef_AS_C(const PyVar& obj) inline const BaseRef* PyRef_AS_C(const PyVar& obj)
{ {
if(!obj->is_type(_tp_ref)) TypeError("expected an l-value"); if(!obj->is_type(tp_ref)) TypeError("expected an l-value");
return (const BaseRef*)(obj->value()); return (const BaseRef*)(obj->value());
} }
DEF_NATIVE(Int, i64, _tp_int) DEF_NATIVE(Int, i64, tp_int)
DEF_NATIVE(Float, f64, _tp_float) DEF_NATIVE(Float, f64, tp_float)
DEF_NATIVE(Str, _Str, _tp_str) DEF_NATIVE(Str, Str, tp_str)
DEF_NATIVE(List, PyVarList, _tp_list) DEF_NATIVE(List, pkpy::List, tp_list)
DEF_NATIVE(Tuple, _Tuple, _tp_tuple) DEF_NATIVE(Tuple, pkpy::Tuple, tp_tuple)
DEF_NATIVE(Function, _Func, _tp_function) DEF_NATIVE(Function, pkpy::Function_, tp_function)
DEF_NATIVE(NativeFunction, _CppFunc, _tp_native_function) DEF_NATIVE(NativeFunc, pkpy::NativeFunc, tp_native_function)
DEF_NATIVE(Iter, pkpy::shared_ptr<BaseIter>, _tp_native_iterator) DEF_NATIVE(Iter, pkpy::shared_ptr<BaseIter>, tp_native_iterator)
DEF_NATIVE(BoundMethod, _BoundMethod, _tp_bound_method) DEF_NATIVE(BoundMethod, pkpy::BoundMethod, tp_bound_method)
DEF_NATIVE(Range, _Range, _tp_range) DEF_NATIVE(Range, pkpy::Range, tp_range)
DEF_NATIVE(Slice, _Slice, _tp_slice) DEF_NATIVE(Slice, pkpy::Slice, tp_slice)
DEF_NATIVE(Exception, _Exception, _tp_exception) DEF_NATIVE(Exception, pkpy::Exception, tp_exception)
// there is only one True/False, so no need to copy them! // there is only one True/False, so no need to copy them!
inline bool PyBool_AS_C(const PyVar& obj){return obj == True;} inline bool PyBool_AS_C(const PyVar& obj){return obj == True;}
inline const PyVar& PyBool(bool value){return value ? True : False;} inline const PyVar& PyBool(bool value){return value ? True : False;}
void init_builtin_types(){ void init_builtin_types(){
_tp_object = pkpy::make_shared<PyObject, Py_<Dummy>>(nullptr, DUMMY_VAL); tp_object = pkpy::make_shared<PyObject, Py_<Dummy>>(nullptr, DUMMY_VAL);
_tp_type = pkpy::make_shared<PyObject, Py_<Dummy>>(nullptr, DUMMY_VAL); tp_type = pkpy::make_shared<PyObject, Py_<Dummy>>(nullptr, DUMMY_VAL);
_types["object"] = _tp_object; _types["object"] = tp_object;
_types["type"] = _tp_type; _types["type"] = tp_type;
_tp_bool = _new_type_object("bool"); tp_bool = _new_type_object("bool");
_tp_int = _new_type_object("int"); tp_int = _new_type_object("int");
_tp_float = _new_type_object("float"); tp_float = _new_type_object("float");
_tp_str = _new_type_object("str"); tp_str = _new_type_object("str");
_tp_list = _new_type_object("list"); tp_list = _new_type_object("list");
_tp_tuple = _new_type_object("tuple"); tp_tuple = _new_type_object("tuple");
_tp_slice = _new_type_object("slice"); tp_slice = _new_type_object("slice");
_tp_range = _new_type_object("range"); tp_range = _new_type_object("range");
_tp_module = _new_type_object("module"); tp_module = _new_type_object("module");
_tp_ref = _new_type_object("_ref"); tp_ref = _new_type_object("_ref");
_tp_function = _new_type_object("function"); tp_function = _new_type_object("function");
_tp_native_function = _new_type_object("native_function"); tp_native_function = _new_type_object("native_function");
_tp_native_iterator = _new_type_object("native_iterator"); tp_native_iterator = _new_type_object("native_iterator");
_tp_bound_method = _new_type_object("bound_method"); tp_bound_method = _new_type_object("bound_method");
_tp_super = _new_type_object("super"); tp_super = _new_type_object("super");
_tp_exception = _new_type_object("Exception"); tp_exception = _new_type_object("Exception");
this->None = new_object(_new_type_object("NoneType"), DUMMY_VAL); this->None = new_object(_new_type_object("NoneType"), DUMMY_VAL);
this->Ellipsis = new_object(_new_type_object("ellipsis"), DUMMY_VAL); this->Ellipsis = new_object(_new_type_object("ellipsis"), DUMMY_VAL);
this->True = new_object(_tp_bool, true); this->True = new_object(tp_bool, true);
this->False = new_object(_tp_bool, false); this->False = new_object(tp_bool, false);
this->builtins = new_module("builtins"); this->builtins = new_module("builtins");
this->_main = new_module("__main__"); this->_main = new_module("__main__");
this->_py_op_call = new_object(_new_type_object("_internal"), DUMMY_VAL); this->_py_op_call = new_object(_new_type_object("_internal"), DUMMY_VAL);
setattr(_tp_type, __base__, _tp_object); setattr(tp_type, __base__, tp_object);
_tp_type->type = _tp_type; tp_type->type = tp_type;
setattr(_tp_object, __base__, None); setattr(tp_object, __base__, None);
_tp_object->type = _tp_type; tp_object->type = tp_type;
for (auto& [name, type] : _types) { for (auto& [name, type] : _types) {
setattr(type, __name__, PyStr(name)); setattr(type, __name__, PyStr(name));
} }
std::vector<_Str> publicTypes = {"type", "object", "bool", "int", "float", "str", "list", "tuple", "range"}; std::vector<Str> publicTypes = {"type", "object", "bool", "int", "float", "str", "list", "tuple", "range"};
for (auto& name : publicTypes) { for (auto& name : publicTypes) {
setattr(builtins, name, _types[name]); setattr(builtins, name, _types[name]);
} }
} }
i64 hash(const PyVar& obj){ i64 hash(const PyVar& obj){
if (obj->is_type(_tp_int)) return PyInt_AS_C(obj); if (obj->is_type(tp_int)) return PyInt_AS_C(obj);
if (obj->is_type(_tp_bool)) return PyBool_AS_C(obj) ? 1 : 0; if (obj->is_type(tp_bool)) return PyBool_AS_C(obj) ? 1 : 0;
if (obj->is_type(_tp_float)){ if (obj->is_type(tp_float)){
f64 val = PyFloat_AS_C(obj); f64 val = PyFloat_AS_C(obj);
return (i64)std::hash<f64>()(val); return (i64)std::hash<f64>()(val);
} }
if (obj->is_type(_tp_str)) return PyStr_AS_C(obj).hash(); if (obj->is_type(tp_str)) return PyStr_AS_C(obj).hash();
if (obj->is_type(_tp_type)) return (i64)obj.get(); if (obj->is_type(tp_type)) return (i64)obj.get();
if (obj->is_type(_tp_tuple)) { if (obj->is_type(tp_tuple)) {
i64 x = 1000003; i64 x = 1000003;
const _Tuple& items = PyTuple_AS_C(obj); const pkpy::Tuple& items = PyTuple_AS_C(obj);
for (int i=0; i<items.size(); i++) { for (int i=0; i<items.size(); i++) {
i64 y = hash(items[i]); i64 y = hash(items[i]);
x = x ^ (y + 0x9e3779b9 + (x << 6) + (x >> 2)); // recommended by Github Copilot x = x ^ (y + 0x9e3779b9 + (x << 6) + (x >> 2)); // recommended by Github Copilot
@ -894,11 +894,11 @@ public:
/***** Error Reporter *****/ /***** Error Reporter *****/
private: private:
void _error(const _Str& name, const _Str& msg){ void _error(const Str& name, const Str& msg){
_error(_Exception(name, msg)); _error(pkpy::Exception(name, msg));
} }
void _error(_Exception e){ void _error(pkpy::Exception e){
if(callstack.empty()){ if(callstack.empty()){
e.is_re = false; e.is_re = false;
throw e; throw e;
@ -915,13 +915,13 @@ private:
public: public:
void NotImplementedError(){ _error("NotImplementedError", ""); } void NotImplementedError(){ _error("NotImplementedError", ""); }
void TypeError(const _Str& msg){ _error("TypeError", msg); } void TypeError(const Str& msg){ _error("TypeError", msg); }
void ZeroDivisionError(){ _error("ZeroDivisionError", "division by zero"); } void ZeroDivisionError(){ _error("ZeroDivisionError", "division by zero"); }
void IndexError(const _Str& msg){ _error("IndexError", msg); } void IndexError(const Str& msg){ _error("IndexError", msg); }
void ValueError(const _Str& msg){ _error("ValueError", msg); } void ValueError(const Str& msg){ _error("ValueError", msg); }
void NameError(const _Str& name){ _error("NameError", "name " + name.escape(true) + " is not defined"); } void NameError(const Str& name){ _error("NameError", "name " + name.escape(true) + " is not defined"); }
void AttributeError(PyVar obj, const _Str& name){ void AttributeError(PyVar obj, const Str& name){
_error("AttributeError", "type " + OBJ_TP_NAME(obj).escape(true) + " has no attribute " + name.escape(true)); _error("AttributeError", "type " + OBJ_TP_NAME(obj).escape(true) + " has no attribute " + name.escape(true));
} }
@ -931,7 +931,7 @@ public:
template<typename T> template<typename T>
PyVar register_class(PyVar mod){ PyVar register_class(PyVar mod){
PyVar type = new_type_object(mod, T::_name(), _tp_object); PyVar type = new_type_object(mod, T::_name(), tp_object);
if(OBJ_NAME(mod) != T::_mod()) UNREACHABLE(); if(OBJ_NAME(mod) != T::_mod()) UNREACHABLE();
T::_register(this, mod, type); T::_register(this, mod, type);
return type; return type;
@ -950,7 +950,7 @@ public:
} }
} }
_Code compile(_Str source, _Str filename, CompileMode mode); CodeObject_ compile(Str source, Str filename, CompileMode mode);
}; };
/***** Pointers' Impl *****/ /***** Pointers' Impl *****/
@ -1032,7 +1032,7 @@ void IndexRef::del(VM* vm, Frame* frame) const{
} }
PyVar TupleRef::get(VM* vm, Frame* frame) const{ PyVar TupleRef::get(VM* vm, Frame* frame) const{
_Tuple args(objs.size()); pkpy::Tuple args(objs.size());
for (int i = 0; i < objs.size(); i++) { for (int i = 0; i < objs.size(); i++) {
args[i] = vm->PyRef_AS_C(objs[i])->get(vm, frame); args[i] = vm->PyRef_AS_C(objs[i])->get(vm, frame);
} }
@ -1045,11 +1045,11 @@ void TupleRef::set(VM* vm, Frame* frame, PyVar val) const{
if(args.size() < objs.size()) vm->ValueError("not enough values to unpack"); \ if(args.size() < objs.size()) vm->ValueError("not enough values to unpack"); \
for (int i = 0; i < objs.size(); i++) vm->PyRef_AS_C(objs[i])->set(vm, frame, args[i]); for (int i = 0; i < objs.size(); i++) vm->PyRef_AS_C(objs[i])->set(vm, frame, args[i]);
if(val->is_type(vm->_tp_tuple)){ if(val->is_type(vm->tp_tuple)){
const _Tuple& args = OBJ_GET(_Tuple, val); const pkpy::Tuple& args = OBJ_GET(pkpy::Tuple, val);
TUPLE_REF_SET() TUPLE_REF_SET()
}else if(val->is_type(vm->_tp_list)){ }else if(val->is_type(vm->tp_list)){
const PyVarList& args = OBJ_GET(PyVarList, val); const pkpy::List& args = OBJ_GET(pkpy::List, val);
TUPLE_REF_SET() TUPLE_REF_SET()
}else{ }else{
vm->TypeError("only tuple or list can be unpacked"); vm->TypeError("only tuple or list can be unpacked");
@ -1063,10 +1063,10 @@ void TupleRef::del(VM* vm, Frame* frame) const{
/***** Frame's Impl *****/ /***** Frame's Impl *****/
inline void Frame::try_deref(VM* vm, PyVar& v){ inline void Frame::try_deref(VM* vm, PyVar& v){
if(v->is_type(vm->_tp_ref)) v = vm->PyRef_AS_C(v)->get(vm, this); if(v->is_type(vm->tp_ref)) v = vm->PyRef_AS_C(v)->get(vm, this);
} }
PyVar _CppFunc::operator()(VM* vm, const pkpy::Args& args) const{ PyVar pkpy::NativeFunc::operator()(VM* vm, const pkpy::Args& args) const{
int args_size = args.size() - (int)method; // remove self int args_size = args.size() - (int)method; // remove self
if(argc != -1 && args_size != argc) { if(argc != -1 && args_size != argc) {
vm->TypeError("expected " + std::to_string(argc) + " arguments, but got " + std::to_string(args_size)); vm->TypeError("expected " + std::to_string(argc) + " arguments, but got " + std::to_string(args_size));