cython.typeof special method
authorRobert Bradshaw <robertwb@math.washington.edu>
Sun, 4 Oct 2009 05:37:02 +0000 (22:37 -0700)
committerRobert Bradshaw <robertwb@math.washington.edu>
Sun, 4 Oct 2009 05:37:02 +0000 (22:37 -0700)
Cython/Compiler/ExprNodes.py
Cython/Compiler/ParseTreeTransforms.py
Cython/Shadow.py
tests/run/typeof.pyx [new file with mode: 0644]

index 981ddbef9d4ff9017c39315442b618efaecf64a9..7eb42ec14d5dc82a180f9f2088c949af9708f1d7 100644 (file)
@@ -4245,6 +4245,24 @@ class SizeofVarNode(SizeofNode):
     def generate_result_code(self, code):
         pass
 
+class TypeofNode(StringNode):
+    #  Compile-time type of an expression, as a string.
+    #
+    #  operand   ExprNode
+    
+    subexprs = ['operand']
+    
+    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
+    
+    def generate_evaluation_code(self, code):
+        self.generate_result_code(code)
 
 #-------------------------------------------------------------------
 #
@@ -4850,9 +4868,6 @@ class CondExprNode(ExprNode):
     def infer_type(self, env):
         return self.compute_result_type(self.true_val.infer_type(env),
                                         self.false_val.infer_type(env))
-    def infer_types(self, env):
-        return self.compute_result_type(self.true_val.infer_types(env),
-                                        self.false_val.infer_types(env))
 
     def calculate_constant_result(self):
         if self.test.constant_result:
index 2836a36ead5e313d52864be7c8c34d4009fd31bb..cc98d12868c260672df6fdbbf383a3f0825c29e4 100644 (file)
@@ -328,7 +328,7 @@ class InterpretCompilerDirectives(CythonTransform, SkipDeclarations):
     duplication of functionality has to occur: We manually track cimports
     and which names the "cython" module may have been imported to.
     """
-    special_methods = set(['declare', 'union', 'struct', 'typedef', 'sizeof', 'cast', 'address', 'pointer', 'compiled', 'NULL'])
+    special_methods = set(['declare', 'union', 'struct', 'typedef', 'sizeof', 'typeof', 'cast', 'address', 'pointer', 'compiled', 'NULL'])
 
     def __init__(self, context, compilation_option_overrides):
         super(InterpretCompilerDirectives, self).__init__(context)
@@ -1009,6 +1009,11 @@ class TransformBuiltinMethods(EnvTransform):
                         node = SizeofTypeNode(node.function.pos, arg_type=type)
                     else:
                         node = SizeofVarNode(node.function.pos, operand=node.args[0])
+            elif function == 'typeof':
+                if len(node.args) != 1:
+                    error(node.function.pos, u"sizeof takes exactly one argument" % function)
+                else:
+                    node = TypeofNode(node.function.pos, operand=node.args[0])
             elif function == 'address':
                 if len(node.args) != 1:
                     error(node.function.pos, u"sizeof takes exactly one argument" % function)
index 49e05f3d51df17c3ce2e02baf9bf906d8fc91897..63269ca39376abb740303b46c72b44ff15d08862 100644 (file)
@@ -30,6 +30,9 @@ def cast(type, arg):
 
 def sizeof(arg):
     return 1
+
+def typeof(arg):
+    return type(arg)
     
 def address(arg):
     return pointer(type(arg))([arg])
diff --git a/tests/run/typeof.pyx b/tests/run/typeof.pyx
new file mode 100644 (file)
index 0000000..b87a3d6
--- /dev/null
@@ -0,0 +1,60 @@
+__doc__ = u"""
+    >>> simple()
+    int
+    long
+    long long
+    int *
+    int **
+    A
+    B
+    X
+    Python object
+    
+    >>> expression()
+    double
+    double complex
+    int
+    unsigned int
+"""
+
+from cython cimport typeof
+
+cdef class A:
+    pass
+
+cdef class B(A):
+    pass
+
+cdef struct X:
+    double a
+    double complex b
+
+def simple():
+    cdef int i
+    cdef long l
+    cdef long long ll
+    cdef int* iptr
+    cdef int** iptrptr
+    cdef A a
+    cdef B b
+    cdef X x
+    print typeof(i)
+    print typeof(l)
+    print typeof(ll)
+    print typeof(iptr)
+    print typeof(iptrptr)
+    print typeof(a)
+    print typeof(b)
+    print typeof(x)
+    print typeof(None)
+    
+def expression():
+    cdef X x
+    cdef X *xptr
+    cdef short s
+    cdef int i
+    cdef unsigned int ui
+    print typeof(x.a)
+    print typeof(xptr.b)
+    print typeof(s + i)
+    print typeof(i + ui)