List comprehension support.

This commit is contained in:
Darryl Pogue
2011-10-10 15:57:20 -07:00
parent f0d47dc959
commit e2cf440736
2 changed files with 110 additions and 5 deletions

View File

@@ -473,7 +473,14 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
case Pyc::DELETE_GLOBAL_A:
case Pyc::DELETE_NAME_A:
{
PycRef<ASTNode> name = new ASTName(code->getName(operand));
PycRef<PycString> varname = code->getName(operand);
if (varname->value()[0] == '_' && varname->value()[1] == '[') {
/* Don't show deletes that are a result of list comps. */
break;
}
PycRef<ASTNode> name = new ASTName(varname);
curblock->append(new ASTDelete(name));
}
break;
@@ -626,11 +633,18 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
case Pyc::FOR_ITER_A:
{
PycRef<ASTNode> iter = stack.top(); // Iterable
stack.pop();
/* Pop it? Don't pop it? */
bool comprehension = false;
PycRef<ASTBlock> top = blocks.top();
blocks.pop();
if (top->blktype() == ASTBlock::BLK_WHILE) {
blocks.pop();
} else {
comprehension = true;
}
PycRef<ASTIterBlock> forblk = new ASTIterBlock(ASTBlock::BLK_FOR, pos+operand, iter);
forblk->setComprehension(comprehension);
blocks.push(forblk.cast<ASTBlock>());
curblock = blocks.top();
@@ -902,7 +916,21 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
case Pyc::JUMP_ABSOLUTE_A:
{
if (operand < pos) {
curblock->append(new ASTKeyword(ASTKeyword::KW_CONTINUE));
if (curblock->blktype() != ASTBlock::BLK_FOR
|| !curblock.cast<ASTIterBlock>()->isComprehension()) {
curblock->append(new ASTKeyword(ASTKeyword::KW_CONTINUE));
} else {
PycRef<ASTNode> top = stack.top();
if (top->type() == ASTNode::NODE_COMPREHENSION) {
PycRef<ASTComprehension> comp = top.cast<ASTComprehension>();
comp->addGenerator(curblock.cast<ASTIterBlock>());
}
blocks.pop();
curblock = blocks.top();
}
/* We're in a loop, this jumps back to the start */
/* I think we'll just ignore this case... */
@@ -1045,6 +1073,23 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
curblock = blocks.top();
}
break;
case Pyc::LIST_APPEND:
case Pyc::LIST_APPEND_A:
{
PycRef<ASTNode> value = stack.top();
stack.pop();
PycRef<ASTNode> list = stack.top();
if (curblock->blktype() == ASTBlock::BLK_FOR
&& curblock.cast<ASTIterBlock>()->isComprehension()) {
stack.push(new ASTComprehension(value));
} else {
stack.push(new ASTSubscr(list, value)); /* Total hack */
}
}
break;
case Pyc::LOAD_ATTR_A:
{
PycRef<ASTNode> name = stack.top();
@@ -1189,6 +1234,19 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
}
curblock->append(value);
if (curblock->blktype() == ASTBlock::BLK_FOR
&& curblock.cast<ASTIterBlock>()->isComprehension()) {
/* This relies on some really uncertain logic...
* If it's a comprehension, the only POP_TOP should be
* a call to append the iter to the list.
*/
if (value->type() == ASTNode::NODE_CALL) {
PycRef<ASTNode> res = value.cast<ASTCall>()->pparams().front();
stack.push(new ASTComprehension(res));
}
}
}
break;
case Pyc::PRINT_ITEM:
@@ -1482,7 +1540,13 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
PycRef<ASTNode> value = stack.top();
stack.pop();
PycRef<ASTNode> name = new ASTName(code->getName(operand));
PycRef<PycString> varname = code->getName(operand);
if (varname->value()[0] == '_' && varname->value()[1] == '[') {
/* Don't show stores of list comp append objects. */
break;
}
PycRef<ASTNode> name = new ASTName(varname);
if (curblock->blktype() == ASTBlock::BLK_FOR
&& !curblock->inited()) {
@@ -1877,6 +1941,23 @@ void print_src(PycRef<ASTNode> node, PycModule* mod)
printf("]");
}
break;
case ASTNode::NODE_COMPREHENSION:
{
PycRef<ASTComprehension> comp = node.cast<ASTComprehension>();
ASTComprehension::generator_t values = comp->generators();
printf("[ ");
print_src(comp->result(), mod);
for (ASTComprehension::generator_t::const_iterator it = values.begin(); it != values.end(); ++it) {
printf(" for ");
print_src((*it)->index(), mod);
printf(" in ");
print_src((*it)->iter(), mod);
}
printf(" ]");
}
break;
case ASTNode::NODE_MAP:
{
ASTMap::map_t values = node.cast<ASTMap>()->values();