Permalink
Browse files

pyassem: Simplify PyFlowGraph interface.

Also remove members from PyFlowGraph.  More variables are locals in
the MakeCodeObject() method.
  • Loading branch information...
Andy Chu
Andy Chu committed Mar 20, 2018
1 parent ed4d1fb commit 9c47ae3ceffb17064f48d125d2f4573841c2541f
Showing with 32 additions and 50 deletions.
  1. +29 −47 opy/compiler2/pyassem.py
  2. +2 −2 opy/compiler2/pycodegen.py
  3. +1 −1 opy/compiler2/symbols.py
View
@@ -335,36 +335,21 @@ def __init__(self, name, filename, optimized=0, klass=None):
klass: Whether we're compiling a class block.
"""
FlowGraph.__init__(self)
self.name = name # name that is put in the code object
self.filename = filename
self.docstring = None
self.flags = (CO_OPTIMIZED | CO_NEWLOCALS) if optimized else 0
self.klass = klass
if optimized:
self.flags = CO_OPTIMIZED | CO_NEWLOCALS
else:
self.flags = 0
# TODO: All of these go in the code object. Might want to separate
# them. CodeContext.
self.consts = []
self.names = []
# Free variables found by the symbol table scan, including
# variables used only in nested scopes, are included here.
self.freevars = []
self.cellvars = []
# The closure list is used to track the order of cell
# variables and free variables in the resulting code object.
# The offsets used by LOAD_CLOSURE/LOAD_DEREF refer to both
# kinds of variables.
self.closure = []
# Mutated by setArgs()
self.varnames = []
self.argcount = 0
# TODO: setArgs, setFreeVars, setCellVars can be done in constructor. The
# scope is available.
# Mutated by setVars(). Free variables found by the symbol table scan,
# including variables used only in nested scopes, are included here.
self.freevars = []
self.cellvars = []
self.docstring = None
def setArgs(self, args):
"""Only called by functions, not modules or classes."""
@@ -373,51 +358,46 @@ def setArgs(self, args):
self.varnames = list(args)
self.argcount = len(args)
def setFreeVars(self, names):
self.freevars = list(names)
def setCellVars(self, names):
self.cellvars = names
def setVars(self, freevars, cellvars):
self.freevars = freevars
self.cellvars = cellvars
def setDocstring(self, doc):
self.docstring = doc
def setFlag(self, flag):
self.flags = self.flags | flag
if flag == CO_VARARGS:
self.argcount -= 1
self.flags |= flag
def checkFlag(self, flag):
if self.flags & flag:
return 1
return bool(self.flags & flag)
def MakeCodeObject(self):
"""Assemble a Python code object."""
# NOTE: It would be nice to split this into two representations: graph
# and insts. Maybe VarContext?
stacksize = ComputeStackDepth(self.blocks, self.entry, self.exit)
blocks = OrderBlocks(self.entry, self.exit)
insts = FlattenGraph(blocks)
assert len(self.consts) == 0, self.consts
self.consts.append(self.docstring)
# Rearrange self.cellvars so the ones in self.varnames are first.
# And prune from freevars (?)
# Sort self.cellvars so the ones in self.varnames are first. And prune
# from freevars (?)
lookup = set(self.cellvars)
remaining = lookup - set(self.varnames)
self.cellvars = [n for n in self.varnames if n in lookup]
self.cellvars.extend(remaining)
cellvars = [n for n in self.varnames if n in lookup]
cellvars.extend(remaining)
consts = [self.docstring]
names = []
self.closure = self.cellvars + self.freevars
# The closure list is used to track the order of cell variables and
# free variables in the resulting code object. The offsets used by
# LOAD_CLOSURE/LOAD_DEREF refer to both kinds of variables.
closure = self.cellvars + self.freevars
# Convert arguments from symbolic to concrete form
# Mutates the insts argument. The converters mutate self.names,
# self.varnames, etc.
enc = ArgEncoder(self.klass, self.consts, self.names, self.varnames,
self.closure)
enc = ArgEncoder(self.klass, consts, names, self.varnames, closure)
for i, t in enumerate(insts):
if len(t) == 2:
@@ -434,20 +414,22 @@ def MakeCodeObject(self):
if self.flags & CO_VARKEYWORDS:
self.argcount -= 1
if self.flags & CO_VARARGS:
self.argcount -= 1
a = Assembler()
bytecode, firstline, lnotab = a.Run(insts)
return types.CodeType(
self.argcount, nlocals, stacksize, self.flags,
bytecode,
tuple(self.consts),
tuple(self.names),
tuple(consts),
tuple(names),
tuple(self.varnames),
self.filename, self.name, firstline,
lnotab,
tuple(self.freevars),
tuple(self.cellvars))
tuple(cellvars))
class ArgEncoder(object):
@@ -141,8 +141,8 @@ def Finish(self):
raise NotImplementedError
def Start(self):
self.graph.setFreeVars(self.scope.get_free_vars())
self.graph.setCellVars(self.scope.get_cell_vars())
self.graph.setVars(self.scope.get_free_vars(),
self.scope.get_cell_vars())
self._Start()
def mangle(self, name):
View
@@ -107,7 +107,7 @@ def get_free_vars(self):
# return Adder
"""
if not self.nested:
return ()
return []
free = set()
free.update(self.frees)
for name in self.uses:

0 comments on commit 9c47ae3

Please sign in to comment.