Skip to content
This repository was archived by the owner on Mar 23, 2023. It is now read-only.

Commit 9ca28dd

Browse files
S-YOUtrotterdylan
authored andcommitted
Add unary plus (#253)
1 parent d641069 commit 9ca28dd

9 files changed

Lines changed: 71 additions & 5 deletions

File tree

compiler/expr_visitor.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,7 @@ def visit_Yield(self, node):
410410

411411
_UNARY_OP_TEMPLATES = {
412412
ast.Invert: 'πg.Invert(πF, {operand})',
413+
ast.UAdd: 'πg.Pos(πF, {operand})',
413414
ast.USub: 'πg.Neg(πF, {operand})',
414415
}
415416

compiler/expr_visitor_test.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -220,11 +220,7 @@ def foo():
220220

221221
testUnaryOpNot = _MakeExprTest('not True')
222222
testUnaryOpInvert = _MakeExprTest('~4')
223-
224-
def testUnaryOpNotImplemented(self):
225-
self.assertRaisesRegexp(util.ParseError, 'unary op not implemented',
226-
_ParseAndVisitExpr, '+foo')
227-
223+
testUnaryOpPos = _MakeExprTest('+4')
228224

229225
def _MakeModuleBlock():
230226
return block.ModuleBlock('__main__', 'grumpy', 'grumpy/lib', '<test>', '',

runtime/core.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,16 @@ func Oct(f *Frame, o *Object) (*Object, *BaseException) {
640640
return o, nil
641641
}
642642

643+
// Pos returns the result of o.__pos__ and is equivalent to the Python
644+
// expression "+o".
645+
func Pos(f *Frame, o *Object) (*Object, *BaseException) {
646+
pos := o.typ.slots.Pos
647+
if pos == nil {
648+
return nil, f.RaiseType(TypeErrorType, fmt.Sprintf("bad operand type for unary +: '%s'", o.typ.Name()))
649+
}
650+
return pos.Fn(f, o)
651+
}
652+
643653
// Print implements the Python print statement. It calls str() on the given args
644654
// and outputs the results to stdout separated by spaces. Similar to the Python
645655
// print statement.

runtime/core_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -795,6 +795,26 @@ func TestOct(t *testing.T) {
795795
}
796796
}
797797

798+
func TestPos(t *testing.T) {
799+
pos := newTestClass("pos", []*Type{ObjectType}, newStringDict(map[string]*Object{
800+
"__pos__": newBuiltinFunction("__pos__", func(f *Frame, _ Args, _ KWArgs) (*Object, *BaseException) {
801+
return NewInt(-42).ToObject(), nil
802+
}).ToObject(),
803+
}))
804+
cases := []invokeTestCase{
805+
{args: wrapArgs(42), want: NewInt(42).ToObject()},
806+
{args: wrapArgs(1.2), want: NewFloat(1.2).ToObject()},
807+
{args: wrapArgs(NewLong(big.NewInt(123))), want: NewLong(big.NewInt(123)).ToObject()},
808+
{args: wrapArgs(newObject(pos)), want: NewInt(-42).ToObject()},
809+
{args: wrapArgs("foo"), wantExc: mustCreateException(TypeErrorType, "bad operand type for unary +: 'str'")},
810+
}
811+
for _, cas := range cases {
812+
if err := runInvokeTestCase(wrapFuncForTest(Pos), &cas); err != "" {
813+
t.Error(err)
814+
}
815+
}
816+
}
817+
798818
func TestPyPrint(t *testing.T) {
799819
fun := wrapFuncForTest(func(f *Frame, args *Tuple, sep, end string) (string, *BaseException) {
800820
return captureStdout(f, func() *BaseException {

runtime/float.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,10 @@ func floatNonZero(f *Frame, o *Object) (*Object, *BaseException) {
194194
return GetBool(toFloatUnsafe(o).Value() != 0).ToObject(), nil
195195
}
196196

197+
func floatPos(f *Frame, o *Object) (*Object, *BaseException) {
198+
return o, nil
199+
}
200+
197201
func floatPow(f *Frame, v, w *Object) (*Object, *BaseException) {
198202
return floatArithmeticOp(f, "__pow__", v, w, func(v, w float64) float64 { return math.Pow(v, w) })
199203
}
@@ -257,6 +261,7 @@ func initFloatType(dict map[string]*Object) {
257261
FloatType.slots.Neg = &unaryOpSlot{floatNeg}
258262
FloatType.slots.New = &newSlot{floatNew}
259263
FloatType.slots.NonZero = &unaryOpSlot{floatNonZero}
264+
FloatType.slots.Pos = &unaryOpSlot{floatPos}
260265
FloatType.slots.Pow = &binaryOpSlot{floatPow}
261266
FloatType.slots.RAdd = &binaryOpSlot{floatRAdd}
262267
FloatType.slots.RDiv = &binaryOpSlot{floatRDiv}

runtime/int.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,10 @@ func intOr(f *Frame, v, w *Object) (*Object, *BaseException) {
264264
return NewInt(toIntUnsafe(v).Value() | toIntUnsafe(w).Value()).ToObject(), nil
265265
}
266266

267+
func intPos(f *Frame, o *Object) (*Object, *BaseException) {
268+
return o, nil
269+
}
270+
267271
func intPow(f *Frame, v, w *Object) (*Object, *BaseException) {
268272
if w.isInstance(IntType) {
269273
// First try to use the faster floating point arithmetic
@@ -388,6 +392,7 @@ func initIntType(dict map[string]*Object) {
388392
IntType.slots.NonZero = &unaryOpSlot{intNonZero}
389393
IntType.slots.Oct = &unaryOpSlot{intOct}
390394
IntType.slots.Or = &binaryOpSlot{intOr}
395+
IntType.slots.Pos = &unaryOpSlot{intPos}
391396
IntType.slots.Pow = &binaryOpSlot{intPow}
392397
IntType.slots.RAdd = &binaryOpSlot{intRAdd}
393398
IntType.slots.RAnd = &binaryOpSlot{intAnd}

runtime/long.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,10 @@ func longOr(z, x, y *big.Int) {
307307
z.Or(x, y)
308308
}
309309

310+
func longPos(z, x *big.Int) {
311+
z.Set(x)
312+
}
313+
310314
func longRepr(f *Frame, o *Object) (*Object, *BaseException) {
311315
return NewStr(toLongUnsafe(o).value.Text(10) + "L").ToObject(), nil
312316
}
@@ -355,6 +359,7 @@ func initLongType(dict map[string]*Object) {
355359
LongType.slots.NonZero = longUnaryBoolOpSlot(longNonZero)
356360
LongType.slots.Oct = &unaryOpSlot{longOct}
357361
LongType.slots.Or = longBinaryOpSlot(longOr)
362+
LongType.slots.Pos = longUnaryOpSlot(longPos)
358363
// This operation can return a float, it must use binaryOpSlot directly.
359364
LongType.slots.Pow = &binaryOpSlot{longPow}
360365
LongType.slots.RAdd = longRBinaryOpSlot(longAdd)

runtime/slots.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,7 @@ type typeSlots struct {
420420
NonZero *unaryOpSlot
421421
Oct *unaryOpSlot
422422
Or *binaryOpSlot
423+
Pos *unaryOpSlot
423424
Pow *binaryOpSlot
424425
RAdd *binaryOpSlot
425426
RAnd *binaryOpSlot

testing/op_test.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,5 +81,28 @@ def TestNeg():
8181
assert -x == -100
8282

8383

84+
def TestPos():
85+
x = 12
86+
assert +x == 12
87+
88+
x = 1.1
89+
assert +x == 1.1
90+
91+
x = 0.0
92+
assert +x == 0.0
93+
94+
x = float('inf')
95+
assert math.isinf(+x)
96+
97+
x = +float('inf')
98+
assert math.isinf(+x)
99+
100+
x = float('nan')
101+
assert math.isnan(+x)
102+
103+
x = long(100)
104+
assert +x == 100
105+
106+
84107
if __name__ == '__main__':
85108
weetest.RunTests()

0 commit comments

Comments
 (0)