micropython

Annotated lib/operator.py

328:62c4e5c5a254
2010-06-05 Paul Boddie Fixed function name to avoid conflict with keyword.
paul@324 1
#!/usr/bin/env python
paul@324 2
paul@324 3
"""
paul@324 4
Operator support.
paul@324 5
paul@324 6
Copyright (C) 2010 Paul Boddie <paul@boddie.org.uk>
paul@324 7
paul@324 8
This program is free software; you can redistribute it and/or modify it under
paul@324 9
the terms of the GNU General Public License as published by the Free Software
paul@324 10
Foundation; either version 3 of the License, or (at your option) any later
paul@324 11
version.
paul@324 12
paul@324 13
This program is distributed in the hope that it will be useful, but WITHOUT
paul@324 14
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
paul@324 15
FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
paul@324 16
details.
paul@324 17
paul@324 18
You should have received a copy of the GNU General Public License along with
paul@324 19
this program.  If not, see <http://www.gnu.org/licenses/>.
paul@324 20
"""
paul@324 21
paul@325 22
def binary_op(a, b, left_accessor, right_accessor):
paul@324 23
paul@324 24
    """
paul@324 25
    A single parameterised function providing the binary operator mechanism for
paul@325 26
    arguments 'a' and 'b' using accessors given as 'left_accessor' and
paul@325 27
    'right_accessor' which provide the methods for the operands.
paul@324 28
    """
paul@324 29
paul@324 30
    # First, try and get a method for the left argument, and then call it with
paul@324 31
    # the right argument.
paul@324 32
paul@324 33
    try:
paul@325 34
        fn = left_accessor(a)
paul@324 35
    except AttributeError:
paul@324 36
        pass
paul@324 37
    else:
paul@324 38
        result = fn(b)
paul@324 39
        if result is not NotImplemented:
paul@324 40
            return result
paul@324 41
paul@324 42
    # Otherwise, try and get a method for the right argument, and then call it
paul@324 43
    # with the left argument.
paul@324 44
paul@324 45
    try:
paul@325 46
        fn = right_accessor(b)
paul@324 47
    except AttributeError:
paul@324 48
        pass
paul@324 49
    else:
paul@324 50
        result = fn(a)
paul@324 51
        if result is not NotImplemented:
paul@324 52
            return result
paul@324 53
paul@324 54
    # Where no methods were available, or if neither method could support the
paul@324 55
    # operation, raise an exception.
paul@324 56
paul@324 57
    raise TypeError
paul@324 58
paul@325 59
# Concrete operator functions.
paul@325 60
# These functions defer method lookup by wrapping the attribute access in
paul@325 61
# lambda functions. Thus, the appropriate methods are defined locally, but no
paul@325 62
# attempt to obtain them is made until the generic function is called.
paul@325 63
paul@325 64
# NOTE: The compiler should make it possible for these to call the generic
paul@325 65
# NOTE: operator implementation with no additional call overhead.
paul@325 66
paul@324 67
def add(a, b):
paul@325 68
    return binary_op(a, b, lambda a: a.__add__, lambda b: b.__radd__)
paul@324 69
paul@324 70
def and_(a, b):
paul@325 71
    return binary_op(a, b, lambda a: a.__and__, lambda b: b.__rand__)
paul@324 72
paul@324 73
def div(a, b):
paul@325 74
    return binary_op(a, b, lambda a: a.__div__, lambda b: b.__rdiv__)
paul@324 75
paul@324 76
def floordiv(a, b):
paul@325 77
    return binary_op(a, b, lambda a: a.__floordiv__, lambda b: b.__rfloordiv__)
paul@324 78
paul@324 79
def lshift(a, b):
paul@325 80
    return binary_op(a, b, lambda a: a.__lshift__, lambda b: b.__rlshift__)
paul@324 81
paul@324 82
def mod(a, b):
paul@325 83
    return binary_op(a, b, lambda a: a.__mod__, lambda b: b.__rmod__)
paul@324 84
paul@324 85
def mul(a, b):
paul@325 86
    return binary_op(a, b, lambda a: a.__mul__, lambda b: b.__rmul__)
paul@324 87
paul@328 88
def or_(a, b):
paul@325 89
    return binary_op(a, b, lambda a: a.__or__, lambda b: b.__ror__)
paul@324 90
paul@324 91
def pow(a, b):
paul@325 92
    return binary_op(a, b, lambda a: a.__pow__, lambda b: b.__rpow__)
paul@324 93
paul@324 94
def rshift(a, b):
paul@325 95
    return binary_op(a, b, lambda a: a.__rshift__, lambda b: b.__rrshift__)
paul@324 96
paul@324 97
def sub(a, b):
paul@325 98
    return binary_op(a, b, lambda a: a.__sub__, lambda b: b.__rsub__)
paul@324 99
paul@324 100
def xor(a, b):
paul@325 101
    return binary_op(a, b, lambda a: a.__xor__, lambda b: b.__rxor__)
paul@324 102
paul@324 103
# vim: tabstop=4 expandtab shiftwidth=4