Skip to content

Commit f4c0904

Browse files
committed
Support "bit clear" (aka "and not") bitwise operator for type params.
1 parent af59ead commit f4c0904

File tree

3 files changed

+41
-0
lines changed

3 files changed

+41
-0
lines changed

compiler/expressions.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -702,6 +702,8 @@ func (fc *funcContext) translateBinaryExpr(e *ast.BinaryExpr) *expression {
702702
return fc.formatExpr("%s.or(%e, %e)", fc.typeName(t), e.X, e.Y)
703703
case token.XOR:
704704
return fc.formatExpr("%s.xor(%e, %e)", fc.typeName(t), e.X, e.Y)
705+
case token.AND_NOT:
706+
return fc.formatExpr("%s.andNot(%e, %e)", fc.typeName(t), e.X, e.Y)
705707
}
706708
}
707709

compiler/prelude/types.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,7 @@ var $newType = (size, kind, string, named, pkg, exported, constructor) => {
428428
typ.and = (x, y) => (x & y);
429429
typ.or = (x, y) => (x | y);
430430
typ.xor = (x, y) => $truncateNumber(x ^ y, typ);
431+
typ.andNot = (x, y) => $truncateNumber(x & ~y, typ);
431432
break;
432433
case $kindUint8:
433434
case $kindUint16:
@@ -439,6 +440,7 @@ var $newType = (size, kind, string, named, pkg, exported, constructor) => {
439440
typ.and = (x, y) => (x & y) >>> 0;
440441
typ.or = (x, y) => (x | y) >>> 0;
441442
typ.xor = (x, y) => $truncateNumber(x ^ y, typ);
443+
typ.andNot = (x, y) => $truncateNumber(x & ~y, typ);
442444
break;
443445
case $kindUint:
444446
case $kindUint32:
@@ -451,6 +453,7 @@ var $newType = (size, kind, string, named, pkg, exported, constructor) => {
451453
typ.and = (x, y) => (x & y) >>> 0;
452454
typ.or = (x, y) => (x | y) >>> 0;
453455
typ.xor = (x, y) => $truncateNumber(x ^ y, typ);
456+
typ.andNot = (x, y) => $truncateNumber(x & ~y, typ);
454457
break;
455458
case $kindInt:
456459
case $kindInt32:
@@ -462,6 +465,7 @@ var $newType = (size, kind, string, named, pkg, exported, constructor) => {
462465
typ.and = (x, y) => (x & y);
463466
typ.or = (x, y) => (x | y);
464467
typ.xor = (x, y) => $truncateNumber(x ^ y, typ);
468+
typ.andNot = (x, y) => $truncateNumber(x & ~y, typ);
465469
break;
466470
case $kindInt64:
467471
case $kindUint64:
@@ -473,6 +477,7 @@ var $newType = (size, kind, string, named, pkg, exported, constructor) => {
473477
typ.and = (x, y) => new typ(x.$high & y.$high, (x.$low & y.$low) >>> 0);
474478
typ.or = (x, y) => new typ(x.$high | y.$high, (x.$low | y.$low) >>> 0);
475479
typ.xor = (x, y) => new typ(x.$high ^ y.$high, (x.$low ^ y.$low) >>> 0);
480+
typ.andNot = (x, y) => new typ(x.$high & ~y.$high, (x.$low & ~y.$low) >>> 0);
476481
break;
477482
case $kindFloat32:
478483
case $kindFloat64:

tests/typeparams/arithmetics_test.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,3 +334,37 @@ func TestBitwiseXor(t *testing.T) {
334334
t.Run(test.String(), test.Run)
335335
}
336336
}
337+
338+
func andNot[T constraints.Integer](x, y T) T {
339+
return x &^ y
340+
}
341+
342+
func andNotTC[T constraints.Integer](x, y, want T) *testCase[T] {
343+
return &testCase[T]{
344+
op: andNot[T],
345+
opName: token.AND_NOT,
346+
x: x,
347+
y: y,
348+
want: want,
349+
}
350+
}
351+
352+
func TestBitwiseAndNot(t *testing.T) {
353+
tests := []testCaseI{
354+
andNotTC[int](0x0011, 0x0101, 0x0010),
355+
andNotTC[uint](0x0011, 0x0101, 0x0010),
356+
andNotTC[uintptr](0x0011, 0x0101, 0x0010),
357+
andNotTC[int8](0x11, 0x01, 0x10),
358+
andNotTC[int16](0x0011, 0x0101, 0x0010),
359+
andNotTC[int32](0x0011, 0x0101, 0x0010),
360+
andNotTC[uint8](0x11, 0x01, 0x10),
361+
andNotTC[uint16](0x0011, 0x0101, 0x0010),
362+
andNotTC[uint32](0x0011, 0x0101, 0x0010),
363+
andNotTC[int64](0x0000001100000011, 0x0000010100000101, 0x0000001000000010),
364+
andNotTC[uint64](0x0000001100000011, 0x0000010100000101, 0x0000001000000010),
365+
}
366+
367+
for _, test := range tests {
368+
t.Run(test.String(), test.Run)
369+
}
370+
}

0 commit comments

Comments
 (0)