From: Robert Bradshaw Date: Sun, 4 Oct 2009 05:37:02 +0000 (-0700) Subject: cython.typeof special method X-Git-Tag: 0.12.alpha0~177^2~7 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=8da8ec52f47dd1f98f73fdda184e5caa6ab336bb;p=cython.git cython.typeof special method --- diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py index 981ddbef..7eb42ec1 100644 --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@ -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: diff --git a/Cython/Compiler/ParseTreeTransforms.py b/Cython/Compiler/ParseTreeTransforms.py index 2836a36e..cc98d128 100644 --- a/Cython/Compiler/ParseTreeTransforms.py +++ b/Cython/Compiler/ParseTreeTransforms.py @@ -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) diff --git a/Cython/Shadow.py b/Cython/Shadow.py index 49e05f3d..63269ca3 100644 --- a/Cython/Shadow.py +++ b/Cython/Shadow.py @@ -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 index 00000000..b87a3d6d --- /dev/null +++ b/tests/run/typeof.pyx @@ -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)