mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 03:20:18 +00:00
adjust errors
This commit is contained in:
parent
01bbda85ec
commit
5c7f1e6dd8
@ -593,6 +593,7 @@ __LISTCOMP:
|
||||
}
|
||||
consume(TK("@indent"));
|
||||
while (peek() != TK("@dedent")) {
|
||||
matchNewLines();
|
||||
(this->*action)();
|
||||
matchNewLines();
|
||||
}
|
||||
@ -624,17 +625,13 @@ __LISTCOMP:
|
||||
void parsePrecedence(Precedence precedence) {
|
||||
lexToken();
|
||||
GrammarFn prefix = rules[parser->previous.type].prefix;
|
||||
|
||||
if (prefix == nullptr) syntaxError("expected an expression");
|
||||
|
||||
if (prefix == nullptr) syntaxError(_Str("expected an expression, but got ") + TK_STR(parser->previous.type));
|
||||
(this->*prefix)();
|
||||
while (rules[peek()].precedence >= precedence) {
|
||||
lexToken();
|
||||
_TokenType op = parser->previous.type;
|
||||
GrammarFn infix = rules[op].infix;
|
||||
if(infix == nullptr) {
|
||||
throw UnexpectedError("(infix == nullptr) is true");
|
||||
}
|
||||
if(infix == nullptr) throw UnexpectedError("(infix == nullptr) is true");
|
||||
(this->*infix)();
|
||||
}
|
||||
}
|
||||
@ -874,23 +871,18 @@ __LITERAL_EXIT:
|
||||
}
|
||||
}
|
||||
|
||||
/**** Error Reporter ***/
|
||||
/***** Error Reporter *****/
|
||||
LineSnapshot getLineSnapshot(){
|
||||
LineSnapshot snapshot;
|
||||
snapshot.filename = path;
|
||||
snapshot.lineno = parser->previous.line;
|
||||
snapshot.source = "<?>";
|
||||
return snapshot;
|
||||
const char* line_start = parser->line_starts.at(parser->previous.line-1);
|
||||
const char* i = line_start;
|
||||
while(*i != '\n' && *i != '\0') i++;
|
||||
return LineSnapshot(path, parser->previous.line, _Str(line_start, i-line_start));
|
||||
}
|
||||
|
||||
void syntaxError(_Str msg){
|
||||
throw CompileError("SyntaxError", msg, getLineSnapshot());
|
||||
}
|
||||
|
||||
void unknownSyntaxError(){
|
||||
throw CompileError("SyntaxError", "invalid syntax", getLineSnapshot());
|
||||
}
|
||||
|
||||
void indentationError(_Str msg){
|
||||
throw CompileError("IndentationError", msg, getLineSnapshot());
|
||||
}
|
||||
|
@ -25,10 +25,12 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
struct LineSnapshot {
|
||||
class LineSnapshot {
|
||||
_Str filename;
|
||||
int lineno;
|
||||
_Str source;
|
||||
public:
|
||||
LineSnapshot(_Str filename, int lineno, _Str source="<?>") : filename(filename), lineno(lineno), source(source) {}
|
||||
|
||||
_Str str() const {
|
||||
_StrStream ss;
|
||||
|
@ -48,7 +48,7 @@ void REPL(){
|
||||
|
||||
while(true){
|
||||
CompileMode mode = SINGLE_MODE;
|
||||
vm->printFn(need_more_lines ? "... " : ">>> ");
|
||||
vm->_stdout(need_more_lines ? "... " : ">>> ");
|
||||
std::string line;
|
||||
std::getline(std::cin, line);
|
||||
|
||||
@ -86,8 +86,8 @@ __NOT_ENOUGH_LINES:
|
||||
buffer += '\n';
|
||||
need_more_lines = ne->isClassDef ? 3 : 2;
|
||||
}else{
|
||||
vm->printFn(e.what());
|
||||
vm->printFn("\n");
|
||||
vm->_stdout(e.what());
|
||||
vm->_stdout("\n");
|
||||
vm->cleanError();
|
||||
}
|
||||
}
|
||||
|
@ -87,10 +87,11 @@ struct Parser {
|
||||
const char* source; //< Currently compiled source.
|
||||
const char* token_start; //< Start of the currently parsed token.
|
||||
const char* current_char; //< Current char position in the source.
|
||||
const char* line_start; //< Start of the current line.
|
||||
|
||||
int current_line = 1;
|
||||
|
||||
std::vector<const char*> line_starts;
|
||||
|
||||
Token previous, current;
|
||||
std::queue<Token> nexts;
|
||||
|
||||
@ -159,7 +160,7 @@ struct Parser {
|
||||
current_char++;
|
||||
if (c == '\n'){
|
||||
current_line++;
|
||||
line_start = current_char;
|
||||
line_starts.push_back(current_char);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
@ -235,8 +236,7 @@ struct Parser {
|
||||
this->source = source;
|
||||
this->token_start = source;
|
||||
this->current_char = source;
|
||||
this->line_start = source;
|
||||
|
||||
this->line_starts.push_back(source);
|
||||
this->nexts.push(Token{TK("@sof"), token_start, 0, current_line});
|
||||
this->indents.push(0);
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ inline int _round(float f){
|
||||
#define BIND_NUM_ARITH_OPT(name, op) \
|
||||
_vm->bindMethodMulti({"int","float"}, #name, [](VM* vm, PyVarList args){ \
|
||||
if(!vm->isIntOrFloat(args[0], args[1])) \
|
||||
vm->_error("TypeError", "unsupported operand type(s) for " #op ); \
|
||||
vm->typeError("unsupported operand type(s) for " #op ); \
|
||||
if(args[0]->isType(vm->_tp_int) && args[1]->isType(vm->_tp_int)){ \
|
||||
return vm->PyInt(vm->PyInt_AS_C(args[0]) op vm->PyInt_AS_C(args[1])); \
|
||||
}else{ \
|
||||
@ -23,7 +23,7 @@ inline int _round(float f){
|
||||
_vm->bindMethodMulti({"int","float"}, #name, [](VM* vm, PyVarList args){ \
|
||||
if(!vm->isIntOrFloat(args[0], args[1])){ \
|
||||
if constexpr(fallback) return vm->PyBool(args[0] op args[1]); \
|
||||
vm->_error("TypeError", "unsupported operand type(s) for " #op ); \
|
||||
vm->typeError("unsupported operand type(s) for " #op ); \
|
||||
} \
|
||||
return vm->PyBool(vm->numToFloat(args[0]) op vm->numToFloat(args[1])); \
|
||||
});
|
||||
@ -44,14 +44,14 @@ void __initializeBuiltinFunctions(VM* _vm) {
|
||||
#undef BIND_NUM_LOGICAL_OPT
|
||||
|
||||
_vm->bindBuiltinFunc("print", [](VM* vm, PyVarList args) {
|
||||
for (auto& arg : args) vm->printFn(vm->PyStr_AS_C(vm->asStr(arg)) + " ");
|
||||
vm->printFn("\n");
|
||||
for (auto& arg : args) vm->_stdout(vm->PyStr_AS_C(vm->asStr(arg)) + " ");
|
||||
vm->_stdout("\n");
|
||||
return vm->None;
|
||||
});
|
||||
|
||||
_vm->bindBuiltinFunc("eval", [](VM* vm, PyVarList args) {
|
||||
if (args.size() != 1) vm->_error("TypeError", "eval() takes exactly one argument");
|
||||
if (!args[0]->isType(vm->_tp_str)) vm->_error("TypeError", "eval() argument must be a string");
|
||||
if (args.size() != 1) vm->typeError("eval() takes exactly one argument");
|
||||
if (!args[0]->isType(vm->_tp_str)) vm->typeError("eval() argument must be a string");
|
||||
const _Str& expr = vm->PyStr_AS_C(args[0]);
|
||||
_Code code = compile(vm, expr, "<f-string>", EVAL_MODE);
|
||||
return vm->exec(code); // not working in function
|
||||
@ -67,7 +67,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
|
||||
|
||||
_vm->bindBuiltinFunc("chr", [](VM* vm, PyVarList args) {
|
||||
int i = vm->PyInt_AS_C(args.at(0));
|
||||
if (i < 0 || i > 128) vm->_error("ValueError", "chr() arg not in range(128)");
|
||||
if (i < 0 || i > 128) vm->valueError("chr() arg not in range(128)");
|
||||
return vm->PyStr(_Str(1, (char)i));
|
||||
});
|
||||
|
||||
@ -77,7 +77,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
|
||||
|
||||
_vm->bindBuiltinFunc("ord", [](VM* vm, PyVarList args) {
|
||||
_Str s = vm->PyStr_AS_C(args.at(0));
|
||||
if (s.size() != 1) vm->_error("TypeError", "ord() expected an ASCII character");
|
||||
if (s.size() != 1) vm->typeError("ord() expected an ASCII character");
|
||||
return vm->PyInt((int)s[0]);
|
||||
});
|
||||
|
||||
@ -104,7 +104,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
|
||||
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 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->_error("TypeError", "range expected 1-3 arguments, got " + std::to_string(args.size()));
|
||||
default: vm->typeError("range expected 1-3 arguments, got " + std::to_string(args.size()));
|
||||
}
|
||||
return vm->PyRange(r);
|
||||
});
|
||||
@ -121,13 +121,13 @@ void __initializeBuiltinFunctions(VM* _vm) {
|
||||
|
||||
_vm->bindMethodMulti({"int", "float"}, "__truediv__", [](VM* vm, PyVarList args) {
|
||||
if(!vm->isIntOrFloat(args[0], args[1]))
|
||||
vm->_error("TypeError", "unsupported operand type(s) for " "/" );
|
||||
vm->typeError("unsupported operand type(s) for " "/" );
|
||||
return vm->PyFloat(vm->numToFloat(args[0]) / vm->numToFloat(args[1]));
|
||||
});
|
||||
|
||||
_vm->bindMethodMulti({"int", "float"}, "__pow__", [](VM* vm, PyVarList args) {
|
||||
if(!vm->isIntOrFloat(args[0], args[1]))
|
||||
vm->_error("TypeError", "unsupported operand type(s) for " "**" );
|
||||
vm->typeError("unsupported operand type(s) for " "**" );
|
||||
if(args[0]->isType(vm->_tp_int) && args[1]->isType(vm->_tp_int)){
|
||||
return vm->PyInt(_round(pow(vm->PyInt_AS_C(args[0]), vm->PyInt_AS_C(args[1]))));
|
||||
}else{
|
||||
@ -138,19 +138,19 @@ void __initializeBuiltinFunctions(VM* _vm) {
|
||||
/************ PyInt ************/
|
||||
_vm->bindMethod("int", "__floordiv__", [](VM* vm, PyVarList args) {
|
||||
if(!args[0]->isType(vm->_tp_int) || !args[1]->isType(vm->_tp_int))
|
||||
vm->_error("TypeError", "unsupported operand type(s) for " "//" );
|
||||
vm->typeError("unsupported operand type(s) for " "//" );
|
||||
return vm->PyInt(vm->PyInt_AS_C(args[0]) / vm->PyInt_AS_C(args[1]));
|
||||
});
|
||||
|
||||
_vm->bindMethod("int", "__mod__", [](VM* vm, PyVarList args) {
|
||||
if(!args[0]->isType(vm->_tp_int) || !args[1]->isType(vm->_tp_int))
|
||||
vm->_error("TypeError", "unsupported operand type(s) for " "%" );
|
||||
vm->typeError("unsupported operand type(s) for " "%" );
|
||||
return vm->PyInt(vm->PyInt_AS_C(args[0]) % vm->PyInt_AS_C(args[1]));
|
||||
});
|
||||
|
||||
_vm->bindMethod("int", "__neg__", [](VM* vm, PyVarList args) {
|
||||
if(!args[0]->isType(vm->_tp_int))
|
||||
vm->_error("TypeError", "unsupported operand type(s) for " "-" );
|
||||
vm->typeError("unsupported operand type(s) for " "-" );
|
||||
return vm->PyInt(-1 * vm->PyInt_AS_C(args[0]));
|
||||
});
|
||||
|
||||
@ -175,7 +175,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
|
||||
|
||||
_vm->bindMethod("str", "__add__", [](VM* vm, PyVarList args) {
|
||||
if(!args[0]->isType(vm->_tp_str) || !args[1]->isType(vm->_tp_str))
|
||||
vm->_error("TypeError", "unsupported operand type(s) for " "+" );
|
||||
vm->typeError("unsupported operand type(s) for " "+" );
|
||||
const _Str& lhs = vm->PyStr_AS_C(args[0]);
|
||||
const _Str& rhs = vm->PyStr_AS_C(args[1]);
|
||||
return vm->PyStr(lhs + rhs);
|
||||
@ -317,7 +317,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
|
||||
|
||||
_vm->bindMethod("list", "pop", [](VM* vm, PyVarList args) {
|
||||
PyVarList& _self = vm->PyList_AS_C(args[0]);
|
||||
if(_self.empty()) vm->_error("IndexError", "pop from empty list");
|
||||
if(_self.empty()) vm->indexError("pop from empty list");
|
||||
PyVar ret = _self.back();
|
||||
_self.pop_back();
|
||||
return ret;
|
||||
@ -428,12 +428,12 @@ void __addModuleRandom(VM* vm){
|
||||
|
||||
extern "C" {
|
||||
__EXPORT
|
||||
VM* createVM(PrintFn printFn){
|
||||
VM* createVM(PrintFn _stdout){
|
||||
VM* vm = new VM();
|
||||
__initializeBuiltinFunctions(vm);
|
||||
__runCodeBuiltins(vm, __BUILTINS_CODE);
|
||||
__addModuleRandom(vm);
|
||||
vm->printFn = printFn;
|
||||
vm->_stdout = _stdout;
|
||||
return vm;
|
||||
}
|
||||
|
||||
@ -448,8 +448,8 @@ extern "C" {
|
||||
_Code code = compile(vm, source, "main.py");
|
||||
vm->exec(code);
|
||||
}catch(std::exception& e){
|
||||
vm->printFn(e.what());
|
||||
vm->printFn("\n");
|
||||
vm->_stdout(e.what());
|
||||
vm->_stdout("\n");
|
||||
vm->cleanError();
|
||||
}
|
||||
}
|
||||
|
124
src/vm.h
124
src/vm.h
@ -2,6 +2,7 @@
|
||||
|
||||
#include "codeobject.h"
|
||||
#include "iter.h"
|
||||
#include "error.h"
|
||||
|
||||
#define __DEF_PY_AS_C(type, ctype, ptype) \
|
||||
inline ctype& Py##type##_AS_C(const PyVar& obj) { \
|
||||
@ -18,7 +19,6 @@
|
||||
__DEF_PY(type, ctype, ptype) \
|
||||
__DEF_PY_AS_C(type, ctype, ptype)
|
||||
|
||||
// TODO: we should split this into stdout and stderr
|
||||
typedef void(*PrintFn)(const char*);
|
||||
|
||||
#define NUM_POOL_MAX_SIZE 1024
|
||||
@ -31,7 +31,8 @@ public:
|
||||
PyVarDict _types; // builtin types
|
||||
PyVar None, True, False;
|
||||
|
||||
PrintFn printFn = [](auto s){};
|
||||
PrintFn _stdout = [](auto s){};
|
||||
PrintFn _stderr = [](auto s){};
|
||||
|
||||
PyVar builtins; // builtins module
|
||||
PyVar _main; // __main__ module
|
||||
@ -41,24 +42,6 @@ public:
|
||||
initializeBuiltinClasses();
|
||||
}
|
||||
|
||||
void cleanError(){
|
||||
while(!callstack.empty()) callstack.pop();
|
||||
}
|
||||
|
||||
void nameError(const _Str& name){
|
||||
_error("NameError", "name '" + name + "' is not defined");
|
||||
}
|
||||
|
||||
void attributeError(PyVar obj, const _Str& name){
|
||||
_error("AttributeError", "type '" + obj->getTypeName() + "' has no attribute '" + name + "'");
|
||||
}
|
||||
|
||||
inline void __checkType(const PyVar& obj, const PyVar& type){
|
||||
if(!obj->isType(type)){
|
||||
_error("TypeError", "expected '" + type->getName() + "', but got '" + obj->getTypeName() + "'");
|
||||
}
|
||||
}
|
||||
|
||||
PyVar asStr(const PyVar& obj){
|
||||
PyVarOrNull str_fn = getAttr(obj, __str__, false);
|
||||
if(str_fn != nullptr) return call(str_fn, {});
|
||||
@ -130,7 +113,7 @@ public:
|
||||
if(i < args.size()) {
|
||||
locals[name] = args[i++];
|
||||
}else{
|
||||
_error("TypeError", "missing positional argument '" + name + "'");
|
||||
typeError("missing positional argument '" + name + "'");
|
||||
}
|
||||
}
|
||||
// handle *args
|
||||
@ -148,12 +131,12 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
if(i < args.size()) _error("TypeError", "too many arguments");
|
||||
if(i < args.size()) typeError("too many arguments");
|
||||
|
||||
// TODO: handle **kwargs
|
||||
return exec(fn.code, locals);
|
||||
}
|
||||
_error("TypeError", "'" + callable->getTypeName() + "' object is not callable");
|
||||
typeError("'" + callable->getTypeName() + "' object is not callable");
|
||||
return None;
|
||||
}
|
||||
|
||||
@ -264,8 +247,8 @@ public:
|
||||
{
|
||||
const PyVar& expr = frame->topValue(this);
|
||||
if(expr == None) break;
|
||||
printFn(PyStr_AS_C(asRepr(expr)));
|
||||
printFn("\n");
|
||||
_stdout(PyStr_AS_C(asRepr(expr)));
|
||||
_stdout("\n");
|
||||
} break;
|
||||
case OP_POP_TOP: frame->popValue(this); break;
|
||||
case OP_BINARY_OP:
|
||||
@ -318,7 +301,7 @@ public:
|
||||
case OP_ASSERT:
|
||||
{
|
||||
PyVar expr = frame->popValue(this);
|
||||
if(!PyBool_AS_C(expr)) _error("AssertionError", "assertion failed");
|
||||
_assert(PyBool_AS_C(expr), "assertion failed");
|
||||
} break;
|
||||
case OP_RAISE_ERROR:
|
||||
{
|
||||
@ -357,7 +340,7 @@ public:
|
||||
PyIter_AS_C(tmp)->var = PyPointer_AS_C(frame->__pop());
|
||||
frame->push(tmp);
|
||||
}else{
|
||||
_error("TypeError", "'" + obj->getTypeName() + "' object is not iterable");
|
||||
typeError("'" + obj->getTypeName() + "' object is not iterable");
|
||||
}
|
||||
} break;
|
||||
case OP_FOR_ITER:
|
||||
@ -404,19 +387,19 @@ public:
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
_error("SystemError", _Str("opcode ") + OP_NAMES[byte.op] + " is not implemented");
|
||||
systemError(_Str("opcode ") + OP_NAMES[byte.op] + " is not implemented");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(frame->code->mode == EVAL_MODE) {
|
||||
if(frame->stackSize() != 1) {
|
||||
_error("SystemError", "stack size is not 1 in EVAL_MODE");
|
||||
systemError("stack size is not 1 in EVAL_MODE");
|
||||
}
|
||||
return frame->popValue(this);
|
||||
}
|
||||
|
||||
if(frame->stackSize() != 0) _error("SystemError", "stack not empty in EXEC_MODE");
|
||||
if(frame->stackSize() != 0) systemError("stack not empty in EXEC_MODE");
|
||||
callstack.pop();
|
||||
return None;
|
||||
}
|
||||
@ -431,19 +414,6 @@ public:
|
||||
return runFrame(frame);
|
||||
}
|
||||
|
||||
void _assert(bool val, const _Str& msg){
|
||||
if (!val) _error("AssertionError", msg);
|
||||
}
|
||||
|
||||
void _error(const _Str& name, const _Str& msg){
|
||||
_StrStream ss;
|
||||
auto frame = callstack.top();
|
||||
ss << "Traceback (most recent call last):" << std::endl;
|
||||
ss << " File '" << frame->code->co_filename << "', line ";
|
||||
ss << frame->currentLine() << '\n' << name << ": " << msg;
|
||||
throw std::runtime_error(ss.str());
|
||||
}
|
||||
|
||||
PyVar newUserClassType(_Str name, PyVar base){
|
||||
PyVar obj = newClassType(name, base);
|
||||
setAttr(obj, "__name__", PyStr(name));
|
||||
@ -469,7 +439,7 @@ public:
|
||||
|
||||
PyVar newNumber(PyVar type, _Value _native) {
|
||||
if(type != _tp_int && type != _tp_float)
|
||||
_error("SystemError", "type is not a number type");
|
||||
systemError("type is not a number type");
|
||||
PyObject* _raw = nullptr;
|
||||
if(numPool.size() > 0) {
|
||||
_raw = numPool.back();
|
||||
@ -567,7 +537,7 @@ public:
|
||||
int normalizedIndex(int index, int size){
|
||||
if(index < 0) index += size;
|
||||
if(index < 0 || index >= size){
|
||||
_error("IndexError", "index out of range, " + std::to_string(index) + " not in [0, " + std::to_string(size) + ")");
|
||||
indexError("index out of range, " + std::to_string(index) + " not in [0, " + std::to_string(size) + ")");
|
||||
}
|
||||
return index;
|
||||
}
|
||||
@ -651,7 +621,7 @@ public:
|
||||
}
|
||||
if (obj->isType(_tp_str)) return PyStr_AS_C(obj).hash();
|
||||
if (obj->isType(_tp_type)) return (int64_t)obj.get();
|
||||
_error("TypeError", "unhashable type: " + obj->getTypeName());
|
||||
typeError("unhashable type: " + obj->getTypeName());
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -660,9 +630,61 @@ public:
|
||||
exec(code, {}, _m);
|
||||
_modules[name] = _m;
|
||||
}
|
||||
|
||||
/***** Error Reporter *****/
|
||||
private:
|
||||
void _error(const _Str& name, const _Str& msg){
|
||||
std::stack<LineSnapshot> snapshots;
|
||||
while (!callstack.empty()){
|
||||
auto frame = callstack.top();
|
||||
snapshots.push(LineSnapshot(
|
||||
frame->code->co_filename,
|
||||
frame->currentLine()
|
||||
));
|
||||
callstack.pop();
|
||||
}
|
||||
throw RuntimeError(name, msg, snapshots);
|
||||
}
|
||||
|
||||
public:
|
||||
void cleanError(){
|
||||
while(!callstack.empty()) callstack.pop();
|
||||
}
|
||||
|
||||
void typeError(const _Str& msg){
|
||||
typeError(msg);
|
||||
}
|
||||
|
||||
void systemError(const _Str& msg){
|
||||
systemError(msg);
|
||||
}
|
||||
|
||||
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 + "' is not defined");
|
||||
}
|
||||
|
||||
void attributeError(PyVar obj, const _Str& name){
|
||||
_error("AttributeError", "type '" + obj->getTypeName() + "' has no attribute '" + name + "'");
|
||||
}
|
||||
|
||||
inline void __checkType(const PyVar& obj, const PyVar& type){
|
||||
if(!obj->isType(type)) typeError("expected '" + type->getName() + "', but got '" + obj->getTypeName() + "'");
|
||||
}
|
||||
|
||||
void _assert(bool val, const _Str& msg){
|
||||
if (!val) _error("AssertionError", msg);
|
||||
}
|
||||
};
|
||||
|
||||
/**************** Pointers' Impl ****************/
|
||||
/***** Pointers' Impl *****/
|
||||
|
||||
PyVar NamePointer::get(VM* vm, Frame* frame) const{
|
||||
auto it = frame->f_locals.find(name);
|
||||
@ -724,7 +746,7 @@ void AttrPointer::set(VM* vm, Frame* frame, PyVar val) const{
|
||||
}
|
||||
|
||||
void AttrPointer::del(VM* vm, Frame* frame) const{
|
||||
vm->_error("AttributeError", "can't delete attribute");
|
||||
vm->typeError("cannot delete attribute");
|
||||
}
|
||||
|
||||
PyVar IndexPointer::get(VM* vm, Frame* frame) const{
|
||||
@ -749,11 +771,11 @@ PyVar CompoundPointer::get(VM* vm, Frame* frame) const{
|
||||
|
||||
void CompoundPointer::set(VM* vm, Frame* frame, PyVar val) const{
|
||||
if(!val->isType(vm->_tp_tuple) && !val->isType(vm->_tp_list)){
|
||||
vm->_error("TypeError", "only tuple or list can be unpacked");
|
||||
vm->typeError("only tuple or list can be unpacked");
|
||||
}
|
||||
const PyVarList& args = std::get<PyVarList>(val->_native);
|
||||
if(args.size() > pointers.size()) vm->_error("ValueError", "too many values to unpack");
|
||||
if(args.size() < pointers.size()) vm->_error("ValueError", "not enough values to unpack");
|
||||
if(args.size() > pointers.size()) vm->valueError("too many values to unpack");
|
||||
if(args.size() < pointers.size()) vm->valueError("not enough values to unpack");
|
||||
for (int i = 0; i < pointers.size(); i++) {
|
||||
pointers[i]->set(vm, frame, args[i]);
|
||||
}
|
||||
|
17
tests/errors/1.py
Normal file
17
tests/errors/1.py
Normal file
@ -0,0 +1,17 @@
|
||||
def is_prime(x):
|
||||
if x<2:
|
||||
return False
|
||||
|
||||
for i in range(2,x):
|
||||
if x%i == 0:
|
||||
return False1
|
||||
return True
|
||||
|
||||
def test(n):
|
||||
k = 0
|
||||
for i in range(n):
|
||||
if is_prime(i):
|
||||
k += 1
|
||||
return k
|
||||
|
||||
print(test(100))
|
Loading…
x
Reference in New Issue
Block a user