From 51db01c94813eeaeb7c9426424d754276f759532 Mon Sep 17 00:00:00 2001 From: Robert Bradshaw Date: Sat, 3 Oct 2009 22:37:02 -0700 Subject: [PATCH] Type inference testing. --- Cython/Compiler/ExprNodes.py | 21 +++++++++++++-------- Cython/Compiler/Nodes.py | 6 ++++++ Cython/Compiler/PyrexTypes.py | 7 +++++-- Cython/Compiler/TypeInference.py | 8 ++++++-- Demos/embed/main.c | 9 --------- tests/compile/cassign.pyx | 1 + tests/run/pycmp.pyx | 1 + 7 files changed, 32 insertions(+), 21 deletions(-) delete mode 100644 Demos/embed/main.c diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py index 7eb42ec1..a1a36cf8 100644 --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@ -4245,24 +4245,29 @@ class SizeofVarNode(SizeofNode): def generate_result_code(self, code): pass -class TypeofNode(StringNode): +class TypeofNode(ExprNode): # Compile-time type of an expression, as a string. # # operand ExprNode + # literal StringNode # internal - subexprs = ['operand'] + literal = None + type = py_object_type + + subexprs = ['operand', 'literal'] def analyse_types(self, env): self.operand.analyse_types(env) from StringEncoding import EncodedString - self.value = EncodedString(str(self.operand.type)) - StringNode.analyse_types(self, env) - - def analyse_as_type(self, env): - return None + self.literal = StringNode(self.pos, value=EncodedString(str(self.operand.type))) + self.literal.analyse_types(env) + self.literal = self.literal.coerce_to_pyobject(env) def generate_evaluation_code(self, code): - self.generate_result_code(code) + self.literal.generate_evaluation_code(code) + + def calculate_result_code(self): + return self.literal.calculate_result_code() #------------------------------------------------------------------- # diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py index 82e211a4..1b40e84e 100644 --- a/Cython/Compiler/Nodes.py +++ b/Cython/Compiler/Nodes.py @@ -4,6 +4,12 @@ import sys, os, time, copy +try: + set +except NameError: + # Python 2.3 + from sets import Set as set + import Code import Builtin from Errors import error, warning, InternalError diff --git a/Cython/Compiler/PyrexTypes.py b/Cython/Compiler/PyrexTypes.py index f4854441..6f71360f 100644 --- a/Cython/Compiler/PyrexTypes.py +++ b/Cython/Compiler/PyrexTypes.py @@ -1801,10 +1801,14 @@ def widest_numeric_type(type1, type2): def spanning_type(type1, type2): # Return a type assignable from both type1 and type2. - if type1 == type2: + if type1 is py_object_type or type2 is py_object_type: + return py_object_type + elif type1 == type2: return type1 elif type1.is_numeric and type2.is_numeric: return widest_numeric_type(type1, type2) + elif type1.is_pyobject ^ type2.is_pyobject: + return py_object_type elif type1.assignable_from(type2): return type1 elif type2.assignable_from(type1): @@ -1812,7 +1816,6 @@ def spanning_type(type1, type2): else: return py_object_type - def simple_c_type(signed, longness, name): # Find type descriptor for simple type given name and modifiers. # Returns None if arguments don't make sense. diff --git a/Cython/Compiler/TypeInference.py b/Cython/Compiler/TypeInference.py index 4b876388..0d9b2753 100644 --- a/Cython/Compiler/TypeInference.py +++ b/Cython/Compiler/TypeInference.py @@ -50,12 +50,14 @@ class MarkAssignments(CythonTransform): def visit_ForInStatNode(self, node): # TODO: Remove redundancy with range optimization... + is_range = False sequence = node.iterator.sequence if isinstance(sequence, ExprNodes.SimpleCallNode): function = sequence.function if sequence.self is None and \ isinstance(function, ExprNodes.NameNode) and \ function.name in ('range', 'xrange'): + is_range = True self.mark_assignment(node.target, sequence.args[0]) if len(sequence.args) > 1: self.mark_assignment(node.target, sequence.args[1]) @@ -65,7 +67,7 @@ class MarkAssignments(CythonTransform): '+', sequence.args[0], sequence.args[2])) - else: + if not is_range: self.mark_assignment(node.target, object_expr) self.visitchildren(node) return node @@ -143,7 +145,7 @@ class SimpleAssignmentTypeInferer: del dependancies_by_entry[entry] ready_to_infer.append(entry) # Try to infer things in order... - while ready_to_infer: + while True: while ready_to_infer: entry = ready_to_infer.pop() types = [expr.infer_type(scope) for expr in entry.assignments] @@ -165,6 +167,8 @@ class SimpleAssignmentTypeInferer: del dependancies_by_entry[entry] if ready_to_infer: break + if not ready_to_infer: + break # We can't figure out the rest with this algorithm, let them be objects. for entry in dependancies_by_entry: diff --git a/Demos/embed/main.c b/Demos/embed/main.c deleted file mode 100644 index 3e089abc..00000000 --- a/Demos/embed/main.c +++ /dev/null @@ -1,9 +0,0 @@ -#include "Python.h" -#include "embedded.h" - -int main(int argc, char *argv) { - Py_Initialize(); - initembedded(); - spam(); - Py_Finalize(); -} diff --git a/tests/compile/cassign.pyx b/tests/compile/cassign.pyx index d5119470..e3e26089 100644 --- a/tests/compile/cassign.pyx +++ b/tests/compile/cassign.pyx @@ -2,6 +2,7 @@ cdef void foo(): cdef int i1, i2=0 cdef char c1=0, c2 cdef char *p1, *p2=NULL + cdef object obj1 i1 = i2 i1 = c1 p1 = p2 diff --git a/tests/run/pycmp.pyx b/tests/run/pycmp.pyx index ec4334b5..a6916422 100644 --- a/tests/run/pycmp.pyx +++ b/tests/run/pycmp.pyx @@ -5,6 +5,7 @@ __doc__ = u""" def f(): cdef int bool, int1, int2 + cdef object obj1, obj2 int1 = 0 int2 = 0 obj1 = 1 -- 2.26.2