summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorscoder <stefan_ml@behnel.de>2017-10-28 17:18:50 +0200
committerGitHub <noreply@github.com>2017-10-28 17:18:50 +0200
commit12eaff0561051ff3596520f219e257010eb61739 (patch)
tree784576ca9e238f5162d2a19039d41406daaa58e8
parent33c4f688cc92a1e498b1b572ccd5be2119673ff1 (diff)
parentb1d62ad550fa7509e70854fc753c6b3e841d4b8a (diff)
downloadcython-12eaff0561051ff3596520f219e257010eb61739.tar.gz
Merge pull request #1954 from nils-braun/pythran-multiple-line-support
Type inference for Pythran expressions
-rw-r--r--Cython/Compiler/ExprNodes.py21
-rw-r--r--Cython/Compiler/PyrexTypes.py9
-rw-r--r--Cython/Compiler/Pythran.py13
-rw-r--r--Cython/Compiler/TypeInference.py2
4 files changed, 36 insertions, 9 deletions
diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py
index b415e1410..50e1f6a6c 100644
--- a/Cython/Compiler/ExprNodes.py
+++ b/Cython/Compiler/ExprNodes.py
@@ -2284,7 +2284,11 @@ class NameNode(AtomicExprNode):
code.putln('%s = %s;' % (self.result(), result))
else:
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:
print("NameNode.generate_assignment_code:")
print("...generating post-assignment code for %s" % rhs)
@@ -3450,6 +3454,10 @@ class IndexNode(_IndexingBaseNode):
if index_func is not None:
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
if base_type in (unicode_type, str_type):
# these types always returns their own type on Python indexing/slicing
@@ -4100,7 +4108,8 @@ class BufferIndexNode(_IndexingBaseNode):
def analyse_buffer_index(self, env, getting):
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:
self.base = self.base.coerce_to_simple(env)
self.type = self.base.type.dtype
@@ -12241,7 +12250,13 @@ class PrimaryCmpNode(ExprNode, CmpNode):
is_memslice_nonecheck = False
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
def type_dependencies(self, env):
diff --git a/Cython/Compiler/PyrexTypes.py b/Cython/Compiler/PyrexTypes.py
index b5bd41a28..572e25ee7 100644
--- a/Cython/Compiler/PyrexTypes.py
+++ b/Cython/Compiler/PyrexTypes.py
@@ -1506,6 +1506,15 @@ class PythranExpr(CType):
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):
is_const = 1
diff --git a/Cython/Compiler/Pythran.py b/Cython/Compiler/Pythran.py
index d2c3573bc..cf0e324e5 100644
--- a/Cython/Compiler/Pythran.py
+++ b/Cython/Compiler/Pythran.py
@@ -66,7 +66,8 @@ def _index_access(index_code, indices):
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.step.is_none:
func = "contiguous_slice"
@@ -76,11 +77,11 @@ def _index_type_code(idx):
n = 3
return "pythonic::types::%s(%s)" % (
func, ",".join(["0"]*n))
- elif idx.type.is_int:
- return "std::declval<%s>()" % idx.type.sign_and_name()
- elif idx.type.is_pythran_expr:
- return "std::declval<%s>()" % idx.type.pythran_type
- raise ValueError("unsupported indexing type %s!" % idx.type)
+ elif index_type.is_int:
+ return "std::declval<%s>()" % index_type.sign_and_name()
+ elif index_type.is_pythran_expr:
+ return "std::declval<%s>()" % index_type.pythran_type
+ raise ValueError("unsupported indexing type %s!" % index_type)
def _index_code(idx):
diff --git a/Cython/Compiler/TypeInference.py b/Cython/Compiler/TypeInference.py
index 18a15a915..0f018aad7 100644
--- a/Cython/Compiler/TypeInference.py
+++ b/Cython/Compiler/TypeInference.py
@@ -561,6 +561,8 @@ def safe_spanning_type(types, might_overflow, pos, scope):
# find_spanning_type() only returns 'bint' for clean boolean
# operations without other int types, so this is safe, too
return result_type
+ elif result_type.is_pythran_expr:
+ return result_type
elif result_type.is_ptr:
# Any pointer except (signed|unsigned|) char* can't implicitly
# become a PyObject, and inferring char* is now accepted, too.