Much better handling of if/else statements.

This commit is contained in:
Darryl Pogue
2010-09-04 23:51:22 -07:00
parent 6f67603858
commit 6fb01bbbf6
2 changed files with 50 additions and 8 deletions

View File

@@ -337,7 +337,13 @@ private:
class ASTPopHack : public ASTNode {
public:
ASTPopHack() : ASTNode(NODE_POP_HACK) { }
ASTPopHack(PycRef<ASTNode> value)
: ASTNode(NODE_POP_HACK), m_value(value) { }
PycRef<ASTNode> value() const { return m_value; }
private:
PycRef<ASTNode> m_value;
};
#endif

View File

@@ -24,6 +24,8 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
FastStack stack((mod->majorVer() == 1) ? 20 : code->stackSize());
stackhist_t stack_hist;
std::stack<int> jumps;
int opcode, operand;
int pos = 0;
@@ -337,6 +339,7 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
PycRef<ASTNode> cond = stack.top();
stack.pop();
stack.push(new ASTJump(operand, ASTJump::JMP_FALSE, cond));
jumps.push(pos + operand);
}
break;
case (PY_1000 | Py1k::JUMP_IF_TRUE):
@@ -346,6 +349,7 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
PycRef<ASTNode> cond = stack.top();
stack.pop();
stack.push(new ASTJump(operand, ASTJump::JMP_TRUE, cond));
jumps.push(pos + operand);
}
break;
case (PY_1000 | Py1k::JUMP_FORWARD):
@@ -353,6 +357,20 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
case (PY_3000 | Py3k::JUMP_FORWARD):
{
stack.push(new ASTJump(operand, ASTJump::JUMP, NULL));
std::stack<int> tmp;
int top = jumps.top();
while (top < pos + operand) {
tmp.push(jumps.top());
jumps.pop();
if (!jumps.size())
break;
top = jumps.top();
}
jumps.push(pos + operand);
while (tmp.size()) {
jumps.push(tmp.top());
tmp.pop();
}
}
break;
case (PY_1000 | Py1k::LOAD_ATTR):
@@ -570,6 +588,14 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
cleanBuild = false;
return new ASTNodeList(lines);
}
while (jumps.size() && jumps.top() == pos)
{
PycRef<ASTNode> dest = lines.back();
lines.pop_back();
lines.push_back(new ASTPopHack(dest));
jumps.pop();
}
}
cleanBuild = true;
@@ -858,10 +884,12 @@ void print_src(PycRef<ASTNode> node, PycModule* mod, int indent)
}
break;
case ASTNode::NODE_SUBSCR:
print_src(node.cast<ASTSubscr>()->name(), mod, indent);
printf("[");
print_src(node.cast<ASTSubscr>()->key(), mod, indent);
printf("]");
{
print_src(node.cast<ASTSubscr>()->name(), mod, indent);
printf("[");
print_src(node.cast<ASTSubscr>()->key(), mod, indent);
printf("]");
}
break;
case ASTNode::NODE_TUPLE:
{
@@ -883,11 +911,11 @@ void print_src(PycRef<ASTNode> node, PycModule* mod, int indent)
{
ASTJump::Condition jtype = node.cast<ASTJump>()->jtype();
if (jtype != ASTJump::JUMP) {
printf("if (");
printf("if ");
if (jtype == ASTJump::JMP_TRUE)
printf("not ");
print_src(node.cast<ASTJump>()->cond(), mod, indent);
printf("):");
printf(":");
cur_indent++;
} else {
if (node.cast<ASTJump>()->dest() != 1) {
@@ -898,7 +926,15 @@ void print_src(PycRef<ASTNode> node, PycModule* mod, int indent)
}
break;
case ASTNode::NODE_POP_HACK:
cur_indent--;
{
PycRef<ASTNode> val = node.cast<ASTPopHack>()->value();
print_src(val, mod, indent);
if (cur_indent > 0)
cur_indent--;
//printf(" #%d", val.cast<ASTNode>()->type());
}
break;
default:
printf("<NODE:%d>", node->type());