Permalink
Browse files

Great refactoring: SymbolVisitor pulled into RunCompiler.

_ModuleContext() gets a self.scopes member.  It was confusing that
visitExpression called parseSymbols.  It made it seem as though
self.scopes was being mutated, when it really happened only at the top
level.

The Expression node is for 'eval' only.

Also, inline a useless function.
  • Loading branch information...
Andy Chu
Andy Chu committed Mar 20, 2018
1 parent 2499287 commit 7e528a41efad1a7efbe5e067b55d2498620478b5
Showing with 37 additions and 39 deletions.
  1. +24 −33 opy/compiler2/pycodegen.py
  2. +2 −2 opy/compiler2/symbols.py
  3. +11 −4 opy/opy_main.py
View
@@ -1,4 +1,4 @@
from . import ast, pyassem, misc, symbols
from . import ast, pyassem, misc
from .visitor import ASTVisitor
from .consts import (
SC_LOCAL, SC_GLOBAL_IMPLICIT, SC_GLOBAL_EXPLICIT, SC_FREE, SC_CELL)
@@ -102,6 +102,10 @@ def __init__(self, graph, ctx):
self.graph = graph
self.ctx = ctx # passed down to child CodeGenerator instances
# Set by visitModule, visitExpression (for eval), or by subclass
# constructor.
self.scope = None
self.locals = Stack()
self.setups = Stack()
self.last_lineno = None
@@ -144,11 +148,6 @@ def Start(self):
def mangle(self, name):
return misc.mangle(name, self.class_name)
def parseSymbols(self, tree):
s = symbols.SymbolVisitor()
s.Dispatch(tree)
return s.scopes
# Next five methods handle name access
def storeName(self, name):
@@ -220,8 +219,7 @@ def set_lineno(self, node, force=False):
return False
def visitModule(self, node):
self.scopes = self.parseSymbols(node)
self.scope = self.scopes[node]
self.scope = self.ctx.scopes[node]
self.emit('SET_LINENO', 0)
if node.doc:
self.emit('LOAD_CONST', node.doc)
@@ -236,10 +234,12 @@ def visitModule(self, node):
self.emit('RETURN_VALUE')
def visitExpression(self, node):
"""Expression is an artificial node to support "eval". """
"""Expression is an artificial node to support "eval".
TODO: Could be renamed EvalModule?
"""
self.set_lineno(node)
self.scopes = self.parseSymbols(node)
self.scope = self.scopes[node]
self.scope = self.ctx.scopes[node]
self.visit(node.node)
self.emit('RETURN_VALUE')
@@ -261,8 +261,7 @@ def visitFunction(self, node):
graph = pyassem.PyFlowGraph(node.name, self.ctx.filename, optimized=1)
graph.setArgs(node.argnames)
gen = FunctionCodeGenerator(graph, self.ctx, node, self.scopes,
self.class_name)
gen = FunctionCodeGenerator(graph, self.ctx, node, self.class_name)
self._funcOrLambda(node, gen, ndecorators)
@@ -283,8 +282,7 @@ def visitLambda(self, node):
graph = pyassem.PyFlowGraph(obj_name, self.ctx.filename, optimized=1)
graph.setArgs(node.argnames)
gen = LambdaCodeGenerator(graph, self.ctx, node, self.scopes,
self.class_name)
gen = LambdaCodeGenerator(graph, self.ctx, node, self.class_name)
self._funcOrLambda(node, gen, 0)
@@ -304,7 +302,7 @@ def _funcOrLambda(self, node, gen, ndecorators):
def visitClass(self, node):
graph = pyassem.PyFlowGraph(node.name, self.ctx.filename,
optimized=0, klass=1)
gen = ClassCodeGenerator(graph, self.ctx, node, self.scopes)
gen = ClassCodeGenerator(graph, self.ctx, node)
gen.Start()
gen.FindLocals()
@@ -595,8 +593,7 @@ def visitGenExpr(self, node):
graph = pyassem.PyFlowGraph(obj_name, self.ctx.filename, optimized=1)
graph.setArgs(node.argnames)
gen = GenExprCodeGenerator(graph, self.ctx, node, self.scopes,
self.class_name)
gen = GenExprCodeGenerator(graph, self.ctx, node, self.class_name)
gen.Start()
gen.FindLocals()
@@ -907,7 +904,10 @@ def visitAssAttr(self, node):
print(node)
def _visitAssSequence(self, node, op='UNPACK_SEQUENCE'):
if findOp(node) != 'OP_DELETE':
v = OpFinder()
v.Dispatch(node)
if v.op != 'OP_DELETE':
self.emit(op, len(node.nodes))
for child in node.nodes:
self.visit(child)
@@ -1239,13 +1239,12 @@ class _FunctionCodeGenerator(CodeGenerator):
"""Abstract class."""
optimized = 1
def __init__(self, graph, ctx, func, scopes, class_name):
def __init__(self, graph, ctx, func, class_name):
CodeGenerator.__init__(self, graph, ctx)
self.func = func
self.scopes = scopes
self.class_name = class_name
self.scope = scopes[func]
self.scope = self.ctx.scopes[func]
def FindLocals(self):
func = self.func
@@ -1298,14 +1297,12 @@ def Finish(self):
class ClassCodeGenerator(CodeGenerator):
def __init__(self, graph, ctx, klass, scopes):
def __init__(self, graph, ctx, klass):
CodeGenerator.__init__(self, graph, ctx)
self.klass = klass
self.scopes = scopes
self.class_name = klass.name
self.scope = scopes[klass]
self.scope = self.ctx.scopes[klass]
def _Start(self):
self.set_lineno(self.klass)
@@ -1330,14 +1327,8 @@ def Finish(self):
self.emit('RETURN_VALUE')
def findOp(node):
"""Find the op (DELETE, LOAD, STORE) in an AssTuple tree"""
v = OpFinder()
v.Dispatch(node)
return v.op
class OpFinder(ASTVisitor):
"""Find the op (DELETE, LOAD, STORE) in an AssTuple tree"""
def __init__(self):
ASTVisitor.__init__(self)
View
@@ -210,10 +210,10 @@ class ClassScope(Scope):
class SymbolVisitor(ASTVisitor):
def __init__(self):
ASTVisitor.__init__(self)
self.scopes = {} # The "return value" of walk()
self.scopes = {} # node -> Scope instance, the "return value".
self.klass = None
# node that define new scopes
# Nodes that define new scopes
def visitModule(self, node):
scope = self.module = self.scopes[node] = ModuleScope()
View
@@ -29,6 +29,7 @@
from .compiler2 import pyassem
from .compiler2 import pycodegen
from .compiler2 import syntax
from .compiler2 import symbols
from .compiler2 import transformer
# Disabled for now because byterun imports 'six', and that breaks the build.
@@ -148,8 +149,9 @@ def py2st(unused_gr, raw_node):
class _ModuleContext(object):
"""Module-level data for the CodeGenerator tree."""
def __init__(self, filename, futures=()):
def __init__(self, filename, scopes, futures=()):
self.filename = filename
self.scopes = scopes
self.futures = futures
@@ -166,14 +168,19 @@ def RunCompiler(f, filename, gr, start_symbol, mode):
tr = transformer.Transformer()
as_tree = tr.transform(parse_tree)
#log('AST: %s', as_tree)
# NOTE: This currently does nothing!
v = syntax.SyntaxErrorChecker()
v.Dispatch(as_tree)
s = symbols.SymbolVisitor()
s.Dispatch(as_tree)
if mode == "single":
# NOTE: the name of the flow graph is a comment, not exposed to users.
graph = pyassem.PyFlowGraph("<interactive>", filename)
ctx = _ModuleContext(filename)
ctx = _ModuleContext(filename, s.scopes)
gen = pycodegen.InteractiveCodeGenerator(graph, ctx)
gen.set_lineno(as_tree)
@@ -186,12 +193,12 @@ def RunCompiler(f, filename, gr, start_symbol, mode):
p1.Dispatch(as_tree)
p2.Dispatch(as_tree)
ctx = _ModuleContext(filename, futures=p1.get_features())
ctx = _ModuleContext(filename, s.scopes, futures=p1.get_features())
gen = pycodegen.TopLevelCodeGenerator(graph, ctx)
elif mode == "eval":
graph = pyassem.PyFlowGraph("<expression>", filename)
ctx = _ModuleContext(filename)
ctx = _ModuleContext(filename, s.scopes)
gen = pycodegen.TopLevelCodeGenerator(graph, ctx)
else:

0 comments on commit 7e528a4

Please sign in to comment.