diff options
author | scoder <stefan_ml@behnel.de> | 2017-10-28 17:18:50 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-10-28 17:18:50 +0200 |
commit | 12eaff0561051ff3596520f219e257010eb61739 (patch) | |
tree | 784576ca9e238f5162d2a19039d41406daaa58e8 | |
parent | 33c4f688cc92a1e498b1b572ccd5be2119673ff1 (diff) | |
parent | b1d62ad550fa7509e70854fc753c6b3e841d4b8a (diff) | |
download | cython-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.py | 21 | ||||
-rw-r--r-- | Cython/Compiler/PyrexTypes.py | 9 | ||||
-rw-r--r-- | Cython/Compiler/Pythran.py | 13 | ||||
-rw-r--r-- | Cython/Compiler/TypeInference.py | 2 |
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. |