Skip to content

Commit a15f55d

Browse files
committed
Implement bitwise right shift operator for type params.
1 parent ac13918 commit a15f55d

File tree

3 files changed

+51
-1
lines changed

3 files changed

+51
-1
lines changed

compiler/expressions.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -706,6 +706,8 @@ func (fc *funcContext) translateBinaryExpr(e *ast.BinaryExpr) *expression {
706706
return fc.formatExpr("%s.andNot(%e, %e)", fc.typeName(t), e.X, e.Y)
707707
case token.SHL:
708708
return fc.formatExpr("%s.shl(%e, $flatten64(%e, %s))", fc.typeName(t), e.X, e.Y, fc.typeName(t2))
709+
case token.SHR:
710+
return fc.formatExpr("%s.shr(%e, $flatten64(%e, %s))", fc.typeName(t), e.X, e.Y, fc.typeName(t2))
709711
}
710712
}
711713

compiler/prelude/types.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,7 @@ var $newType = (size, kind, string, named, pkg, exported, constructor) => {
430430
typ.xor = (x, y) => $truncateNumber(x ^ y, typ);
431431
typ.andNot = (x, y) => $truncateNumber(x & ~y, typ);
432432
typ.shl = (x, y) => (y < 32) ? $truncateNumber(x << y, typ) : 0;
433+
typ.shr = (x, y) => $truncateNumber(x >> $min(y, 31), typ);
433434
break;
434435
case $kindUint8:
435436
case $kindUint16:
@@ -443,6 +444,7 @@ var $newType = (size, kind, string, named, pkg, exported, constructor) => {
443444
typ.xor = (x, y) => $truncateNumber(x ^ y, typ);
444445
typ.andNot = (x, y) => $truncateNumber(x & ~y, typ);
445446
typ.shl = (x, y) => (y < 32) ? $truncateNumber(x << y, typ) : 0;
447+
typ.shr = (x, y) => (y < 32) ? $truncateNumber(x >>> y, typ) : 0;
446448
break;
447449
case $kindUint:
448450
case $kindUint32:
@@ -457,6 +459,7 @@ var $newType = (size, kind, string, named, pkg, exported, constructor) => {
457459
typ.xor = (x, y) => $truncateNumber(x ^ y, typ);
458460
typ.andNot = (x, y) => $truncateNumber(x & ~y, typ);
459461
typ.shl = (x, y) => (y < 32) ? $truncateNumber(x << y, typ) : 0;
462+
typ.shr = (x, y) => (y < 32) ? $truncateNumber(x >>> y, typ) : 0;
460463
break;
461464
case $kindInt:
462465
case $kindInt32:
@@ -470,6 +473,7 @@ var $newType = (size, kind, string, named, pkg, exported, constructor) => {
470473
typ.xor = (x, y) => $truncateNumber(x ^ y, typ);
471474
typ.andNot = (x, y) => $truncateNumber(x & ~y, typ);
472475
typ.shl = (x, y) => (y < 32) ? $truncateNumber(x << y, typ) : 0;
476+
typ.shr = (x, y) => $truncateNumber(x >> $min(y, 31), typ);
473477
break;
474478
case $kindInt64:
475479
case $kindUint64:
@@ -482,7 +486,8 @@ var $newType = (size, kind, string, named, pkg, exported, constructor) => {
482486
typ.or = (x, y) => new typ(x.$high | y.$high, (x.$low | y.$low) >>> 0);
483487
typ.xor = (x, y) => new typ(x.$high ^ y.$high, (x.$low ^ y.$low) >>> 0);
484488
typ.andNot = (x, y) => new typ(x.$high & ~y.$high, (x.$low & ~y.$low) >>> 0);
485-
typ.shl = (x, y) => $shiftLeft64(x, y);
489+
typ.shl = $shiftLeft64;
490+
typ.shr = (kind === $kindInt64) ? $shiftRightInt64 : $shiftRightUint64;
486491
break;
487492
case $kindFloat32:
488493
case $kindFloat64:

tests/typeparams/arithmetics_test.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,8 @@ func TestBitwiseShitLeft(t *testing.T) {
394394
leftShiftTC[uint32](0x80000008, 1, 0x00000010),
395395
leftShiftTC[int64](0x4000000000000008, 1, -0x7ffffffffffffff0),
396396
leftShiftTC[uint64](0x8000000000000008, 1, 0x0000000000000010),
397+
leftShiftTC[uint32](0xFFFFFFFF, 32, 0),
398+
leftShiftTC[int32](-0x80000000, 32, 0),
397399
}
398400

399401
if bits.UintSize == 32 {
@@ -408,3 +410,44 @@ func TestBitwiseShitLeft(t *testing.T) {
408410
t.Run(test.String(), test.Run)
409411
}
410412
}
413+
414+
func rightShift[T constraints.Integer](x, y T) T {
415+
return x >> y
416+
}
417+
418+
func rightShiftTC[T constraints.Integer](x, y, want T) *testCase[T] {
419+
return &testCase[T]{
420+
op: rightShift[T],
421+
opName: token.SHR,
422+
x: x,
423+
y: y,
424+
want: want,
425+
}
426+
}
427+
428+
func TestBitwiseShitRight(t *testing.T) {
429+
tests := []testCaseI{
430+
rightShiftTC[int8](-0x70, 1, -0x38),
431+
rightShiftTC[int16](-0x7ff0, 1, -0x3ff8),
432+
rightShiftTC[int32](-0x7ffffff0, 1, -0x3ffffff8),
433+
rightShiftTC[uint8](0x80, 1, 0x40),
434+
rightShiftTC[uint16](0x8010, 1, 0x4008),
435+
rightShiftTC[uint32](0x80000010, 1, 0x40000008),
436+
rightShiftTC[int64](-0x7ffffffffffffff0, 1, -0x3ffffffffffffff8),
437+
rightShiftTC[uint64](0x8000000000000010, 1, 0x4000000000000008),
438+
rightShiftTC[uint32](0xFFFFFFFF, 32, 0),
439+
rightShiftTC[int32](-0x80000000, 32, -1),
440+
}
441+
442+
if bits.UintSize == 32 {
443+
tests = append(tests,
444+
rightShiftTC[int](-0x7ffffff0, 1, -0x3ffffff8),
445+
rightShiftTC[uint](0x80000010, 1, 0x40000008),
446+
rightShiftTC[uintptr](0x80000010, 1, 0x40000008),
447+
)
448+
}
449+
450+
for _, test := range tests {
451+
t.Run(test.String(), test.Run)
452+
}
453+
}

0 commit comments

Comments
 (0)