Home | History | Annotate | Download | only in Compiler
      1 #
      2 #   Builtin Definitions
      3 #
      4 
      5 from Symtab import BuiltinScope, StructOrUnionScope
      6 from Code import UtilityCode
      7 from TypeSlots import Signature
      8 import PyrexTypes
      9 import Options
     10 
     11 
     12 # C-level implementations of builtin types, functions and methods
     13 
     14 iter_next_utility_code = UtilityCode.load("IterNext", "ObjectHandling.c")
     15 getattr_utility_code = UtilityCode.load("GetAttr", "ObjectHandling.c")
     16 getattr3_utility_code = UtilityCode.load("GetAttr3", "Builtins.c")
     17 pyexec_utility_code = UtilityCode.load("PyExec", "Builtins.c")
     18 pyexec_globals_utility_code = UtilityCode.load("PyExecGlobals", "Builtins.c")
     19 globals_utility_code = UtilityCode.load("Globals", "Builtins.c")
     20 
     21 py_set_utility_code = UtilityCode.load("pyset_compat", "Builtins.c")
     22 
     23 builtin_utility_code = {
     24     'set'       : py_set_utility_code,
     25     'frozenset' : py_set_utility_code,
     26 }
     27 
     28 
     29 # mapping from builtins to their C-level equivalents
     30 
     31 class _BuiltinOverride(object):
     32     def __init__(self, py_name, args, ret_type, cname, py_equiv="*",
     33                  utility_code=None, sig=None, func_type=None,
     34                  is_strict_signature=False, builtin_return_type=None):
     35         self.py_name, self.cname, self.py_equiv = py_name, cname, py_equiv
     36         self.args, self.ret_type = args, ret_type
     37         self.func_type, self.sig = func_type, sig
     38         self.builtin_return_type = builtin_return_type
     39         self.is_strict_signature = is_strict_signature
     40         self.utility_code = utility_code
     41 
     42     def build_func_type(self, sig=None, self_arg=None):
     43         if sig is None:
     44             sig = Signature(self.args, self.ret_type)
     45             sig.exception_check = False  # not needed for the current builtins
     46         func_type = sig.function_type(self_arg)
     47         if self.is_strict_signature:
     48             func_type.is_strict_signature = True
     49         if self.builtin_return_type:
     50             func_type.return_type = builtin_types[self.builtin_return_type]
     51         return func_type
     52 
     53 
     54 class BuiltinAttribute(object):
     55     def __init__(self, py_name, cname=None, field_type=None, field_type_name=None):
     56         self.py_name = py_name
     57         self.cname = cname or py_name
     58         self.field_type_name = field_type_name # can't do the lookup before the type is declared!
     59         self.field_type = field_type
     60 
     61     def declare_in_type(self, self_type):
     62         if self.field_type_name is not None:
     63             # lazy type lookup
     64             field_type = builtin_scope.lookup(self.field_type_name).type
     65         else:
     66             field_type = self.field_type or PyrexTypes.py_object_type
     67         entry = self_type.scope.declare(self.py_name, self.cname, field_type, None, 'private')
     68         entry.is_variable = True
     69 
     70 
     71 class BuiltinFunction(_BuiltinOverride):
     72     def declare_in_scope(self, scope):
     73         func_type, sig = self.func_type, self.sig
     74         if func_type is None:
     75             func_type = self.build_func_type(sig)
     76         scope.declare_builtin_cfunction(self.py_name, func_type, self.cname,
     77                                         self.py_equiv, self.utility_code)
     78 
     79 
     80 class BuiltinMethod(_BuiltinOverride):
     81     def declare_in_type(self, self_type):
     82         method_type, sig = self.func_type, self.sig
     83         if method_type is None:
     84             # override 'self' type (first argument)
     85             self_arg = PyrexTypes.CFuncTypeArg("", self_type, None)
     86             self_arg.not_none = True
     87             self_arg.accept_builtin_subtypes = True
     88             method_type = self.build_func_type(sig, self_arg)
     89         self_type.scope.declare_builtin_cfunction(
     90             self.py_name, method_type, self.cname, utility_code=self.utility_code)
     91 
     92 
     93 builtin_function_table = [
     94     # name,        args,   return,  C API func,           py equiv = "*"
     95     BuiltinFunction('abs',        "d",    "d",     "fabs",
     96                     is_strict_signature = True),
     97     BuiltinFunction('abs',        "f",    "f",     "fabsf",
     98                     is_strict_signature = True),
     99     BuiltinFunction('abs',        None,    None,   "__Pyx_abs_int",
    100                     utility_code = UtilityCode.load("abs_int", "Builtins.c"),
    101                     func_type = PyrexTypes.CFuncType(
    102                         PyrexTypes.c_uint_type, [
    103                             PyrexTypes.CFuncTypeArg("arg", PyrexTypes.c_int_type, None)
    104                             ],
    105                         is_strict_signature = True)),
    106     BuiltinFunction('abs',        None,    None,   "__Pyx_abs_long",
    107                     utility_code = UtilityCode.load("abs_long", "Builtins.c"),
    108                     func_type = PyrexTypes.CFuncType(
    109                         PyrexTypes.c_ulong_type, [
    110                             PyrexTypes.CFuncTypeArg("arg", PyrexTypes.c_long_type, None)
    111                             ],
    112                         is_strict_signature = True)),
    113     BuiltinFunction('abs',        None,    None,   "__Pyx_abs_longlong",
    114                     utility_code = UtilityCode.load("abs_longlong", "Builtins.c"),
    115                     func_type = PyrexTypes.CFuncType(
    116                         PyrexTypes.c_ulonglong_type, [
    117                             PyrexTypes.CFuncTypeArg("arg", PyrexTypes.c_longlong_type, None)
    118                         ],
    119                         is_strict_signature = True)),
    120     BuiltinFunction('abs',        "O",    "O",     "PyNumber_Absolute"),
    121     BuiltinFunction('callable',   "O",    "b",     "__Pyx_PyCallable_Check",
    122                     utility_code = UtilityCode.load("CallableCheck", "ObjectHandling.c")),
    123     #('chr',       "",     "",      ""),
    124     #('cmp', "",   "",     "",      ""), # int PyObject_Cmp(PyObject *o1, PyObject *o2, int *result)
    125     #('compile',   "",     "",      ""), # PyObject* Py_CompileString(    char *str, char *filename, int start)
    126     BuiltinFunction('delattr',    "OO",   "r",     "PyObject_DelAttr"),
    127     BuiltinFunction('dir',        "O",    "O",     "PyObject_Dir"),
    128     BuiltinFunction('divmod',     "OO",   "O",     "PyNumber_Divmod"),
    129     BuiltinFunction('exec',       "O",    "O",     "__Pyx_PyExecGlobals",
    130                     utility_code = pyexec_globals_utility_code),
    131     BuiltinFunction('exec',       "OO",   "O",     "__Pyx_PyExec2",
    132                     utility_code = pyexec_utility_code),
    133     BuiltinFunction('exec',       "OOO",  "O",     "__Pyx_PyExec3",
    134                     utility_code = pyexec_utility_code),
    135     #('eval',      "",     "",      ""),
    136     #('execfile',  "",     "",      ""),
    137     #('filter',    "",     "",      ""),
    138     BuiltinFunction('getattr3',   "OOO",  "O",     "__Pyx_GetAttr3",     "getattr",
    139                     utility_code=getattr3_utility_code),  # Pyrex legacy
    140     BuiltinFunction('getattr',    "OOO",  "O",     "__Pyx_GetAttr3",
    141                     utility_code=getattr3_utility_code),
    142     BuiltinFunction('getattr',    "OO",   "O",     "__Pyx_GetAttr",
    143                     utility_code=getattr_utility_code),
    144     BuiltinFunction('hasattr',    "OO",   "b",     "PyObject_HasAttr"),
    145     BuiltinFunction('hash',       "O",    "h",     "PyObject_Hash"),
    146     #('hex',       "",     "",      ""),
    147     #('id',        "",     "",      ""),
    148     #('input',     "",     "",      ""),
    149     BuiltinFunction('intern',     "O",    "O",     "__Pyx_Intern",
    150                     utility_code = UtilityCode.load("Intern", "Builtins.c")),
    151     BuiltinFunction('isinstance', "OO",   "b",     "PyObject_IsInstance"),
    152     BuiltinFunction('issubclass', "OO",   "b",     "PyObject_IsSubclass"),
    153     BuiltinFunction('iter',       "OO",   "O",     "PyCallIter_New"),
    154     BuiltinFunction('iter',       "O",    "O",     "PyObject_GetIter"),
    155     BuiltinFunction('len',        "O",    "z",     "PyObject_Length"),
    156     BuiltinFunction('locals',     "",     "O",     "__pyx_locals"),
    157     #('map',       "",     "",      ""),
    158     #('max',       "",     "",      ""),
    159     #('min',       "",     "",      ""),
    160     BuiltinFunction('next',       "O",    "O",     "__Pyx_PyIter_Next",
    161                     utility_code = iter_next_utility_code),   # not available in Py2 => implemented here
    162     BuiltinFunction('next',      "OO",    "O",     "__Pyx_PyIter_Next2",
    163                     utility_code = iter_next_utility_code),  # not available in Py2 => implemented here
    164     #('oct',       "",     "",      ""),
    165     #('open',       "ss",   "O",     "PyFile_FromString"),   # not in Py3
    166     #('ord',       "",     "",      ""),
    167     BuiltinFunction('pow',        "OOO",  "O",     "PyNumber_Power"),
    168     BuiltinFunction('pow',        "OO",   "O",     "__Pyx_PyNumber_Power2",
    169                     utility_code = UtilityCode.load("pow2", "Builtins.c")),
    170     #('range',     "",     "",      ""),
    171     #('raw_input', "",     "",      ""),
    172     #('reduce',    "",     "",      ""),
    173     BuiltinFunction('reload',     "O",    "O",     "PyImport_ReloadModule"),
    174     BuiltinFunction('repr',       "O",    "O",     "PyObject_Repr", builtin_return_type='str'),
    175     #('round',     "",     "",      ""),
    176     BuiltinFunction('setattr',    "OOO",  "r",     "PyObject_SetAttr"),
    177     #('sum',       "",     "",      ""),
    178     #('type',       "O",    "O",     "PyObject_Type"),
    179     #('unichr',    "",     "",      ""),
    180     #('unicode',   "",     "",      ""),
    181     #('vars',      "",     "",      ""),
    182     #('zip',       "",     "",      ""),
    183     #  Can't do these easily until we have builtin type entries.
    184     #('typecheck',  "OO",   "i",     "PyObject_TypeCheck", False),
    185     #('issubtype',  "OO",   "i",     "PyType_IsSubtype",   False),
    186 
    187     # Put in namespace append optimization.
    188     BuiltinFunction('__Pyx_PyObject_Append', "OO",  "O",     "__Pyx_PyObject_Append"),
    189 ]
    190 
    191 if not Options.old_style_globals:
    192     builtin_function_table.append(
    193         BuiltinFunction('globals',    "",     "O",     "__Pyx_Globals",
    194                         utility_code=globals_utility_code))
    195 
    196 # Builtin types
    197 #  bool
    198 #  buffer
    199 #  classmethod
    200 #  dict
    201 #  enumerate
    202 #  file
    203 #  float
    204 #  int
    205 #  list
    206 #  long
    207 #  object
    208 #  property
    209 #  slice
    210 #  staticmethod
    211 #  super
    212 #  str
    213 #  tuple
    214 #  type
    215 #  xrange
    216 
    217 builtin_types_table = [
    218 
    219     ("type",    "PyType_Type",     []),
    220 
    221 # This conflicts with the C++ bool type, and unfortunately
    222 # C++ is too liberal about PyObject* <-> bool conversions,
    223 # resulting in unintuitive runtime behavior and segfaults.
    224 #    ("bool",    "PyBool_Type",     []),
    225 
    226     ("int",     "PyInt_Type",      []),
    227     ("long",    "PyLong_Type",     []),
    228     ("float",   "PyFloat_Type",    []),
    229 
    230     ("complex", "PyComplex_Type",  [BuiltinAttribute('cval', field_type_name = 'Py_complex'),
    231                                     BuiltinAttribute('real', 'cval.real', field_type = PyrexTypes.c_double_type),
    232                                     BuiltinAttribute('imag', 'cval.imag', field_type = PyrexTypes.c_double_type),
    233                                     ]),
    234 
    235     ("basestring", "PyBaseString_Type", [
    236                                     BuiltinMethod("join",  "TO",   "T", "__Pyx_PyBaseString_Join",
    237                                                   utility_code=UtilityCode.load("StringJoin", "StringTools.c")),
    238                                     ]),
    239     ("bytearray", "PyByteArray_Type", [
    240                                     ]),
    241     ("bytes",   "PyBytes_Type",    [BuiltinMethod("__contains__",  "TO",   "b", "PySequence_Contains"),
    242                                     BuiltinMethod("join",  "TO",   "O", "__Pyx_PyBytes_Join",
    243                                                   utility_code=UtilityCode.load("StringJoin", "StringTools.c")),
    244                                     ]),
    245     ("str",     "PyString_Type",   [BuiltinMethod("__contains__",  "TO",   "b", "PySequence_Contains"),
    246                                     BuiltinMethod("join",  "TO",   "O", "__Pyx_PyString_Join",
    247                                                   builtin_return_type='basestring',
    248                                                   utility_code=UtilityCode.load("StringJoin", "StringTools.c")),
    249                                     ]),
    250     ("unicode", "PyUnicode_Type",  [BuiltinMethod("__contains__",  "TO",   "b", "PyUnicode_Contains"),
    251                                     BuiltinMethod("join",  "TO",   "T", "PyUnicode_Join"),
    252                                     ]),
    253 
    254     ("tuple",   "PyTuple_Type",    [BuiltinMethod("__contains__",  "TO",   "b", "PySequence_Contains"),
    255                                     ]),
    256 
    257     ("list",    "PyList_Type",     [BuiltinMethod("__contains__",  "TO",   "b", "PySequence_Contains"),
    258                                     BuiltinMethod("insert",  "TzO",  "r", "PyList_Insert"),
    259                                     BuiltinMethod("reverse", "T",    "r", "PyList_Reverse"),
    260                                     BuiltinMethod("append",  "TO",   "r", "__Pyx_PyList_Append",
    261                                                   utility_code=UtilityCode.load("ListAppend", "Optimize.c")),
    262                                     BuiltinMethod("extend",  "TO",   "r", "__Pyx_PyList_Extend",
    263                                                   utility_code=UtilityCode.load("ListExtend", "Optimize.c")),
    264                                     ]),
    265 
    266     ("dict",    "PyDict_Type",     [BuiltinMethod("__contains__",  "TO",   "b", "PyDict_Contains"),
    267                                     BuiltinMethod("has_key",       "TO",   "b", "PyDict_Contains"),
    268                                     BuiltinMethod("items",  "T",   "O", "__Pyx_PyDict_Items",
    269                                                   utility_code=UtilityCode.load("py_dict_items", "Builtins.c")),
    270                                     BuiltinMethod("keys",   "T",   "O", "__Pyx_PyDict_Keys",
    271                                                   utility_code=UtilityCode.load("py_dict_keys", "Builtins.c")),
    272                                     BuiltinMethod("values", "T",   "O", "__Pyx_PyDict_Values",
    273                                                   utility_code=UtilityCode.load("py_dict_values", "Builtins.c")),
    274                                     BuiltinMethod("iteritems",  "T",   "O", "__Pyx_PyDict_IterItems",
    275                                                   utility_code=UtilityCode.load("py_dict_iteritems", "Builtins.c")),
    276                                     BuiltinMethod("iterkeys",   "T",   "O", "__Pyx_PyDict_IterKeys",
    277                                                   utility_code=UtilityCode.load("py_dict_iterkeys", "Builtins.c")),
    278                                     BuiltinMethod("itervalues", "T",   "O", "__Pyx_PyDict_IterValues",
    279                                                   utility_code=UtilityCode.load("py_dict_itervalues", "Builtins.c")),
    280                                     BuiltinMethod("viewitems",  "T",   "O", "__Pyx_PyDict_ViewItems",
    281                                                   utility_code=UtilityCode.load("py_dict_viewitems", "Builtins.c")),
    282                                     BuiltinMethod("viewkeys",   "T",   "O", "__Pyx_PyDict_ViewKeys",
    283                                                   utility_code=UtilityCode.load("py_dict_viewkeys", "Builtins.c")),
    284                                     BuiltinMethod("viewvalues", "T",   "O", "__Pyx_PyDict_ViewValues",
    285                                                   utility_code=UtilityCode.load("py_dict_viewvalues", "Builtins.c")),
    286                                     BuiltinMethod("clear",  "T",   "r", "__Pyx_PyDict_Clear",
    287                                                   utility_code=UtilityCode.load("py_dict_clear", "Optimize.c")),
    288                                     BuiltinMethod("copy",   "T",   "T", "PyDict_Copy")]),
    289 
    290     ("slice",   "PySlice_Type",    [BuiltinAttribute('start'),
    291                                     BuiltinAttribute('stop'),
    292                                     BuiltinAttribute('step'),
    293                                     ]),
    294 #    ("file",    "PyFile_Type",     []),  # not in Py3
    295 
    296     ("set",       "PySet_Type",    [BuiltinMethod("__contains__",  "TO",   "b", "PySequence_Contains"),
    297                                     BuiltinMethod("clear",   "T",  "r", "PySet_Clear",
    298                                                   utility_code = py_set_utility_code),
    299                                     # discard() and remove() have a special treatment for unhashable values
    300 #                                    BuiltinMethod("discard", "TO", "r", "PySet_Discard",
    301 #                                                  utility_code = py_set_utility_code),
    302                                     BuiltinMethod("add",     "TO", "r", "PySet_Add",
    303                                                   utility_code = py_set_utility_code),
    304                                     BuiltinMethod("pop",     "T",  "O", "PySet_Pop",
    305                                                   utility_code = py_set_utility_code)]),
    306     ("frozenset", "PyFrozenSet_Type", []),
    307 ]
    308 
    309 
    310 types_that_construct_their_instance = set([
    311     # some builtin types do not always return an instance of
    312     # themselves - these do:
    313     'type', 'bool', 'long', 'float', 'complex',
    314     'bytes', 'unicode', 'bytearray',
    315     'tuple', 'list', 'dict', 'set', 'frozenset'
    316     # 'str',             # only in Py3.x
    317     # 'file',            # only in Py2.x
    318 ])
    319 
    320 
    321 builtin_structs_table = [
    322     ('Py_buffer', 'Py_buffer',
    323      [("buf",        PyrexTypes.c_void_ptr_type),
    324       ("obj",        PyrexTypes.py_object_type),
    325       ("len",        PyrexTypes.c_py_ssize_t_type),
    326       ("itemsize",   PyrexTypes.c_py_ssize_t_type),
    327       ("readonly",   PyrexTypes.c_bint_type),
    328       ("ndim",       PyrexTypes.c_int_type),
    329       ("format",     PyrexTypes.c_char_ptr_type),
    330       ("shape",      PyrexTypes.c_py_ssize_t_ptr_type),
    331       ("strides",    PyrexTypes.c_py_ssize_t_ptr_type),
    332       ("suboffsets", PyrexTypes.c_py_ssize_t_ptr_type),
    333       ("smalltable", PyrexTypes.CArrayType(PyrexTypes.c_py_ssize_t_type, 2)),
    334       ("internal",   PyrexTypes.c_void_ptr_type),
    335       ]),
    336     ('Py_complex', 'Py_complex',
    337      [('real', PyrexTypes.c_double_type),
    338       ('imag', PyrexTypes.c_double_type),
    339       ])
    340 ]
    341 
    342 # set up builtin scope
    343 
    344 builtin_scope = BuiltinScope()
    345 
    346 def init_builtin_funcs():
    347     for bf in builtin_function_table:
    348         bf.declare_in_scope(builtin_scope)
    349 
    350 builtin_types = {}
    351 
    352 def init_builtin_types():
    353     global builtin_types
    354     for name, cname, methods in builtin_types_table:
    355         utility = builtin_utility_code.get(name)
    356         if name == 'frozenset':
    357             objstruct_cname = 'PySetObject'
    358         elif name == 'bool':
    359             objstruct_cname = None
    360         else:
    361             objstruct_cname = 'Py%sObject' % name.capitalize()
    362         the_type = builtin_scope.declare_builtin_type(name, cname, utility, objstruct_cname)
    363         builtin_types[name] = the_type
    364         for method in methods:
    365             method.declare_in_type(the_type)
    366 
    367 def init_builtin_structs():
    368     for name, cname, attribute_types in builtin_structs_table:
    369         scope = StructOrUnionScope(name)
    370         for attribute_name, attribute_type in attribute_types:
    371             scope.declare_var(attribute_name, attribute_type, None,
    372                               attribute_name, allow_pyobject=True)
    373         builtin_scope.declare_struct_or_union(
    374             name, "struct", scope, 1, None, cname = cname)
    375 
    376 
    377 def init_builtins():
    378     init_builtin_structs()
    379     init_builtin_types()
    380     init_builtin_funcs()
    381     builtin_scope.declare_var(
    382         '__debug__', PyrexTypes.c_const_type(PyrexTypes.c_bint_type),
    383         pos=None, cname='(!Py_OptimizeFlag)', is_cdef=True)
    384     global list_type, tuple_type, dict_type, set_type, frozenset_type
    385     global bytes_type, str_type, unicode_type, basestring_type, slice_type
    386     global float_type, bool_type, type_type, complex_type, bytearray_type
    387     type_type  = builtin_scope.lookup('type').type
    388     list_type  = builtin_scope.lookup('list').type
    389     tuple_type = builtin_scope.lookup('tuple').type
    390     dict_type  = builtin_scope.lookup('dict').type
    391     set_type   = builtin_scope.lookup('set').type
    392     frozenset_type = builtin_scope.lookup('frozenset').type
    393     slice_type   = builtin_scope.lookup('slice').type
    394     bytes_type = builtin_scope.lookup('bytes').type
    395     str_type   = builtin_scope.lookup('str').type
    396     unicode_type = builtin_scope.lookup('unicode').type
    397     basestring_type = builtin_scope.lookup('basestring').type
    398     bytearray_type = builtin_scope.lookup('bytearray').type
    399     float_type = builtin_scope.lookup('float').type
    400     bool_type  = builtin_scope.lookup('bool').type
    401     complex_type  = builtin_scope.lookup('complex').type
    402 
    403 
    404 init_builtins()
    405