[pypy-svn] r16558 - pypy/dist/pypy/lib/_stablecompiler
hpk at codespeak.net
hpk at codespeak.net
Thu Aug 25 22:18:06 CEST 2005
Author: hpk
Date: Thu Aug 25 22:18:06 2005
New Revision: 16558
Modified:
pypy/dist/pypy/lib/_stablecompiler/consts.py
pypy/dist/pypy/lib/_stablecompiler/pyassem.py
pypy/dist/pypy/lib/_stablecompiler/pycodegen.py
pypy/dist/pypy/lib/_stablecompiler/symbols.py
pypy/dist/pypy/lib/_stablecompiler/transformer.py
Log:
merge of pypy/interpreter/stablecompiler changes
to pypy/lib/_stablecompiler with
svn merge -r 15452:16555 http://codespeak.net/svn/pypy/dist/pypy/interpreter/stablecompiler
while being in the _stablecompiler directory.
resolved conflicts that were mostly related to the
trailing import sections.
Modified: pypy/dist/pypy/lib/_stablecompiler/consts.py
==============================================================================
--- pypy/dist/pypy/lib/_stablecompiler/consts.py (original)
+++ pypy/dist/pypy/lib/_stablecompiler/consts.py Thu Aug 25 22:18:06 2005
@@ -8,6 +8,7 @@
SC_FREE = 3
SC_CELL = 4
SC_UNKNOWN = 5
+SC_DEFAULT = 6
CO_OPTIMIZED = 0x0001
CO_NEWLOCALS = 0x0002
Modified: pypy/dist/pypy/lib/_stablecompiler/pyassem.py
==============================================================================
--- pypy/dist/pypy/lib/_stablecompiler/pyassem.py (original)
+++ pypy/dist/pypy/lib/_stablecompiler/pyassem.py Thu Aug 25 22:18:06 2005
@@ -316,7 +316,8 @@
class PyFlowGraph(FlowGraph):
super_init = FlowGraph.__init__
- def __init__(self, name, filename, args=(), optimized=0, klass=None):
+ def __init__(self, name, filename, args=(), optimized=0,
+ klass=None, newlocals=0):
self.super_init()
self.name = name
self.filename = filename
@@ -324,10 +325,11 @@
self.args = args # XXX
self.argcount = getArgCount(args)
self.klass = klass
+ self.flags = 0
if optimized:
- self.flags = CO_OPTIMIZED | CO_NEWLOCALS
- else:
- self.flags = 0
+ self.flags |= CO_OPTIMIZED
+ if newlocals:
+ self.flags |= CO_NEWLOCALS
self.consts = []
self.names = []
# Free variables found by the symbol table scan, including
Modified: pypy/dist/pypy/lib/_stablecompiler/pycodegen.py
==============================================================================
--- pypy/dist/pypy/lib/_stablecompiler/pycodegen.py (original)
+++ pypy/dist/pypy/lib/_stablecompiler/pycodegen.py Thu Aug 25 22:18:06 2005
@@ -10,7 +10,7 @@
from transformer import parse
from visitor import walk
import pyassem, misc, future, symbols
-from consts import SC_LOCAL, SC_GLOBAL, SC_FREE, SC_CELL
+from consts import SC_LOCAL, SC_GLOBAL, SC_FREE, SC_CELL, SC_DEFAULT
from consts import CO_VARARGS, CO_VARKEYWORDS, \
CO_NEWLOCALS, CO_NESTED, CO_GENERATOR, CO_GENERATOR_ALLOWED, CO_FUTURE_DIVISION
from pyassem import TupleArg
@@ -195,6 +195,9 @@
defined.
"""
+ scopeambiguity = False
+ parentscopeambiguity = False
+
optimized = 0 # is namespace access optimized?
__initialized = None
class_name = None # provide default for instance variable
@@ -267,9 +270,18 @@
self._nameOp('STORE', name)
def loadName(self, name):
+ if (self.scope.nested and self.scopeambiguity and
+ name in self.scope.hasbeenfree):
+ raise SyntaxError("cannot reference variable '%s' because "
+ "of ambiguity between "
+ "scopes" % name)
self._nameOp('LOAD', name)
def delName(self, name):
+ scope = self.scope.check_name(name)
+ if scope == SC_CELL:
+ raise SyntaxError("can not delete variable '%s' "
+ "referenced in nested scope" % name)
self._nameOp('DELETE', name)
def _nameOp(self, prefix, name):
@@ -281,12 +293,14 @@
else:
self.emit(prefix + '_FAST', name)
elif scope == SC_GLOBAL:
- if not self.optimized:
- self.emit(prefix + '_NAME', name)
- else:
- self.emit(prefix + '_GLOBAL', name)
+ self.emit(prefix + '_GLOBAL', name)
elif scope == SC_FREE or scope == SC_CELL:
self.emit(prefix + '_DEREF', name)
+ elif scope == SC_DEFAULT:
+ if self.optimized and self.localsfullyknown:
+ self.emit(prefix + '_GLOBAL', name)
+ else:
+ self.emit(prefix + '_NAME', name)
else:
raise RuntimeError, "unsupported scope for var %s: %d" % \
(name, scope)
@@ -376,7 +390,8 @@
ndecorators = 0
gen = self.FunctionGen(node, self.scopes, isLambda,
- self.class_name, self.get_module())
+ self.class_name, self.get_module(),
+ parentscopeambiguity = self.scopeambiguity or self.parentscopeambiguity)
walk(node.code, gen)
gen.finish()
self.set_lineno(node)
@@ -397,7 +412,8 @@
def visitClass(self, node):
gen = self.ClassGen(node, self.scopes,
- self.get_module())
+ self.get_module(),
+ parentscopeambiguity = self.scopeambiguity or self.parentscopeambiguity)
walk(node.code, gen)
gen.finish()
self.set_lineno(node)
@@ -631,7 +647,8 @@
def visitGenExpr(self, node):
gen = GenExprCodeGenerator(node, self.scopes, self.class_name,
- self.get_module())
+ self.get_module(),
+ parentscopeambiguity=self.scopeambiguity or self.parentscopeambiguity)
walk(node.code, gen)
gen.finish()
self.set_lineno(node)
@@ -811,6 +828,11 @@
# misc
def visitDiscard(self, node):
+ # Important: this function is overridden in InteractiveCodeGenerator,
+ # which also has the effect that the following test only occurs in
+ # non-'single' modes.
+ if isinstance(node.expr, ast.Const):
+ return # skip LOAD_CONST/POP_TOP pairs (for e.g. docstrings)
self.set_lineno(node)
self.visit(node.expr)
self.emit('POP_TOP')
@@ -1289,7 +1311,8 @@
args, hasTupleArg = generateArgList(func.argnames)
self.graph = pyassem.PyFlowGraph(name, func.filename, args,
- optimized=1)
+ optimized=self.localsfullyknown,
+ newlocals=1)
self.isLambda = isLambda
self.super_init()
@@ -1342,9 +1365,14 @@
__super_init = AbstractFunctionCode.__init__
- def __init__(self, func, scopes, isLambda, class_name, mod):
+ def __init__(self, func, scopes, isLambda, class_name, mod, parentscopeambiguity):
self.scopes = scopes
self.scope = scopes[func]
+
+ self.localsfullyknown = self.scope.localsfullyknown
+ self.parentscopeambiguity = parentscopeambiguity
+ self.scopeambiguity = (not self.localsfullyknown or parentscopeambiguity)
+
self.__super_init(func, scopes, isLambda, class_name, mod)
self.graph.setFreeVars(self.scope.get_free_vars())
self.graph.setCellVars(self.scope.get_cell_vars())
@@ -1358,9 +1386,14 @@
__super_init = AbstractFunctionCode.__init__
- def __init__(self, gexp, scopes, class_name, mod):
+ def __init__(self, gexp, scopes, class_name, mod, parentscopeambiguity):
self.scopes = scopes
self.scope = scopes[gexp]
+
+ self.localsfullyknown = self.scope.localsfullyknown
+ self.parentscopeambiguity = parentscopeambiguity
+ self.scopeambiguity = (not self.localsfullyknown or parentscopeambiguity)
+
self.__super_init(gexp, scopes, 1, class_name, mod)
self.graph.setFreeVars(self.scope.get_free_vars())
self.graph.setCellVars(self.scope.get_cell_vars())
@@ -1394,9 +1427,13 @@
__super_init = AbstractClassCode.__init__
- def __init__(self, klass, scopes, module):
+ def __init__(self, klass, scopes, module, parentscopeambiguity):
self.scopes = scopes
self.scope = scopes[klass]
+
+ self.parentscopeambiguity = parentscopeambiguity
+ self.scopeambiguity = parentscopeambiguity
+
self.__super_init(klass, scopes, module)
self.graph.setFreeVars(self.scope.get_free_vars())
self.graph.setCellVars(self.scope.get_cell_vars())
Modified: pypy/dist/pypy/lib/_stablecompiler/symbols.py
==============================================================================
--- pypy/dist/pypy/lib/_stablecompiler/symbols.py (original)
+++ pypy/dist/pypy/lib/_stablecompiler/symbols.py Thu Aug 25 22:18:06 2005
@@ -1,7 +1,8 @@
"""Module symbol-table generator"""
import ast
-from consts import SC_LOCAL, SC_GLOBAL, SC_FREE, SC_CELL, SC_UNKNOWN
+from consts import SC_LOCAL, SC_GLOBAL, SC_FREE, SC_CELL, \
+ SC_UNKNOWN, SC_DEFAULT
from misc import mangle
import types
@@ -11,6 +12,7 @@
MANGLE_LEN = 256
class Scope:
+ localsfullyknown = True
# XXX how much information do I need about each name?
def __init__(self, name, module, klass=None):
self.name = name
@@ -20,6 +22,7 @@
self.globals = {}
self.params = {}
self.frees = {}
+ self.hasbeenfree = {}
self.cells = {}
self.children = []
# nested is true if the class could contain free variables,
@@ -100,7 +103,7 @@
if self.nested:
return SC_UNKNOWN
else:
- return SC_GLOBAL
+ return SC_DEFAULT
def get_free_vars(self):
if not self.nested:
@@ -111,6 +114,7 @@
if not (self.defs.has_key(name) or
self.globals.has_key(name)):
free[name] = 1
+ self.hasbeenfree.update(free)
return free.keys()
def handle_children(self):
@@ -133,7 +137,8 @@
Be careful to stop if a child does not think the name is
free.
"""
- self.globals[name] = 1
+ if name not in self.defs:
+ self.globals[name] = 1
if self.frees.has_key(name):
del self.frees[name]
for child in self.children:
@@ -237,6 +242,12 @@
self.visit(node.code, scope)
self.handle_free_vars(scope, parent)
+ def visitExec(self, node, parent):
+ if not (node.globals or node.locals):
+ parent.localsfullyknown = False # bare exec statement
+ for child in node.getChildNodes():
+ self.visit(child, parent)
+
def visitGenExpr(self, node, parent):
scope = GenExprScope(self.module, self.klass);
if parent.nested or isinstance(parent, FunctionScope) \
@@ -331,6 +342,7 @@
def visitFrom(self, node, scope):
for name, asname in node.names:
if name == "*":
+ scope.localsfullyknown = False
continue
scope.add_def(asname or name)
Modified: pypy/dist/pypy/lib/_stablecompiler/transformer.py
==============================================================================
--- pypy/dist/pypy/lib/_stablecompiler/transformer.py (original)
+++ pypy/dist/pypy/lib/_stablecompiler/transformer.py Thu Aug 25 22:18:06 2005
@@ -172,24 +172,26 @@
raise WalkerError, ('unexpected node type', n)
def single_input(self, node):
- ### do we want to do anything about being "interactive" ?
# NEWLINE | simple_stmt | compound_stmt NEWLINE
n = node[0][0]
if n != token.NEWLINE:
- return self.com_stmt(node[0])
-
- return Pass()
+ stmt = self.com_stmt(node[0])
+ else:
+ stmt = Pass()
+ return Module(None, stmt)
def file_input(self, nodelist):
doc = self.get_docstring(nodelist, symbol.file_input)
- if doc is not None:
- i = 1
- else:
- i = 0
stmts = []
- for node in nodelist[i:]:
+ for node in nodelist:
if node[0] != token.ENDMARKER and node[0] != token.NEWLINE:
self.com_append_stmt(stmts, node)
+
+ if doc is not None:
+ assert isinstance(stmts[0], Discard)
+ assert isinstance(stmts[0].expr, Const)
+ del stmts[0]
+
return Module(doc, Stmt(stmts))
def eval_input(self, nodelist):
@@ -255,7 +257,8 @@
if args[0] == symbol.varargslist:
names, defaults, flags = self.com_arglist(args[1:])
else:
- names = defaults = ()
+ names = []
+ defaults = []
flags = 0
doc = self.get_docstring(nodelist[-1])
@@ -704,7 +707,7 @@
def atom_lsqb(self, nodelist):
if nodelist[1][0] == token.RSQB:
- return List(())
+ return List([])
return self.com_list_constructor(nodelist[1])
def atom_lbrace(self, nodelist):
@@ -929,6 +932,7 @@
l = self.com_node(node)
if l.__class__ in (Name, Slice, Subscript, Getattr):
return l
+ print node # XXX
raise SyntaxError, "can't assign to %s" % l.__class__.__name__
def com_assign(self, node, assigning):
More information about the Pypy-commit
mailing list