mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 19:40:18 +00:00
a bunch of rename
This commit is contained in:
parent
1c6ea53050
commit
b20e9b49c0
@ -23,7 +23,7 @@ struct Bytecode{
|
||||
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);
|
||||
return s + std::string(n - s.size(), ' ');
|
||||
}
|
||||
@ -50,27 +50,27 @@ struct CodeBlock {
|
||||
|
||||
struct CodeObject {
|
||||
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->name = name;
|
||||
}
|
||||
|
||||
std::vector<Bytecode> codes;
|
||||
PyVarList consts;
|
||||
std::vector<std::pair<_Str, NameScope>> names;
|
||||
emhash8::HashMap<_Str, int> global_names;
|
||||
pkpy::List consts;
|
||||
std::vector<std::pair<Str, NameScope>> names;
|
||||
emhash8::HashMap<Str, int> global_names;
|
||||
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;
|
||||
labels[label] = codes.size();
|
||||
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;
|
||||
auto p = std::make_pair(name, scope);
|
||||
for(int i=0; i<names.size(); i++){
|
||||
@ -116,16 +116,16 @@ struct Frame {
|
||||
int _ip = -1;
|
||||
int _next_ip = 0;
|
||||
|
||||
const _Code co;
|
||||
const CodeObject_ co;
|
||||
PyVar _module;
|
||||
pkpy::shared_ptr<PyVarDict> _locals;
|
||||
pkpy::shared_ptr<pkpy::NameDict> _locals;
|
||||
const i64 id;
|
||||
std::stack<std::pair<int, std::vector<PyVar>>> s_try_block;
|
||||
|
||||
inline PyVarDict& f_locals() noexcept { return *_locals; }
|
||||
inline PyVarDict& f_globals() noexcept { return _module->attribs; }
|
||||
inline pkpy::NameDict& f_locals() noexcept { return *_locals; }
|
||||
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++) { }
|
||||
|
||||
inline const Bytecode& next_bytecode() {
|
||||
@ -134,12 +134,12 @@ struct Frame {
|
||||
return co->codes[_ip];
|
||||
}
|
||||
|
||||
_Str snapshot(){
|
||||
Str snapshot(){
|
||||
int line = co->codes[_ip].line;
|
||||
return co->src->snapshot(line);
|
||||
}
|
||||
|
||||
_Str stack_info(){
|
||||
Str stack_info(){
|
||||
_StrStream ss;
|
||||
ss << "[";
|
||||
for(int i=0; i<_data.size(); i++){
|
||||
|
@ -19,18 +19,18 @@ enum StringType { NORMAL_STRING, RAW_STRING, F_STRING };
|
||||
|
||||
class Compiler {
|
||||
std::unique_ptr<Parser> parser;
|
||||
std::stack<_Code> codes;
|
||||
std::stack<CodeObject_> codes;
|
||||
bool is_compiling_class = false;
|
||||
int lexing_count = 0;
|
||||
bool used = false;
|
||||
VM* vm;
|
||||
emhash8::HashMap<TokenIndex, GrammarRule> rules;
|
||||
|
||||
_Code co() const{ return codes.top(); }
|
||||
CodeObject_ co() const{ return codes.top(); }
|
||||
CompileMode mode() const{ return parser->src->mode; }
|
||||
|
||||
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->parser = std::make_unique<Parser>(
|
||||
pkpy::make_shared<SourceData>(source, filename, mode)
|
||||
@ -99,7 +99,7 @@ public:
|
||||
}
|
||||
|
||||
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);
|
||||
std::vector<char> buff;
|
||||
while (true) {
|
||||
@ -138,11 +138,11 @@ private:
|
||||
buff.push_back(c);
|
||||
}
|
||||
}
|
||||
return _Str(buff.data(), buff.size());
|
||||
return Str(buff.data(), buff.size());
|
||||
}
|
||||
|
||||
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){
|
||||
parser->set_next_token(TK("@fstr"), vm->PyStr(s));
|
||||
}else{
|
||||
@ -190,7 +190,7 @@ private:
|
||||
parser->prev = parser->curr;
|
||||
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') {
|
||||
parser->token_start = parser->curr_char;
|
||||
@ -357,7 +357,7 @@ private:
|
||||
void exprFString() {
|
||||
static const std::regex pattern(R"(\{(.*?)\})");
|
||||
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 end;
|
||||
int size = 0;
|
||||
@ -384,7 +384,7 @@ private:
|
||||
}
|
||||
|
||||
void exprLambda() {
|
||||
_Func func = pkpy::make_shared<Function>();
|
||||
pkpy::Function_ func = pkpy::make_shared<pkpy::Function>();
|
||||
func->name = "<lambda>";
|
||||
if(!match(TK(":"))){
|
||||
_compile_f_args(func, false);
|
||||
@ -594,7 +594,7 @@ __LISTCOMP:
|
||||
if (peek() == TK(")")) break;
|
||||
if(peek() == TK("@id") && peek_next() == TK("=")) {
|
||||
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)));
|
||||
consume(TK("="));
|
||||
co()->_rvalue=true; EXPR(); co()->_rvalue=false;
|
||||
@ -624,7 +624,7 @@ __LISTCOMP:
|
||||
|
||||
void exprAttrib() {
|
||||
consume(TK("@id"));
|
||||
const _Str& name = parser->prev.str();
|
||||
const Str& name = parser->prev.str();
|
||||
int index = co()->add_name(name, NAME_ATTR);
|
||||
emit(OP_BUILD_ATTR_REF, index);
|
||||
}
|
||||
@ -745,7 +745,7 @@ __LISTCOMP:
|
||||
void parse_expression(Precedence precedence) {
|
||||
lex_token();
|
||||
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)();
|
||||
while (rules[peek()].precedence >= precedence) {
|
||||
lex_token();
|
||||
@ -887,7 +887,7 @@ __LISTCOMP:
|
||||
} else if(match(TK("label"))){
|
||||
if(mode() != EXEC_MODE) SyntaxError("'label' is only available in EXEC_MODE");
|
||||
consume(TK(".")); consume(TK("@id"));
|
||||
_Str label = parser->prev.str();
|
||||
Str label = parser->prev.str();
|
||||
bool ok = co()->add_label(label);
|
||||
if(!ok) SyntaxError("label '" + label + "' already exists");
|
||||
consume_end_stmt();
|
||||
@ -947,7 +947,7 @@ __LISTCOMP:
|
||||
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
|
||||
do {
|
||||
if(state == 3) SyntaxError("**kwargs should be the last argument");
|
||||
@ -961,7 +961,7 @@ __LISTCOMP:
|
||||
}
|
||||
|
||||
consume(TK("@id"));
|
||||
const _Str& name = parser->prev.str();
|
||||
const Str& name = parser->prev.str();
|
||||
if(func->hasName(name)) SyntaxError("duplicate argument name");
|
||||
|
||||
// eat type hints
|
||||
@ -977,7 +977,7 @@ __LISTCOMP:
|
||||
consume(TK("="));
|
||||
PyVarOrNull value = read_literal();
|
||||
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->kwArgsOrder.push_back(name);
|
||||
@ -992,7 +992,7 @@ __LISTCOMP:
|
||||
if(match(TK("pass"))) return;
|
||||
consume(TK("def"));
|
||||
}
|
||||
_Func func = pkpy::make_shared<Function>();
|
||||
pkpy::Function_ func = pkpy::make_shared<pkpy::Function>();
|
||||
consume(TK("@id"));
|
||||
func->name = parser->prev.str();
|
||||
|
||||
@ -1029,7 +1029,7 @@ __LISTCOMP:
|
||||
}
|
||||
|
||||
/***** Error Reporter *****/
|
||||
void throw_err(_Str type, _Str msg){
|
||||
void throw_err(Str type, Str msg){
|
||||
int lineno = parser->curr.line;
|
||||
const char* cursor = parser->curr.start;
|
||||
// if error occurs in lexing, lineno should be `parser->current_line`
|
||||
@ -1038,20 +1038,20 @@ __LISTCOMP:
|
||||
cursor = parser->curr_char;
|
||||
}
|
||||
if(parser->peekchar() == '\n') lineno--;
|
||||
auto e = _Exception("SyntaxError", msg);
|
||||
auto e = pkpy::Exception("SyntaxError", msg);
|
||||
e.st_push(parser->src->snapshot(lineno, cursor));
|
||||
throw e;
|
||||
}
|
||||
void SyntaxError(_Str msg){ throw_err("SyntaxError", msg); }
|
||||
void IndentationError(_Str msg){ throw_err("IndentationError", msg); }
|
||||
void SyntaxError(Str msg){ throw_err("SyntaxError", msg); }
|
||||
void IndentationError(Str msg){ throw_err("IndentationError", msg); }
|
||||
|
||||
public:
|
||||
_Code compile(){
|
||||
CodeObject_ compile(){
|
||||
// can only be called once
|
||||
if(used) UNREACHABLE();
|
||||
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);
|
||||
|
||||
lex_token(); lex_token();
|
||||
|
32
src/error.h
32
src/error.h
@ -20,7 +20,7 @@ enum CompileMode {
|
||||
|
||||
struct SourceData {
|
||||
const char* source;
|
||||
_Str filename;
|
||||
Str filename;
|
||||
std::vector<const char*> line_starts;
|
||||
CompileMode mode;
|
||||
|
||||
@ -34,7 +34,7 @@ struct SourceData {
|
||||
return {_start, i};
|
||||
}
|
||||
|
||||
SourceData(const char* source, _Str filename, CompileMode mode) {
|
||||
SourceData(const char* source, Str filename, CompileMode mode) {
|
||||
source = strdup(source);
|
||||
// Skip utf8 BOM if there is any.
|
||||
if (strncmp(source, "\xEF\xBB\xBF", 3) == 0) source += 3;
|
||||
@ -44,14 +44,14 @@ struct SourceData {
|
||||
this->mode = mode;
|
||||
}
|
||||
|
||||
_Str snapshot(int lineno, const char* cursor=nullptr){
|
||||
Str snapshot(int lineno, const char* cursor=nullptr){
|
||||
_StrStream ss;
|
||||
ss << " " << "File \"" << filename << "\", line " << lineno << '\n';
|
||||
std::pair<const char*,const char*> pair = get_line(lineno);
|
||||
_Str line = "<?>";
|
||||
Str line = "<?>";
|
||||
int removed_spaces = 0;
|
||||
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();
|
||||
if(line.empty()) line = "<?>";
|
||||
}
|
||||
@ -66,26 +66,28 @@ struct SourceData {
|
||||
~SourceData() { free((void*)source); }
|
||||
};
|
||||
|
||||
class _Exception {
|
||||
_Str type;
|
||||
_Str msg;
|
||||
std::stack<_Str> stacktrace;
|
||||
namespace pkpy{
|
||||
class Exception {
|
||||
Str type;
|
||||
Str msg;
|
||||
std::stack<Str> stacktrace;
|
||||
public:
|
||||
_Exception(_Str type, _Str msg): type(type), msg(msg) {}
|
||||
bool match_type(const _Str& type) const { return this->type == type;}
|
||||
Exception(Str type, Str msg): type(type), msg(msg) {}
|
||||
bool match_type(const Str& type) const { return this->type == type;}
|
||||
bool is_re = true;
|
||||
|
||||
void st_push(_Str snapshot){
|
||||
void st_push(Str snapshot){
|
||||
if(stacktrace.size() >= 8) return;
|
||||
stacktrace.push(snapshot);
|
||||
}
|
||||
|
||||
_Str summary() const {
|
||||
std::stack<_Str> st(stacktrace);
|
||||
Str summary() const {
|
||||
std::stack<Str> st(stacktrace);
|
||||
_StrStream ss;
|
||||
if(is_re) ss << "Traceback (most recent call last):\n";
|
||||
while(!st.empty()) { ss << st.top() << '\n'; st.pop(); }
|
||||
ss << type << ": " << msg;
|
||||
return ss.str();
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
@ -4,10 +4,10 @@
|
||||
|
||||
class RangeIter : public BaseIter {
|
||||
i64 current;
|
||||
_Range r;
|
||||
pkpy::Range r;
|
||||
public:
|
||||
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;
|
||||
}
|
||||
|
||||
@ -33,10 +33,10 @@ public:
|
||||
|
||||
class StringIter : public BaseIter {
|
||||
int index = 0;
|
||||
_Str str;
|
||||
Str str;
|
||||
public:
|
||||
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(); }
|
||||
|
45
src/obj.h
45
src/obj.h
@ -7,28 +7,28 @@ struct Frame;
|
||||
struct BaseRef;
|
||||
class VM;
|
||||
|
||||
//typedef PyVar (*_CppFuncRaw)(VM*, const pkpy::Args&);
|
||||
typedef std::function<PyVar(VM*, const pkpy::Args&)> _CppFuncRaw;
|
||||
typedef pkpy::shared_ptr<CodeObject> _Code;
|
||||
typedef std::function<PyVar(VM*, const pkpy::Args&)> NativeFuncRaw;
|
||||
typedef pkpy::shared_ptr<CodeObject> CodeObject_;
|
||||
|
||||
struct _CppFunc {
|
||||
_CppFuncRaw f;
|
||||
namespace pkpy{
|
||||
struct NativeFunc {
|
||||
NativeFuncRaw f;
|
||||
int argc; // DONOT include self
|
||||
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;
|
||||
};
|
||||
|
||||
struct Function {
|
||||
_Str name;
|
||||
_Code code;
|
||||
std::vector<_Str> args;
|
||||
_Str starredArg; // empty if no *arg
|
||||
PyVarDict kwArgs; // empty if no k=v
|
||||
std::vector<_Str> kwArgsOrder;
|
||||
Str name;
|
||||
CodeObject_ code;
|
||||
std::vector<Str> args;
|
||||
Str starredArg; // empty if no *arg
|
||||
pkpy::NameDict kwArgs; // empty if no k=v
|
||||
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 _1 = starredArg == val;
|
||||
bool _2 = kwArgs.find(val) != kwArgs.end();
|
||||
@ -36,18 +36,18 @@ struct Function {
|
||||
}
|
||||
};
|
||||
|
||||
struct _BoundMethod {
|
||||
struct BoundMethod {
|
||||
PyVar obj;
|
||||
PyVar method;
|
||||
};
|
||||
|
||||
struct _Range {
|
||||
struct Range {
|
||||
i64 start = 0;
|
||||
i64 stop = -1;
|
||||
i64 step = 1;
|
||||
};
|
||||
|
||||
struct _Slice {
|
||||
struct Slice {
|
||||
int start = 0;
|
||||
int stop = 0x7fffffff;
|
||||
|
||||
@ -59,6 +59,9 @@ struct _Slice {
|
||||
}
|
||||
};
|
||||
|
||||
typedef shared_ptr<Function> Function_;
|
||||
}
|
||||
|
||||
class BaseIter {
|
||||
protected:
|
||||
VM* vm;
|
||||
@ -71,11 +74,9 @@ public:
|
||||
virtual ~BaseIter() = default;
|
||||
};
|
||||
|
||||
typedef pkpy::shared_ptr<Function> _Func;
|
||||
|
||||
struct PyObject {
|
||||
PyVar type;
|
||||
PyVarDict attribs;
|
||||
pkpy::NameDict attribs;
|
||||
void* _tid;
|
||||
|
||||
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_NAME(obj) OBJ_GET(_Str, (obj)->attribs[__name__])
|
||||
#define OBJ_TP_NAME(obj) OBJ_GET(_Str, (obj)->type->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 PY_CLASS(mod, name) \
|
||||
inline static PyVar _type(VM* vm) { return vm->_modules[#mod]->attribs[#name]; } \
|
||||
inline static const char* _mod() { return #mod; } \
|
||||
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;
|
||||
|
||||
|
@ -53,12 +53,12 @@ struct Token{
|
||||
int line; //< Line number of the token (1 based).
|
||||
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;
|
||||
_Str raw = str();
|
||||
if (raw == _Str("\n")) raw = "\\n";
|
||||
Str raw = str();
|
||||
if (raw == Str("\n")) raw = "\\n";
|
||||
ss << line << ": " << TK_STR(type) << " '" << raw << "'";
|
||||
return ss.str();
|
||||
}
|
||||
|
188
src/pocketpy.h
188
src/pocketpy.h
@ -8,11 +8,11 @@
|
||||
#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; })
|
||||
|
||||
_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);
|
||||
try{
|
||||
return compiler.compile();
|
||||
}catch(_Exception& e){
|
||||
}catch(pkpy::Exception& e){
|
||||
_error(e);
|
||||
return nullptr;
|
||||
}
|
||||
@ -20,7 +20,7 @@ _Code VM::compile(_Str source, _Str filename, CompileMode mode) {
|
||||
|
||||
#define BIND_NUM_ARITH_OPT(name, op) \
|
||||
_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])); \
|
||||
}else{ \
|
||||
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) \
|
||||
_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 _1 = args[1]->is_type(vm->_tp_int) || args[1]->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); \
|
||||
if(!_0 || !_1){ \
|
||||
if constexpr(is_eq) return vm->PyBool(args[0].get() op args[1].get()); \
|
||||
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) {
|
||||
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");
|
||||
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) {
|
||||
_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);
|
||||
});
|
||||
|
||||
_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);
|
||||
return vm->None;
|
||||
});
|
||||
@ -94,7 +94,7 @@ void init_builtins(VM* _vm) {
|
||||
});
|
||||
|
||||
_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");
|
||||
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) {
|
||||
_Str name = vm->PyStr_AS_C(args[1]);
|
||||
Str name = vm->PyStr_AS_C(args[1]);
|
||||
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) {
|
||||
std::vector<_Str> names;
|
||||
std::vector<Str> names;
|
||||
for (auto& [k, _] : args[0]->attribs) names.push_back(k);
|
||||
for (auto& [k, _] : args[0]->type->attribs) {
|
||||
if (k.find("__") == 0) continue;
|
||||
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));
|
||||
std::sort(ret.begin(), ret.end(), [vm](const PyVar& a, const PyVar& 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];
|
||||
std::stringstream ss;
|
||||
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);
|
||||
});
|
||||
|
||||
@ -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>("range", "__new__", [](VM* vm, const pkpy::Args& args) {
|
||||
_Range r;
|
||||
pkpy::Range r;
|
||||
switch (args.size()) {
|
||||
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;
|
||||
@ -173,7 +173,7 @@ void init_builtins(VM* _vm) {
|
||||
});
|
||||
|
||||
_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]))));
|
||||
}else{
|
||||
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 ************/
|
||||
_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_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_str)) {
|
||||
const _Str& s = vm->PyStr_AS_C(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_bool)) return vm->PyInt(vm->PyBool_AS_C(args[0]) ? 1 : 0);
|
||||
if (args[0]->is_type(vm->tp_str)) {
|
||||
const Str& s = vm->PyStr_AS_C(args[0]);
|
||||
try{
|
||||
size_t parsed = 0;
|
||||
i64 val = std::stoll(s, &parsed, 10);
|
||||
@ -235,11 +235,11 @@ void init_builtins(VM* _vm) {
|
||||
|
||||
/************ PyFloat ************/
|
||||
_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_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_str)) {
|
||||
const _Str& s = vm->PyStr_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_bool)) return vm->PyFloat(vm->PyBool_AS_C(args[0]) ? 1.0 : 0.0);
|
||||
if (args[0]->is_type(vm->tp_str)) {
|
||||
const Str& s = vm->PyStr_AS_C(args[0]);
|
||||
if(s == "inf") return vm->PyFloat(INFINITY);
|
||||
if(s == "-inf") return vm->PyFloat(-INFINITY);
|
||||
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_method<1>("str", "__add__", [](VM* vm, const pkpy::Args& args) {
|
||||
const _Str& lhs = vm->PyStr_AS_C(args[0]);
|
||||
const _Str& rhs = vm->PyStr_AS_C(args[1]);
|
||||
const Str& lhs = vm->PyStr_AS_C(args[0]);
|
||||
const Str& rhs = vm->PyStr_AS_C(args[1]);
|
||||
return vm->PyStr(lhs + rhs);
|
||||
});
|
||||
|
||||
_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());
|
||||
});
|
||||
|
||||
_vm->bind_method<1>("str", "__contains__", [](VM* vm, const pkpy::Args& args) {
|
||||
const _Str& _self = vm->PyStr_AS_C(args[0]);
|
||||
const _Str& _other = vm->PyStr_AS_C(args[1]);
|
||||
return vm->PyBool(_self.find(_other) != _Str::npos);
|
||||
const Str& _self = vm->PyStr_AS_C(args[0]);
|
||||
const Str& _other = vm->PyStr_AS_C(args[1]);
|
||||
return vm->PyBool(_self.find(_other) != Str::npos);
|
||||
});
|
||||
|
||||
_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) {
|
||||
const _Str& _self = vm->PyStr_AS_C(args[0]);
|
||||
const Str& _self = vm->PyStr_AS_C(args[0]);
|
||||
return vm->PyStr(_self.escape(true));
|
||||
});
|
||||
|
||||
_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));
|
||||
});
|
||||
|
||||
_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(args[0] == args[1]);
|
||||
});
|
||||
|
||||
_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(args[0] != args[1]);
|
||||
});
|
||||
|
||||
_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)){
|
||||
_Slice s = vm->PySlice_AS_C(args[1]);
|
||||
if(args[1]->is_type(vm->tp_slice)){
|
||||
pkpy::Slice s = vm->PySlice_AS_C(args[1]);
|
||||
s.normalize(_self.u8_length());
|
||||
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) {
|
||||
const _Str& _self (vm->PyStr_AS_C(args[0]));
|
||||
const _Str& _obj (vm->PyStr_AS_C(args[1]));
|
||||
const Str& _self (vm->PyStr_AS_C(args[0]));
|
||||
const Str& _obj (vm->PyStr_AS_C(args[1]));
|
||||
return vm->PyBool(_self > _obj);
|
||||
});
|
||||
|
||||
_vm->bind_method<1>("str", "__lt__", [](VM* vm, const pkpy::Args& args) {
|
||||
const _Str& _self (vm->PyStr_AS_C(args[0]));
|
||||
const _Str& _obj (vm->PyStr_AS_C(args[1]));
|
||||
const Str& _self (vm->PyStr_AS_C(args[0]));
|
||||
const Str& _obj (vm->PyStr_AS_C(args[1]));
|
||||
return vm->PyBool(_self < _obj);
|
||||
});
|
||||
|
||||
_vm->bind_method<2>("str", "replace", [](VM* vm, const pkpy::Args& args) {
|
||||
const _Str& _self = vm->PyStr_AS_C(args[0]);
|
||||
const _Str& _old = vm->PyStr_AS_C(args[1]);
|
||||
const _Str& _new = vm->PyStr_AS_C(args[2]);
|
||||
_Str _copy = _self;
|
||||
const Str& _self = vm->PyStr_AS_C(args[0]);
|
||||
const Str& _old = vm->PyStr_AS_C(args[1]);
|
||||
const Str& _new = vm->PyStr_AS_C(args[2]);
|
||||
Str _copy = _self;
|
||||
// replace all occurences of _old with _new in _copy
|
||||
size_t pos = 0;
|
||||
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) {
|
||||
const _Str& _self = vm->PyStr_AS_C(args[0]);
|
||||
const _Str& _prefix = vm->PyStr_AS_C(args[1]);
|
||||
const Str& _self = vm->PyStr_AS_C(args[0]);
|
||||
const Str& _prefix = vm->PyStr_AS_C(args[1]);
|
||||
return vm->PyBool(_self.find(_prefix) == 0);
|
||||
});
|
||||
|
||||
_vm->bind_method<1>("str", "endswith", [](VM* vm, const pkpy::Args& args) {
|
||||
const _Str& _self = vm->PyStr_AS_C(args[0]);
|
||||
const _Str& _suffix = vm->PyStr_AS_C(args[1]);
|
||||
const Str& _self = vm->PyStr_AS_C(args[0]);
|
||||
const Str& _suffix = vm->PyStr_AS_C(args[1]);
|
||||
return vm->PyBool(_self.rfind(_suffix) == _self.length() - _suffix.length());
|
||||
});
|
||||
|
||||
_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;
|
||||
if(args[1]->is_type(vm->_tp_list)){
|
||||
const PyVarList& a = vm->PyList_AS_C(args[1]);
|
||||
if(args[1]->is_type(vm->tp_list)){
|
||||
const pkpy::List& a = vm->PyList_AS_C(args[1]);
|
||||
for(int i = 0; i < a.size(); i++){
|
||||
if(i > 0) ss << self;
|
||||
ss << vm->PyStr_AS_C(vm->asStr(a[i]));
|
||||
}
|
||||
}else if(args[1]->is_type(vm->_tp_tuple)){
|
||||
const _Tuple& a = vm->PyTuple_AS_C(args[1]);
|
||||
}else if(args[1]->is_type(vm->tp_tuple)){
|
||||
const pkpy::Tuple& a = vm->PyTuple_AS_C(args[1]);
|
||||
for(int i = 0; i < a.size(); i++){
|
||||
if(i > 0) ss << self;
|
||||
ss << vm->PyStr_AS_C(vm->asStr(a[i]));
|
||||
@ -392,13 +392,13 @@ void init_builtins(VM* _vm) {
|
||||
|
||||
/************ PyList ************/
|
||||
_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]);
|
||||
return vm->None;
|
||||
});
|
||||
|
||||
_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]);
|
||||
if(_index < 0) _index += _self.size();
|
||||
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) {
|
||||
const PyVarList& _self = vm->PyList_AS_C(args[0]);
|
||||
const PyVarList& _obj = vm->PyList_AS_C(args[1]);
|
||||
PyVarList _new_list = _self;
|
||||
const pkpy::List& _self = vm->PyList_AS_C(args[0]);
|
||||
const pkpy::List& _obj = vm->PyList_AS_C(args[1]);
|
||||
pkpy::List _new_list = _self;
|
||||
_new_list.insert(_new_list.end(), _obj.begin(), _obj.end());
|
||||
return vm->PyList(_new_list);
|
||||
});
|
||||
|
||||
_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());
|
||||
});
|
||||
|
||||
_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) {
|
||||
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)){
|
||||
_Slice s = vm->PySlice_AS_C(args[1]);
|
||||
if(args[1]->is_type(vm->tp_slice)){
|
||||
pkpy::Slice s = vm->PySlice_AS_C(args[1]);
|
||||
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]);
|
||||
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) {
|
||||
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]);
|
||||
_index = vm->normalized_index(_index, _self.size());
|
||||
_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) {
|
||||
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]);
|
||||
_index = vm->normalized_index(_index, _self.size());
|
||||
_self.erase(_self.begin() + _index);
|
||||
@ -467,7 +467,7 @@ void init_builtins(VM* _vm) {
|
||||
|
||||
/************ PyTuple ************/
|
||||
_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));
|
||||
});
|
||||
|
||||
@ -476,12 +476,12 @@ void init_builtins(VM* _vm) {
|
||||
});
|
||||
|
||||
_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)){
|
||||
_Slice s = vm->PySlice_AS_C(args[1]);
|
||||
if(args[1]->is_type(vm->tp_slice)){
|
||||
pkpy::Slice s = vm->PySlice_AS_C(args[1]);
|
||||
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]);
|
||||
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) {
|
||||
const _Tuple& self = vm->PyTuple_AS_C(args[0]);
|
||||
const pkpy::Tuple& self = vm->PyTuple_AS_C(args[0]);
|
||||
return vm->PyInt(self.size());
|
||||
});
|
||||
|
||||
@ -556,8 +556,8 @@ void add_module_sys(VM* vm){
|
||||
void add_module_json(VM* vm){
|
||||
PyVar mod = vm->new_module("json");
|
||||
vm->bind_func<1>(mod, "loads", [](VM* vm, const pkpy::Args& args) {
|
||||
const _Str& expr = vm->PyStr_AS_C(args[0]);
|
||||
_Code code = vm->compile(expr, "<json>", JSON_MODE);
|
||||
const Str& expr = vm->PyStr_AS_C(args[0]);
|
||||
CodeObject_ code = vm->compile(expr, "<json>", JSON_MODE);
|
||||
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){
|
||||
PyVar mod = vm->new_module("dis");
|
||||
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);
|
||||
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::smatch m;
|
||||
if(std::regex_search(string, m, re)){
|
||||
@ -632,32 +632,32 @@ void add_module_re(VM* vm){
|
||||
vm->register_class<ReMatch>(mod);
|
||||
|
||||
vm->bind_func<2>(mod, "match", [](VM* vm, const pkpy::Args& args) {
|
||||
const _Str& pattern = vm->PyStr_AS_C(args[0]);
|
||||
const _Str& string = vm->PyStr_AS_C(args[1]);
|
||||
const Str& pattern = vm->PyStr_AS_C(args[0]);
|
||||
const Str& string = vm->PyStr_AS_C(args[1]);
|
||||
return _regex_search(pattern, string, true, vm);
|
||||
});
|
||||
|
||||
vm->bind_func<2>(mod, "search", [](VM* vm, const pkpy::Args& args) {
|
||||
const _Str& pattern = vm->PyStr_AS_C(args[0]);
|
||||
const _Str& string = vm->PyStr_AS_C(args[1]);
|
||||
const Str& pattern = vm->PyStr_AS_C(args[0]);
|
||||
const Str& string = vm->PyStr_AS_C(args[1]);
|
||||
return _regex_search(pattern, string, false, vm);
|
||||
});
|
||||
|
||||
vm->bind_func<3>(mod, "sub", [](VM* vm, const pkpy::Args& args) {
|
||||
const _Str& pattern = vm->PyStr_AS_C(args[0]);
|
||||
const _Str& repl = vm->PyStr_AS_C(args[1]);
|
||||
const _Str& string = vm->PyStr_AS_C(args[2]);
|
||||
const Str& pattern = vm->PyStr_AS_C(args[0]);
|
||||
const Str& repl = vm->PyStr_AS_C(args[1]);
|
||||
const Str& string = vm->PyStr_AS_C(args[2]);
|
||||
std::regex re(pattern);
|
||||
return vm->PyStr(std::regex_replace(string, re, repl));
|
||||
});
|
||||
|
||||
vm->bind_func<2>(mod, "split", [](VM* vm, const pkpy::Args& args) {
|
||||
const _Str& pattern = vm->PyStr_AS_C(args[0]);
|
||||
const _Str& string = vm->PyStr_AS_C(args[1]);
|
||||
const Str& pattern = vm->PyStr_AS_C(args[0]);
|
||||
const Str& string = vm->PyStr_AS_C(args[1]);
|
||||
std::regex re(pattern);
|
||||
std::sregex_token_iterator it(string.begin(), string.end(), re, -1);
|
||||
std::sregex_token_iterator end;
|
||||
PyVarList vec;
|
||||
pkpy::List vec;
|
||||
for(; it != end; ++it){
|
||||
vec.push_back(vm->PyStr(it->str()));
|
||||
}
|
||||
@ -725,7 +725,7 @@ extern "C" {
|
||||
auto it = vm->_main->attribs.find(name);
|
||||
if(it == vm->_main->attribs.end()) return nullptr;
|
||||
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());
|
||||
}catch(...){
|
||||
return nullptr;
|
||||
@ -741,7 +741,7 @@ extern "C" {
|
||||
PyVarOrNull ret = vm->exec(source, "<eval>", EVAL_MODE);
|
||||
if(ret == nullptr) return nullptr;
|
||||
try{
|
||||
_Str _repr = vm->PyStr_AS_C(vm->asRepr(ret));
|
||||
Str _repr = vm->PyStr_AS_C(vm->asRepr(ret));
|
||||
return strdup(_repr.c_str());
|
||||
}catch(...){
|
||||
return nullptr;
|
||||
@ -778,8 +778,8 @@ extern "C" {
|
||||
add_module_re(vm);
|
||||
add_module_dis(vm);
|
||||
|
||||
_Code code = vm->compile(kBuiltinsCode, "<builtins>", EXEC_MODE);
|
||||
vm->_exec(code, vm->builtins, pkpy::make_shared<PyVarDict>());
|
||||
CodeObject_ code = vm->compile(kBuiltinsCode, "<builtins>", EXEC_MODE);
|
||||
vm->_exec(code, vm->builtins, pkpy::make_shared<pkpy::NameDict>());
|
||||
|
||||
pkpy_vm_add_module(vm, "random", kRandomCode);
|
||||
return vm;
|
||||
@ -795,8 +795,8 @@ extern "C" {
|
||||
if(vm->use_stdio) return nullptr;
|
||||
_StrStream* s_out = (_StrStream*)(vm->_stdout);
|
||||
_StrStream* s_err = (_StrStream*)(vm->_stderr);
|
||||
_Str _stdout = s_out->str();
|
||||
_Str _stderr = s_err->str();
|
||||
Str _stdout = s_out->str();
|
||||
Str _stderr = s_err->str();
|
||||
_StrStream ss;
|
||||
ss << '{' << "\"stdout\": " << _stdout.escape(false);
|
||||
ss << ", " << "\"stderr\": " << _stderr.escape(false) << '}';
|
||||
|
10
src/ref.h
10
src/ref.h
@ -17,10 +17,10 @@ enum NameScope {
|
||||
};
|
||||
|
||||
struct NameRef : BaseRef {
|
||||
std::pair<_Str, NameScope>* _pair;
|
||||
inline const _Str& name() const { return _pair->first; }
|
||||
std::pair<Str, NameScope>* _pair;
|
||||
inline const Str& name() const { return _pair->first; }
|
||||
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;
|
||||
void set(VM* vm, Frame* frame, PyVar val) const;
|
||||
@ -48,8 +48,8 @@ struct IndexRef : BaseRef {
|
||||
};
|
||||
|
||||
struct TupleRef : BaseRef {
|
||||
_Tuple objs;
|
||||
TupleRef(_Tuple&& objs) : objs(std::move(objs)) {}
|
||||
pkpy::Tuple objs;
|
||||
TupleRef(pkpy::Tuple&& objs) : objs(std::move(objs)) {}
|
||||
|
||||
PyVar get(VM* vm, Frame* frame) const;
|
||||
void set(VM* vm, Frame* frame, PyVar val) const;
|
||||
|
@ -9,7 +9,8 @@ typedef pkpy::shared_ptr<PyObject> PyVar;
|
||||
typedef PyVar PyVarOrNull;
|
||||
typedef PyVar PyVarRef;
|
||||
|
||||
class PyVarList: public std::vector<PyVar> {
|
||||
namespace pkpy{
|
||||
class List: public std::vector<PyVar> {
|
||||
PyVar& at(size_t) = delete;
|
||||
|
||||
inline void _check_index(size_t i) const {
|
||||
@ -32,7 +33,9 @@ public:
|
||||
using std::vector<PyVar>::vector;
|
||||
};
|
||||
|
||||
typedef emhash8::HashMap<_Str, PyVar> PyVarDict;
|
||||
typedef emhash8::HashMap<Str, PyVar> NameDict;
|
||||
|
||||
}
|
||||
|
||||
namespace pkpy {
|
||||
const int kMaxPoolSize = 10;
|
||||
@ -89,7 +92,7 @@ namespace pkpy {
|
||||
other._size = 0;
|
||||
}
|
||||
|
||||
Args(PyVarList&& other) noexcept {
|
||||
Args(pkpy::List&& other) noexcept {
|
||||
_alloc(other.size());
|
||||
for(int i=0; i<_size; i++) _args[i] = std::move(other[i]);
|
||||
other.clear();
|
||||
@ -109,8 +112,8 @@ namespace pkpy {
|
||||
|
||||
inline int size() const { return _size; }
|
||||
|
||||
PyVarList to_list() const {
|
||||
PyVarList ret(_size);
|
||||
pkpy::List to_list() const {
|
||||
pkpy::List ret(_size);
|
||||
for(int i=0; i<_size; i++) ret[i] = _args[i];
|
||||
return ret;
|
||||
}
|
||||
@ -152,6 +155,6 @@ namespace pkpy {
|
||||
ret[1] = std::forward<T2>(b);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
typedef pkpy::Args _Tuple;
|
||||
typedef Args Tuple;
|
||||
}
|
84
src/str.h
84
src/str.h
@ -4,7 +4,7 @@
|
||||
|
||||
typedef std::stringstream _StrStream;
|
||||
|
||||
class _Str : public std::string {
|
||||
class Str : public std::string {
|
||||
mutable std::vector<uint16_t>* _u8_index = nullptr;
|
||||
mutable bool hash_initialized = false;
|
||||
mutable size_t _hash;
|
||||
@ -21,11 +21,11 @@ class _Str : public std::string {
|
||||
}
|
||||
}
|
||||
public:
|
||||
_Str() : std::string() {}
|
||||
_Str(const char* s) : std::string(s) {}
|
||||
_Str(const char* s, size_t n) : std::string(s, n) {}
|
||||
_Str(const std::string& s) : std::string(s) {}
|
||||
_Str(const _Str& s) : std::string(s) {
|
||||
Str() : std::string() {}
|
||||
Str(const char* s) : std::string(s) {}
|
||||
Str(const char* s, size_t n) : std::string(s, n) {}
|
||||
Str(const std::string& s) : std::string(s) {}
|
||||
Str(const Str& s) : std::string(s) {
|
||||
if(s._u8_index != nullptr){
|
||||
_u8_index = new std::vector<uint16_t>(*s._u8_index);
|
||||
}
|
||||
@ -34,7 +34,7 @@ public:
|
||||
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;
|
||||
_u8_index = s._u8_index;
|
||||
s._u8_index = nullptr;
|
||||
@ -64,27 +64,27 @@ public:
|
||||
return _u8_index->size();
|
||||
}
|
||||
|
||||
_Str u8_getitem(int i) const{
|
||||
Str u8_getitem(int i) const{
|
||||
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();
|
||||
if(start >= end) return _Str();
|
||||
if(start >= end) return Str();
|
||||
int c_end = end >= _u8_index->size() ? size() : _u8_index->at(end);
|
||||
return substr(_u8_index->at(start), c_end - _u8_index->at(start));
|
||||
}
|
||||
|
||||
_Str lstrip() const {
|
||||
_Str copy(*this);
|
||||
Str lstrip() const {
|
||||
Str copy(*this);
|
||||
copy.erase(copy.begin(), std::find_if(copy.begin(), copy.end(), [](char c) {
|
||||
// std::isspace(c) does not working on windows (Debug)
|
||||
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;
|
||||
ss << (single_quote ? '\'' : '"');
|
||||
for (int i=0; i<length(); i++) {
|
||||
@ -115,7 +115,7 @@ public:
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
_Str& operator=(const _Str& s){
|
||||
Str& operator=(const Str& s){
|
||||
this->std::string::operator=(s);
|
||||
if(_u8_index != nullptr){
|
||||
delete _u8_index;
|
||||
@ -126,7 +126,7 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
_Str& operator=(_Str&& s){
|
||||
Str& operator=(Str&& s){
|
||||
this->std::string::operator=(std::move(s));
|
||||
if(_u8_index != nullptr) delete _u8_index;
|
||||
this->_u8_index = s._u8_index;
|
||||
@ -136,51 +136,51 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
~_Str(){
|
||||
~Str(){
|
||||
if(_u8_index != nullptr) delete _u8_index;
|
||||
}
|
||||
};
|
||||
|
||||
namespace std {
|
||||
template<>
|
||||
struct hash<_Str> {
|
||||
inline std::size_t operator()(const _Str& s) const {
|
||||
struct hash<Str> {
|
||||
inline std::size_t operator()(const Str& s) const {
|
||||
return s.hash();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const _Str __class__ = _Str("__class__");
|
||||
const _Str __base__ = _Str("__base__");
|
||||
const _Str __new__ = _Str("__new__");
|
||||
const _Str __iter__ = _Str("__iter__");
|
||||
const _Str __str__ = _Str("__str__");
|
||||
const _Str __repr__ = _Str("__repr__");
|
||||
const _Str __module__ = _Str("__module__");
|
||||
const _Str __getitem__ = _Str("__getitem__");
|
||||
const _Str __setitem__ = _Str("__setitem__");
|
||||
const _Str __delitem__ = _Str("__delitem__");
|
||||
const _Str __contains__ = _Str("__contains__");
|
||||
const _Str __init__ = _Str("__init__");
|
||||
const _Str __json__ = _Str("__json__");
|
||||
const _Str __name__ = _Str("__name__");
|
||||
const _Str __len__ = _Str("__len__");
|
||||
const Str __class__ = Str("__class__");
|
||||
const Str __base__ = Str("__base__");
|
||||
const Str __new__ = Str("__new__");
|
||||
const Str __iter__ = Str("__iter__");
|
||||
const Str __str__ = Str("__str__");
|
||||
const Str __repr__ = Str("__repr__");
|
||||
const Str __module__ = Str("__module__");
|
||||
const Str __getitem__ = Str("__getitem__");
|
||||
const Str __setitem__ = Str("__setitem__");
|
||||
const Str __delitem__ = Str("__delitem__");
|
||||
const Str __contains__ = Str("__contains__");
|
||||
const Str __init__ = Str("__init__");
|
||||
const Str __json__ = Str("__json__");
|
||||
const Str __name__ = Str("__name__");
|
||||
const Str __len__ = Str("__len__");
|
||||
|
||||
const _Str m_append = _Str("append");
|
||||
const _Str m_eval = _Str("eval");
|
||||
const _Str m_self = _Str("self");
|
||||
const _Str __enter__ = _Str("__enter__");
|
||||
const _Str __exit__ = _Str("__exit__");
|
||||
const Str m_append = Str("append");
|
||||
const Str m_eval = Str("eval");
|
||||
const Str m_self = Str("self");
|
||||
const Str __enter__ = Str("__enter__");
|
||||
const Str __exit__ = Str("__exit__");
|
||||
|
||||
const _Str CMP_SPECIAL_METHODS[] = {
|
||||
const Str CMP_SPECIAL_METHODS[] = {
|
||||
"__lt__", "__le__", "__eq__", "__ne__", "__gt__", "__ge__"
|
||||
};
|
||||
|
||||
const _Str BINARY_SPECIAL_METHODS[] = {
|
||||
const Str BINARY_SPECIAL_METHODS[] = {
|
||||
"__add__", "__sub__", "__mul__", "__truediv__", "__floordiv__", "__mod__", "__pow__"
|
||||
};
|
||||
|
||||
const _Str BITWISE_SPECIAL_METHODS[] = {
|
||||
const Str BITWISE_SPECIAL_METHODS[] = {
|
||||
"__lshift__", "__rshift__", "__and__", "__or__", "__xor__"
|
||||
};
|
||||
|
||||
|
300
src/vm.h
300
src/vm.h
@ -65,7 +65,7 @@ class VM {
|
||||
pkpy::Args items = frame->pop_n_reversed(byte.arg);
|
||||
bool done = false;
|
||||
for(int i=0; i<items.size(); i++){
|
||||
if(!items[i]->is_type(_tp_ref)) {
|
||||
if(!items[i]->is_type(tp_ref)) {
|
||||
done = true;
|
||||
for(int j=i; j<items.size(); j++) frame->try_deref(this, items[j]);
|
||||
frame->push(PyTuple(std::move(items)));
|
||||
@ -94,21 +94,21 @@ class VM {
|
||||
case OP_STORE_FUNCTION:
|
||||
{
|
||||
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);
|
||||
frame->f_globals()[fn->name] = obj;
|
||||
} break;
|
||||
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);
|
||||
if(clsBase == None) clsBase = _tp_object;
|
||||
check_type(clsBase, _tp_type);
|
||||
if(clsBase == None) clsBase = tp_object;
|
||||
check_type(clsBase, tp_type);
|
||||
PyVar cls = new_type_object(frame->_module, clsName, clsBase);
|
||||
while(true){
|
||||
PyVar fn = frame->pop_value(this);
|
||||
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(cls, f->name, fn);
|
||||
}
|
||||
@ -180,14 +180,14 @@ class VM {
|
||||
case OP_EXCEPTION_MATCH:
|
||||
{
|
||||
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)));
|
||||
} break;
|
||||
case OP_RAISE:
|
||||
{
|
||||
PyVar obj = frame->pop_value(this);
|
||||
_Str msg = obj == None ? "" : PyStr_AS_C(asStr(obj));
|
||||
_Str type = frame->co->names[byte.arg].first;
|
||||
Str msg = obj == None ? "" : PyStr_AS_C(asStr(obj));
|
||||
Str type = frame->co->names[byte.arg].first;
|
||||
_error(type, msg);
|
||||
} 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_SAFE_JUMP_ABSOLUTE: frame->jump_abs_safe(byte.arg); break;
|
||||
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);
|
||||
if(target == nullptr) _error("KeyError", "label '" + label + "' not found");
|
||||
frame->jump_abs_safe(*target);
|
||||
@ -240,7 +240,7 @@ class VM {
|
||||
if(iter_fn != nullptr){
|
||||
PyVar tmp = call(iter_fn);
|
||||
PyVarRef var = frame->pop();
|
||||
check_type(var, _tp_ref);
|
||||
check_type(var, tp_ref);
|
||||
PyIter_AS_C(tmp)->var = var;
|
||||
frame->push(std::move(tmp));
|
||||
}else{
|
||||
@ -284,24 +284,24 @@ class VM {
|
||||
{
|
||||
PyVar stop = frame->pop_value(this);
|
||||
PyVar start = frame->pop_value(this);
|
||||
_Slice s;
|
||||
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);}
|
||||
pkpy::Slice s;
|
||||
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);}
|
||||
frame->push(PySlice(s));
|
||||
} break;
|
||||
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);
|
||||
if(it == _modules.end()){
|
||||
auto it2 = _lazy_modules.find(name);
|
||||
if(it2 == _lazy_modules.end()){
|
||||
_error("ImportError", "module '" + name + "' not found");
|
||||
}else{
|
||||
const _Str& source = it2->second;
|
||||
_Code code = compile(source, name, EXEC_MODE);
|
||||
const Str& source = it2->second;
|
||||
CodeObject_ code = compile(source, name, EXEC_MODE);
|
||||
PyVar _m = new_module(name);
|
||||
_exec(code, _m, pkpy::make_shared<PyVarDict>());
|
||||
_exec(code, _m, pkpy::make_shared<pkpy::NameDict>());
|
||||
frame->push(_m);
|
||||
_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_EXIT: frame->on_try_block_exit(); break;
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -330,9 +330,9 @@ class VM {
|
||||
}
|
||||
|
||||
public:
|
||||
PyVarDict _types;
|
||||
PyVarDict _modules; // loaded modules
|
||||
emhash8::HashMap<_Str, _Str> _lazy_modules; // lazy loaded modules
|
||||
pkpy::NameDict _types;
|
||||
pkpy::NameDict _modules; // loaded modules
|
||||
emhash8::HashMap<Str, Str> _lazy_modules; // lazy loaded modules
|
||||
PyVar None, True, False, Ellipsis;
|
||||
|
||||
bool use_stdio;
|
||||
@ -371,15 +371,15 @@ public:
|
||||
}
|
||||
|
||||
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__);
|
||||
}
|
||||
|
||||
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->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_int)) return PyBool(PyInt_AS_C(obj) != 0);
|
||||
if(obj->is_type(tp_float)) return PyBool(PyFloat_AS_C(obj) != 0.0);
|
||||
PyVarOrNull len_fn = getattr(obj, __len__, false);
|
||||
if(len_fn != nullptr){
|
||||
PyVar ret = call(len_fn);
|
||||
@ -388,7 +388,7 @@ public:
|
||||
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();
|
||||
while(cls != None.get()) {
|
||||
PyVar* val = cls->attribs.try_get(name);
|
||||
@ -411,16 +411,16 @@ public:
|
||||
|
||||
template<typename ArgT>
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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__);
|
||||
PyVar obj;
|
||||
if(it != _callable->attribs.end()){
|
||||
@ -434,20 +434,20 @@ public:
|
||||
}
|
||||
|
||||
const PyVar* callable = &_callable;
|
||||
if((*callable)->is_type(_tp_bound_method)){
|
||||
if((*callable)->is_type(tp_bound_method)){
|
||||
auto& bm = PyBoundMethod_AS_C((*callable));
|
||||
callable = &bm.method; // get unbound method
|
||||
args.extend_self(bm.obj);
|
||||
}
|
||||
|
||||
if((*callable)->is_type(_tp_native_function)){
|
||||
const auto& f = OBJ_GET(_CppFunc, *callable);
|
||||
if((*callable)->is_type(tp_native_function)){
|
||||
const auto& f = OBJ_GET(pkpy::NativeFunc, *callable);
|
||||
if(kwargs.size() != 0) TypeError("native_function does not accept keyword arguments");
|
||||
return f(this, args);
|
||||
} else if((*callable)->is_type(_tp_function)){
|
||||
const _Func& fn = PyFunction_AS_C((*callable));
|
||||
pkpy::shared_ptr<PyVarDict> _locals = pkpy::make_shared<PyVarDict>();
|
||||
PyVarDict& locals = *_locals;
|
||||
} else if((*callable)->is_type(tp_function)){
|
||||
const pkpy::Function_& fn = PyFunction_AS_C((*callable));
|
||||
pkpy::shared_ptr<pkpy::NameDict> _locals = pkpy::make_shared<pkpy::NameDict>();
|
||||
pkpy::NameDict& locals = *_locals;
|
||||
|
||||
int i = 0;
|
||||
for(const auto& name : fn->args){
|
||||
@ -460,9 +460,9 @@ public:
|
||||
|
||||
locals.insert(fn->kwArgs.begin(), fn->kwArgs.end());
|
||||
|
||||
std::vector<_Str> positional_overrided_keys;
|
||||
std::vector<Str> positional_overrided_keys;
|
||||
if(!fn->starredArg.empty()){
|
||||
PyVarList vargs; // handle *args
|
||||
pkpy::List vargs; // handle *args
|
||||
while(i < args.size()) vargs.push_back(args[i++]);
|
||||
locals.emplace(fn->starredArg, PyTuple(std::move(vargs)));
|
||||
}else{
|
||||
@ -478,7 +478,7 @@ public:
|
||||
}
|
||||
|
||||
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)){
|
||||
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
|
||||
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;
|
||||
try {
|
||||
_Code code = compile(source, filename, mode);
|
||||
return _exec(code, _module, pkpy::make_shared<PyVarDict>());
|
||||
}catch (const _Exception& e){
|
||||
CodeObject_ code = compile(source, filename, mode);
|
||||
return _exec(code, _module, pkpy::make_shared<pkpy::NameDict>());
|
||||
}catch (const pkpy::Exception& e){
|
||||
*_stderr << e.summary() << '\n';
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
@ -560,7 +560,7 @@ public:
|
||||
continue;
|
||||
}catch(UnhandledException& e){
|
||||
PyVar obj = frame->pop();
|
||||
_Exception& _e = PyException_AS_C(obj);
|
||||
pkpy::Exception& _e = PyException_AS_C(obj);
|
||||
_e.st_push(frame->snapshot());
|
||||
callstack.pop();
|
||||
if(callstack.empty()) throw _e;
|
||||
@ -574,20 +574,20 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
PyVar new_type_object(PyVar mod, _Str name, PyVar base){
|
||||
if(!base->is_type(_tp_type)) UNREACHABLE();
|
||||
PyVar obj = pkpy::make_shared<PyObject, Py_<Dummy>>(_tp_type, DUMMY_VAL);
|
||||
PyVar new_type_object(PyVar mod, Str name, PyVar base){
|
||||
if(!base->is_type(tp_type)) UNREACHABLE();
|
||||
PyVar obj = pkpy::make_shared<PyObject, Py_<Dummy>>(tp_type, DUMMY_VAL);
|
||||
setattr(obj, __base__, base);
|
||||
_Str fullName = name;
|
||||
Str fullName = name;
|
||||
if(mod != builtins) fullName = OBJ_NAME(mod) + "." + name;
|
||||
setattr(obj, __name__, PyStr(fullName));
|
||||
setattr(mod, name, obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
PyVar _new_type_object(_Str name, PyVar base=nullptr) {
|
||||
if(base == nullptr) base = _tp_object;
|
||||
PyVar obj = pkpy::make_shared<PyObject, Py_<Dummy>>(_tp_type, DUMMY_VAL);
|
||||
PyVar _new_type_object(Str name, PyVar base=nullptr) {
|
||||
if(base == nullptr) base = tp_object;
|
||||
PyVar obj = pkpy::make_shared<PyObject, Py_<Dummy>>(tp_type, DUMMY_VAL);
|
||||
setattr(obj, __base__, base);
|
||||
_types[name] = obj;
|
||||
return obj;
|
||||
@ -595,7 +595,7 @@ public:
|
||||
|
||||
template<typename T>
|
||||
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);
|
||||
std::vector<int*>& pool = _obj_pool[tid<T>()];
|
||||
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)...));
|
||||
}
|
||||
|
||||
PyVar new_module(const _Str& name) {
|
||||
PyVar obj = new_object(_tp_module, DUMMY_VAL);
|
||||
PyVar new_module(const Str& name) {
|
||||
PyVar obj = new_object(tp_module, DUMMY_VAL);
|
||||
setattr(obj, __name__, PyStr(name));
|
||||
_modules[name] = obj;
|
||||
return obj;
|
||||
}
|
||||
|
||||
PyVarOrNull getattr(const PyVar& obj, const _Str& name, bool throw_err=true) {
|
||||
PyVarDict::iterator it;
|
||||
PyVarOrNull getattr(const PyVar& obj, const Str& name, bool throw_err=true) {
|
||||
pkpy::NameDict::iterator it;
|
||||
PyObject* cls;
|
||||
|
||||
if(obj->is_type(_tp_super)){
|
||||
if(obj->is_type(tp_super)){
|
||||
const PyVar* root = &obj;
|
||||
int depth = 1;
|
||||
while(true){
|
||||
root = &OBJ_GET(PyVar, *root);
|
||||
if(!(*root)->is_type(_tp_super)) break;
|
||||
if(!(*root)->is_type(tp_super)) break;
|
||||
depth++;
|
||||
}
|
||||
cls = (*root)->type.get();
|
||||
@ -646,7 +646,7 @@ public:
|
||||
it = cls->attribs.find(name);
|
||||
if(it != cls->attribs.end()){
|
||||
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)});
|
||||
}else{
|
||||
return valueFromCls;
|
||||
@ -659,47 +659,47 @@ public:
|
||||
}
|
||||
|
||||
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();
|
||||
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);
|
||||
}
|
||||
|
||||
template<int ARGC>
|
||||
void bind_method(PyVar obj, _Str funcName, _CppFuncRaw fn) {
|
||||
check_type(obj, _tp_type);
|
||||
setattr(obj, funcName, PyNativeFunction(_CppFunc(fn, ARGC, true)));
|
||||
void bind_method(PyVar obj, Str funcName, NativeFuncRaw fn) {
|
||||
check_type(obj, tp_type);
|
||||
setattr(obj, funcName, PyNativeFunc(pkpy::NativeFunc(fn, ARGC, true)));
|
||||
}
|
||||
|
||||
template<int ARGC>
|
||||
void bind_func(PyVar obj, _Str funcName, _CppFuncRaw fn) {
|
||||
setattr(obj, funcName, PyNativeFunction(_CppFunc(fn, ARGC, false)));
|
||||
void bind_func(PyVar obj, Str funcName, NativeFuncRaw fn) {
|
||||
setattr(obj, funcName, PyNativeFunc(pkpy::NativeFunc(fn, ARGC, false)));
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}else if(obj->is_type(_tp_float)){
|
||||
}else if(obj->is_type(tp_float)){
|
||||
return PyFloat_AS_C(obj);
|
||||
}
|
||||
TypeError("expected 'int' or 'float', got " + OBJ_TP_NAME(obj).escape(true));
|
||||
@ -707,9 +707,9 @@ public:
|
||||
}
|
||||
|
||||
PyVar num_negated(const PyVar& obj){
|
||||
if (obj->is_type(_tp_int)){
|
||||
if (obj->is_type(tp_int)){
|
||||
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));
|
||||
}
|
||||
TypeError("unsupported operand type(s) for -");
|
||||
@ -724,7 +724,7 @@ public:
|
||||
return index;
|
||||
}
|
||||
|
||||
_Str disassemble(_Code co){
|
||||
Str disassemble(CodeObject_ co){
|
||||
std::vector<int> jumpTargets;
|
||||
for(auto byte : co->codes){
|
||||
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;
|
||||
for(int i=0; i<co->codes.size(); 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 = "";
|
||||
else{
|
||||
if(prev_line != -1) ss << "\n";
|
||||
@ -770,7 +770,7 @@ public:
|
||||
|
||||
_StrStream names;
|
||||
names << "co_names: ";
|
||||
PyVarList list;
|
||||
pkpy::List list;
|
||||
for(int i=0; i<co->names.size(); i++){
|
||||
list.push_back(PyStr(co->names[i].first));
|
||||
}
|
||||
@ -779,109 +779,109 @@ public:
|
||||
|
||||
for(int i=0; i<co->consts.size(); 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);
|
||||
ss << disassemble(f->code);
|
||||
}
|
||||
}
|
||||
return _Str(ss.str());
|
||||
return Str(ss.str());
|
||||
}
|
||||
|
||||
// for quick access
|
||||
PyVar _tp_object, _tp_type, _tp_int, _tp_float, _tp_bool, _tp_str;
|
||||
PyVar _tp_list, _tp_tuple;
|
||||
PyVar _tp_function, _tp_native_function, _tp_native_iterator, _tp_bound_method;
|
||||
PyVar _tp_slice, _tp_range, _tp_module, _tp_ref;
|
||||
PyVar _tp_super, _tp_exception;
|
||||
PyVar tp_object, tp_type, tp_int, tp_float, tp_bool, tp_str;
|
||||
PyVar tp_list, tp_tuple;
|
||||
PyVar tp_function, tp_native_function, tp_native_iterator, tp_bound_method;
|
||||
PyVar tp_slice, tp_range, tp_module, tp_ref;
|
||||
PyVar tp_super, tp_exception;
|
||||
|
||||
template<typename P>
|
||||
inline PyVarRef PyRef(P&& value) {
|
||||
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)
|
||||
{
|
||||
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());
|
||||
}
|
||||
|
||||
DEF_NATIVE(Int, i64, _tp_int)
|
||||
DEF_NATIVE(Float, f64, _tp_float)
|
||||
DEF_NATIVE(Str, _Str, _tp_str)
|
||||
DEF_NATIVE(List, PyVarList, _tp_list)
|
||||
DEF_NATIVE(Tuple, _Tuple, _tp_tuple)
|
||||
DEF_NATIVE(Function, _Func, _tp_function)
|
||||
DEF_NATIVE(NativeFunction, _CppFunc, _tp_native_function)
|
||||
DEF_NATIVE(Iter, pkpy::shared_ptr<BaseIter>, _tp_native_iterator)
|
||||
DEF_NATIVE(BoundMethod, _BoundMethod, _tp_bound_method)
|
||||
DEF_NATIVE(Range, _Range, _tp_range)
|
||||
DEF_NATIVE(Slice, _Slice, _tp_slice)
|
||||
DEF_NATIVE(Exception, _Exception, _tp_exception)
|
||||
DEF_NATIVE(Int, i64, tp_int)
|
||||
DEF_NATIVE(Float, f64, tp_float)
|
||||
DEF_NATIVE(Str, Str, tp_str)
|
||||
DEF_NATIVE(List, pkpy::List, tp_list)
|
||||
DEF_NATIVE(Tuple, pkpy::Tuple, tp_tuple)
|
||||
DEF_NATIVE(Function, pkpy::Function_, tp_function)
|
||||
DEF_NATIVE(NativeFunc, pkpy::NativeFunc, tp_native_function)
|
||||
DEF_NATIVE(Iter, pkpy::shared_ptr<BaseIter>, tp_native_iterator)
|
||||
DEF_NATIVE(BoundMethod, pkpy::BoundMethod, tp_bound_method)
|
||||
DEF_NATIVE(Range, pkpy::Range, tp_range)
|
||||
DEF_NATIVE(Slice, pkpy::Slice, tp_slice)
|
||||
DEF_NATIVE(Exception, pkpy::Exception, tp_exception)
|
||||
|
||||
// there is only one True/False, so no need to copy them!
|
||||
inline bool PyBool_AS_C(const PyVar& obj){return obj == True;}
|
||||
inline const PyVar& PyBool(bool value){return value ? True : False;}
|
||||
|
||||
void init_builtin_types(){
|
||||
_tp_object = 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["type"] = _tp_type;
|
||||
tp_object = 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["type"] = tp_type;
|
||||
|
||||
_tp_bool = _new_type_object("bool");
|
||||
_tp_int = _new_type_object("int");
|
||||
_tp_float = _new_type_object("float");
|
||||
_tp_str = _new_type_object("str");
|
||||
_tp_list = _new_type_object("list");
|
||||
_tp_tuple = _new_type_object("tuple");
|
||||
_tp_slice = _new_type_object("slice");
|
||||
_tp_range = _new_type_object("range");
|
||||
_tp_module = _new_type_object("module");
|
||||
_tp_ref = _new_type_object("_ref");
|
||||
tp_bool = _new_type_object("bool");
|
||||
tp_int = _new_type_object("int");
|
||||
tp_float = _new_type_object("float");
|
||||
tp_str = _new_type_object("str");
|
||||
tp_list = _new_type_object("list");
|
||||
tp_tuple = _new_type_object("tuple");
|
||||
tp_slice = _new_type_object("slice");
|
||||
tp_range = _new_type_object("range");
|
||||
tp_module = _new_type_object("module");
|
||||
tp_ref = _new_type_object("_ref");
|
||||
|
||||
_tp_function = _new_type_object("function");
|
||||
_tp_native_function = _new_type_object("native_function");
|
||||
_tp_native_iterator = _new_type_object("native_iterator");
|
||||
_tp_bound_method = _new_type_object("bound_method");
|
||||
_tp_super = _new_type_object("super");
|
||||
_tp_exception = _new_type_object("Exception");
|
||||
tp_function = _new_type_object("function");
|
||||
tp_native_function = _new_type_object("native_function");
|
||||
tp_native_iterator = _new_type_object("native_iterator");
|
||||
tp_bound_method = _new_type_object("bound_method");
|
||||
tp_super = _new_type_object("super");
|
||||
tp_exception = _new_type_object("Exception");
|
||||
|
||||
this->None = new_object(_new_type_object("NoneType"), DUMMY_VAL);
|
||||
this->Ellipsis = new_object(_new_type_object("ellipsis"), DUMMY_VAL);
|
||||
this->True = new_object(_tp_bool, true);
|
||||
this->False = new_object(_tp_bool, false);
|
||||
this->True = new_object(tp_bool, true);
|
||||
this->False = new_object(tp_bool, false);
|
||||
this->builtins = new_module("builtins");
|
||||
this->_main = new_module("__main__");
|
||||
this->_py_op_call = new_object(_new_type_object("_internal"), DUMMY_VAL);
|
||||
|
||||
setattr(_tp_type, __base__, _tp_object);
|
||||
_tp_type->type = _tp_type;
|
||||
setattr(_tp_object, __base__, None);
|
||||
_tp_object->type = _tp_type;
|
||||
setattr(tp_type, __base__, tp_object);
|
||||
tp_type->type = tp_type;
|
||||
setattr(tp_object, __base__, None);
|
||||
tp_object->type = tp_type;
|
||||
|
||||
for (auto& [name, type] : _types) {
|
||||
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) {
|
||||
setattr(builtins, name, _types[name]);
|
||||
}
|
||||
}
|
||||
|
||||
i64 hash(const PyVar& 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_float)){
|
||||
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_float)){
|
||||
f64 val = PyFloat_AS_C(obj);
|
||||
return (i64)std::hash<f64>()(val);
|
||||
}
|
||||
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_tuple)) {
|
||||
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_tuple)) {
|
||||
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++) {
|
||||
i64 y = hash(items[i]);
|
||||
x = x ^ (y + 0x9e3779b9 + (x << 6) + (x >> 2)); // recommended by Github Copilot
|
||||
@ -894,11 +894,11 @@ public:
|
||||
|
||||
/***** Error Reporter *****/
|
||||
private:
|
||||
void _error(const _Str& name, const _Str& msg){
|
||||
_error(_Exception(name, msg));
|
||||
void _error(const Str& name, const Str& msg){
|
||||
_error(pkpy::Exception(name, msg));
|
||||
}
|
||||
|
||||
void _error(_Exception e){
|
||||
void _error(pkpy::Exception e){
|
||||
if(callstack.empty()){
|
||||
e.is_re = false;
|
||||
throw e;
|
||||
@ -915,13 +915,13 @@ private:
|
||||
|
||||
public:
|
||||
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 IndexError(const _Str& msg){ _error("IndexError", msg); }
|
||||
void ValueError(const _Str& msg){ _error("ValueError", msg); }
|
||||
void NameError(const _Str& name){ _error("NameError", "name " + name.escape(true) + " is not defined"); }
|
||||
void IndexError(const Str& msg){ _error("IndexError", msg); }
|
||||
void ValueError(const Str& msg){ _error("ValueError", msg); }
|
||||
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));
|
||||
}
|
||||
|
||||
@ -931,7 +931,7 @@ public:
|
||||
|
||||
template<typename T>
|
||||
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();
|
||||
T::_register(this, mod, 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 *****/
|
||||
@ -1032,7 +1032,7 @@ void IndexRef::del(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++) {
|
||||
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"); \
|
||||
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)){
|
||||
const _Tuple& args = OBJ_GET(_Tuple, val);
|
||||
if(val->is_type(vm->tp_tuple)){
|
||||
const pkpy::Tuple& args = OBJ_GET(pkpy::Tuple, val);
|
||||
TUPLE_REF_SET()
|
||||
}else if(val->is_type(vm->_tp_list)){
|
||||
const PyVarList& args = OBJ_GET(PyVarList, val);
|
||||
}else if(val->is_type(vm->tp_list)){
|
||||
const pkpy::List& args = OBJ_GET(pkpy::List, val);
|
||||
TUPLE_REF_SET()
|
||||
}else{
|
||||
vm->TypeError("only tuple or list can be unpacked");
|
||||
@ -1063,10 +1063,10 @@ void TupleRef::del(VM* vm, Frame* frame) const{
|
||||
|
||||
/***** Frame's Impl *****/
|
||||
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
|
||||
if(argc != -1 && args_size != argc) {
|
||||
vm->TypeError("expected " + std::to_string(argc) + " arguments, but got " + std::to_string(args_size));
|
||||
|
Loading…
x
Reference in New Issue
Block a user