Commit 28f055ef authored by Kevin Modzelewski's avatar Kevin Modzelewski

Add continue/break out of finally, sys.exc_clear

parent 0a9db607
......@@ -468,35 +468,40 @@ const LineInfo* getMostRecentLineInfo() {
return lineInfoForFrame(*frame);
}
ExcInfo getFrameExcInfo() {
ExcInfo* getFrameExcInfo() {
std::vector<ExcInfo*> to_update;
ExcInfo* copy_from_exc = NULL;
ExcInfo* cur_exc = NULL;
for (PythonFrameIterator& frame_iter : unwindPythonFrames()) {
FrameInfo* frame_info = frame_iter.getFrameInfo();
cur_exc = &frame_info->exc;
if (!cur_exc->type) {
to_update.push_back(cur_exc);
copy_from_exc = &frame_info->exc;
if (!cur_exc)
cur_exc = copy_from_exc;
if (!copy_from_exc->type) {
to_update.push_back(copy_from_exc);
continue;
}
break;
}
assert(cur_exc); // Only way this could still be NULL is if there weren't any python frames
assert(copy_from_exc); // Only way this could still be NULL is if there weren't any python frames
if (!cur_exc->type) {
if (!copy_from_exc->type) {
// No exceptions found:
*cur_exc = ExcInfo(None, None, None);
*copy_from_exc = ExcInfo(None, None, None);
}
assert(cur_exc->value);
assert(cur_exc->traceback);
assert(copy_from_exc->value);
assert(copy_from_exc->traceback);
for (auto* ex : to_update) {
*ex = *cur_exc;
*ex = *copy_from_exc;
}
return *cur_exc;
assert(cur_exc);
return cur_exc;
}
CompiledFunction* getTopCompiledFunction() {
......
......@@ -29,8 +29,9 @@ BoxedModule* getCurrentModule();
class BoxedDict;
BoxedDict* getLocals(bool only_user_visible);
// Fetches the frame-local excinfo object, calculating it if necessary (from previous frames):
ExcInfo getFrameExcInfo();
// Fetches a writeable pointer to the frame-local excinfo object,
// calculating it if necessary (from previous frames).
ExcInfo* getFrameExcInfo();
}
#endif
......@@ -157,7 +157,7 @@ private:
AST_Jump* j = makeJump();
j->target = region.continue_dest;
curblock->connectTo(region.continue_dest);
curblock->connectTo(region.continue_dest, true);
push_back(j);
curblock = NULL;
return;
......@@ -177,7 +177,7 @@ private:
AST_Jump* j = makeJump();
j->target = region.break_dest;
curblock->connectTo(region.break_dest);
curblock->connectTo(region.break_dest, true);
push_back(j);
curblock = NULL;
return;
......@@ -2016,10 +2016,8 @@ public:
exc_handlers.pop_back();
int did_why = regions.back().did_why; // bad to just reach in like this
assert((did_why & (1 << Why::BREAK)) == 0); // haven't added this yet
assert((did_why & (1 << Why::CONTINUE)) == 0); // haven't added this yet
popRegion(); // finally region
int did_why = regions.back().did_why; // bad to just reach in like this
popRegion(); // finally region
if (curblock) {
// assign the exc_*_name variables to tell irgen that they won't be undefined?
......@@ -2053,6 +2051,7 @@ public:
}
if (curblock) {
// TODO: these 4 cases are pretty copy-pasted from each other:
if (did_why & (1 << Why::RETURN)) {
CFGBlock* doreturn = cfg->addBlock();
CFGBlock* otherwise = cfg->addBlock();
......@@ -2076,8 +2075,51 @@ public:
curblock = otherwise;
}
CFGBlock* reraise = cfg->addBlock();
CFGBlock* noexc = cfg->addBlock();
if (did_why & (1 << Why::BREAK)) {
CFGBlock* doreturn = cfg->addBlock();
CFGBlock* otherwise = cfg->addBlock();
AST_Compare* compare = new AST_Compare();
compare->ops.push_back(AST_TYPE::Eq);
compare->left = makeName(exc_why_name, AST_TYPE::Load, node->lineno);
compare->comparators.push_back(makeNum(Why::BREAK));
AST_Branch* br = new AST_Branch();
br->test = callNonzero(compare);
br->iftrue = doreturn;
br->iffalse = otherwise;
curblock->connectTo(doreturn);
curblock->connectTo(otherwise);
push_back(br);
curblock = doreturn;
doBreak();
curblock = otherwise;
}
if (did_why & (1 << Why::CONTINUE)) {
CFGBlock* doreturn = cfg->addBlock();
CFGBlock* otherwise = cfg->addBlock();
AST_Compare* compare = new AST_Compare();
compare->ops.push_back(AST_TYPE::Eq);
compare->left = makeName(exc_why_name, AST_TYPE::Load, node->lineno);
compare->comparators.push_back(makeNum(Why::CONTINUE));
AST_Branch* br = new AST_Branch();
br->test = callNonzero(compare);
br->iftrue = doreturn;
br->iffalse = otherwise;
curblock->connectTo(doreturn);
curblock->connectTo(otherwise);
push_back(br);
curblock = doreturn;
doContinue();
curblock = otherwise;
}
AST_Compare* compare = new AST_Compare();
compare->ops.push_back(AST_TYPE::Eq);
......@@ -2086,6 +2128,10 @@ public:
AST_Branch* br = new AST_Branch();
br->test = callNonzero(compare);
CFGBlock* reraise = cfg->addBlock();
CFGBlock* noexc = cfg->addBlock();
br->iftrue = reraise;
br->iffalse = noexc;
curblock->connectTo(reraise);
......
......@@ -33,11 +33,24 @@ BoxedModule* sys_module;
BoxedDict* sys_modules_dict;
Box* sysExcInfo() {
ExcInfo exc = getFrameExcInfo();
assert(exc.type);
assert(exc.value);
assert(exc.traceback);
return new BoxedTuple({ exc.type, exc.value, exc.traceback });
ExcInfo* exc = getFrameExcInfo();
assert(exc->type);
assert(exc->value);
assert(exc->traceback);
return new BoxedTuple({ exc->type, exc->value, exc->traceback });
}
Box* sysExcClear() {
ExcInfo* exc = getFrameExcInfo();
assert(exc->type);
assert(exc->value);
assert(exc->traceback);
exc->type = None;
exc->value = None;
exc->traceback = None;
return None;
}
static Box* sysExit(Box* arg) {
......@@ -212,6 +225,7 @@ void setupSys() {
sys_module->giveAttr("stderr", new BoxedFile(stderr, "<stderr>", "w"));
sys_module->giveAttr("exc_info", new BoxedFunction(boxRTFunction((void*)sysExcInfo, BOXED_TUPLE, 0)));
sys_module->giveAttr("exc_clear", new BoxedFunction(boxRTFunction((void*)sysExcClear, NONE, 0)));
sys_module->giveAttr("exit", new BoxedFunction(boxRTFunction((void*)sysExit, NONE, 1, 1, false, false), { None }));
sys_module->giveAttr("warnoptions", new BoxedList());
......
......@@ -1695,7 +1695,9 @@ extern "C" bool nonzero(Box* obj) {
func = getclsattr_internal(obj, "__len__", NULL);
if (func == NULL) {
ASSERT(isUserDefined(obj->cls) || obj->cls == classobj_cls || obj->cls == type_cls, "%s.__nonzero__",
ASSERT(isUserDefined(obj->cls) || obj->cls == classobj_cls || obj->cls == type_cls
|| isSubclass(obj->cls, Exception),
"%s.__nonzero__",
getTypeName(obj)->c_str()); // TODO
return true;
}
......
......@@ -219,7 +219,14 @@ extern "C" void exit(int code) {
}
void raise0() {
raiseRaw(getFrameExcInfo());
ExcInfo* exc_info = getFrameExcInfo();
assert(exc_info->type);
// TODO need to clean up when we call normalize, do_raise, etc
if (exc_info->type == None)
raiseExcHelper(TypeError, "exceptions must be old-style classes or derived from BaseException, not NoneType");
raiseRaw(*exc_info);
}
bool ExcInfo::matches(BoxedClass* cls) const {
......@@ -230,6 +237,8 @@ bool ExcInfo::matches(BoxedClass* cls) const {
void raise3(Box* arg0, Box* arg1, Box* arg2) {
RELEASE_ASSERT(arg2 == None, "unsupported");
// TODO switch this to PyErr_Normalize
if (isSubclass(arg0->cls, type_cls)) {
BoxedClass* c = static_cast<BoxedClass*>(arg0);
if (isSubclass(c, Exception)) {
......
# expected: fail
# - try-finally not supported yet
#
# try-finally support
import sys
......@@ -278,7 +275,7 @@ def f6():
except:
pass
print sys.exc_info()
print sys.exc_info()[0]
if reraise:
raise
......@@ -299,8 +296,9 @@ def f6():
inner(False, True)
# Shouldn't get here
raise Exception()
except TypeError:
except TypeError, e:
print "Got TypeError as expected, since exc_info was None"
print e
f6()
def f7():
......
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