Commit 12eaff05 authored by scoder's avatar scoder Committed by GitHub

Merge pull request #1954 from nils-braun/pythran-multiple-line-support

Type inference for Pythran expressions
parents 33c4f688 b1d62ad5
...@@ -2284,7 +2284,11 @@ class NameNode(AtomicExprNode): ...@@ -2284,7 +2284,11 @@ class NameNode(AtomicExprNode):
code.putln('%s = %s;' % (self.result(), result)) code.putln('%s = %s;' % (self.result(), result))
else: else:
result = rhs.result_as(self.ctype()) result = rhs.result_as(self.ctype())
code.putln('%s = %s;' % (self.result(), result))
if is_pythran_expr(self.type):
code.putln('new (&%s) decltype(%s){%s};' % (self.result(), self.result(), result))
else:
code.putln('%s = %s;' % (self.result(), result))
if debug_disposal_code: if debug_disposal_code:
print("NameNode.generate_assignment_code:") print("NameNode.generate_assignment_code:")
print("...generating post-assignment code for %s" % rhs) print("...generating post-assignment code for %s" % rhs)
...@@ -3450,6 +3454,10 @@ class IndexNode(_IndexingBaseNode): ...@@ -3450,6 +3454,10 @@ class IndexNode(_IndexingBaseNode):
if index_func is not None: if index_func is not None:
return index_func.type.return_type return index_func.type.return_type
if is_pythran_expr(base_type) and is_pythran_expr(index_type):
index_with_type = (self.index, index_type)
return PythranExpr(pythran_indexing_type(base_type, [index_with_type]))
# may be slicing or indexing, we don't know # may be slicing or indexing, we don't know
if base_type in (unicode_type, str_type): if base_type in (unicode_type, str_type):
# these types always returns their own type on Python indexing/slicing # these types always returns their own type on Python indexing/slicing
...@@ -4100,7 +4108,8 @@ class BufferIndexNode(_IndexingBaseNode): ...@@ -4100,7 +4108,8 @@ class BufferIndexNode(_IndexingBaseNode):
def analyse_buffer_index(self, env, getting): def analyse_buffer_index(self, env, getting):
if is_pythran_expr(self.base.type): if is_pythran_expr(self.base.type):
self.type = PythranExpr(pythran_indexing_type(self.base.type, self.indices)) index_with_type_list = [(idx, idx.type) for idx in self.indices]
self.type = PythranExpr(pythran_indexing_type(self.base.type, index_with_type_list))
else: else:
self.base = self.base.coerce_to_simple(env) self.base = self.base.coerce_to_simple(env)
self.type = self.base.type.dtype self.type = self.base.type.dtype
...@@ -12241,7 +12250,13 @@ class PrimaryCmpNode(ExprNode, CmpNode): ...@@ -12241,7 +12250,13 @@ class PrimaryCmpNode(ExprNode, CmpNode):
is_memslice_nonecheck = False is_memslice_nonecheck = False
def infer_type(self, env): def infer_type(self, env):
# TODO: Actually implement this (after merging with -unstable). type1 = self.operand1.infer_type(env)
type2 = self.operand2.infer_type(env)
if is_pythran_expr(type1) or is_pythran_expr(type2):
if is_pythran_supported_type(type1) and is_pythran_supported_type(type2):
return PythranExpr(pythran_binop_type(self.operator, type1, type2))
return py_object_type return py_object_type
def type_dependencies(self, env): def type_dependencies(self, env):
......
...@@ -1506,6 +1506,15 @@ class PythranExpr(CType): ...@@ -1506,6 +1506,15 @@ class PythranExpr(CType):
return True return True
def __eq__(self, other):
"""Equality operation for PythranExpr using the str representation"""
return str(self) == str(other)
def __hash__(self):
"""Hash function using the str representation"""
return hash(str(self))
class CConstType(BaseType): class CConstType(BaseType):
is_const = 1 is_const = 1
......
...@@ -66,7 +66,8 @@ def _index_access(index_code, indices): ...@@ -66,7 +66,8 @@ def _index_access(index_code, indices):
return ('[%s]' if len(indices) == 1 else '(%s)') % indexing return ('[%s]' if len(indices) == 1 else '(%s)') % indexing
def _index_type_code(idx): def _index_type_code(index_with_type):
idx, index_type = index_with_type
if idx.is_slice: if idx.is_slice:
if idx.step.is_none: if idx.step.is_none:
func = "contiguous_slice" func = "contiguous_slice"
...@@ -76,11 +77,11 @@ def _index_type_code(idx): ...@@ -76,11 +77,11 @@ def _index_type_code(idx):
n = 3 n = 3
return "pythonic::types::%s(%s)" % ( return "pythonic::types::%s(%s)" % (
func, ",".join(["0"]*n)) func, ",".join(["0"]*n))
elif idx.type.is_int: elif index_type.is_int:
return "std::declval<%s>()" % idx.type.sign_and_name() return "std::declval<%s>()" % index_type.sign_and_name()
elif idx.type.is_pythran_expr: elif index_type.is_pythran_expr:
return "std::declval<%s>()" % idx.type.pythran_type return "std::declval<%s>()" % index_type.pythran_type
raise ValueError("unsupported indexing type %s!" % idx.type) raise ValueError("unsupported indexing type %s!" % index_type)
def _index_code(idx): def _index_code(idx):
......
...@@ -561,6 +561,8 @@ def safe_spanning_type(types, might_overflow, pos, scope): ...@@ -561,6 +561,8 @@ def safe_spanning_type(types, might_overflow, pos, scope):
# find_spanning_type() only returns 'bint' for clean boolean # find_spanning_type() only returns 'bint' for clean boolean
# operations without other int types, so this is safe, too # operations without other int types, so this is safe, too
return result_type return result_type
elif result_type.is_pythran_expr:
return result_type
elif result_type.is_ptr: elif result_type.is_ptr:
# Any pointer except (signed|unsigned|) char* can't implicitly # Any pointer except (signed|unsigned|) char* can't implicitly
# become a PyObject, and inferring char* is now accepted, too. # become a PyObject, and inferring char* is now accepted, too.
......
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