forked from zrax/pycdc
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
556 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
#include "ASTNode.h" | ||
|
||
PycRef<ASTNode> Node_NULL = (ASTNode*)0; | ||
|
||
/* ASTCompare */ | ||
const char* ASTCompare::op_str() const | ||
{ | ||
static const char* s_cmp_strings[] = { | ||
"<", "<=", "==", "!=", ">", ">=", "in", "not in", "is", "is not", | ||
"<EXCEPTION MATCH>", "<BAD>" | ||
}; | ||
return s_cmp_strings[m_op]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
#ifndef _PYC_ASTNODE_H | ||
#define _PYC_ASTNODE_H | ||
|
||
#include "module.h" | ||
#include <list> | ||
|
||
/* Similar interface to PycObject, so PycRef can work on it... * | ||
* However, this does *NOT* mean the two are interchangeable! */ | ||
class ASTNode { | ||
public: | ||
enum Type { | ||
NODE_INVALID, NODE_LIST, NODE_OBJECT, NODE_UNARY, NODE_BINARY, | ||
NODE_COMPARE, NODE_STORE, NODE_RETURN, NODE_NAME, NODE_DELETE | ||
}; | ||
|
||
ASTNode(int type = NODE_INVALID) : m_refs(0), m_type(type) { } | ||
virtual ~ASTNode() { } | ||
|
||
int type() const { return (this) ? m_type : NODE_INVALID; } | ||
|
||
private: | ||
int m_refs; | ||
int m_type; | ||
|
||
public: | ||
void addRef() { if (this) ++m_refs; } | ||
void delRef() { if (this && --m_refs == 0) delete this; } | ||
}; | ||
|
||
/* A NULL node for comparison */ | ||
extern PycRef<ASTNode> Node_NULL; | ||
|
||
|
||
class ASTNodeList : public ASTNode { | ||
public: | ||
typedef std::list<PycRef<ASTNode> > list_t; | ||
|
||
ASTNodeList(list_t nodes) | ||
: ASTNode(NODE_LIST), m_nodes(nodes) { } | ||
|
||
list_t nodes() const { return m_nodes; } | ||
|
||
private: | ||
list_t m_nodes; | ||
}; | ||
|
||
|
||
class ASTObject : public ASTNode { | ||
public: | ||
ASTObject(PycRef<PycObject> obj) | ||
: ASTNode(NODE_OBJECT), m_obj(obj) { } | ||
|
||
PycRef<PycObject> object() const { return m_obj; } | ||
|
||
private: | ||
PycRef<PycObject> m_obj; | ||
}; | ||
|
||
|
||
class ASTUnary : public ASTNode { | ||
public: | ||
ASTUnary(PycRef<ASTNode> operand) | ||
: ASTNode(NODE_UNARY), m_operand(operand) { } | ||
|
||
PycRef<ASTNode> operand() const { return m_operand; } | ||
|
||
private: | ||
PycRef<ASTNode> m_operand; | ||
}; | ||
|
||
|
||
class ASTBinary : public ASTNode { | ||
public: | ||
ASTBinary(PycRef<ASTNode> left, PycRef<ASTNode> right, int type = NODE_BINARY) | ||
: ASTNode(type), m_left(left), m_right(right) { } | ||
|
||
PycRef<ASTNode> left() const { return m_left; } | ||
PycRef<ASTNode> right() const { return m_right; } | ||
|
||
private: | ||
PycRef<ASTNode> m_left; | ||
PycRef<ASTNode> m_right; | ||
}; | ||
|
||
|
||
class ASTCompare : public ASTBinary { | ||
public: | ||
enum CompareOp { | ||
CMP_LESS, CMP_LESS_EQUAL, CMP_EQUAL, CMP_NOT_EQUAL, CMP_GREATER, | ||
CMP_GREATER_EQUAL, CMP_IN, CMP_NOT_IN, CMP_IS, CMP_IS_NOT, | ||
CMP_EXCEPTION, CMP_BAD | ||
}; | ||
|
||
ASTCompare(PycRef<ASTNode> left, PycRef<ASTNode> right, CompareOp op) | ||
: ASTBinary(left, right, NODE_COMPARE), m_op(op) { } | ||
|
||
CompareOp op() const { return m_op; } | ||
const char* op_str() const; | ||
|
||
private: | ||
CompareOp m_op; | ||
}; | ||
|
||
|
||
class ASTStore : public ASTNode { | ||
public: | ||
ASTStore(PycRef<ASTNode> src, PycRef<ASTNode> dest) | ||
: ASTNode(NODE_STORE), m_src(src), m_dest(dest) { } | ||
|
||
PycRef<ASTNode> src() const { return m_src; } | ||
PycRef<ASTNode> dest() const { return m_dest; } | ||
|
||
private: | ||
PycRef<ASTNode> m_src; | ||
PycRef<ASTNode> m_dest; | ||
}; | ||
|
||
|
||
class ASTReturn : public ASTNode { | ||
public: | ||
ASTReturn(PycRef<ASTNode> value) | ||
: ASTNode(NODE_RETURN), m_value(value) { } | ||
|
||
PycRef<ASTNode> value() const { return m_value; } | ||
|
||
private: | ||
PycRef<ASTNode> m_value; | ||
}; | ||
|
||
|
||
class ASTName : public ASTNode { | ||
public: | ||
typedef std::list<PycRef<PycString> > name_t; | ||
|
||
ASTName(PycRef<PycString> name) | ||
: ASTNode(NODE_NAME) { m_name.push_back(name); } | ||
|
||
name_t name() const { return m_name; } | ||
void add(PycRef<PycString> name) { m_name.push_back(name); } | ||
|
||
private: | ||
name_t m_name; | ||
}; | ||
|
||
|
||
class ASTDelete : public ASTNode { | ||
public: | ||
ASTDelete(PycRef<ASTNode> value) | ||
: ASTNode(NODE_DELETE), m_value(value) { } | ||
|
||
PycRef<ASTNode> value() const { return m_value; } | ||
|
||
private: | ||
PycRef<ASTNode> m_value; | ||
}; | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,224 @@ | ||
#include "ASTree.h" | ||
#include "FastStack.h" | ||
#include "bytecode.h" | ||
|
||
// These are used to avoid writing code 3 times for each of | ||
// the different python generations | ||
#define PY_1000 0x1000 | ||
#define PY_2000 0x2000 | ||
#define PY_3000 0x3000 | ||
|
||
PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod) | ||
{ | ||
PycBuffer source(code->code()->value(), code->code()->length()); | ||
ASTNodeList::list_t lines; | ||
|
||
FastStack stack((mod->majorVer() == 1) ? 20 : code->stackSize()); | ||
stackhist_t stack_hist; | ||
|
||
int opcode, operand; | ||
int pos = 0; | ||
|
||
int opadd = 0; | ||
if (mod->majorVer() == 1) | ||
opadd = PY_1000; | ||
else if (mod->majorVer() == 2) | ||
opadd = PY_2000; | ||
else if (mod->majorVer() == 3) | ||
opadd = PY_3000; | ||
|
||
while (!source.atEof()) { | ||
bc_next(source, mod, opcode, operand, pos); | ||
opcode |= opadd; | ||
|
||
switch (opcode) { | ||
//case Py2k::STOP_CODE: | ||
//case Py2k::POP_TOP: | ||
//case Py2k::ROT_TWO: | ||
//case Py2k::ROT_THREE: | ||
//case Py2k::DUP_TOP: | ||
//case Py2k::ROT_FOUR: | ||
//case Py2k::NOP: | ||
//case Py2k::UNARY_POSITIVE: | ||
//case Py2k::UNARY_NEGATIVE: | ||
//case Py2k::UNARY_NOT: | ||
//case Py2k::UNARY_CONVERT: | ||
//case Py2k::UNARY_INVERT: | ||
//case Py2k::LIST_APPEND: | ||
//case Py2k::BINARY_POWER: | ||
//case Py2k::BINARY_MULTIPLY: | ||
//case Py2k::BINARY_DIVIDE: | ||
//case Py2k::BINARY_MODULO: | ||
//case Py2k::BINARY_ADD: | ||
//case Py2k::BINARY_SUBTRACT: | ||
//case Py2k::BINARY_SUBSCR: | ||
//case Py2k::BINARY_FLOOR_DIVIDE: | ||
//case Py2k::BINARY_TRUE_DIVIDE: | ||
//case Py2k::INPLACE_FLOOR_DIVIDE: | ||
//case Py2k::INPLACE_TRUE_DIVIDE: | ||
//case Py2k::SLICE_0: | ||
//case Py2k::SLICE_1: | ||
//case Py2k::SLICE_2: | ||
//case Py2k::SLICE_3: | ||
//case Py2k::STORE_SLICE_0: | ||
//case Py2k::STORE_SLICE_1: | ||
//case Py2k::STORE_SLICE_2: | ||
//case Py2k::STORE_SLICE_3: | ||
//case Py2k::DELETE_SLICE_0: | ||
//case Py2k::DELETE_SLICE_1: | ||
//case Py2k::DELETE_SLICE_2: | ||
//case Py2k::DELETE_SLICE_3: | ||
//case Py2k::STORE_MAP: | ||
//case Py2k::INPLACE_ADD: | ||
//case Py2k::INPLACE_SUBTRACT: | ||
//case Py2k::INPLACE_MULTIPLY: | ||
//case Py2k::INPLACE_DIVIDE: | ||
//case Py2k::INPLACE_MODULO: | ||
//case Py2k::STORE_SUBSCR: | ||
//case Py2k::DELETE_SUBSCR: | ||
//case Py2k::BINARY_LSHIFT: | ||
//case Py2k::BINARY_RSHIFT: | ||
//case Py2k::BINARY_AND: | ||
//case Py2k::BINARY_XOR: | ||
//case Py2k::BINARY_OR: | ||
//case Py2k::INPLACE_POWER: | ||
//case Py2k::GET_ITER: | ||
//case Py2k::PRINT_EXPR: | ||
//case Py2k::PRINT_ITEM: | ||
//case Py2k::PRINT_NEWLINE: | ||
//case Py2k::PRINT_ITEM_TO: | ||
//case Py2k::PRINT_NEWLINE_TO: | ||
//case Py2k::INPLACE_LSHIFT: | ||
//case Py2k::INPLACE_RSHIFT: | ||
//case Py2k::INPLACE_AND: | ||
//case Py2k::INPLACE_XOR: | ||
//case Py2k::INPLACE_OR: | ||
//case Py2k::BREAK_LOOP: | ||
//case Py2k::WITH_CLEANUP: | ||
//case Py2k::LOAD_LOCALS: | ||
//case Py2k::RETURN_VALUE: | ||
//case Py2k::IMPORT_STAR: | ||
//case Py2k::EXEC_STMT: | ||
//case Py2k::YIELD_VALUE: | ||
//case Py2k::POP_BLOCK: | ||
//case Py2k::END_FINALLY: | ||
//case Py2k::BUILD_CLASS: | ||
case (PY_1000 | Py1k::STORE_NAME): | ||
case (PY_2000 | Py2k::STORE_NAME): | ||
case (PY_3000 | Py3k::STORE_NAME): | ||
{ | ||
PycRef<ASTNode> value = stack.top(); | ||
PycRef<ASTNode> name = new ASTName(code->getName(operand)); | ||
stack.pop(); | ||
lines.push_back(new ASTStore(value, name)); | ||
} | ||
break; | ||
//case Py2k::DELETE_NAME: | ||
//case Py2k::UNPACK_SEQUENCE: | ||
//case Py2k::FOR_ITER: | ||
//case Py2k::STORE_ATTR: | ||
//case Py2k::DELETE_ATTR: | ||
//case Py2k::STORE_GLOBAL: | ||
//case Py2k::DELETE_GLOBAL: | ||
//case Py2k::DUP_TOPX: | ||
case (PY_1000 | Py1k::LOAD_CONST): | ||
case (PY_2000 | Py2k::LOAD_CONST): | ||
case (PY_3000 | Py3k::LOAD_CONST): | ||
stack.push(new ASTObject(code->getConst(operand))); | ||
break; | ||
//case Py2k::LOAD_NAME: | ||
//case Py2k::BUILD_TUPLE: | ||
//case Py2k::BUILD_LIST: | ||
//case Py2k::BUILD_MAP: | ||
//case Py2k::LOAD_ATTR: | ||
//case Py2k::COMPARE_OP: | ||
//case Py2k::IMPORT_NAME: | ||
//case Py2k::IMPORT_FROM: | ||
//case Py2k::JUMP_FORWARD: | ||
//case Py2k::JUMP_IF_FALSE: | ||
//case Py2k::JUMP_IF_TRUE: | ||
//case Py2k::JUMP_ABSOLUTE: | ||
//case Py2k::FOR_LOOP: | ||
//case Py2k::LOAD_GLOBAL: | ||
//case Py2k::CONTINUE_LOOP: | ||
//case Py2k::SETUP_LOOP: | ||
//case Py2k::SETUP_EXCEPT: | ||
//case Py2k::SETUP_FINALLY: | ||
//case Py2k::LOAD_FAST: | ||
//case Py2k::STORE_FAST: | ||
//case Py2k::DELETE_FAST: | ||
//case Py2k::SET_LINENO: | ||
//case Py2k::RAISE_VARARGS: | ||
//case Py2k::CALL_FUNCTION: | ||
//case Py2k::MAKE_FUNCTION: | ||
//case Py2k::BUILD_SLICE: | ||
//case Py2k::MAKE_CLOSURE: | ||
//case Py2k::LOAD_CLOSURE: | ||
//case Py2k::LOAD_DEREF: | ||
//case Py2k::STORE_DEREF: | ||
//case Py2k::CALL_FUNCTION_VAR: | ||
//case Py2k::CALL_FUNCTION_KW: | ||
//case Py2k::CALL_FUNCTION_VAR_KW: | ||
//case Py2k::EXTENDED_ARG: | ||
default: | ||
if (mod->majorVer() == 1) | ||
fprintf(stderr, "Unsupported opcode: %s\n", Py1k::OpcodeNames[opcode & 0xFF]); | ||
else if (mod->majorVer() == 2) | ||
fprintf(stderr, "Unsupported opcode: %s\n", Py2k::OpcodeNames[opcode & 0xFF]); | ||
else if (mod->majorVer() == 3) | ||
fprintf(stderr, "Unsupported opcode: %s\n", Py3k::OpcodeNames[opcode & 0xFF]); | ||
return new ASTNodeList(lines); | ||
} | ||
} | ||
|
||
return new ASTNodeList(lines); | ||
} | ||
|
||
static void start_indent(int indent) | ||
{ | ||
for (int i=0; i<indent; i++) | ||
printf(" "); | ||
} | ||
|
||
static void print_src(PycRef<ASTNode> node, PycModule* mod, int indent = 0) | ||
{ | ||
switch (node->type()) { | ||
case ASTNode::NODE_LIST: | ||
{ | ||
ASTNodeList::list_t lines = node.cast<ASTNodeList>()->nodes(); | ||
for (ASTNodeList::list_t::iterator ln = lines.begin(); ln != lines.end(); ++ln) | ||
print_src(*ln, mod, indent); | ||
} | ||
break; | ||
case ASTNode::NODE_STORE: | ||
{ | ||
PycRef<ASTNode> src = node.cast<ASTStore>()->src(); | ||
PycRef<ASTNode> dest = node.cast<ASTStore>()->dest(); | ||
start_indent(indent); | ||
print_src(dest, mod); | ||
printf(" = "); | ||
print_src(src, mod); | ||
printf("\n"); | ||
} | ||
break; | ||
case ASTNode::NODE_OBJECT: | ||
print_const(node.cast<ASTObject>()->object(), mod); | ||
break; | ||
case ASTNode::NODE_NAME: | ||
{ | ||
ASTName::name_t name = node.cast<ASTName>()->name(); | ||
ASTName::name_t::iterator n = name.begin(); | ||
printf("%s", (*n)->value()); | ||
while (++n != name.end()) | ||
printf(".%s", (*n)->value()); | ||
} | ||
break; | ||
default: | ||
printf("Unsupported Node type: %d\n", node->type()); | ||
} | ||
} | ||
|
||
void ASTree::printSource(PycModule* mod) const | ||
{ | ||
print_src(m_root, mod, 0); | ||
} |
Oops, something went wrong.