bit2 0.0.1

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 (138) hide show
  1. package/dist/bit2.d.ts +229 -0
  2. package/dist/bit2.js +1 -0
  3. package/dist/src/bx/biEval.d.ts +6 -0
  4. package/dist/src/bx/biEval.js +59 -0
  5. package/dist/src/bx/biEval.js.map +1 -0
  6. package/dist/src/common/Exp.d.ts +53 -0
  7. package/dist/src/common/Exp.js +44 -0
  8. package/dist/src/common/Exp.js.map +1 -0
  9. package/dist/src/common/PrettyPrint.d.ts +4 -0
  10. package/dist/src/common/PrettyPrint.js +32 -0
  11. package/dist/src/common/PrettyPrint.js.map +1 -0
  12. package/dist/src/common/Print.d.ts +3 -0
  13. package/dist/src/common/Print.js +73 -0
  14. package/dist/src/common/Print.js.map +1 -0
  15. package/dist/src/core/AST.d.ts +92 -0
  16. package/dist/src/core/AST.js +47 -0
  17. package/dist/src/core/AST.js.map +1 -0
  18. package/dist/src/core/PrettyPrint.d.ts +2 -0
  19. package/dist/src/core/PrettyPrint.js +64 -0
  20. package/dist/src/core/PrettyPrint.js.map +1 -0
  21. package/dist/src/core/Print.d.ts +3 -0
  22. package/dist/src/core/Print.js +77 -0
  23. package/dist/src/core/Print.js.map +1 -0
  24. package/dist/src/fuse/Fuse.d.ts +23 -0
  25. package/dist/src/fuse/Fuse.js +1436 -0
  26. package/dist/src/fuse/Fuse.js.map +1 -0
  27. package/dist/src/fuse/Print.d.ts +2 -0
  28. package/dist/src/fuse/Print.js +22 -0
  29. package/dist/src/fuse/Print.js.map +1 -0
  30. package/dist/src/fuse/Update.d.ts +19 -0
  31. package/dist/src/fuse/Update.js +3 -0
  32. package/dist/src/fuse/Update.js.map +1 -0
  33. package/dist/src/lambda/AST.d.ts +23 -0
  34. package/dist/src/lambda/AST.js +3 -0
  35. package/dist/src/lambda/AST.js.map +1 -0
  36. package/dist/src/lambda/Evaluation.d.ts +4 -0
  37. package/dist/src/lambda/Evaluation.js +98 -0
  38. package/dist/src/lambda/Evaluation.js.map +1 -0
  39. package/dist/src/lambda/Print.d.ts +2 -0
  40. package/dist/src/lambda/Print.js +31 -0
  41. package/dist/src/lambda/Print.js.map +1 -0
  42. package/dist/src/lambdalize/lambdalize.d.ts +3 -0
  43. package/dist/src/lambdalize/lambdalize.js +94 -0
  44. package/dist/src/lambdalize/lambdalize.js.map +1 -0
  45. package/dist/src/lambdalize/unLambdalize.d.ts +3 -0
  46. package/dist/src/lambdalize/unLambdalize.js +59 -0
  47. package/dist/src/lambdalize/unLambdalize.js.map +1 -0
  48. package/dist/src/partial/AST.d.ts +86 -0
  49. package/dist/src/partial/AST.js +3 -0
  50. package/dist/src/partial/AST.js.map +1 -0
  51. package/dist/src/partial/Print.d.ts +6 -0
  52. package/dist/src/partial/Print.js +93 -0
  53. package/dist/src/partial/Print.js.map +1 -0
  54. package/dist/src/partialEval/peval.d.ts +11 -0
  55. package/dist/src/partialEval/peval.js +322 -0
  56. package/dist/src/partialEval/peval.js.map +1 -0
  57. package/dist/src/partialEval/unpeval.d.ts +4 -0
  58. package/dist/src/partialEval/unpeval.js +360 -0
  59. package/dist/src/partialEval/unpeval.js.map +1 -0
  60. package/dist/src/surface/AST.d.ts +57 -0
  61. package/dist/src/surface/AST.js +3 -0
  62. package/dist/src/surface/AST.js.map +1 -0
  63. package/dist/src/surface/Parser.d.ts +4 -0
  64. package/dist/src/surface/Parser.js +314 -0
  65. package/dist/src/surface/Parser.js.map +1 -0
  66. package/dist/src/translate/Translate.d.ts +3 -0
  67. package/dist/src/translate/Translate.js +91 -0
  68. package/dist/src/translate/Translate.js.map +1 -0
  69. package/dist/src/utils/Utils.d.ts +2 -0
  70. package/dist/src/utils/Utils.js +7 -0
  71. package/dist/src/utils/Utils.js.map +1 -0
  72. package/dist/test/bx/biEval.test.d.ts +1 -0
  73. package/dist/test/bx/biEval.test.js +41 -0
  74. package/dist/test/bx/biEval.test.js.map +1 -0
  75. package/dist/test/bx/test.d.ts +1 -0
  76. package/dist/test/bx/test.js +29 -0
  77. package/dist/test/bx/test.js.map +1 -0
  78. package/dist/test/core/0.simple.test.d.ts +4 -0
  79. package/dist/test/core/0.simple.test.js +68 -0
  80. package/dist/test/core/0.simple.test.js.map +1 -0
  81. package/dist/test/core/1.core.test.d.ts +2 -0
  82. package/dist/test/core/1.core.test.js +30 -0
  83. package/dist/test/core/1.core.test.js.map +1 -0
  84. package/dist/test/core/core.test.d.ts +1 -0
  85. package/dist/test/core/core.test.js +28 -0
  86. package/dist/test/core/core.test.js.map +1 -0
  87. package/dist/test/fuse/branchnop.test.d.ts +1 -0
  88. package/dist/test/fuse/branchnop.test.js +47 -0
  89. package/dist/test/fuse/branchnop.test.js.map +1 -0
  90. package/dist/test/fuse/bulk.test.d.ts +1 -0
  91. package/dist/test/fuse/bulk.test.js +111 -0
  92. package/dist/test/fuse/bulk.test.js.map +1 -0
  93. package/dist/test/fuse/const.test.d.ts +1 -0
  94. package/dist/test/fuse/const.test.js +118 -0
  95. package/dist/test/fuse/const.test.js.map +1 -0
  96. package/dist/test/fuse/exp.test.d.ts +1 -0
  97. package/dist/test/fuse/exp.test.js +225 -0
  98. package/dist/test/fuse/exp.test.js.map +1 -0
  99. package/dist/test/fuse/lambda.test.d.ts +1 -0
  100. package/dist/test/fuse/lambda.test.js +139 -0
  101. package/dist/test/fuse/lambda.test.js.map +1 -0
  102. package/dist/test/fuse/loop.test.d.ts +1 -0
  103. package/dist/test/fuse/loop.test.js +39 -0
  104. package/dist/test/fuse/loop.test.js.map +1 -0
  105. package/dist/test/fuse/seq.test.d.ts +1 -0
  106. package/dist/test/fuse/seq.test.js +64 -0
  107. package/dist/test/fuse/seq.test.js.map +1 -0
  108. package/dist/test/fuse/space.test.d.ts +1 -0
  109. package/dist/test/fuse/space.test.js +136 -0
  110. package/dist/test/fuse/space.test.js.map +1 -0
  111. package/dist/test/lambda/evaluation.test.d.ts +1 -0
  112. package/dist/test/lambda/evaluation.test.js +24 -0
  113. package/dist/test/lambda/evaluation.test.js.map +1 -0
  114. package/dist/test/lambda/lambda.test.d.ts +1 -0
  115. package/dist/test/lambda/lambda.test.js +45 -0
  116. package/dist/test/lambda/lambda.test.js.map +1 -0
  117. package/dist/test/lambdalize/lambdalize.test.d.ts +1 -0
  118. package/dist/test/lambdalize/lambdalize.test.js +23 -0
  119. package/dist/test/lambdalize/lambdalize.test.js.map +1 -0
  120. package/dist/test/lambdalize/unLambdalize.test.d.ts +1 -0
  121. package/dist/test/lambdalize/unLambdalize.test.js +35 -0
  122. package/dist/test/lambdalize/unLambdalize.test.js.map +1 -0
  123. package/dist/test/partial/partial.test.d.ts +1 -0
  124. package/dist/test/partial/partial.test.js +35 -0
  125. package/dist/test/partial/partial.test.js.map +1 -0
  126. package/dist/test/partialEval/peval.test.d.ts +1 -0
  127. package/dist/test/partialEval/peval.test.js +29 -0
  128. package/dist/test/partialEval/peval.test.js.map +1 -0
  129. package/dist/test/partialEval/unPeval.test.d.ts +1 -0
  130. package/dist/test/partialEval/unPeval.test.js +40 -0
  131. package/dist/test/partialEval/unPeval.test.js.map +1 -0
  132. package/dist/test/surface/AST.test.d.ts +1 -0
  133. package/dist/test/surface/AST.test.js +41 -0
  134. package/dist/test/surface/AST.test.js.map +1 -0
  135. package/dist/test/translate/translate.test.d.ts +1 -0
  136. package/dist/test/translate/translate.test.js +45 -0
  137. package/dist/test/translate/translate.test.js.map +1 -0
  138. package/package.json +49 -0
@@ -0,0 +1,1436 @@
1
+ "use strict";
2
+ var __rest = (this && this.__rest) || function (s, e) {
3
+ var t = {};
4
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
5
+ t[p] = s[p];
6
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
7
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
8
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
9
+ t[p[i]] = s[p[i]];
10
+ }
11
+ return t;
12
+ };
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ const Utils_1 = require("../utils/Utils");
15
+ const Exp_1 = require("../common/Exp");
16
+ const peval_1 = require("../partialEval/peval");
17
+ const Print_1 = require("../partial/Print");
18
+ const Evaluation_1 = require("../lambda/Evaluation");
19
+ // Apply update to a TermNode and return the updated TermNode and remaining operation
20
+ function fuse(env, operation, term) {
21
+ // Check if the term is a ConstNode
22
+ if ((term.type === "const" ||
23
+ term.type === "sep" ||
24
+ term.type === "loopfront" ||
25
+ term.type === "looprear") &&
26
+ typeof term.value === "string") {
27
+ // add a new arr to env
28
+ if (term.type === "loopfront") {
29
+ let exp = term.lst;
30
+ if (exp.name) {
31
+ // Ensure exp is a Variable and has a name property
32
+ let expName = exp.name;
33
+ env[expName + "_new"] = [[], []]; // Set env[expName_new] to [[], []]
34
+ }
35
+ else {
36
+ throw new Error("exp is not a Variable with a name property in loopfront");
37
+ }
38
+ }
39
+ else if (term.type === "looprear") {
40
+ let exp = term.lst;
41
+ if (exp.name) {
42
+ let expName = exp.name;
43
+ env[expName] = env[expName + "_new"]; // assign back
44
+ }
45
+ else {
46
+ throw new Error("exp is not a Variable with a name property in loopfront");
47
+ }
48
+ }
49
+ const s_c = term.value;
50
+ switch (operation.type) {
51
+ case "insert":
52
+ const { str, position } = operation;
53
+ if (s_c.length === 0) {
54
+ return [
55
+ { newEnv: env, newTermNode: term, remainingOperation: operation },
56
+ {
57
+ newEnv: env,
58
+ newTermNode: Object.assign(Object.assign({}, term), { value: str }),
59
+ remainingOperation: { type: "id" },
60
+ },
61
+ ];
62
+ }
63
+ else if (position === 0) {
64
+ // 两种更新策略
65
+ return [
66
+ {
67
+ newEnv: Object.assign({}, env),
68
+ newTermNode: Object.assign(Object.assign({}, term), { value: str + s_c }),
69
+ remainingOperation: { type: "id" },
70
+ },
71
+ {
72
+ newEnv: Object.assign({}, env),
73
+ newTermNode: {
74
+ type: "seq",
75
+ nodes: [{ type: "const", value: str }, term],
76
+ },
77
+ remainingOperation: { type: "id" },
78
+ },
79
+ ];
80
+ }
81
+ else if (position < s_c.length) {
82
+ const newStr = s_c.slice(0, position) + str + s_c.slice(position);
83
+ return [
84
+ {
85
+ newEnv: env,
86
+ newTermNode: Object.assign(Object.assign({}, term), { value: newStr }),
87
+ remainingOperation: { type: "id" },
88
+ },
89
+ ];
90
+ }
91
+ else if (position === s_c.length) {
92
+ // 两种策略
93
+ return [
94
+ {
95
+ newEnv: Object.assign({}, env),
96
+ newTermNode: Object.assign(Object.assign({}, term), { value: s_c + str }),
97
+ remainingOperation: { type: "id" },
98
+ },
99
+ {
100
+ newEnv: Object.assign({}, env),
101
+ newTermNode: term,
102
+ remainingOperation: {
103
+ type: "insert",
104
+ str,
105
+ position: position - s_c.length,
106
+ },
107
+ },
108
+ ];
109
+ }
110
+ else {
111
+ const newPos = position - s_c.length;
112
+ return [
113
+ {
114
+ newEnv: env,
115
+ newTermNode: term,
116
+ remainingOperation: { type: "insert", str, position: newPos },
117
+ },
118
+ ];
119
+ }
120
+ case "delete":
121
+ const { str: delStr, position: delPos } = operation;
122
+ if (delPos === 0) {
123
+ if (s_c.startsWith(delStr) && delStr.length <= s_c.length) {
124
+ // 如果delStr===s_c,那么 newStr=""; 还有一个策略,即bot
125
+ const newStr = s_c.slice(delStr.length);
126
+ let result = [
127
+ {
128
+ newEnv: env,
129
+ newTermNode: Object.assign(Object.assign({}, term), { value: newStr }),
130
+ remainingOperation: { type: "id" },
131
+ },
132
+ ];
133
+ if (delStr.length === s_c.length) {
134
+ result.push({
135
+ newEnv: Object.assign({}, env),
136
+ //@ts-ignore
137
+ newTermNode: { type: "bot" },
138
+ remainingOperation: { type: "id" },
139
+ });
140
+ }
141
+ //@ts-ignore
142
+ return result;
143
+ }
144
+ else if (delStr.startsWith(s_c) && delStr.length > s_c.length) {
145
+ const remainingStr = delStr.slice(s_c.length);
146
+ return [
147
+ {
148
+ newEnv: env,
149
+ newTermNode: { type: "bot" },
150
+ remainingOperation: {
151
+ type: "delete",
152
+ str: remainingStr,
153
+ position: 0,
154
+ },
155
+ },
156
+ {
157
+ newEnv: Object.assign({}, env),
158
+ newTermNode: Object.assign(Object.assign({}, term), { value: "" }),
159
+ remainingOperation: {
160
+ type: "delete",
161
+ str: remainingStr,
162
+ position: 0,
163
+ },
164
+ },
165
+ ];
166
+ }
167
+ }
168
+ else if (delPos < s_c.length &&
169
+ delPos + delStr.length <= s_c.length) {
170
+ const newStr = s_c.slice(0, delPos) + s_c.slice(delPos + delStr.length);
171
+ return [
172
+ {
173
+ newEnv: env,
174
+ newTermNode: Object.assign(Object.assign({}, term), { value: newStr }),
175
+ remainingOperation: { type: "id" },
176
+ },
177
+ ];
178
+ }
179
+ else if (delPos < s_c.length && delPos + delStr.length > s_c.length) {
180
+ const remainingS_c = s_c.substring(0, delPos); // 保留s_c删除位置之前的部分
181
+ const remainingDelStr = delStr.substring(s_c.length - delPos); // 剩余需要删除的字符串
182
+ return [
183
+ {
184
+ newEnv: env,
185
+ newTermNode: { type: "const", value: remainingS_c },
186
+ remainingOperation: {
187
+ type: "delete",
188
+ str: remainingDelStr,
189
+ position: 0,
190
+ },
191
+ },
192
+ ];
193
+ }
194
+ else {
195
+ const newPos = delPos - s_c.length;
196
+ return [
197
+ {
198
+ newEnv: env,
199
+ newTermNode: term,
200
+ remainingOperation: {
201
+ type: "delete",
202
+ str: delStr,
203
+ position: newPos,
204
+ },
205
+ },
206
+ ];
207
+ }
208
+ case "replace":
209
+ const { str1, str2, position: repPos, } = operation;
210
+ if (repPos === 0) {
211
+ if (s_c.startsWith(str1) && str1.length <= s_c.length) {
212
+ const newStr = str2 + s_c.slice(str1.length);
213
+ return [
214
+ {
215
+ newEnv: env,
216
+ newTermNode: Object.assign(Object.assign({}, term), { value: newStr }),
217
+ remainingOperation: { type: "id" },
218
+ },
219
+ ];
220
+ }
221
+ else if (str1.startsWith(s_c) && str1.length > s_c.length) {
222
+ const remainingS_c = str2.slice(0, s_c.length);
223
+ const remainingStr1 = str1.slice(s_c.length);
224
+ const remainingStr2 = str2.slice(s_c.length);
225
+ return [
226
+ {
227
+ newEnv: env,
228
+ newTermNode: Object.assign(Object.assign({}, term), { value: remainingS_c }),
229
+ remainingOperation: {
230
+ type: "replace",
231
+ str1: remainingStr1,
232
+ str2: remainingStr2,
233
+ position: 0,
234
+ },
235
+ },
236
+ ];
237
+ }
238
+ }
239
+ else if (repPos < s_c.length && repPos + str1.length <= s_c.length) {
240
+ const newStr = s_c.slice(0, repPos) + str2 + s_c.slice(repPos + str1.length);
241
+ return [
242
+ {
243
+ newEnv: env,
244
+ newTermNode: Object.assign(Object.assign({}, term), { value: newStr }),
245
+ remainingOperation: { type: "id" },
246
+ },
247
+ ];
248
+ }
249
+ else if (repPos < s_c.length && repPos + str1.length > s_c.length) {
250
+ const part1 = s_c.substring(0, repPos); // 替换位置之前的部分
251
+ const overlapPart = s_c.substring(repPos); // 与替换的 str1 重叠的部分
252
+ const overlapStr2 = str2.substring(0, overlapPart.length);
253
+ const remainingStr1 = str1.substring(overlapPart.length); // 剩余需要替换的 str1 部分
254
+ const remainingStr2 = str2.substring(overlapPart.length); // 剩余替换的 str2 部分
255
+ const newOperation = {
256
+ type: "replace",
257
+ str1: remainingStr1,
258
+ str2: remainingStr2,
259
+ position: 0,
260
+ };
261
+ const newExpression = {
262
+ type: "const",
263
+ value: part1 + overlapStr2,
264
+ };
265
+ return [
266
+ {
267
+ newEnv: env,
268
+ newTermNode: newExpression,
269
+ remainingOperation: newOperation,
270
+ },
271
+ ];
272
+ }
273
+ else {
274
+ const newPos = repPos - s_c.length;
275
+ return [
276
+ {
277
+ newEnv: env,
278
+ newTermNode: Object.assign(Object.assign({}, term), { value: s_c }),
279
+ remainingOperation: {
280
+ type: "replace",
281
+ str1,
282
+ str2,
283
+ position: newPos,
284
+ },
285
+ },
286
+ ];
287
+ }
288
+ case "bulk":
289
+ return fuseBulk(env, operation, term);
290
+ case "id":
291
+ return [
292
+ {
293
+ newEnv: env,
294
+ newTermNode: term,
295
+ remainingOperation: { type: "id" },
296
+ },
297
+ ];
298
+ default:
299
+ const exhaustiveCheck = operation;
300
+ throw new Error(`Unhandled operation type: ${exhaustiveCheck}`);
301
+ }
302
+ }
303
+ else if (term.type === "space") {
304
+ switch (operation.type) {
305
+ case "insert":
306
+ const { str, position } = operation;
307
+ // zero-width space
308
+ if (term.width == 0) {
309
+ return [
310
+ { newEnv: env, newTermNode: term, remainingOperation: operation },
311
+ {
312
+ newEnv: Object.assign({}, env),
313
+ newTermNode: {
314
+ type: "seq",
315
+ nodes: [{ type: "const", value: str }, term],
316
+ },
317
+ remainingOperation: { type: "id" },
318
+ },
319
+ ];
320
+ }
321
+ else if (position == 0) {
322
+ // non-zero space
323
+ let resultList = [
324
+ {
325
+ newEnv: env,
326
+ newTermNode: {
327
+ type: "seq",
328
+ nodes: [{ type: "const", value: str }, term],
329
+ },
330
+ remainingOperation: { type: "id" },
331
+ },
332
+ ];
333
+ if (Utils_1.isWhitespace(str)) {
334
+ resultList.push({
335
+ newEnv: Object.assign({}, env),
336
+ newTermNode: {
337
+ type: "space",
338
+ width: term.width + str.length,
339
+ },
340
+ remainingOperation: { type: "id" },
341
+ });
342
+ }
343
+ return resultList;
344
+ }
345
+ else if (position < term.width) {
346
+ if (Utils_1.isWhitespace(str)) {
347
+ return [
348
+ {
349
+ newEnv: env,
350
+ newTermNode: Object.assign(Object.assign({}, term), { width: str.length + term.width }),
351
+ remainingOperation: { type: "id" },
352
+ },
353
+ ];
354
+ }
355
+ else {
356
+ throw new Error(`Cannot insert non-space between space term: ${operation}`);
357
+ }
358
+ }
359
+ else if (position === term.width) {
360
+ // 两种策略
361
+ let resultList = [
362
+ { newEnv: env, newTermNode: term, remainingOperation: operation },
363
+ ];
364
+ if (Utils_1.isWhitespace(str)) {
365
+ resultList.push({
366
+ newEnv: Object.assign({}, env),
367
+ newTermNode: Object.assign(Object.assign({}, term), { width: term.width + str.length }),
368
+ remainingOperation: { type: "id" },
369
+ });
370
+ }
371
+ return resultList;
372
+ }
373
+ else {
374
+ const newPos = position - term.width;
375
+ return [
376
+ {
377
+ newEnv: env,
378
+ newTermNode: term,
379
+ remainingOperation: { type: "insert", str, position: newPos },
380
+ },
381
+ ];
382
+ }
383
+ case "delete":
384
+ const { str: delStr, position: delPos } = operation;
385
+ if (delPos === 0) {
386
+ if (Utils_1.isWhitespace(delStr) && delStr.length <= term.width) {
387
+ // 如果delStr===s_c,还有一个策略, 即bot
388
+ const newWidth = term.width - delStr.length;
389
+ let result = [
390
+ {
391
+ newEnv: env,
392
+ newTermNode: Object.assign(Object.assign({}, term), { width: newWidth }),
393
+ remainingOperation: { type: "id" },
394
+ },
395
+ ];
396
+ // if (delStr.length === term.width) {
397
+ // result.push({
398
+ // newEnv: {...env},
399
+ // //@ts-ignore
400
+ // newTermNode: { type: "bot" },
401
+ // remainingOperation: { type: "id" },
402
+ // });
403
+ // }
404
+ //@ts-ignore
405
+ return result;
406
+ }
407
+ else if (delStr.length > term.width) {
408
+ const remainingStr = delStr.slice(term.width);
409
+ return [
410
+ {
411
+ newEnv: env,
412
+ newTermNode: { type: "bot" },
413
+ remainingOperation: {
414
+ type: "delete",
415
+ str: remainingStr,
416
+ position: 0,
417
+ },
418
+ },
419
+ {
420
+ newEnv: Object.assign({}, env),
421
+ newTermNode: Object.assign(Object.assign({}, term), { width: 0 }),
422
+ remainingOperation: {
423
+ type: "delete",
424
+ str: remainingStr,
425
+ position: 0,
426
+ },
427
+ },
428
+ ];
429
+ }
430
+ }
431
+ else if (delPos < term.width &&
432
+ delPos + delStr.length <= term.width) {
433
+ const newWidth = term.width - delStr.length;
434
+ return [
435
+ {
436
+ newEnv: env,
437
+ newTermNode: Object.assign(Object.assign({}, term), { width: newWidth }),
438
+ remainingOperation: { type: "id" },
439
+ },
440
+ ];
441
+ }
442
+ else if (delPos < term.width && delPos + delStr.length > term.width) {
443
+ const remainingWidth = delPos;
444
+ const remainingDelStr = delStr.substring(term.width - delPos); // 剩余需要删除的字符串
445
+ return [
446
+ {
447
+ newEnv: env,
448
+ newTermNode: { type: "space", width: remainingWidth },
449
+ remainingOperation: {
450
+ type: "delete",
451
+ str: remainingDelStr,
452
+ position: 0,
453
+ },
454
+ },
455
+ ];
456
+ }
457
+ else {
458
+ const newPos = delPos - term.width;
459
+ return [
460
+ {
461
+ newEnv: env,
462
+ newTermNode: term,
463
+ remainingOperation: {
464
+ type: "delete",
465
+ str: delStr,
466
+ position: newPos,
467
+ },
468
+ },
469
+ ];
470
+ }
471
+ case "replace":
472
+ const { str1, str2, position: repPos, } = operation;
473
+ if (repPos === 0) {
474
+ if (str1.length <= term.width) {
475
+ if (Utils_1.isWhitespace(str2)) {
476
+ const newWidth = term.width - str1.length + str2.length;
477
+ return [
478
+ {
479
+ newEnv: env,
480
+ newTermNode: Object.assign(Object.assign({}, term), { width: newWidth }),
481
+ remainingOperation: { type: "id" },
482
+ },
483
+ ];
484
+ }
485
+ else {
486
+ return [
487
+ {
488
+ newEnv: env,
489
+ newTermNode: {
490
+ type: "seq",
491
+ nodes: [
492
+ { type: "const", value: str2 },
493
+ Object.assign(Object.assign({}, term), { width: term.width - str1.length }),
494
+ ],
495
+ },
496
+ remainingOperation: { type: "id" },
497
+ },
498
+ ];
499
+ }
500
+ }
501
+ else if (str1.length > term.width) {
502
+ const remainingS_c = str2.slice(0, term.width);
503
+ const remainingStr1 = str1.slice(term.width);
504
+ const remainingStr2 = str2.slice(term.width);
505
+ return [
506
+ {
507
+ newEnv: env,
508
+ newTermNode: { type: "const", value: remainingS_c },
509
+ remainingOperation: {
510
+ type: "replace",
511
+ str1: remainingStr1,
512
+ str2: remainingStr2,
513
+ position: 0,
514
+ },
515
+ },
516
+ ];
517
+ }
518
+ }
519
+ else if (repPos < term.width && repPos + str1.length <= term.width) {
520
+ if (Utils_1.isWhitespace(str2)) {
521
+ return [
522
+ {
523
+ newEnv: env,
524
+ newTermNode: Object.assign(Object.assign({}, term), { width: str2.length + term.width - str1.length }),
525
+ remainingOperation: { type: "id" },
526
+ },
527
+ ];
528
+ }
529
+ else {
530
+ const newStr = " ".repeat(repPos) +
531
+ str2 +
532
+ " ".repeat(term.width - (repPos + str1.length));
533
+ return [
534
+ {
535
+ newEnv: env,
536
+ newTermNode: { type: "const", value: newStr },
537
+ remainingOperation: { type: "id" },
538
+ },
539
+ ];
540
+ }
541
+ }
542
+ else if (repPos < term.width && repPos + str1.length > term.width) {
543
+ const part1 = " ".repeat(repPos); // 替换位置之前的部分
544
+ const overlapPartLength = term.width - repPos; // 与替换的 str1 重叠的部分
545
+ const overlapStr2 = str2.substring(0, overlapPartLength);
546
+ const remainingStr1 = str1.substring(overlapPartLength); // 剩余需要替换的 str1 部分
547
+ const remainingStr2 = str2.substring(overlapPartLength); // 剩余替换的 str2 部分
548
+ const newOperation = {
549
+ type: "replace",
550
+ str1: remainingStr1,
551
+ str2: remainingStr2,
552
+ position: 0,
553
+ };
554
+ const newExpression = {
555
+ type: "const",
556
+ value: part1 + overlapStr2,
557
+ };
558
+ return [
559
+ {
560
+ newEnv: env,
561
+ newTermNode: newExpression,
562
+ remainingOperation: newOperation,
563
+ },
564
+ ];
565
+ }
566
+ else {
567
+ const newPos = repPos - term.width;
568
+ return [
569
+ {
570
+ newEnv: env,
571
+ newTermNode: term,
572
+ remainingOperation: {
573
+ type: "replace",
574
+ str1,
575
+ str2,
576
+ position: newPos,
577
+ },
578
+ },
579
+ ];
580
+ }
581
+ case "bulk":
582
+ return fuseBulk(env, operation, term);
583
+ case "id":
584
+ return [
585
+ {
586
+ newEnv: env,
587
+ newTermNode: term,
588
+ remainingOperation: { type: "id" },
589
+ },
590
+ ];
591
+ default:
592
+ throw new Error(`Unhandled operation type: ${operation}`);
593
+ }
594
+ }
595
+ else if (term.type === "exp") {
596
+ const expTerm = term;
597
+ const binding = term.binding;
598
+ const exp = binding[0];
599
+ const val = binding[1];
600
+ const valStr = valToStr(val);
601
+ switch (operation.type) {
602
+ case "insert":
603
+ const { str, position } = operation;
604
+ if (position === 0) {
605
+ let resultList = [];
606
+ resultList.push({
607
+ newEnv: env,
608
+ newTermNode: {
609
+ type: "seq",
610
+ nodes: [{ type: "const", value: str }, term],
611
+ },
612
+ remainingOperation: { type: "id" },
613
+ });
614
+ if (!Utils_1.isWhitespace(str)) {
615
+ // another choice:
616
+ let newStr = str + valStr;
617
+ try {
618
+ let newVal = strToVal(newStr, val);
619
+ let { newEnv, newExp } = fuseExp(Object.assign({}, env), newVal, exp);
620
+ resultList.push({
621
+ newEnv: newEnv,
622
+ newTermNode: Object.assign(Object.assign({}, term), { binding: [newExp, newVal] }),
623
+ remainingOperation: { type: "id" },
624
+ });
625
+ }
626
+ catch (error) {
627
+ // console.error(error);
628
+ }
629
+ }
630
+ return resultList;
631
+ }
632
+ else if (position < valStr.length) {
633
+ const newStr = valStr.slice(0, position) + str + valStr.slice(position);
634
+ const newVal = strToVal(newStr, val);
635
+ let { newEnv, newExp } = fuseExp(env, newVal, exp);
636
+ return [
637
+ {
638
+ newEnv: newEnv,
639
+ newTermNode: Object.assign(Object.assign({}, term), { binding: [newExp, newVal] }),
640
+ remainingOperation: { type: "id" },
641
+ },
642
+ ];
643
+ }
644
+ else if (position == valStr.length) {
645
+ let resultList = [];
646
+ if (!Utils_1.isWhitespace(str)) {
647
+ const newStr = valStr + str;
648
+ try {
649
+ const newVal = strToVal(newStr, val);
650
+ let { newEnv, newExp } = fuseExp(Object.assign({}, env), newVal, exp);
651
+ resultList.push({
652
+ newEnv: newEnv,
653
+ newTermNode: Object.assign(Object.assign({}, term), { binding: [newExp, newVal] }),
654
+ remainingOperation: { type: "id" },
655
+ });
656
+ }
657
+ catch (error) {
658
+ console.error(error);
659
+ }
660
+ }
661
+ // If the expression is a variable, them add variable's bidning to env to mark it unmodifiable.
662
+ let env2 = Object.assign({}, env);
663
+ if (exp.name) {
664
+ let x = exp.name;
665
+ env2[x] = [val, [val]]; // mark x as unmodifiable.
666
+ }
667
+ resultList.push({
668
+ newEnv: env2,
669
+ newTermNode: term,
670
+ remainingOperation: Object.assign(Object.assign({}, operation), { position: 0 }),
671
+ });
672
+ return resultList;
673
+ }
674
+ else {
675
+ const newPosition = position - valStr.length;
676
+ // If the expression is a variable, them add variable's bidning to env to mark it unmodifiable.
677
+ if (exp.name) {
678
+ let x = exp.name;
679
+ env[x] = [val, [val]]; // mark x as unmodifiable.
680
+ }
681
+ return [
682
+ {
683
+ newEnv: env,
684
+ newTermNode: term,
685
+ remainingOperation: Object.assign(Object.assign({}, operation), { position: newPosition }),
686
+ },
687
+ ];
688
+ }
689
+ case "delete":
690
+ const { str: delStr, position: delPos } = operation;
691
+ if (delPos === 0) {
692
+ if (delStr.length < valStr.length) {
693
+ const newValStr = valStr.slice(delStr.length);
694
+ const newVal = strToVal(newValStr, val);
695
+ let { newEnv, newExp } = fuseExp(env, newVal, exp);
696
+ return [
697
+ {
698
+ newEnv: newEnv,
699
+ newTermNode: Object.assign(Object.assign({}, term), { binding: [newExp, newVal] }),
700
+ remainingOperation: { type: "id" },
701
+ },
702
+ ];
703
+ }
704
+ else if (delStr.length == valStr.length) {
705
+ if (exp.name) {
706
+ let x = exp.name;
707
+ if (typeof val == "string") {
708
+ // two choice: update exp to "", or delete exp
709
+ let { newEnv, newExp } = fuseExp(Object.assign({}, env), "", exp);
710
+ return [
711
+ {
712
+ newEnv: newEnv,
713
+ newTermNode: Object.assign(Object.assign({}, term), { binding: [newExp, ""] }),
714
+ remainingOperation: { type: "id" },
715
+ },
716
+ {
717
+ newEnv: deleteFromEnv(env, x),
718
+ newTermNode: { type: "bot" },
719
+ remainingOperation: { type: "id" },
720
+ },
721
+ ];
722
+ }
723
+ else {
724
+ // delete exp, delete from env
725
+ return [
726
+ {
727
+ newEnv: deleteFromEnv(env, x),
728
+ newTermNode: { type: "bot" },
729
+ remainingOperation: { type: "id" },
730
+ },
731
+ ];
732
+ }
733
+ }
734
+ else if (exp) {
735
+ let x = exp.object.name;
736
+ let field = exp.field;
737
+ let xVal = env[x][0];
738
+ let xValUpdatedMark = env[x][1][0];
739
+ if (xValUpdatedMark.fields[field].length == 0) {
740
+ let newXVal = deleteField(xVal, field);
741
+ let newXValUpdatedMark = deleteField(xValUpdatedMark, field);
742
+ let newEnv = deleteFromEnv(env, x);
743
+ newEnv[x] = [newXVal, [newXValUpdatedMark]];
744
+ return [
745
+ {
746
+ newEnv: newEnv,
747
+ newTermNode: { type: "bot" },
748
+ remainingOperation: { type: "id" },
749
+ },
750
+ ];
751
+ }
752
+ else {
753
+ throw new Error(`field has been updaeted, cannot be remvoed: ${field}$`);
754
+ }
755
+ }
756
+ }
757
+ else if (delStr.length > valStr.length) {
758
+ let delStr1 = delStr.slice(0, valStr.length);
759
+ let delStr2 = delStr.slice(valStr.length);
760
+ let op1 = {
761
+ type: "delete",
762
+ str: delStr1,
763
+ position: 0,
764
+ };
765
+ let resultList = fuse(env, op1, term);
766
+ let op2 = {
767
+ type: "delete",
768
+ str: delStr2,
769
+ position: 0,
770
+ };
771
+ resultList.forEach((result) => {
772
+ result.remainingOperation = op2;
773
+ });
774
+ return resultList;
775
+ }
776
+ }
777
+ else if (delPos + delStr.length <= valStr.length) {
778
+ const newStr = valStr.slice(0, delPos) + valStr.slice(delPos + delStr.length);
779
+ const newVal = strToVal(newStr, val);
780
+ let { newEnv, newExp } = fuseExp(env, newVal, exp);
781
+ return [
782
+ {
783
+ newEnv: newEnv,
784
+ newTermNode: Object.assign(Object.assign({}, term), { binding: [newExp, newVal] }),
785
+ remainingOperation: { type: "id" },
786
+ },
787
+ ];
788
+ }
789
+ else if (delPos <= valStr.length &&
790
+ delPos + delStr.length > valStr.length) {
791
+ const newStr = valStr.slice(0, delPos);
792
+ const remainingDelStr = delStr.slice(valStr.length - delPos);
793
+ const newVal = strToVal(newStr, val);
794
+ let { newEnv, newExp } = fuseExp(env, newVal, exp);
795
+ return [
796
+ {
797
+ newEnv: newEnv,
798
+ newTermNode: Object.assign(Object.assign({}, term), { binding: [newExp, newVal] }),
799
+ remainingOperation: {
800
+ type: "delete",
801
+ str: remainingDelStr,
802
+ position: 0,
803
+ },
804
+ },
805
+ ];
806
+ }
807
+ else if (delPos > valStr.length) {
808
+ const newDelPos = delPos - valStr.length;
809
+ let [{ newEnv, newTermNode, remainingOperation }] = fuse(env, { type: "id" }, term);
810
+ return [
811
+ {
812
+ newEnv: newEnv,
813
+ newTermNode: newTermNode,
814
+ remainingOperation: {
815
+ type: "delete",
816
+ str: delStr,
817
+ position: newDelPos,
818
+ },
819
+ },
820
+ ];
821
+ }
822
+ case "replace":
823
+ const { str1, str2, position: repPos, } = operation;
824
+ if (repPos === 0) {
825
+ if (valStr.startsWith(str1)) {
826
+ const newValStr = str2 + valStr.slice(str1.length);
827
+ const newVal = strToVal(newValStr, val);
828
+ let { newEnv, newExp } = fuseExp(env, newVal, exp);
829
+ // console.log("fuseExp, newVal:", newVal);
830
+ // console.log("newEnv:", newEnv);
831
+ return [
832
+ {
833
+ newEnv: newEnv,
834
+ newTermNode: Object.assign(Object.assign({}, term), { binding: [newExp, newVal] }),
835
+ remainingOperation: { type: "id" },
836
+ },
837
+ ];
838
+ }
839
+ else {
840
+ throw new Error(`unsupported replacement: ${str1}; ${valStr}`);
841
+ }
842
+ }
843
+ else if (repPos > valStr.length) {
844
+ const newRepPos = repPos - valStr.length;
845
+ let [{ newEnv, newTermNode, remainingOperation }] = fuse(env, { type: "id" }, term);
846
+ return [
847
+ {
848
+ newEnv: newEnv,
849
+ newTermNode: newTermNode,
850
+ remainingOperation: Object.assign(Object.assign({}, operation), { position: newRepPos }),
851
+ },
852
+ ];
853
+ }
854
+ else {
855
+ throw new Error(`Unsupported replacement`);
856
+ }
857
+ case "bulk":
858
+ return fuseBulk(env, operation, term);
859
+ case "id":
860
+ // find variables in e, and update them in env
861
+ let { variables, fields } = Exp_1.findVariablesAndFields(exp);
862
+ variables.forEach((variable) => {
863
+ env = markVariableInEnv(variable, env);
864
+ });
865
+ fields.forEach(({ variable, field }) => {
866
+ env = markFieldOfObjectInEnv(field, variable, env);
867
+ });
868
+ return [
869
+ {
870
+ newEnv: env,
871
+ newTermNode: term,
872
+ remainingOperation: { type: "id" },
873
+ },
874
+ ];
875
+ default:
876
+ throw new Error(`Unhandled operation type: ${operation}`);
877
+ }
878
+ }
879
+ else if (term.type === "lambda") {
880
+ let marker = term.marker;
881
+ if (marker.type === "loopitem") {
882
+ let varName = term.variable.name;
883
+ let varExp = term.binding[0];
884
+ let varVal = term.binding[1];
885
+ let env1 = Object.assign({}, env);
886
+ env1[varName] = [varVal, []];
887
+ let newArrVarName = "";
888
+ if (marker.lst) {
889
+ let expName = marker.lst.name;
890
+ newArrVarName = expName + "_new";
891
+ }
892
+ else {
893
+ throw new Error("exp is not a Variable with a name property in loopitem's marker");
894
+ }
895
+ let resultList = fuse(env1, operation, term.body);
896
+ return resultList.map(({ newEnv, newTermNode, remainingOperation }) => {
897
+ let newVarVal = newEnv[varName][0];
898
+ let newArrVal = env[newArrVarName][0]; // must be an array
899
+ newArrVal.push(newVarVal);
900
+ env[newArrVarName] = [newArrVal, [newArrVal]];
901
+ let { newEnv: updatedEnv, newExp } = fuseExp(env, newVarVal, varExp);
902
+ return {
903
+ newEnv: updatedEnv,
904
+ newTermNode: {
905
+ type: "lambda",
906
+ variable: term.variable,
907
+ body: newTermNode,
908
+ binding: [newExp, newVarVal],
909
+ marker: term.marker,
910
+ },
911
+ remainingOperation: remainingOperation,
912
+ };
913
+ });
914
+ }
915
+ else {
916
+ let varName = term.variable.name;
917
+ let varExp = term.binding[0];
918
+ let varVal = term.binding[1];
919
+ let env1 = Object.assign({}, env);
920
+ env1[varName] = [varVal, []];
921
+ // console.log("--------lambda----------");
922
+ // console.log("operation:", operation);
923
+ // console.log("term.body:", term.body);
924
+ // console.log("env1:", env1);
925
+ let resultList = fuse(env1, operation, term.body);
926
+ return resultList.map(({ newEnv, newTermNode, remainingOperation }) => {
927
+ // console.log("newEnv:", newEnv);
928
+ let newVarVal = newEnv[varName][0];
929
+ delete newEnv[varName];
930
+ let updatedOldEnv = updateEnvByEnv(env, newEnv);
931
+ let { newEnv: updatedEnv, newExp } = fuseExp(updatedOldEnv, newVarVal, varExp);
932
+ // console.log("lambda, newVarVal:", newVarVal);
933
+ // console.log("updatedOldEnv:", updatedOldEnv);
934
+ // console.log("exp:", varExp);
935
+ // console.log("newExp:", newExp);
936
+ // console.log("updatedEnv:", updatedEnv);
937
+ return {
938
+ newEnv: updatedEnv,
939
+ newTermNode: {
940
+ type: "lambda",
941
+ variable: term.variable,
942
+ body: newTermNode,
943
+ binding: [newExp, newVarVal],
944
+ marker: term.marker,
945
+ },
946
+ remainingOperation: remainingOperation,
947
+ };
948
+ });
949
+ }
950
+ }
951
+ else if (term.type === "branchstart" ||
952
+ term.type === "branchend" ||
953
+ term.type === "nop") {
954
+ let resultList = [];
955
+ resultList.push({
956
+ newEnv: env,
957
+ newTermNode: term,
958
+ remainingOperation: operation,
959
+ });
960
+ switch (operation.type) {
961
+ case "insert":
962
+ const { str, position } = operation;
963
+ if (position === 0) {
964
+ resultList.push({
965
+ newEnv: env,
966
+ newTermNode: {
967
+ type: "seq",
968
+ nodes: [{ type: "const", value: str }, term],
969
+ },
970
+ remainingOperation: { type: "id" },
971
+ });
972
+ }
973
+ case "delete":
974
+ case "replace":
975
+ return resultList;
976
+ case "bulk":
977
+ return fuseBulk(env, operation, term);
978
+ default:
979
+ throw new Error(`Unhandled operation type: ${operation}`);
980
+ }
981
+ }
982
+ else if (term.type === "seq") {
983
+ if (operation.type === "bulk") {
984
+ return fuseBulk(env, operation, term);
985
+ }
986
+ const terms = term.nodes;
987
+ let results = [
988
+ {
989
+ newEnv: env,
990
+ newTermNode: { type: "seq", nodes: [] },
991
+ remainingOperation: operation,
992
+ },
993
+ ];
994
+ for (const subTerm of terms) {
995
+ const newResults = [];
996
+ for (const result of results) {
997
+ // console.log("-------------seq-----------");
998
+ // console.log(result);
999
+ // console.log(subTerm);
1000
+ const subResults = fuse(result.newEnv, result.remainingOperation, subTerm);
1001
+ for (const subResult of subResults) {
1002
+ const updatedNodes = (result.newTermNode.type === "seq"
1003
+ ? result.newTermNode.nodes
1004
+ : [result.newTermNode]).concat(subResult.newTermNode.type === "seq"
1005
+ ? subResult.newTermNode.nodes
1006
+ : [subResult.newTermNode]);
1007
+ newResults.push({
1008
+ newEnv: subResult.newEnv,
1009
+ newTermNode: {
1010
+ type: "seq",
1011
+ nodes: updatedNodes,
1012
+ },
1013
+ remainingOperation: subResult.remainingOperation,
1014
+ });
1015
+ }
1016
+ }
1017
+ results = newResults;
1018
+ }
1019
+ return results.map((result) => ({
1020
+ newEnv: result.newEnv,
1021
+ newTermNode: result.newTermNode.type === "seq" &&
1022
+ result.newTermNode.nodes.length === 1
1023
+ ? result.newTermNode.nodes[0]
1024
+ : result.newTermNode,
1025
+ remainingOperation: result.remainingOperation,
1026
+ }));
1027
+ }
1028
+ else if (term.type === "end") {
1029
+ let results = [{ newEnv: env, newTermNode: term, remainingOperation: operation }];
1030
+ return results;
1031
+ }
1032
+ else {
1033
+ throw new Error("Operation can only be applied to ConstNode with string value");
1034
+ }
1035
+ }
1036
+ exports.fuse = fuse;
1037
+ function fuseExp(env, value, exp) {
1038
+ switch (exp.type) {
1039
+ case "constant":
1040
+ return { newEnv: env, newExp: valueToConstantExpr(value) };
1041
+ case "variable":
1042
+ if (!(exp.name in env)) {
1043
+ throw new Error(`Variable ${exp.name} not found in environment.`);
1044
+ }
1045
+ const [varValue, marks] = env[exp.name];
1046
+ if (marks.length === 0) {
1047
+ const newEnv = Object.assign({}, env);
1048
+ newEnv[exp.name] = [value, [value]];
1049
+ return { newEnv, newExp: exp };
1050
+ }
1051
+ else if (marks.length === 1 && marks[0] === value) {
1052
+ return { newEnv: env, newExp: exp };
1053
+ }
1054
+ else {
1055
+ throw new Error(`Fail, variable cannot be updated to different value ${exp.name}, previous: ${marks[0]}, new: ${value}`);
1056
+ }
1057
+ case "freeze":
1058
+ let [_, evaluated] = peval_1.evaluateExpr(transformEnvironment(env), exp.expression);
1059
+ if (evaluated !== value) {
1060
+ throw new Error(`Fail, freezed expression cannot be changed, old: ${value}, new: ${evaluated}`);
1061
+ }
1062
+ else {
1063
+ return { newEnv: env, newExp: exp };
1064
+ }
1065
+ case "field":
1066
+ // Rule for field access
1067
+ const objExp = exp.object;
1068
+ if (objExp.type === "variable" && objExp.name in env) {
1069
+ const [objValue, objMarks] = env[objExp.name];
1070
+ if (objValue.type === "object") {
1071
+ const newFields = Object.assign(Object.assign({}, objValue.fields), { [exp.field]: value });
1072
+ const newObjValue = {
1073
+ type: "object",
1074
+ fields: newFields,
1075
+ };
1076
+ const newMarks = updateFieldMarkWithValue(objMarks[0], exp.field, value);
1077
+ const newEnv = Object.assign({}, env);
1078
+ newEnv[objExp.name] = [newObjValue, [newMarks]];
1079
+ return { newEnv, newExp: exp };
1080
+ }
1081
+ else {
1082
+ throw new Error("Field access's value is not an object");
1083
+ }
1084
+ }
1085
+ else {
1086
+ throw new Error(`Field access not start with variable.`);
1087
+ }
1088
+ case "binary":
1089
+ let transformedEnv = transformEnvironment(env);
1090
+ let [envLeft, left] = peval_1.evaluateExpr(transformedEnv, exp.left);
1091
+ // let [envRight, right] = evaluateExpr(transformedEnv, exp.right);
1092
+ // if(value as number){
1093
+ // console.log("transformedEnv:", transformedEnv);
1094
+ // console.log("left:", left);
1095
+ // console.log("value:", value);
1096
+ // console.log("exp:", exp);
1097
+ if (typeof value === "number") {
1098
+ if (typeof value !== "number" || value === null) {
1099
+ throw new Error("Value must be a non-null number");
1100
+ }
1101
+ switch (exp.operator) {
1102
+ case "+":
1103
+ let subResultForPlus = fuseExp(env, value - left, exp.right);
1104
+ // console.log("subResult:", subResultForPlus);
1105
+ return {
1106
+ newEnv: subResultForPlus.newEnv,
1107
+ newExp: Object.assign(Object.assign({}, exp), { right: subResultForPlus.newExp }),
1108
+ };
1109
+ case "-":
1110
+ let subResultForMinus = fuseExp(env, left - value, exp.right);
1111
+ return {
1112
+ newEnv: subResultForMinus.newEnv,
1113
+ newExp: Object.assign(Object.assign({}, exp), { right: subResultForMinus.newExp }),
1114
+ };
1115
+ case "*":
1116
+ let subResultForTimes = fuseExp(env, value / left, exp.right);
1117
+ return {
1118
+ newEnv: subResultForTimes.newEnv,
1119
+ newExp: Object.assign(Object.assign({}, exp), { right: subResultForTimes.newExp }),
1120
+ };
1121
+ case "/":
1122
+ let subResultForDivide = fuseExp(env, left / value, exp.right);
1123
+ return {
1124
+ newEnv: subResultForDivide.newEnv,
1125
+ newExp: Object.assign(Object.assign({}, exp), { right: subResultForDivide.newExp }),
1126
+ };
1127
+ }
1128
+ // } else if (value as boolean) {
1129
+ }
1130
+ else if (typeof value === "boolean") {
1131
+ // TODO
1132
+ }
1133
+ case "unary":
1134
+ // Add logic for unary operations here
1135
+ return { newEnv: env, newExp: exp };
1136
+ default:
1137
+ throw new Error(`Unsupported expression type: ${exp.type}`);
1138
+ }
1139
+ }
1140
+ exports.fuseExp = fuseExp;
1141
+ function strToVal(s, v) {
1142
+ if (typeof v === "number") {
1143
+ const parsedNumber = parseFloat(s);
1144
+ if (isNaN(parsedNumber)) {
1145
+ throw new Error("convert to number fail: ${s}");
1146
+ }
1147
+ else {
1148
+ return parsedNumber;
1149
+ }
1150
+ }
1151
+ else if (typeof v === "boolean") {
1152
+ if (s === "true") {
1153
+ return true;
1154
+ }
1155
+ else if (s === "false") {
1156
+ return false;
1157
+ }
1158
+ else {
1159
+ throw new Error("convert to boolean fail: ${s}");
1160
+ }
1161
+ }
1162
+ else if (typeof v === "string") {
1163
+ return s; // v is already string, return s as is
1164
+ }
1165
+ else {
1166
+ throw new Error(`Unsupported type: ${typeof v}`);
1167
+ }
1168
+ }
1169
+ function valToStr(value) {
1170
+ if (typeof value === "number" ||
1171
+ typeof value === "boolean" ||
1172
+ typeof value === "string") {
1173
+ return String(value); // Convert number, boolean, and string to string
1174
+ }
1175
+ else {
1176
+ return "Unknown"; // Handle unexpected types
1177
+ }
1178
+ }
1179
+ function deleteFromEnv(env, key) {
1180
+ const newEnv = Object.assign({}, env); // Create a shallow copy of env
1181
+ delete newEnv[key]; // Delete the specified key from the new environment
1182
+ return newEnv; // Return the modified environment
1183
+ }
1184
+ /**
1185
+ * Deletes a specified field from an ObjectValue.
1186
+ * @param obj The ObjectValue from which to delete the field.
1187
+ * @param field The field to delete.
1188
+ * @returns A new ObjectValue with the specified field removed.
1189
+ */
1190
+ function deleteField(obj, field) {
1191
+ // Destructure the fields, omitting the specified field
1192
+ const _a = obj.fields, _b = field, _ = _a[_b], newFields = __rest(_a, [typeof _b === "symbol" ? _b : _b + ""]);
1193
+ // Return a new ObjectValue with the updated fields
1194
+ return {
1195
+ type: "object",
1196
+ fields: newFields,
1197
+ };
1198
+ }
1199
+ function updateFieldMark(obj, field, objVal) {
1200
+ // Destructure the fields, omitting the specified field
1201
+ const _a = obj.fields, _b = field, _ = _a[_b], newFields = __rest(_a, [typeof _b === "symbol" ? _b : _b + ""]);
1202
+ newFields[field] = objVal.fields[field];
1203
+ // Return a new ObjectValue with the updated fields
1204
+ return {
1205
+ type: "object",
1206
+ fields: newFields,
1207
+ };
1208
+ }
1209
+ function updateFieldMarkWithValue(obj, field, value) {
1210
+ // Destructure the fields, omitting the specified field
1211
+ const _a = obj.fields, _b = field, val = _a[_b], newFields = __rest(_a, [typeof _b === "symbol" ? _b : _b + ""]);
1212
+ newFields[field] = [value];
1213
+ // Return a new ObjectValue with the updated fields
1214
+ return {
1215
+ type: "object",
1216
+ fields: newFields,
1217
+ };
1218
+ }
1219
+ function markVariableInEnv(variable, env) {
1220
+ if (!(variable.name in env)) {
1221
+ throw new Error(`Variable ${variable.name} not found in environment.`);
1222
+ }
1223
+ let val = env[variable.name][0];
1224
+ let newEnv = deleteFromEnv(env, variable.name);
1225
+ newEnv[variable.name] = [val, [val]];
1226
+ return newEnv;
1227
+ }
1228
+ function markFieldOfObjectInEnv(field, variable, env) {
1229
+ let x = variable.name;
1230
+ if (!(x in env)) {
1231
+ throw new Error(`Variable ${x} not found in environment.`);
1232
+ }
1233
+ let xVal = env[x][0];
1234
+ let xValMark = env[x][1][0];
1235
+ let newXValUpdatedMark = updateFieldMark(xValMark, field, xVal);
1236
+ let newEnv = deleteFromEnv(env, x);
1237
+ newEnv[x] = [xVal, [newXValUpdatedMark]];
1238
+ return newEnv;
1239
+ }
1240
+ function updateEnvByEnv(env, env2) {
1241
+ // Create a copy of env to avoid mutating the original env
1242
+ let updatedEnv = Object.assign({}, env);
1243
+ // Iterate over keys in env2
1244
+ for (const key in env2) {
1245
+ if (env2.hasOwnProperty(key)) {
1246
+ // Update the value in the updatedEnv
1247
+ updatedEnv[key] = env2[key];
1248
+ }
1249
+ }
1250
+ return updatedEnv;
1251
+ }
1252
+ function transformEnvironment(env) {
1253
+ const map = new Map();
1254
+ for (const variable in env) {
1255
+ if (env.hasOwnProperty(variable)) {
1256
+ map.set(variable, env[variable][0]);
1257
+ }
1258
+ }
1259
+ return map;
1260
+ }
1261
+ function valueToConstantExpr(value) {
1262
+ if (value === null ||
1263
+ typeof value === "number" ||
1264
+ typeof value === "boolean" ||
1265
+ typeof value === "string") {
1266
+ return { type: "constant", value: value };
1267
+ }
1268
+ else if (Array.isArray(value)) {
1269
+ return {
1270
+ type: "constant",
1271
+ value: value.map((v) => valueToConstantExpr(v)),
1272
+ };
1273
+ }
1274
+ else if (value.type === "object") {
1275
+ const objectValue = value;
1276
+ const fields = {};
1277
+ for (const key in objectValue.fields) {
1278
+ if (objectValue.fields.hasOwnProperty(key)) {
1279
+ fields[key] = valueToConstantExpr(objectValue.fields[key]);
1280
+ }
1281
+ }
1282
+ return {
1283
+ type: "constant",
1284
+ value: { type: "object", fields: fields },
1285
+ };
1286
+ }
1287
+ else {
1288
+ throw new Error(`Unhandled value type: ${typeof value}`);
1289
+ }
1290
+ }
1291
+ exports.valueToConstantExpr = valueToConstantExpr;
1292
+ function printEnvironment(env) {
1293
+ console.log("{\n");
1294
+ for (const variable in env) {
1295
+ if (env.hasOwnProperty(variable)) {
1296
+ const [currentValue, marks] = env[variable];
1297
+ console.log(`${variable}: {`);
1298
+ console.log(" val: ");
1299
+ Print_1.printValue(currentValue, " ");
1300
+ console.log(",marks: [");
1301
+ marks.forEach((v, index) => {
1302
+ Print_1.printValue(v, " ");
1303
+ if (index < marks.length - 1) {
1304
+ console.log(", ");
1305
+ }
1306
+ });
1307
+ console.log("]\n },\n");
1308
+ }
1309
+ }
1310
+ console.log("}");
1311
+ }
1312
+ exports.printEnvironment = printEnvironment;
1313
+ function fuseBulk(env, bulkOp, term) {
1314
+ if (bulkOp.type === "id") {
1315
+ // console.log("Bulk, term:", term);
1316
+ return fuse(env, bulkOp, term);
1317
+ // return [{ newEnv: env, newTermNode: term, remainingOperation: { type: 'id' } }];
1318
+ }
1319
+ if (bulkOp.type !== "bulk" || !bulkOp.operations) {
1320
+ throw new Error("Invalid bulk operation");
1321
+ }
1322
+ // ending of recursive call
1323
+ if (bulkOp.operations.length == 0) {
1324
+ return [
1325
+ { newEnv: env, newTermNode: term, remainingOperation: { type: "id" } },
1326
+ ];
1327
+ }
1328
+ else if (term.type === "seq" && term.nodes.length == 0) {
1329
+ return [{ newEnv: env, newTermNode: term, remainingOperation: bulkOp }];
1330
+ }
1331
+ const [op1, ...restOps] = bulkOp.operations;
1332
+ if (term.type === "seq") {
1333
+ const firstTerm = term.nodes[0];
1334
+ const remainingTerms = term.nodes.slice(1);
1335
+ const fuseResultsOfFirstTerm = fuseBulk(env, bulkOp, firstTerm);
1336
+ // console.log("fuseResultsOfFirstTerm:", fuseResultsOfFirstTerm);
1337
+ const results = [];
1338
+ for (const result of fuseResultsOfFirstTerm) {
1339
+ const subResults = fuseBulk(result.newEnv, result.remainingOperation, {
1340
+ type: "seq",
1341
+ nodes: remainingTerms,
1342
+ });
1343
+ for (const subResult of subResults) {
1344
+ let remainingNodesTerm = [];
1345
+ if (subResult.newTermNode.type != "seq") {
1346
+ remainingNodesTerm.push(subResult.newTermNode);
1347
+ }
1348
+ else {
1349
+ remainingNodesTerm = subResult.newTermNode.nodes;
1350
+ }
1351
+ results.push({
1352
+ newEnv: subResult.newEnv,
1353
+ newTermNode: {
1354
+ type: "seq",
1355
+ nodes: [result.newTermNode, ...remainingNodesTerm],
1356
+ },
1357
+ remainingOperation: subResult.remainingOperation,
1358
+ });
1359
+ }
1360
+ }
1361
+ return results;
1362
+ }
1363
+ else if (term.type === "lambda") {
1364
+ return fuse(env, bulkOp, term);
1365
+ }
1366
+ else {
1367
+ if (op1.type === "insert" ||
1368
+ op1.type === "delete" ||
1369
+ op1.type === "replace") {
1370
+ const n1 = op1.position;
1371
+ // 这里不能简单的fuse整个term,要根据term类型来,就好比上一个if判断是seq,除了seq外,LambdaAppNode需要特殊处理
1372
+ const op1Results = fuse(env, op1, term);
1373
+ let listOfList = op1Results.map((op1Result) => {
1374
+ let op1Prime = op1Result.remainingOperation;
1375
+ if (op1Prime.type === "id" ||
1376
+ op1Prime.type === "insert" ||
1377
+ op1Prime.type === "delete" ||
1378
+ op1Prime.type === "replace") {
1379
+ let termStr = Evaluation_1.evaluateTermNode(op1Result.newTermNode);
1380
+ let deltaN = termStr.length;
1381
+ // Adjust positions for the remaining operations
1382
+ const adjustedRestOps = restOps.map((op) => {
1383
+ if (op.type === "id") {
1384
+ return op;
1385
+ }
1386
+ else if (!("position" in op)) {
1387
+ throw new Error("All operations must have positions");
1388
+ }
1389
+ else {
1390
+ return Object.assign(Object.assign({}, op), { position: op.position - deltaN });
1391
+ }
1392
+ });
1393
+ // Combine the remaining operations
1394
+ let remainingBulkOp = {
1395
+ type: "bulk",
1396
+ operations: [op1Result.remainingOperation, ...adjustedRestOps],
1397
+ };
1398
+ return [
1399
+ {
1400
+ newEnv: op1Result.newEnv,
1401
+ newTermNode: op1Result.newTermNode,
1402
+ remainingOperation: remainingBulkOp,
1403
+ },
1404
+ ];
1405
+ }
1406
+ else {
1407
+ throw new Error("nested bulk current not supported");
1408
+ }
1409
+ });
1410
+ return listOfList.reduce((acc, val) => acc.concat(val), []);
1411
+ }
1412
+ else if (op1.type === "id") {
1413
+ // case 3
1414
+ // Create a new bulk operation with the remaining operations
1415
+ const newBulkOp = {
1416
+ type: "bulk",
1417
+ operations: restOps,
1418
+ };
1419
+ return fuseBulk(env, newBulkOp, term);
1420
+ }
1421
+ }
1422
+ return [];
1423
+ }
1424
+ exports.fuseBulk = fuseBulk;
1425
+ function getOpStr(op1) {
1426
+ if (op1.type === "insert" || op1.type === "delete") {
1427
+ return op1.str;
1428
+ }
1429
+ else if (op1.type === "replace") {
1430
+ return op1.str1;
1431
+ }
1432
+ else {
1433
+ return undefined;
1434
+ }
1435
+ }
1436
+ //# sourceMappingURL=Fuse.js.map