Commit 9e30d6dc authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge pull request #398 from rntz/with-exceptions

in merge:
- with_ctxclass_instance_attrs now succeeds due to d1387d74
- merge ~conflict in LangPrimitive opcodes
parents 3c042a82 449cb458
...@@ -36,6 +36,7 @@ stdlib*.ll ...@@ -36,6 +36,7 @@ stdlib*.ll
oprofile_data oprofile_data
pprof.jit pprof.jit
tags tags
TAGS
*.pyc *.pyc
perf.data perf.data
......
...@@ -37,6 +37,9 @@ VERBOSE := 0 ...@@ -37,6 +37,9 @@ VERBOSE := 0
ENABLE_INTEL_JIT_EVENTS := 0 ENABLE_INTEL_JIT_EVENTS := 0
CTAGS := ctags
ETAGS := ctags-exuberant -e
# Setting this to 1 will set the Makefile to use binaries from the trunk # Setting this to 1 will set the Makefile to use binaries from the trunk
# directory, even if USE_TEST_LLVM is set to 1. # directory, even if USE_TEST_LLVM is set to 1.
# This is useful if clang isn't installed into the test directory, ex due # This is useful if clang isn't installed into the test directory, ex due
...@@ -408,7 +411,11 @@ all: pyston_dbg pyston_release pyston_prof ext_python ext_pyston unittests ...@@ -408,7 +411,11 @@ all: pyston_dbg pyston_release pyston_prof ext_python ext_pyston unittests
ALL_HEADERS := $(wildcard src/*/*.h) $(wildcard src/*/*/*.h) $(wildcard from_cpython/Include/*.h) ALL_HEADERS := $(wildcard src/*/*.h) $(wildcard src/*/*/*.h) $(wildcard from_cpython/Include/*.h)
tags: $(SRCS) $(OPTIONAL_SRCS) $(FROM_CPYTHON_SRCS) $(ALL_HEADERS) tags: $(SRCS) $(OPTIONAL_SRCS) $(FROM_CPYTHON_SRCS) $(ALL_HEADERS)
$(ECHO) Calculating tags... $(ECHO) Calculating tags...
$(VERB) ctags $^ $(VERB) $(CTAGS) $^
TAGS: $(SRCS) $(OPTIONAL_SRCS) $(FROM_CPYTHON_SRCS) $(ALL_HEADERS)
$(ECHO) Calculating TAGS...
$(VERB) $(ETAGS) $^
NON_ENTRY_OBJS := $(filter-out src/jit.o,$(OBJS)) NON_ENTRY_OBJS := $(filter-out src/jit.o,$(OBJS))
......
...@@ -511,7 +511,9 @@ private: ...@@ -511,7 +511,9 @@ private:
} }
} }
void visit_classdef(AST_ClassDef* node) override { void* visit_makeclass(AST_MakeClass* mkclass) override {
AST_ClassDef* node = mkclass->class_def;
for (auto d : node->decorator_list) { for (auto d : node->decorator_list) {
getType(d); getType(d);
} }
...@@ -521,9 +523,8 @@ private: ...@@ -521,9 +523,8 @@ private:
} }
// TODO should we speculate that classdefs will generally return a class? // TODO should we speculate that classdefs will generally return a class?
// CompilerType* t = typeFromClass(type_cls); // return typeFromClass(type_cls);
CompilerType* t = UNKNOWN; return UNKNOWN;
_doSet(scope_info->mangleName(node->name), t);
} }
void visit_delete(AST_Delete* node) override { void visit_delete(AST_Delete* node) override {
...@@ -551,7 +552,9 @@ private: ...@@ -551,7 +552,9 @@ private:
} }
} }
void visit_functiondef(AST_FunctionDef* node) override { void* visit_makefunction(AST_MakeFunction* mkfn) override {
AST_FunctionDef* node = mkfn->function_def;
for (auto d : node->decorator_list) { for (auto d : node->decorator_list) {
getType(d); getType(d);
} }
...@@ -563,7 +566,7 @@ private: ...@@ -563,7 +566,7 @@ private:
CompilerType* t = UNKNOWN; CompilerType* t = UNKNOWN;
if (node->decorator_list.empty()) if (node->decorator_list.empty())
t = typeFromClass(function_cls); t = typeFromClass(function_cls);
_doSet(scope_info->mangleName(node->name), t); return t;
} }
void visit_global(AST_Global* node) override {} void visit_global(AST_Global* node) override {}
......
...@@ -88,10 +88,8 @@ private: ...@@ -88,10 +88,8 @@ private:
Value visit_assign(AST_Assign* node); Value visit_assign(AST_Assign* node);
Value visit_binop(AST_BinOp* node); Value visit_binop(AST_BinOp* node);
Value visit_call(AST_Call* node); Value visit_call(AST_Call* node);
Value visit_classDef(AST_ClassDef* node);
Value visit_compare(AST_Compare* node); Value visit_compare(AST_Compare* node);
Value visit_delete(AST_Delete* node); Value visit_delete(AST_Delete* node);
Value visit_functionDef(AST_FunctionDef* node);
Value visit_global(AST_Global* node); Value visit_global(AST_Global* node);
Value visit_module(AST_Module* node); Value visit_module(AST_Module* node);
Value visit_print(AST_Print* node); Value visit_print(AST_Print* node);
...@@ -117,6 +115,8 @@ private: ...@@ -117,6 +115,8 @@ private:
Value visit_tuple(AST_Tuple* node); Value visit_tuple(AST_Tuple* node);
Value visit_yield(AST_Yield* node); Value visit_yield(AST_Yield* node);
Value visit_makeClass(AST_MakeClass* node);
Value visit_makeFunction(AST_MakeFunction* node);
// pseudo // pseudo
Value visit_augBinOp(AST_AugBinOp* node); Value visit_augBinOp(AST_AugBinOp* node);
...@@ -605,14 +605,10 @@ Value ASTInterpreter::visit_stmt(AST_stmt* node) { ...@@ -605,14 +605,10 @@ Value ASTInterpreter::visit_stmt(AST_stmt* node) {
return visit_assert((AST_Assert*)node); return visit_assert((AST_Assert*)node);
case AST_TYPE::Assign: case AST_TYPE::Assign:
return visit_assign((AST_Assign*)node); return visit_assign((AST_Assign*)node);
case AST_TYPE::ClassDef:
return visit_classDef((AST_ClassDef*)node);
case AST_TYPE::Delete: case AST_TYPE::Delete:
return visit_delete((AST_Delete*)node); return visit_delete((AST_Delete*)node);
case AST_TYPE::Expr: case AST_TYPE::Expr:
return visit_expr((AST_Expr*)node); return visit_expr((AST_Expr*)node);
case AST_TYPE::FunctionDef:
return visit_functionDef((AST_FunctionDef*)node);
case AST_TYPE::Pass: case AST_TYPE::Pass:
return Value(); // nothing todo return Value(); // nothing todo
case AST_TYPE::Print: case AST_TYPE::Print:
...@@ -690,7 +686,8 @@ Box* ASTInterpreter::createFunction(AST* node, AST_arguments* args, const std::v ...@@ -690,7 +686,8 @@ Box* ASTInterpreter::createFunction(AST* node, AST_arguments* args, const std::v
return boxCLFunction(cl, closure, is_generator, u.il); return boxCLFunction(cl, closure, is_generator, u.il);
} }
Value ASTInterpreter::visit_functionDef(AST_FunctionDef* node) { Value ASTInterpreter::visit_makeFunction(AST_MakeFunction* mkfn) {
AST_FunctionDef* node = mkfn->function_def;
AST_arguments* args = node->args; AST_arguments* args = node->args;
std::vector<Box*, StlCompatAllocator<Box*>> decorators; std::vector<Box*, StlCompatAllocator<Box*>> decorators;
...@@ -702,11 +699,11 @@ Value ASTInterpreter::visit_functionDef(AST_FunctionDef* node) { ...@@ -702,11 +699,11 @@ Value ASTInterpreter::visit_functionDef(AST_FunctionDef* node) {
for (int i = decorators.size() - 1; i >= 0; i--) for (int i = decorators.size() - 1; i >= 0; i--)
func = runtimeCall(decorators[i], ArgPassSpec(1), func, 0, 0, 0, 0); func = runtimeCall(decorators[i], ArgPassSpec(1), func, 0, 0, 0, 0);
doStore(source_info->mangleName(node->name), func); return Value(func);
return Value();
} }
Value ASTInterpreter::visit_classDef(AST_ClassDef* node) { Value ASTInterpreter::visit_makeClass(AST_MakeClass* mkclass) {
AST_ClassDef* node = mkclass->class_def;
ScopeInfo* scope_info = source_info->scoping->getScopeInfoForNode(node); ScopeInfo* scope_info = source_info->scoping->getScopeInfoForNode(node);
assert(scope_info); assert(scope_info);
...@@ -729,8 +726,7 @@ Value ASTInterpreter::visit_classDef(AST_ClassDef* node) { ...@@ -729,8 +726,7 @@ Value ASTInterpreter::visit_classDef(AST_ClassDef* node) {
for (int i = decorators.size() - 1; i >= 0; i--) for (int i = decorators.size() - 1; i >= 0; i--)
classobj = runtimeCall(decorators[i], ArgPassSpec(1), classobj, 0, 0, 0, 0); classobj = runtimeCall(decorators[i], ArgPassSpec(1), classobj, 0, 0, 0, 0);
doStore(source_info->mangleName(node->name), classobj); return Value(classobj);
return Value();
} }
Value ASTInterpreter::visit_raise(AST_Raise* node) { Value ASTInterpreter::visit_raise(AST_Raise* node) {
...@@ -896,6 +892,10 @@ Value ASTInterpreter::visit_expr(AST_expr* node) { ...@@ -896,6 +892,10 @@ Value ASTInterpreter::visit_expr(AST_expr* node) {
return visit_clsAttribute((AST_ClsAttribute*)node); return visit_clsAttribute((AST_ClsAttribute*)node);
case AST_TYPE::LangPrimitive: case AST_TYPE::LangPrimitive:
return visit_langPrimitive((AST_LangPrimitive*)node); return visit_langPrimitive((AST_LangPrimitive*)node);
case AST_TYPE::MakeClass:
return visit_makeClass((AST_MakeClass*)node);
case AST_TYPE::MakeFunction:
return visit_makeFunction((AST_MakeFunction*)node);
default: default:
RELEASE_ASSERT(0, ""); RELEASE_ASSERT(0, "");
}; };
......
...@@ -757,6 +757,8 @@ CompilerVariable* makeFunction(IREmitter& emitter, CLFunction* f, CompilerVariab ...@@ -757,6 +757,8 @@ CompilerVariable* makeFunction(IREmitter& emitter, CLFunction* f, CompilerVariab
llvm::Value* isGenerator_v = llvm::ConstantInt::get(g.i1, isGenerator, false); llvm::Value* isGenerator_v = llvm::ConstantInt::get(g.i1, isGenerator, false);
// We know this function call can't throw, so it's safe to use emitter.getBuilder()->CreateCall() rather than
// emitter.createCall().
llvm::Value* boxed = emitter.getBuilder()->CreateCall( llvm::Value* boxed = emitter.getBuilder()->CreateCall(
g.funcs.boxCLFunction, g.funcs.boxCLFunction,
std::vector<llvm::Value*>{ embedConstantPtr(f, g.llvm_clfunction_type_ptr), closure_v, isGenerator_v, scratch, std::vector<llvm::Value*>{ embedConstantPtr(f, g.llvm_clfunction_type_ptr), closure_v, isGenerator_v, scratch,
......
...@@ -291,7 +291,7 @@ private: ...@@ -291,7 +291,7 @@ private:
protected: protected:
void drop(IREmitter& emitter) override { type->drop(emitter, this); } void drop(IREmitter& emitter) override { type->drop(emitter, this); }
void grab(IREmitter& emmitter) override { type->grab(emmitter, this); } void grab(IREmitter& emitter) override { type->grab(emitter, this); }
public: public:
ValuedCompilerVariable(T* type, V value, bool grabbed) : CompilerVariable(grabbed), type(type), value(value) { ValuedCompilerVariable(T* type, V value, bool grabbed) : CompilerVariable(grabbed), type(type), value(value) {
......
This diff is collapsed.
This diff is collapsed.
...@@ -95,10 +95,14 @@ public: ...@@ -95,10 +95,14 @@ public:
ParamNames* getParamNames() { return param_names; } ParamNames* getParamNames() { return param_names; }
}; };
// turns CFGBlocks into LLVM IR
class IRGenerator { class IRGenerator {
private: private:
public: public:
struct EndingState { struct EndingState {
// symbol_table records which Python variables are bound to what CompilerVariables at the end of this block.
// phi_symbol_table records the ones that will need to be `phi'd.
// both only record non-globals.
SymbolTable* symbol_table; SymbolTable* symbol_table;
ConcreteSymbolTable* phi_symbol_table; ConcreteSymbolTable* phi_symbol_table;
llvm::BasicBlock* ending_block; llvm::BasicBlock* ending_block;
...@@ -113,7 +117,7 @@ public: ...@@ -113,7 +117,7 @@ public:
virtual void giveLocalSymbol(InternedString name, CompilerVariable* var) = 0; virtual void giveLocalSymbol(InternedString name, CompilerVariable* var) = 0;
virtual void copySymbolsFrom(SymbolTable* st) = 0; virtual void copySymbolsFrom(SymbolTable* st) = 0;
virtual void run(const CFGBlock* block) = 0; virtual void run(const CFGBlock* block) = 0; // primary entry point
virtual EndingState getEndingSymbolTable() = 0; virtual EndingState getEndingSymbolTable() = 0;
virtual void doSafePoint() = 0; virtual void doSafePoint() = 0;
virtual void addFrameStackmapArgs(PatchpointInfo* pp, AST_stmt* current_stmt, virtual void addFrameStackmapArgs(PatchpointInfo* pp, AST_stmt* current_stmt,
......
...@@ -953,7 +953,6 @@ void AST_Branch::accept_stmt(StmtVisitor* v) { ...@@ -953,7 +953,6 @@ void AST_Branch::accept_stmt(StmtVisitor* v) {
v->visit_branch(this); v->visit_branch(this);
} }
void AST_Jump::accept(ASTVisitor* v) { void AST_Jump::accept(ASTVisitor* v) {
bool skip = v->visit_jump(this); bool skip = v->visit_jump(this);
if (skip) if (skip)
...@@ -976,7 +975,29 @@ void* AST_ClsAttribute::accept_expr(ExprVisitor* v) { ...@@ -976,7 +975,29 @@ void* AST_ClsAttribute::accept_expr(ExprVisitor* v) {
return v->visit_clsattribute(this); return v->visit_clsattribute(this);
} }
void AST_MakeFunction::accept(ASTVisitor* v) {
bool skip = v->visit_makefunction(this);
if (skip)
return;
function_def->accept(v);
}
void* AST_MakeFunction::accept_expr(ExprVisitor* v) {
return v->visit_makefunction(this);
}
void AST_MakeClass::accept(ASTVisitor* v) {
bool skip = v->visit_makeclass(this);
if (skip)
return;
class_def->accept(v);
}
void* AST_MakeClass::accept_expr(ExprVisitor* v) {
return v->visit_makeclass(this);
}
void print_ast(AST* ast) { void print_ast(AST* ast) {
PrintVisitor v; PrintVisitor v;
...@@ -1851,6 +1872,16 @@ bool PrintVisitor::visit_clsattribute(AST_ClsAttribute* node) { ...@@ -1851,6 +1872,16 @@ bool PrintVisitor::visit_clsattribute(AST_ClsAttribute* node) {
return true; return true;
} }
bool PrintVisitor::visit_makefunction(AST_MakeFunction* node) {
printf("make_");
return false;
}
bool PrintVisitor::visit_makeclass(AST_MakeClass* node) {
printf("make_");
return false;
}
class FlattenVisitor : public ASTVisitor { class FlattenVisitor : public ASTVisitor {
private: private:
std::vector<AST*>* output; std::vector<AST*>* output;
...@@ -2098,6 +2129,15 @@ public: ...@@ -2098,6 +2129,15 @@ public:
output->push_back(node); output->push_back(node);
return false; return false;
} }
virtual bool visit_makeclass(AST_MakeClass* node) {
output->push_back(node);
return false;
}
virtual bool visit_makefunction(AST_MakeFunction* node) {
output->push_back(node);
return false;
}
}; };
void flatten(const std::vector<AST_stmt*>& roots, std::vector<AST*>& output, bool expand_scopes) { void flatten(const std::vector<AST_stmt*>& roots, std::vector<AST*>& output, bool expand_scopes) {
......
...@@ -118,7 +118,7 @@ enum AST_TYPE { ...@@ -118,7 +118,7 @@ enum AST_TYPE {
DictComp = 15, DictComp = 15,
Set = 43, Set = 43,
Ellipsis = 87, Ellipsis = 87,
Expression = 88, Expression = 88, // like Module, but used for eval.
SetComp = 89, SetComp = 89,
// Pseudo-nodes that are specific to this compiler: // Pseudo-nodes that are specific to this compiler:
...@@ -128,6 +128,8 @@ enum AST_TYPE { ...@@ -128,6 +128,8 @@ enum AST_TYPE {
AugBinOp = 203, AugBinOp = 203,
Invoke = 204, Invoke = 204,
LangPrimitive = 205, LangPrimitive = 205,
MakeClass = 206, // wraps a ClassDef to make it an expr
MakeFunction = 207, // wraps a FunctionDef to make it an expr
// These aren't real AST types, but since we use AST types to represent binexp types // 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): // and divmod+truediv are essentially types of binops, we add them here (at least for now):
...@@ -951,6 +953,31 @@ public: ...@@ -951,6 +953,31 @@ public:
static const AST_TYPE::AST_TYPE TYPE = AST_TYPE::Yield; static const AST_TYPE::AST_TYPE TYPE = AST_TYPE::Yield;
}; };
class AST_MakeFunction : public AST_expr {
public:
AST_FunctionDef* function_def;
virtual void accept(ASTVisitor* v);
virtual void* accept_expr(ExprVisitor* v);
AST_MakeFunction(AST_FunctionDef* fd)
: AST_expr(AST_TYPE::MakeFunction, fd->lineno, fd->col_offset), function_def(fd) {}
static const AST_TYPE::AST_TYPE TYPE = AST_TYPE::MakeFunction;
};
class AST_MakeClass : public AST_expr {
public:
AST_ClassDef* class_def;
virtual void accept(ASTVisitor* v);
virtual void* accept_expr(ExprVisitor* v);
AST_MakeClass(AST_ClassDef* cd) : AST_expr(AST_TYPE::MakeClass, cd->lineno, cd->col_offset), class_def(cd) {}
static const AST_TYPE::AST_TYPE TYPE = AST_TYPE::MakeClass;
};
// AST pseudo-nodes that will get added during CFG-construction. These don't exist in the input AST, but adding them in // AST pseudo-nodes that will get added during CFG-construction. These don't exist in the input AST, but adding them in
// lets us avoid creating a completely new IR for this phase // lets us avoid creating a completely new IR for this phase
...@@ -1019,14 +1046,14 @@ public: ...@@ -1019,14 +1046,14 @@ public:
class AST_LangPrimitive : public AST_expr { class AST_LangPrimitive : public AST_expr {
public: public:
enum Opcodes { enum Opcodes {
LANDINGPAD, LANDINGPAD, // grabs the info about the last raised exception
LOCALS, LOCALS,
GET_ITER, GET_ITER,
IMPORT_FROM, IMPORT_FROM,
IMPORT_NAME, IMPORT_NAME,
IMPORT_STAR, IMPORT_STAR,
NONE, NONE,
NONZERO, NONZERO, // determines whether something is "true" for purposes of `if' and so forth
CHECK_EXC_MATCH, CHECK_EXC_MATCH,
SET_EXC_INFO, SET_EXC_INFO,
UNCACHE_EXC_INFO, UNCACHE_EXC_INFO,
...@@ -1115,6 +1142,8 @@ public: ...@@ -1115,6 +1142,8 @@ public:
virtual bool visit_with(AST_With* node) { RELEASE_ASSERT(0, ""); } virtual bool visit_with(AST_With* node) { RELEASE_ASSERT(0, ""); }
virtual bool visit_yield(AST_Yield* node) { RELEASE_ASSERT(0, ""); } virtual bool visit_yield(AST_Yield* node) { RELEASE_ASSERT(0, ""); }
virtual bool visit_makeclass(AST_MakeClass* node) { RELEASE_ASSERT(0, ""); }
virtual bool visit_makefunction(AST_MakeFunction* node) { RELEASE_ASSERT(0, ""); }
virtual bool visit_branch(AST_Branch* node) { RELEASE_ASSERT(0, ""); } virtual bool visit_branch(AST_Branch* node) { RELEASE_ASSERT(0, ""); }
virtual bool visit_jump(AST_Jump* node) { RELEASE_ASSERT(0, ""); } virtual bool visit_jump(AST_Jump* node) { RELEASE_ASSERT(0, ""); }
}; };
...@@ -1187,6 +1216,8 @@ public: ...@@ -1187,6 +1216,8 @@ public:
virtual bool visit_branch(AST_Branch* node) { return false; } virtual bool visit_branch(AST_Branch* node) { return false; }
virtual bool visit_jump(AST_Jump* node) { return false; } virtual bool visit_jump(AST_Jump* node) { return false; }
virtual bool visit_makeclass(AST_MakeClass* node) { return false; }
virtual bool visit_makefunction(AST_MakeFunction* node) { return false; }
}; };
class ExprVisitor { class ExprVisitor {
...@@ -1223,6 +1254,8 @@ public: ...@@ -1223,6 +1254,8 @@ public:
virtual void* visit_tuple(AST_Tuple* node) { RELEASE_ASSERT(0, ""); } virtual void* visit_tuple(AST_Tuple* node) { RELEASE_ASSERT(0, ""); }
virtual void* visit_unaryop(AST_UnaryOp* node) { RELEASE_ASSERT(0, ""); } virtual void* visit_unaryop(AST_UnaryOp* node) { RELEASE_ASSERT(0, ""); }
virtual void* visit_yield(AST_Yield* node) { RELEASE_ASSERT(0, ""); } virtual void* visit_yield(AST_Yield* node) { RELEASE_ASSERT(0, ""); }
virtual void* visit_makeclass(AST_MakeClass* node) { RELEASE_ASSERT(0, ""); }
virtual void* visit_makefunction(AST_MakeFunction* node) { RELEASE_ASSERT(0, ""); }
}; };
class StmtVisitor { class StmtVisitor {
...@@ -1332,6 +1365,8 @@ public: ...@@ -1332,6 +1365,8 @@ public:
virtual bool visit_branch(AST_Branch* node); virtual bool visit_branch(AST_Branch* node);
virtual bool visit_jump(AST_Jump* node); virtual bool visit_jump(AST_Jump* node);
virtual bool visit_makefunction(AST_MakeFunction* node);
virtual bool visit_makeclass(AST_MakeClass* node);
}; };
// Given an AST node, return a vector of the node plus all its descendents. // Given an AST node, return a vector of the node plus all its descendents.
......
This diff is collapsed.
...@@ -56,6 +56,7 @@ public: ...@@ -56,6 +56,7 @@ public:
void unconnectFrom(CFGBlock* successor); void unconnectFrom(CFGBlock* successor);
void push_back(AST_stmt* node) { body.push_back(node); } void push_back(AST_stmt* node) { body.push_back(node); }
void print();
}; };
// Control Flow Graph // Control Flow Graph
...@@ -79,6 +80,9 @@ public: ...@@ -79,6 +80,9 @@ public:
return block; return block;
} }
// Creates a block which must be placed later, using placeBlock().
// Must be placed on same CFG it was created on.
// You can also safely delete it without placing it.
CFGBlock* addDeferredBlock() { CFGBlock* addDeferredBlock() {
CFGBlock* block = new CFGBlock(this, -1); CFGBlock* block = new CFGBlock(this, -1);
return block; return block;
......
...@@ -39,6 +39,8 @@ ...@@ -39,6 +39,8 @@
#define _CAT(A, B) A##B #define _CAT(A, B) A##B
#define CAT(A, B) _CAT(A, B) #define CAT(A, B) _CAT(A, B)
#define ARRAY_LEN(arr) (sizeof(arr) / sizeof((arr)[0]))
// GCC and clang handle always_inline very differently; // GCC and clang handle always_inline very differently;
// we mostly only care about it for the stdlib, so just remove the attributes // we mostly only care about it for the stdlib, so just remove the attributes
// if we're not in clang // if we're not in clang
......
...@@ -55,7 +55,9 @@ bool endswith(const std::string& s, const std::string& pattern); ...@@ -55,7 +55,9 @@ bool endswith(const std::string& s, const std::string& pattern);
void removeDirectoryIfExists(const std::string& path); void removeDirectoryIfExists(const std::string& path);
template <class T1, class T2> void compareKeyset(T1* lhs, T2* rhs) { // Checks that lhs and rhs, which are iterables of InternedStrings, have the
// same set of names in them.
template <class T1, class T2> bool sameKeyset(T1* lhs, T2* rhs) {
std::vector<InternedString> lv, rv; std::vector<InternedString> lv, rv;
for (typename T1::iterator it = lhs->begin(); it != lhs->end(); it++) { for (typename T1::iterator it = lhs->begin(); it != lhs->end(); it++) {
lv.push_back(it->first); lv.push_back(it->first);
...@@ -92,7 +94,7 @@ template <class T1, class T2> void compareKeyset(T1* lhs, T2* rhs) { ...@@ -92,7 +94,7 @@ template <class T1, class T2> void compareKeyset(T1* lhs, T2* rhs) {
} }
good = false; good = false;
} }
assert(good); return good;
} }
} }
......
...@@ -800,10 +800,6 @@ Box* fileEnter(BoxedFile* self) { ...@@ -800,10 +800,6 @@ Box* fileEnter(BoxedFile* self) {
Box* fileExit(BoxedFile* self, Box* exc_type, Box* exc_val, Box** args) { Box* fileExit(BoxedFile* self, Box* exc_type, Box* exc_val, Box** args) {
Box* exc_tb = args[0]; Box* exc_tb = args[0];
assert(self->cls == file_cls); assert(self->cls == file_cls);
assert(exc_type == None);
assert(exc_val == None);
assert(exc_tb == None);
fileClose(self); fileClose(self);
return None; return None;
} }
......
...@@ -390,6 +390,9 @@ std::string BoxedModule::name() { ...@@ -390,6 +390,9 @@ std::string BoxedModule::name() {
} }
} }
// This mustn't throw; our IR generator generates calls to it without "invoke" even when there are exception handlers /
// finally-blocks in scope.
// TODO: should we use C++11 `noexcept' here?
extern "C" Box* boxCLFunction(CLFunction* f, BoxedClosure* closure, bool isGenerator, extern "C" Box* boxCLFunction(CLFunction* f, BoxedClosure* closure, bool isGenerator,
std::initializer_list<Box*> defaults) { std::initializer_list<Box*> defaults) {
if (closure) if (closure)
......
# expected: fail
# - with statements
class TestException(Exception): class TestException(Exception):
pass pass
...@@ -361,7 +358,11 @@ def f12(): ...@@ -361,7 +358,11 @@ def f12():
except Exception as l[0]: except Exception as l[0]:
print "shouldnt get here" print "shouldnt get here"
except Exception as e2: except Exception as e2:
print e2 # print it to stderr, so that our tester's error message substituter can
# deal with differences between error messages between different Python
# versions.
import traceback
traceback.print_exc()
l = [] l = []
try: try:
......
# expected: fail
import sys
print sys.stdout.closed
# these may seem pointless, but they exercise a family of corner cases in our
# CFG generation pass (cfg.cpp).
def returner():
try:
try:
print '2 + 2'
return
finally:
print 'finally'
except:
print 'exception'
returner()
def continuer():
for x in [1]:
try:
try:
print '2 + 2'
continue
finally:
print 'finally'
except:
print 'exception'
continuer()
def breaker():
for x in [1]:
try:
try:
print '2 + 2'
break
finally:
print 'finally'
except:
print 'exception'
breaker()
def raiser():
try:
try:
print '2 + 2'
raise Exception('blaaargh')
finally:
print 'finally'
except:
print 'exception'
raiser()
def alltogethernow():
for x in [1,2,3,4]:
try:
try:
print '2 + 2'
if x == 1: break
if x == 2: continue
if x == 3: raise Exception('blaargh')
if x == 4: return
finally:
print 'finally'
except:
print 'exception'
alltogethernow()
# we have one test at global scope, another at local.
# they behave differently in codegen; there have been points at which either was bugged when the other was not.
try:
class C(object):
print 'here'
finally:
print 'finally'
def f():
try:
class C(object):
print 'here'
finally:
print 'finally'
f()
try:
class D(object):
print 'here'
except:
print 'impossible'
raise
def f2():
try:
class D(object):
print 'here'
except:
print 'impossible'
print D
raise
f2()
# expected: fail
# Syntax error to have a continue outside a loop.
def foo():
try: continue
finally: pass
def f():
try:
def foo(): return 0
except:
print 'except'
finally:
print 'finally'
f()
def f2():
try:
def foo(): return 0
except:
print 'except'
f2()
def f3():
try:
def foo(): return 0
finally:
print 'finally'
f3()
def f():
try:
# Looks like this returns from the function, but it needs to go to the finally block
return
finally:
pass
f()
def f():
# originally this exposed a bug in our irgen phase, so even `with None`
# failed here; the bug happened before actual execution. Just to test more
# things, though, we use an actual contextmanager here.
with open('/dev/null'):
class C(object):
print 'hello'
f()
def f():
C = 23
try:
class C(object): pass
except:
print 'except: C = %s' % C
raise
finally:
print 'finally: C = %s' % C
print 'end: C = %s' % C
f()
# should_error
class Mgr(object):
def __enter__(self):
print 'entered!'
def __exit__(self, *args):
print 'exited!'
with Mgr() as m:
continue
class Mgr(object):
def __init__(self): self.__enter__ = 'sucks to be you'
def __enter__(self): pass
def __exit__(self, typ, val, tback): pass
with Mgr() as m:
print 'boom boom boom boom'
class Mgr2(object):
def __init__(self): self.__exit__ = 'screwed!'
def __enter__(self): pass
def __exit__(self, typ, val, tback): pass
with Mgr2() as m:
print 'bang bang bang bang'
class Mgr(object):
def __init__(self): print 'Mgr.__init__()'
@property
def __enter__(self):
print 'Mgr.__enter__ accessed'
def enterer(*args):
print 'Mgr.__enter__ called'
return 23
return enterer
@property
def __exit__(self):
print 'Mgr.__exit__ accessed'
def exiter(*args):
print 'Mgr.__exit__ called'
return False
return exiter
with Mgr() as m:
print 'hello I am a with block'
print 'm: %s' % m
try:
with Mgr() as m:
1/0
print "you can't get there from here"
except ZeroDivisionError, e:
print e
f = open('/dev/null')
try:
with f:
1/0
except ZeroDivisionError as e:
print e
try:
f.readline()
except ValueError as e:
print e
def f():
# this exposes a bug in our irgen phase, so even `with None` bugs out here;
# the bug happens before actual execution. Just to test more things, though,
# we use an actual contextmanager here.
with open('/dev/null'):
def foo():
pass
f()
...@@ -115,6 +115,7 @@ def canonicalize_stderr(stderr): ...@@ -115,6 +115,7 @@ def canonicalize_stderr(stderr):
("NameError: global name '", "NameError: name '"), ("NameError: global name '", "NameError: name '"),
("AttributeError: '(\w+)' object attribute '(\w+)' is read-only", "AttributeError: \\2"), ("AttributeError: '(\w+)' object attribute '(\w+)' is read-only", "AttributeError: \\2"),
(r"TypeError: object.__new__\(\) takes no parameters", "TypeError: object() takes no parameters"), (r"TypeError: object.__new__\(\) takes no parameters", "TypeError: object() takes no parameters"),
("IndexError: list assignment index out of range", "IndexError: list index out of range"),
] ]
for pattern, subst_with in substitutions: for pattern, subst_with in substitutions:
......
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