@harmoniclabs/pebble 0.1.0-dev6 → 0.1.0-dev8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/IR/IRNodes/IRConst.js +1 -1
- package/dist/IR/IRNodes/IRNative/IRNativeTag.d.ts +6 -3
- package/dist/IR/IRNodes/IRNative/IRNativeTag.js +12 -4
- package/dist/IR/IRNodes/IRNative/index.d.ts +5 -2
- package/dist/IR/IRNodes/IRNative/index.js +6 -2
- package/dist/IR/toUPLC/CompilerOptions.d.ts +6 -1
- package/dist/IR/toUPLC/CompilerOptions.js +11 -1
- package/dist/IR/toUPLC/compileIRToUPLC.js +34 -35
- package/dist/IR/toUPLC/ctx/ToUplcCtx.js +2 -10
- package/dist/IR/toUPLC/subRoutines/handleLetted/groupByScope.js +0 -2
- package/dist/IR/toUPLC/subRoutines/handleLetted/index.js +69 -3
- package/dist/IR/toUPLC/subRoutines/replaceNatives/nativeToIR.d.ts +3 -1
- package/dist/IR/toUPLC/subRoutines/replaceNatives/nativeToIR.js +42 -10
- package/dist/IR/toUPLC/subRoutines/rewriteNativesAppliedToConstantsAndReturnRoot.js +292 -17
- package/dist/IR/utils/isClosedIRTerm.js +1 -1
- package/dist/IR/utils/positiveIntAsBytes.js +1 -5
- package/dist/compiler/AstCompiler/AstCompiler.d.ts +3 -0
- package/dist/compiler/AstCompiler/AstCompiler.js +66 -3
- package/dist/compiler/AstCompiler/internal/_deriveContractBody/_deriveContractBody.js +1 -1
- package/dist/compiler/AstCompiler/internal/exprs/_compileExpr.js +4 -0
- package/dist/compiler/AstCompiler/internal/exprs/_compileFuncExpr.js +13 -4
- package/dist/compiler/AstCompiler/internal/exprs/_compileTypeConversionExpr.js +0 -1
- package/dist/compiler/AstCompiler/internal/exprs/_compileVarAccessExpr.js +3 -1
- package/dist/compiler/AstCompiler/internal/statements/_compileAssignmentStmt.js +7 -7
- package/dist/compiler/AstCompiler/internal/statements/_compileVarStmt.d.ts +2 -1
- package/dist/compiler/AstCompiler/internal/statements/_compileVarStmt.js +2 -1
- package/dist/compiler/AstCompiler/scope/AstScope.d.ts +1 -0
- package/dist/compiler/AstCompiler/scope/AstScope.js +5 -0
- package/dist/compiler/Compiler.d.ts +8 -1
- package/dist/compiler/Compiler.js +38 -1
- package/dist/compiler/TirCompiler/compileTirProgram.js +2 -1
- package/dist/compiler/TirCompiler/expressify/ExpressifyCtx.d.ts +4 -2
- package/dist/compiler/TirCompiler/expressify/ExpressifyCtx.js +42 -16
- package/dist/compiler/TirCompiler/expressify/determineReassignedVariablesAndReturn.js +2 -0
- package/dist/compiler/TirCompiler/expressify/expressify.js +26 -9
- package/dist/compiler/TirCompiler/expressify/expressifyForStmt.js +23 -7
- package/dist/compiler/TirCompiler/expressify/expressifyVarAssignmentStmt.d.ts +1 -2
- package/dist/compiler/TirCompiler/expressify/expressifyVarAssignmentStmt.js +15 -8
- package/dist/compiler/TirCompiler/expressify/expressifyVarDecl.js +6 -9
- package/dist/compiler/TirCompiler/expressify/expressifyVars.js +51 -16
- package/dist/compiler/TirCompiler/expressify/flattenSopNamedDeconstructInplace_addTopDestructToCtx_getNestedDeconstruct.js +1 -0
- package/dist/compiler/internalVar.d.ts +1 -1
- package/dist/compiler/internalVar.js +31 -24
- package/dist/compiler/io/CompilerIoApi.d.ts +1 -1
- package/dist/compiler/tir/expressions/TirCallExpr.d.ts +1 -1
- package/dist/compiler/tir/expressions/TirCallExpr.js +1 -1
- package/dist/compiler/tir/expressions/TirCaseExpr.js +2 -0
- package/dist/compiler/tir/expressions/TirFromDataExpr.js +2 -2
- package/dist/compiler/tir/expressions/TirFuncExpr.d.ts +1 -1
- package/dist/compiler/tir/expressions/TirFuncExpr.js +1 -1
- package/dist/compiler/tir/expressions/TirLettedExpr.d.ts +2 -2
- package/dist/compiler/tir/expressions/TirLettedExpr.js +4 -6
- package/dist/compiler/tir/expressions/TirNativeFunc.d.ts +3 -2
- package/dist/compiler/tir/expressions/TirNativeFunc.js +33 -12
- package/dist/compiler/tir/expressions/TirPropAccessExpr.js +1 -2
- package/dist/compiler/tir/expressions/TirVariableAccessExpr.d.ts +0 -1
- package/dist/compiler/tir/expressions/TirVariableAccessExpr.js +9 -5
- package/dist/compiler/tir/expressions/ToIRTermCtx.d.ts +3 -0
- package/dist/compiler/tir/expressions/ToIRTermCtx.js +8 -1
- package/dist/compiler/tir/expressions/binary/TirBinaryExpr.d.ts +1 -0
- package/dist/compiler/tir/expressions/binary/TirBinaryExpr.js +6 -1
- package/dist/compiler/tir/program/TypedProgram.d.ts +2 -2
- package/dist/compiler/tir/program/stdScope/stdScope.js +9 -23
- package/dist/compiler/tir/statements/TirIfStmt.d.ts +0 -1
- package/dist/compiler/tir/statements/TirIfStmt.js +0 -3
- package/dist/parser/Parser.js +18 -2
- package/dist/parser/Precedence.js +1 -0
- package/dist/utils/BitUtils/index.d.ts +1 -1
- package/dist/utils/BitUtils/index.js +1 -1
- package/dist/utils/IsSingleKey.d.ts +1 -1
- package/dist/utils/UPLCFlatUtils/index.d.ts +1 -1
- package/dist/utils/UPLCFlatUtils/index.js +2 -2
- package/dist/utils/array/keepSortedArrInplace.js +1 -0
- package/package.json +7 -6
- package/dist/compiler/TirCompiler/internal/_compileHoistedDeps.d.ts +0 -5
- package/dist/compiler/TirCompiler/internal/_compileHoistedDeps.js +0 -39
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { TirBoolT, TirIntT } from "../../../compiler/tir/types/TirNativeType/index.js";
|
|
2
|
+
import { equalIrHash } from "../../IRHash.js";
|
|
1
3
|
import { _ir_apps } from "../../IRNodes/IRApp.js";
|
|
2
4
|
import { IRConst } from "../../IRNodes/IRConst.js";
|
|
3
5
|
import { IRFunc } from "../../IRNodes/IRFunc.js";
|
|
@@ -9,13 +11,25 @@ import { IRVar } from "../../IRNodes/IRVar.js";
|
|
|
9
11
|
import { _modifyChildFromTo } from "../_internal/_modifyChildFromTo.js";
|
|
10
12
|
import { getApplicationTerms } from "../utils/getApplicationTerms.js";
|
|
11
13
|
import { _compTimeDropN } from "./_comptimeDropN.js";
|
|
14
|
+
import { hoisted_isZero, hoisted_length, hoisted_not } from "./replaceNatives/nativeToIR.js";
|
|
12
15
|
export function rewriteNativesAppliedToConstantsAndReturnRoot(term) {
|
|
13
16
|
// traverse the tree, find applications of natives to constants
|
|
14
17
|
// and replace them with the optimized equivalent
|
|
15
18
|
const stack = [term];
|
|
19
|
+
function modifyTermAndPushToReprocess(current, newTerm) {
|
|
20
|
+
const parent = current.parent;
|
|
21
|
+
if (parent) {
|
|
22
|
+
_modifyChildFromTo(parent, current, newTerm);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
term = newTerm;
|
|
26
|
+
term.parent = undefined;
|
|
27
|
+
}
|
|
28
|
+
stack.unshift(newTerm); // reprocess new term for further optimizations (if any)
|
|
29
|
+
}
|
|
16
30
|
while (stack.length > 0) {
|
|
17
31
|
const current = stack.pop();
|
|
18
|
-
const parent = current.parent;
|
|
32
|
+
// const parent = current.parent;
|
|
19
33
|
const appTerms = getApplicationTerms(current);
|
|
20
34
|
if (!appTerms) {
|
|
21
35
|
stack.unshift(...current.children());
|
|
@@ -25,16 +39,196 @@ export function rewriteNativesAppliedToConstantsAndReturnRoot(term) {
|
|
|
25
39
|
const [fstArg, ...restArgs] = args;
|
|
26
40
|
if (isId(func)
|
|
27
41
|
&& restArgs.length === 0) {
|
|
28
|
-
|
|
29
|
-
_modifyChildFromTo(parent, current, fstArg);
|
|
30
|
-
}
|
|
31
|
-
else {
|
|
32
|
-
term = fstArg;
|
|
33
|
-
term.parent = undefined;
|
|
34
|
-
}
|
|
35
|
-
stack.unshift(fstArg);
|
|
42
|
+
modifyTermAndPushToReprocess(current, fstArg);
|
|
36
43
|
continue;
|
|
37
44
|
}
|
|
45
|
+
if (func instanceof IRNative) {
|
|
46
|
+
const tag = func.tag;
|
|
47
|
+
if (tag === IRNativeTag.strictIfThenElse
|
|
48
|
+
&& restArgs.length === 2) {
|
|
49
|
+
const conditionArg = fstArg;
|
|
50
|
+
const condtionAppTerms = getApplicationTerms(conditionArg);
|
|
51
|
+
if (!condtionAppTerms) {
|
|
52
|
+
const boolValue = getConstBool(conditionArg);
|
|
53
|
+
if (typeof boolValue === "boolean") {
|
|
54
|
+
const newTerm = boolValue ? restArgs[0] : restArgs[1];
|
|
55
|
+
modifyTermAndPushToReprocess(current, newTerm);
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
stack.unshift(...current.children()); // normal processing
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
const { func: condFunc, args: condArgs } = condtionAppTerms;
|
|
62
|
+
const thenArg = restArgs[0];
|
|
63
|
+
const elseArg = restArgs[1];
|
|
64
|
+
if (isNot(condFunc)
|
|
65
|
+
&& condArgs.length === 1) {
|
|
66
|
+
// replace with swapped branches
|
|
67
|
+
const newTerm = _ir_apps(IRNative.strictIfThenElse, condArgs[0], elseArg, thenArg);
|
|
68
|
+
modifyTermAndPushToReprocess(current, newTerm);
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
else if (isLessThanOrEqualInteger(condFunc)
|
|
72
|
+
&& condArgs.length === 2) {
|
|
73
|
+
const [lhs, rhs] = condArgs;
|
|
74
|
+
const lhsInt = getConstInt(lhs);
|
|
75
|
+
const rhsInt = getConstInt(rhs);
|
|
76
|
+
if (typeof lhsInt === "bigint" && typeof rhsInt === "bigint") {
|
|
77
|
+
// replace with constant
|
|
78
|
+
const newTerm = (lhsInt <= rhsInt) ? thenArg : elseArg;
|
|
79
|
+
modifyTermAndPushToReprocess(current, newTerm);
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
else if (typeof lhsInt === "bigint") {
|
|
83
|
+
const newTerm = _ir_apps(IRNative.strictIfThenElse, _ir_apps(new IRHoisted(_ir_apps(IRNative.lessThanEqualInteger, lhs)), rhs), thenArg, elseArg);
|
|
84
|
+
modifyTermAndPushToReprocess(current, newTerm);
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
else if (typeof rhsInt === "bigint") {
|
|
88
|
+
const newTerm = _ir_apps(IRNative.strictIfThenElse, _ir_apps(new IRHoisted(_ir_apps(IRNative.lessThanInteger, rhs)), lhs), elseArg, thenArg);
|
|
89
|
+
modifyTermAndPushToReprocess(current, newTerm);
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
else if (isLessThanInteger(condFunc)
|
|
94
|
+
&& condArgs.length === 2) {
|
|
95
|
+
const [lhs, rhs] = condArgs;
|
|
96
|
+
const lhsInt = getConstInt(lhs);
|
|
97
|
+
const rhsInt = getConstInt(rhs);
|
|
98
|
+
if (typeof lhsInt === "bigint" && typeof rhsInt === "bigint") {
|
|
99
|
+
// replace with constant
|
|
100
|
+
const newTerm = (lhsInt < rhsInt) ? thenArg : elseArg;
|
|
101
|
+
modifyTermAndPushToReprocess(current, newTerm);
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
else if (typeof lhsInt === "bigint") {
|
|
105
|
+
const newTerm = _ir_apps(IRNative.strictIfThenElse, _ir_apps(new IRHoisted(_ir_apps(IRNative.lessThanInteger, lhs)), rhs), thenArg, elseArg);
|
|
106
|
+
modifyTermAndPushToReprocess(current, newTerm);
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
else if (typeof rhsInt === "bigint") {
|
|
110
|
+
const newTerm = _ir_apps(IRNative.strictIfThenElse, _ir_apps(new IRHoisted(_ir_apps(IRNative.lessThanEqualInteger, rhs)), lhs), elseArg, thenArg);
|
|
111
|
+
modifyTermAndPushToReprocess(current, newTerm);
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
else if (isEqualsZero(condFunc)
|
|
116
|
+
&& condArgs.length === 1) {
|
|
117
|
+
const equalZeroArg = condArgs[0];
|
|
118
|
+
const equalZeroArgAppTerms = getApplicationTerms(equalZeroArg);
|
|
119
|
+
if (!equalZeroArgAppTerms) {
|
|
120
|
+
// standard continuation
|
|
121
|
+
stack.unshift(...current.children());
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
const { func: eqZeroArgFunc, args: eqZeroArgArgs } = equalZeroArgAppTerms;
|
|
125
|
+
if (isListLength(eqZeroArgFunc)
|
|
126
|
+
&& eqZeroArgArgs.length === 1) {
|
|
127
|
+
const listTerm = eqZeroArgArgs[0];
|
|
128
|
+
// replace with isNullList
|
|
129
|
+
const newTerm = _ir_apps(IRNative.strictChooseList, listTerm, thenArg, elseArg);
|
|
130
|
+
modifyTermAndPushToReprocess(current, newTerm);
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
// standard continuation
|
|
134
|
+
stack.unshift(...current.children());
|
|
135
|
+
continue;
|
|
136
|
+
} // if( x.length() === 0 )
|
|
137
|
+
else if (isNullList(condFunc)
|
|
138
|
+
&& condArgs.length === 1) {
|
|
139
|
+
const listTerm = condArgs[0];
|
|
140
|
+
// replace with isListLength
|
|
141
|
+
const newTerm = _ir_apps(IRNative.strictChooseList, listTerm, thenArg, elseArg);
|
|
142
|
+
modifyTermAndPushToReprocess(current, newTerm);
|
|
143
|
+
continue;
|
|
144
|
+
} // if( x.isEmpty() )
|
|
145
|
+
} // strictIfThenElse
|
|
146
|
+
else if (tag === IRNativeTag.equalsInteger
|
|
147
|
+
&& restArgs.length === 1) {
|
|
148
|
+
const sndArg = restArgs[0];
|
|
149
|
+
const fstInt = getConstInt(fstArg);
|
|
150
|
+
const sndInt = getConstInt(sndArg);
|
|
151
|
+
if (fstInt === BigInt(0)) {
|
|
152
|
+
// replace as `isZero( sndArg )`
|
|
153
|
+
const newTerm = _ir_apps(IRNative._isZero, sndArg);
|
|
154
|
+
modifyTermAndPushToReprocess(current, newTerm);
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
else if (sndInt === BigInt(0)) {
|
|
158
|
+
// replace as `isZero( fstArg )`
|
|
159
|
+
const newTerm = _ir_apps(IRNative._isZero, fstArg);
|
|
160
|
+
modifyTermAndPushToReprocess(current, newTerm);
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
else if (typeof fstInt === "bigint" && typeof sndInt === "bigint") {
|
|
164
|
+
// replace as constant
|
|
165
|
+
const newTerm = IRConst.bool(fstInt === sndInt);
|
|
166
|
+
modifyTermAndPushToReprocess(current, newTerm);
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
else if (typeof fstInt === "bigint") {
|
|
170
|
+
const newTerm = _ir_apps(new IRHoisted(_ir_apps(IRNative.equalsInteger, fstArg)), sndArg);
|
|
171
|
+
modifyTermAndPushToReprocess(current, newTerm);
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
else if (typeof sndInt === "bigint") {
|
|
175
|
+
const newTerm = _ir_apps(new IRHoisted(_ir_apps(IRNative.equalsInteger, sndArg)), fstArg);
|
|
176
|
+
modifyTermAndPushToReprocess(current, newTerm);
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
} // equalsInteger
|
|
180
|
+
else if (tag === IRNativeTag.addInteger
|
|
181
|
+
&& restArgs.length === 1) {
|
|
182
|
+
const sndArg = restArgs[0];
|
|
183
|
+
const fstInt = getConstInt(fstArg);
|
|
184
|
+
const sndInt = getConstInt(sndArg);
|
|
185
|
+
if (fstInt === BigInt(1)) {
|
|
186
|
+
// replace as `incr( sndArg )`
|
|
187
|
+
const newTerm = _ir_apps(IRNative._increment, sndArg);
|
|
188
|
+
modifyTermAndPushToReprocess(current, newTerm);
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
else if (sndInt === BigInt(1)) {
|
|
192
|
+
// replace as `incr( fstArg )`
|
|
193
|
+
const newTerm = _ir_apps(IRNative._increment, fstArg);
|
|
194
|
+
modifyTermAndPushToReprocess(current, newTerm);
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
else if (typeof fstInt === "bigint" && typeof sndInt === "bigint") {
|
|
198
|
+
// replace as constant
|
|
199
|
+
const newTerm = IRConst.int(fstInt + sndInt);
|
|
200
|
+
modifyTermAndPushToReprocess(current, newTerm);
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
else if (typeof fstInt === "bigint") {
|
|
204
|
+
const newTerm = _ir_apps(new IRHoisted(_ir_apps(IRNative.addInteger, fstArg)), sndArg);
|
|
205
|
+
modifyTermAndPushToReprocess(current, newTerm);
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
else if (typeof sndInt === "bigint") {
|
|
209
|
+
const newTerm = _ir_apps(new IRHoisted(_ir_apps(IRNative.addInteger, sndArg)), fstArg);
|
|
210
|
+
modifyTermAndPushToReprocess(current, newTerm);
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
} // addInteger
|
|
214
|
+
else if (tag === IRNativeTag.subtractInteger
|
|
215
|
+
&& restArgs.length === 1) {
|
|
216
|
+
const sndArg = restArgs[0];
|
|
217
|
+
const sndInt = getConstInt(sndArg);
|
|
218
|
+
if (sndInt === BigInt(1)) {
|
|
219
|
+
// replace as `decr( fstArg )`
|
|
220
|
+
const newTerm = _ir_apps(IRNative._decrement, fstArg);
|
|
221
|
+
modifyTermAndPushToReprocess(current, newTerm);
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
else if (typeof sndInt === "bigint") {
|
|
225
|
+
const newTerm = _ir_apps(new IRHoisted(_ir_apps(IRNative.addInteger, IRConst.int(-sndInt))), fstArg);
|
|
226
|
+
modifyTermAndPushToReprocess(current, newTerm);
|
|
227
|
+
continue;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
// only optimizations if first argument is constant after this point
|
|
38
232
|
if (!(fstArg instanceof IRConst)) {
|
|
39
233
|
stack.unshift(...current.children());
|
|
40
234
|
continue;
|
|
@@ -43,14 +237,7 @@ export function rewriteNativesAppliedToConstantsAndReturnRoot(term) {
|
|
|
43
237
|
&& (typeof fstArg.value === "bigint"
|
|
44
238
|
|| typeof fstArg.value === "number")) {
|
|
45
239
|
const newTerm = restArgs.length >= 1 ? _ir_apps(_compTimeDropN(fstArg.value), ...restArgs) : _compTimeDropN(fstArg.value);
|
|
46
|
-
|
|
47
|
-
_modifyChildFromTo(parent, current, newTerm);
|
|
48
|
-
}
|
|
49
|
-
else {
|
|
50
|
-
term = newTerm;
|
|
51
|
-
term.parent = undefined;
|
|
52
|
-
}
|
|
53
|
-
stack.unshift(newTerm);
|
|
240
|
+
modifyTermAndPushToReprocess(current, newTerm);
|
|
54
241
|
continue;
|
|
55
242
|
}
|
|
56
243
|
// const tsEnsureExhaustiveCheck: never = func;
|
|
@@ -83,3 +270,91 @@ function isId(term) {
|
|
|
83
270
|
&& term.body instanceof IRVar
|
|
84
271
|
&& term.body.name === term.params[0]));
|
|
85
272
|
}
|
|
273
|
+
function isNot(term) {
|
|
274
|
+
while (term instanceof IRHoisted
|
|
275
|
+
|| term instanceof IRLetted) {
|
|
276
|
+
if (term instanceof IRHoisted)
|
|
277
|
+
term = term.hoisted;
|
|
278
|
+
else if (term instanceof IRLetted)
|
|
279
|
+
term = term.value;
|
|
280
|
+
}
|
|
281
|
+
return (term instanceof IRNative
|
|
282
|
+
&& term.tag === IRNativeTag._not) || (equalIrHash(hoisted_not.hoisted.hash, term.hash));
|
|
283
|
+
}
|
|
284
|
+
function isNullList(term) {
|
|
285
|
+
while (term instanceof IRHoisted
|
|
286
|
+
|| term instanceof IRLetted) {
|
|
287
|
+
if (term instanceof IRHoisted)
|
|
288
|
+
term = term.hoisted;
|
|
289
|
+
else if (term instanceof IRLetted)
|
|
290
|
+
term = term.value;
|
|
291
|
+
}
|
|
292
|
+
return (term instanceof IRNative
|
|
293
|
+
&& term.tag === IRNativeTag.nullList);
|
|
294
|
+
}
|
|
295
|
+
function isEqualsZero(term) {
|
|
296
|
+
while (term instanceof IRHoisted
|
|
297
|
+
|| term instanceof IRLetted) {
|
|
298
|
+
if (term instanceof IRHoisted)
|
|
299
|
+
term = term.hoisted;
|
|
300
|
+
else if (term instanceof IRLetted)
|
|
301
|
+
term = term.value;
|
|
302
|
+
}
|
|
303
|
+
return (term instanceof IRNative
|
|
304
|
+
&& term.tag === IRNativeTag._isZero) || (equalIrHash(hoisted_isZero.hash, term.hash));
|
|
305
|
+
}
|
|
306
|
+
function isLessThanOrEqualInteger(term) {
|
|
307
|
+
while (term instanceof IRHoisted
|
|
308
|
+
|| term instanceof IRLetted) {
|
|
309
|
+
if (term instanceof IRHoisted)
|
|
310
|
+
term = term.hoisted;
|
|
311
|
+
else if (term instanceof IRLetted)
|
|
312
|
+
term = term.value;
|
|
313
|
+
}
|
|
314
|
+
return (term instanceof IRNative
|
|
315
|
+
&& term.tag === IRNativeTag.lessThanEqualInteger);
|
|
316
|
+
}
|
|
317
|
+
function isLessThanInteger(term) {
|
|
318
|
+
while (term instanceof IRHoisted
|
|
319
|
+
|| term instanceof IRLetted) {
|
|
320
|
+
if (term instanceof IRHoisted)
|
|
321
|
+
term = term.hoisted;
|
|
322
|
+
else if (term instanceof IRLetted)
|
|
323
|
+
term = term.value;
|
|
324
|
+
}
|
|
325
|
+
return (term instanceof IRNative
|
|
326
|
+
&& term.tag === IRNativeTag.lessThanInteger);
|
|
327
|
+
}
|
|
328
|
+
function isListLength(term) {
|
|
329
|
+
while (term instanceof IRHoisted
|
|
330
|
+
|| term instanceof IRLetted) {
|
|
331
|
+
if (term instanceof IRHoisted)
|
|
332
|
+
term = term.hoisted;
|
|
333
|
+
else if (term instanceof IRLetted)
|
|
334
|
+
term = term.value;
|
|
335
|
+
}
|
|
336
|
+
return (term instanceof IRNative
|
|
337
|
+
&& term.tag === IRNativeTag._length) || equalIrHash(hoisted_length.hash, term.hash);
|
|
338
|
+
}
|
|
339
|
+
function getConstInt(term) {
|
|
340
|
+
if (term instanceof IRConst
|
|
341
|
+
&& term.type instanceof TirIntT
|
|
342
|
+
&& typeof term.value === "bigint")
|
|
343
|
+
return term.value;
|
|
344
|
+
return undefined;
|
|
345
|
+
}
|
|
346
|
+
// function isConstIntOne( term: IRTerm ): boolean
|
|
347
|
+
// {
|
|
348
|
+
// return (
|
|
349
|
+
// term instanceof IRConst
|
|
350
|
+
// && term.type instanceof TirIntT
|
|
351
|
+
// && term.value === BigInt( 1 )
|
|
352
|
+
// );
|
|
353
|
+
// }
|
|
354
|
+
function getConstBool(term) {
|
|
355
|
+
if (term instanceof IRConst
|
|
356
|
+
&& term.type instanceof TirBoolT
|
|
357
|
+
&& typeof term.value === "boolean")
|
|
358
|
+
return term.value;
|
|
359
|
+
return undefined;
|
|
360
|
+
}
|
|
@@ -54,7 +54,7 @@ function _isClosedIRTerm(term, boundedVars, parent) {
|
|
|
54
54
|
return _isClosedIRTerm(term.delayed, boundedVars, term);
|
|
55
55
|
const tsEnsureExhaustiveCheck = term;
|
|
56
56
|
// not even an IRTerm
|
|
57
|
-
console.
|
|
57
|
+
console.error(parent);
|
|
58
58
|
throw new Error("`isClosedIRTerm` called on non-IR argument");
|
|
59
59
|
}
|
|
60
60
|
export function isClosedIRTerm(term) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { fromHex } from "@harmoniclabs/uint8array-utils";
|
|
2
|
-
import UPLCFlatUtils from "../../utils/UPLCFlatUtils/index.js";
|
|
2
|
+
import { UPLCFlatUtils } from "../../utils/UPLCFlatUtils/index.js";
|
|
3
3
|
/**
|
|
4
4
|
* writes the number in a new `Uint8Array` Big Endian
|
|
5
5
|
*/
|
|
@@ -8,8 +8,6 @@ export function positiveIntAsBytes(n) {
|
|
|
8
8
|
return positiveBigIntAsBytes(n);
|
|
9
9
|
}
|
|
10
10
|
if (!Number.isSafeInteger(n) || n < 0) {
|
|
11
|
-
console.log(n);
|
|
12
|
-
console.trace(); // some help
|
|
13
11
|
throw new Error("how did you end up here? the name of the function explicitly says 'positiveIntAsBytes'");
|
|
14
12
|
}
|
|
15
13
|
let str = n.toString(16);
|
|
@@ -18,8 +16,6 @@ export function positiveIntAsBytes(n) {
|
|
|
18
16
|
}
|
|
19
17
|
export function positiveBigIntAsBytes(n) {
|
|
20
18
|
if (n < 0 || typeof n !== "bigint") {
|
|
21
|
-
console.log(n);
|
|
22
|
-
console.trace(); // some help
|
|
23
19
|
throw new Error("how did you end up here? the name of the function explicitly says 'positiveBigIntAsBytes'");
|
|
24
20
|
}
|
|
25
21
|
let strHex = n.toString(16);
|
|
@@ -41,6 +41,8 @@ export declare class AstCompiler extends DiagnosticEmitter {
|
|
|
41
41
|
readonly parsedAstSources: Map<string, Source>;
|
|
42
42
|
get rootPath(): string;
|
|
43
43
|
constructor(cfg: CompilerOptions, io?: CompilerIoApi, diagnostics?: DiagnosticMessage[]);
|
|
44
|
+
private _isExporting;
|
|
45
|
+
export(funcName: string, modulePath?: string): Promise<TypedProgram>;
|
|
44
46
|
/**
|
|
45
47
|
* compiles the entry file specified in the config
|
|
46
48
|
*
|
|
@@ -56,6 +58,7 @@ export declare class AstCompiler extends DiagnosticEmitter {
|
|
|
56
58
|
private _compileParsedSource;
|
|
57
59
|
private _collectAllTopLevelSignatures;
|
|
58
60
|
private _collectInterfaceImplSigs;
|
|
61
|
+
private _collectTopLevelConst;
|
|
59
62
|
private _collectTopLevelFuncDeclSig;
|
|
60
63
|
private _collectInterfaceDeclarations;
|
|
61
64
|
registerInternalTypeDecl(decl: StructDecl | TypeAliasDecl): void;
|
|
@@ -33,6 +33,9 @@ import { _compileFuncExpr } from "./internal/exprs/_compileFuncExpr.js";
|
|
|
33
33
|
import { ContractDecl } from "../../ast/nodes/statements/declarations/ContractDecl.js";
|
|
34
34
|
import { _deriveContractBody } from "./internal/_deriveContractBody/_deriveContractBody.js";
|
|
35
35
|
import { DiagnosticCategory } from "../../diagnostics/DiagnosticCategory.js";
|
|
36
|
+
import { VarStmt } from "../../ast/nodes/statements/VarStmt.js";
|
|
37
|
+
import { _compileSimpleVarDecl } from "./internal/statements/_compileVarStmt.js";
|
|
38
|
+
import { isIdentifier } from "../../utils/text.js";
|
|
36
39
|
/*
|
|
37
40
|
Handling type expressions that depend on other types
|
|
38
41
|
(such as generics, function return types, and inferred types from complex expressions)
|
|
@@ -82,6 +85,24 @@ export class AstCompiler extends DiagnosticEmitter {
|
|
|
82
85
|
this.cfg = cfg;
|
|
83
86
|
this.io = io;
|
|
84
87
|
this.program = new TypedProgram(this.diagnostics);
|
|
88
|
+
this._isExporting = false;
|
|
89
|
+
}
|
|
90
|
+
_isExporting;
|
|
91
|
+
async export(funcName, modulePath) {
|
|
92
|
+
this._isExporting = true;
|
|
93
|
+
if (typeof funcName !== "string")
|
|
94
|
+
throw new Error("AstCompiler.export: funcName must be a string");
|
|
95
|
+
funcName = funcName.trim();
|
|
96
|
+
if (funcName === "" || !isIdentifier(funcName))
|
|
97
|
+
throw new Error("AstCompiler.export: funcName must be a valid function identifier");
|
|
98
|
+
if (typeof modulePath === "string") {
|
|
99
|
+
const nextEntryPath = modulePath;
|
|
100
|
+
if (!nextEntryPath)
|
|
101
|
+
throw new Error("AstCompiler.export: modulePath not found: " + modulePath);
|
|
102
|
+
this.cfg.entry = nextEntryPath;
|
|
103
|
+
}
|
|
104
|
+
this.program.contractTirFuncName = funcName;
|
|
105
|
+
return await this.compile();
|
|
85
106
|
}
|
|
86
107
|
/**
|
|
87
108
|
* compiles the entry file specified in the config
|
|
@@ -113,6 +134,7 @@ export class AstCompiler extends DiagnosticEmitter {
|
|
|
113
134
|
}
|
|
114
135
|
const mainFuncExpr = this.program.functions.get(this.program.contractTirFuncName);
|
|
115
136
|
if (this.program.contractTirFuncName === "" || !mainFuncExpr) {
|
|
137
|
+
console.log([...this.program.functions.keys()]);
|
|
116
138
|
console.error(mainFuncExpr, `"${this.program.contractTirFuncName}"`);
|
|
117
139
|
this.error(DiagnosticCode.Contract_is_missing, undefined);
|
|
118
140
|
return this.program;
|
|
@@ -167,7 +189,7 @@ export class AstCompiler extends DiagnosticEmitter {
|
|
|
167
189
|
this._srcDonelogUids.add(src.uid);
|
|
168
190
|
}
|
|
169
191
|
_collectAllTopLevelSignatures(stmts, srcUid, topLevelScope, srcExports, isEntryFile = false) {
|
|
170
|
-
for (let i = 0; i < stmts.length; i++) {
|
|
192
|
+
top_level_stmts_iter: for (let i = 0; i < stmts.length; i++) {
|
|
171
193
|
let stmt = stmts[i];
|
|
172
194
|
let exported = false;
|
|
173
195
|
let exportRange = undefined;
|
|
@@ -178,13 +200,36 @@ export class AstCompiler extends DiagnosticEmitter {
|
|
|
178
200
|
}
|
|
179
201
|
if (!(stmt instanceof FuncDecl
|
|
180
202
|
|| stmt instanceof TypeImplementsStmt
|
|
181
|
-
|| stmt instanceof ContractDecl
|
|
203
|
+
|| stmt instanceof ContractDecl
|
|
204
|
+
|| stmt instanceof VarStmt))
|
|
205
|
+
continue;
|
|
206
|
+
if (stmt instanceof VarStmt) {
|
|
207
|
+
const nDecl = stmt.declarations.length;
|
|
208
|
+
for (let dI = 0; dI < nDecl; dI++) {
|
|
209
|
+
const decl = stmt.declarations[dI];
|
|
210
|
+
if (!(decl.isConst()
|
|
211
|
+
&& decl instanceof SimpleVarDecl)) {
|
|
212
|
+
this.error(DiagnosticCode.Only_constants_can_be_declared_outside_of_a_function, stmt.range);
|
|
213
|
+
// remove from array so we don't process it again
|
|
214
|
+
void stmts.splice(i, 1);
|
|
215
|
+
i--;
|
|
216
|
+
continue top_level_stmts_iter;
|
|
217
|
+
}
|
|
218
|
+
this._collectTopLevelConst(decl, srcUid, topLevelScope, srcExports, exportRange, isEntryFile);
|
|
219
|
+
}
|
|
220
|
+
// remove from array so we don't process it again
|
|
221
|
+
void stmts.splice(i, 1);
|
|
222
|
+
i--;
|
|
182
223
|
continue;
|
|
224
|
+
}
|
|
183
225
|
if (exported && stmt instanceof TypeImplementsStmt)
|
|
184
226
|
this.error(DiagnosticCode.Interface_implementations_cannot_be_exported, exportRange ?? stmt.range);
|
|
185
227
|
if (stmt instanceof ContractDecl) {
|
|
228
|
+
if (!(
|
|
186
229
|
// ignore contract declarations if not in the entry file
|
|
187
|
-
|
|
230
|
+
isEntryFile
|
|
231
|
+
// ignore contract decalarations if we are exporting a specific function
|
|
232
|
+
|| this._isExporting)) {
|
|
188
233
|
// remove from array so we don't process it again
|
|
189
234
|
void stmts.splice(i, 1);
|
|
190
235
|
i--;
|
|
@@ -259,10 +304,28 @@ export class AstCompiler extends DiagnosticEmitter {
|
|
|
259
304
|
this.program.functions.set(tirMethodName, funcExpr);
|
|
260
305
|
}
|
|
261
306
|
}
|
|
307
|
+
_collectTopLevelConst(decl, srcUid, topLevelScope, srcExports = undefined, exportRange = undefined, isEntryFile = false) {
|
|
308
|
+
const astName = decl.name.text;
|
|
309
|
+
// const tirConstName = PEBBLE_INTERNAL_IDENTIFIER_PREFIX + astName + "_" + srcUid;
|
|
310
|
+
const declContext = AstCompilationCtx.fromScope(this.program, topLevelScope);
|
|
311
|
+
const tirVarDecl = _compileSimpleVarDecl(declContext, decl, undefined // type hint (extracted from init expr if explicit, or inferred from expression)
|
|
312
|
+
);
|
|
313
|
+
if (!tirVarDecl)
|
|
314
|
+
return undefined;
|
|
315
|
+
if (!tirVarDecl.initExpr)
|
|
316
|
+
return this.error(DiagnosticCode._const_declarations_must_be_initialized, tirVarDecl.range);
|
|
317
|
+
if (this.program.constants.has(astName)) {
|
|
318
|
+
throw new Error("not_implemented::AstCompiler::_collectTopLevelConst::const_redefinition_check");
|
|
319
|
+
}
|
|
320
|
+
this.program.constants.set(astName, tirVarDecl);
|
|
321
|
+
}
|
|
262
322
|
_collectTopLevelFuncDeclSig(stmt, srcUid, topLevelScope, srcExports = undefined, exportRange = undefined, isEntryFile = false) {
|
|
263
323
|
const astFuncExpr = stmt.expr;
|
|
264
324
|
const astFuncName = astFuncExpr.name.text;
|
|
265
325
|
const tirFuncName = PEBBLE_INTERNAL_IDENTIFIER_PREFIX + astFuncName + "_" + srcUid;
|
|
326
|
+
if (this._isExporting && astFuncName === this.program.contractTirFuncName) {
|
|
327
|
+
this.program.contractTirFuncName = tirFuncName;
|
|
328
|
+
}
|
|
266
329
|
const declContext = AstCompilationCtx.fromScope(this.program, topLevelScope);
|
|
267
330
|
const funcExpr = _compileFuncExpr(declContext, astFuncExpr, undefined, // sig
|
|
268
331
|
false // isMethod
|
|
@@ -739,7 +739,7 @@ function _exprReplaceParamsAndAssertNoLitContext(compiler, expr, paramsInternalN
|
|
|
739
739
|
return expr;
|
|
740
740
|
}
|
|
741
741
|
const tsEnsureExhaustiveCheck = expr;
|
|
742
|
-
console.
|
|
742
|
+
console.error(expr);
|
|
743
743
|
throw new Error("unreachable::_exprReplaceParamsAndAssertNoLitContext");
|
|
744
744
|
}
|
|
745
745
|
function _deriveRedeemerTypeDef(redeemerName, methods, contractRange) {
|
|
@@ -11,6 +11,7 @@ import { TernaryExpr } from "../../../../ast/nodes/expr/TernaryExpr.js";
|
|
|
11
11
|
import { TypeConversionExpr } from "../../../../ast/nodes/expr/TypeConversionExpr.js";
|
|
12
12
|
import { NonNullExpr } from "../../../../ast/nodes/expr/unary/NonNullExpr.js";
|
|
13
13
|
import { isUnaryPrefixExpr } from "../../../../ast/nodes/expr/unary/UnaryPrefixExpr.js";
|
|
14
|
+
import { isTirExpr } from "../../../tir/expressions/TirExpr.js";
|
|
14
15
|
import { _compileBinaryExpr } from "./_compileBinaryExpr.js";
|
|
15
16
|
import { _compileCallExpr } from "./_compileCallExpr.js";
|
|
16
17
|
import { _compileCaseExpr } from "./_compileCaseExpr.js";
|
|
@@ -41,6 +42,9 @@ export function _compileExpr(ctx, expr,
|
|
|
41
42
|
* if that is the case, it needs to be checked OUTSIDE this function
|
|
42
43
|
**/
|
|
43
44
|
typeHint) {
|
|
45
|
+
// already compiled (TODO: how did we get here?)
|
|
46
|
+
if (isTirExpr(expr))
|
|
47
|
+
return expr;
|
|
44
48
|
if (expr instanceof Identifier)
|
|
45
49
|
return _compileVarAccessExpr(ctx, expr, typeHint);
|
|
46
50
|
if (isUnaryPrefixExpr(expr))
|
|
@@ -74,10 +74,16 @@ export function _compileFuncExpr(ctx, expr, expectedFuncType, isMethod = false)
|
|
|
74
74
|
}
|
|
75
75
|
const returnType = expectedFuncType.returnType;
|
|
76
76
|
const funcCtx = ctx.newFunctionChildScope(returnType, isMethod);
|
|
77
|
+
// define value in case of recursion
|
|
78
|
+
funcCtx.scope.defineValue({
|
|
79
|
+
name: expr.name.text,
|
|
80
|
+
type: expectedFuncType,
|
|
81
|
+
isConstant: true,
|
|
82
|
+
});
|
|
77
83
|
// if( _hasDuplicateTypeParams( ctx, expr.typeParams ) ) return undefined;
|
|
78
84
|
if (expr.typeParams.length > 0)
|
|
79
85
|
return ctx.error(DiagnosticCode.Not_implemented_0, expr.typeParams[0].range, "generic functions");
|
|
80
|
-
const destructuredParamsResult = _getDestructuredParamsAsVarDecls(funcCtx, expr);
|
|
86
|
+
const destructuredParamsResult = _getDestructuredParamsAsVarDecls(funcCtx, expr, expectedFuncType);
|
|
81
87
|
if (!destructuredParamsResult)
|
|
82
88
|
return undefined;
|
|
83
89
|
const { blockInitStmts, params } = destructuredParamsResult;
|
|
@@ -91,11 +97,14 @@ export function _compileFuncExpr(ctx, expr, expectedFuncType, isMethod = false)
|
|
|
91
97
|
const funcExpr = new TirFuncExpr(expr.name.text, params, returnType, body, expr.range);
|
|
92
98
|
return funcExpr;
|
|
93
99
|
}
|
|
94
|
-
function _getDestructuredParamsAsVarDecls(funcCtx, expr) {
|
|
100
|
+
function _getDestructuredParamsAsVarDecls(funcCtx, expr, expectedFuncType) {
|
|
95
101
|
const blockInitStmts = [];
|
|
96
102
|
const params = [];
|
|
97
|
-
|
|
98
|
-
|
|
103
|
+
const nParams = expr.signature.params.length;
|
|
104
|
+
for (let i = 0; i < nParams; i++) {
|
|
105
|
+
const astParam = expr.signature.params[i];
|
|
106
|
+
const paramTypeHint = expectedFuncType.argTypes[i];
|
|
107
|
+
const tirParam = _compileVarDecl(funcCtx, astParam, paramTypeHint);
|
|
99
108
|
if (!tirParam)
|
|
100
109
|
return undefined;
|
|
101
110
|
if (tirParam instanceof TirSimpleVarDecl) {
|
|
@@ -7,7 +7,6 @@ export function _compileTypeConversionExpr(ctx, ast, typeHint) {
|
|
|
7
7
|
const data_t = ctx.program.stdTypes.data;
|
|
8
8
|
const possibleTargetTypeTirNames = ctx.scope.resolveType(ast.asType.toAstName());
|
|
9
9
|
if (!possibleTargetTypeTirNames) {
|
|
10
|
-
console.log(ctx.scope);
|
|
11
10
|
return ctx.error(DiagnosticCode._0_is_not_defined, ast.asType.range, ast.asType.toAstName());
|
|
12
11
|
}
|
|
13
12
|
const sopTargetType = ctx.program.types.get(possibleTargetTypeTirNames.sopTirName);
|
|
@@ -2,8 +2,10 @@ import { DiagnosticCode } from "../../../../diagnostics/diagnosticMessages.gener
|
|
|
2
2
|
import { TirVariableAccessExpr } from "../../../tir/expressions/TirVariableAccessExpr.js";
|
|
3
3
|
export function _compileVarAccessExpr(ctx, expr, typeHint) {
|
|
4
4
|
const resolvedValue = ctx.scope.resolveValue(expr.text);
|
|
5
|
-
if (!resolvedValue)
|
|
5
|
+
if (!resolvedValue) {
|
|
6
|
+
console.trace(ctx.scope.allVariables(), expr.text);
|
|
6
7
|
return ctx.error(DiagnosticCode._0_is_not_defined, expr.range, expr.text);
|
|
8
|
+
}
|
|
7
9
|
// const { variableInfos, isDefinedOutsideFuncScope } = resolvedValue;
|
|
8
10
|
return new TirVariableAccessExpr(resolvedValue, expr.range);
|
|
9
11
|
}
|
|
@@ -20,9 +20,9 @@ export function _compileAssignmentStmt(ctx, stmt) {
|
|
|
20
20
|
if (!canAssignTo(varType, int_t))
|
|
21
21
|
return ctx.error(DiagnosticCode.Type_0_is_not_assignable_to_type_1, stmt.varIdentifier.range, varType.toString(), int_t.toString());
|
|
22
22
|
const varAccessExpr = new TirVariableAccessExpr(resolvedValue, stmt.varIdentifier.range);
|
|
23
|
-
return ([new TirAssignmentStmt(varAccessExpr, stmt instanceof IncrStmt ?
|
|
24
|
-
new TirAddExpr(varAccessExpr, new TirLitIntExpr(BigInt(1), stmt.range), stmt.range) :
|
|
25
|
-
new TirSubExpr(varAccessExpr, new TirLitIntExpr(BigInt(1), stmt.range), stmt.range), stmt.range)]);
|
|
23
|
+
return ([new TirAssignmentStmt(varAccessExpr.clone(), stmt instanceof IncrStmt ?
|
|
24
|
+
new TirAddExpr(varAccessExpr.clone(), new TirLitIntExpr(BigInt(1), stmt.range), stmt.range) :
|
|
25
|
+
new TirSubExpr(varAccessExpr.clone(), new TirLitIntExpr(BigInt(1), stmt.range), stmt.range), stmt.range)]);
|
|
26
26
|
}
|
|
27
27
|
if (isExplicitAssignmentStmt(stmt)) {
|
|
28
28
|
const tirStmt = _compileExplicitAssignmentStmt(ctx, stmt);
|
|
@@ -31,7 +31,7 @@ export function _compileAssignmentStmt(ctx, stmt) {
|
|
|
31
31
|
return [tirStmt];
|
|
32
32
|
}
|
|
33
33
|
else {
|
|
34
|
-
const tsEnsureExhautstiveCheck = stmt;
|
|
34
|
+
// const tsEnsureExhautstiveCheck: never = stmt;
|
|
35
35
|
console.error(stmt);
|
|
36
36
|
throw new Error("unreachable::AstCompiler::_compileForUpdateStmts");
|
|
37
37
|
}
|
|
@@ -61,13 +61,13 @@ export function _compileExplicitAssignmentStmt(ctx, stmt) {
|
|
|
61
61
|
expr = __getBinOpAssignmentLeftArg(ctx, stmt, varType, int_t);
|
|
62
62
|
if (!expr)
|
|
63
63
|
return undefined;
|
|
64
|
-
expr = new TirAddExpr(varAccessExpr, expr, stmt.range);
|
|
64
|
+
expr = new TirAddExpr(varAccessExpr.clone(), expr.clone(), stmt.range);
|
|
65
65
|
}
|
|
66
66
|
else if (stmt instanceof SubAssignmentStmt) {
|
|
67
67
|
expr = __getBinOpAssignmentLeftArg(ctx, stmt, varType, int_t);
|
|
68
68
|
if (!expr)
|
|
69
69
|
return undefined;
|
|
70
|
-
expr = new TirSubExpr(varAccessExpr, expr, stmt.range);
|
|
70
|
+
expr = new TirSubExpr(varAccessExpr.clone(), expr.clone(), stmt.range);
|
|
71
71
|
}
|
|
72
72
|
else if (stmt instanceof ExpAssignmentStmt) {
|
|
73
73
|
expr = __getBinOpAssignmentLeftArg(ctx, stmt, varType, int_t);
|
|
@@ -140,7 +140,7 @@ export function _compileExplicitAssignmentStmt(ctx, stmt) {
|
|
|
140
140
|
console.error(stmt);
|
|
141
141
|
throw new Error("unreachable::AstCompiler::_compileExplicitAssignmentStmt");
|
|
142
142
|
}
|
|
143
|
-
return new TirAssignmentStmt(varAccessExpr, expr, stmt.range);
|
|
143
|
+
return new TirAssignmentStmt(varAccessExpr.clone(), expr, stmt.range);
|
|
144
144
|
}
|
|
145
145
|
export function __getBinOpAssignmentLeftArg(ctx, stmt, varType, exprType) {
|
|
146
146
|
if (!canAssignTo(varType, exprType))
|