#
# value BytesLiteral
- type = PyrexTypes.c_char_ptr_type
+ # start off as Python 'bytes' to support len() in O(1)
+ type = bytes_type
def compile_time_value(self, denv):
return self.value
return len(self.value) == 1
def coerce_to_boolean(self, env):
- # This is special because we start off as a C char*. Testing
- # that for truth directly would yield the wrong result.
+ # This is special because testing a C char* for truth directly
+ # would yield the wrong result.
return BoolNode(self.pos, value=bool(self.value))
def coerce_to(self, dst_type, env):
+ if self.type == dst_type:
+ return self
if dst_type.is_int:
if not self.can_coerce_to_char_literal():
error(self.pos, "Only single-character string literals can be coerced into ints.")
return CharNode(self.pos, value=self.value)
node = BytesNode(self.pos, value=self.value)
- if dst_type == PyrexTypes.c_char_ptr_type:
- node.type = PyrexTypes.c_char_ptr_type
+ if dst_type.is_pyobject:
+ if dst_type in (py_object_type, Builtin.bytes_type):
+ node.type = Builtin.bytes_type
+ else:
+ self.check_for_coercion_error(dst_type, fail=True)
+ return node
+ elif dst_type == PyrexTypes.c_char_ptr_type:
+ node.type = dst_type
return node
elif dst_type == PyrexTypes.c_uchar_ptr_type:
node.type = PyrexTypes.c_char_ptr_type
return CastNode(node, PyrexTypes.c_uchar_ptr_type)
-
- if not self.type.is_pyobject:
- if dst_type in (py_object_type, Builtin.bytes_type):
- node.type = Builtin.bytes_type
- elif dst_type.is_pyobject:
- self.fail_assignment(dst_type)
- return self
- elif dst_type.is_pyobject and dst_type is not py_object_type:
- self.check_for_coercion_error(dst_type, fail=True)
+ elif dst_type.assignable_from(PyrexTypes.c_char_ptr_type):
+ node.type = dst_type
return node
# We still need to perform normal coerce_to processing on the
# in which case a type test node will be needed.
return ConstNode.coerce_to(node, dst_type, env)
- def as_py_string_node(self, env):
- # Return a new BytesNode with the same value as this node
- # but whose type is a Python type instead of a C type.
- return BytesNode(self.pos, value = self.value, type = Builtin.bytes_type)
-
def generate_evaluation_code(self, code):
if self.type.is_pyobject:
self.result_code = code.get_py_string_const(self.value)
# Unfortunately the type attribute of type objects
# is used for the pointer to the type they represent.
return type_type
+ elif self.entry.type.is_cfunction:
+ # special case: referring to a C function must return its pointer
+ return PyrexTypes.CPtrType(self.entry.type)
else:
return self.entry.type
if self.is_used_as_rvalue:
entry = self.entry
if entry.is_builtin:
- # if not Options.cache_builtins: # cached builtins are ok
- self.gil_error()
+ if not Options.cache_builtins: # cached builtins are ok
+ self.gil_error()
elif entry.is_pyglobal:
self.gil_error()
return None
def type_dependencies(self, env):
- return self.base.type_dependencies(env)
+ return self.base.type_dependencies(env) + self.index.type_dependencies(env)
def infer_type(self, env):
base_type = self.base.infer_type(env)
self.start_code(),
self.stop_code()))
self.generate_subexpr_disposal_code(code)
+ self.free_subexpr_temps(code)
def generate_slice_guard_code(self, code, target_size):
if not self.base.type.is_array:
# Coerce arguments
for i in range(min(max_nargs, actual_nargs)):
formal_type = func_type.args[i].type
- self.args[i] = self.args[i].coerce_to(formal_type, env)
+ arg = self.args[i].coerce_to(formal_type, env)
+ if arg.type.is_pyobject and not env.nogil and (arg.is_attribute or not arg.is_simple):
+ # we do not own the argument's reference, but we must
+ # make sure it cannot be collected before we return
+ # from the function, so we create an owned temp
+ # reference to it
+ arg = arg.coerce_to_temp(env)
+ self.args[i] = arg
for i in range(max_nargs, actual_nargs):
- if self.args[i].type.is_pyobject:
- error(self.args[i].pos,
- "Python object cannot be passed as a varargs parameter")
+ arg = self.args[i]
+ if arg.type.is_pyobject:
+ arg_ctype = arg.type.default_coerced_ctype()
+ if arg_ctype is None:
+ error(self.args[i].pos,
+ "Python object cannot be passed as a varargs parameter")
+ else:
+ self.args[i] = arg.coerce_to(arg_ctype, env)
# Calc result type and code fragment
if isinstance(self.function, NewExprNode):
self.type = PyrexTypes.CPtrType(self.function.class_type)
elif self.analyse_as_unbound_cmethod(env):
return self.entry.type
else:
- self.analyse_attribute(env, obj_type = self.obj.infer_type(env))
+ obj_type = self.obj.infer_type(env)
+ self.analyse_attribute(env, obj_type = obj_type)
+ if obj_type.is_builtin_type and self.type.is_cfunction:
+ # special case: C-API replacements for C methods of
+ # builtin types cannot be inferred as C functions as
+ # that would prevent their use as bound methods
+ self.type = py_object_type
+ return py_object_type
return self.type
def analyse_target_declaration(self, env):
return module_scope.lookup_type(self.attribute)
if not isinstance(self.obj, (UnicodeNode, StringNode, BytesNode)):
base_type = self.obj.analyse_as_type(env)
- if base_type and hasattr(base_type, 'scope'):
+ if base_type and hasattr(base_type, 'scope') and base_type.scope is not None:
return base_type.scope.lookup_type(self.attribute)
return None
PyCFunctionObject func;
} %(binding_cfunc)s_object;
-PyTypeObject %(binding_cfunc)s_type;
-PyTypeObject *%(binding_cfunc)s = NULL;
+static PyTypeObject %(binding_cfunc)s_type;
+static PyTypeObject *%(binding_cfunc)s = NULL;
-PyObject *%(binding_cfunc)s_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module); /* proto */
+static PyObject *%(binding_cfunc)s_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module); /* proto */
#define %(binding_cfunc)s_New(ml, self) %(binding_cfunc)s_NewEx(ml, self, NULL)
-int %(binding_cfunc)s_init(void); /* proto */
+static int %(binding_cfunc)s_init(void); /* proto */
""" % Naming.__dict__,
impl="""
-PyObject *%(binding_cfunc)s_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module) {
+static PyObject *%(binding_cfunc)s_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module) {
%(binding_cfunc)s_object *op = PyObject_GC_New(%(binding_cfunc)s_object, %(binding_cfunc)s);
if (op == NULL)
return NULL;
return PyMethod_New(func, obj, type);
}
-int %(binding_cfunc)s_init(void) {
+static int %(binding_cfunc)s_init(void) {
%(binding_cfunc)s_type = PyCFunction_Type;
%(binding_cfunc)s_type.tp_name = __Pyx_NAMESTR("cython_binding_builtin_function_or_method");
%(binding_cfunc)s_type.tp_dealloc = (destructor)%(binding_cfunc)s_dealloc;