From 88c3bd0414139523afefa8fadedf359a867e4884 Mon Sep 17 00:00:00 2001 From: Robert Bradshaw Date: Wed, 8 Oct 2008 14:35:54 -0700 Subject: [PATCH] pure mode enhancements, tests --- Cython/Compiler/ExprNodes.py | 13 +++-- Cython/Compiler/Nodes.py | 6 +-- Cython/Compiler/ParseTreeTransforms.py | 40 ++++++++------- Cython/Compiler/PyrexTypes.py | 1 + tests/run/pure.pyx | 67 ++++++++++++++++++++++++++ 5 files changed, 102 insertions(+), 25 deletions(-) create mode 100644 tests/run/pure.pyx diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py index f87d14f4..64668c99 100644 --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@ -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 diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py index a57252bf..4a1ea98f 100644 --- a/Cython/Compiler/Nodes.py +++ b/Cython/Compiler/Nodes.py @@ -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 diff --git a/Cython/Compiler/ParseTreeTransforms.py b/Cython/Compiler/ParseTreeTransforms.py index 94cf1681..a32c169a 100644 --- a/Cython/Compiler/ParseTreeTransforms.py +++ b/Cython/Compiler/ParseTreeTransforms.py @@ -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: diff --git a/Cython/Compiler/PyrexTypes.py b/Cython/Compiler/PyrexTypes.py index e51b0edc..55ccc80d 100644 --- a/Cython/Compiler/PyrexTypes.py +++ b/Cython/Compiler/PyrexTypes.py @@ -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 index 00000000..b8550364 --- /dev/null +++ b/tests/run/pure.pyx @@ -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]) -- 2.26.2