Skip to content

Commit 2e76d2d

Browse files
committed
Support division operator for type parameters.
1 parent 98523b4 commit 2e76d2d

File tree

4 files changed

+77
-17
lines changed

4 files changed

+77
-17
lines changed

compiler/expressions.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,8 @@ func (fc *funcContext) translateBinaryExpr(e *ast.BinaryExpr) *expression {
692692
return fc.formatExpr("%s.sub(%e, %e)", fc.typeName(t), e.X, e.Y)
693693
case token.MUL:
694694
return fc.formatExpr("%s.mul(%e, %e)", fc.typeName(t), e.X, e.Y)
695+
case token.QUO:
696+
return fc.formatExpr("%s.div(%e, %e)", fc.typeName(t), e.X, e.Y)
695697
}
696698
}
697699

compiler/prelude/numeric.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,15 @@ var $mul64 = (x, y) => {
116116
return r;
117117
};
118118

119+
const $idiv = (x, y) => {
120+
const result = x / y;
121+
if (result === result && result != 1/0 && result != -1/0) {
122+
return result;
123+
} else {
124+
$throwRuntimeError("integer divide by zero");
125+
}
126+
};
127+
119128
var $div64 = (x, y, returnRemainder) => {
120129
if (y.$high === 0 && y.$low === 0) {
121130
$throwRuntimeError("integer divide by zero");

compiler/prelude/types.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -420,38 +420,53 @@ var $newType = (size, kind, string, named, pkg, exported, constructor) => {
420420
switch (kind) {
421421
case $kindInt8:
422422
case $kindInt16:
423-
case $kindUint:
423+
typ.add = (x, y) => $truncateNumber(x + y, typ);
424+
typ.sub = (x, y) => $truncateNumber(x - y, typ);
425+
typ.mul = (x, y) => $truncateNumber(x * y, typ);
426+
typ.div = (x, y) => $idiv(x, y) >> 0;
427+
break;
424428
case $kindUint8:
425429
case $kindUint16:
430+
typ.add = (x, y) => $truncateNumber(x + y, typ);
431+
typ.sub = (x, y) => $truncateNumber(x - y, typ);
432+
typ.mul = (x, y) => $truncateNumber(x * y, typ);
433+
typ.div = (x, y) => $idiv(x, y) >>> 0;
434+
break;
426435
case $kindFloat32:
427436
case $kindFloat64:
428437
typ.add = (x, y) => $truncateNumber(x + y, typ);
429438
typ.sub = (x, y) => $truncateNumber(x - y, typ);
430439
typ.mul = (x, y) => $truncateNumber(x * y, typ);
440+
typ.div = (x, y) => $truncateNumber(x / y, typ);
431441
break;
442+
case $kindUint:
432443
case $kindUint32:
433444
case $kindUintptr:
434445
typ.add = (x, y) => $truncateNumber(x + y, typ);
435446
typ.sub = (x, y) => $truncateNumber(x - y, typ);
436447
typ.mul = (x, y) => $imul(x, y) >>> 0;
448+
typ.div = (x, y) => $idiv(x, y) >>> 0;
437449
break;
438450
case $kindInt:
439451
case $kindInt32:
440452
typ.add = (x, y) => $truncateNumber(x + y, typ);
441453
typ.sub = (x, y) => $truncateNumber(x - y, typ);
442454
typ.mul = (x, y) => $imul(x, y);
455+
typ.div = (x, y) => $idiv(x, y) >> 0;
443456
break;
444457
case $kindInt64:
445458
case $kindUint64:
446459
typ.add = (x, y) => new typ(x.$high + y.$high, x.$low + y.$low);
447460
typ.sub = (x, y) => new typ(x.$high - y.$high, x.$low - y.$low);
448461
typ.mul = (x, y) => $mul64(x, y);
462+
typ.div = (x, y) => $div64(x, y, false);
449463
break;
450464
case $kindComplex64:
451465
case $kindComplex128:
452466
typ.add = (x, y) => new typ(x.$real + y.$real, x.$imag + y.$imag);
453467
typ.sub = (x, y) => new typ(x.$real - y.$real, x.$imag - y.$imag);
454468
typ.mul = (x, y) => new typ(x.$real * y.$real - x.$imag * y.$imag, x.$real * y.$imag + x.$imag * y.$real);
469+
typ.div = (x, y) => $divComplex(x, y);
455470
break;
456471
case $kindString:
457472
typ.add = (x, y) => x + y;

tests/typeparams/arithmetics_test.go

Lines changed: 50 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,14 @@ import (
88
"golang.org/x/exp/constraints"
99
)
1010

11+
type arithmetic interface {
12+
constraints.Integer | constraints.Float | constraints.Complex
13+
}
14+
15+
type addable interface {
16+
arithmetic | string
17+
}
18+
1119
type testCaseI interface {
1220
Run(t *testing.T)
1321
String() string
@@ -32,10 +40,6 @@ func (tc *testCase[T]) String() string {
3240
return fmt.Sprintf("%T/%v%v%v", tc.x, tc.x, tc.opName, tc.y)
3341
}
3442

35-
type addable interface {
36-
constraints.Integer | constraints.Float | constraints.Complex | string
37-
}
38-
3943
func add[T addable](x, y T) T {
4044
return x + y
4145
}
@@ -77,15 +81,11 @@ func TestAdd(t *testing.T) {
7781
}
7882
}
7983

80-
type subtractable interface {
81-
constraints.Integer | constraints.Float | constraints.Complex
82-
}
83-
84-
func subtract[T subtractable](x, y T) T {
84+
func subtract[T arithmetic](x, y T) T {
8585
return x - y
8686
}
8787

88-
func subTC[T subtractable](x, y, want T) *testCase[T] {
88+
func subTC[T arithmetic](x, y, want T) *testCase[T] {
8989
return &testCase[T]{
9090
op: subtract[T],
9191
opName: token.SUB,
@@ -121,15 +121,11 @@ func TestSubtract(t *testing.T) {
121121
}
122122
}
123123

124-
type muiltipliable interface {
125-
constraints.Integer | constraints.Float | constraints.Complex
126-
}
127-
128-
func mul[T muiltipliable](x, y T) T {
124+
func mul[T arithmetic](x, y T) T {
129125
return x * y
130126
}
131127

132-
func mulTC[T muiltipliable](x, y, want T) *testCase[T] {
128+
func mulTC[T arithmetic](x, y, want T) *testCase[T] {
133129
return &testCase[T]{
134130
op: mul[T],
135131
opName: token.MUL,
@@ -164,3 +160,41 @@ func TestMul(t *testing.T) {
164160
t.Run(test.String(), test.Run)
165161
}
166162
}
163+
164+
func div[T arithmetic](x, y T) T {
165+
return x / y
166+
}
167+
168+
func divTC[T arithmetic](x, y, want T) *testCase[T] {
169+
return &testCase[T]{
170+
op: div[T],
171+
opName: token.QUO,
172+
x: x,
173+
y: y,
174+
want: want,
175+
}
176+
}
177+
178+
func TestDiv(t *testing.T) {
179+
tests := []testCaseI{
180+
divTC[int](7, 2, 3),
181+
divTC[uint](7, 2, 3),
182+
divTC[uintptr](7, 2, 3),
183+
divTC[int8](7, 2, 3),
184+
divTC[int16](7, 2, 3),
185+
divTC[int32](7, 2, 3),
186+
divTC[uint8](7, 2, 3),
187+
divTC[uint16](7, 2, 3),
188+
divTC[uint32](7, 2, 3),
189+
divTC[float32](3.5, 2.5, 1.4),
190+
divTC[float64](3.5, 2.5, 1.4),
191+
divTC[int64](0x0000006500000003, 0x0000003200000001, 2),
192+
divTC[uint64](0x0000006500000003, 0x0000003200000001, 2),
193+
divTC[complex64](-5+10i, 1+2i, 3+4i),
194+
divTC[complex128](-5+10i, 1+2i, 3+4i),
195+
}
196+
197+
for _, test := range tests {
198+
t.Run(test.String(), test.Run)
199+
}
200+
}

0 commit comments

Comments
 (0)