This commit is contained in:
blueloveTH 2023-02-09 13:00:34 +08:00
parent ada630b2db
commit 8c0e7aad45
4 changed files with 85 additions and 85 deletions

View File

@ -42,4 +42,4 @@ typedef double f64;
#define DUMMY_VAL (i64)0 #define DUMMY_VAL (i64)0
#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; })

View File

@ -115,10 +115,10 @@ private:
if(quote3 && parser->src->mode == SINGLE_MODE){ if(quote3 && parser->src->mode == SINGLE_MODE){
throw NeedMoreLines(false); throw NeedMoreLines(false);
} }
syntaxError("EOL while scanning string literal"); SyntaxError("EOL while scanning string literal");
} }
if (c == '\n'){ if (c == '\n'){
if(!quote3) syntaxError("EOL while scanning string literal"); if(!quote3) SyntaxError("EOL while scanning string literal");
else{ else{
buff.push_back(c); buff.push_back(c);
continue; continue;
@ -132,7 +132,7 @@ private:
case 'n': buff.push_back('\n'); break; case 'n': buff.push_back('\n'); break;
case 'r': buff.push_back('\r'); break; case 'r': buff.push_back('\r'); break;
case 't': buff.push_back('\t'); break; case 't': buff.push_back('\t'); break;
default: syntaxError("invalid escape character"); default: SyntaxError("invalid escape character");
} }
} else { } else {
buff.push_back(c); buff.push_back(c);
@ -167,7 +167,7 @@ private:
size_t size; size_t size;
if (m[1].matched) base = 16; if (m[1].matched) base = 16;
if (m[2].matched) { if (m[2].matched) {
if(base == 16) syntaxError("hex literal should not contain a dot"); if(base == 16) SyntaxError("hex literal should not contain a dot");
parser->set_next_token(TK("@num"), vm->PyFloat(std::stod(m[0], &size))); parser->set_next_token(TK("@num"), vm->PyFloat(std::stod(m[0], &size)));
} else { } else {
parser->set_next_token(TK("@num"), vm->PyInt(std::stoll(m[0], &size, base))); parser->set_next_token(TK("@num"), vm->PyInt(std::stoll(m[0], &size, base)));
@ -175,7 +175,7 @@ private:
if (size != m.length()) UNREACHABLE(); if (size != m.length()) UNREACHABLE();
} }
}catch(std::exception& _){ }catch(std::exception& _){
syntaxError("invalid number literal"); SyntaxError("invalid number literal");
} }
} }
@ -217,7 +217,7 @@ private:
if(parser->matchchar('.')) { if(parser->matchchar('.')) {
parser->set_next_token(TK("...")); parser->set_next_token(TK("..."));
} else { } else {
syntaxError("invalid token '..'"); SyntaxError("invalid token '..'");
} }
} else { } else {
parser->set_next_token(TK(".")); parser->set_next_token(TK("."));
@ -246,7 +246,7 @@ private:
} }
case '!': case '!':
if(parser->matchchar('=')) parser->set_next_token(TK("!=")); if(parser->matchchar('=')) parser->set_next_token(TK("!="));
else syntaxError("expected '=' after '!'"); else SyntaxError("expected '=' after '!'");
break; break;
case '*': case '*':
if (parser->matchchar('*')) { if (parser->matchchar('*')) {
@ -266,7 +266,7 @@ private:
case ' ': case '\t': parser->eat_spaces(); break; case ' ': case '\t': parser->eat_spaces(); break;
case '\n': { case '\n': {
parser->set_next_token(TK("@eol")); parser->set_next_token(TK("@eol"));
if(!parser->eat_indentation()) indentationError("unindent does not match any outer indentation level"); if(!parser->eat_indentation()) IndentationError("unindent does not match any outer indentation level");
return; return;
} }
default: { default: {
@ -286,10 +286,10 @@ private:
switch (parser->eat_name()) switch (parser->eat_name())
{ {
case 0: break; case 0: break;
case 1: syntaxError("invalid char: " + std::string(1, c)); case 1: SyntaxError("invalid char: " + std::string(1, c));
case 2: syntaxError("invalid utf8 sequence: " + std::string(1, c)); case 2: SyntaxError("invalid utf8 sequence: " + std::string(1, c));
case 3: syntaxError("@id contains invalid char"); break; case 3: SyntaxError("@id contains invalid char"); break;
case 4: syntaxError("invalid JSON token"); break; case 4: SyntaxError("invalid JSON token"); break;
default: UNREACHABLE(); default: UNREACHABLE();
} }
return; return;
@ -321,7 +321,7 @@ private:
if (!match(expected)){ if (!match(expected)){
_StrStream ss; _StrStream ss;
ss << "expected '" << TK_STR(expected) << "', but got '" << TK_STR(peek()) << "'"; ss << "expected '" << TK_STR(expected) << "', but got '" << TK_STR(peek()) << "'";
syntaxError(ss.str()); SyntaxError(ss.str());
} }
} }
@ -345,7 +345,7 @@ private:
} }
void consume_end_stmt() { void consume_end_stmt() {
if (!match_end_stmt()) syntaxError("expected statement end"); if (!match_end_stmt()) SyntaxError("expected statement end");
} }
void exprLiteral() { void exprLiteral() {
@ -493,7 +493,7 @@ private:
switch (op) { switch (op) {
case TK("-"): emit(OP_UNARY_NEGATIVE); break; case TK("-"): emit(OP_UNARY_NEGATIVE); break;
case TK("not"): emit(OP_UNARY_NOT); break; case TK("not"): emit(OP_UNARY_NOT); break;
case TK("*"): syntaxError("cannot use '*' as unary operator"); break; case TK("*"): SyntaxError("cannot use '*' as unary operator"); break;
default: UNREACHABLE(); default: UNREACHABLE();
} }
} }
@ -598,7 +598,7 @@ __LISTCOMP:
EXPR(); EXPR();
KWARGC++; KWARGC++;
} else{ } else{
if(KWARGC > 0) syntaxError("positional argument follows keyword argument"); if(KWARGC > 0) SyntaxError("positional argument follows keyword argument");
EXPR(); EXPR();
ARGC++; ARGC++;
} }
@ -683,7 +683,7 @@ __LISTCOMP:
if(action == nullptr) action = &Compiler::compile_stmt; if(action == nullptr) action = &Compiler::compile_stmt;
consume(TK(":")); consume(TK(":"));
if(!match_newlines(mode()==SINGLE_MODE)){ if(!match_newlines(mode()==SINGLE_MODE)){
syntaxError("expected a new line after ':'"); SyntaxError("expected a new line after ':'");
} }
consume(TK("@indent")); consume(TK("@indent"));
while (peek() != TK("@dedent")) { while (peek() != TK("@dedent")) {
@ -740,7 +740,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();
@ -830,16 +830,16 @@ __LISTCOMP:
void compile_stmt() { void compile_stmt() {
if (match(TK("break"))) { if (match(TK("break"))) {
if (!co()->_is_curr_block_loop()) syntaxError("'break' outside loop"); if (!co()->_is_curr_block_loop()) SyntaxError("'break' outside loop");
consume_end_stmt(); consume_end_stmt();
emit(OP_LOOP_BREAK); emit(OP_LOOP_BREAK);
} else if (match(TK("continue"))) { } else if (match(TK("continue"))) {
if (!co()->_is_curr_block_loop()) syntaxError("'continue' not properly in loop"); if (!co()->_is_curr_block_loop()) SyntaxError("'continue' not properly in loop");
consume_end_stmt(); consume_end_stmt();
emit(OP_LOOP_CONTINUE); emit(OP_LOOP_CONTINUE);
} else if (match(TK("return"))) { } else if (match(TK("return"))) {
if (codes.size() == 1) if (codes.size() == 1)
syntaxError("'return' outside function"); SyntaxError("'return' outside function");
if(match_end_stmt()){ if(match_end_stmt()){
emit(OP_LOAD_NONE); emit(OP_LOAD_NONE);
}else{ }else{
@ -875,14 +875,14 @@ __LISTCOMP:
emit(OP_LOAD_NAME_REF, index); emit(OP_LOAD_NAME_REF, index);
emit(OP_WITH_EXIT); emit(OP_WITH_EXIT);
} 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();
} else if(match(TK("goto"))){ // https://entrian.com/goto/ } else if(match(TK("goto"))){ // https://entrian.com/goto/
if(mode() != EXEC_MODE) syntaxError("'goto' is only available in EXEC_MODE"); if(mode() != EXEC_MODE) SyntaxError("'goto' is only available in EXEC_MODE");
consume(TK(".")); consume(TK("@id")); consume(TK(".")); consume(TK("@id"));
emit(OP_GOTO, co()->add_name(parser->prev.str(), NAME_SPECIAL)); emit(OP_GOTO, co()->add_name(parser->prev.str(), NAME_SPECIAL));
consume_end_stmt(); consume_end_stmt();
@ -940,11 +940,11 @@ __LISTCOMP:
void _compile_f_args(_Func func, bool enable_type_hints){ void _compile_f_args(_Func 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");
match_newlines(); match_newlines();
if(match(TK("*"))){ if(match(TK("*"))){
if(state < 1) state = 1; if(state < 1) state = 1;
else syntaxError("*args should be placed before **kwargs"); else SyntaxError("*args should be placed before **kwargs");
} }
else if(match(TK("**"))){ else if(match(TK("**"))){
state = 3; state = 3;
@ -952,7 +952,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
if(enable_type_hints && match(TK(":"))) consume(TK("@id")); if(enable_type_hints && match(TK(":"))) consume(TK("@id"));
@ -967,12 +967,12 @@ __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);
} break; } break;
case 3: syntaxError("**kwargs is not supported yet"); break; case 3: SyntaxError("**kwargs is not supported yet"); break;
} }
} while (match(TK(","))); } while (match(TK(",")));
} }
@ -1032,8 +1032,8 @@ __LISTCOMP:
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(){ _Code compile(){
@ -1057,7 +1057,7 @@ public:
if(value != nullptr) emit(OP_LOAD_CONST, code->add_const(value)); if(value != nullptr) emit(OP_LOAD_CONST, code->add_const(value));
else if(match(TK("{"))) exprMap(); else if(match(TK("{"))) exprMap();
else if(match(TK("["))) exprList(); else if(match(TK("["))) exprList();
else syntaxError("expect a JSON object or array"); else SyntaxError("expect a JSON object or array");
consume(TK("@eof")); consume(TK("@eof"));
return code; // no need to optimize for JSON decoding return code; // no need to optimize for JSON decoding
} }

View File

@ -29,7 +29,7 @@ _Code VM::compile(_Str source, _Str filename, CompileMode mode) {
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 ); \
} \ } \
return vm->PyBool(vm->num_to_float(args[0]) op vm->num_to_float(args[1])); \ return vm->PyBool(vm->num_to_float(args[0]) op vm->num_to_float(args[1])); \
}); });
@ -57,7 +57,7 @@ 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);
}); });
@ -75,7 +75,7 @@ void init_builtins(VM* _vm) {
_vm->bind_builtin_func<-1>("exit", [](VM* vm, const pkpy::Args& args) { _vm->bind_builtin_func<-1>("exit", [](VM* vm, const pkpy::Args& args) {
if(args.size() == 0) std::exit(0); if(args.size() == 0) std::exit(0);
else if(args.size() == 1) std::exit((int)vm->PyInt_AS_C(args[0])); else if(args.size() == 1) std::exit((int)vm->PyInt_AS_C(args[0]));
else vm->typeError("exit() takes at most 1 argument"); else vm->TypeError("exit() takes at most 1 argument");
return vm->None; return vm->None;
}); });
@ -85,13 +85,13 @@ void init_builtins(VM* _vm) {
_vm->bind_builtin_func<1>("chr", [](VM* vm, const pkpy::Args& args) { _vm->bind_builtin_func<1>("chr", [](VM* vm, const pkpy::Args& args) {
i64 i = vm->PyInt_AS_C(args[0]); i64 i = vm->PyInt_AS_C(args[0]);
if (i < 0 || i > 128) vm->valueError("chr() arg not in range(128)"); if (i < 0 || i > 128) vm->ValueError("chr() arg not in range(128)");
return vm->PyStr(std::string(1, (char)i)); return vm->PyStr(std::string(1, (char)i));
}); });
_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]));
}); });
@ -150,7 +150,7 @@ void init_builtins(VM* _vm) {
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;
case 3: r.start = vm->PyInt_AS_C(args[0]); r.stop = vm->PyInt_AS_C(args[1]); r.step = vm->PyInt_AS_C(args[2]); break; case 3: r.start = vm->PyInt_AS_C(args[0]); r.stop = vm->PyInt_AS_C(args[1]); r.step = vm->PyInt_AS_C(args[2]); break;
default: vm->typeError("expected 1-3 arguments, but got " + std::to_string(args.size())); default: vm->TypeError("expected 1-3 arguments, but got " + std::to_string(args.size()));
} }
return vm->PyRange(r); return vm->PyRange(r);
}); });
@ -164,7 +164,7 @@ void init_builtins(VM* _vm) {
_vm->_bind_methods<1>({"int", "float"}, "__truediv__", [](VM* vm, const pkpy::Args& args) { _vm->_bind_methods<1>({"int", "float"}, "__truediv__", [](VM* vm, const pkpy::Args& args) {
f64 rhs = vm->num_to_float(args[1]); f64 rhs = vm->num_to_float(args[1]);
if (rhs == 0) vm->zeroDivisionError(); if (rhs == 0) vm->ZeroDivisionError();
return vm->PyFloat(vm->num_to_float(args[0]) / rhs); return vm->PyFloat(vm->num_to_float(args[0]) / rhs);
}); });
@ -189,22 +189,22 @@ void init_builtins(VM* _vm) {
if(parsed != s.size()) throw std::invalid_argument(""); if(parsed != s.size()) throw std::invalid_argument("");
return vm->PyInt(val); return vm->PyInt(val);
}catch(std::invalid_argument&){ }catch(std::invalid_argument&){
vm->valueError("invalid literal for int(): '" + s + "'"); vm->ValueError("invalid literal for int(): '" + s + "'");
} }
} }
vm->typeError("int() argument must be a int, float, bool or str"); vm->TypeError("int() argument must be a int, float, bool or str");
return vm->None; return vm->None;
}); });
_vm->bind_method<1>("int", "__floordiv__", [](VM* vm, const pkpy::Args& args) { _vm->bind_method<1>("int", "__floordiv__", [](VM* vm, const pkpy::Args& args) {
i64 rhs = vm->PyInt_AS_C(args[1]); i64 rhs = vm->PyInt_AS_C(args[1]);
if(rhs == 0) vm->zeroDivisionError(); if(rhs == 0) vm->ZeroDivisionError();
return vm->PyInt(vm->PyInt_AS_C(args[0]) / rhs); return vm->PyInt(vm->PyInt_AS_C(args[0]) / rhs);
}); });
_vm->bind_method<1>("int", "__mod__", [](VM* vm, const pkpy::Args& args) { _vm->bind_method<1>("int", "__mod__", [](VM* vm, const pkpy::Args& args) {
i64 rhs = vm->PyInt_AS_C(args[1]); i64 rhs = vm->PyInt_AS_C(args[1]);
if(rhs == 0) vm->zeroDivisionError(); if(rhs == 0) vm->ZeroDivisionError();
return vm->PyInt(vm->PyInt_AS_C(args[0]) % rhs); return vm->PyInt(vm->PyInt_AS_C(args[0]) % rhs);
}); });
@ -242,10 +242,10 @@ void init_builtins(VM* _vm) {
f64 val = std::stod(s); f64 val = std::stod(s);
return vm->PyFloat(val); return vm->PyFloat(val);
}catch(std::invalid_argument&){ }catch(std::invalid_argument&){
vm->valueError("invalid literal for float(): '" + s + "'"); vm->ValueError("invalid literal for float(): '" + s + "'");
} }
} }
vm->typeError("float() argument must be a int, float, bool or str"); vm->TypeError("float() argument must be a int, float, bool or str");
return vm->None; return vm->None;
}); });
@ -261,7 +261,7 @@ void init_builtins(VM* _vm) {
_vm->bind_method<0>("float", "__json__", [](VM* vm, const pkpy::Args& args) { _vm->bind_method<0>("float", "__json__", [](VM* vm, const pkpy::Args& args) {
f64 val = vm->PyFloat_AS_C(args[0]); f64 val = vm->PyFloat_AS_C(args[0]);
if(std::isinf(val) || std::isnan(val)) vm->valueError("cannot jsonify 'nan' or 'inf'"); if(std::isinf(val) || std::isnan(val)) vm->ValueError("cannot jsonify 'nan' or 'inf'");
return vm->PyStr(std::to_string(val)); return vm->PyStr(std::to_string(val));
}); });
@ -373,7 +373,7 @@ void init_builtins(VM* _vm) {
}else if(args[1]->is_type(vm->_tp_tuple)){ }else if(args[1]->is_type(vm->_tp_tuple)){
_list = &vm->PyTuple_AS_C(args[1]); _list = &vm->PyTuple_AS_C(args[1]);
}else{ }else{
vm->typeError("can only join a list or tuple"); vm->TypeError("can only join a list or tuple");
} }
_StrStream ss; _StrStream ss;
for(int i = 0; i < _list->size(); i++){ for(int i = 0; i < _list->size(); i++){

View File

@ -23,7 +23,7 @@
class VM { class VM {
std::vector<PyVar> _small_integers; // [-5, 256] std::vector<PyVar> _small_integers; // [-5, 256]
std::stack< std::unique_ptr<Frame> > callstack; std::stack< std::unique_ptr<Frame> > callstack;
PyVar __py2py_call_signal; PyVar _py_op_call;
PyVar run_frame(Frame* frame){ PyVar run_frame(Frame* frame){
while(frame->has_next_bytecode()){ while(frame->has_next_bytecode()){
@ -232,7 +232,7 @@ class VM {
pkpy::Args args = frame->pop_n_values_reversed(this, ARGC); pkpy::Args args = frame->pop_n_values_reversed(this, ARGC);
PyVar callable = frame->pop_value(this); PyVar callable = frame->pop_value(this);
PyVar ret = call(callable, std::move(args), kwargs, true); PyVar ret = call(callable, std::move(args), kwargs, true);
if(ret == __py2py_call_signal) return ret; if(ret == _py_op_call) return ret;
frame->push(std::move(ret)); frame->push(std::move(ret));
} break; } break;
case OP_JUMP_ABSOLUTE: frame->jump_abs(byte.arg); break; case OP_JUMP_ABSOLUTE: frame->jump_abs(byte.arg); break;
@ -254,7 +254,7 @@ class VM {
PyIter_AS_C(tmp)->var = var; PyIter_AS_C(tmp)->var = var;
frame->push(std::move(tmp)); frame->push(std::move(tmp));
}else{ }else{
typeError("'" + OBJ_TP_NAME(obj) + "' object is not iterable"); TypeError("'" + OBJ_TP_NAME(obj) + "' object is not iterable");
} }
} break; } break;
case OP_FOR_ITER: case OP_FOR_ITER:
@ -407,7 +407,7 @@ public:
if(val != nullptr) return call(*val, std::move(args)); if(val != nullptr) return call(*val, std::move(args));
cls = cls->attribs[__base__].get(); cls = cls->attribs[__base__].get();
} }
attributeError(args[0], name); AttributeError(args[0], name);
return nullptr; return nullptr;
} }
@ -454,7 +454,7 @@ public:
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(_CppFunc, *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 _Func& fn = PyFunction_AS_C((*callable));
@ -467,7 +467,7 @@ public:
locals.emplace(name, args[i++]); locals.emplace(name, args[i++]);
continue; continue;
} }
typeError("missing positional argument '" + name + "'"); TypeError("missing positional argument '" + name + "'");
} }
locals.insert(fn->kwArgs.begin(), fn->kwArgs.end()); locals.insert(fn->kwArgs.begin(), fn->kwArgs.end());
@ -487,19 +487,19 @@ public:
break; break;
} }
} }
if(i < args.size()) typeError("too many arguments"); if(i < args.size()) TypeError("too many arguments");
} }
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 + "()");
} }
const PyVar& val = kwargs[i+1]; const PyVar& val = kwargs[i+1];
if(!positional_overrided_keys.empty()){ if(!positional_overrided_keys.empty()){
auto it = std::find(positional_overrided_keys.begin(), positional_overrided_keys.end(), key); auto it = std::find(positional_overrided_keys.begin(), positional_overrided_keys.end(), key);
if(it != positional_overrided_keys.end()){ if(it != positional_overrided_keys.end()){
typeError("multiple values for argument '" + key + "'"); TypeError("multiple values for argument '" + key + "'");
} }
} }
locals[key] = val; locals[key] = val;
@ -509,11 +509,11 @@ public:
PyVar _module = it_m != nullptr ? *it_m : top_frame()->_module; PyVar _module = it_m != nullptr ? *it_m : top_frame()->_module;
if(opCall){ if(opCall){
__new_frame(fn->code, _module, _locals); __new_frame(fn->code, _module, _locals);
return __py2py_call_signal; return _py_op_call;
} }
return _exec(fn->code, _module, _locals); return _exec(fn->code, _module, _locals);
} }
typeError("'" + OBJ_TP_NAME(*callable) + "' object is not callable"); TypeError("'" + OBJ_TP_NAME(*callable) + "' object is not callable");
return None; return None;
} }
@ -557,7 +557,7 @@ public:
if(need_raise){ need_raise = false; _raise(); } if(need_raise){ need_raise = false; _raise(); }
ret = run_frame(frame); ret = run_frame(frame);
if(ret != __py2py_call_signal){ if(ret != _py_op_call){
if(frame->id == base_id){ // [ frameBase<- ] if(frame->id == base_id){ // [ frameBase<- ]
callstack.pop(); callstack.pop();
return ret; return ret;
@ -659,7 +659,7 @@ public:
} }
cls = cls->attribs[__base__].get(); cls = cls->attribs[__base__].get();
} }
if(throw_err) attributeError(obj, name); if(throw_err) AttributeError(obj, name);
return nullptr; return nullptr;
} }
@ -707,7 +707,7 @@ public:
}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)); TypeError("expected int or float, got " + OBJ_TP_NAME(obj));
return 0; return 0;
} }
@ -717,14 +717,14 @@ public:
}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 -");
return nullptr; return nullptr;
} }
int normalized_index(int index, int size){ int normalized_index(int index, int size){
if(index < 0) index += size; if(index < 0) index += size;
if(index < 0 || index >= size){ if(index < 0 || index >= size){
indexError(std::to_string(index) + " not in [0, " + std::to_string(size) + ")"); IndexError(std::to_string(index) + " not in [0, " + std::to_string(size) + ")");
} }
return index; return index;
} }
@ -807,7 +807,7 @@ public:
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());
} }
@ -851,8 +851,8 @@ public:
_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");
@ -863,7 +863,7 @@ public:
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->__py2py_call_signal = new_object(new_type_object("_signal"), 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;
@ -897,7 +897,7 @@ public:
} }
return x; return x;
} }
typeError("unhashable type: " + OBJ_TP_NAME(obj)); TypeError("unhashable type: " + OBJ_TP_NAME(obj));
return 0; return 0;
} }
@ -923,19 +923,19 @@ 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 + "' is not defined"); } void NameError(const _Str& name){ _error("NameError", "name '" + name + "' is not defined"); }
void attributeError(PyVar obj, const _Str& name){ void AttributeError(PyVar obj, const _Str& name){
_error("AttributeError", "type '" + OBJ_TP_NAME(obj) + "' has no attribute '" + name + "'"); _error("AttributeError", "type '" + OBJ_TP_NAME(obj) + "' has no attribute '" + name + "'");
} }
inline void check_type(const PyVar& obj, const PyVar& type){ inline void check_type(const PyVar& obj, const PyVar& type){
if(!obj->is_type(type)) typeError("expected '" + OBJ_NAME(type) + "', but got '" + OBJ_TP_NAME(obj) + "'"); if(!obj->is_type(type)) TypeError("expected '" + OBJ_NAME(type) + "', but got '" + OBJ_TP_NAME(obj) + "'");
} }
template<typename T> template<typename T>
@ -971,7 +971,7 @@ PyVar NameRef::get(VM* vm, Frame* frame) const{
if(val) return *val; if(val) return *val;
val = vm->builtins->attribs.try_get(pair->first); val = vm->builtins->attribs.try_get(pair->first);
if(val) return *val; if(val) return *val;
vm->nameError(pair->first); vm->NameError(pair->first);
return nullptr; return nullptr;
} }
@ -997,7 +997,7 @@ void NameRef::del(VM* vm, Frame* frame) const{
if(frame->f_locals().contains(pair->first)){ if(frame->f_locals().contains(pair->first)){
frame->f_locals().erase(pair->first); frame->f_locals().erase(pair->first);
}else{ }else{
vm->nameError(pair->first); vm->NameError(pair->first);
} }
} break; } break;
case NAME_GLOBAL: case NAME_GLOBAL:
@ -1008,7 +1008,7 @@ void NameRef::del(VM* vm, Frame* frame) const{
if(frame->f_globals().contains(pair->first)){ if(frame->f_globals().contains(pair->first)){
frame->f_globals().erase(pair->first); frame->f_globals().erase(pair->first);
}else{ }else{
vm->nameError(pair->first); vm->NameError(pair->first);
} }
} }
} break; } break;
@ -1025,7 +1025,7 @@ void AttrRef::set(VM* vm, Frame* frame, PyVar val) const{
} }
void AttrRef::del(VM* vm, Frame* frame) const{ void AttrRef::del(VM* vm, Frame* frame) const{
vm->typeError("cannot delete attribute"); vm->TypeError("cannot delete attribute");
} }
PyVar IndexRef::get(VM* vm, Frame* frame) const{ PyVar IndexRef::get(VM* vm, Frame* frame) const{
@ -1050,11 +1050,11 @@ PyVar TupleRef::get(VM* vm, Frame* frame) const{
void TupleRef::set(VM* vm, Frame* frame, PyVar val) const{ void TupleRef::set(VM* vm, Frame* frame, PyVar val) const{
if(!val->is_type(vm->_tp_tuple) && !val->is_type(vm->_tp_list)){ if(!val->is_type(vm->_tp_tuple) && !val->is_type(vm->_tp_list)){
vm->typeError("only tuple or list can be unpacked"); vm->TypeError("only tuple or list can be unpacked");
} }
const PyVarList& args = OBJ_GET(PyVarList, val); const PyVarList& args = OBJ_GET(PyVarList, val);
if(args.size() > varRefs.size()) vm->valueError("too many values to unpack"); if(args.size() > varRefs.size()) vm->ValueError("too many values to unpack");
if(args.size() < varRefs.size()) vm->valueError("not enough values to unpack"); if(args.size() < varRefs.size()) vm->ValueError("not enough values to unpack");
for (int i = 0; i < varRefs.size(); i++) { for (int i = 0; i < varRefs.size(); i++) {
vm->PyRef_AS_C(varRefs[i])->set(vm, frame, args[i]); vm->PyRef_AS_C(varRefs[i])->set(vm, frame, args[i]);
} }
@ -1083,7 +1083,7 @@ PyVar StringIterator::next(){
PyVar _CppFunc::operator()(VM* vm, const pkpy::Args& args) const{ PyVar _CppFunc::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));
} }
return f(vm, args); return f(vm, args);
} }