Home | History | Annotate | Download | only in Compiler
      1 from Symtab import ModuleScope
      2 from PyrexTypes import *
      3 from UtilityCode import CythonUtilityCode
      4 from Errors import error
      5 from Scanning import StringSourceDescriptor
      6 import MemoryView
      7 
      8 class CythonScope(ModuleScope):
      9     is_cython_builtin = 1
     10     _cythonscope_initialized = False
     11 
     12     def __init__(self, context):
     13         ModuleScope.__init__(self, u'cython', None, None)
     14         self.pxd_file_loaded = True
     15         self.populate_cython_scope()
     16         # The Main.Context object
     17         self.context = context
     18 
     19         for fused_type in (cy_integral_type, cy_floating_type, cy_numeric_type):
     20             entry = self.declare_typedef(fused_type.name,
     21                                          fused_type,
     22                                          None,
     23                                          cname='<error>')
     24             entry.in_cinclude = True
     25 
     26     def lookup_type(self, name):
     27         # This function should go away when types are all first-level objects.
     28         type = parse_basic_type(name)
     29         if type:
     30             return type
     31 
     32         return super(CythonScope, self).lookup_type(name)
     33 
     34     def lookup(self, name):
     35         entry = super(CythonScope, self).lookup(name)
     36 
     37         if entry is None and not self._cythonscope_initialized:
     38             self.load_cythonscope()
     39             entry = super(CythonScope, self).lookup(name)
     40 
     41         return entry
     42 
     43     def find_module(self, module_name, pos):
     44         error("cython.%s is not available" % module_name, pos)
     45 
     46     def find_submodule(self, module_name):
     47         entry = self.entries.get(module_name, None)
     48         if not entry:
     49             self.load_cythonscope()
     50             entry = self.entries.get(module_name, None)
     51 
     52         if entry and entry.as_module:
     53             return entry.as_module
     54         else:
     55             # TODO: fix find_submodule control flow so that we're not
     56             # expected to create a submodule here (to protect CythonScope's
     57             # possible immutability). Hack ourselves out of the situation
     58             # for now.
     59             raise error((StringSourceDescriptor(u"cython", u""), 0, 0),
     60                   "cython.%s is not available" % module_name)
     61 
     62     def lookup_qualified_name(self, qname):
     63         # ExprNode.as_cython_attribute generates qnames and we untangle it here...
     64         name_path = qname.split(u'.')
     65         scope = self
     66         while len(name_path) > 1:
     67             scope = scope.lookup_here(name_path[0]).as_module
     68             del name_path[0]
     69             if scope is None:
     70                 return None
     71         else:
     72             return scope.lookup_here(name_path[0])
     73 
     74     def populate_cython_scope(self):
     75         # These are used to optimize isinstance in FinalOptimizePhase
     76         type_object = self.declare_typedef(
     77             'PyTypeObject',
     78             base_type = c_void_type,
     79             pos = None,
     80             cname = 'PyTypeObject')
     81         type_object.is_void = True
     82         type_object_type = type_object.type
     83 
     84         self.declare_cfunction(
     85             'PyObject_TypeCheck',
     86             CFuncType(c_bint_type, [CFuncTypeArg("o", py_object_type, None),
     87                                     CFuncTypeArg("t", c_ptr_type(type_object_type), None)]),
     88             pos = None,
     89             defining = 1,
     90             cname = 'PyObject_TypeCheck')
     91 
     92     def load_cythonscope(self):
     93         """
     94         Creates some entries for testing purposes and entries for
     95         cython.array() and for cython.view.*.
     96         """
     97         if self._cythonscope_initialized:
     98             return
     99 
    100         self._cythonscope_initialized = True
    101         cython_testscope_utility_code.declare_in_scope(
    102                                 self, cython_scope=self)
    103         cython_test_extclass_utility_code.declare_in_scope(
    104                                     self, cython_scope=self)
    105 
    106         #
    107         # The view sub-scope
    108         #
    109         self.viewscope = viewscope = ModuleScope(u'view', self, None)
    110         self.declare_module('view', viewscope, None).as_module = viewscope
    111         viewscope.is_cython_builtin = True
    112         viewscope.pxd_file_loaded = True
    113 
    114         cythonview_testscope_utility_code.declare_in_scope(
    115                                             viewscope, cython_scope=self)
    116 
    117         view_utility_scope = MemoryView.view_utility_code.declare_in_scope(
    118                                             self.viewscope, cython_scope=self,
    119                                             whitelist=MemoryView.view_utility_whitelist)
    120 
    121         # self.entries["array"] = view_utility_scope.entries.pop("array")
    122 
    123 
    124 def create_cython_scope(context):
    125     # One could in fact probably make it a singleton,
    126     # but not sure yet whether any code mutates it (which would kill reusing
    127     # it across different contexts)
    128     return CythonScope(context)
    129 
    130 # Load test utilities for the cython scope
    131 
    132 def load_testscope_utility(cy_util_name, **kwargs):
    133     return CythonUtilityCode.load(cy_util_name, "TestCythonScope.pyx", **kwargs)
    134 
    135 
    136 undecorated_methods_protos = UtilityCode(proto=u"""
    137     /* These methods are undecorated and have therefore no prototype */
    138     static PyObject *__pyx_TestClass_cdef_method(
    139             struct __pyx_TestClass_obj *self, int value);
    140     static PyObject *__pyx_TestClass_cpdef_method(
    141             struct __pyx_TestClass_obj *self, int value, int skip_dispatch);
    142     static PyObject *__pyx_TestClass_def_method(
    143             PyObject *self, PyObject *value);
    144 """)
    145 
    146 cython_testscope_utility_code = load_testscope_utility("TestScope")
    147 
    148 test_cython_utility_dep = load_testscope_utility("TestDep")
    149 
    150 cython_test_extclass_utility_code = \
    151     load_testscope_utility("TestClass", name="TestClass",
    152                            requires=[undecorated_methods_protos,
    153                                      test_cython_utility_dep])
    154 
    155 cythonview_testscope_utility_code = load_testscope_utility("View.TestScope")
    156