Commit c4067082 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge branch 'tryfinally'

parents 1c25c150 d0672808
......@@ -297,7 +297,6 @@ public:
virtual bool visit_print(AST_Print* node) { return true; }
virtual bool visit_raise(AST_Raise* node) { return true; }
virtual bool visit_return(AST_Return* node) { return true; }
virtual bool visit_unreachable(AST_Unreachable* node) { return true; }
virtual bool visit_classdef(AST_ClassDef* node) {
_doSet(node->name);
......
......@@ -594,8 +594,6 @@ private:
}
}
void visit_unreachable(AST_Unreachable* node) override {}
public:
static void propagate(CFGBlock* block, const TypeMap& starting, TypeMap& ending, ExprTypeMap& expr_types,
TypeSpeculations& type_speculations, TypeAnalysis::SpeculationLevel speculation,
......
......@@ -827,7 +827,7 @@ static void emitBBs(IRGenState* irstate, const char* bb_type, GuardList& out_gua
if (full_blocks.count(b2) == 0 && partial_blocks.count(b2) == 0)
continue;
// printf("%d %d %ld %ld\n", b->idx, b2->idx, phi_ending_symbol_tables[b2]->size(), phis->size());
// printf("(%d %ld) -> (%d %ld)\n", b2->idx, phi_ending_symbol_tables[b2]->size(), b->idx, phis->size());
compareKeyset(phi_ending_symbol_tables[b2], phis);
assert(phi_ending_symbol_tables[b2]->size() == phis->size());
}
......
......@@ -2178,10 +2178,6 @@ private:
case AST_TYPE::Raise:
doRaise(ast_cast<AST_Raise>(node), unw_info);
break;
case AST_TYPE::Unreachable:
emitter.getBuilder()->CreateUnreachable();
endBlock(FINISHED);
break;
default:
printf("Unhandled stmt type at " __FILE__ ":" STRINGIFY(__LINE__) ": %d\n", node->type);
exit(1);
......@@ -2208,6 +2204,8 @@ private:
SourceInfo* source = irstate->getSourceInfo();
ScopeInfo* scope_info = irstate->getScopeInfo();
// Additional names to remove; remove them after iteration is done to new mess up the iterators
std::vector<std::string> also_remove;
for (SymbolTable::iterator it = symbol_table.begin(); it != symbol_table.end();) {
if (allowableFakeEndingSymbol(it->first)) {
++it;
......@@ -2220,6 +2218,8 @@ private:
if (!source->liveness->isLiveAtEnd(it->first, myblock)) {
// printf("%s dead at end of %d; grabbed = %d, %d vrefs\n", it->first.c_str(), myblock->idx,
// it->second->isGrabbed(), it->second->getVrefs());
also_remove.push_back(getIsDefinedName(it->first));
it->second->decvref(emitter);
it = symbol_table.erase(it);
} else if (source->phis->isRequiredAfter(it->first, myblock)) {
......@@ -2249,6 +2249,10 @@ private:
}
}
for (const auto& s : also_remove) {
symbol_table.erase(s);
}
const PhiAnalysis::RequiredSet& all_phis = source->phis->getAllRequiredAfter(myblock);
for (PhiAnalysis::RequiredSet::const_iterator it = all_phis.begin(), end = all_phis.end(); it != end; ++it) {
// printf("phi will be required for %s\n", it->c_str());
......
......@@ -61,7 +61,7 @@ AST_TYPE::AST_TYPE readItem(pypa::AstBoolOpType type) {
break;
}
assert("Unknown AstBoolOpType" && false);
return AST_TYPE::Unreachable;
abort();
}
AST_TYPE::AST_TYPE readItem(pypa::AstBinOpType type) {
......@@ -94,7 +94,7 @@ AST_TYPE::AST_TYPE readItem(pypa::AstBinOpType type) {
break;
}
assert("Unknown AstBinOpType" && false);
return AST_TYPE::Unreachable;
abort();
}
AST_TYPE::AST_TYPE readItem(pypa::AstUnaryOpType type) {
......@@ -111,7 +111,7 @@ AST_TYPE::AST_TYPE readItem(pypa::AstUnaryOpType type) {
break;
}
assert("Unknown AstUnaryOpType" && false);
return AST_TYPE::Unreachable;
abort();
}
......@@ -162,7 +162,7 @@ AST_TYPE::AST_TYPE readItem(pypa::AstCompareOpType type) {
break;
}
assert("Unknown AstCompareOpType" && false);
return AST_TYPE::Unreachable;
abort();
}
std::string readName(pypa::AstExpression& e) {
......
......@@ -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
......@@ -869,16 +869,6 @@ void* AST_UnaryOp::accept_expr(ExprVisitor* v) {
return v->visit_unaryop(this);
}
void AST_Unreachable::accept(ASTVisitor* v) {
bool skip = v->visit_unreachable(this);
if (skip)
return;
}
void AST_Unreachable::accept_stmt(StmtVisitor* v) {
v->visit_unreachable(this);
}
void AST_While::accept(ASTVisitor* v) {
bool skip = v->visit_while(this);
if (skip)
......@@ -1726,11 +1716,6 @@ bool PrintVisitor::visit_unaryop(AST_UnaryOp* node) {
return true;
}
bool PrintVisitor::visit_unreachable(AST_Unreachable* node) {
printf("<unreachable>");
return true;
}
bool PrintVisitor::visit_while(AST_While* node) {
printf("while ");
node->test->accept(this);
......@@ -2025,10 +2010,6 @@ public:
output->push_back(node);
return false;
}
virtual bool visit_unreachable(AST_Unreachable* node) {
output->push_back(node);
return false;
}
virtual bool visit_while(AST_While* node) {
output->push_back(node);
return false;
......
......@@ -125,7 +125,6 @@ enum AST_TYPE {
AugBinOp = 203,
Invoke = 204,
LangPrimitive = 205,
Unreachable = 206,
// These aren't real AST types, but since we use AST types to represent binexp types
// and divmod+truediv are essentially types of binops, we add them here (at least for now):
......@@ -989,16 +988,6 @@ public:
static const AST_TYPE::AST_TYPE TYPE = AST_TYPE::LangPrimitive;
};
class AST_Unreachable : public AST_stmt {
public:
virtual void accept(ASTVisitor* v);
virtual void accept_stmt(StmtVisitor* v);
AST_Unreachable() : AST_stmt(AST_TYPE::Unreachable) {}
static const AST_TYPE::AST_TYPE TYPE = AST_TYPE::Unreachable;
};
template <typename T> T* ast_cast(AST* node) {
assert(node->type == T::TYPE);
return static_cast<T*>(node);
......@@ -1066,7 +1055,6 @@ public:
virtual bool visit_tryfinally(AST_TryFinally* node) { RELEASE_ASSERT(0, ""); }
virtual bool visit_tuple(AST_Tuple* node) { RELEASE_ASSERT(0, ""); }
virtual bool visit_unaryop(AST_UnaryOp* node) { RELEASE_ASSERT(0, ""); }
virtual bool visit_unreachable(AST_Unreachable* node) { RELEASE_ASSERT(0, ""); }
virtual bool visit_while(AST_While* node) { RELEASE_ASSERT(0, ""); }
virtual bool visit_with(AST_With* node) { RELEASE_ASSERT(0, ""); }
virtual bool visit_yield(AST_Yield* node) { RELEASE_ASSERT(0, ""); }
......@@ -1135,7 +1123,6 @@ public:
virtual bool visit_tryfinally(AST_TryFinally* node) { return false; }
virtual bool visit_tuple(AST_Tuple* node) { return false; }
virtual bool visit_unaryop(AST_UnaryOp* node) { return false; }
virtual bool visit_unreachable(AST_Unreachable* node) { return false; }
virtual bool visit_while(AST_While* node) { return false; }
virtual bool visit_with(AST_With* node) { return false; }
virtual bool visit_yield(AST_Yield* node) { return false; }
......@@ -1206,7 +1193,6 @@ public:
virtual void visit_return(AST_Return* node) { RELEASE_ASSERT(0, ""); }
virtual void visit_tryexcept(AST_TryExcept* node) { RELEASE_ASSERT(0, ""); }
virtual void visit_tryfinally(AST_TryFinally* node) { RELEASE_ASSERT(0, ""); }
virtual void visit_unreachable(AST_Unreachable* node) { RELEASE_ASSERT(0, ""); }
virtual void visit_while(AST_While* node) { RELEASE_ASSERT(0, ""); }
virtual void visit_with(AST_With* node) { RELEASE_ASSERT(0, ""); }
......@@ -1279,7 +1265,6 @@ public:
virtual bool visit_tryexcept(AST_TryExcept* node);
virtual bool visit_tryfinally(AST_TryFinally* node);
virtual bool visit_unaryop(AST_UnaryOp* node);
virtual bool visit_unreachable(AST_Unreachable* node);
virtual bool visit_while(AST_While* node);
virtual bool visit_with(AST_With* node);
virtual bool visit_yield(AST_Yield* node);
......
This diff is collapsed.
......@@ -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, "%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
......@@ -22,6 +19,19 @@ print basic_finally(1)
print basic_finally(0)
print
# If we return from inside the try part of a try-finally, we have to save the return value,
# execute the finally block, then do the actual return.
print "finally_after_return"
def finally_after_return():
try:
print 1
return 2
finally:
print 3
print 4
print finally_after_return()
print
# Return from a finally will disable any exception propagation:
print "return_from_finally"
def return_from_finally(to_throw=None):
......@@ -87,19 +97,6 @@ except Exception, e:
print e
print
# If we return from inside the try part of a try-finally, we have to save the return value,
# execute the finally block, then do the actual return.
print "finally_after_return"
def finally_after_return():
try:
print 1
return 2
finally:
print 3
print 4
print finally_after_return()
print
# Similarly for continues
print "finally_after_continue"
def finally_after_continue():
......@@ -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