Skip to content

Commit 3685e8e

Browse files
committed
feat: support augmented assignment operators in runtimehelper
1 parent 11e3df1 commit 3685e8e

File tree

4 files changed

+83
-11
lines changed

4 files changed

+83
-11
lines changed

src/runtime-helpers.ts

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,30 @@ export function switchableValue(x: unknown): bigint | string | boolean {
2020
// internalError(`Cannot wrap ${nameOfType(x)}`)
2121
// }
2222

23-
type BinaryOps = '+' | '-' | '*' | '**' | '/' | '%' | '>' | '>=' | '<' | '<=' | '===' | '!==' | '<<' | '>>' | '&' | '|' | '^'
23+
type BinaryOps =
24+
| '+'
25+
| '-'
26+
| '*'
27+
| '**'
28+
| '/'
29+
| '%'
30+
| '>'
31+
| '>='
32+
| '<'
33+
| '<='
34+
| '==='
35+
| '!=='
36+
| '<<'
37+
| '>>'
38+
| '&'
39+
| '|'
40+
| '^'
41+
| '+='
42+
| '-='
43+
| '/='
44+
| '*='
45+
| '**='
46+
| '%='
2447
type UnaryOps = '~'
2548

2649
function tryGetBigInt(value: unknown): bigint | undefined {
@@ -72,19 +95,25 @@ function uint64BinaryOp(left: DeliberateAny, right: DeliberateAny, op: BinaryOps
7295
const result = (function () {
7396
switch (op) {
7497
case '+':
98+
case '+=':
7599
return lbi + rbi
76100
case '-':
101+
case '-=':
77102
return lbi - rbi
78103
case '*':
104+
case '*=':
79105
return lbi * rbi
80106
case '**':
107+
case '**=':
81108
if (lbi === 0n && rbi === 0n) {
82109
throw internal.errors.codeError('0 ** 0 is undefined')
83110
}
84111
return lbi ** rbi
85112
case '/':
113+
case '/=':
86114
return lbi / rbi
87115
case '%':
116+
case '%=':
88117
return lbi % rbi
89118
case '>>':
90119
if (rbi > 63n) {
@@ -127,19 +156,25 @@ function bigUintBinaryOp(left: DeliberateAny, right: DeliberateAny, op: BinaryOp
127156
const result = (function () {
128157
switch (op) {
129158
case '+':
159+
case '+=':
130160
return lbi + rbi
131161
case '-':
162+
case '-=':
132163
return lbi - rbi
133164
case '*':
165+
case '*=':
134166
return lbi * rbi
135167
case '**':
168+
case '**=':
136169
if (lbi === 0n && rbi === 0n) {
137170
throw internal.errors.codeError('0 ** 0 is undefined')
138171
}
139172
return lbi ** rbi
140173
case '/':
174+
case '/=':
141175
return lbi / rbi
142176
case '%':
177+
case '%=':
143178
return lbi % rbi
144179
case '>>':
145180
throw new internal.errors.CodeError('BigUint does not support >> operator')
@@ -207,19 +242,25 @@ function bytesBinaryOp(left: DeliberateAny, right: DeliberateAny, op: BinaryOps)
207242
function defaultBinaryOp(left: DeliberateAny, right: DeliberateAny, op: BinaryOps): DeliberateAny {
208243
switch (op) {
209244
case '+':
245+
case '+=':
210246
return left + right
211247
case '-':
248+
case '-=':
212249
return left - right
213250
case '*':
251+
case '*=':
214252
return left * right
215253
case '**':
254+
case '**=':
216255
if (left === 0n && right === 0n) {
217256
throw new internal.errors.CodeError('0 ** 0 is undefined')
218257
}
219258
return left ** right
220259
case '/':
260+
case '/=':
221261
return left / right
222262
case '%':
263+
case '%=':
223264
return left % right
224265
case '>>':
225266
if (typeof left === 'bigint' && typeof right === 'bigint') {

src/test-transformer/node-factory.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,16 @@ export const nodeFactory = {
2828
[left, right, factory.createStringLiteral(op)],
2929
)
3030
},
31+
augmentedAssignmentBinaryOp(left: ts.Expression, right: ts.Expression, op: string) {
32+
return factory.createAssignment(
33+
left,
34+
factory.createCallExpression(
35+
factory.createPropertyAccessExpression(factory.createIdentifier('runtimeHelpers'), factory.createIdentifier('binaryOp')),
36+
undefined,
37+
[left, right, factory.createStringLiteral(op)],
38+
),
39+
)
40+
},
3141

3242
prefixUnaryOp(operand: ts.Expression, op: string) {
3343
return factory.createCallExpression(

src/test-transformer/supported-binary-op-string.ts

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,6 @@ export function supportedBinaryOpString(x: BinaryOperator): string | undefined {
4040
case ts.SyntaxKind.AmpersandAmpersandEqualsToken:
4141
case ts.SyntaxKind.AmpersandAmpersandToken:
4242
case ts.SyntaxKind.AmpersandEqualsToken:
43-
case ts.SyntaxKind.AsteriskAsteriskEqualsToken:
44-
case ts.SyntaxKind.AsteriskEqualsToken:
4543
case ts.SyntaxKind.BarBarEqualsToken:
4644
case ts.SyntaxKind.BarBarToken:
4745
case ts.SyntaxKind.BarEqualsToken:
@@ -52,11 +50,7 @@ export function supportedBinaryOpString(x: BinaryOperator): string | undefined {
5250
case ts.SyntaxKind.ExclamationEqualsToken:
5351
case ts.SyntaxKind.InKeyword:
5452
case ts.SyntaxKind.InstanceOfKeyword:
55-
case ts.SyntaxKind.PercentEqualsToken:
56-
case ts.SyntaxKind.PlusEqualsToken:
5753
case ts.SyntaxKind.QuestionQuestionEqualsToken:
58-
case ts.SyntaxKind.MinusEqualsToken:
59-
case ts.SyntaxKind.SlashEqualsToken:
6054
case ts.SyntaxKind.QuestionQuestionToken:
6155
case ts.SyntaxKind.GreaterThanGreaterThanEqualsToken:
6256
case ts.SyntaxKind.LessThanLessThanEqualsToken:
@@ -66,6 +60,25 @@ export function supportedBinaryOpString(x: BinaryOperator): string | undefined {
6660
}
6761
}
6862

63+
export function supportedAugmentedAssignmentBinaryOpString(x: BinaryOperator): string | undefined {
64+
switch (x) {
65+
case ts.SyntaxKind.PlusEqualsToken:
66+
return '+='
67+
case ts.SyntaxKind.MinusEqualsToken:
68+
return '-='
69+
case ts.SyntaxKind.SlashEqualsToken:
70+
return '/='
71+
case ts.SyntaxKind.AsteriskEqualsToken:
72+
return '*='
73+
case ts.SyntaxKind.AsteriskAsteriskEqualsToken:
74+
return '**='
75+
case ts.SyntaxKind.PercentEqualsToken:
76+
return '%='
77+
default:
78+
return undefined
79+
}
80+
}
81+
6982
export function supportedPrefixUnaryOpString(x: PrefixUnaryOperator): string | undefined {
7083
switch (x) {
7184
case ts.SyntaxKind.TildeToken:

src/test-transformer/visitors.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@ import type { TypeInfo } from '../encoders'
44
import { DeliberateAny } from '../typescript-helpers'
55
import { TransformerConfig } from './index'
66
import { nodeFactory } from './node-factory'
7-
import { supportedBinaryOpString, supportedPrefixUnaryOpString } from './supported-binary-op-string'
7+
import {
8+
supportedAugmentedAssignmentBinaryOpString,
9+
supportedBinaryOpString,
10+
supportedPrefixUnaryOpString,
11+
} from './supported-binary-op-string'
812

913
const { factory } = ts
1014

@@ -81,9 +85,13 @@ class FunctionOrMethodVisitor {
8185
}
8286

8387
if (ts.isBinaryExpression(node)) {
84-
const tokenText = supportedBinaryOpString(node.operatorToken.kind)
85-
if (tokenText) {
86-
return nodeFactory.binaryOp(node.left, node.right, tokenText)
88+
const opTokenText = supportedBinaryOpString(node.operatorToken.kind)
89+
if (opTokenText) {
90+
return nodeFactory.binaryOp(node.left, node.right, opTokenText)
91+
}
92+
const augmentedAssignmentOpTokenText = supportedAugmentedAssignmentBinaryOpString(node.operatorToken.kind)
93+
if (augmentedAssignmentOpTokenText) {
94+
return nodeFactory.augmentedAssignmentBinaryOp(node.left, node.right, augmentedAssignmentOpTokenText)
8795
}
8896
}
8997
if (ts.isPrefixUnaryExpression(node)) {

0 commit comments

Comments
 (0)