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

Skip to content

Commit 2afff32

Browse files
committed
Many changes -- bug fixes and sundry improvements
Make nested scopes enabled by default Add is_constant_false() helper so that compiled code and symbols are consistent with builtin compiler's handling of "if 0:" Fix doc string handling to be consistent with recent change that eliminates the doc string from the Module's node attribute. Add fix to print handling from Evan & Shane. Track change to visitor api by making "verbose" explicit. Comment out setting CO_NESTED flag (it's unnecessary in 2.2).
1 parent 9f44815 commit 2afff32

2 files changed

Lines changed: 60 additions & 66 deletions

File tree

Lib/compiler/pycodegen.py

Lines changed: 30 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -40,18 +40,14 @@ def compile(filename, display=0):
4040

4141
class Module:
4242
def __init__(self, source, filename):
43-
self.filename = filename
43+
self.filename = os.path.abspath(filename)
4444
self.source = source
4545
self.code = None
4646

4747
def compile(self, display=0):
4848
tree = parse(self.source)
49-
root, filename = os.path.split(self.filename)
50-
if "nested_scopes" in future.find_futures(tree):
51-
gen = NestedScopeModuleCodeGenerator(filename)
52-
else:
53-
gen = ModuleCodeGenerator(filename)
54-
walk(tree, gen, 1)
49+
gen = NestedScopeModuleCodeGenerator(self.filename)
50+
walk(tree, gen, verbose=1)
5551
if display:
5652
import pprint
5753
print pprint.pprint(tree)
@@ -115,6 +111,12 @@ def visitClass(self, node):
115111
def visitAssName(self, node):
116112
self.names.add(node.name)
117113

114+
def is_constant_false(node):
115+
if isinstance(node, ast.Const):
116+
if not node.value:
117+
return 1
118+
return 0
119+
118120
class CodeGenerator:
119121
"""Defines basic code generator for Python bytecode
120122
@@ -234,10 +236,11 @@ def set_lineno(self, node, force=0):
234236

235237
def visitModule(self, node):
236238
self.emit('SET_LINENO', 0)
237-
lnf = walk(node.node, self.NameFinder(), 0)
238-
self.locals.push(lnf.getLocals())
239239
if node.doc:
240-
self.fixDocstring(node.node)
240+
self.emit('LOAD_CONST', node.doc)
241+
self.storeName('__doc__')
242+
lnf = walk(node.node, self.NameFinder(), verbose=0)
243+
self.locals.push(lnf.getLocals())
241244
self.visit(node.node)
242245
self.emit('LOAD_CONST', None)
243246
self.emit('RETURN_VALUE')
@@ -264,7 +267,8 @@ def _visitFuncOrLambda(self, node, isLambda=0):
264267
def visitClass(self, node):
265268
gen = self.ClassGen(node, self.filename, self.scopes)
266269
if node.doc:
267-
self.fixDocstring(node.code)
270+
self.emit('LOAD_CONST', node.doc)
271+
self.storeName('__doc__')
268272
walk(node.code, gen)
269273
gen.finish()
270274
self.set_lineno(node)
@@ -278,19 +282,6 @@ def visitClass(self, node):
278282
self.emit('BUILD_CLASS')
279283
self.storeName(node.name)
280284

281-
def fixDocstring(self, node):
282-
"""Rewrite the ast for a class with a docstring.
283-
284-
The AST includes a Discard(Const(docstring)) node. Replace
285-
this with an Assign([AssName('__doc__', ...])
286-
"""
287-
assert isinstance(node, ast.Stmt)
288-
stmts = node.nodes
289-
discard = stmts[0]
290-
assert isinstance(discard, ast.Discard)
291-
stmts[0] = ast.Assign([ast.AssName('__doc__', 'OP_ASSIGN')],
292-
discard.expr)
293-
stmts[0].lineno = discard.lineno
294285
# The rest are standard visitor methods
295286

296287
# The next few implement control-flow statements
@@ -300,6 +291,9 @@ def visitIf(self, node):
300291
numtests = len(node.tests)
301292
for i in range(numtests):
302293
test, suite = node.tests[i]
294+
if is_constant_false(test):
295+
# XXX will need to check generator stuff here
296+
continue
303297
self.set_lineno(test)
304298
self.visit(test)
305299
nextTest = self.newBlock()
@@ -793,7 +787,7 @@ def visitCallFunc(self, node):
793787
opcode = callfunc_opcode_info[have_star, have_dstar]
794788
self.emit(opcode, kw << 8 | pos)
795789

796-
def visitPrint(self, node):
790+
def visitPrint(self, node, newline=0):
797791
self.set_lineno(node)
798792
if node.dest:
799793
self.visit(node.dest)
@@ -806,9 +800,11 @@ def visitPrint(self, node):
806800
self.emit('PRINT_ITEM_TO')
807801
else:
808802
self.emit('PRINT_ITEM')
803+
if node.dest and not newline:
804+
self.emit('POP_TOP')
809805

810806
def visitPrintnl(self, node):
811-
self.visitPrint(node)
807+
self.visitPrint(node, newline=1)
812808
if node.dest:
813809
self.emit('PRINT_NEWLINE_TO')
814810
else:
@@ -1021,7 +1017,8 @@ def _visitFuncOrLambda(self, node, isLambda=0):
10211017
def visitClass(self, node):
10221018
gen = self.ClassGen(node, self.filename, self.scopes)
10231019
if node.doc:
1024-
self.fixDocstring(node.code)
1020+
self.emit('LOAD_CONST', node.doc)
1021+
self.storeName('__doc__')
10251022
walk(node.code, gen)
10261023
gen.finish()
10271024
self.set_lineno(node)
@@ -1072,7 +1069,7 @@ class NestedScopeModuleCodeGenerator(NestedScopeMixin,
10721069
def __init__(self, filename):
10731070
self.graph = pyassem.PyFlowGraph("<module>", filename)
10741071
self.__super_init(filename)
1075-
self.graph.setFlag(CO_NESTED)
1072+
## self.graph.setFlag(CO_NESTED)
10761073

10771074
class AbstractFunctionCode:
10781075
optimized = 1
@@ -1094,7 +1091,7 @@ def __init__(self, func, filename, scopes, isLambda):
10941091
if not isLambda and func.doc:
10951092
self.setDocstring(func.doc)
10961093

1097-
lnf = walk(func.code, self.NameFinder(args), 0)
1094+
lnf = walk(func.code, self.NameFinder(args), verbose=0)
10981095
self.locals.push(lnf.getLocals())
10991096
if func.varargs:
11001097
self.graph.setFlag(CO_VARARGS)
@@ -1147,15 +1144,15 @@ def __init__(self, func, filename, scopes, isLambda):
11471144
self.__super_init(func, filename, scopes, isLambda)
11481145
self.graph.setFreeVars(self.scope.get_free_vars())
11491146
self.graph.setCellVars(self.scope.get_cell_vars())
1150-
self.graph.setFlag(CO_NESTED)
1147+
## self.graph.setFlag(CO_NESTED)
11511148

11521149
class AbstractClassCode:
11531150

11541151
def __init__(self, klass, filename, scopes):
11551152
self.graph = pyassem.PyFlowGraph(klass.name, filename,
11561153
optimized=0)
11571154
self.super_init(filename)
1158-
lnf = walk(klass.code, self.NameFinder(), 0)
1155+
lnf = walk(klass.code, self.NameFinder(), verbose=0)
11591156
self.locals.push(lnf.getLocals())
11601157
self.graph.setFlag(CO_NEWLOCALS)
11611158
if klass.doc:
@@ -1186,7 +1183,7 @@ def __init__(self, klass, filename, scopes):
11861183
self.__super_init(klass, filename, scopes)
11871184
self.graph.setFreeVars(self.scope.get_free_vars())
11881185
self.graph.setCellVars(self.scope.get_cell_vars())
1189-
self.graph.setFlag(CO_NESTED)
1186+
## self.graph.setFlag(CO_NESTED)
11901187

11911188
def generateArgList(arglist):
11921189
"""Generate an arg list marking TupleArgs"""
@@ -1208,7 +1205,7 @@ def generateArgList(arglist):
12081205
def findOp(node):
12091206
"""Find the op (DELETE, LOAD, STORE) in an AssTuple tree"""
12101207
v = OpFinder()
1211-
walk(node, v, 0)
1208+
walk(node, v, verbose=0)
12121209
return v.op
12131210

12141211
class OpFinder:

Tools/compiler/compiler/pycodegen.py

Lines changed: 30 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -40,18 +40,14 @@ def compile(filename, display=0):
4040

4141
class Module:
4242
def __init__(self, source, filename):
43-
self.filename = filename
43+
self.filename = os.path.abspath(filename)
4444
self.source = source
4545
self.code = None
4646

4747
def compile(self, display=0):
4848
tree = parse(self.source)
49-
root, filename = os.path.split(self.filename)
50-
if "nested_scopes" in future.find_futures(tree):
51-
gen = NestedScopeModuleCodeGenerator(filename)
52-
else:
53-
gen = ModuleCodeGenerator(filename)
54-
walk(tree, gen, 1)
49+
gen = NestedScopeModuleCodeGenerator(self.filename)
50+
walk(tree, gen, verbose=1)
5551
if display:
5652
import pprint
5753
print pprint.pprint(tree)
@@ -115,6 +111,12 @@ def visitClass(self, node):
115111
def visitAssName(self, node):
116112
self.names.add(node.name)
117113

114+
def is_constant_false(node):
115+
if isinstance(node, ast.Const):
116+
if not node.value:
117+
return 1
118+
return 0
119+
118120
class CodeGenerator:
119121
"""Defines basic code generator for Python bytecode
120122
@@ -234,10 +236,11 @@ def set_lineno(self, node, force=0):
234236

235237
def visitModule(self, node):
236238
self.emit('SET_LINENO', 0)
237-
lnf = walk(node.node, self.NameFinder(), 0)
238-
self.locals.push(lnf.getLocals())
239239
if node.doc:
240-
self.fixDocstring(node.node)
240+
self.emit('LOAD_CONST', node.doc)
241+
self.storeName('__doc__')
242+
lnf = walk(node.node, self.NameFinder(), verbose=0)
243+
self.locals.push(lnf.getLocals())
241244
self.visit(node.node)
242245
self.emit('LOAD_CONST', None)
243246
self.emit('RETURN_VALUE')
@@ -264,7 +267,8 @@ def _visitFuncOrLambda(self, node, isLambda=0):
264267
def visitClass(self, node):
265268
gen = self.ClassGen(node, self.filename, self.scopes)
266269
if node.doc:
267-
self.fixDocstring(node.code)
270+
self.emit('LOAD_CONST', node.doc)
271+
self.storeName('__doc__')
268272
walk(node.code, gen)
269273
gen.finish()
270274
self.set_lineno(node)
@@ -278,19 +282,6 @@ def visitClass(self, node):
278282
self.emit('BUILD_CLASS')
279283
self.storeName(node.name)
280284

281-
def fixDocstring(self, node):
282-
"""Rewrite the ast for a class with a docstring.
283-
284-
The AST includes a Discard(Const(docstring)) node. Replace
285-
this with an Assign([AssName('__doc__', ...])
286-
"""
287-
assert isinstance(node, ast.Stmt)
288-
stmts = node.nodes
289-
discard = stmts[0]
290-
assert isinstance(discard, ast.Discard)
291-
stmts[0] = ast.Assign([ast.AssName('__doc__', 'OP_ASSIGN')],
292-
discard.expr)
293-
stmts[0].lineno = discard.lineno
294285
# The rest are standard visitor methods
295286

296287
# The next few implement control-flow statements
@@ -300,6 +291,9 @@ def visitIf(self, node):
300291
numtests = len(node.tests)
301292
for i in range(numtests):
302293
test, suite = node.tests[i]
294+
if is_constant_false(test):
295+
# XXX will need to check generator stuff here
296+
continue
303297
self.set_lineno(test)
304298
self.visit(test)
305299
nextTest = self.newBlock()
@@ -793,7 +787,7 @@ def visitCallFunc(self, node):
793787
opcode = callfunc_opcode_info[have_star, have_dstar]
794788
self.emit(opcode, kw << 8 | pos)
795789

796-
def visitPrint(self, node):
790+
def visitPrint(self, node, newline=0):
797791
self.set_lineno(node)
798792
if node.dest:
799793
self.visit(node.dest)
@@ -806,9 +800,11 @@ def visitPrint(self, node):
806800
self.emit('PRINT_ITEM_TO')
807801
else:
808802
self.emit('PRINT_ITEM')
803+
if node.dest and not newline:
804+
self.emit('POP_TOP')
809805

810806
def visitPrintnl(self, node):
811-
self.visitPrint(node)
807+
self.visitPrint(node, newline=1)
812808
if node.dest:
813809
self.emit('PRINT_NEWLINE_TO')
814810
else:
@@ -1021,7 +1017,8 @@ def _visitFuncOrLambda(self, node, isLambda=0):
10211017
def visitClass(self, node):
10221018
gen = self.ClassGen(node, self.filename, self.scopes)
10231019
if node.doc:
1024-
self.fixDocstring(node.code)
1020+
self.emit('LOAD_CONST', node.doc)
1021+
self.storeName('__doc__')
10251022
walk(node.code, gen)
10261023
gen.finish()
10271024
self.set_lineno(node)
@@ -1072,7 +1069,7 @@ class NestedScopeModuleCodeGenerator(NestedScopeMixin,
10721069
def __init__(self, filename):
10731070
self.graph = pyassem.PyFlowGraph("<module>", filename)
10741071
self.__super_init(filename)
1075-
self.graph.setFlag(CO_NESTED)
1072+
## self.graph.setFlag(CO_NESTED)
10761073

10771074
class AbstractFunctionCode:
10781075
optimized = 1
@@ -1094,7 +1091,7 @@ def __init__(self, func, filename, scopes, isLambda):
10941091
if not isLambda and func.doc:
10951092
self.setDocstring(func.doc)
10961093

1097-
lnf = walk(func.code, self.NameFinder(args), 0)
1094+
lnf = walk(func.code, self.NameFinder(args), verbose=0)
10981095
self.locals.push(lnf.getLocals())
10991096
if func.varargs:
11001097
self.graph.setFlag(CO_VARARGS)
@@ -1147,15 +1144,15 @@ def __init__(self, func, filename, scopes, isLambda):
11471144
self.__super_init(func, filename, scopes, isLambda)
11481145
self.graph.setFreeVars(self.scope.get_free_vars())
11491146
self.graph.setCellVars(self.scope.get_cell_vars())
1150-
self.graph.setFlag(CO_NESTED)
1147+
## self.graph.setFlag(CO_NESTED)
11511148

11521149
class AbstractClassCode:
11531150

11541151
def __init__(self, klass, filename, scopes):
11551152
self.graph = pyassem.PyFlowGraph(klass.name, filename,
11561153
optimized=0)
11571154
self.super_init(filename)
1158-
lnf = walk(klass.code, self.NameFinder(), 0)
1155+
lnf = walk(klass.code, self.NameFinder(), verbose=0)
11591156
self.locals.push(lnf.getLocals())
11601157
self.graph.setFlag(CO_NEWLOCALS)
11611158
if klass.doc:
@@ -1186,7 +1183,7 @@ def __init__(self, klass, filename, scopes):
11861183
self.__super_init(klass, filename, scopes)
11871184
self.graph.setFreeVars(self.scope.get_free_vars())
11881185
self.graph.setCellVars(self.scope.get_cell_vars())
1189-
self.graph.setFlag(CO_NESTED)
1186+
## self.graph.setFlag(CO_NESTED)
11901187

11911188
def generateArgList(arglist):
11921189
"""Generate an arg list marking TupleArgs"""
@@ -1208,7 +1205,7 @@ def generateArgList(arglist):
12081205
def findOp(node):
12091206
"""Find the op (DELETE, LOAD, STORE) in an AssTuple tree"""
12101207
v = OpFinder()
1211-
walk(node, v, 0)
1208+
walk(node, v, verbose=0)
12121209
return v.op
12131210

12141211
class OpFinder:

0 commit comments

Comments
 (0)