1.1 --- a/lib/operator.py Sat Aug 07 02:06:15 2010 +0200
1.2 +++ b/lib/operator.py Mon Aug 09 01:23:05 2010 +0200
1.3 @@ -56,13 +56,64 @@
1.4
1.5 raise TypeError
1.6
1.7 -# Concrete operator functions.
1.8 +def unary_op(a, accessor):
1.9 +
1.10 + """
1.11 + A single parameterised function providing the unary operator mechanism for
1.12 + the argument 'a' using the given 'accessor' to provide the method for the
1.13 + operand.
1.14 + """
1.15 +
1.16 + # First, try and get a method for the argument, and then call it.
1.17 +
1.18 + try:
1.19 + fn = accessor(a)
1.20 + except AttributeError:
1.21 + pass
1.22 + else:
1.23 + result = fn()
1.24 + if result is not NotImplemented:
1.25 + return result
1.26 +
1.27 + # Where no method was available, or if the method could not support the
1.28 + # operation, raise an exception.
1.29 +
1.30 + raise TypeError
1.31 +
1.32 +def augassign(a, b, augmented_accessor, left_accessor, right_accessor):
1.33 +
1.34 + """
1.35 + A single parameterised function providing the augmented assignment mechanism
1.36 + for arguments 'a' and 'b' either using 'augmented_accessor' (directly
1.37 + affecting 'a') or using 'left_accessor' and 'right_accessor' (conventional
1.38 + operator method accessors).
1.39 +
1.40 + The result of the assignment is returned.
1.41 + """
1.42 +
1.43 + # First, try and get a method that directly affects the assignment target.
1.44 +
1.45 + try:
1.46 + fn = augmented_accessor(a)
1.47 + except AttributeError:
1.48 + pass
1.49 + else:
1.50 + result = fn(b)
1.51 + if result is not NotImplemented:
1.52 + return result
1.53 +
1.54 + # Otherwise, attempt a conventional binary operation.
1.55 +
1.56 + return binary_op(a, b, left_accessor, right_accessor)
1.57 +
1.58 # These functions defer method lookup by wrapping the attribute access in
1.59 # lambda functions. Thus, the appropriate methods are defined locally, but no
1.60 # attempt to obtain them is made until the generic function is called.
1.61
1.62 -# NOTE: The compiler should make it possible for these to call the generic
1.63 -# NOTE: operator implementation with no additional call overhead.
1.64 +# NOTE: The compiler should make it possible for the following functions to call
1.65 +# NOTE: the generic operator implementations with no additional call overhead.
1.66 +
1.67 +# Binary operator functions.
1.68
1.69 def add(a, b):
1.70 return binary_op(a, b, lambda a: a.__add__, lambda b: b.__radd__)
1.71 @@ -100,4 +151,73 @@
1.72 def xor(a, b):
1.73 return binary_op(a, b, lambda a: a.__xor__, lambda b: b.__rxor__)
1.74
1.75 +# Unary operator functions.
1.76 +
1.77 +def invert(a):
1.78 + return unary_op(a, lambda a: a.__invert__)
1.79 +
1.80 +def neg(a):
1.81 + return unary_op(a, lambda a: a.__neg__)
1.82 +
1.83 +def pos(a):
1.84 + return unary_op(a, lambda a: a.__pos__)
1.85 +
1.86 +# Augmented assignment functions.
1.87 +
1.88 +def iadd(a, b):
1.89 + return augassign(a, b, lambda a: a.__iadd__, lambda a: a.__add__, lambda b: b.__radd__)
1.90 +
1.91 +def iand_(a, b):
1.92 + return augassign(a, b, lambda a: a.__iand__, lambda a: a.__and__, lambda b: b.__rand__)
1.93 +
1.94 +def idiv(a, b):
1.95 + return augassign(a, b, lambda a: a.__idiv__, lambda a: a.__div__, lambda b: b.__rdiv__)
1.96 +
1.97 +def ifloordiv(a, b):
1.98 + return augassign(a, b, lambda a: a.__ifloordiv__, lambda a: a.__floordiv__, lambda b: b.__rfloordiv__)
1.99 +
1.100 +def ilshift(a, b):
1.101 + return augassign(a, b, lambda a: a.__ilshift__, lambda a: a.__lshift__, lambda b: b.__rlshift__)
1.102 +
1.103 +def imod(a, b):
1.104 + return augassign(a, b, lambda a: a.__imod__, lambda a: a.__mod__, lambda b: b.__rmod__)
1.105 +
1.106 +def imul(a, b):
1.107 + return augassign(a, b, lambda a: a.__imul__, lambda a: a.__mul__, lambda b: b.__rmul__)
1.108 +
1.109 +def ior_(a, b):
1.110 + return augassign(a, b, lambda a: a.__ior__, lambda a: a.__or__, lambda b: b.__ror__)
1.111 +
1.112 +def ipow(a, b):
1.113 + return augassign(a, b, lambda a: a.__ipow__, lambda a: a.__pow__, lambda b: b.__rpow__)
1.114 +
1.115 +def irshift(a, b):
1.116 + return augassign(a, b, lambda a: a.__irshift__, lambda a: a.__rshift__, lambda b: b.__rrshift__)
1.117 +
1.118 +def isub(a, b):
1.119 + return augassign(a, b, lambda a: a.__isub__, lambda a: a.__sub__, lambda b: b.__rsub__)
1.120 +
1.121 +def ixor(a, b):
1.122 + return augassign(a, b, lambda a: a.__ixor__, lambda a: a.__xor__, lambda b: b.__rxor__)
1.123 +
1.124 +# Comparison functions.
1.125 +
1.126 +def eq(a, b):
1.127 + return binary_op(a, b, lambda a: a.__eq__, lambda b: b.__eq__)
1.128 +
1.129 +def ge(a, b):
1.130 + return binary_op(a, b, lambda a: a.__ge__, lambda b: b.__le__)
1.131 +
1.132 +def gt(a, b):
1.133 + return binary_op(a, b, lambda a: a.__gt__, lambda b: b.__lt__)
1.134 +
1.135 +def le(a, b):
1.136 + return binary_op(a, b, lambda a: a.__le__, lambda b: b.__ge__)
1.137 +
1.138 +def lt(a, b):
1.139 + return binary_op(a, b, lambda a: a.__lt__, lambda b: b.__gt__)
1.140 +
1.141 +def ne(a, b):
1.142 + return binary_op(a, b, lambda a: a.__ne__, lambda b: b.__ne__)
1.143 +
1.144 # vim: tabstop=4 expandtab shiftwidth=4