Add raise, break, continue, and a hacky attempt at for loops.
for loops currently generate a core dump.
This commit is contained in:
13
ASTNode.cpp
13
ASTNode.cpp
@@ -21,7 +21,7 @@ void ASTNodeList::removeFirst()
|
||||
const char* ASTUnary::op_str() const
|
||||
{
|
||||
static const char* s_op_strings[] = {
|
||||
"+", "-", "~", "not ", "`"
|
||||
"+", "-", "~", "not "
|
||||
};
|
||||
return s_op_strings[op()];
|
||||
}
|
||||
@@ -50,6 +50,17 @@ const char* ASTCompare::op_str() const
|
||||
return s_cmp_strings[op()];
|
||||
}
|
||||
|
||||
|
||||
/* ASTKeyword */
|
||||
const char* ASTKeyword::word_str() const
|
||||
{
|
||||
static const char* s_word_strings[] = {
|
||||
"break", "continue"
|
||||
};
|
||||
return s_word_strings[key()];
|
||||
}
|
||||
|
||||
|
||||
/* ASTBlock */
|
||||
void ASTBlock::removeLast()
|
||||
{
|
||||
|
74
ASTNode.h
74
ASTNode.h
@@ -12,7 +12,8 @@ public:
|
||||
NODE_INVALID, NODE_NODELIST, NODE_OBJECT, NODE_UNARY, NODE_BINARY,
|
||||
NODE_COMPARE, NODE_STORE, NODE_RETURN, NODE_NAME, NODE_DELETE,
|
||||
NODE_FUNCTION, NODE_CLASS, NODE_CALL, NODE_IMPORT, NODE_TUPLE,
|
||||
NODE_LIST, NODE_MAP, NODE_SUBSCR, NODE_PRINT, NODE_BLOCK,
|
||||
NODE_LIST, NODE_MAP, NODE_SUBSCR, NODE_PRINT, NODE_CONVERT,
|
||||
NODE_KEYWORD, NODE_RAISE, NODE_BLOCK,
|
||||
|
||||
// Empty nodes
|
||||
NODE_PASS, NODE_LOCALS
|
||||
@@ -68,7 +69,7 @@ private:
|
||||
class ASTUnary : public ASTNode {
|
||||
public:
|
||||
enum UnOp {
|
||||
UN_POSITIVE, UN_NEGATIVE, UN_INVERT, UN_NOT, UN_CONVERT
|
||||
UN_POSITIVE, UN_NEGATIVE, UN_INVERT, UN_NOT
|
||||
};
|
||||
|
||||
ASTUnary(PycRef<ASTNode> operand, int op)
|
||||
@@ -315,6 +316,47 @@ private:
|
||||
};
|
||||
|
||||
|
||||
class ASTConvert : public ASTNode {
|
||||
public:
|
||||
ASTConvert(PycRef<ASTNode> name)
|
||||
: ASTNode(NODE_CONVERT), m_name(name) { }
|
||||
|
||||
PycRef<ASTNode> name() const { return m_name; }
|
||||
|
||||
private:
|
||||
PycRef<ASTNode> m_name;
|
||||
};
|
||||
|
||||
|
||||
class ASTKeyword : public ASTNode {
|
||||
public:
|
||||
enum Word {
|
||||
KW_BREAK, KW_CONTINUE
|
||||
};
|
||||
|
||||
ASTKeyword(Word key) : ASTNode(NODE_KEYWORD), m_key(key) { }
|
||||
|
||||
Word key() const { return m_key; }
|
||||
const char* word_str() const;
|
||||
|
||||
private:
|
||||
Word m_key;
|
||||
};
|
||||
|
||||
|
||||
class ASTRaise : public ASTNode {
|
||||
public:
|
||||
typedef std::list<PycRef<ASTNode> > param_t;
|
||||
|
||||
ASTRaise(param_t params) : ASTNode(NODE_RAISE), m_params(params) { }
|
||||
|
||||
const param_t& params() const { return m_params; }
|
||||
|
||||
private:
|
||||
param_t m_params;
|
||||
};
|
||||
|
||||
|
||||
class ASTBlock : public ASTNode {
|
||||
public:
|
||||
typedef std::list<PycRef<ASTNode> > list_t;
|
||||
@@ -342,18 +384,40 @@ private:
|
||||
list_t m_nodes;
|
||||
};
|
||||
|
||||
|
||||
class ASTCondBlock : public ASTBlock {
|
||||
public:
|
||||
ASTCondBlock(ASTBlock::BlkType blktype, unsigned int end, PycRef<ASTNode> cond,
|
||||
bool negative = false)
|
||||
: ASTBlock(blktype, end), m_cond(cond), m_negative(negative) { }
|
||||
ASTCondBlock(ASTBlock::BlkType blktype, unsigned int end, PycRef<ASTNode> cond, bool negative = false)
|
||||
: ASTBlock(blktype, end), m_cond(cond), m_negative(negative), m_popped(false) { }
|
||||
|
||||
PycRef<ASTNode> cond() const { return m_cond; }
|
||||
bool negative() const { return m_negative; }
|
||||
bool popped() const { return m_popped; }
|
||||
|
||||
void popCondition() { m_popped = true; }
|
||||
|
||||
private:
|
||||
PycRef<ASTNode> m_cond;
|
||||
bool m_negative;
|
||||
bool m_popped; /* Has the condition been popped off the stack? */
|
||||
};
|
||||
|
||||
|
||||
class ASTIterBlock : public ASTBlock {
|
||||
public:
|
||||
ASTIterBlock(ASTBlock::BlkType blktype, unsigned int end, PycRef<ASTNode> iter)
|
||||
: ASTBlock(blktype, end), m_iter(iter), m_idx(), m_idx_set(false) { }
|
||||
|
||||
PycRef<ASTNode> iter() const { return m_iter; }
|
||||
PycRef<ASTNode> index() const { return m_idx; }
|
||||
bool idxset() const { return m_idx_set; }
|
||||
|
||||
void setIndex(PycRef<ASTNode> idx) { m_idx = idx; m_idx_set = true; }
|
||||
|
||||
private:
|
||||
PycRef<ASTNode> m_iter;
|
||||
PycRef<ASTNode> m_idx;
|
||||
bool m_idx_set;
|
||||
};
|
||||
|
||||
/*class ASTTryBlock : public ASTBlock {
|
||||
|
98
ASTree.cpp
98
ASTree.cpp
@@ -165,6 +165,9 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
|
||||
stack.push(new ASTBinary(left, right, ASTBinary::BIN_XOR));
|
||||
}
|
||||
break;
|
||||
case Pyc::BREAK_LOOP:
|
||||
stack.push(new ASTKeyword(ASTKeyword::KW_BREAK));
|
||||
break;
|
||||
case Pyc::BUILD_CLASS:
|
||||
{
|
||||
PycRef<ASTNode> code = stack.top();
|
||||
@@ -229,6 +232,9 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
|
||||
stack.push(new ASTCall(func, pparamList, kwparamList));
|
||||
}
|
||||
break;
|
||||
case Pyc::CONTINUE_LOOP_A:
|
||||
stack.push(new ASTKeyword(ASTKeyword::KW_CONTINUE));
|
||||
break;
|
||||
case Pyc::COMPARE_OP_A:
|
||||
{
|
||||
PycRef<ASTNode> right = stack.top();
|
||||
@@ -251,6 +257,27 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Pyc::FOR_LOOP_A:
|
||||
{
|
||||
PycRef<ASTNode> curidx = stack.top(); // Current index
|
||||
stack.pop();
|
||||
PycRef<ASTNode> iter = stack.top(); // Iterable
|
||||
stack.pop();
|
||||
|
||||
PycRef<ASTBlock> top = blocks.top();
|
||||
blocks.pop();
|
||||
PycRef<ASTIterBlock> forblk = new ASTIterBlock(ASTBlock::BLK_FOR, top->end(), iter);
|
||||
blocks.push(forblk.cast<ASTBlock>());
|
||||
curblock = blocks.top();
|
||||
|
||||
/* Python Docs say:
|
||||
"push the sequence, the incremented counter,
|
||||
and the current item onto the stack." */
|
||||
stack.push(iter);
|
||||
stack.push(curidx);
|
||||
stack.push(Node_NULL); // We can totally hack this >_>
|
||||
}
|
||||
break;
|
||||
case Pyc::IMPORT_NAME_A:
|
||||
if (mod->majorVer() == 1) {
|
||||
stack.push(new ASTImport(new ASTName(code->getName(operand)), Node_NULL));
|
||||
@@ -299,12 +326,14 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
|
||||
case Pyc::POP_JUMP_IF_TRUE_A:
|
||||
{
|
||||
PycRef<ASTNode> cond = stack.top();
|
||||
PycRef<ASTBlock> ifblk;
|
||||
PycRef<ASTCondBlock> ifblk;
|
||||
bool popped = false;
|
||||
|
||||
if (opcode == Pyc::POP_JUMP_IF_FALSE_A
|
||||
|| opcode == Pyc::POP_JUMP_IF_TRUE_A) {
|
||||
/* Pop condition before the jump */
|
||||
stack.pop();
|
||||
popped = true;
|
||||
}
|
||||
/* Store the current stack for the else statement(s) */
|
||||
stack_hist.push(stack);
|
||||
@@ -312,6 +341,7 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
|
||||
|| opcode == Pyc::JUMP_IF_TRUE_OR_POP_A) {
|
||||
/* Pop condition only if condition is met */
|
||||
stack.pop();
|
||||
popped = true;
|
||||
}
|
||||
|
||||
/* "Jump if true" means "Jump if not false" */
|
||||
@@ -345,6 +375,10 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
|
||||
/* Plain old if statement */
|
||||
ifblk = new ASTCondBlock(ASTBlock::BLK_IF, offs, cond, neg);
|
||||
}
|
||||
|
||||
if (popped)
|
||||
ifblk->popCondition();
|
||||
|
||||
blocks.push(ifblk.cast<ASTBlock>());
|
||||
curblock = blocks.top();
|
||||
}
|
||||
@@ -457,6 +491,9 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
|
||||
{
|
||||
PycRef<ASTBlock> tmp = curblock;
|
||||
|
||||
if (tmp->blktype() == ASTBlock::BLK_FOR)
|
||||
break;
|
||||
|
||||
blocks.pop();
|
||||
curblock = blocks.top();
|
||||
curblock->append(tmp.cast<ASTNode>());
|
||||
@@ -476,6 +513,14 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
|
||||
{
|
||||
PycRef<ASTNode> value = stack.top();
|
||||
stack.pop();
|
||||
if (curblock->blktype() == ASTBlock::BLK_IF
|
||||
|| curblock->blktype() == ASTBlock::BLK_ELIF
|
||||
|| curblock->blktype() == ASTBlock::BLK_ELSE)
|
||||
{
|
||||
curblock.cast<ASTCondBlock>()->popCondition();
|
||||
break;
|
||||
}
|
||||
|
||||
if (value->type() == ASTNode::NODE_CALL) {
|
||||
curblock->append(value);
|
||||
}
|
||||
@@ -488,6 +533,16 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
|
||||
case Pyc::PRINT_NEWLINE:
|
||||
curblock->append(new ASTPrint(Node_NULL));
|
||||
break;
|
||||
case Pyc::RAISE_VARARGS_A:
|
||||
{
|
||||
ASTRaise::param_t paramList;
|
||||
for (int i = 0; i < operand; i++) {
|
||||
paramList.push_front(stack.top());
|
||||
stack.pop();
|
||||
}
|
||||
curblock->append(new ASTRaise(paramList));
|
||||
}
|
||||
break;
|
||||
case Pyc::RETURN_VALUE:
|
||||
{
|
||||
PycRef<ASTNode> value = stack.top();
|
||||
@@ -558,11 +613,19 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
|
||||
PycRef<ASTNode> value = stack.top();
|
||||
stack.pop();
|
||||
PycRef<ASTNode> name;
|
||||
|
||||
if (mod->majorVer() == 1 && mod->minorVer() < 3)
|
||||
name = new ASTName(code->getName(operand));
|
||||
else
|
||||
name = new ASTName(code->getVarName(operand));
|
||||
curblock->append(new ASTStore(value, name));
|
||||
|
||||
if (curblock->blktype() == ASTBlock::BLK_FOR
|
||||
&& !curblock.cast<ASTIterBlock>()->idxset())
|
||||
{
|
||||
curblock.cast<ASTIterBlock>()->setIndex(name);
|
||||
} else {
|
||||
curblock->append(new ASTStore(value, name));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Pyc::STORE_GLOBAL_A:
|
||||
@@ -603,6 +666,13 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
|
||||
stack.push(new ASTCall(func, ASTCall::pparam_t(), ASTCall::kwparam_t()));
|
||||
}
|
||||
break;
|
||||
case Pyc::UNARY_CONVERT:
|
||||
{
|
||||
PycRef<ASTNode> name = stack.top();
|
||||
stack.pop();
|
||||
stack.push(new ASTConvert(name));
|
||||
}
|
||||
break;
|
||||
case Pyc::UNARY_INVERT:
|
||||
{
|
||||
PycRef<ASTNode> arg = stack.top();
|
||||
@@ -792,6 +862,11 @@ void print_src(PycRef<ASTNode> node, PycModule* mod)
|
||||
printf(")");
|
||||
}
|
||||
break;
|
||||
case ASTNode::NODE_KEYWORD:
|
||||
{
|
||||
printf("%s", node.cast<ASTKeyword>()->word_str());
|
||||
}
|
||||
break;
|
||||
case ASTNode::NODE_LIST:
|
||||
{
|
||||
ASTList::value_t values = node.cast<ASTList>()->values();
|
||||
@@ -901,6 +976,18 @@ void print_src(PycRef<ASTNode> node, PycModule* mod)
|
||||
print_src(node.cast<ASTPrint>()->value(), mod);
|
||||
}
|
||||
break;
|
||||
case ASTNode::NODE_RAISE:
|
||||
{
|
||||
PycRef<ASTRaise> raise = node.cast<ASTRaise>();
|
||||
printf("raise ");
|
||||
bool first = true;
|
||||
for (ASTRaise::param_t::const_iterator p = raise->params().begin(); p != raise->params().end(); ++p) {
|
||||
if (!first) printf(", ");
|
||||
print_src(*p, mod);
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ASTNode::NODE_RETURN:
|
||||
printf("return ");
|
||||
print_src(node.cast<ASTReturn>()->value(), mod);
|
||||
@@ -1014,6 +1101,13 @@ void print_src(PycRef<ASTNode> node, PycModule* mod)
|
||||
printf("]");
|
||||
}
|
||||
break;
|
||||
case ASTNode::NODE_CONVERT:
|
||||
{
|
||||
printf("`");
|
||||
print_src(node.cast<ASTConvert>()->name(), mod);
|
||||
printf("`");
|
||||
}
|
||||
break;
|
||||
case ASTNode::NODE_TUPLE:
|
||||
{
|
||||
ASTTuple::value_t values = node.cast<ASTTuple>()->values();
|
||||
|
@@ -141,7 +141,8 @@ bool Pyc::IsJumpOffsetArg(int opcode)
|
||||
{
|
||||
return (opcode == Pyc::JUMP_FORWARD_A) || (opcode == Pyc::JUMP_IF_FALSE_A) ||
|
||||
(opcode == Pyc::JUMP_IF_TRUE_A) || (opcode == Pyc::SETUP_LOOP_A) ||
|
||||
(opcode == Pyc::SETUP_FINALLY_A) || (opcode == Pyc::SETUP_EXCEPT_A);
|
||||
(opcode == Pyc::SETUP_FINALLY_A) || (opcode == Pyc::SETUP_EXCEPT_A) ||
|
||||
(opcode == Pyc::FOR_LOOP_A);
|
||||
}
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user