# type
# xrange
+builtin_types_table = [
+
+ ("type", "PyType_Type", []),
+# ("str", "PyString_Type", []),
+ ("unicode", "PyUnicode_Type", []),
+ ("file", "PyFile_Type", []),
+# ("slice", "PySlice_Type", []),
+# ("set", "PySet_Type", []),
+ ("frozenset", "PyFrozenSet_Type", []),
+
+ ("tuple", "PyTuple_Type", []),
+
+ ("list", "PyList_Type", [("append", "OO", "i", "PyList_Append"),
+ ("insert", "OiO", "i", "PyList_Insert"),
+ ("sort", "O", "i", "PyList_Sort"),
+ ("reverse","O", "i", "PyList_Reverse")]),
+
+ ("dict", "PyDict_Type", [("items", "O", "O", "PyDict_Items"),
+ ("keys", "O", "O", "PyDict_Keys"),
+ ("values","O", "O", "PyDict_Values")]),
+]
+
getattr3_utility_code = ["""
static PyObject *__Pyx_GetAttr3(PyObject *, PyObject *, PyObject *); /*proto*/
""","""
for desc in builtin_function_table:
declare_builtin_func(*desc)
+def init_builtin_types():
+ for name, cname, funcs in builtin_types_table:
+ the_type = builtin_scope.declare_builtin_type(name, cname)
+ for name, args, ret, cname in funcs:
+ sig = Signature(args, ret)
+ the_type.scope.declare_cfunction(name, sig.function_type(), None, cname)
+
def init_builtins():
init_builtin_funcs()
-
+ init_builtin_types()
+ global list_type, tuple_type, dict_type
+ list_type = builtin_scope.lookup('list').type
+ tuple_type = builtin_scope.lookup('tuple').type
+ dict_type = builtin_scope.lookup('dict').type
+
init_builtins()
from Nodes import Node
import PyrexTypes
from PyrexTypes import py_object_type, c_long_type, typecast, error_type
+from Builtin import list_type, tuple_type, dict_type
import Symtab
import Options
from Annotate import AnnotationItem
obj_code = obj.result_as(obj.type)
#print "...obj_code =", obj_code ###
if self.entry and self.entry.is_cmethod:
- return "((struct %s *)%s%s%s)->%s" % (
- obj.type.vtabstruct_cname, obj_code, self.op,
- obj.type.vtabslot_cname, self.member)
+ if obj.type.is_extension_type:
+ return "((struct %s *)%s%s%s)->%s" % (
+ obj.type.vtabstruct_cname, obj_code, self.op,
+ obj.type.vtabslot_cname, self.member)
+ else:
+ return self.member
else:
return "%s%s%s" % (obj_code, self.op, self.member)
def analyse_types(self, env):
if len(self.args) == 0:
- self.type = py_object_type
self.is_temp = 0
self.is_literal = 1
else:
SequenceNode.analyse_types(self, env)
+ self.type = tuple_type
def calculate_result_code(self):
if len(self.args) > 0:
class ListNode(SequenceNode):
# List constructor.
+ def analyse_types(self, env):
+ SequenceNode.analyse_types(self, env)
+ self.type = list_type
+
def compile_time_value(self, denv):
return self.compile_time_value_list(denv)
is_sequence_constructor = 0 # not unpackable
def analyse_types(self, env):
- self.type = py_object_type
+ self.type = list_type
self.is_temp = 1
self.append.target = self # this is a CloneNode used in the PyList_Append in the inner loop
def analyse_types(self, env):
for item in self.key_value_pairs:
item.analyse_types(env)
- self.type = py_object_type
+ self.type = dict_type
self.is_temp = 1
def allocate_temps(self, env, result = None):
def __init__(self, arg, dst_type, env):
# The arg is know to be a Python object, and
# the dst_type is known to be an extension type.
- assert dst_type.is_extension_type, "PyTypeTest on non extension type"
+ assert dst_type.is_extension_type or dst_type.is_builtin_type, "PyTypeTest on non extension type"
CoercionNode.__init__(self, arg)
self.type = dst_type
self.result_ctype = arg.ctype()
def generate_result_code(self, code):
if self.type.typeobj_is_available():
code.putln(
- "if (!__Pyx_TypeTest(%s, %s)) %s" % (
- self.arg.py_result(),
- self.type.typeptr_cname,
+ "if (!(%s)) %s" % (
+ self.type.type_test_code(self.arg.py_result()),
code.error_goto(self.pos)))
else:
error(self.pos, "Cannot test type of extern C class "
typeptr_cname = arg.type.typeptr_cname
arg_code = "((PyObject *)%s)" % arg.cname
code.putln(
- 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s"))) %s' % (
+ 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
arg_code,
typeptr_cname,
not arg.not_none,
arg.name,
+ type.is_builtin_type,
code.error_goto(arg.pos)))
else:
error(arg.pos, "Cannot test type of extern C class "
if not sig.has_generic_args:
self.bad_signature()
for arg in self.args:
- if arg.is_generic and arg.type.is_extension_type:
+ if arg.is_generic and \
+ (arg.type.is_extension_type or arg.type.is_builtin_type):
arg.needs_type_test = 1
any_type_tests_needed = 1
elif arg.type is PyrexTypes.c_py_ssize_t_type:
typeptr_cname = arg.type.typeptr_cname
arg_code = "((PyObject *)%s)" % arg.entry.cname
code.putln(
- 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s"))) %s' % (
+ 'if (unlikely(!__Pyx_ArgTypeTest(%s, %s, %d, "%s", %s))) %s' % (
arg_code,
typeptr_cname,
not arg.not_none,
arg.name,
+ arg.type.is_builtin_type,
code.error_goto(arg.pos)))
else:
error(arg.pos, "Cannot test type of extern C class "
if isinstance(sequence, ExprNodes.SimpleCallNode) \
and sequence.self is None \
and isinstance(sequence.function, ExprNodes.NameNode) \
- and sequence.function.name == 'range':
+ and (sequence.function.name == 'range' or sequence.function.name == 'xrange'):
args = sequence.args
# Make sure we can determine direction from step
if self.analyse_range_step(args):
arg_type_test_utility_code = [
"""
-static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed, char *name); /*proto*/
+static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed, char *name, int exact); /*proto*/
""","""
-static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed, char *name) {
+static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed, char *name, int exact) {
if (!type) {
PyErr_Format(PyExc_SystemError, "Missing type object");
return 0;
}
- if ((none_allowed && obj == Py_None) || PyObject_TypeCheck(obj, type))
- return 1;
+ if (none_allowed && obj == Py_None) return 1;
+ else if (exact) {
+ if (PyObject_TypeCheck(obj, type)) return 1;
+ }
+ else {
+ if (obj->ob_type == type) return 1;
+ }
PyErr_Format(PyExc_TypeError,
"Argument '%s' has incorrect type (expected %s, got %s)",
name, type->tp_name, obj->ob_type->tp_name);
is_pyobject = 0
is_extension_type = 0
+ is_builtin_type = 0
is_numeric = 0
is_int = 0
is_float = 0
return "%s *%s" % (public_decl("PyObject", dll_linkage), entity_code)
+class BuiltinObjectType(PyObjectType):
+
+ is_builtin_type = 1
+ has_attributes = 1
+ base_type = None
+ module_name = '__builtin__'
+
+ def __init__(self, name, cname):
+ self.name = name
+ self.cname = cname
+ self.typeptr_cname = "&" + cname
+
+ def set_scope(self, scope):
+ self.scope = scope
+ if scope:
+ scope.parent_type = self
+
+ def __str__(self):
+ return "%s object" % self.name
+
+ def __repr__(self):
+ return "<%s>"% self.cname
+
+ def assignable_from(self, src_type):
+ if isinstance(src_type, BuiltinObjectType):
+ return src_type.name == self.name
+ else:
+ return not src_type.is_extension_type
+
+ def typeobj_is_available(self):
+ return True
+
+ def attributes_known(self):
+ return True
+
+ def subtype_of(self, type):
+ return type.is_pyobject and self.assignable_from(type)
+
+ def type_test_code(self, arg):
+ return 'likely(Py%s_CheckExact(%s)) || (%s) == Py_None || (PyErr_Format(PyExc_TypeError, "Expected %s, got %%s", %s->ob_type->tp_name), 0)' % (self.name[0].upper() + self.name[1:], arg, arg, self.name, arg)
+
+
class PyExtensionType(PyObjectType):
#
# A Python extension type.
else:
return "%s *%s" % (base, entity_code)
+ def type_test_code(self, py_arg):
+ return "__Pyx_TypeTest(%s, %s)" % (py_arg, self.typeptr_cname)
+
def attributes_known(self):
return self.scope is not None
Scope.__init__(self, "__builtin__", None, None)
else:
Scope.__init__(self, "__builtin__", PreImportScope(), None)
+ self.type_names = {}
for name, definition in self.builtin_entries.iteritems():
cname, type = definition
var_entry.is_builtin = 1
entry.as_variable = var_entry
return entry
+
+ def declare_builtin_type(self, name, cname):
+ type = PyrexTypes.BuiltinObjectType(name, cname)
+ type.set_scope(CClassScope(name, outer_scope=None, visibility='extern'))
+ self.type_names[name] = 1
+ entry = self.declare_type(name, type, None, visibility='extern')
+
+ var_entry = Entry(name = entry.name,
+ type = py_object_type,
+ pos = entry.pos,
+ cname = "((PyObject*)%s)" % entry.type.typeptr_cname)
+ var_entry.is_variable = 1
+ var_entry.is_cglobal = 1
+ var_entry.is_readonly = 1
+ entry.as_variable = var_entry
+
+ return type
def builtin_scope(self):
return self
self.module_entries = {}
self.python_include_files = ["Python.h", "structmember.h"]
self.include_files = []
- self.type_names = {}
+ self.type_names = dict(outer_scope.type_names)
self.pxd_file_loaded = 0
self.cimported_modules = []
self.intern_map = {}