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