pure mode enhancements, tests
authorRobert Bradshaw <robertwb@math.washington.edu>
Wed, 8 Oct 2008 21:35:54 +0000 (14:35 -0700)
committerRobert Bradshaw <robertwb@math.washington.edu>
Wed, 8 Oct 2008 21:35:54 +0000 (14:35 -0700)
Cython/Compiler/ExprNodes.py
Cython/Compiler/Nodes.py
Cython/Compiler/ParseTreeTransforms.py
Cython/Compiler/PyrexTypes.py
tests/run/pure.pyx [new file with mode: 0644]

index f87d14f4805bf9c12219726ba96348bf4b5f1442..64668c99f33670b53062ace2e44b8c6c08b90c2d 100644 (file)
@@ -570,7 +570,7 @@ class ExprNode(Node):
         #  reference, or temporary.
         return self.result_in_temp()
         
-    def magic_cython_method(self):
+    def as_cython_attribute(self):
         return None
 
 
@@ -939,7 +939,7 @@ class NameNode(AtomicExprNode):
         node.analyse_types(env, entry=entry)
         return node
         
-    def magic_cython_method(self):
+    def as_cython_attribute(self):
         return self.cython_attribute
     
     create_analysed_rvalue = staticmethod(create_analysed_rvalue)
@@ -979,7 +979,10 @@ class NameNode(AtomicExprNode):
         return None
         
     def analyse_as_type(self, env):
-        type = PyrexTypes.parse_basic_type(self.name)
+        if self.cython_attribute:
+            type = PyrexTypes.parse_basic_type(self.cython_attribute)
+        else:
+            type = PyrexTypes.parse_basic_type(self.name)
         if type:
             return type
         entry = self.entry
@@ -1907,7 +1910,7 @@ class SimpleCallNode(CallNode):
             self.compile_time_value_error(e)
             
     def analyse_as_type(self, env):
-        attr = self.function.magic_cython_method()
+        attr = self.function.as_cython_attribute()
         if attr == 'pointer':
             if len(self.args) != 1:
                 error(self.args.pos, "only one type allowed.")
@@ -2262,7 +2265,7 @@ class AttributeNode(ExprNode):
     is_called = 0
     needs_none_check = True
 
-    def magic_cython_method(self):
+    def as_cython_attribute(self):
         if isinstance(self.obj, NameNode) and self.obj.is_cython_module:
             return self.attribute
 
index a57252bf81145b4f350095d330b2cf5c2adb5bcb..4a1ea98f5a4ac3ee44519aeb8cf8ae2a70ac22ef 100644 (file)
@@ -2552,7 +2552,7 @@ class ExprStatNode(StatNode):
     def analyse_declarations(self, env):
         import ExprNodes
         if isinstance(self.expr, ExprNodes.GeneralCallNode):
-            func = self.expr.function.magic_cython_method()
+            func = self.expr.function.as_cython_attribute()
             if func == u'declare':
                 args, kwds = self.expr.explicit_args_kwds()
                 if len(args):
@@ -2620,7 +2620,7 @@ class SingleAssignmentNode(AssignmentNode):
         
         # handle declarations of the form x = cython.foo()
         if isinstance(self.rhs, ExprNodes.CallNode):
-            func_name = self.rhs.function.magic_cython_method()
+            func_name = self.rhs.function.as_cython_attribute()
             if func_name:
                 args, kwds = self.rhs.explicit_args_kwds()
                 
@@ -2652,7 +2652,7 @@ class SingleAssignmentNode(AssignmentNode):
                         self.declaration_only = True
                         if not isinstance(lhs, ExprNodes.NameNode):
                             error(lhs.pos, "Invalid declaration.")
-                        env.declare_typedef(lhs.name, type, self.pos, 'private')
+                        env.declare_typedef(lhs.name, type, self.pos, visibility='private')
                     
                 elif func_name in ['struct', 'union']:
                     self.declaration_only = True
index 94cf1681042da90c023578aefd2599b87df5e92e..a32c169afb1ba54e5dd766d890340d6f5fe469ca 100644 (file)
@@ -267,6 +267,7 @@ class InterpretCompilerDirectives(CythonTransform):
     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'])
 
     def __init__(self, context, compilation_option_overrides):
         super(InterpretCompilerDirectives, self).__init__(context)
@@ -299,7 +300,9 @@ class InterpretCompilerDirectives(CythonTransform):
         if node.module_name == u"cython":
             newimp = []
             for pos, name, as_name, kind in node.imported_names:
-                if name in Options.option_types:
+                if (name in Options.option_types or 
+                        name in self.special_methods or
+                        PyrexTypes.parse_basic_type(name)):
                     if as_name is None:
                         as_name = name
                     self.option_names[as_name] = name
@@ -316,11 +319,13 @@ class InterpretCompilerDirectives(CythonTransform):
     def visit_FromImportStatNode(self, node):
         if node.module.module_name.value == u"cython":
             newimp = []
-            for true_name, name_node in node.items:
-                if true_name in Options.option_types:
-                    self.option_names[name_node.name] = true_name
+            for name, name_node in node.items:
+                if (name in Options.option_types or 
+                        name in self.special_methods or
+                        PyrexTypes.parse_basic_type(name)):
+                    self.option_names[name_node.name] = name
                 else:
-                    newimp.append((true_name, name_node))
+                    newimp.append((name, name_node))
             if not newimp:
                 return None
             node.items = newimp
@@ -355,14 +360,7 @@ class InterpretCompilerDirectives(CythonTransform):
         optname = None
         if isinstance(node, CallNode):
             self.visit(node.function)
-            optname = node.function.magic_cython_method()
-#            if (isinstance(node.function, AttributeNode) and
-#                  isinstance(node.function.obj, NameNode) and
-#                  node.function.obj.name in self.cython_module_names):
-#                optname = node.function.attribute
-#            elif (isinstance(node.function, NameNode) and
-#                  node.function.name in self.option_names):
-#                optname = self.option_names[node.function.name]
+            optname = node.function.as_cython_attribute()
 
         if optname:
             optiontype = Options.option_types.get(optname)
@@ -714,11 +712,19 @@ class TransformBuiltinMethods(EnvTransform):
             return node
     
     def visit_AttributeNode(self, node):
-        attribute = node.magic_cython_method()
+        return self.visit_cython_attribute(node)
+
+    def visit_NameNode(self, node):
+        return self.visit_cython_attribute(node)
+        
+    def visit_cython_attribute(self, node):
+        attribute = node.as_cython_attribute()
         if attribute:
             if attribute == u'compiled':
                 node = BoolNode(node.pos, value=True)
-            else:
+            elif attribute == u'NULL':
+                node = NullNode(node.pos)
+            elif not PyrexTypes.parse_basic_type(attribute):
                 error(node.pos, u"'%s' not a valid cython attribute or is being used incorrectly" % attribute)
         return node
 
@@ -735,11 +741,11 @@ class TransformBuiltinMethods(EnvTransform):
                 return ExprNodes.DictNode(pos, key_value_pairs=items)
 
         # cython.foo
-        function = node.function.magic_cython_method()
+        function = node.function.as_cython_attribute()
         if function:
             if function == u'cast':
                 if len(node.args) != 2:
-                    error(node.function.pos, u"cast takes exactly two arguments" % function)
+                    error(node.function.pos, u"cast takes exactly two arguments")
                 else:
                     type = node.args[0].analyse_as_type(self.env_stack[-1])
                     if type:
index e51b0edc86829cda22f5025ee3d1694f2ddea78f..55ccc80df67d04657064f293228c6ca551f21273 100644 (file)
@@ -1251,6 +1251,7 @@ modifiers_and_name_to_type = {
     (2, 0, "Py_ssize_t"): c_py_ssize_t_type,
     
     (1, 0, "long"): c_long_type,
+    (1, 0, "short"): c_short_type,
     (1, 0, "longlong"): c_longlong_type,
     (1, 0, "bint"): c_bint_type,
 }
diff --git a/tests/run/pure.pyx b/tests/run/pure.pyx
new file mode 100644 (file)
index 0000000..b855036
--- /dev/null
@@ -0,0 +1,67 @@
+import sys, os
+sys.path.insert(0, "..")
+
+import cython
+
+
+def test_sizeof():
+    x = cython.declare(cython.bint)
+    print sizeof(x) == sizeof(cython.bint)
+    print sizeof(cython.char) <= sizeof(cython.short) <= sizeof(cython.int) <= sizeof(cython.long) <= sizeof(cython.longlong)
+    print sizeof(cython.uint) == sizeof(cython.int)
+    print sizeof(cython.p_int) == sizeof(cython.p_double)
+    if cython.compiled:
+        print sizeof(cython.char) < sizeof(cython.longlong)
+    else:
+        print sizeof(cython.char) == 1
+
+def test_declare(n):
+    x = cython.declare(cython.int)
+    y = cython.declare(cython.int, n)
+    if cython.compiled:
+        cython.declare(xx=cython.int, yy=cython.long)
+        sizeof(xx)
+    ptr = cython.declare(cython.p_int, cython.address(y))
+    return y, ptr[0]
+    
+@cython.locals(x=cython.double, n=cython.int)
+def test_cast(x):
+    n = cython.cast(cython.int, x)
+    return n
+    
+@cython.locals(x=cython.int, y=cython.p_int)
+def test_address(x):
+    y = cython.address(x)
+    return y[0]
+
+@cython.locals(x=cython.int, y=cython.bint)
+def test_locals(x):
+    y = x
+    return y
+    
+
+MyUnion = cython.union(n=cython.int, x=cython.double)
+MyStruct = cython.struct(is_integral=cython.bint, data=MyUnion)
+MyStruct2 = cython.typedef(MyStruct[2])
+
+def test_struct(n, x):
+    a = cython.declare(MyStruct2)
+    a[0] = MyStruct(True, data=MyUnion(n=n))
+    a[1] = MyStruct(is_integral=False, data={x: x})
+    return a[0].data.n, a[1].data.x
+
+import cython as cy
+from cython import declare, cast, locals, address, typedef, p_void, compiled
+from cython import declare as my_declare, locals as my_locals, p_void as my_void_star, typedef as my_typedef, my_compiled
+
+@my_locals(a=cython.p_void)
+def test_imports():
+    a = NULL
+    b = declare(p_void, NULL)
+    c = my_declare(my_void_star, NULL)
+    d = cy.declare(cy.p_void, NULL)
+    compiled and my_compiled
+
+MyStruct3 = typedef(MyStruct[3])
+MyStruct4 = my_typedef(MyStruct[4])
+MyStruct5 = cy.typedef(MyStruct[5])