Commit 4e19bc79 authored by Dag Sverre Seljebotn's avatar Dag Sverre Seljebotn Committed by Mark Florisson

Refactor the 'cython' cimport scope to use CythonUtilityCode

parent f4e4484f
from Symtab import ModuleScope
from PyrexTypes import *
shape_func_type = CFuncType(
c_ptr_type(c_py_ssize_t_type),
[CFuncTypeArg("buffer", py_object_type, None)])
from UtilityCode import CythonUtilityCode
class CythonScope(ModuleScope):
def __init__(self, context):
ModuleScope.__init__(self, u'cython', None, context)
def __init__(self):
ModuleScope.__init__(self, u'cython', None, None)
self.pxd_file_loaded = True
self.shape_entry = self.declare_cfunction('shape',
shape_func_type,
pos=None,
defining = 1,
cname='<error>')
self.populate_cython_scope()
def lookup_type(self, name):
# This function should go away when types are all first-level objects.
......@@ -22,28 +14,47 @@ class CythonScope(ModuleScope):
if type:
return type
def create_cython_scope(context):
create_utility_scope(context)
return CythonScope(context)
def find_module(self, module_name, pos):
error("cython.%s is not available" % module_name)
def populate_cython_scope(self):
# These are used to optimize isinstance in FinalOptimizePhase
type_object = self.declare_typedef(
'PyTypeObject',
base_type = c_void_type,
pos = None,
cname = 'PyTypeObject')
type_object.is_void = True
self.declare_cfunction(
'PyObject_TypeCheck',
CFuncType(c_bint_type, [CFuncTypeArg("o", py_object_type, None),
CFuncTypeArg("t", c_ptr_type(type_object), None)]),
pos = None,
defining = 1,
cname = 'PyObject_TypeCheck')
#
# A special function just to make it easy to test the scope and
# utility code functionality in isolation. It is available to
# "end-users" but nobody will know it is there anyway...
#
testcythonscope = self.declare_cfunction(
'_testcythonscope',
CFuncType(py_object_type, [CFuncTypeArg("value", c_int_type, None)]),
pos=None,
defining=1,
cname='__pyx_cython__testcythonscope'
)
testcythonscope.utility_code_definition = cython_testscope_utility_code
def create_utility_scope(context):
global utility_scope
utility_scope = ModuleScope(u'utility', None, context)
# These are used to optimize isinstance in FinalOptimizePhase
type_object = utility_scope.declare_typedef('PyTypeObject',
base_type = c_void_type,
pos = None,
cname = 'PyTypeObject')
type_object.is_void = True
utility_scope.declare_cfunction(
'PyObject_TypeCheck',
CFuncType(c_bint_type, [CFuncTypeArg("o", py_object_type, None),
CFuncTypeArg("t", c_ptr_type(type_object), None)]),
pos = None,
defining = 1,
cname = 'PyObject_TypeCheck')
return utility_scope
def create_cython_scope(context):
# One could in fact probably make it a singleton,
# but not sure yet whether any code mutates it (which would kill reusing
# it across different contexts)
return CythonScope()
cython_testscope_utility_code = CythonUtilityCode(u"""
cdef object _testcythonscope(int value):
return "hello value=%d" % value
""", name="cython utility code", prefix="__pyx_cython_")
......@@ -28,7 +28,6 @@ from Errors import PyrexError, CompileError, InternalError, AbortError, error, w
from Symtab import BuiltinScope, ModuleScope
from Cython import Utils
from Cython.Utils import open_new_file, replace_suffix
import CythonScope
import DebugFlags
import Options
......@@ -62,10 +61,16 @@ class Context(object):
# future_directives [object]
# language_level int currently 2 or 3 for Python 2/3
cython_scope = None
def __init__(self, include_directories, compiler_directives, cpp=False, language_level=2, options=None):
# cython_scope is a hack, set to False by subclasses, in order to break
# an infinite loop.
# Better code organization would fix it.
import Builtin, CythonScope
self.modules = {"__builtin__" : Builtin.builtin_scope}
self.modules["cython"] = CythonScope.create_cython_scope(self)
self.modules["cython"] = self.cython_scope = CythonScope.create_cython_scope(self)
self.include_directories = include_directories
self.future_directives = set()
self.compiler_directives = compiler_directives
......
......@@ -3443,10 +3443,10 @@ class FinalOptimizePhase(Visitor.CythonTransform):
if node.function.name == 'isinstance':
type_arg = node.args[1]
if type_arg.type.is_builtin_type and type_arg.type.name == 'type':
from CythonScope import utility_scope
node.function.entry = utility_scope.lookup('PyObject_TypeCheck')
cython_scope = self.context.cython_scope
node.function.entry = cython_scope.lookup('PyObject_TypeCheck')
node.function.type = node.function.entry.type
PyTypeObjectPtr = PyrexTypes.CPtrType(utility_scope.lookup('PyTypeObject').type)
PyTypeObjectPtr = PyrexTypes.CPtrType(cython_scope.lookup('PyTypeObject').type)
node.args[1] = ExprNodes.CastNode(node.args[1], PyTypeObjectPtr)
return node
......
import cython
cython.declare(PyrexTypes=object, Naming=object, ExprNodes=object, Nodes=object,
Options=object, UtilNodes=object, ModuleNode=object,
......@@ -2192,7 +2191,11 @@ class TransformBuiltinMethods(EnvTransform):
elif attribute in (u'set', u'frozenset'):
node = ExprNodes.NameNode(node.pos, name=EncodedString(attribute),
entry=self.current_env().builtin_scope().lookup_here(attribute))
elif not PyrexTypes.parse_basic_type(attribute):
elif PyrexTypes.parse_basic_type(attribute):
pass
elif self.context.cython_scope.lookup(attribute):
pass
else:
error(node.pos, u"'%s' not a valid cython attribute or is being used incorrectly" % attribute)
return node
......@@ -2282,7 +2285,12 @@ class TransformBuiltinMethods(EnvTransform):
elif function == u'set':
node.function = ExprNodes.NameNode(node.pos, name=EncodedString('set'))
else:
error(node.function.pos, u"'%s' not a valid cython language construct" % function)
entry = self.context.cython_scope.lookup(function)
if entry and entry.utility_code_definition:
self.env_stack[0].use_utility_code(entry.utility_code_definition)
if not entry:
error(node.function.pos,
u"'%s' not a valid cython language construct" % function)
self.visitchildren(node)
return node
......
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