@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.
Files changed (76) hide show
  1. package/dist/IR/IRNodes/IRConst.js +1 -1
  2. package/dist/IR/IRNodes/IRNative/IRNativeTag.d.ts +6 -3
  3. package/dist/IR/IRNodes/IRNative/IRNativeTag.js +12 -4
  4. package/dist/IR/IRNodes/IRNative/index.d.ts +5 -2
  5. package/dist/IR/IRNodes/IRNative/index.js +6 -2
  6. package/dist/IR/toUPLC/CompilerOptions.d.ts +6 -1
  7. package/dist/IR/toUPLC/CompilerOptions.js +11 -1
  8. package/dist/IR/toUPLC/compileIRToUPLC.js +34 -35
  9. package/dist/IR/toUPLC/ctx/ToUplcCtx.js +2 -10
  10. package/dist/IR/toUPLC/subRoutines/handleLetted/groupByScope.js +0 -2
  11. package/dist/IR/toUPLC/subRoutines/handleLetted/index.js +69 -3
  12. package/dist/IR/toUPLC/subRoutines/replaceNatives/nativeToIR.d.ts +3 -1
  13. package/dist/IR/toUPLC/subRoutines/replaceNatives/nativeToIR.js +42 -10
  14. package/dist/IR/toUPLC/subRoutines/rewriteNativesAppliedToConstantsAndReturnRoot.js +292 -17
  15. package/dist/IR/utils/isClosedIRTerm.js +1 -1
  16. package/dist/IR/utils/positiveIntAsBytes.js +1 -5
  17. package/dist/compiler/AstCompiler/AstCompiler.d.ts +3 -0
  18. package/dist/compiler/AstCompiler/AstCompiler.js +66 -3
  19. package/dist/compiler/AstCompiler/internal/_deriveContractBody/_deriveContractBody.js +1 -1
  20. package/dist/compiler/AstCompiler/internal/exprs/_compileExpr.js +4 -0
  21. package/dist/compiler/AstCompiler/internal/exprs/_compileFuncExpr.js +13 -4
  22. package/dist/compiler/AstCompiler/internal/exprs/_compileTypeConversionExpr.js +0 -1
  23. package/dist/compiler/AstCompiler/internal/exprs/_compileVarAccessExpr.js +3 -1
  24. package/dist/compiler/AstCompiler/internal/statements/_compileAssignmentStmt.js +7 -7
  25. package/dist/compiler/AstCompiler/internal/statements/_compileVarStmt.d.ts +2 -1
  26. package/dist/compiler/AstCompiler/internal/statements/_compileVarStmt.js +2 -1
  27. package/dist/compiler/AstCompiler/scope/AstScope.d.ts +1 -0
  28. package/dist/compiler/AstCompiler/scope/AstScope.js +5 -0
  29. package/dist/compiler/Compiler.d.ts +8 -1
  30. package/dist/compiler/Compiler.js +38 -1
  31. package/dist/compiler/TirCompiler/compileTirProgram.js +2 -1
  32. package/dist/compiler/TirCompiler/expressify/ExpressifyCtx.d.ts +4 -2
  33. package/dist/compiler/TirCompiler/expressify/ExpressifyCtx.js +42 -16
  34. package/dist/compiler/TirCompiler/expressify/determineReassignedVariablesAndReturn.js +2 -0
  35. package/dist/compiler/TirCompiler/expressify/expressify.js +26 -9
  36. package/dist/compiler/TirCompiler/expressify/expressifyForStmt.js +23 -7
  37. package/dist/compiler/TirCompiler/expressify/expressifyVarAssignmentStmt.d.ts +1 -2
  38. package/dist/compiler/TirCompiler/expressify/expressifyVarAssignmentStmt.js +15 -8
  39. package/dist/compiler/TirCompiler/expressify/expressifyVarDecl.js +6 -9
  40. package/dist/compiler/TirCompiler/expressify/expressifyVars.js +51 -16
  41. package/dist/compiler/TirCompiler/expressify/flattenSopNamedDeconstructInplace_addTopDestructToCtx_getNestedDeconstruct.js +1 -0
  42. package/dist/compiler/internalVar.d.ts +1 -1
  43. package/dist/compiler/internalVar.js +31 -24
  44. package/dist/compiler/io/CompilerIoApi.d.ts +1 -1
  45. package/dist/compiler/tir/expressions/TirCallExpr.d.ts +1 -1
  46. package/dist/compiler/tir/expressions/TirCallExpr.js +1 -1
  47. package/dist/compiler/tir/expressions/TirCaseExpr.js +2 -0
  48. package/dist/compiler/tir/expressions/TirFromDataExpr.js +2 -2
  49. package/dist/compiler/tir/expressions/TirFuncExpr.d.ts +1 -1
  50. package/dist/compiler/tir/expressions/TirFuncExpr.js +1 -1
  51. package/dist/compiler/tir/expressions/TirLettedExpr.d.ts +2 -2
  52. package/dist/compiler/tir/expressions/TirLettedExpr.js +4 -6
  53. package/dist/compiler/tir/expressions/TirNativeFunc.d.ts +3 -2
  54. package/dist/compiler/tir/expressions/TirNativeFunc.js +33 -12
  55. package/dist/compiler/tir/expressions/TirPropAccessExpr.js +1 -2
  56. package/dist/compiler/tir/expressions/TirVariableAccessExpr.d.ts +0 -1
  57. package/dist/compiler/tir/expressions/TirVariableAccessExpr.js +9 -5
  58. package/dist/compiler/tir/expressions/ToIRTermCtx.d.ts +3 -0
  59. package/dist/compiler/tir/expressions/ToIRTermCtx.js +8 -1
  60. package/dist/compiler/tir/expressions/binary/TirBinaryExpr.d.ts +1 -0
  61. package/dist/compiler/tir/expressions/binary/TirBinaryExpr.js +6 -1
  62. package/dist/compiler/tir/program/TypedProgram.d.ts +2 -2
  63. package/dist/compiler/tir/program/stdScope/stdScope.js +9 -23
  64. package/dist/compiler/tir/statements/TirIfStmt.d.ts +0 -1
  65. package/dist/compiler/tir/statements/TirIfStmt.js +0 -3
  66. package/dist/parser/Parser.js +18 -2
  67. package/dist/parser/Precedence.js +1 -0
  68. package/dist/utils/BitUtils/index.d.ts +1 -1
  69. package/dist/utils/BitUtils/index.js +1 -1
  70. package/dist/utils/IsSingleKey.d.ts +1 -1
  71. package/dist/utils/UPLCFlatUtils/index.d.ts +1 -1
  72. package/dist/utils/UPLCFlatUtils/index.js +2 -2
  73. package/dist/utils/array/keepSortedArrInplace.js +1 -0
  74. package/package.json +7 -6
  75. package/dist/compiler/TirCompiler/internal/_compileHoistedDeps.d.ts +0 -5
  76. 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
- if (parent) {
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
- if (parent) {
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.log(parent);
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
- if (!isEntryFile) {
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.log(expr);
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
- for (const astParam of expr.signature.params) {
98
- const tirParam = _compileVarDecl(funcCtx, astParam, undefined);
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))