Lichen

Annotated lib/operator/augmented.py

955:db49ed1bde3b
2021-11-09 Paul Boddie Avoid making general expressions immutable as arguments. tagged-address-values
paul@6 1
#!/usr/bin/env python
paul@6 2
paul@6 3
"""
paul@6 4
Operator support.
paul@6 5
paul@873 6
Copyright (C) 2010, 2013, 2015, 2017, 2019 Paul Boddie <paul@boddie.org.uk>
paul@6 7
paul@6 8
This program is free software; you can redistribute it and/or modify it under
paul@6 9
the terms of the GNU General Public License as published by the Free Software
paul@6 10
Foundation; either version 3 of the License, or (at your option) any later
paul@6 11
version.
paul@6 12
paul@6 13
This program is distributed in the hope that it will be useful, but WITHOUT
paul@6 14
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
paul@6 15
FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
paul@6 16
details.
paul@6 17
paul@6 18
You should have received a copy of the GNU General Public License along with
paul@6 19
this program.  If not, see <http://www.gnu.org/licenses/>.
paul@6 20
"""
paul@6 21
paul@6 22
from operator.core import augassign
paul@762 23
from native import int_add, int_div, int_mod, int_mul, int_pow, int_sub, \
paul@762 24
                   int_and, int_or, int_xor, \
paul@873 25
                   is_int, \
paul@873 26
                   float_add, float_div, float_mul, float_pow, float_sub
paul@6 27
paul@6 28
# These functions defer method lookup by wrapping the attribute access in
paul@6 29
# lambda functions. Thus, the appropriate methods are defined locally, but no
paul@6 30
# attempt to obtain them is made until the generic function is called.
paul@6 31
paul@6 32
# NOTE: The compiler should make it possible for the following functions to call
paul@6 33
# NOTE: the generic operator implementations with no additional call overhead.
paul@6 34
paul@6 35
# Augmented assignment functions.
paul@6 36
paul@6 37
def iadd(a, b):
paul@762 38
    if is_int(a) and is_int(b):
paul@762 39
        return int_add(a, b)
paul@873 40
    elif a.__class__ is float and b.__class__ is float:
paul@873 41
        return float_add(a, b)
paul@6 42
    return augassign(a, b, lambda a: a.__iadd__, lambda a: a.__add__, lambda b: b.__radd__)
paul@6 43
paul@6 44
def iand_(a, b):
paul@762 45
    if is_int(a) and is_int(b):
paul@762 46
        return int_and(a, b)
paul@6 47
    return augassign(a, b, lambda a: a.__iand__, lambda a: a.__and__, lambda b: b.__rand__)
paul@6 48
paul@6 49
def idiv(a, b):
paul@762 50
    if is_int(a) and is_int(b):
paul@762 51
        return int_div(a, b)
paul@873 52
    elif a.__class__ is float and b.__class__ is float:
paul@873 53
        return float_div(a, b)
paul@6 54
    return augassign(a, b, lambda a: a.__idiv__, lambda a: a.__div__, lambda b: b.__rdiv__)
paul@6 55
paul@6 56
def ifloordiv(a, b):
paul@6 57
    return augassign(a, b, lambda a: a.__ifloordiv__, lambda a: a.__floordiv__, lambda b: b.__rfloordiv__)
paul@6 58
paul@6 59
def ilshift(a, b):
paul@6 60
    return augassign(a, b, lambda a: a.__ilshift__, lambda a: a.__lshift__, lambda b: b.__rlshift__)
paul@6 61
paul@6 62
def imod(a, b):
paul@762 63
    if is_int(a) and is_int(b):
paul@762 64
        return int_mod(a, b)
paul@6 65
    return augassign(a, b, lambda a: a.__imod__, lambda a: a.__mod__, lambda b: b.__rmod__)
paul@6 66
paul@6 67
def imul(a, b):
paul@762 68
    if is_int(a) and is_int(b):
paul@762 69
        return int_mul(a, b)
paul@873 70
    elif a.__class__ is float and b.__class__ is float:
paul@873 71
        return float_mul(a, b)
paul@6 72
    return augassign(a, b, lambda a: a.__imul__, lambda a: a.__mul__, lambda b: b.__rmul__)
paul@6 73
paul@6 74
def ior_(a, b):
paul@762 75
    if is_int(a) and is_int(b):
paul@762 76
        return int_or(a, b)
paul@6 77
    return augassign(a, b, lambda a: a.__ior__, lambda a: a.__or__, lambda b: b.__ror__)
paul@6 78
paul@6 79
def ipow(a, b):
paul@762 80
    if is_int(a) and is_int(b):
paul@762 81
        return int_pow(a, b)
paul@873 82
    elif a.__class__ is float and b.__class__ is float:
paul@873 83
        return float_pow(a, b)
paul@6 84
    return augassign(a, b, lambda a: a.__ipow__, lambda a: a.__pow__, lambda b: b.__rpow__)
paul@6 85
paul@6 86
def irshift(a, b):
paul@6 87
    return augassign(a, b, lambda a: a.__irshift__, lambda a: a.__rshift__, lambda b: b.__rrshift__)
paul@6 88
paul@6 89
def isub(a, b):
paul@762 90
    if is_int(a) and is_int(b):
paul@762 91
        return int_sub(a, b)
paul@873 92
    elif a.__class__ is float and b.__class__ is float:
paul@873 93
        return float_sub(a, b)
paul@6 94
    return augassign(a, b, lambda a: a.__isub__, lambda a: a.__sub__, lambda b: b.__rsub__)
paul@6 95
paul@6 96
def ixor(a, b):
paul@762 97
    if is_int(a) and is_int(b):
paul@762 98
        return int_xor(a, b)
paul@6 99
    return augassign(a, b, lambda a: a.__ixor__, lambda a: a.__xor__, lambda b: b.__rxor__)
paul@6 100
paul@6 101
# vim: tabstop=4 expandtab shiftwidth=4