Commit 67df43bf authored by Meador Inge's avatar Meador Inge Committed by Dylan Trotter

Finished implementing unary minus (#61)

This patch finishes implementing support for unary minus.
The slot and core dispatch functions were already there,
but the individual numeric slot implementations were missing.
parent 8460de18
......@@ -774,7 +774,7 @@ func ToStr(f *Frame, o *Object) (*Str, *BaseException) {
func Neg(f *Frame, o *Object) (*Object, *BaseException) {
neg := o.typ.slots.Neg
if neg == nil {
return nil, f.RaiseType(TypeErrorType, fmt.Sprintf("bad operand type for unary ~: '%s'", o.typ.Name()))
return nil, f.RaiseType(TypeErrorType, fmt.Sprintf("bad operand type for unary -: '%s'", o.typ.Name()))
}
return neg.Fn(f, o)
}
......
......@@ -512,6 +512,20 @@ func TestIter(t *testing.T) {
}
}
func TestNeg(t *testing.T) {
cases := []invokeTestCase{
{args: wrapArgs(42), want: NewInt(-42).ToObject()},
{args: wrapArgs(1.2), want: NewFloat(-1.2).ToObject()},
{args: wrapArgs(NewLong(big.NewInt(123))), want: NewLong(big.NewInt(-123)).ToObject()},
{args: wrapArgs("foo"), wantExc: mustCreateException(TypeErrorType, "bad operand type for unary -: 'str'")},
}
for _, cas := range cases {
if err := runInvokeTestCase(wrapFuncForTest(Neg), &cas); err != "" {
t.Error(err)
}
}
}
func TestNext(t *testing.T) {
fun := newBuiltinFunction("TestNext", func(f *Frame, args Args, _ KWArgs) (*Object, *BaseException) {
if argc := len(args); argc != 1 {
......
......@@ -143,6 +143,11 @@ func floatNE(f *Frame, v, w *Object) (*Object, *BaseException) {
return floatCompare(toFloatUnsafe(v), w, True, False, True), nil
}
func floatNeg(f *Frame, o *Object) (*Object, *BaseException) {
z := toFloatUnsafe(o).Value()
return NewFloat(-z).ToObject(), nil
}
func floatNew(f *Frame, t *Type, args Args, _ KWArgs) (*Object, *BaseException) {
argc := len(args)
if argc == 0 {
......@@ -241,6 +246,7 @@ func initFloatType(dict map[string]*Object) {
FloatType.slots.Mul = &binaryOpSlot{floatMul}
FloatType.slots.Native = &nativeSlot{floatNative}
FloatType.slots.NE = &binaryOpSlot{floatNE}
FloatType.slots.Neg = &unaryOpSlot{floatNeg}
FloatType.slots.New = &newSlot{floatNew}
FloatType.slots.NonZero = &unaryOpSlot{floatNonZero}
FloatType.slots.RAdd = &binaryOpSlot{floatRAdd}
......
......@@ -71,11 +71,7 @@ func intAbs(f *Frame, o *Object) (*Object, *BaseException) {
if z.Value() > 0 {
return z.ToObject(), nil
}
if z.Value() == MinInt {
nz := big.NewInt(int64(z.Value()))
return NewLong(nz.Neg(nz)).ToObject(), nil
}
return NewInt(-z.Value()).ToObject(), nil
return intNeg(f, o)
}
func intAdd(f *Frame, v, w *Object) (*Object, *BaseException) {
......@@ -168,6 +164,15 @@ func intNE(f *Frame, v, w *Object) (*Object, *BaseException) {
return intCompare(compareOpNE, toIntUnsafe(v), w), nil
}
func intNeg(f *Frame, o *Object) (*Object, *BaseException) {
z := toIntUnsafe(o)
if z.Value() == MinInt {
nz := big.NewInt(int64(z.Value()))
return NewLong(nz.Neg(nz)).ToObject(), nil
}
return NewInt(-z.Value()).ToObject(), nil
}
func intNew(f *Frame, t *Type, args Args, _ KWArgs) (*Object, *BaseException) {
if len(args) == 0 {
return newObject(t), nil
......@@ -319,6 +324,7 @@ func initIntType(dict map[string]*Object) {
IntType.slots.Mul = &binaryOpSlot{intMul}
IntType.slots.Native = &nativeSlot{intNative}
IntType.slots.NE = &binaryOpSlot{intNE}
IntType.slots.Neg = &unaryOpSlot{intNeg}
IntType.slots.New = &newSlot{intNew}
IntType.slots.NonZero = &unaryOpSlot{intNonZero}
IntType.slots.Or = &binaryOpSlot{intOr}
......
......@@ -200,6 +200,10 @@ func longNE(x, y *big.Int) bool {
return x.Cmp(y) != 0
}
func longNeg(z, x *big.Int) {
z.Neg(x)
}
func longNew(f *Frame, t *Type, args Args, _ KWArgs) (*Object, *BaseException) {
if t != LongType {
// Allocate a plain long and then copy its value into an
......@@ -323,6 +327,7 @@ func initLongType(dict map[string]*Object) {
LongType.slots.Mul = longBinaryOpSlot(longMul)
LongType.slots.Native = &nativeSlot{longNative}
LongType.slots.NE = longBinaryBoolOpSlot(longNE)
LongType.slots.Neg = longUnaryOpSlot(longNeg)
LongType.slots.New = &newSlot{longNew}
LongType.slots.NonZero = longUnaryBoolOpSlot(longNonZero)
LongType.slots.Or = longBinaryOpSlot(longOr)
......
......@@ -14,6 +14,7 @@
"""Arithmetic and boolean operator tests."""
from __go__.math import IsNaN, IsInf
import weetest
......@@ -56,5 +57,28 @@ def TestBoolOpsLazyEval():
assert ran == ['Yes']
def TestNeg():
x = 12
assert -x == -12
x = 1.1
assert -x == -1.1
x = 0.0
assert -x == -0.0
x = float('inf')
assert IsInf(-x, -1)
x = -float('inf')
assert IsInf(-x, 1)
x = float('nan')
assert IsNaN(-x)
x = long(100)
assert -x == -100
if __name__ == '__main__':
weetest.RunTests()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment