Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 7fab23e

Browse files
committed
rename compile.py to pycodegen.py
fix imports remove parse functions and visitor code track name change: Classdef to Class add some comments and tweak order of visitXXX methods get rid of if __name__ == "__main__ section
1 parent 8c78341 commit 7fab23e

2 files changed

Lines changed: 50 additions & 352 deletions

File tree

Lib/compiler/pycodegen.py

Lines changed: 25 additions & 176 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
a generic tool and CodeGenerator as a specific tool.
66
"""
77

8-
from p2c import transformer, ast
8+
from compiler import parseFile, ast, visitor, walk, parse
99
from pyassem import StackRef, PyAssembler, TupleArg
1010
import dis
1111
import misc
@@ -18,143 +18,6 @@
1818
import struct
1919
import types
2020

21-
def parse(path):
22-
f = open(path)
23-
src = f.read()
24-
f.close()
25-
t = transformer.Transformer()
26-
return t.parsesuite(src)
27-
28-
def walk(tree, visitor, verbose=None, walker=None):
29-
if walker:
30-
w = walker()
31-
else:
32-
w = ASTVisitor()
33-
if verbose is not None:
34-
w.VERBOSE = verbose
35-
w.preorder(tree, visitor)
36-
return w.visitor
37-
38-
def dumpNode(node):
39-
print node.__class__
40-
for attr in dir(node):
41-
if attr[0] != '_':
42-
print "\t", "%-10.10s" % attr, getattr(node, attr)
43-
44-
class ASTVisitor:
45-
"""Performs a depth-first walk of the AST
46-
47-
The ASTVisitor will walk the AST, performing either a preorder or
48-
postorder traversal depending on which method is called.
49-
50-
methods:
51-
preorder(tree, visitor)
52-
postorder(tree, visitor)
53-
tree: an instance of ast.Node
54-
visitor: an instance with visitXXX methods
55-
56-
The ASTVisitor is responsible for walking over the tree in the
57-
correct order. For each node, it checks the visitor argument for
58-
a method named 'visitNodeType' where NodeType is the name of the
59-
node's class, e.g. Classdef. If the method exists, it is called
60-
with the node as its sole argument.
61-
62-
The visitor method for a particular node type can control how
63-
child nodes are visited during a preorder walk. (It can't control
64-
the order during a postorder walk, because it is called _after_
65-
the walk has occurred.) The ASTVisitor modifies the visitor
66-
argument by adding a visit method to the visitor; this method can
67-
be used to visit a particular child node. If the visitor method
68-
returns a true value, the ASTVisitor will not traverse the child
69-
nodes.
70-
71-
XXX The interface for controlling the preorder walk needs to be
72-
re-considered. The current interface is convenient for visitors
73-
that mostly let the ASTVisitor do everything. For something like
74-
a code generator, where you want to walk to occur in a specific
75-
order, it's a pain to add "return 1" to the end of each method.
76-
77-
XXX Perhaps I can use a postorder walk for the code generator?
78-
"""
79-
80-
VERBOSE = 0
81-
82-
def __init__(self):
83-
self.node = None
84-
85-
def preorder(self, tree, visitor):
86-
"""Do preorder walk of tree using visitor"""
87-
self.visitor = visitor
88-
visitor.visit = self._preorder
89-
self._preorder(tree)
90-
91-
def _preorder(self, node):
92-
stop = self.dispatch(node)
93-
if stop:
94-
return
95-
for child in node.getChildren():
96-
if isinstance(child, ast.Node):
97-
self._preorder(child)
98-
99-
def postorder(self, tree, visitor):
100-
"""Do preorder walk of tree using visitor"""
101-
self.visitor = visitor
102-
visitor.visit = self._postorder
103-
self._postorder(tree)
104-
105-
def _postorder(self, tree):
106-
for child in node.getChildren():
107-
if isinstance(child, ast.Node):
108-
self._preorder(child)
109-
self.dispatch(node)
110-
111-
def dispatch(self, node):
112-
self.node = node
113-
className = node.__class__.__name__
114-
meth = getattr(self.visitor, 'visit' + className, None)
115-
if self.VERBOSE > 0:
116-
if self.VERBOSE == 1:
117-
if meth is None:
118-
print "dispatch", className
119-
else:
120-
print "dispatch", className, (meth and meth.__name__ or '')
121-
if meth:
122-
return meth(node)
123-
124-
class ExampleASTVisitor(ASTVisitor):
125-
"""Prints examples of the nodes that aren't visited
126-
127-
This visitor-driver is only useful for development, when it's
128-
helpful to develop a visitor incremently, and get feedback on what
129-
you still have to do.
130-
"""
131-
examples = {}
132-
133-
def dispatch(self, node):
134-
self.node = node
135-
className = node.__class__.__name__
136-
meth = getattr(self.visitor, 'visit' + className, None)
137-
if self.VERBOSE > 0:
138-
if self.VERBOSE == 1:
139-
if meth is None:
140-
print "dispatch", className
141-
else:
142-
print "dispatch", className, (meth and meth.__name__ or '')
143-
if meth:
144-
return meth(node)
145-
else:
146-
klass = node.__class__
147-
if self.VERBOSE < 2:
148-
if self.examples.has_key(klass):
149-
return
150-
self.examples[klass] = klass
151-
print
152-
print klass
153-
for attr in dir(node):
154-
if attr[0] != '_':
155-
print "\t", "%-12.12s" % attr, getattr(node, attr)
156-
print
157-
15821
class CodeGenerator:
15922
"""Generate bytecode for the Python VM"""
16023

@@ -311,7 +174,7 @@ def visitFrom(self, node):
311174
self.emit('IMPORT_FROM', name)
312175
self.emit('POP_TOP')
313176

314-
def visitClassdef(self, node):
177+
def visitClass(self, node):
315178
self.emit('SET_LINENO', node.lineno)
316179
self.emit('LOAD_CONST', node.name)
317180
for base in node.bases:
@@ -660,17 +523,14 @@ def visitAssTuple(self, node):
660523

661524
visitAssList = visitAssTuple
662525

526+
# binary ops
527+
663528
def binaryOp(self, node, op):
664529
self.visit(node.left)
665530
self.visit(node.right)
666531
self.emit(op)
667532
return 1
668533

669-
def unaryOp(self, node, op):
670-
self.visit(node.expr)
671-
self.emit(op)
672-
return 1
673-
674534
def visitAdd(self, node):
675535
return self.binaryOp(node, 'BINARY_ADD')
676536

@@ -695,6 +555,13 @@ def visitLeftShift(self, node):
695555
def visitRightShift(self, node):
696556
return self.binaryOp(node, 'BINARY_RSHIFT')
697557

558+
# unary ops
559+
560+
def unaryOp(self, node, op):
561+
self.visit(node.expr)
562+
self.emit(op)
563+
return 1
564+
698565
def visitInvert(self, node):
699566
return self.unaryOp(node, 'UNARY_INVERT')
700567

@@ -713,6 +580,8 @@ def visitNot(self, node):
713580
def visitBackquote(self, node):
714581
return self.unaryOp(node, 'UNARY_CONVERT')
715582

583+
# bit ops
584+
716585
def bitOp(self, nodes, op):
717586
self.visit(nodes[0])
718587
for node in nodes[1:]:
@@ -729,16 +598,6 @@ def visitBitor(self, node):
729598
def visitBitxor(self, node):
730599
return self.bitOp(node.nodes, 'BINARY_XOR')
731600

732-
def visitTest(self, node, jump):
733-
end = StackRef()
734-
for child in node.nodes[:-1]:
735-
self.visit(child)
736-
self.emit(jump, end)
737-
self.emit('POP_TOP')
738-
self.visit(node.nodes[-1])
739-
end.bind(self.code.getCurInst())
740-
return 1
741-
742601
def visitAssert(self, node):
743602
# XXX __debug__ and AssertionError appear to be special cases
744603
# -- they are always loaded as globals even if there are local
@@ -757,6 +616,16 @@ def visitAssert(self, node):
757616
self.emit('POP_TOP')
758617
return 1
759618

619+
def visitTest(self, node, jump):
620+
end = StackRef()
621+
for child in node.nodes[:-1]:
622+
self.visit(child)
623+
self.emit(jump, end)
624+
self.emit('POP_TOP')
625+
self.visit(node.nodes[-1])
626+
end.bind(self.code.getCurInst())
627+
return 1
628+
760629
def visitAnd(self, node):
761630
return self.visitTest(node, 'JUMP_IF_FALSE')
762631

@@ -879,7 +748,7 @@ def visitFrom(self, node):
879748
for name in node.names:
880749
self.names.add(name)
881750

882-
def visitClassdef(self, node):
751+
def visitClass(self, node):
883752
self.names.add(node.name)
884753
return 1
885754

@@ -921,8 +790,7 @@ def __init__(self, source, filename):
921790
self.filename = filename
922791

923792
def compile(self):
924-
t = transformer.Transformer()
925-
self.ast = t.parsesuite(self.source)
793+
self.ast = parse(self.source)
926794
cg = CodeGenerator(self.filename)
927795
walk(self.ast, cg)
928796
self.code = cg.asConst()
@@ -950,22 +818,3 @@ def compile(filename):
950818
mod.compile()
951819
mod.dump(filename + 'c')
952820

953-
if __name__ == "__main__":
954-
import getopt
955-
956-
VERBOSE = 0
957-
opts, args = getopt.getopt(sys.argv[1:], 'vq')
958-
for k, v in opts:
959-
if k == '-v':
960-
VERBOSE = 1
961-
ASTVisitor.VERBOSE = ASTVisitor.VERBOSE + 1
962-
if k == '-q':
963-
f = open('/dev/null', 'wb')
964-
sys.stdout = f
965-
if not args:
966-
print "no files to compile"
967-
else:
968-
for filename in args:
969-
if VERBOSE:
970-
print filename
971-
compile(filename)

0 commit comments

Comments
 (0)