Commit f3daed10 authored by Robert Bradshaw's avatar Robert Bradshaw

Refine analysis of undeclared symbols in cython.inline.

Previously cython.inline didn't correctly handle variables
declared in nested scopes (such as function declarations).
parent 80638c1a
...@@ -12,10 +12,11 @@ from distutils.command.build_ext import build_ext ...@@ -12,10 +12,11 @@ from distutils.command.build_ext import build_ext
import Cython import Cython
from Cython.Compiler.Main import Context, CompilationOptions, default_options from Cython.Compiler.Main import Context, CompilationOptions, default_options
from Cython.Compiler.ParseTreeTransforms import CythonTransform, SkipDeclarations, AnalyseDeclarationsTransform from Cython.Compiler.ParseTreeTransforms import (CythonTransform,
SkipDeclarations, AnalyseDeclarationsTransform, EnvTransform)
from Cython.Compiler.TreeFragment import parse_from_strings from Cython.Compiler.TreeFragment import parse_from_strings
from Cython.Build.Dependencies import strip_string_literals, cythonize, cached_function from Cython.Build.Dependencies import strip_string_literals, cythonize, cached_function
from Cython.Compiler import Pipeline from Cython.Compiler import Pipeline, Nodes
from Cython.Utils import get_cython_cache_dir from Cython.Utils import get_cython_cache_dir
import cython as cython_module import cython as cython_module
...@@ -30,12 +31,17 @@ else: ...@@ -30,12 +31,17 @@ else:
to_unicode = lambda x: x to_unicode = lambda x: x
class AllSymbols(CythonTransform, SkipDeclarations): class UnboundSymbols(EnvTransform, SkipDeclarations):
def __init__(self): def __init__(self):
CythonTransform.__init__(self, None) CythonTransform.__init__(self, None)
self.names = set() self.unbound = set()
def visit_NameNode(self, node): def visit_NameNode(self, node):
self.names.add(node.name) if not self.current_env().lookup(node.name):
self.unbound.add(node.name)
return node
def __call__(self, node):
super(UnboundSymbols, self).__call__(node)
return self.unbound
@cached_function @cached_function
def unbound_symbols(code, context=None): def unbound_symbols(code, context=None):
...@@ -50,17 +56,11 @@ def unbound_symbols(code, context=None): ...@@ -50,17 +56,11 @@ def unbound_symbols(code, context=None):
tree = phase(tree) tree = phase(tree)
if isinstance(phase, AnalyseDeclarationsTransform): if isinstance(phase, AnalyseDeclarationsTransform):
break break
symbol_collector = AllSymbols()
symbol_collector(tree)
unbound = []
try: try:
import builtins import builtins
except ImportError: except ImportError:
import __builtin__ as builtins import __builtin__ as builtins
for name in symbol_collector.names: return UnboundSymbols()(tree) - set(dir(builtins))
if not tree.scope.lookup(name) and not hasattr(builtins, name):
unbound.append(name)
return unbound
def unsafe_type(arg, context=None): def unsafe_type(arg, context=None):
py_type = type(arg) py_type = type(arg)
......
...@@ -47,6 +47,10 @@ class TestInline(CythonTest): ...@@ -47,6 +47,10 @@ class TestInline(CythonTest):
cdef c = [] cdef c = []
"""), dict(a=1, b=2.0, c=[])) """), dict(a=1, b=2.0, c=[]))
def test_def_node(self):
foo = inline("def foo(x): return x * x")['foo']
self.assertEquals(foo(7), 49)
def test_pure(self): def test_pure(self):
import cython as cy import cython as cy
b = inline(""" b = inline("""
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment