Commit acf80b82 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Switch from our exception definitions to CPython's

This also forced us to make our exception handling more compatible in
a couple places, as well as fix some bugs that weren't getting exposed.

There might be some benefit to implementing the exceptions ourselves
(get to use faster Pyston interfaces, make them GC-aware) but maybe
we can get these benefits but still use the 2kloc exceptions.c file.
parent d1c00711
......@@ -292,7 +292,7 @@ STDLIB_RELEASE_OBJS := stdlib.release.bc.o
ASM_SRCS := $(wildcard src/runtime/*.S)
STDMODULE_SRCS := errnomodule.c shamodule.c sha256module.c sha512module.c _math.c mathmodule.c md5.c md5module.c _randommodule.c _sre.c operator.c binascii.c pwdmodule.c posixmodule.c _struct.c datetimemodule.c _functoolsmodule.c _collectionsmodule.c itertoolsmodule.c resource.c signalmodule.c selectmodule.c fcntlmodule.c timemodule.c arraymodule.c zlibmodule.c _codecsmodule.c socketmodule.c $(EXTRA_STDMODULE_SRCS)
STDOBJECT_SRCS := structseq.c capsule.c stringobject.c $(EXTRA_STDOBJECT_SRCS)
STDOBJECT_SRCS := structseq.c capsule.c stringobject.c exceptions.c $(EXTRA_STDOBJECT_SRCS)
STDPYTHON_SRCS := pyctype.c getargs.c formatter_string.c pystrtod.c dtoa.c $(EXTRA_STDPYTHON_SRCS)
FROM_CPYTHON_SRCS := $(addprefix from_cpython/Modules/,$(STDMODULE_SRCS)) $(addprefix from_cpython/Objects/,$(STDOBJECT_SRCS)) $(addprefix from_cpython/Python/,$(STDPYTHON_SRCS))
......
......@@ -18,7 +18,7 @@ add_custom_target(copy_stdlib ALL DEPENDS ${STDLIB_TARGETS})
file(GLOB_RECURSE STDMODULE_SRCS Modules errnomodule.c shamodule.c sha256module.c sha512module.c _math.c mathmodule.c md5.c md5module.c _randommodule.c _sre.c operator.c binascii.c pwdmodule.c posixmodule.c _struct.c datetimemodule.c _functoolsmodule.c _collectionsmodule.c itertoolsmodule.c resource.c signalmodule.c selectmodule.c fcntlmodule.c timemodule.c arraymodule.c zlibmodule.c _codecsmodule.c socketmodule.c)
# compile specified files in from_cpython/Objects
file(GLOB_RECURSE STDOBJECT_SRCS Objects structseq.c capsule.c stringobject.c)
file(GLOB_RECURSE STDOBJECT_SRCS Objects structseq.c capsule.c stringobject.c exceptions.c)
# compile specified files in from_cpython/Python
file(GLOB_RECURSE STDPYTHON_SRCS Python getargs.c pyctype.c formatter_string.c pystrtod.c dtoa.c)
......
......@@ -8,8 +8,6 @@ extern "C" {
/* Error objects */
// Pyston change: these are not our object formats
#if 0
typedef struct {
PyObject_HEAD
PyObject *dict;
......@@ -74,8 +72,6 @@ typedef struct {
PyObject *winerror;
} PyWindowsErrorObject;
#endif
#endif
// (Pyston TODO: add opaque definitions of those names)
/* Error handling definitions */
......@@ -132,119 +128,68 @@ PyAPI_FUNC(PyObject*) PyExceptionInstance_Class(PyObject*) PYSTON_NOEXCEPT;
// as PyTypeObject's.
// TODO not sure if this is worth it -- a fair amount of confusion (duplicating these names) for fairly
// little gain (getting to treat them as PyTypeObject's and using our own names)
#define PyExc_BaseException ((PyObject*)BaseException)
PyAPI_DATA(PyTypeObject *) BaseException;
#define PyExc_Exception ((PyObject*)Exception)
PyAPI_DATA(PyTypeObject *) Exception;
#define PyExc_StopIteration ((PyObject*)StopIteration)
PyAPI_DATA(PyTypeObject *) StopIteration;
#define PyExc_GeneratorExit ((PyObject*)GeneratorExit)
PyAPI_DATA(PyTypeObject *) GeneratorExit;
#define PyExc_StandardError ((PyObject*)StandardError)
PyAPI_DATA(PyTypeObject *) StandardError;
#define PyExc_ArithmeticError ((PyObject*)ArithmeticError)
PyAPI_DATA(PyTypeObject *) ArithmeticError;
#define PyExc_LookupError ((PyObject*)LookupError)
PyAPI_DATA(PyTypeObject *) LookupError;
#define PyExc_AssertionError ((PyObject*)AssertionError)
PyAPI_DATA(PyTypeObject *) AssertionError;
#define PyExc_AttributeError ((PyObject*)AttributeError)
PyAPI_DATA(PyTypeObject *) AttributeError;
#define PyExc_EOFError ((PyObject*)EOFError)
PyAPI_DATA(PyTypeObject *) EOFError;
#define PyExc_FloatingPointError ((PyObject*)FloatingPointError)
PyAPI_DATA(PyTypeObject *) FloatingPointError;
#define PyExc_EnvironmentError ((PyObject*)EnvironmentError)
PyAPI_DATA(PyTypeObject *) EnvironmentError;
#define PyExc_IOError ((PyObject*)IOError)
PyAPI_DATA(PyTypeObject *) IOError;
#define PyExc_OSError ((PyObject*)OSError)
PyAPI_DATA(PyTypeObject *) OSError;
#define PyExc_ImportError ((PyObject*)ImportError)
PyAPI_DATA(PyTypeObject *) ImportError;
#define PyExc_IndexError ((PyObject*)IndexError)
PyAPI_DATA(PyTypeObject *) IndexError;
#define PyExc_KeyError ((PyObject*)KeyError)
PyAPI_DATA(PyTypeObject *) KeyError;
#define PyExc_KeyboardInterrupt ((PyObject*)KeyboardInterrupt)
PyAPI_DATA(PyTypeObject *) KeyboardInterrupt;
#define PyExc_MemoryError ((PyObject*)MemoryError)
PyAPI_DATA(PyTypeObject *) MemoryError;
#define PyExc_NameError ((PyObject*)NameError)
PyAPI_DATA(PyTypeObject *) NameError;
#define PyExc_OverflowError ((PyObject*)OverflowError)
PyAPI_DATA(PyTypeObject *) OverflowError;
#define PyExc_RuntimeError ((PyObject*)RuntimeError)
PyAPI_DATA(PyTypeObject *) RuntimeError;
#define PyExc_NotImplementedError ((PyObject*)NotImplementedError)
PyAPI_DATA(PyTypeObject *) NotImplementedError;
#define PyExc_SyntaxError ((PyObject*)SyntaxError)
PyAPI_DATA(PyTypeObject *) SyntaxError;
#define PyExc_IndentationError ((PyObject*)IndentationError)
PyAPI_DATA(PyTypeObject *) IndentationError;
#define PyExc_TabError ((PyObject*)TabError)
PyAPI_DATA(PyTypeObject *) TabError;
#define PyExc_ReferenceError ((PyObject*)ReferenceError)
PyAPI_DATA(PyTypeObject *) ReferenceError;
#define PyExc_SystemError ((PyObject*)SystemError)
PyAPI_DATA(PyTypeObject *) SystemError;
#define PyExc_SystemExit ((PyObject*)SystemExit)
PyAPI_DATA(PyTypeObject *) SystemExit;
#define PyExc_TypeError ((PyObject*)TypeError)
PyAPI_DATA(PyTypeObject *) TypeError;
#define PyExc_UnboundLocalError ((PyObject*)UnboundLocalError)
PyAPI_DATA(PyTypeObject *) UnboundLocalError;
#define PyExc_UnicodeError ((PyObject*)UnicodeError)
PyAPI_DATA(PyTypeObject *) UnicodeError;
#define PyExc_UnicodeEncodeError ((PyObject*)UnicodeEncodeError)
PyAPI_DATA(PyTypeObject *) UnicodeEncodeError;
#define PyExc_UnicodeDecodeError ((PyObject*)UnicodeDecodeError)
PyAPI_DATA(PyTypeObject *) UnicodeDecodeError;
#define PyExc_UnicodeTranslateError ((PyObject*)UnicodeTranslateError)
PyAPI_DATA(PyTypeObject *) UnicodeTranslateError;
#define PyExc_ValueError ((PyObject*)ValueError)
PyAPI_DATA(PyTypeObject *) ValueError;
#define PyExc_ZeroDivisionError ((PyObject*)ZeroDivisionError)
PyAPI_DATA(PyTypeObject *) ZeroDivisionError;
PyAPI_DATA(PyObject *) PyExc_BaseException;
PyAPI_DATA(PyObject *) PyExc_Exception;
PyAPI_DATA(PyObject *) PyExc_StopIteration;
PyAPI_DATA(PyObject *) PyExc_GeneratorExit;
PyAPI_DATA(PyObject *) PyExc_StandardError;
PyAPI_DATA(PyObject *) PyExc_ArithmeticError;
PyAPI_DATA(PyObject *) PyExc_LookupError;
PyAPI_DATA(PyObject *) PyExc_AssertionError;
PyAPI_DATA(PyObject *) PyExc_AttributeError;
PyAPI_DATA(PyObject *) PyExc_EOFError;
PyAPI_DATA(PyObject *) PyExc_FloatingPointError;
PyAPI_DATA(PyObject *) PyExc_EnvironmentError;
PyAPI_DATA(PyObject *) PyExc_IOError;
PyAPI_DATA(PyObject *) PyExc_OSError;
PyAPI_DATA(PyObject *) PyExc_ImportError;
PyAPI_DATA(PyObject *) PyExc_IndexError;
PyAPI_DATA(PyObject *) PyExc_KeyError;
PyAPI_DATA(PyObject *) PyExc_KeyboardInterrupt;
PyAPI_DATA(PyObject *) PyExc_MemoryError;
PyAPI_DATA(PyObject *) PyExc_NameError;
PyAPI_DATA(PyObject *) PyExc_OverflowError;
PyAPI_DATA(PyObject *) PyExc_RuntimeError;
PyAPI_DATA(PyObject *) PyExc_NotImplementedError;
PyAPI_DATA(PyObject *) PyExc_SyntaxError;
PyAPI_DATA(PyObject *) PyExc_IndentationError;
PyAPI_DATA(PyObject *) PyExc_TabError;
PyAPI_DATA(PyObject *) PyExc_ReferenceError;
PyAPI_DATA(PyObject *) PyExc_SystemError;
PyAPI_DATA(PyObject *) PyExc_SystemExit;
PyAPI_DATA(PyObject *) PyExc_TypeError;
PyAPI_DATA(PyObject *) PyExc_UnboundLocalError;
PyAPI_DATA(PyObject *) PyExc_UnicodeError;
PyAPI_DATA(PyObject *) PyExc_UnicodeEncodeError;
PyAPI_DATA(PyObject *) PyExc_UnicodeDecodeError;
PyAPI_DATA(PyObject *) PyExc_UnicodeTranslateError;
PyAPI_DATA(PyObject *) PyExc_ValueError;
PyAPI_DATA(PyObject *) PyExc_ZeroDivisionError;
#ifdef MS_WINDOWS
#define PyExc_WindowsError ((PyObject*)WindowsError)
PyAPI_DATA(PyTypeObject *) WindowsError;
PyAPI_DATA(PyObject *) PyExc_WindowsError;
#endif
#ifdef __VMS
#define PyExc_VMSError ((PyObject*)VMSError)
PyAPI_DATA(PyTypeObject *) VMSError;
PyAPI_DATA(PyObject *) PyExc_VMSError;
#endif
#define PyExc_BufferError ((PyObject*)BufferError)
PyAPI_DATA(PyTypeObject *) BufferError;
PyAPI_DATA(PyObject *) PyExc_BufferError;
PyAPI_DATA(PyObject *) PyExc_MemoryErrorInst;
PyAPI_DATA(PyObject *) PyExc_RecursionErrorInst;
/* Predefined warning categories */
#define PyExc_Warning ((PyObject*)Warning)
PyAPI_DATA(PyTypeObject *) Warning;
#define PyExc_UserWarning ((PyObject*)UserWarning)
PyAPI_DATA(PyTypeObject *) UserWarning;
#define PyExc_DeprecationWarning ((PyObject*)DeprecationWarning)
PyAPI_DATA(PyTypeObject *) DeprecationWarning;
#define PyExc_PendingDeprecationWarning ((PyObject*)PendingDeprecationWarning)
PyAPI_DATA(PyTypeObject *) PendingDeprecationWarning;
#define PyExc_SyntaxWarning ((PyObject*)SyntaxWarning)
PyAPI_DATA(PyTypeObject *) SyntaxWarning;
#define PyExc_RuntimeWarning ((PyObject*)RuntimeWarning)
PyAPI_DATA(PyTypeObject *) RuntimeWarning;
#define PyExc_FutureWarning ((PyObject*)FutureWarning)
PyAPI_DATA(PyTypeObject *) FutureWarning;
#define PyExc_ImportWarning ((PyObject*)ImportWarning)
PyAPI_DATA(PyTypeObject *) ImportWarning;
#define PyExc_UnicodeWarning ((PyObject*)UnicodeWarning)
PyAPI_DATA(PyTypeObject *) UnicodeWarning;
#define PyExc_BytesWarning ((PyObject*)BytesWarning)
PyAPI_DATA(PyTypeObject *) BytesWarning;
PyAPI_DATA(PyObject *) PyExc_Warning;
PyAPI_DATA(PyObject *) PyExc_UserWarning;
PyAPI_DATA(PyObject *) PyExc_DeprecationWarning;
PyAPI_DATA(PyObject *) PyExc_PendingDeprecationWarning;
PyAPI_DATA(PyObject *) PyExc_SyntaxWarning;
PyAPI_DATA(PyObject *) PyExc_RuntimeWarning;
PyAPI_DATA(PyObject *) PyExc_FutureWarning;
PyAPI_DATA(PyObject *) PyExc_ImportWarning;
PyAPI_DATA(PyObject *) PyExc_UnicodeWarning;
PyAPI_DATA(PyObject *) PyExc_BytesWarning;
/* Convenience functions */
......
......@@ -372,6 +372,9 @@ static PyGetSetDef BaseException_getset[] = {
{NULL},
};
// Leave this in as a reminder in case we want to go back to using it:
#define Py_TPFLAGS_BASE_EXC_SUBCLASS (0)
static PyTypeObject _PyExc_BaseException = {
PyObject_HEAD_INIT(NULL)
......
......@@ -188,7 +188,73 @@ extern "C" void PyErr_WriteUnraisable(PyObject* obj) noexcept {
static int parse_syntax_error(PyObject* err, PyObject** message, const char** filename, int* lineno, int* offset,
const char** text) noexcept {
Py_FatalError("unimplemented");
long hold;
PyObject* v;
/* old style errors */
if (PyTuple_Check(err))
return PyArg_ParseTuple(err, "O(ziiz)", message, filename, lineno, offset, text);
*message = NULL;
/* new style errors. `err' is an instance */
*message = PyObject_GetAttrString(err, "msg");
if (!*message)
goto finally;
v = PyObject_GetAttrString(err, "filename");
if (!v)
goto finally;
if (v == Py_None) {
Py_DECREF(v);
*filename = NULL;
} else {
*filename = PyString_AsString(v);
Py_DECREF(v);
if (!*filename)
goto finally;
}
v = PyObject_GetAttrString(err, "lineno");
if (!v)
goto finally;
hold = PyInt_AsLong(v);
Py_DECREF(v);
if (hold < 0 && PyErr_Occurred())
goto finally;
*lineno = (int)hold;
v = PyObject_GetAttrString(err, "offset");
if (!v)
goto finally;
if (v == Py_None) {
*offset = -1;
Py_DECREF(v);
} else {
hold = PyInt_AsLong(v);
Py_DECREF(v);
if (hold < 0 && PyErr_Occurred())
goto finally;
*offset = (int)hold;
}
v = PyObject_GetAttrString(err, "text");
if (!v)
goto finally;
if (v == Py_None) {
Py_DECREF(v);
*text = NULL;
} else {
*text = PyString_AsString(v);
Py_DECREF(v);
if (!*text)
goto finally;
}
return 1;
finally:
Py_XDECREF(*message);
return 0;
}
static void print_error_text(PyObject* f, int offset, const char* text) noexcept {
......
......@@ -72,6 +72,10 @@ extern "C" int PyObject_GenericSetAttr(PyObject* obj, PyObject* name, PyObject*
Py_FatalError("unimplemented");
}
extern "C" int PyObject_SetAttr(PyObject* v, PyObject* name, PyObject* value) noexcept {
Py_FatalError("unimplemented");
}
extern "C" PyObject* PyObject_GetAttrString(PyObject* o, const char* attr) noexcept {
// TODO do something like this? not sure if this is safe; will people expect that calling into a known function
// won't end up doing a GIL check?
......
......@@ -1784,6 +1784,10 @@ void PystonType_Ready(BoxedClass* cls) {
}
}
extern "C" void PyType_Modified(PyTypeObject* type) noexcept {
// We don't cache anything yet that would need to be invalidated:
}
extern "C" int PyType_Ready(PyTypeObject* cls) noexcept {
gc::registerNonheapRootObject(cls);
......
......@@ -522,8 +522,6 @@ void appendToSysPath(const std::string& path);
void prependToSysPath(const std::string& path);
void addToSysArgv(const char* str);
std::string formatException(Box* e);
// Raise a SyntaxError that occurs at a specific location.
// The traceback given to the user will include this,
// even though the execution didn't actually arrive there.
......
......@@ -589,19 +589,6 @@ Box* eval(Box* code) {
BoxedClass* notimplemented_cls;
BoxedModule* builtins_module;
// TODO looks like CPython and pypy put this into an "exceptions" module:
extern "C" {
BoxedClass* BaseException, *Exception, *StandardError, *AssertionError, *AttributeError, *GeneratorExit, *TypeError,
*NameError, *KeyError, *IndexError, *IOError, *OSError, *ZeroDivisionError, *ValueError, *UnboundLocalError,
*RuntimeError, *ImportError, *StopIteration, *Warning, *SyntaxError, *OverflowError, *DeprecationWarning,
*MemoryError, *LookupError, *EnvironmentError, *ArithmeticError, *BufferError, *KeyboardInterrupt, *SystemExit,
*SystemError, *NotImplementedError, *PendingDeprecationWarning, *EOFError, *UnicodeError, *UnicodeEncodeError,
*UnicodeDecodeError, *UnicodeTranslateError;
Box* PyExc_RecursionErrorInst;
Box* PyExc_MemoryErrorInst;
}
class BoxedException : public Box {
public:
HCAttrs attrs;
......@@ -879,123 +866,6 @@ Box* pydumpAddr(Box* p) {
return None;
}
class BoxedEnvironmentError : public BoxedException {
public:
// Box* args, *message, *myerrno, *strerror, *filename;
Box* myerrno, *strerror, *filename;
static Box* __init__(BoxedEnvironmentError* self, Box* errno_, Box* strerror, Box** _args) {
Box* filename = _args[0];
RELEASE_ASSERT(isSubclass(self->cls, EnvironmentError), "");
self->myerrno = errno_;
self->strerror = strerror;
self->filename = filename;
return None;
}
static Box* __reduce__(Box* self) { Py_FatalError("unimplemented"); }
static PyObject* __str__(BoxedEnvironmentError* self) noexcept {
PyObject* rtnval = NULL;
if (self->filename) {
PyObject* fmt;
PyObject* repr;
PyObject* tuple;
fmt = PyString_FromString("[Errno %s] %s: %s");
if (!fmt)
return NULL;
repr = PyObject_Repr(self->filename);
if (!repr) {
Py_DECREF(fmt);
return NULL;
}
tuple = PyTuple_New(3);
if (!tuple) {
Py_DECREF(repr);
Py_DECREF(fmt);
return NULL;
}
if (self->myerrno) {
Py_INCREF(self->myerrno);
PyTuple_SET_ITEM(tuple, 0, self->myerrno);
} else {
Py_INCREF(Py_None);
PyTuple_SET_ITEM(tuple, 0, Py_None);
}
if (self->strerror) {
Py_INCREF(self->strerror);
PyTuple_SET_ITEM(tuple, 1, self->strerror);
} else {
Py_INCREF(Py_None);
PyTuple_SET_ITEM(tuple, 1, Py_None);
}
PyTuple_SET_ITEM(tuple, 2, repr);
rtnval = PyString_Format(fmt, tuple);
Py_DECREF(fmt);
Py_DECREF(tuple);
} else if (self->myerrno && self->strerror) {
PyObject* fmt;
PyObject* tuple;
fmt = PyString_FromString("[Errno %s] %s");
if (!fmt)
return NULL;
tuple = PyTuple_New(2);
if (!tuple) {
Py_DECREF(fmt);
return NULL;
}
if (self->myerrno) {
Py_INCREF(self->myerrno);
PyTuple_SET_ITEM(tuple, 0, self->myerrno);
} else {
Py_INCREF(Py_None);
PyTuple_SET_ITEM(tuple, 0, Py_None);
}
if (self->strerror) {
Py_INCREF(self->strerror);
PyTuple_SET_ITEM(tuple, 1, self->strerror);
} else {
Py_INCREF(Py_None);
PyTuple_SET_ITEM(tuple, 1, Py_None);
}
rtnval = PyString_Format(fmt, tuple);
Py_DECREF(fmt);
Py_DECREF(tuple);
} else
rtnval = exceptionStr(self);
return rtnval;
}
static void gcHandler(GCVisitor* v, Box* _b) {
assert(isSubclass(_b->cls, EnvironmentError));
boxGCHandler(v, _b);
BoxedEnvironmentError* ee = static_cast<BoxedEnvironmentError*>(_b);
if (ee->myerrno)
v->visit(ee->myerrno);
if (ee->strerror)
v->visit(ee->strerror);
if (ee->filename)
v->visit(ee->filename);
}
};
void setupBuiltins() {
builtins_module = createModule("__builtin__", "__builtin__");
......@@ -1018,67 +888,6 @@ void setupBuiltins() {
builtins_module->giveAttr("all", new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)all, BOXED_BOOL, 1), "all"));
builtins_module->giveAttr("any", new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)any, BOXED_BOOL, 1), "any"));
BaseException = makeBuiltinException(object_cls, "BaseException", sizeof(BoxedException));
Exception = makeBuiltinException(BaseException, "Exception");
StandardError = makeBuiltinException(Exception, "StandardError");
AssertionError = makeBuiltinException(StandardError, "AssertionError");
AttributeError = makeBuiltinException(StandardError, "AttributeError");
GeneratorExit = makeBuiltinException(BaseException, "GeneratorExit");
TypeError = makeBuiltinException(StandardError, "TypeError");
NameError = makeBuiltinException(StandardError, "NameError");
LookupError = makeBuiltinException(StandardError, "LookupError");
KeyError = makeBuiltinException(LookupError, "KeyError");
IndexError = makeBuiltinException(LookupError, "IndexError");
EnvironmentError = makeBuiltinException(StandardError, "EnvironmentError", sizeof(BoxedEnvironmentError));
IOError = makeBuiltinException(EnvironmentError, "IOError");
OSError = makeBuiltinException(EnvironmentError, "OSError");
ArithmeticError = makeBuiltinException(StandardError, "ArithmeticError");
ZeroDivisionError = makeBuiltinException(ArithmeticError, "ZeroDivisionError");
ValueError = makeBuiltinException(StandardError, "ValueError");
UnboundLocalError = makeBuiltinException(NameError, "UnboundLocalError");
RuntimeError = makeBuiltinException(StandardError, "RuntimeError");
ImportError = makeBuiltinException(StandardError, "ImportError");
StopIteration = makeBuiltinException(Exception, "StopIteration");
Warning = makeBuiltinException(Exception, "Warning");
SyntaxError = makeBuiltinException(StandardError, "SyntaxError");
OverflowError = makeBuiltinException(ArithmeticError, "OverflowError");
/*ImportWarning =*/makeBuiltinException(Warning, "ImportWarning");
DeprecationWarning = makeBuiltinException(Warning, "DeprecationWarning");
/*BytesWarning =*/makeBuiltinException(Warning, "BytesWarning");
MemoryError = makeBuiltinException(StandardError, "MemoryError");
BufferError = makeBuiltinException(StandardError, "BufferError");
KeyboardInterrupt = makeBuiltinException(BaseException, "KeyboardInterrupt");
SystemExit = makeBuiltinException(BaseException, "SystemExit");
SystemError = makeBuiltinException(StandardError, "SystemError");
NotImplementedError = makeBuiltinException(RuntimeError, "NotImplementedError");
PendingDeprecationWarning = makeBuiltinException(Warning, "PendingDeprecationWarning");
EOFError = makeBuiltinException(StandardError, "EOFError");
// Unicode errors
UnicodeError = makeBuiltinException(ValueError, "UnicodeError");
UnicodeEncodeError = makeBuiltinException(UnicodeError, "UnicodeEncodeError");
UnicodeDecodeError = makeBuiltinException(UnicodeError, "UnicodeDecodeError");
UnicodeTranslateError = makeBuiltinException(UnicodeError, "UnicodeTranslateError");
BaseException->giveAttr("__reduce__",
new BoxedFunction(boxRTFunction((void*)BoxedException::__reduce__, UNKNOWN, 1)));
EnvironmentError->giveAttr("__reduce__",
new BoxedFunction(boxRTFunction((void*)BoxedEnvironmentError::__reduce__, UNKNOWN, 1)));
EnvironmentError->gc_visit = BoxedEnvironmentError::gcHandler;
EnvironmentError->giveAttr(
"__init__", new BoxedFunction(boxRTFunction((void*)BoxedEnvironmentError::__init__, NONE, 4, 3, false, false),
{ NULL, NULL, NULL }));
EnvironmentError->giveAttr(
"errno", new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT, offsetof(BoxedEnvironmentError, myerrno)));
EnvironmentError->giveAttr("strerror", new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT,
offsetof(BoxedEnvironmentError, strerror)));
EnvironmentError->giveAttr("filename", new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT,
offsetof(BoxedEnvironmentError, filename)));
EnvironmentError->giveAttr("__str__",
new BoxedFunction(boxRTFunction((void*)BoxedEnvironmentError::__str__, UNKNOWN, 1)));
repr_obj = new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)repr, UNKNOWN, 1), "repr");
builtins_module->giveAttr("repr", repr_obj);
......@@ -1228,10 +1037,5 @@ void setupBuiltins() {
builtins_module->giveAttr("classmethod", classmethod_cls);
builtins_module->giveAttr(
"eval", new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)eval, UNKNOWN, 1, 0, false, false), "eval"));
PyExc_RecursionErrorInst = new (RuntimeError) BoxedException();
gc::registerPermanentRoot(PyExc_RecursionErrorInst);
PyExc_MemoryErrorInst = new (MemoryError) BoxedException();
gc::registerPermanentRoot(PyExc_MemoryErrorInst);
}
}
......@@ -673,21 +673,24 @@ void checkAndThrowCAPIException() {
if (!tb)
tb = None;
// Make sure to call PyErr_Clear() *before* normalizing the exception, since otherwise
// the normalization can think that it had raised an exception, resulting to a call
// to checkAndThrowCAPIException, and boom.
PyErr_Clear();
// This is similar to PyErr_NormalizeException:
if (!isInstance(value, type)) {
if (value->cls == tuple_cls) {
value = runtimeCall(cur_thread_state.curexc_type, ArgPassSpec(0, 0, true, false), value, NULL, NULL,
NULL, NULL);
value = runtimeCall(type, ArgPassSpec(0, 0, true, false), value, NULL, NULL, NULL, NULL);
} else if (value == None) {
value = runtimeCall(cur_thread_state.curexc_type, ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL);
value = runtimeCall(type, ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL);
} else {
value = runtimeCall(cur_thread_state.curexc_type, ArgPassSpec(1), value, NULL, NULL, NULL, NULL);
value = runtimeCall(type, ArgPassSpec(1), value, NULL, NULL, NULL, NULL);
}
}
RELEASE_ASSERT(value->cls == type, "unsupported");
PyErr_Clear();
if (tb != None)
raiseRaw(ExcInfo(value->cls, value, tb));
raiseExc(value);
......@@ -856,6 +859,11 @@ extern "C" PyObject* PyErr_Occurred() noexcept {
}
extern "C" int PyErr_WarnEx(PyObject* category, const char* text, Py_ssize_t stacklevel) noexcept {
// These warnings are silenced by default:
// We should copy the real CPython code in here
if (category == PyExc_DeprecationWarning)
return 0;
Py_FatalError("unimplemented");
}
......
......@@ -174,12 +174,7 @@ Box* dictGetitem(BoxedDict* self, Box* k) {
auto it = self->d.find(k);
if (it == self->d.end()) {
BoxedString* s = reprOrNull(k);
if (s)
raiseExcHelper(KeyError, "%s", s->s.c_str());
else
raiseExcHelper(KeyError, "");
raiseExcHelper(KeyError, k);
}
Box* pos = self->d[k];
......@@ -306,12 +301,7 @@ Box* dictDelitem(BoxedDict* self, Box* k) {
auto it = self->d.find(k);
if (it == self->d.end()) {
BoxedString* s = reprOrNull(k);
if (s)
raiseExcHelper(KeyError, "%s", s->s.c_str());
else
raiseExcHelper(KeyError, "");
raiseExcHelper(KeyError, k);
}
self->d.erase(it);
......@@ -329,6 +319,18 @@ extern "C" int PyDict_DelItem(PyObject* op, PyObject* key) noexcept {
return 0;
}
extern "C" int PyDict_DelItemString(PyObject* v, const char* key) noexcept {
PyObject* kv;
int err;
kv = PyString_FromString(key);
if (kv == NULL)
return -1;
err = PyDict_DelItem(v, kv);
Py_DECREF(kv);
return err;
}
Box* dictPop(BoxedDict* self, Box* k, Box* d) {
if (!isSubclass(self->cls, dict_cls))
raiseExcHelper(TypeError, "descriptor 'pop' requires a 'dict' object but received a '%s'", getTypeName(self));
......@@ -338,12 +340,7 @@ Box* dictPop(BoxedDict* self, Box* k, Box* d) {
if (d)
return d;
BoxedString* s = reprOrNull(k);
if (s)
raiseExcHelper(KeyError, "%s", s->s.c_str());
else
raiseExcHelper(KeyError, "");
raiseExcHelper(KeyError, k);
}
Box* rtn = it->second;
......
......@@ -261,6 +261,13 @@ static void ensure_fromlist(Box* module, Box* fromlist, const std::string& modul
}
}
extern "C" PyObject* PyImport_ImportModule(const char* name) noexcept {
if (strcmp("__builtin__", name) == 0)
return builtins_module;
Py_FatalError("unimplemented");
}
extern "C" Box* import(int level, Box* from_imports, const std::string* module_name) {
RELEASE_ASSERT(level == -1 || level == 0, "not implemented");
......
......@@ -45,7 +45,8 @@ extern "C" long PyInt_AsLong(PyObject* op) noexcept {
if (op->cls == long_cls)
return PyLong_AsLong(op);
Py_FatalError("unimplemented");
PyErr_SetString(PyExc_TypeError, "an integer is required");
return -1;
}
extern "C" Py_ssize_t PyInt_AsSsize_t(PyObject* op) noexcept {
......
......@@ -208,7 +208,7 @@ extern "C" void assertFail(BoxedModule* inModule, Box* msg) {
BoxedString* tostr = str(msg);
raiseExcHelper(AssertionError, "%s", tostr->s.c_str());
} else {
raiseExcHelper(AssertionError, NULL);
raiseExcHelper(AssertionError, "");
}
}
......
......@@ -41,6 +41,7 @@ extern "C" Box* deopt(AST_expr* expr, Box* value);
// helper function for raising from the runtime:
void raiseExcHelper(BoxedClass*, const char* fmt, ...) __attribute__((__noreturn__));
void raiseExcHelper(BoxedClass*, Box* arg) __attribute__((__noreturn__));
BoxedModule* getCurrentModule();
......
......@@ -200,12 +200,7 @@ Box* setRemove(BoxedSet* self, Box* v) {
auto it = self->s.find(v);
if (it == self->s.end()) {
BoxedString* s = reprOrNull(v);
if (s)
raiseExcHelper(KeyError, "%s", s->s.c_str());
else
raiseExcHelper(KeyError, "");
raiseExcHelper(KeyError, v);
}
self->s.erase(it);
......
......@@ -196,9 +196,7 @@ ExcInfo::ExcInfo(Box* type, Box* value, Box* traceback) : type(type), value(valu
#endif
void ExcInfo::printExcAndTraceback() const {
std::string msg = formatException(value);
printTraceback(traceback);
fprintf(stderr, "%s\n", msg.c_str());
PyErr_Display(type, value, traceback);
}
bool ExcInfo::matches(BoxedClass* cls) const {
......@@ -242,6 +240,11 @@ void raise3(Box* arg0, Box* arg1, Box* arg2) {
getTypeName(arg0));
}
void raiseExcHelper(BoxedClass* cls, Box* arg) {
Box* exc_obj = runtimeCall(cls, ArgPassSpec(1), arg, NULL, NULL, NULL, NULL);
raiseExc(exc_obj);
}
void raiseExcHelper(BoxedClass* cls, const char* msg, ...) {
if (msg != NULL) {
va_list ap;
......@@ -265,18 +268,4 @@ void raiseExcHelper(BoxedClass* cls, const char* msg, ...) {
raiseExc(exc_obj);
}
}
std::string formatException(Box* b) {
std::string name = getTypeName(b);
BoxedString* r = strOrNull(b);
if (!r)
return name;
assert(r->cls == str_cls);
const std::string* msg = &r->s;
if (msg->size())
return name + ": " + *msg;
return name;
}
}
......@@ -559,7 +559,7 @@ extern "C" Box* createUserClass(const std::string* name, Box* _bases, Box* _attr
RELEASE_ASSERT(e.matches(BaseException), "");
Box* msg = e.value->getattr("message");
Box* msg = getattr(e.value, "message");
RELEASE_ASSERT(msg, "");
RELEASE_ASSERT(msg->cls == str_cls, "");
......@@ -834,6 +834,40 @@ Box* typeRepr(BoxedClass* self) {
return boxString(os.str());
}
static PyObject* typeModule(Box* _type, void* context) {
PyTypeObject* type = static_cast<PyTypeObject*>(_type);
PyObject* mod;
const char* s;
if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) {
mod = type->getattr("__module__");
if (!mod)
raiseExcHelper(AttributeError, "__module__");
return mod;
} else {
s = strrchr(type->tp_name, '.');
if (s != NULL)
return PyString_FromStringAndSize(type->tp_name, (Py_ssize_t)(s - type->tp_name));
return PyString_FromString("__builtin__");
}
}
static void typeSetModule(Box* _type, PyObject* value, void* context) {
PyTypeObject* type = static_cast<PyTypeObject*>(_type);
if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {
raiseExcHelper(TypeError, "can't set %s.__module__", type->tp_name);
}
if (!value) {
raiseExcHelper(TypeError, "can't delete %s.__module__", type->tp_name);
}
PyType_Modified(type);
type->setattr("__module__", value, NULL);
}
Box* typeHash(BoxedClass* self) {
assert(isSubclass(self->cls, type_cls));
......@@ -1272,6 +1306,7 @@ void setupRuntime() {
new BoxedFunction(boxRTFunction((void*)typeNew, UNKNOWN, 4, 2, false, false), { NULL, NULL }));
type_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)typeRepr, STR, 1)));
type_cls->giveAttr("__hash__", new BoxedFunction(boxRTFunction((void*)typeHash, BOXED_INT, 1)));
type_cls->giveAttr("__module__", new (pyston_getset_cls) BoxedGetsetDescriptor(typeModule, typeSetModule, NULL));
type_cls->freeze();
none_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)noneRepr, STR, 1)));
......@@ -1365,6 +1400,7 @@ void setupRuntime() {
setupSys();
setupBuiltins();
_PyExc_Init();
setupThread();
setupGC();
setupImport();
......
......@@ -613,12 +613,29 @@ extern "C" void boxGCHandler(GCVisitor* v, Box* b);
Box* objectNewNoArgs(BoxedClass* cls);
extern "C" BoxedClass* Exception, *AssertionError, *AttributeError, *TypeError, *NameError, *KeyError, *IndexError,
*IOError, *OSError, *ZeroDivisionError, *ValueError, *UnboundLocalError, *RuntimeError, *ImportError,
*StopIteration, *GeneratorExit, *SyntaxError;
Box* makeAttrWrapper(Box* b);
#define SystemError ((BoxedClass*)PyExc_SystemError)
#define StopIteration ((BoxedClass*)PyExc_StopIteration)
#define NameError ((BoxedClass*)PyExc_NameError)
#define UnboundLocalError ((BoxedClass*)PyExc_UnboundLocalError)
#define BaseException ((BoxedClass*)PyExc_BaseException)
#define TypeError ((BoxedClass*)PyExc_TypeError)
#define AssertionError ((BoxedClass*)PyExc_AssertionError)
#define ValueError ((BoxedClass*)PyExc_ValueError)
#define SystemExit ((BoxedClass*)PyExc_SystemExit)
#define SyntaxError ((BoxedClass*)PyExc_SyntaxError)
#define Exception ((BoxedClass*)PyExc_Exception)
#define AttributeError ((BoxedClass*)PyExc_AttributeError)
#define RuntimeError ((BoxedClass*)PyExc_RuntimeError)
#define ZeroDivisionError ((BoxedClass*)PyExc_ZeroDivisionError)
#define ImportError ((BoxedClass*)PyExc_ImportError)
#define IndexError ((BoxedClass*)PyExc_IndexError)
#define GeneratorExit ((BoxedClass*)PyExc_GeneratorExit)
#define IOError ((BoxedClass*)PyExc_IOError)
#define KeyError ((BoxedClass*)PyExc_KeyError)
#define OverflowError ((BoxedClass*)PyExc_OverflowError)
// Our default for tp_alloc:
PyObject* PystonType_GenericAlloc(BoxedClass* cls, Py_ssize_t nitems) noexcept;
}
......
......@@ -373,34 +373,6 @@ extern "C" Py_UNICODE _PyUnicode_ToUppercase(Py_UNICODE ch) noexcept {
Py_FatalError("unimplemented");
}
extern "C" int PyUnicodeEncodeError_GetStart(PyObject*, Py_ssize_t*) noexcept {
Py_FatalError("unimplemented");
}
extern "C" int PyUnicodeDecodeError_GetStart(PyObject*, Py_ssize_t*) noexcept {
Py_FatalError("unimplemented");
}
extern "C" int PyUnicodeTranslateError_GetStart(PyObject*, Py_ssize_t*) noexcept {
Py_FatalError("unimplemented");
}
extern "C" int PyUnicodeEncodeError_GetEnd(PyObject*, Py_ssize_t*) noexcept {
Py_FatalError("unimplemented");
}
extern "C" int PyUnicodeDecodeError_GetEnd(PyObject*, Py_ssize_t*) noexcept {
Py_FatalError("unimplemented");
}
extern "C" int PyUnicodeTranslateError_GetEnd(PyObject*, Py_ssize_t*) noexcept {
Py_FatalError("unimplemented");
}
extern "C" PyObject* PyUnicodeEncodeError_GetObject(PyObject*) noexcept {
Py_FatalError("unimplemented");
}
extern "C" PyObject* _PyUnicode_DecodeUnicodeInternal(const char* s, Py_ssize_t size, const char* errors) noexcept {
Py_FatalError("unimplemented");
}
......
# expected: fail
# - exception printing
class BadException(Exception):
def __str__(self):
print "str"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment