Commit 5bbd4c50 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Wow, I guess augassign is quite a bit more complicated than I thought

parent d498e5ca
...@@ -72,23 +72,6 @@ class LivenessBBVisitor : public NoopASTVisitor { ...@@ -72,23 +72,6 @@ class LivenessBBVisitor : public NoopASTVisitor {
} }
return true; return true;
} }
bool visit_augassign(AST_AugAssign* node) {
AST* target = node->target;
switch(target->type) {
case AST_TYPE::Name: {
AST_Name* n = static_cast<AST_Name*>(target);
_doLoad(n->id);
_doStore(n->id);
break;
}
default:
RELEASE_ASSERT(0, "%d", target->type);
}
node->value->accept(this);
return true;
}
}; };
bool LivenessAnalysis::isLiveAtEnd(const std::string &name, CFGBlock *block) { bool LivenessAnalysis::isLiveAtEnd(const std::string &name, CFGBlock *block) {
...@@ -227,11 +210,6 @@ class DefinednessVisitor : public ASTVisitor { ...@@ -227,11 +210,6 @@ class DefinednessVisitor : public ASTVisitor {
return true; return true;
} }
virtual bool visit_augassign(AST_AugAssign *node) {
_doSet(node->target);
return true;
}
virtual bool visit_arguments(AST_arguments *node) { virtual bool visit_arguments(AST_arguments *node) {
if (node->kwarg) _doSet(node->kwarg); if (node->kwarg) _doSet(node->kwarg);
if (node->vararg.size()) _doSet(node->vararg); if (node->vararg.size()) _doSet(node->vararg);
......
...@@ -158,7 +158,6 @@ class BasicBlockTypePropagator : public ExprVisitor, public StmtVisitor { ...@@ -158,7 +158,6 @@ class BasicBlockTypePropagator : public ExprVisitor, public StmtVisitor {
virtual void* visit_attribute(AST_Attribute *node) { virtual void* visit_attribute(AST_Attribute *node) {
CompilerType *t = getType(node->value); CompilerType *t = getType(node->value);
assert(node->ctx_type == AST_TYPE::Load);
CompilerType *rtn = t->getattrType(&node->attr, false); CompilerType *rtn = t->getattrType(&node->attr, false);
//if (speculation != TypeAnalysis::NONE && (node->attr == "x" || node->attr == "y" || node->attr == "z")) { //if (speculation != TypeAnalysis::NONE && (node->attr == "x" || node->attr == "y" || node->attr == "z")) {
...@@ -184,6 +183,31 @@ class BasicBlockTypePropagator : public ExprVisitor, public StmtVisitor { ...@@ -184,6 +183,31 @@ class BasicBlockTypePropagator : public ExprVisitor, public StmtVisitor {
return rtn; return rtn;
} }
virtual void* visit_augbinop(AST_AugBinOp *node) {
CompilerType *left = getType(node->left);
CompilerType *right = getType(node->right);
// TODO this isn't the exact behavior
std::string name = getOpName(node->op_type);
name = "__i" + name.substr(2);
CompilerType *attr_type = left->getattrType(&name, true);
if (attr_type == UNDEF)
attr_type = UNKNOWN;
std::vector<CompilerType*> arg_types;
arg_types.push_back(right);
CompilerType *rtn = attr_type->callType(arg_types);
if (left == right && (left == INT || left == FLOAT)) {
ASSERT((rtn == left || rtn == UNKNOWN) && "not strictly required but probably something worth looking into", "%s %s %s -> %s", left->debugName().c_str(), name.c_str(), right->debugName().c_str(), rtn->debugName().c_str());
}
ASSERT(rtn != UNDEF, "need to implement the actual semantics here for %s.%s", left->debugName().c_str(), name.c_str());
return rtn;
}
virtual void* visit_binop(AST_BinOp *node) { virtual void* visit_binop(AST_BinOp *node) {
CompilerType *left = getType(node->left); CompilerType *left = getType(node->left);
CompilerType *right = getType(node->right); CompilerType *right = getType(node->right);
...@@ -192,14 +216,19 @@ class BasicBlockTypePropagator : public ExprVisitor, public StmtVisitor { ...@@ -192,14 +216,19 @@ class BasicBlockTypePropagator : public ExprVisitor, public StmtVisitor {
std::string name = getOpName(node->op_type); std::string name = getOpName(node->op_type);
CompilerType *attr_type = left->getattrType(&name, true); CompilerType *attr_type = left->getattrType(&name, true);
if (attr_type == UNDEF)
attr_type = UNKNOWN;
std::vector<CompilerType*> arg_types; std::vector<CompilerType*> arg_types;
arg_types.push_back(right); arg_types.push_back(right);
CompilerType *rtn = attr_type->callType(arg_types); CompilerType *rtn = attr_type->callType(arg_types);
if (left == right && (left == INT || left == FLOAT)) { if (left == right && (left == INT || left == FLOAT)) {
ASSERT((rtn == left || rtn == UNDEF) && "not strictly required but probably something worth looking into", "%s %s", name.c_str(), rtn->debugName().c_str()); ASSERT((rtn == left || rtn == UNKNOWN) && "not strictly required but probably something worth looking into", "%s %s %s -> %s", left->debugName().c_str(), name.c_str(), right->debugName().c_str(), rtn->debugName().c_str());
} }
ASSERT(rtn != UNDEF, "need to implement the actual semantics here for %s.%s", left->debugName().c_str(), name.c_str());
return rtn; return rtn;
} }
...@@ -254,6 +283,10 @@ class BasicBlockTypePropagator : public ExprVisitor, public StmtVisitor { ...@@ -254,6 +283,10 @@ class BasicBlockTypePropagator : public ExprVisitor, public StmtVisitor {
} }
std::string name = getOpName(node->ops[0]); std::string name = getOpName(node->ops[0]);
CompilerType *attr_type = left->getattrType(&name, true); CompilerType *attr_type = left->getattrType(&name, true);
if (attr_type == UNDEF)
attr_type = UNKNOWN;
std::vector<CompilerType*> arg_types; std::vector<CompilerType*> arg_types;
arg_types.push_back(right); arg_types.push_back(right);
return attr_type->callType(arg_types); return attr_type->callType(arg_types);
...@@ -297,10 +330,10 @@ class BasicBlockTypePropagator : public ExprVisitor, public StmtVisitor { ...@@ -297,10 +330,10 @@ class BasicBlockTypePropagator : public ExprVisitor, public StmtVisitor {
CompilerType* &t = sym_table[node->id]; CompilerType* &t = sym_table[node->id];
if (t == NULL) { if (t == NULL) {
if (VERBOSITY() >= 2) { //if (VERBOSITY() >= 2) {
printf("%s is undefined!\n", node->id.c_str()); //printf("%s is undefined!\n", node->id.c_str());
raise(SIGTRAP); //raise(SIGTRAP);
} //}
t = UNDEF; t = UNDEF;
} }
return t; return t;
...@@ -362,31 +395,6 @@ class BasicBlockTypePropagator : public ExprVisitor, public StmtVisitor { ...@@ -362,31 +395,6 @@ class BasicBlockTypePropagator : public ExprVisitor, public StmtVisitor {
} }
} }
virtual void visit_augassign(AST_AugAssign* node) {
CompilerType *t = getType(node->target);
CompilerType *v = getType(node->value);
// TODO this isn't the right behavior
std::string name = getOpName(node->op_type);
name = "__i" + name.substr(2);
CompilerType *attr_type = t->getattrType(&name, true);
ASSERT(attr_type != UNDEF, "need to implement the actual semantics here");
std::vector<CompilerType*> arg_types;
arg_types.push_back(v);
CompilerType *rtn = attr_type->callType(arg_types);
if (VERBOSITY() >= 2) printf("%s aug= %s -> %s\n", t->debugName().c_str(), v->debugName().c_str(), rtn->debugName().c_str());
if (t == INT && v == INT)
assert(rtn == INT);
if (t == FLOAT && v == FLOAT)
assert(rtn == FLOAT);
_doSet(node->target, rtn);
}
virtual void visit_branch(AST_Branch* node) { virtual void visit_branch(AST_Branch* node) {
if (EXPAND_UNNEEDED) { if (EXPAND_UNNEEDED) {
getType(node->test); getType(node->test);
...@@ -483,9 +491,14 @@ class PropagatingTypeAnalysis : public TypeAnalysis { ...@@ -483,9 +491,14 @@ class PropagatingTypeAnalysis : public TypeAnalysis {
return true; return true;
} }
if (lhs == UNDEF || rhs == UNDEF) if (lhs == UNDEF)
return false; return false;
if (rhs == UNDEF) {
rhs = lhs;
return true;
}
if (lhs == rhs) if (lhs == rhs)
return false; return false;
if (rhs == UNKNOWN) if (rhs == UNKNOWN)
......
...@@ -1081,6 +1081,15 @@ class StrConstantType : public ValuedCompilerType<std::string*> { ...@@ -1081,6 +1081,15 @@ class StrConstantType : public ValuedCompilerType<std::string*> {
return rtn; return rtn;
} }
virtual CompilerVariable* dup(VAR *var, DupCache &cache) {
CompilerVariable* &rtn = cache[var];
if (rtn == NULL) {
rtn = new VAR(this, var->getValue(), var->isGrabbed());
}
return rtn;
}
}; };
ValuedCompilerType<std::string*> *STR_CONSTANT = new StrConstantType(); ValuedCompilerType<std::string*> *STR_CONSTANT = new StrConstantType();
......
...@@ -218,7 +218,6 @@ class IRGeneratorImpl : public IRGenerator { ...@@ -218,7 +218,6 @@ class IRGeneratorImpl : public IRGenerator {
CompilerVariable* evalAttribute(AST_Attribute *node) { CompilerVariable* evalAttribute(AST_Attribute *node) {
assert(state != PARTIAL); assert(state != PARTIAL);
assert(node->ctx_type == AST_TYPE::Load);
CompilerVariable *value = evalExpr(node->value); CompilerVariable *value = evalExpr(node->value);
...@@ -237,7 +236,7 @@ class IRGeneratorImpl : public IRGenerator { ...@@ -237,7 +236,7 @@ class IRGeneratorImpl : public IRGenerator {
} }
enum BinExpType { enum BinExpType {
AugAssign, AugBinOp,
BinOp, BinOp,
Compare, Compare,
}; };
...@@ -257,7 +256,7 @@ class IRGeneratorImpl : public IRGenerator { ...@@ -257,7 +256,7 @@ class IRGeneratorImpl : public IRGenerator {
v = emitter.getBuilder()->CreateCall2(g.funcs.div_i64_i64, converted_left->getValue(), converted_right->getValue()); v = emitter.getBuilder()->CreateCall2(g.funcs.div_i64_i64, converted_left->getValue(), converted_right->getValue());
} else if (type == AST_TYPE::Pow) { } else if (type == AST_TYPE::Pow) {
v = emitter.getBuilder()->CreateCall2(g.funcs.pow_i64_i64, converted_left->getValue(), converted_right->getValue()); v = emitter.getBuilder()->CreateCall2(g.funcs.pow_i64_i64, converted_left->getValue(), converted_right->getValue());
} else if (exp_type == BinOp || exp_type == AugAssign) { } else if (exp_type == BinOp || exp_type == AugBinOp) {
llvm::Instruction::BinaryOps binopcode; llvm::Instruction::BinaryOps binopcode;
switch (type) { switch (type) {
case AST_TYPE::Add: case AST_TYPE::Add:
...@@ -347,7 +346,7 @@ class IRGeneratorImpl : public IRGenerator { ...@@ -347,7 +346,7 @@ class IRGeneratorImpl : public IRGenerator {
v = emitter.getBuilder()->CreateCall2(g.funcs.div_float_float, converted_left->getValue(), converted_right->getValue()); v = emitter.getBuilder()->CreateCall2(g.funcs.div_float_float, converted_left->getValue(), converted_right->getValue());
} else if (type == AST_TYPE::Pow) { } else if (type == AST_TYPE::Pow) {
v = emitter.getBuilder()->CreateCall2(g.funcs.pow_float_float, converted_left->getValue(), converted_right->getValue()); v = emitter.getBuilder()->CreateCall2(g.funcs.pow_float_float, converted_left->getValue(), converted_right->getValue());
} else if (exp_type == BinOp || exp_type == AugAssign) { } else if (exp_type == BinOp || exp_type == AugBinOp) {
llvm::Instruction::BinaryOps binopcode; llvm::Instruction::BinaryOps binopcode;
switch (type) { switch (type) {
case AST_TYPE::Add: case AST_TYPE::Add:
...@@ -428,9 +427,9 @@ class IRGeneratorImpl : public IRGenerator { ...@@ -428,9 +427,9 @@ class IRGeneratorImpl : public IRGenerator {
if (exp_type == BinOp) { if (exp_type == BinOp) {
rt_func = g.funcs.binop; rt_func = g.funcs.binop;
rt_func_addr = (void*)binop; rt_func_addr = (void*)binop;
} else if (exp_type == AugAssign) { } else if (exp_type == AugBinOp) {
rt_func = g.funcs.augassign; rt_func = g.funcs.augbinop;
rt_func_addr = (void*)augassign; rt_func_addr = (void*)augbinop;
} else { } else {
rt_func = g.funcs.compare; rt_func = g.funcs.compare;
rt_func_addr = (void*)compare; rt_func_addr = (void*)compare;
...@@ -471,6 +470,20 @@ class IRGeneratorImpl : public IRGenerator { ...@@ -471,6 +470,20 @@ class IRGeneratorImpl : public IRGenerator {
return rtn; return rtn;
} }
CompilerVariable* evalAugBinOp(AST_AugBinOp *node) {
assert(state != PARTIAL);
CompilerVariable *left = evalExpr(node->left);
CompilerVariable *right = evalExpr(node->right);
assert(node->op_type != AST_TYPE::Is && node->op_type != AST_TYPE::IsNot && "not tested yet");
CompilerVariable *rtn = this->_evalBinExp(left, right, node->op_type, AugBinOp);
left->decvref(emitter);
right->decvref(emitter);
return rtn;
}
CompilerVariable* evalCompare(AST_Compare *node) { CompilerVariable* evalCompare(AST_Compare *node) {
assert(state != PARTIAL); assert(state != PARTIAL);
...@@ -790,6 +803,9 @@ class IRGeneratorImpl : public IRGenerator { ...@@ -790,6 +803,9 @@ class IRGeneratorImpl : public IRGenerator {
case AST_TYPE::Attribute: case AST_TYPE::Attribute:
rtn = evalAttribute(static_cast<AST_Attribute*>(node)); rtn = evalAttribute(static_cast<AST_Attribute*>(node));
break; break;
case AST_TYPE::AugBinOp:
rtn = evalAugBinOp(static_cast<AST_AugBinOp*>(node));
break;
case AST_TYPE::BinOp: case AST_TYPE::BinOp:
rtn = evalBinOp(static_cast<AST_BinOp*>(node)); rtn = evalBinOp(static_cast<AST_BinOp*>(node));
break; break;
...@@ -1097,20 +1113,6 @@ class IRGeneratorImpl : public IRGenerator { ...@@ -1097,20 +1113,6 @@ class IRGeneratorImpl : public IRGenerator {
val->decvref(emitter); val->decvref(emitter);
} }
void doAugAssign(AST_AugAssign *node) {
CompilerVariable *target = evalExpr(node->target);
CompilerVariable *val = evalExpr(node->value);
if (state == PARTIAL)
return;
CompilerVariable *rtn = this->_evalBinExp(target, val, node->op_type, AugAssign);
target->decvref(emitter);
val->decvref(emitter);
_doSet(node->target, rtn);
rtn->decvref(emitter);
}
void doClassDef(AST_ClassDef *node) { void doClassDef(AST_ClassDef *node) {
if (state == PARTIAL) if (state == PARTIAL)
return; return;
...@@ -1453,9 +1455,6 @@ class IRGeneratorImpl : public IRGenerator { ...@@ -1453,9 +1455,6 @@ class IRGeneratorImpl : public IRGenerator {
case AST_TYPE::Assign: case AST_TYPE::Assign:
doAssign(static_cast<AST_Assign*>(node)); doAssign(static_cast<AST_Assign*>(node));
break; break;
case AST_TYPE::AugAssign:
doAugAssign(static_cast<AST_AugAssign*>(node));
break;
case AST_TYPE::ClassDef: case AST_TYPE::ClassDef:
doClassDef(static_cast<AST_ClassDef*>(node)); doClassDef(static_cast<AST_ClassDef*>(node));
break; break;
......
...@@ -140,7 +140,7 @@ PatchpointSetupInfo* createGetGlobalPatchpoint(CompiledFunction *parent_cf) { ...@@ -140,7 +140,7 @@ PatchpointSetupInfo* createGetGlobalPatchpoint(CompiledFunction *parent_cf) {
} }
PatchpointSetupInfo* createBinexpPatchpoint(CompiledFunction *parent_cf) { PatchpointSetupInfo* createBinexpPatchpoint(CompiledFunction *parent_cf) {
return PatchpointSetupInfo::initialize(true, 4, 160, parent_cf, Binexp); return PatchpointSetupInfo::initialize(true, 4, 196, parent_cf, Binexp);
} }
PatchpointSetupInfo* createNonzeroPatchpoint(CompiledFunction *parent_cf) { PatchpointSetupInfo* createNonzeroPatchpoint(CompiledFunction *parent_cf) {
......
...@@ -151,7 +151,7 @@ void initGlobalFuncs(GlobalState &g) { ...@@ -151,7 +151,7 @@ void initGlobalFuncs(GlobalState &g) {
GET(getGlobal); GET(getGlobal);
GET(binop); GET(binop);
GET(compare); GET(compare);
GET(augassign); GET(augbinop);
GET(nonzero); GET(nonzero);
GET(print); GET(print);
GET(unboxedLen); GET(unboxedLen);
......
...@@ -21,7 +21,7 @@ struct GlobalFuncs { ...@@ -21,7 +21,7 @@ struct GlobalFuncs {
llvm::Value *printf, *my_assert, *malloc, *free; llvm::Value *printf, *my_assert, *malloc, *free;
llvm::Value *boxInt, *unboxInt, *boxFloat, *unboxFloat, *boxStringPtr, *boxCLFunction, *unboxCLFunction, *boxInstanceMethod, *boxBool, *unboxBool, *createTuple, *createDict, *createList, *createSlice, *createClass; llvm::Value *boxInt, *unboxInt, *boxFloat, *unboxFloat, *boxStringPtr, *boxCLFunction, *unboxCLFunction, *boxInstanceMethod, *boxBool, *unboxBool, *createTuple, *createDict, *createList, *createSlice, *createClass;
llvm::Value *getattr, *setattr, *print, *nonzero, *binop, *compare, *augassign, *unboxedLen, *getitem, *getclsattr, *getGlobal, *setitem, *unaryop, *import; llvm::Value *getattr, *setattr, *print, *nonzero, *binop, *compare, *augbinop, *unboxedLen, *getitem, *getclsattr, *getGlobal, *setitem, *unaryop, *import;
llvm::Value *checkUnpackingLength, *raiseAttributeError, *raiseAttributeErrorStr, *raiseNotIterableError, *assertNameDefined; llvm::Value *checkUnpackingLength, *raiseAttributeError, *raiseAttributeErrorStr, *raiseNotIterableError, *assertNameDefined;
llvm::Value *printFloat, *listAppendInternal; llvm::Value *printFloat, *listAppendInternal;
llvm::Value *dump; llvm::Value *dump;
......
...@@ -217,6 +217,18 @@ void AST_AugAssign::accept_stmt(StmtVisitor *v) { ...@@ -217,6 +217,18 @@ void AST_AugAssign::accept_stmt(StmtVisitor *v) {
v->visit_augassign(this); v->visit_augassign(this);
} }
void AST_AugBinOp::accept(ASTVisitor *v) {
bool skip = v->visit_augbinop(this);
if (skip) return;
left->accept(v);
right->accept(v);
}
void* AST_AugBinOp::accept_expr(ExprVisitor *v) {
return v->visit_augbinop(this);
}
void AST_Attribute::accept(ASTVisitor *v) { void AST_Attribute::accept(ASTVisitor *v) {
bool skip = v->visit_attribute(this); bool skip = v->visit_attribute(this);
if (skip) return; if (skip) return;
...@@ -726,6 +738,14 @@ bool PrintVisitor::visit_augassign(AST_AugAssign *node) { ...@@ -726,6 +738,14 @@ bool PrintVisitor::visit_augassign(AST_AugAssign *node) {
return true; return true;
} }
bool PrintVisitor::visit_augbinop(AST_AugBinOp *node) {
node->left->accept(this);
printf("=");
printOp(node->op_type);
node->right->accept(this);
return true;
}
bool PrintVisitor::visit_attribute(AST_Attribute *node) { bool PrintVisitor::visit_attribute(AST_Attribute *node) {
node->value->accept(this); node->value->accept(this);
putchar('.'); putchar('.');
...@@ -996,6 +1016,7 @@ bool PrintVisitor::visit_module(AST_Module *node) { ...@@ -996,6 +1016,7 @@ bool PrintVisitor::visit_module(AST_Module *node) {
bool PrintVisitor::visit_name(AST_Name *node) { bool PrintVisitor::visit_name(AST_Name *node) {
printf("%s", node->id.c_str()); printf("%s", node->id.c_str());
//printf("%s(%d)", node->id.c_str(), node->ctx_type);
return false; return false;
} }
...@@ -1179,6 +1200,7 @@ class FlattenVisitor : public ASTVisitor { ...@@ -1179,6 +1200,7 @@ class FlattenVisitor : public ASTVisitor {
virtual bool visit_arguments(AST_arguments *node) { output->push_back(node); return false; } virtual bool visit_arguments(AST_arguments *node) { output->push_back(node); return false; }
virtual bool visit_assign(AST_Assign *node) { output->push_back(node); return false; } virtual bool visit_assign(AST_Assign *node) { output->push_back(node); return false; }
virtual bool visit_augassign(AST_AugAssign *node) { output->push_back(node); return false; } virtual bool visit_augassign(AST_AugAssign *node) { output->push_back(node); return false; }
virtual bool visit_augbinop(AST_AugBinOp *node) { output->push_back(node); return false; }
virtual bool visit_attribute(AST_Attribute *node) { output->push_back(node); return false; } virtual bool visit_attribute(AST_Attribute *node) { output->push_back(node); return false; }
virtual bool visit_binop(AST_BinOp *node) { output->push_back(node); return false; } virtual bool visit_binop(AST_BinOp *node) { output->push_back(node); return false; }
virtual bool visit_boolop(AST_BoolOp *node) { output->push_back(node); return false; } virtual bool visit_boolop(AST_BoolOp *node) { output->push_back(node); return false; }
......
...@@ -119,6 +119,7 @@ namespace AST_TYPE { ...@@ -119,6 +119,7 @@ namespace AST_TYPE {
Branch = 200, Branch = 200,
Jump = 201, Jump = 201,
ClsAttribute = 202, ClsAttribute = 202,
AugBinOp = 203,
}; };
}; };
...@@ -197,6 +198,17 @@ class AST_AugAssign : public AST_stmt { ...@@ -197,6 +198,17 @@ class AST_AugAssign : public AST_stmt {
AST_AugAssign() : AST_stmt(AST_TYPE::AugAssign) {} AST_AugAssign() : AST_stmt(AST_TYPE::AugAssign) {}
}; };
class AST_AugBinOp : public AST_expr {
public:
AST_TYPE::AST_TYPE op_type;
AST_expr *left, *right;
virtual void accept(ASTVisitor *v);
virtual void* accept_expr(ExprVisitor *v);
AST_AugBinOp() : AST_expr(AST_TYPE::AugBinOp) {}
};
class AST_Attribute : public AST_expr { class AST_Attribute : public AST_expr {
public: public:
AST_expr* value; AST_expr* value;
...@@ -630,6 +642,7 @@ class ASTVisitor { ...@@ -630,6 +642,7 @@ class ASTVisitor {
virtual bool visit_arguments(AST_arguments *node) { assert(0); abort(); } virtual bool visit_arguments(AST_arguments *node) { assert(0); abort(); }
virtual bool visit_assign(AST_Assign *node) { assert(0); abort(); } virtual bool visit_assign(AST_Assign *node) { assert(0); abort(); }
virtual bool visit_augassign(AST_AugAssign *node) { assert(0); abort(); } virtual bool visit_augassign(AST_AugAssign *node) { assert(0); abort(); }
virtual bool visit_augbinop(AST_AugBinOp *node) { assert(0); abort(); }
virtual bool visit_attribute(AST_Attribute *node) { assert(0); abort(); } virtual bool visit_attribute(AST_Attribute *node) { assert(0); abort(); }
virtual bool visit_binop(AST_BinOp *node) { assert(0); abort(); } virtual bool visit_binop(AST_BinOp *node) { assert(0); abort(); }
virtual bool visit_boolop(AST_BoolOp *node) { assert(0); abort(); } virtual bool visit_boolop(AST_BoolOp *node) { assert(0); abort(); }
...@@ -679,6 +692,7 @@ class NoopASTVisitor : public ASTVisitor { ...@@ -679,6 +692,7 @@ class NoopASTVisitor : public ASTVisitor {
virtual bool visit_arguments(AST_arguments *node) { return false; } virtual bool visit_arguments(AST_arguments *node) { return false; }
virtual bool visit_assign(AST_Assign *node) { return false; } virtual bool visit_assign(AST_Assign *node) { return false; }
virtual bool visit_augassign(AST_AugAssign *node) { return false; } virtual bool visit_augassign(AST_AugAssign *node) { return false; }
virtual bool visit_augbinop(AST_AugBinOp *node) { return false; }
virtual bool visit_attribute(AST_Attribute *node) { return false; } virtual bool visit_attribute(AST_Attribute *node) { return false; }
virtual bool visit_binop(AST_BinOp *node) { return false; } virtual bool visit_binop(AST_BinOp *node) { return false; }
virtual bool visit_boolop(AST_BoolOp *node) { return false; } virtual bool visit_boolop(AST_BoolOp *node) { return false; }
...@@ -724,6 +738,7 @@ class ExprVisitor { ...@@ -724,6 +738,7 @@ class ExprVisitor {
public: public:
virtual ~ExprVisitor() {} virtual ~ExprVisitor() {}
virtual void* visit_augbinop(AST_AugBinOp *node) { assert(0); abort(); }
virtual void* visit_attribute(AST_Attribute *node) { assert(0); abort(); } virtual void* visit_attribute(AST_Attribute *node) { assert(0); abort(); }
virtual void* visit_binop(AST_BinOp *node) { assert(0); abort(); } virtual void* visit_binop(AST_BinOp *node) { assert(0); abort(); }
virtual void* visit_boolop(AST_BoolOp *node) { assert(0); abort(); } virtual void* visit_boolop(AST_BoolOp *node) { assert(0); abort(); }
...@@ -783,6 +798,7 @@ class PrintVisitor : public ASTVisitor { ...@@ -783,6 +798,7 @@ class PrintVisitor : public ASTVisitor {
virtual bool visit_arguments(AST_arguments *node); virtual bool visit_arguments(AST_arguments *node);
virtual bool visit_assign(AST_Assign *node); virtual bool visit_assign(AST_Assign *node);
virtual bool visit_augassign(AST_AugAssign *node); virtual bool visit_augassign(AST_AugAssign *node);
virtual bool visit_augbinop(AST_AugBinOp *node);
virtual bool visit_attribute(AST_Attribute *node); virtual bool visit_attribute(AST_Attribute *node);
virtual bool visit_binop(AST_BinOp *node); virtual bool visit_binop(AST_BinOp *node);
virtual bool visit_boolop(AST_BoolOp *node); virtual bool visit_boolop(AST_BoolOp *node);
......
...@@ -198,7 +198,7 @@ class CFGVisitor : public ASTVisitor { ...@@ -198,7 +198,7 @@ class CFGVisitor : public ASTVisitor {
std::string nodeName(AST_expr* node) { std::string nodeName(AST* node) {
char buf[40]; char buf[40];
snprintf(buf, 40, "#%p", node); snprintf(buf, 40, "#%p", node);
return std::string(buf); return std::string(buf);
...@@ -670,7 +670,7 @@ class CFGVisitor : public ASTVisitor { ...@@ -670,7 +670,7 @@ class CFGVisitor : public ASTVisitor {
AST_Assign* remapped = new AST_Assign(); AST_Assign* remapped = new AST_Assign();
remapped->lineno = node->lineno; remapped->lineno = node->lineno;
remapped->col_offset = node->col_offset; remapped->col_offset = node->col_offset;
remapped->value = remapExpr(node->value); remapped->value = remapExpr(node->value, false);
// TODO bad that it's reusing the AST nodes? // TODO bad that it's reusing the AST nodes?
remapped->targets = node->targets; remapped->targets = node->targets;
push_back(remapped); push_back(remapped);
...@@ -678,14 +678,79 @@ class CFGVisitor : public ASTVisitor { ...@@ -678,14 +678,79 @@ class CFGVisitor : public ASTVisitor {
} }
virtual bool visit_augassign(AST_AugAssign* node) { virtual bool visit_augassign(AST_AugAssign* node) {
AST_AugAssign* remapped = new AST_AugAssign(); // augassign is pretty tricky; "x" += "y" mostly textually maps to
remapped->lineno = node->lineno; // "x" = "x" =+ "y" (using "=+" to represent an augbinop)
remapped->col_offset = node->col_offset; // except that "x" only gets evaluated once. So it's something like
remapped->value = remapExpr(node->value); // "target", val = eval("x")
// "target" = val =+ "y"
// where "target" is handled specially, because it can't just be a name;
// it has to be a name-only version of the target type (ex subscript, attribute).
// So for "f().x += g()", it has to translate to
// "c = f(); y = c.x; z = g(); c.x = y =+ z"
//
// Even if the target is a simple name, it can be complicated, because the
// value can change the name. For "x += f()", have to translate to
// "y = x; z = f(); x = y =+ z"
AST_expr* remapped_target;
AST_expr* remapped_lhs;
// TODO bad that it's reusing the AST nodes? // TODO bad that it's reusing the AST nodes?
remapped->target = node->target; switch (node->target->type) {
remapped->op_type = node->op_type; case AST_TYPE::Name: {
push_back(remapped); AST_Name* n = static_cast<AST_Name*>(node->target);
assert(n->ctx_type == AST_TYPE::Store);
push_back(makeAssign(nodeName(node), makeName(n->id, AST_TYPE::Load)));
remapped_target = n;
remapped_lhs = makeName(nodeName(node), AST_TYPE::Load);
break;
}
case AST_TYPE::Subscript: {
AST_Subscript *s = static_cast<AST_Subscript*>(node->target);
assert(s->ctx_type == AST_TYPE::Store);
AST_Subscript *s_target = new AST_Subscript();
s_target->value = remapExpr(s->value);
s_target->slice = remapExpr(s->slice);
s_target->ctx_type = AST_TYPE::Store;
remapped_target = s_target;
AST_Subscript *s_lhs = new AST_Subscript();
s_lhs->value = s_target->value;
s_lhs->slice = s_target->slice;
s_lhs->ctx_type = AST_TYPE::Load;
remapped_lhs = remapExpr(s_lhs);
break;
}
case AST_TYPE::Attribute: {
AST_Attribute *a = static_cast<AST_Attribute*>(node->target);
assert(a->ctx_type == AST_TYPE::Store);
AST_Attribute *a_target = new AST_Attribute();
a_target->value = remapExpr(a->value);
a_target->attr = a->attr;
a_target->ctx_type = AST_TYPE::Store;
remapped_target = a_target;
AST_Attribute *a_lhs = new AST_Attribute();
a_lhs->value = a_target->value;
a_lhs->attr = a->attr;
a_lhs->ctx_type = AST_TYPE::Load;
remapped_lhs = remapExpr(a_lhs);
break;
}
default:
RELEASE_ASSERT(0, "%d", node->target->type);
}
AST_AugBinOp* binop = new AST_AugBinOp();
binop->op_type = node->op_type;
binop->left = remapped_lhs;
binop->right = remapExpr(node->value);
AST_stmt* assign = makeAssign(remapped_target, binop);
push_back(assign);
return true; return true;
} }
......
...@@ -62,7 +62,7 @@ void force() { ...@@ -62,7 +62,7 @@ void force() {
FORCE(nonzero); FORCE(nonzero);
FORCE(binop); FORCE(binop);
FORCE(compare); FORCE(compare);
FORCE(augassign); FORCE(augbinop);
FORCE(unboxedLen); FORCE(unboxedLen);
FORCE(getitem); FORCE(getitem);
FORCE(getclsattr); FORCE(getclsattr);
......
...@@ -1661,7 +1661,7 @@ extern "C" Box* binop(Box* lhs, Box* rhs, int op_type) { ...@@ -1661,7 +1661,7 @@ extern "C" Box* binop(Box* lhs, Box* rhs, int op_type) {
return rtn; return rtn;
} }
extern "C" Box* augassign(Box* lhs, Box* rhs, int op_type) { extern "C" Box* augbinop(Box* lhs, Box* rhs, int op_type) {
static StatCounter slowpath_binop("slowpath_binop"); static StatCounter slowpath_binop("slowpath_binop");
slowpath_binop.log(); slowpath_binop.log();
//static StatCounter nopatch_binop("nopatch_binop"); //static StatCounter nopatch_binop("nopatch_binop");
......
...@@ -54,7 +54,7 @@ extern "C" void dump(Box* obj); ...@@ -54,7 +54,7 @@ extern "C" void dump(Box* obj);
//extern "C" Box* trap(); //extern "C" Box* trap();
extern "C" i64 unboxedLen(Box* obj); extern "C" i64 unboxedLen(Box* obj);
extern "C" Box* binop(Box* lhs, Box* rhs, int op_type); extern "C" Box* binop(Box* lhs, Box* rhs, int op_type);
extern "C" Box* augassign(Box* lhs, Box* rhs, int op_type); extern "C" Box* augbinop(Box* lhs, Box* rhs, int op_type);
extern "C" Box* getGlobal(BoxedModule* m, std::string *name, bool from_global); extern "C" Box* getGlobal(BoxedModule* m, std::string *name, bool from_global);
extern "C" Box* getitem(Box* value, Box* slice); extern "C" Box* getitem(Box* value, Box* slice);
extern "C" void setitem(Box* target, Box* slice, Box* value); extern "C" void setitem(Box* target, Box* slice, Box* value);
......
...@@ -28,5 +28,20 @@ l = l + l ...@@ -28,5 +28,20 @@ l = l + l
print l print l
print l2 print l2
def f2():
# It is *not* ok to translate "expr += y" into "name = expr; name += y"
l = range(10)
l[0] += 5
print l[0]
class C(object):
pass
c = C()
c.x = 1
c.x += 2
print c.x
f2()
print f(4, 2) print f(4, 2)
print f(4.1, 2.3) print f(4.1, 2.3)
...@@ -48,7 +48,70 @@ def f5(): ...@@ -48,7 +48,70 @@ def f5():
f5() f5()
def f6(): def f6():
x = -100
x += [x for x in [50, 51, 52]][0]
print x
# Prints "-50"
f6()
def f7():
global c
class C(object):
pass
c = C()
c.x = 0
def inner1():
global c
print "inner1"
c.x = 25
return c
def inner2():
global c
print "inner2"
c.x = 50
return 1
inner1().x += inner2()
print c.x # prints "26"
f7()
def f8():
global l
l = [0]
def inner1():
global l
print "inner1"
l[0] = 25
return l
def inner2():
global l
print "inner2"
l[0] = 50
return 1
inner1()[0] += inner2()
print l[0] # prints "26"
f8()
x = 9
def f9():
global x
def inner():
global x
x = 5
return 1
x += inner()
print x
f9()
def f10():
# This should error: the lhs is evaluated first # This should error: the lhs is evaluated first
x += [x for x in xrange(5)][0] x += [x for x in xrange(5)][0]
print x print x
f6() f10()
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