Commit 53a6dfb9 authored by Dong-hee Na's avatar Dong-hee Na Committed by Dylan Trotter

Implement floordiv and implement 'NotImplement.__repr__'. (#270)

parent b9a0c8a9
...@@ -24,3 +24,4 @@ Contributors in the order of first contribution ...@@ -24,3 +24,4 @@ Contributors in the order of first contribution
* [wuttem](https://github.com/wuttem) * [wuttem](https://github.com/wuttem)
* [cclauss](https://github.com/cclauss) * [cclauss](https://github.com/cclauss)
* [Mirko Dziadzka](https://github.com/MirkoDziadzka) * [Mirko Dziadzka](https://github.com/MirkoDziadzka)
* [Dong-hee Na](https://github.com/corona10)
...@@ -58,6 +58,10 @@ func noneRepr(*Frame, *Object) (*Object, *BaseException) { ...@@ -58,6 +58,10 @@ func noneRepr(*Frame, *Object) (*Object, *BaseException) {
return NewStr("None").ToObject(), nil return NewStr("None").ToObject(), nil
} }
func notImplementedRepr(*Frame, *Object) (*Object, *BaseException) {
return NewStr("NotImplemented").ToObject(), nil
}
func initEllipsisType(map[string]*Object) { func initEllipsisType(map[string]*Object) {
EllipsisType.flags &= ^(typeFlagInstantiable | typeFlagBasetype) EllipsisType.flags &= ^(typeFlagInstantiable | typeFlagBasetype)
EllipsisType.slots.Repr = &unaryOpSlot{ellipsisRepr} EllipsisType.slots.Repr = &unaryOpSlot{ellipsisRepr}
...@@ -70,6 +74,7 @@ func initNoneType(map[string]*Object) { ...@@ -70,6 +74,7 @@ func initNoneType(map[string]*Object) {
func initNotImplementedType(map[string]*Object) { func initNotImplementedType(map[string]*Object) {
NotImplementedType.flags &= ^(typeFlagInstantiable | typeFlagBasetype) NotImplementedType.flags &= ^(typeFlagInstantiable | typeFlagBasetype)
NotImplementedType.slots.Repr = &unaryOpSlot{notImplementedRepr}
} }
func initUnboundLocalType(map[string]*Object) { func initUnboundLocalType(map[string]*Object) {
......
...@@ -360,6 +360,13 @@ func TestNoneRepr(t *testing.T) { ...@@ -360,6 +360,13 @@ func TestNoneRepr(t *testing.T) {
} }
} }
func TestNotImplementedRepr(t *testing.T) {
cas := invokeTestCase{args: wrapArgs(NotImplemented), want: NewStr("NotImplemented").ToObject()}
if err := runInvokeMethodTestCase(NotImplementedType, "__repr__", &cas); err != "" {
t.Error(err)
}
}
// captureStdout invokes a function closure which writes to stdout and captures // captureStdout invokes a function closure which writes to stdout and captures
// its output as string. // its output as string.
func captureStdout(f *Frame, fn func() *BaseException) (string, *BaseException) { func captureStdout(f *Frame, fn func() *BaseException) (string, *BaseException) {
......
...@@ -177,6 +177,11 @@ func Eq(f *Frame, v, w *Object) (*Object, *BaseException) { ...@@ -177,6 +177,11 @@ func Eq(f *Frame, v, w *Object) (*Object, *BaseException) {
return GetBool(compareDefault(f, v, w) == 0).ToObject(), nil return GetBool(compareDefault(f, v, w) == 0).ToObject(), nil
} }
// FloorDiv returns the equality of v and w according to the __floordiv/rfloordiv__ operator.
func FloorDiv(f *Frame, v, w *Object) (*Object, *BaseException) {
return binaryOp(f, v, w, v.typ.slots.FloorDiv, v.typ.slots.RFloorDiv, w.typ.slots.RFloorDiv, "//")
}
// FormatException returns a single-line exception string for the given // FormatException returns a single-line exception string for the given
// exception object, e.g. "NameError: name 'x' is not defined\n". // exception object, e.g. "NameError: name 'x' is not defined\n".
func FormatException(f *Frame, e *BaseException) (string, *BaseException) { func FormatException(f *Frame, e *BaseException) (string, *BaseException) {
......
...@@ -89,6 +89,15 @@ func floatFloat(f *Frame, o *Object) (*Object, *BaseException) { ...@@ -89,6 +89,15 @@ func floatFloat(f *Frame, o *Object) (*Object, *BaseException) {
return o, nil return o, nil
} }
func floatFloorDiv(f *Frame, v, w *Object) (*Object, *BaseException) {
return floatDivModOp(f, "__floordiv__", v, w, func(v, w float64) (float64, bool) {
if w == 0.0 {
return 0, false
}
return math.Floor(v / w), true
})
}
func floatGE(f *Frame, v, w *Object) (*Object, *BaseException) { func floatGE(f *Frame, v, w *Object) (*Object, *BaseException) {
return floatCompare(toFloatUnsafe(v), w, False, True, True), nil return floatCompare(toFloatUnsafe(v), w, False, True, True), nil
} }
...@@ -258,6 +267,15 @@ func floatRepr(f *Frame, o *Object) (*Object, *BaseException) { ...@@ -258,6 +267,15 @@ func floatRepr(f *Frame, o *Object) (*Object, *BaseException) {
return NewStr(strconv.FormatFloat(toFloatUnsafe(o).Value(), 'g', -1, 64)).ToObject(), nil return NewStr(strconv.FormatFloat(toFloatUnsafe(o).Value(), 'g', -1, 64)).ToObject(), nil
} }
func floatRFloorDiv(f *Frame, v, w *Object) (*Object, *BaseException) {
return floatDivModOp(f, "__rfloordiv__", v, w, func(v, w float64) (float64, bool) {
if v == 0.0 {
return 0, false
}
return math.Floor(w / v), true
})
}
func floatRMod(f *Frame, v, w *Object) (*Object, *BaseException) { func floatRMod(f *Frame, v, w *Object) (*Object, *BaseException) {
return floatDivModOp(f, "__rmod__", v, w, func(v, w float64) (float64, bool) { return floatDivModOp(f, "__rmod__", v, w, func(v, w float64) (float64, bool) {
return floatModFunc(w, v) return floatModFunc(w, v)
...@@ -288,6 +306,7 @@ func initFloatType(dict map[string]*Object) { ...@@ -288,6 +306,7 @@ func initFloatType(dict map[string]*Object) {
FloatType.slots.DivMod = &binaryOpSlot{floatDivMod} FloatType.slots.DivMod = &binaryOpSlot{floatDivMod}
FloatType.slots.Eq = &binaryOpSlot{floatEq} FloatType.slots.Eq = &binaryOpSlot{floatEq}
FloatType.slots.Float = &unaryOpSlot{floatFloat} FloatType.slots.Float = &unaryOpSlot{floatFloat}
FloatType.slots.FloorDiv = &binaryOpSlot{floatFloorDiv}
FloatType.slots.GE = &binaryOpSlot{floatGE} FloatType.slots.GE = &binaryOpSlot{floatGE}
FloatType.slots.GT = &binaryOpSlot{floatGT} FloatType.slots.GT = &binaryOpSlot{floatGT}
FloatType.slots.Hash = &unaryOpSlot{floatHash} FloatType.slots.Hash = &unaryOpSlot{floatHash}
...@@ -308,6 +327,7 @@ func initFloatType(dict map[string]*Object) { ...@@ -308,6 +327,7 @@ func initFloatType(dict map[string]*Object) {
FloatType.slots.RDiv = &binaryOpSlot{floatRDiv} FloatType.slots.RDiv = &binaryOpSlot{floatRDiv}
FloatType.slots.RDivMod = &binaryOpSlot{floatRDivMod} FloatType.slots.RDivMod = &binaryOpSlot{floatRDivMod}
FloatType.slots.Repr = &unaryOpSlot{floatRepr} FloatType.slots.Repr = &unaryOpSlot{floatRepr}
FloatType.slots.RFloorDiv = &binaryOpSlot{floatRFloorDiv}
FloatType.slots.RMod = &binaryOpSlot{floatRMod} FloatType.slots.RMod = &binaryOpSlot{floatRMod}
FloatType.slots.RMul = &binaryOpSlot{floatRMul} FloatType.slots.RMul = &binaryOpSlot{floatRMul}
FloatType.slots.RPow = &binaryOpSlot{floatRPow} FloatType.slots.RPow = &binaryOpSlot{floatRPow}
......
...@@ -60,6 +60,16 @@ func TestFloatArithmeticOps(t *testing.T) { ...@@ -60,6 +60,16 @@ func TestFloatArithmeticOps(t *testing.T) {
{Div, True.ToObject(), NewFloat(0).ToObject(), nil, mustCreateException(ZeroDivisionErrorType, "float division or modulo by zero")}, {Div, True.ToObject(), NewFloat(0).ToObject(), nil, mustCreateException(ZeroDivisionErrorType, "float division or modulo by zero")},
{Div, NewFloat(math.Inf(1)).ToObject(), NewFloat(0).ToObject(), nil, mustCreateException(ZeroDivisionErrorType, "float division or modulo by zero")}, {Div, NewFloat(math.Inf(1)).ToObject(), NewFloat(0).ToObject(), nil, mustCreateException(ZeroDivisionErrorType, "float division or modulo by zero")},
{Div, NewFloat(1.0).ToObject(), NewLong(bigLongNumber).ToObject(), nil, mustCreateException(OverflowErrorType, "long int too large to convert to float")}, {Div, NewFloat(1.0).ToObject(), NewLong(bigLongNumber).ToObject(), nil, mustCreateException(OverflowErrorType, "long int too large to convert to float")},
{FloorDiv, NewFloat(12.5).ToObject(), NewFloat(4).ToObject(), NewFloat(3).ToObject(), nil},
{FloorDiv, NewFloat(-12.5).ToObject(), NewInt(4).ToObject(), NewFloat(-4).ToObject(), nil},
{FloorDiv, NewInt(25).ToObject(), NewFloat(5).ToObject(), NewFloat(5.0).ToObject(), nil},
{FloorDiv, NewFloat(math.Inf(1)).ToObject(), NewFloat(math.Inf(1)).ToObject(), NewFloat(math.NaN()).ToObject(), nil},
{FloorDiv, NewFloat(math.Inf(-1)).ToObject(), NewInt(-20).ToObject(), NewFloat(math.Inf(1)).ToObject(), nil},
{FloorDiv, NewInt(1).ToObject(), NewFloat(math.Inf(1)).ToObject(), NewFloat(0).ToObject(), nil},
{FloorDiv, newObject(ObjectType), NewFloat(1.1).ToObject(), nil, mustCreateException(TypeErrorType, "unsupported operand type(s) for //: 'object' and 'float'")},
{FloorDiv, NewFloat(1.0).ToObject(), NewLong(bigLongNumber).ToObject(), nil, mustCreateException(OverflowErrorType, "long int too large to convert to float")},
{FloorDiv, True.ToObject(), NewFloat(0).ToObject(), nil, mustCreateException(ZeroDivisionErrorType, "float division or modulo by zero")},
{FloorDiv, NewFloat(math.Inf(1)).ToObject(), NewFloat(0).ToObject(), nil, mustCreateException(ZeroDivisionErrorType, "float division or modulo by zero")},
{Mod, NewFloat(50.5).ToObject(), NewInt(10).ToObject(), NewFloat(0.5).ToObject(), nil}, {Mod, NewFloat(50.5).ToObject(), NewInt(10).ToObject(), NewFloat(0.5).ToObject(), nil},
{Mod, NewFloat(50.5).ToObject(), NewFloat(-10).ToObject(), NewFloat(-9.5).ToObject(), nil}, {Mod, NewFloat(50.5).ToObject(), NewFloat(-10).ToObject(), NewFloat(-9.5).ToObject(), nil},
{Mod, NewFloat(-20.2).ToObject(), NewFloat(40).ToObject(), NewFloat(19.8).ToObject(), nil}, {Mod, NewFloat(-20.2).ToObject(), NewFloat(40).ToObject(), NewFloat(19.8).ToObject(), nil},
......
...@@ -384,6 +384,7 @@ func initIntType(dict map[string]*Object) { ...@@ -384,6 +384,7 @@ func initIntType(dict map[string]*Object) {
IntType.slots.Div = &binaryOpSlot{intDiv} IntType.slots.Div = &binaryOpSlot{intDiv}
IntType.slots.DivMod = &binaryOpSlot{intDivMod} IntType.slots.DivMod = &binaryOpSlot{intDivMod}
IntType.slots.Eq = &binaryOpSlot{intEq} IntType.slots.Eq = &binaryOpSlot{intEq}
IntType.slots.FloorDiv = &binaryOpSlot{intDiv}
IntType.slots.GE = &binaryOpSlot{intGE} IntType.slots.GE = &binaryOpSlot{intGE}
IntType.slots.GT = &binaryOpSlot{intGT} IntType.slots.GT = &binaryOpSlot{intGT}
IntType.slots.Float = &unaryOpSlot{intFloat} IntType.slots.Float = &unaryOpSlot{intFloat}
...@@ -412,6 +413,7 @@ func initIntType(dict map[string]*Object) { ...@@ -412,6 +413,7 @@ func initIntType(dict map[string]*Object) {
IntType.slots.RDiv = &binaryOpSlot{intRDiv} IntType.slots.RDiv = &binaryOpSlot{intRDiv}
IntType.slots.RDivMod = &binaryOpSlot{intRDivMod} IntType.slots.RDivMod = &binaryOpSlot{intRDivMod}
IntType.slots.Repr = &unaryOpSlot{intRepr} IntType.slots.Repr = &unaryOpSlot{intRepr}
IntType.slots.RFloorDiv = &binaryOpSlot{intRDiv}
IntType.slots.RMod = &binaryOpSlot{intRMod} IntType.slots.RMod = &binaryOpSlot{intRMod}
IntType.slots.RMul = &binaryOpSlot{intRMul} IntType.slots.RMul = &binaryOpSlot{intRMul}
IntType.slots.ROr = &binaryOpSlot{intOr} IntType.slots.ROr = &binaryOpSlot{intOr}
......
...@@ -46,6 +46,12 @@ func TestIntBinaryOps(t *testing.T) { ...@@ -46,6 +46,12 @@ func TestIntBinaryOps(t *testing.T) {
{DivMod, NewList().ToObject(), NewInt(21).ToObject(), nil, mustCreateException(TypeErrorType, "unsupported operand type(s) for divmod(): 'list' and 'int'")}, {DivMod, NewList().ToObject(), NewInt(21).ToObject(), nil, mustCreateException(TypeErrorType, "unsupported operand type(s) for divmod(): 'list' and 'int'")},
{DivMod, NewInt(1).ToObject(), NewInt(0).ToObject(), nil, mustCreateException(ZeroDivisionErrorType, "integer division or modulo by zero")}, {DivMod, NewInt(1).ToObject(), NewInt(0).ToObject(), nil, mustCreateException(ZeroDivisionErrorType, "integer division or modulo by zero")},
{DivMod, NewInt(MinInt).ToObject(), NewInt(-1).ToObject(), NewTuple2(NewLong(new(big.Int).Neg(minIntBig)).ToObject(), NewLong(big.NewInt(0)).ToObject()).ToObject(), nil}, {DivMod, NewInt(MinInt).ToObject(), NewInt(-1).ToObject(), NewTuple2(NewLong(new(big.Int).Neg(minIntBig)).ToObject(), NewLong(big.NewInt(0)).ToObject()).ToObject(), nil},
{FloorDiv, NewInt(7).ToObject(), NewInt(3).ToObject(), NewInt(2).ToObject(), nil},
{FloorDiv, NewInt(MaxInt).ToObject(), NewInt(MinInt).ToObject(), NewInt(-1).ToObject(), nil},
{FloorDiv, NewInt(MinInt).ToObject(), NewInt(MaxInt).ToObject(), NewInt(-2).ToObject(), nil},
{FloorDiv, NewList().ToObject(), NewInt(21).ToObject(), nil, mustCreateException(TypeErrorType, "unsupported operand type(s) for //: 'list' and 'int'")},
{FloorDiv, NewInt(1).ToObject(), NewInt(0).ToObject(), nil, mustCreateException(ZeroDivisionErrorType, "integer division or modulo by zero")},
{FloorDiv, NewInt(MinInt).ToObject(), NewInt(-1).ToObject(), NewLong(new(big.Int).Neg(minIntBig)).ToObject(), nil},
{LShift, NewInt(2).ToObject(), NewInt(4).ToObject(), NewInt(32).ToObject(), nil}, {LShift, NewInt(2).ToObject(), NewInt(4).ToObject(), NewInt(32).ToObject(), nil},
{LShift, NewInt(-12).ToObject(), NewInt(10).ToObject(), NewInt(-12288).ToObject(), nil}, {LShift, NewInt(-12).ToObject(), NewInt(10).ToObject(), NewInt(-12288).ToObject(), nil},
{LShift, NewInt(10).ToObject(), NewInt(100).ToObject(), NewLong(new(big.Int).Lsh(big.NewInt(10), 100)).ToObject(), nil}, {LShift, NewInt(10).ToObject(), NewInt(100).ToObject(), NewLong(new(big.Int).Lsh(big.NewInt(10), 100)).ToObject(), nil},
......
...@@ -344,6 +344,7 @@ func initLongType(dict map[string]*Object) { ...@@ -344,6 +344,7 @@ func initLongType(dict map[string]*Object) {
LongType.slots.DivMod = longDivAndModOpSlot(longDivAndMod) LongType.slots.DivMod = longDivAndModOpSlot(longDivAndMod)
LongType.slots.Eq = longBinaryBoolOpSlot(longEq) LongType.slots.Eq = longBinaryBoolOpSlot(longEq)
LongType.slots.Float = &unaryOpSlot{longFloat} LongType.slots.Float = &unaryOpSlot{longFloat}
LongType.slots.FloorDiv = longDivModOpSlot(longDiv)
LongType.slots.GE = longBinaryBoolOpSlot(longGE) LongType.slots.GE = longBinaryBoolOpSlot(longGE)
LongType.slots.GT = longBinaryBoolOpSlot(longGT) LongType.slots.GT = longBinaryBoolOpSlot(longGT)
LongType.slots.Hash = &unaryOpSlot{longHash} LongType.slots.Hash = &unaryOpSlot{longHash}
...@@ -372,6 +373,7 @@ func initLongType(dict map[string]*Object) { ...@@ -372,6 +373,7 @@ func initLongType(dict map[string]*Object) {
LongType.slots.RDiv = longRDivModOpSlot(longDiv) LongType.slots.RDiv = longRDivModOpSlot(longDiv)
LongType.slots.RDivMod = longRDivAndModOpSlot(longDivAndMod) LongType.slots.RDivMod = longRDivAndModOpSlot(longDivAndMod)
LongType.slots.Repr = &unaryOpSlot{longRepr} LongType.slots.Repr = &unaryOpSlot{longRepr}
LongType.slots.RFloorDiv = longRDivModOpSlot(longDiv)
LongType.slots.RMod = longRDivModOpSlot(longMod) LongType.slots.RMod = longRDivModOpSlot(longMod)
LongType.slots.RMul = longRBinaryOpSlot(longMul) LongType.slots.RMul = longRBinaryOpSlot(longMul)
LongType.slots.ROr = longRBinaryOpSlot(longOr) LongType.slots.ROr = longRBinaryOpSlot(longOr)
......
...@@ -141,6 +141,12 @@ func TestLongBinaryOps(t *testing.T) { ...@@ -141,6 +141,12 @@ func TestLongBinaryOps(t *testing.T) {
{DivMod, MinInt, -1, NewTuple2(NewLong(new(big.Int).Neg(minIntBig)).ToObject(), NewLong(big.NewInt(0)).ToObject()).ToObject(), nil}, {DivMod, MinInt, -1, NewTuple2(NewLong(new(big.Int).Neg(minIntBig)).ToObject(), NewLong(big.NewInt(0)).ToObject()).ToObject(), nil},
{DivMod, NewList().ToObject(), NewLong(big.NewInt(21)).ToObject(), nil, mustCreateException(TypeErrorType, "unsupported operand type(s) for divmod(): 'list' and 'long'")}, {DivMod, NewList().ToObject(), NewLong(big.NewInt(21)).ToObject(), nil, mustCreateException(TypeErrorType, "unsupported operand type(s) for divmod(): 'list' and 'long'")},
{DivMod, 1, 0, nil, mustCreateException(ZeroDivisionErrorType, "integer division or modulo by zero")}, {DivMod, 1, 0, nil, mustCreateException(ZeroDivisionErrorType, "integer division or modulo by zero")},
{FloorDiv, 7, 3, NewLong(big.NewInt(2)).ToObject(), nil},
{FloorDiv, MaxInt, MinInt, NewLong(big.NewInt(-1)).ToObject(), nil},
{FloorDiv, MinInt, MaxInt, NewLong(big.NewInt(-2)).ToObject(), nil},
{FloorDiv, NewList().ToObject(), NewLong(big.NewInt(21)).ToObject(), nil, mustCreateException(TypeErrorType, "unsupported operand type(s) for //: 'list' and 'long'")},
{FloorDiv, 1, 0, nil, mustCreateException(ZeroDivisionErrorType, "integer division or modulo by zero")},
{FloorDiv, MinInt, -1, NewLong(new(big.Int).Neg(minIntBig)).ToObject(), nil},
{LShift, 2, 4, NewLong(big.NewInt(32)).ToObject(), nil}, {LShift, 2, 4, NewLong(big.NewInt(32)).ToObject(), nil},
{LShift, 12, 10, NewLong(big.NewInt(12288)).ToObject(), nil}, {LShift, 12, 10, NewLong(big.NewInt(12288)).ToObject(), nil},
{LShift, 10, 100, NewLong(new(big.Int).Lsh(big.NewInt(10), 100)).ToObject(), nil}, {LShift, 10, 100, NewLong(new(big.Int).Lsh(big.NewInt(10), 100)).ToObject(), nil},
......
...@@ -383,6 +383,7 @@ type typeSlots struct { ...@@ -383,6 +383,7 @@ type typeSlots struct {
DivMod *binaryOpSlot DivMod *binaryOpSlot
Eq *binaryOpSlot Eq *binaryOpSlot
Float *unaryOpSlot Float *unaryOpSlot
FloorDiv *binaryOpSlot
GE *binaryOpSlot GE *binaryOpSlot
Get *getSlot Get *getSlot
GetAttribute *getAttributeSlot GetAttribute *getAttributeSlot
...@@ -394,6 +395,7 @@ type typeSlots struct { ...@@ -394,6 +395,7 @@ type typeSlots struct {
IAnd *binaryOpSlot IAnd *binaryOpSlot
IDiv *binaryOpSlot IDiv *binaryOpSlot
IDivMod *binaryOpSlot IDivMod *binaryOpSlot
IFloorDiv *binaryOpSlot
ILShift *binaryOpSlot ILShift *binaryOpSlot
IMod *binaryOpSlot IMod *binaryOpSlot
IMul *binaryOpSlot IMul *binaryOpSlot
...@@ -429,6 +431,7 @@ type typeSlots struct { ...@@ -429,6 +431,7 @@ type typeSlots struct {
RDiv *binaryOpSlot RDiv *binaryOpSlot
RDivMod *binaryOpSlot RDivMod *binaryOpSlot
Repr *unaryOpSlot Repr *unaryOpSlot
RFloorDiv *binaryOpSlot
RLShift *binaryOpSlot RLShift *binaryOpSlot
RMod *binaryOpSlot RMod *binaryOpSlot
RMul *binaryOpSlot RMul *binaryOpSlot
......
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