Commits

Carl Friedrich Bolz committed e53aa4a

implement unary plus and unary minus

Comments (0)

Files changed (3)

prolog/interpreter/arithmetic.py

 # remove unneeded parts, use sane names for operations
 simple_functions = [
     ("+", 2, "add"),
+    ("+", 1, "unaryadd"),
     ("-", 2, "sub"),
+    ("-", 1, "unarysub"),
     ("*", 2, "mul"),
     ("/", 2, "div"),
     ("//", 2, "floordiv"),
     def arith_add_float(self, other_float):
         return term.Float(other_float + float(self.num))
 
+    def arith_unaryadd(self):
+        return self
+
     # ------------------ subtraction ------------------ 
     def arith_sub(self, other):
         return other.arith_sub_number(self.num)
     def arith_sub_float(self, other_float):
         return term.Float(other_float - float(self.num))
 
+    def arith_unarysub(self):
+        try:
+            res = rarithmetic.ovfcheck(-self.num)
+        except OverflowError:
+            return term.BigInt(rbigint.fromint(self.num).neg())
+        return term.Number(res)
+
+
     # ------------------ multiplication ------------------ 
     def arith_mul(self, other):
         return other.arith_mul_number(self.num)
     def arith_add_float(self, other_float):
         return term.Float(other_float + self.floatval)
 
+    def arith_unaryadd(self):
+        return self
+
     # ------------------ subtraction ------------------ 
     def arith_sub(self, other):
         return other.arith_sub_float(self.floatval)
     def arith_sub_float(self, other_float):
         return term.Float(other_float - self.floatval)
 
+    def arith_unarysub(self):
+        return term.Float(-self.floatval)
+
     # ------------------ multiplication ------------------ 
     def arith_mul(self, other):
         return other.arith_mul_float(self.floatval)
     def arith_add_float(self, other_float):
         return term.Float(other_float + self.value.tofloat())
 
+    def arith_unaryadd(self):
+        return self
+
     # ------------------ subtraction ------------------ 
     def arith_sub(self, other):
         return other.arith_sub_bigint(self.value)
     def arith_sub_float(self, other_float):
         return term.Float(other_float - self.value.tofloat())
 
+    def arith_unarysub(self):
+        return term.BigInt(self.value.neg())
+
     # ------------------ multiplication ------------------ 
     def arith_mul(self, other):
         return other.arith_mul_bigint(self.value)

prolog/interpreter/term.py

 class Numeric(NonVar):
     __slots__ = ()
 
+    def eval_arithmetic(self, engine):
+        return self
+
+
 class Number(Numeric):#, UnboxedValue):
     TYPE_STANDARD_ORDER = 1
     __slots__ = ("num", )
     def __repr__(self):
         return "Number(%r)" % (self.num, )
     
-    def eval_arithmetic(self, engine):
-        return self
-    
     def cmp_standard_order(self, other, heap):
         # XXX looks a bit terrible
         if isinstance(other, Number):

prolog/interpreter/test/test_arithmetic.py

     assert_true("X is 100 ** 0.0, X = 1.0.")
     assert_true("X is 0 ** 0, X = 1.")
 
+    assert_true("X = 3, Y is +X, Y == 3.")
+    assert_true("X = 3.1, Y is +X, Y == 3.1.")
+
+    assert_true("X = -3, Y is -X, Y == 3.")
+    assert_true("X = -3.1, Y is -X, Y == 3.1.")
+    assert_true("X = %s, Y is -X, Y == %s." % (-sys.maxint-1, sys.maxint + 1))
+
 def test_comparison():
     assert_true("1 =:= 1.0.")
     assert_true("1 + 1 > 1.")