[Python-checkins] CVS: /python/nondist/src/Compiler/compiler pycodegen.py,1.17,1.18

Jeremy Hylton jhylton@cnri.reston.va.us
Mon, 6 Mar 2000 14:10:57 -0500


Update of /projects/cvsroot//python/nondist/src/Compiler/compiler
In directory goon.cnri.reston.va.us:/home/jhylton/python/nondist/src/Compiler/compiler
Modified Files:
	pycodegen.py 
Log Message:
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
Index: pycodegen.py
===================================================================
RCS file: /projects/cvsroot//python/nondist/src/Compiler/compiler/pycodegen.py,v
retrieving revision 1.17
retrieving revision 1.18
diff -C2 -r1.17 -r1.18
*** pycodegen.py	2000年02月17日 22:09:35	1.17
--- pycodegen.py	2000年03月06日 19:10:54	1.18
***************
*** 6,10 ****
 """
 
! from p2c import transformer, ast
 from pyassem import StackRef, PyAssembler, TupleArg
 import dis
--- 6,10 ----
 """
 
! from compiler import parseFile, ast, visitor, walk, parse
 from pyassem import StackRef, PyAssembler, TupleArg
 import dis
***************
*** 19,159 ****
 import types
 
- def parse(path):
- f = open(path)
- src = f.read()
- f.close()
- t = transformer.Transformer()
- return t.parsesuite(src)
- 
- def walk(tree, visitor, verbose=None, walker=None):
- if walker:
- w = walker()
- else:
- w = ASTVisitor()
- if verbose is not None:
- w.VERBOSE = verbose
- w.preorder(tree, visitor)
- return w.visitor
- 
- def dumpNode(node):
- print node.__class__
- for attr in dir(node):
- if attr[0] != '_':
- print "\t", "%-10.10s" % attr, getattr(node, attr)
- 
- class ASTVisitor:
- """Performs a depth-first walk of the AST
- 
- The ASTVisitor will walk the AST, performing either a preorder or
- postorder traversal depending on which method is called.
- 
- methods:
- preorder(tree, visitor)
- postorder(tree, visitor)
- tree: an instance of ast.Node
- visitor: an instance with visitXXX methods
- 
- The ASTVisitor is responsible for walking over the tree in the
- correct order. For each node, it checks the visitor argument for
- a method named 'visitNodeType' where NodeType is the name of the
- node's class, e.g. Classdef. If the method exists, it is called
- with the node as its sole argument.
- 
- The visitor method for a particular node type can control how
- child nodes are visited during a preorder walk. (It can't control
- the order during a postorder walk, because it is called _after_
- the walk has occurred.) The ASTVisitor modifies the visitor
- argument by adding a visit method to the visitor; this method can
- be used to visit a particular child node. If the visitor method
- returns a true value, the ASTVisitor will not traverse the child
- nodes.
- 
- XXX The interface for controlling the preorder walk needs to be
- re-considered. The current interface is convenient for visitors
- that mostly let the ASTVisitor do everything. For something like
- a code generator, where you want to walk to occur in a specific
- order, it's a pain to add "return 1" to the end of each method.
- 
- XXX Perhaps I can use a postorder walk for the code generator?
- """
- 
- VERBOSE = 0
- 
- def __init__(self):
- self.node = None
- 
- def preorder(self, tree, visitor):
- """Do preorder walk of tree using visitor"""
- self.visitor = visitor
- visitor.visit = self._preorder
- self._preorder(tree)
- 
- def _preorder(self, node):
- stop = self.dispatch(node)
- if stop:
- return
- for child in node.getChildren():
- if isinstance(child, ast.Node):
- self._preorder(child)
- 
- def postorder(self, tree, visitor):
- """Do preorder walk of tree using visitor"""
- self.visitor = visitor
- visitor.visit = self._postorder
- self._postorder(tree)
- 
- def _postorder(self, tree):
- for child in node.getChildren():
- if isinstance(child, ast.Node):
- self._preorder(child)
- self.dispatch(node)
- 
- def dispatch(self, node):
- self.node = node
- className = node.__class__.__name__
- meth = getattr(self.visitor, 'visit' + className, None)
- if self.VERBOSE > 0:
- if self.VERBOSE == 1:
- if meth is None:
- print "dispatch", className
- else:
- print "dispatch", className, (meth and meth.__name__ or '')
- if meth:
- return meth(node)
- 
- class ExampleASTVisitor(ASTVisitor):
- """Prints examples of the nodes that aren't visited
- 
- This visitor-driver is only useful for development, when it's
- helpful to develop a visitor incremently, and get feedback on what
- you still have to do.
- """
- examples = {}
- 
- def dispatch(self, node):
- self.node = node
- className = node.__class__.__name__
- meth = getattr(self.visitor, 'visit' + className, None)
- if self.VERBOSE > 0:
- if self.VERBOSE == 1:
- if meth is None:
- print "dispatch", className
- else:
- print "dispatch", className, (meth and meth.__name__ or '')
- if meth:
- return meth(node)
- else:
- klass = node.__class__
- if self.VERBOSE < 2:
- if self.examples.has_key(klass):
- return
- self.examples[klass] = klass
- print
- print klass
- for attr in dir(node):
- if attr[0] != '_':
- print "\t", "%-12.12s" % attr, getattr(node, attr)
- print
- 
 class CodeGenerator:
 """Generate bytecode for the Python VM"""
--- 19,22 ----
***************
*** 312,316 ****
 self.emit('POP_TOP')
 
! def visitClassdef(self, node):
 self.emit('SET_LINENO', node.lineno)
 self.emit('LOAD_CONST', node.name)
--- 175,179 ----
 self.emit('POP_TOP')
 
! def visitClass(self, node):
 self.emit('SET_LINENO', node.lineno)
 self.emit('LOAD_CONST', node.name)
***************
*** 661,664 ****
--- 524,529 ----
 visitAssList = visitAssTuple
 
+ # binary ops
+ 
 def binaryOp(self, node, op):
 self.visit(node.left)
***************
*** 667,675 ****
 return 1
 
- def unaryOp(self, node, op):
- self.visit(node.expr)
- self.emit(op)
- return 1
- 
 def visitAdd(self, node):
 return self.binaryOp(node, 'BINARY_ADD')
--- 532,535 ----
***************
*** 696,699 ****
--- 556,566 ----
 return self.binaryOp(node, 'BINARY_RSHIFT')
 
+ # unary ops
+ 
+ def unaryOp(self, node, op):
+ self.visit(node.expr)
+ self.emit(op)
+ return 1
+ 
 def visitInvert(self, node):
 return self.unaryOp(node, 'UNARY_INVERT')
***************
*** 714,717 ****
--- 581,586 ----
 return self.unaryOp(node, 'UNARY_CONVERT')
 
+ # bit ops
+ 
 def bitOp(self, nodes, op):
 self.visit(nodes[0])
***************
*** 730,743 ****
 return self.bitOp(node.nodes, 'BINARY_XOR')
 
- def visitTest(self, node, jump):
- end = StackRef()
- for child in node.nodes[:-1]:
- self.visit(child)
- self.emit(jump, end)
- self.emit('POP_TOP')
- self.visit(node.nodes[-1])
- end.bind(self.code.getCurInst())
- return 1
- 
 def visitAssert(self, node):
 # XXX __debug__ and AssertionError appear to be special cases
--- 599,602 ----
***************
*** 758,761 ****
--- 617,630 ----
 return 1
 
+ def visitTest(self, node, jump):
+ end = StackRef()
+ for child in node.nodes[:-1]:
+ self.visit(child)
+ self.emit(jump, end)
+ self.emit('POP_TOP')
+ self.visit(node.nodes[-1])
+ end.bind(self.code.getCurInst())
+ return 1
+ 
 def visitAnd(self, node):
 return self.visitTest(node, 'JUMP_IF_FALSE')
***************
*** 880,884 ****
 self.names.add(name)
 
! def visitClassdef(self, node):
 self.names.add(node.name)
 return 1
--- 749,753 ----
 self.names.add(name)
 
! def visitClass(self, node):
 self.names.add(node.name)
 return 1
***************
*** 922,927 ****
 
 def compile(self):
! t = transformer.Transformer()
! self.ast = t.parsesuite(self.source)
 cg = CodeGenerator(self.filename)
 walk(self.ast, cg)
--- 791,795 ----
 
 def compile(self):
! 	self.ast = parse(self.source)
 cg = CodeGenerator(self.filename)
 walk(self.ast, cg)
***************
*** 951,971 ****
 mod.dump(filename + 'c')
 
- if __name__ == "__main__":
- import getopt
- 
- VERBOSE = 0
- opts, args = getopt.getopt(sys.argv[1:], 'vq')
- for k, v in opts:
- if k == '-v':
- VERBOSE = 1
- ASTVisitor.VERBOSE = ASTVisitor.VERBOSE + 1
- if k == '-q':
- f = open('/dev/null', 'wb')
- sys.stdout = f
- if not args:
- print "no files to compile"
- else:
- for filename in args:
- if VERBOSE:
- print filename
- compile(filename)
--- 819,820 ----

AltStyle によって変換されたページ (->オリジナル) /