From 532074a24c9e1c0d6e049eaffa76cbedfa6c2b4a Mon Sep 17 00:00:00 2001 From: Robert Bradshaw Date: Thu, 26 Aug 2010 00:20:49 -0700 Subject: [PATCH] support for comma operator --- Cython/Compiler/ExprNodes.py | 22 ++++++++++++++++++++++ Cython/Compiler/ParseTreeTransforms.py | 11 ++++++++++- Cython/Compiler/Parsing.py | 5 ++--- tests/run/cpp_operators.pyx | 4 ++++ tests/run/cpp_operators_helper.h | 3 +++ 5 files changed, 41 insertions(+), 4 deletions(-) diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py index c635d668..549779b7 100755 --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@ -5279,6 +5279,28 @@ class BinopNode(ExprNode): self.type = PyrexTypes.error_type +class CBinopNode(BinopNode): + + def analyse_types(self, env): + BinopNode.analyse_types(self, env) + if self.is_py_operation(): + self.type = PyrexTypes.error_type + + def py_operation_function(): + return "" + + def calculate_result_code(self): + return "(%s %s %s)" % ( + self.operand1.result(), + self.operator, + self.operand2.result()) + + +def c_binop_constructor(operator): + def make_binop_node(pos, **operands): + return CBinopNode(pos, operator=operator, **operands) + return make_binop_node + class NumBinopNode(BinopNode): # Binary operation taking numeric arguments. diff --git a/Cython/Compiler/ParseTreeTransforms.py b/Cython/Compiler/ParseTreeTransforms.py index 64c29a0c..fccba177 100644 --- a/Cython/Compiler/ParseTreeTransforms.py +++ b/Cython/Compiler/ParseTreeTransforms.py @@ -577,10 +577,14 @@ class InterpretCompilerDirectives(CythonTransform, SkipDeclarations): 'operator.predecrement' : inc_dec_constructor(True, '--'), 'operator.postincrement': inc_dec_constructor(False, '++'), 'operator.postdecrement': inc_dec_constructor(False, '--'), - + # For backwards compatability. 'address': AmpersandNode, } + + binop_method_nodes = { + 'operator.comma' : c_binop_constructor(','), + } special_methods = set(['declare', 'union', 'struct', 'typedef', 'sizeof', 'cast', 'pointer', 'compiled', 'NULL'] @@ -1385,6 +1389,11 @@ class TransformBuiltinMethods(EnvTransform): error(node.function.pos, u"%s() takes exactly one argument" % function) else: node = InterpretCompilerDirectives.unop_method_nodes[function](node.function.pos, operand=node.args[0]) + elif function in InterpretCompilerDirectives.binop_method_nodes: + if len(node.args) != 2: + error(node.function.pos, u"%s() takes exactly two arguments" % function) + else: + node = InterpretCompilerDirectives.binop_method_nodes[function](node.function.pos, operand1=node.args[0], operand2=node.args[1]) elif function == u'cast': if len(node.args) != 2: error(node.function.pos, u"cast() takes exactly two arguments") diff --git a/Cython/Compiler/Parsing.py b/Cython/Compiler/Parsing.py index 7b853018..35f92d1c 100644 --- a/Cython/Compiler/Parsing.py +++ b/Cython/Compiler/Parsing.py @@ -2056,7 +2056,7 @@ def p_c_func_declarator(s, pos, ctx, base, cmethod_flag): supported_overloaded_operators = cython.set([ '+', '-', '*', '/', '%', - '++', '--', '~', '|', '&', '^', '<<', '>>', + '++', '--', '~', '|', '&', '^', '<<', '>>', ',', '==', '!=', '>=', '>', '<=', '<', '[]', '()', ]) @@ -2102,12 +2102,11 @@ def p_c_simple_declarator(s, ctx, empty, is_type, cmethod_flag, error(s.position(), "Empty declarator") name = "" cname = None - print pos, ctx.__dict__ if cname is None and ctx.namespace is not None: cname = ctx.namespace + "::" + name if name == 'operator' and ctx.visibility == 'extern' and nonempty: op = s.sy - if op in '+-*/<=>!%&|([^~,': + if [c in '+-*/<=>!%&|([^~,' for c in op]: s.next() # Handle diphthong operators. if op == '(': diff --git a/tests/run/cpp_operators.pyx b/tests/run/cpp_operators.pyx index 9487dd45..1b782486 100644 --- a/tests/run/cpp_operators.pyx +++ b/tests/run/cpp_operators.pyx @@ -26,6 +26,7 @@ cdef extern from "cpp_operators_helper.h": char* operator|(int) char* operator&(int) char* operator^(int) + char* operator,(int) char* operator<<(int) char* operator>>(int) @@ -83,6 +84,7 @@ def test_binop(): binary ^ binary << binary >> + binary COMMA """ cdef TestOps* t = new TestOps() out(t[0] + 1) @@ -97,6 +99,8 @@ def test_binop(): out(t[0] << 1) out(t[0] >> 1) + + out(cython.operator.comma(t[0], 1)) del t def test_cmp(): diff --git a/tests/run/cpp_operators_helper.h b/tests/run/cpp_operators_helper.h index b8372f27..231f4868 100644 --- a/tests/run/cpp_operators_helper.h +++ b/tests/run/cpp_operators_helper.h @@ -2,6 +2,8 @@ #define POST_UN_OP(op) const char* operator op (int x) { return "post "#op; } #define BIN_OP(op) const char* operator op (int x) { return "binary "#op; } +#define COMMA , + class TestOps { public: @@ -30,6 +32,7 @@ public: BIN_OP(|); BIN_OP(&); BIN_OP(^); + BIN_OP(COMMA); BIN_OP(==); BIN_OP(!=); -- 2.26.2