Commit 342eb45a authored by Stefan Behnel's avatar Stefan Behnel

fix ticket #602: let bytes literals start off as 'bytes' instead of 'char*'

parent 69ac804f
...@@ -948,7 +948,8 @@ class BytesNode(ConstNode): ...@@ -948,7 +948,8 @@ class BytesNode(ConstNode):
# #
# value BytesLiteral # 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): def compile_time_value(self, denv):
return self.value return self.value
...@@ -969,11 +970,13 @@ class BytesNode(ConstNode): ...@@ -969,11 +970,13 @@ class BytesNode(ConstNode):
return len(self.value) == 1 return len(self.value) == 1
def coerce_to_boolean(self, env): def coerce_to_boolean(self, env):
# This is special because we start off as a C char*. Testing # This is special because testing a C char* for truth directly
# that for truth directly would yield the wrong result. # would yield the wrong result.
return BoolNode(self.pos, value=bool(self.value)) return BoolNode(self.pos, value=bool(self.value))
def coerce_to(self, dst_type, env): def coerce_to(self, dst_type, env):
if self.type == dst_type:
return self
if dst_type.is_int: if dst_type.is_int:
if not self.can_coerce_to_char_literal(): if not self.can_coerce_to_char_literal():
error(self.pos, "Only single-character string literals can be coerced into ints.") error(self.pos, "Only single-character string literals can be coerced into ints.")
...@@ -984,21 +987,20 @@ class BytesNode(ConstNode): ...@@ -984,21 +987,20 @@ class BytesNode(ConstNode):
return CharNode(self.pos, value=self.value) return CharNode(self.pos, value=self.value)
node = BytesNode(self.pos, value=self.value) node = BytesNode(self.pos, value=self.value)
if dst_type == PyrexTypes.c_char_ptr_type: if dst_type.is_pyobject:
node.type = PyrexTypes.c_char_ptr_type 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 return node
elif dst_type == PyrexTypes.c_uchar_ptr_type: elif dst_type == PyrexTypes.c_uchar_ptr_type:
node.type = PyrexTypes.c_char_ptr_type node.type = PyrexTypes.c_char_ptr_type
return CastNode(node, PyrexTypes.c_uchar_ptr_type) return CastNode(node, PyrexTypes.c_uchar_ptr_type)
elif dst_type.assignable_from(PyrexTypes.c_char_ptr_type):
if not self.type.is_pyobject: node.type = dst_type
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)
return node return node
# We still need to perform normal coerce_to processing on the # We still need to perform normal coerce_to processing on the
...@@ -1006,11 +1008,6 @@ class BytesNode(ConstNode): ...@@ -1006,11 +1008,6 @@ class BytesNode(ConstNode):
# in which case a type test node will be needed. # in which case a type test node will be needed.
return ConstNode.coerce_to(node, dst_type, env) 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): def generate_evaluation_code(self, code):
if self.type.is_pyobject: if self.type.is_pyobject:
self.result_code = code.get_py_string_const(self.value) self.result_code = code.get_py_string_const(self.value)
...@@ -2962,9 +2959,14 @@ class SimpleCallNode(CallNode): ...@@ -2962,9 +2959,14 @@ class SimpleCallNode(CallNode):
arg = arg.coerce_to_temp(env) arg = arg.coerce_to_temp(env)
self.args[i] = arg self.args[i] = arg
for i in range(max_nargs, actual_nargs): for i in range(max_nargs, actual_nargs):
if self.args[i].type.is_pyobject: 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, error(self.args[i].pos,
"Python object cannot be passed as a varargs parameter") "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 # Calc result type and code fragment
if isinstance(self.function, NewExprNode): if isinstance(self.function, NewExprNode):
self.type = PyrexTypes.CPtrType(self.function.class_type) self.type = PyrexTypes.CPtrType(self.function.class_type)
......
...@@ -353,6 +353,10 @@ class PyObjectType(PyrexType): ...@@ -353,6 +353,10 @@ class PyObjectType(PyrexType):
def can_coerce_to_pyobject(self, env): def can_coerce_to_pyobject(self, env):
return True return True
def default_coerced_ctype(self):
"The default C type that this Python type coerces to, or None."
return None
def assignable_from(self, src_type): def assignable_from(self, src_type):
# except for pointers, conversion will be attempted # except for pointers, conversion will be attempted
return not src_type.is_ptr or src_type.is_string return not src_type.is_ptr or src_type.is_string
...@@ -404,6 +408,15 @@ class BuiltinObjectType(PyObjectType): ...@@ -404,6 +408,15 @@ class BuiltinObjectType(PyObjectType):
def __repr__(self): def __repr__(self):
return "<%s>"% self.cname return "<%s>"% self.cname
def default_coerced_ctype(self):
if self.name == 'bytes':
return c_char_ptr_type
elif self.name == 'bool':
return c_bint_type
elif self.name == 'float':
return c_double_type
return None
def assignable_from(self, src_type): def assignable_from(self, src_type):
if isinstance(src_type, BuiltinObjectType): if isinstance(src_type, BuiltinObjectType):
return src_type.name == self.name return src_type.name == self.name
......
...@@ -58,18 +58,18 @@ _ERRORS = u""" ...@@ -58,18 +58,18 @@ _ERRORS = u"""
30:22: Cannot convert Unicode string to 'bytes' implicitly, encoding required. 30:22: Cannot convert Unicode string to 'bytes' implicitly, encoding required.
31:22: Cannot convert 'str' to 'bytes' implicitly. This is not portable. 31:22: Cannot convert 'str' to 'bytes' implicitly. This is not portable.
33:17: Cannot assign type 'char *' to 'str object' 33:17: Cannot convert 'bytes' object to str implicitly. This is not portable to Py3.
34:19: Cannot convert 'bytes' object to str implicitly. This is not portable to Py3. 34:19: Cannot convert 'bytes' object to str implicitly. This is not portable to Py3.
35:17: Cannot convert Unicode string to 'str' implicitly. This is not portable and requires explicit encoding. 35:17: Cannot convert Unicode string to 'str' implicitly. This is not portable and requires explicit encoding.
36:19: Cannot convert Unicode string to 'str' implicitly. This is not portable and requires explicit encoding. 36:19: Cannot convert Unicode string to 'str' implicitly. This is not portable and requires explicit encoding.
38:20: str objects do not support coercion to unicode, use a unicode string literal instead (u'') 38:20: str objects do not support coercion to unicode, use a unicode string literal instead (u'')
39:22: str objects do not support coercion to unicode, use a unicode string literal instead (u'') 39:22: str objects do not support coercion to unicode, use a unicode string literal instead (u'')
40:20: Cannot assign type 'char *' to 'unicode object' 40:20: Cannot convert 'bytes' object to unicode implicitly, decoding required
41:22: Cannot convert 'bytes' object to unicode implicitly, decoding required 41:22: Cannot convert 'bytes' object to unicode implicitly, decoding required
42:22: Cannot convert 'char*' to unicode implicitly, decoding required 42:22: Cannot convert 'char*' to unicode implicitly, decoding required
44:19: Cannot assign type 'str object' to 'tuple object' 44:19: Cannot assign type 'str object' to 'tuple object'
45:18: Cannot assign type 'unicode object' to 'tuple object' 45:18: Cannot assign type 'unicode object' to 'tuple object'
46:18: Cannot assign type 'char *' to 'tuple object' 46:18: Cannot assign type 'bytes object' to 'tuple object'
""" """
...@@ -25,7 +25,7 @@ def simple(): ...@@ -25,7 +25,7 @@ def simple():
xptrptr = &xptr xptrptr = &xptr
assert typeof(xptrptr) == "double **", typeof(xptrptr) assert typeof(xptrptr) == "double **", typeof(xptrptr)
b = b"abc" b = b"abc"
assert typeof(b) == "char *", typeof(b) assert typeof(b) == "bytes object", typeof(b)
s = "abc" s = "abc"
assert typeof(s) == "str object", typeof(s) assert typeof(s) == "str object", typeof(s)
u = u"xyz" u = u"xyz"
...@@ -57,7 +57,7 @@ def slicing(): ...@@ -57,7 +57,7 @@ def slicing():
>>> slicing() >>> slicing()
""" """
b = b"abc" b = b"abc"
assert typeof(b) == "char *", typeof(b) assert typeof(b) == "bytes object", typeof(b)
b1 = b[1:2] b1 = b[1:2]
assert typeof(b1) == "bytes object", typeof(b1) assert typeof(b1) == "bytes object", typeof(b1)
b2 = b[1:2:2] b2 = b[1:2:2]
...@@ -92,9 +92,9 @@ def indexing(): ...@@ -92,9 +92,9 @@ def indexing():
>>> indexing() >>> indexing()
""" """
b = b"abc" b = b"abc"
assert typeof(b) == "char *", typeof(b) assert typeof(b) == "bytes object", typeof(b)
b1 = b[1] b1 = b[1]
assert typeof(b1) == "char", typeof(b1) # FIXME: Python object ?? assert typeof(b1) == "Python object", typeof(b1)
u = u"xyz" u = u"xyz"
assert typeof(u) == "unicode object", typeof(u) assert typeof(u) == "unicode object", typeof(u)
u1 = u[1] u1 = u[1]
......
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