@markw65/monkeyc-optimizer 1.0.21 → 1.0.24
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/README.md +36 -0
- package/build/api.cjs +717 -237
- package/build/optimizer.cjs +499 -161
- package/build/src/api.d.ts +7 -3
- package/build/src/ast.d.ts +2 -0
- package/build/src/inliner.d.ts +1 -5
- package/build/src/mc-rewrite.d.ts +4 -4
- package/build/src/optimizer.d.ts +28 -11
- package/build/src/pragma-checker.d.ts +1 -1
- package/build/src/util.d.ts +1 -0
- package/build/src/visitor.d.ts +2 -0
- package/build/util.cjs +10 -4
- package/package.json +9 -4
package/build/api.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
0 && (module.exports = {collectNamespaces,formatAst,getApiMapping,hasProperty,isStateNode,traverseAst,variableDeclarationName});
|
|
1
|
+
0 && (module.exports = {collectNamespaces,findUsingForNode,formatAst,getApiMapping,hasProperty,isStateNode,sameLookupResult,traverseAst,variableDeclarationName,visitReferences});
|
|
2
2
|
/******/ (() => { // webpackBootstrap
|
|
3
3
|
/******/ "use strict";
|
|
4
4
|
/******/ // The require scope
|
|
@@ -53,12 +53,15 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
53
53
|
// EXPORTS
|
|
54
54
|
__webpack_require__.d(__webpack_exports__, {
|
|
55
55
|
"collectNamespaces": () => (/* binding */ api_collectNamespaces),
|
|
56
|
-
"
|
|
56
|
+
"findUsingForNode": () => (/* binding */ findUsingForNode),
|
|
57
|
+
"formatAst": () => (/* binding */ api_formatAst),
|
|
57
58
|
"getApiMapping": () => (/* binding */ api_getApiMapping),
|
|
58
59
|
"hasProperty": () => (/* binding */ api_hasProperty),
|
|
59
60
|
"isStateNode": () => (/* binding */ api_isStateNode),
|
|
60
|
-
"
|
|
61
|
-
"
|
|
61
|
+
"sameLookupResult": () => (/* binding */ api_sameLookupResult),
|
|
62
|
+
"traverseAst": () => (/* reexport */ ast_traverseAst),
|
|
63
|
+
"variableDeclarationName": () => (/* binding */ api_variableDeclarationName),
|
|
64
|
+
"visitReferences": () => (/* reexport */ visitor_visitReferences)
|
|
62
65
|
});
|
|
63
66
|
|
|
64
67
|
;// CONCATENATED MODULE: external "@markw65/prettier-plugin-monkeyc"
|
|
@@ -68,10 +71,148 @@ var prettier_plugin_monkeyc_default = /*#__PURE__*/__webpack_require__.n(prettie
|
|
|
68
71
|
const promises_namespaceObject = require("fs/promises");
|
|
69
72
|
;// CONCATENATED MODULE: external "prettier"
|
|
70
73
|
const external_prettier_namespaceObject = require("prettier");
|
|
74
|
+
;// CONCATENATED MODULE: ./src/ast.ts
|
|
75
|
+
/*
|
|
76
|
+
* This ensures that mctreeTypeInfo has every key of MCTreeTypeInfo,
|
|
77
|
+
* and that the corresponding arrays contain every element of the
|
|
78
|
+
* corresponding type.
|
|
79
|
+
*
|
|
80
|
+
* ie, any time mctree.Node changes, we'll get errors here if
|
|
81
|
+
* mctreeTypeInfo needs updating.
|
|
82
|
+
*
|
|
83
|
+
*/
|
|
84
|
+
function _check(x) {
|
|
85
|
+
const y = x;
|
|
86
|
+
x = y;
|
|
87
|
+
}
|
|
88
|
+
const mctreeTypeInfo = {
|
|
89
|
+
ArrayExpression: ["elements"],
|
|
90
|
+
AssignmentExpression: ["left", "right"],
|
|
91
|
+
AttributeList: ["attributes"],
|
|
92
|
+
Attributes: ["elements"],
|
|
93
|
+
BinaryExpression: ["left", "right"],
|
|
94
|
+
Block: [],
|
|
95
|
+
BlockStatement: ["body", "innerComments"],
|
|
96
|
+
BreakStatement: [],
|
|
97
|
+
CallExpression: ["callee", "arguments"],
|
|
98
|
+
CatchClause: ["param", "body"],
|
|
99
|
+
CatchClauses: ["catches"],
|
|
100
|
+
ClassBody: ["body"],
|
|
101
|
+
ClassDeclaration: ["attrs", "id", "superClass", "body"],
|
|
102
|
+
ClassElement: ["item"],
|
|
103
|
+
ConditionalExpression: ["test", "consequent", "alternate"],
|
|
104
|
+
ContinueStatement: [],
|
|
105
|
+
DoWhileStatement: ["body", "test"],
|
|
106
|
+
EnumDeclaration: ["attrs", "id", "body"],
|
|
107
|
+
EnumStringBody: ["members"],
|
|
108
|
+
EnumStringMember: ["id", "init"],
|
|
109
|
+
ExpressionStatement: ["expression"],
|
|
110
|
+
ForStatement: ["init", "test", "body", "update"],
|
|
111
|
+
FunctionDeclaration: ["attrs", "id", "params", "body"],
|
|
112
|
+
Identifier: [],
|
|
113
|
+
IfStatement: ["test", "consequent", "alternate"],
|
|
114
|
+
ImportModule: ["id"],
|
|
115
|
+
InstanceOfCase: ["id"],
|
|
116
|
+
Line: [],
|
|
117
|
+
Literal: [],
|
|
118
|
+
LogicalExpression: ["left", "right"],
|
|
119
|
+
MemberExpression: ["object", "property"],
|
|
120
|
+
MethodDefinition: ["params", "returnType"],
|
|
121
|
+
ModuleDeclaration: ["attrs", "id", "body"],
|
|
122
|
+
MultiLine: [],
|
|
123
|
+
NewExpression: ["callee", "arguments"],
|
|
124
|
+
ObjectExpression: ["properties"],
|
|
125
|
+
ParenthesizedExpression: ["expression"],
|
|
126
|
+
Program: ["body", "comments"],
|
|
127
|
+
Property: ["key", "value"],
|
|
128
|
+
ReturnStatement: ["argument"],
|
|
129
|
+
SequenceExpression: ["expressions"],
|
|
130
|
+
SizedArrayExpression: ["size", "ts"],
|
|
131
|
+
SwitchCase: ["test", "consequent"],
|
|
132
|
+
SwitchStatement: ["discriminant", "cases"],
|
|
133
|
+
ThisExpression: [],
|
|
134
|
+
ThrowStatement: ["argument"],
|
|
135
|
+
TryStatement: ["block", "handler", "finalizer"],
|
|
136
|
+
TypedefDeclaration: ["attrs", "id", "ts"],
|
|
137
|
+
TypeSpecList: ["ts"],
|
|
138
|
+
TypeSpecPart: ["name", "body", "callspec", "generics"],
|
|
139
|
+
UnaryExpression: ["argument"],
|
|
140
|
+
UpdateExpression: ["argument"],
|
|
141
|
+
Using: ["id", "as"],
|
|
142
|
+
VariableDeclaration: ["attrs", "declarations"],
|
|
143
|
+
VariableDeclarator: ["id", "init"],
|
|
144
|
+
WhileStatement: ["test", "body"],
|
|
145
|
+
};
|
|
146
|
+
function isMCTreeNode(node) {
|
|
147
|
+
return node ? typeof node === "object" && "type" in node : false;
|
|
148
|
+
}
|
|
149
|
+
/*
|
|
150
|
+
* Traverse the ast rooted at node, calling pre before
|
|
151
|
+
* visiting each node, and post after.
|
|
152
|
+
*
|
|
153
|
+
* - if pre returns false, the node is not traversed, and
|
|
154
|
+
* post is not called;
|
|
155
|
+
* - if pre returns a list of child nodes, only those will
|
|
156
|
+
* be traversed
|
|
157
|
+
* - otherwise all child nodes are traversed
|
|
158
|
+
*
|
|
159
|
+
* - if post returns false, the node it was called on is
|
|
160
|
+
* removed.
|
|
161
|
+
*/
|
|
162
|
+
function ast_traverseAst(node, pre, post) {
|
|
163
|
+
const nodes = pre && pre(node);
|
|
164
|
+
if (nodes === false)
|
|
165
|
+
return;
|
|
166
|
+
if (!mctreeTypeInfo[node.type]) {
|
|
167
|
+
throw new Error("what?");
|
|
168
|
+
}
|
|
169
|
+
for (const key of nodes || mctreeTypeInfo[node.type]) {
|
|
170
|
+
const value = node[key];
|
|
171
|
+
if (!value)
|
|
172
|
+
continue;
|
|
173
|
+
if (Array.isArray(value)) {
|
|
174
|
+
const values = value;
|
|
175
|
+
const deletions = values.reduce((state, obj, i) => {
|
|
176
|
+
if (isMCTreeNode(obj)) {
|
|
177
|
+
const repl = ast_traverseAst(obj, pre, post);
|
|
178
|
+
if (repl === false) {
|
|
179
|
+
if (!state)
|
|
180
|
+
state = {};
|
|
181
|
+
state[i] = true;
|
|
182
|
+
}
|
|
183
|
+
else if (repl != null) {
|
|
184
|
+
if (!state)
|
|
185
|
+
state = {};
|
|
186
|
+
values[i] = repl;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return state;
|
|
190
|
+
}, null);
|
|
191
|
+
if (deletions) {
|
|
192
|
+
values.splice(0, values.length, ...values.filter((obj, i) => deletions[i] !== true).flat(1));
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
else if (isMCTreeNode(value)) {
|
|
196
|
+
const repl = ast_traverseAst(value, pre, post);
|
|
197
|
+
if (repl === false) {
|
|
198
|
+
delete node[key];
|
|
199
|
+
}
|
|
200
|
+
else if (repl != null) {
|
|
201
|
+
if (Array.isArray(repl)) {
|
|
202
|
+
throw new Error("Array returned by traverseAst in Node context");
|
|
203
|
+
}
|
|
204
|
+
node[key] = repl;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
return post && post(node);
|
|
209
|
+
}
|
|
210
|
+
|
|
71
211
|
;// CONCATENATED MODULE: external "./api.cjs"
|
|
72
212
|
const external_api_cjs_namespaceObject = require("./api.cjs");
|
|
73
213
|
;// CONCATENATED MODULE: ./src/variable-renamer.ts
|
|
74
214
|
|
|
215
|
+
|
|
75
216
|
function variable_renamer_renameVariable(state, locals, declName) {
|
|
76
217
|
const map = locals.map;
|
|
77
218
|
if (!hasProperty(map, declName))
|
|
@@ -128,6 +269,7 @@ function variable_renamer_renameVariable(state, locals, declName) {
|
|
|
128
269
|
;// CONCATENATED MODULE: ./src/inliner.ts
|
|
129
270
|
|
|
130
271
|
|
|
272
|
+
|
|
131
273
|
function getArgSafety(state, func, args, requireAll) {
|
|
132
274
|
// determine whether decl might be changed by a function call
|
|
133
275
|
// or assignment during the evaluation of FunctionStateNode.
|
|
@@ -169,11 +311,13 @@ function getArgSafety(state, func, args, requireAll) {
|
|
|
169
311
|
case "Identifier":
|
|
170
312
|
case "MemberExpression": {
|
|
171
313
|
const [, results] = state.lookup(arg);
|
|
172
|
-
if (!results ||
|
|
314
|
+
if (!results ||
|
|
315
|
+
results.length !== 1 ||
|
|
316
|
+
results[0].results.length !== 1) {
|
|
173
317
|
safeArgs.push(null);
|
|
174
318
|
return !requireAll;
|
|
175
319
|
}
|
|
176
|
-
const safety = getSafety(results[0]);
|
|
320
|
+
const safety = getSafety(results[0].results[0]);
|
|
177
321
|
safeArgs.push(safety);
|
|
178
322
|
if (!safety) {
|
|
179
323
|
allSafe = false;
|
|
@@ -193,25 +337,12 @@ function getArgSafety(state, func, args, requireAll) {
|
|
|
193
337
|
if (allSafe && requireAll)
|
|
194
338
|
return true;
|
|
195
339
|
let callSeen = false;
|
|
196
|
-
let ok = true;
|
|
197
340
|
const params = Object.fromEntries(func.node.params.map((param, i) => [variableDeclarationName(param), i]));
|
|
198
|
-
const getLoc = (node) => (Array.isArray(node) ? node[0].start : node.start) || 0;
|
|
199
341
|
// look for uses of "unsafe" args that occur after a call.
|
|
200
342
|
// use post to do the checking, because arguments are evaluated
|
|
201
343
|
// prior to the call, so eg "return f(x.y);" is fine, but
|
|
202
344
|
// "return f()+x.y" is not.
|
|
203
|
-
|
|
204
|
-
// We also have to use a "pre" to ensure that child nodes are
|
|
205
|
-
// visited in source order (otherwise we could visit x.y before f()
|
|
206
|
-
// in the above example)
|
|
207
|
-
traverseAst(func.node.body, (node) => {
|
|
208
|
-
return Object.entries(node)
|
|
209
|
-
.filter((kv) => Array.isArray(kv[1])
|
|
210
|
-
? kv[1].length !== 0 && hasProperty(kv[1][0], "type")
|
|
211
|
-
: hasProperty(kv[1], "type"))
|
|
212
|
-
.sort(([, a], [, b]) => getLoc(a) - getLoc(b))
|
|
213
|
-
.map(([key]) => key);
|
|
214
|
-
}, (node) => {
|
|
345
|
+
traverseAst(func.node.body, null, (node) => {
|
|
215
346
|
switch (node.type) {
|
|
216
347
|
case "AssignmentExpression":
|
|
217
348
|
case "UpdateExpression": {
|
|
@@ -265,12 +396,6 @@ function inliningLooksUseful(func, node) {
|
|
|
265
396
|
}
|
|
266
397
|
return false;
|
|
267
398
|
}
|
|
268
|
-
var InlineStatus;
|
|
269
|
-
(function (InlineStatus) {
|
|
270
|
-
InlineStatus[InlineStatus["Never"] = 0] = "Never";
|
|
271
|
-
InlineStatus[InlineStatus["AsExpression"] = 1] = "AsExpression";
|
|
272
|
-
InlineStatus[InlineStatus["AsStatement"] = 2] = "AsStatement";
|
|
273
|
-
})(InlineStatus || (InlineStatus = {}));
|
|
274
399
|
function inlineRequested(state, func) {
|
|
275
400
|
const excludeAnnotations = (func.node.loc?.source &&
|
|
276
401
|
state.fnMap[func.node.loc?.source]?.excludeAnnotations) ||
|
|
@@ -280,7 +405,7 @@ function inlineRequested(state, func) {
|
|
|
280
405
|
func.node.attrs.attributes.elements.some((attr) => attr.type === "UnaryExpression" &&
|
|
281
406
|
(attr.argument.name === "inline" ||
|
|
282
407
|
(attr.argument.name.startsWith("inline_") &&
|
|
283
|
-
hasProperty(excludeAnnotations, attr.argument.name.substring(7)))))) {
|
|
408
|
+
!hasProperty(excludeAnnotations, attr.argument.name.substring(7)))))) {
|
|
284
409
|
return true;
|
|
285
410
|
}
|
|
286
411
|
return false;
|
|
@@ -450,13 +575,13 @@ function inliner_unused(expression, top) {
|
|
|
450
575
|
},
|
|
451
576
|
];
|
|
452
577
|
}
|
|
453
|
-
function
|
|
578
|
+
function inliner_diagnostic(state, loc, message, type = "INFO") {
|
|
454
579
|
if (!loc || !loc.source)
|
|
455
580
|
return;
|
|
456
581
|
const source = loc.source;
|
|
457
582
|
if (!state.diagnostics)
|
|
458
583
|
state.diagnostics = {};
|
|
459
|
-
if (!hasProperty(state.diagnostics, source)) {
|
|
584
|
+
if (!(0,external_api_cjs_namespaceObject.hasProperty)(state.diagnostics, source)) {
|
|
460
585
|
if (!message)
|
|
461
586
|
return;
|
|
462
587
|
state.diagnostics[source] = [];
|
|
@@ -466,7 +591,7 @@ function diagnostic(state, loc, message) {
|
|
|
466
591
|
if (message) {
|
|
467
592
|
if (index < 0)
|
|
468
593
|
index = diags.length;
|
|
469
|
-
diags[index] = { type
|
|
594
|
+
diags[index] = { type, loc, message };
|
|
470
595
|
}
|
|
471
596
|
else if (index >= 0) {
|
|
472
597
|
diags.splice(index, 1);
|
|
@@ -474,7 +599,7 @@ function diagnostic(state, loc, message) {
|
|
|
474
599
|
}
|
|
475
600
|
function inlineDiagnostic(state, func, call, message) {
|
|
476
601
|
if (inlineRequested(state, func)) {
|
|
477
|
-
|
|
602
|
+
inliner_diagnostic(state, call.loc, message && `While inlining ${func.node.id.name}: ${message}`);
|
|
478
603
|
}
|
|
479
604
|
}
|
|
480
605
|
function inlineWithArgs(state, func, call, context) {
|
|
@@ -522,7 +647,7 @@ function inlineWithArgs(state, func, call, context) {
|
|
|
522
647
|
if (!processInlineBody(state, func, call, body, func.node.params.length ? false : true, params)) {
|
|
523
648
|
return null;
|
|
524
649
|
}
|
|
525
|
-
|
|
650
|
+
inliner_diagnostic(state, call.loc, null);
|
|
526
651
|
if (context.type !== "ReturnStatement" && retStmtCount) {
|
|
527
652
|
const last = body.body[body.body.length - 1];
|
|
528
653
|
if (last.type != "ReturnStatement") {
|
|
@@ -585,23 +710,25 @@ function fixNodeScope(state, lookupNode, nodeStack) {
|
|
|
585
710
|
// With a bit more work, we could find the guaranteed shortest
|
|
586
711
|
// reference, and then use this to optimize *all* symbols, not
|
|
587
712
|
// just fix inlined ones.
|
|
588
|
-
if (current &&
|
|
589
|
-
current.length === original.length &&
|
|
590
|
-
current.every((item, index) => item == original[index])) {
|
|
713
|
+
if (current && sameLookupResult(original, current)) {
|
|
591
714
|
return lookupNode;
|
|
592
715
|
}
|
|
593
716
|
const node = lookupNode.type === "Identifier"
|
|
594
717
|
? lookupNode
|
|
595
718
|
: lookupNode.property;
|
|
596
|
-
if (original.length === 1 &&
|
|
597
|
-
|
|
719
|
+
if (original.length === 1 &&
|
|
720
|
+
original[0].results.length === 1 &&
|
|
721
|
+
original[0].results[0].type === "EnumStringMember") {
|
|
722
|
+
return applyTypeIfNeeded(original[0].results[0].init);
|
|
598
723
|
}
|
|
599
|
-
const prefixes = original
|
|
724
|
+
const prefixes = original
|
|
725
|
+
.map((lookupDef) => lookupDef.results.map((sn) => {
|
|
600
726
|
if (isStateNode(sn) && sn.fullName) {
|
|
601
727
|
return sn.fullName;
|
|
602
728
|
}
|
|
603
729
|
return "";
|
|
604
|
-
})
|
|
730
|
+
}))
|
|
731
|
+
.flat();
|
|
605
732
|
if (prefixes.length &&
|
|
606
733
|
prefixes[0].startsWith("$.") &&
|
|
607
734
|
prefixes.every((prefix, i) => !i || prefix === prefixes[i - 1])) {
|
|
@@ -611,9 +738,7 @@ function fixNodeScope(state, lookupNode, nodeStack) {
|
|
|
611
738
|
if (found)
|
|
612
739
|
return current;
|
|
613
740
|
const [, results] = state.lookup(current);
|
|
614
|
-
if (results &&
|
|
615
|
-
results.length === original.length &&
|
|
616
|
-
results.every((result, i) => result === original[i])) {
|
|
741
|
+
if (results && sameLookupResult(original, results)) {
|
|
617
742
|
found = true;
|
|
618
743
|
return current;
|
|
619
744
|
}
|
|
@@ -655,6 +780,99 @@ function fixNodeScope(state, lookupNode, nodeStack) {
|
|
|
655
780
|
|
|
656
781
|
;// CONCATENATED MODULE: external "./util.cjs"
|
|
657
782
|
const external_util_cjs_namespaceObject = require("./util.cjs");
|
|
783
|
+
;// CONCATENATED MODULE: ./src/visitor.ts
|
|
784
|
+
|
|
785
|
+
function visitor_visitReferences(state, ast, name, defn, callback) {
|
|
786
|
+
const checkResults = ([name, results], node) => {
|
|
787
|
+
if (name && results) {
|
|
788
|
+
if (!defn || (0,external_api_cjs_namespaceObject.sameLookupResult)(results, defn)) {
|
|
789
|
+
if (callback(node, results, false) === false) {
|
|
790
|
+
return [];
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
else if (defn === false) {
|
|
795
|
+
if (callback(node, [], results === null) === false) {
|
|
796
|
+
return [];
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
return null;
|
|
800
|
+
};
|
|
801
|
+
state.pre = (node) => {
|
|
802
|
+
switch (node.type) {
|
|
803
|
+
case "AttributeList":
|
|
804
|
+
return [];
|
|
805
|
+
case "UnaryExpression":
|
|
806
|
+
// a bare symbol isn't a reference
|
|
807
|
+
if (node.operator === ":")
|
|
808
|
+
return [];
|
|
809
|
+
break;
|
|
810
|
+
case "BinaryExpression":
|
|
811
|
+
/*
|
|
812
|
+
* `expr has :symbol` can be treated as a reference
|
|
813
|
+
* to expr.symbol.
|
|
814
|
+
*/
|
|
815
|
+
if (node.operator === "has") {
|
|
816
|
+
if (node.right.type === "UnaryExpression" &&
|
|
817
|
+
node.right.operator === ":") {
|
|
818
|
+
if (!name || node.right.argument.name === name) {
|
|
819
|
+
return checkResults(state.lookup({
|
|
820
|
+
type: "MemberExpression",
|
|
821
|
+
object: node.left,
|
|
822
|
+
property: node.right.argument,
|
|
823
|
+
computed: false,
|
|
824
|
+
}), node.right.argument);
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
break;
|
|
829
|
+
case "CallExpression":
|
|
830
|
+
// A call expression whose callee is an identifier is looked
|
|
831
|
+
// up as a non-local. ie even if there's a same named local,
|
|
832
|
+
// it will be ignored, and the lookup will start as if the
|
|
833
|
+
// call had been written self.foo() rather than foo().
|
|
834
|
+
if (node.callee.type === "Identifier") {
|
|
835
|
+
if (!name || node.callee.name === name) {
|
|
836
|
+
/* ignore return value */
|
|
837
|
+
checkResults(state.lookupNonlocal(node.callee), node.callee);
|
|
838
|
+
}
|
|
839
|
+
return ["arguments"];
|
|
840
|
+
}
|
|
841
|
+
break;
|
|
842
|
+
case "Identifier":
|
|
843
|
+
if (!name || node.name === name) {
|
|
844
|
+
return checkResults(state.lookup(node), node);
|
|
845
|
+
}
|
|
846
|
+
break;
|
|
847
|
+
case "MemberExpression":
|
|
848
|
+
if (!node.computed && node.property.type === "Identifier") {
|
|
849
|
+
if (!name || node.property.name === name) {
|
|
850
|
+
return checkResults(state.lookup(node), node) || ["object"];
|
|
851
|
+
}
|
|
852
|
+
return ["object"];
|
|
853
|
+
}
|
|
854
|
+
break;
|
|
855
|
+
case "MethodDefinition": {
|
|
856
|
+
if (!state.inType) {
|
|
857
|
+
throw new Error("Method definition outside of type!");
|
|
858
|
+
}
|
|
859
|
+
if (node.params) {
|
|
860
|
+
node.params.forEach((param) => {
|
|
861
|
+
if (param.type == "BinaryExpression") {
|
|
862
|
+
state.traverse(param.right);
|
|
863
|
+
state.inType = true;
|
|
864
|
+
}
|
|
865
|
+
});
|
|
866
|
+
}
|
|
867
|
+
return ["returnType"];
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
return null;
|
|
871
|
+
};
|
|
872
|
+
(0,external_api_cjs_namespaceObject.collectNamespaces)(ast, state);
|
|
873
|
+
delete state.pre;
|
|
874
|
+
}
|
|
875
|
+
|
|
658
876
|
;// CONCATENATED MODULE: ./src/mc-rewrite.ts
|
|
659
877
|
|
|
660
878
|
|
|
@@ -662,43 +880,25 @@ const external_util_cjs_namespaceObject = require("./util.cjs");
|
|
|
662
880
|
|
|
663
881
|
|
|
664
882
|
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
const [name, module] = lookup(node.id, ("as" in node && node.as && node.as.name) || null, stack);
|
|
668
|
-
if (name && module) {
|
|
669
|
-
const [parent] = stack.slice(-1);
|
|
670
|
-
if (!parent.decls)
|
|
671
|
-
parent.decls = {};
|
|
672
|
-
const decls = parent.decls;
|
|
673
|
-
if (!hasProperty(decls, name))
|
|
674
|
-
decls[name] = [];
|
|
675
|
-
module.forEach((m) => {
|
|
676
|
-
if (isStateNode(m) && m.type == "ModuleDeclaration") {
|
|
677
|
-
pushUnique(decls[name], m);
|
|
678
|
-
if (!parent.type_decls)
|
|
679
|
-
parent.type_decls = {};
|
|
680
|
-
const tdecls = parent.type_decls;
|
|
681
|
-
if (!hasProperty(tdecls, name))
|
|
682
|
-
tdecls[name] = [];
|
|
683
|
-
pushUnique(tdecls[name], m);
|
|
684
|
-
if (node.type == "ImportModule" && m.type_decls) {
|
|
685
|
-
Object.entries(m.type_decls).forEach(([name, decls]) => {
|
|
686
|
-
if (!hasProperty(tdecls, name))
|
|
687
|
-
tdecls[name] = [];
|
|
688
|
-
decls.forEach((decl) => pushUnique(tdecls[name], decl));
|
|
689
|
-
});
|
|
690
|
-
}
|
|
691
|
-
}
|
|
692
|
-
});
|
|
693
|
-
}
|
|
694
|
-
});
|
|
695
|
-
}
|
|
883
|
+
|
|
884
|
+
|
|
696
885
|
function collectClassInfo(state) {
|
|
886
|
+
const toybox = state.stack[0].decls["Toybox"][0];
|
|
887
|
+
const lang = toybox.decls["Lang"][0];
|
|
888
|
+
const object = lang.decls["Object"];
|
|
697
889
|
state.allClasses.forEach((elm) => {
|
|
890
|
+
if (elm.stack[elm.stack.length - 1].type === "ClassDeclaration") {
|
|
891
|
+
// nested classes don't get access to their contained
|
|
892
|
+
// context. Put them in the global scope instead.
|
|
893
|
+
elm.stack = elm.stack.slice(0, 1);
|
|
894
|
+
}
|
|
698
895
|
if (elm.node.superClass) {
|
|
699
|
-
const [name,
|
|
700
|
-
const superClass =
|
|
701
|
-
|
|
896
|
+
const [name, lookupDefns] = state.lookup(elm.node.superClass, null, elm.stack);
|
|
897
|
+
const superClass = lookupDefns &&
|
|
898
|
+
lookupDefns
|
|
899
|
+
.map((lookupDefn) => lookupDefn.results)
|
|
900
|
+
.flat()
|
|
901
|
+
.filter((c) => isStateNode(c) && c.type === "ClassDeclaration");
|
|
702
902
|
// set it "true" if there is a superClass, but we can't find it.
|
|
703
903
|
elm.superClass = superClass && superClass.length ? superClass : true;
|
|
704
904
|
if (name && elm.superClass !== true) {
|
|
@@ -730,6 +930,9 @@ function collectClassInfo(state) {
|
|
|
730
930
|
elm.decls[name] = elm.superClass;
|
|
731
931
|
}
|
|
732
932
|
}
|
|
933
|
+
else if (elm !== object[0]) {
|
|
934
|
+
elm.superClass = object;
|
|
935
|
+
}
|
|
733
936
|
});
|
|
734
937
|
const markOverrides = (cls, scls) => {
|
|
735
938
|
if (scls === true)
|
|
@@ -760,7 +963,9 @@ function getFileSources(fnMap) {
|
|
|
760
963
|
fs
|
|
761
964
|
.readFile(name)
|
|
762
965
|
.then((data) => (value.monkeyCSource = data.toString().replace(/\r\n/g, "\n"))));
|
|
763
|
-
})).then(() => {
|
|
966
|
+
})).then(() => {
|
|
967
|
+
return;
|
|
968
|
+
});
|
|
764
969
|
}
|
|
765
970
|
function getFileASTs(fnMap) {
|
|
766
971
|
return getFileSources(fnMap).then(() => Object.entries(fnMap).reduce((ok, [name, value]) => {
|
|
@@ -783,11 +988,12 @@ function getFileASTs(fnMap) {
|
|
|
783
988
|
return ok;
|
|
784
989
|
}, true));
|
|
785
990
|
}
|
|
786
|
-
async function analyze(fnMap) {
|
|
991
|
+
async function analyze(fnMap, barrelList, config) {
|
|
787
992
|
let hasTests = false;
|
|
788
|
-
|
|
993
|
+
let markApi = true;
|
|
789
994
|
const preState = {
|
|
790
995
|
fnMap,
|
|
996
|
+
config,
|
|
791
997
|
allFunctions: [],
|
|
792
998
|
allClasses: [],
|
|
793
999
|
shouldExclude(node) {
|
|
@@ -815,45 +1021,38 @@ async function analyze(fnMap) {
|
|
|
815
1021
|
}
|
|
816
1022
|
return false;
|
|
817
1023
|
},
|
|
818
|
-
|
|
1024
|
+
pre(node, state) {
|
|
819
1025
|
switch (node.type) {
|
|
820
1026
|
case "FunctionDeclaration":
|
|
1027
|
+
if (markApi) {
|
|
1028
|
+
node.body = null;
|
|
1029
|
+
break;
|
|
1030
|
+
}
|
|
1031
|
+
// falls through
|
|
1032
|
+
case "ModuleDeclaration":
|
|
821
1033
|
case "ClassDeclaration": {
|
|
822
1034
|
const [scope] = state.stack.slice(-1);
|
|
823
|
-
|
|
824
|
-
scope.stack = stack;
|
|
1035
|
+
scope.stack = state.stackClone().slice(0, -1);
|
|
825
1036
|
if (scope.type == "FunctionDeclaration") {
|
|
1037
|
+
scope.isStatic =
|
|
1038
|
+
scope.stack.slice(-1)[0].type !== "ClassDeclaration" ||
|
|
1039
|
+
(scope.node.attrs &&
|
|
1040
|
+
scope.node.attrs.access &&
|
|
1041
|
+
scope.node.attrs.access.includes("static"));
|
|
826
1042
|
state.allFunctions.push(scope);
|
|
827
1043
|
}
|
|
828
|
-
else {
|
|
1044
|
+
else if (scope.type === "ClassDeclaration") {
|
|
829
1045
|
state.allClasses.push(scope);
|
|
830
1046
|
}
|
|
831
|
-
|
|
1047
|
+
break;
|
|
832
1048
|
}
|
|
833
|
-
case "Using":
|
|
834
|
-
case "ImportModule":
|
|
835
|
-
allImports.push({ node, stack: state.stack.slice() });
|
|
836
|
-
return null;
|
|
837
|
-
default:
|
|
838
|
-
return null;
|
|
839
1049
|
}
|
|
1050
|
+
return null;
|
|
840
1051
|
},
|
|
841
1052
|
};
|
|
842
|
-
await getApiMapping(preState);
|
|
1053
|
+
await getApiMapping(preState, barrelList);
|
|
1054
|
+
markApi = false;
|
|
843
1055
|
const state = preState;
|
|
844
|
-
// Mark all functions from api.mir as "special" by
|
|
845
|
-
// setting their bodies to null. In api.mir, they're
|
|
846
|
-
// all empty, which makes it look like they're
|
|
847
|
-
// do-nothing functions.
|
|
848
|
-
const markApi = (node) => {
|
|
849
|
-
if (node.type == "FunctionDeclaration") {
|
|
850
|
-
node.node.body = null;
|
|
851
|
-
}
|
|
852
|
-
if (isStateNode(node) && node.decls) {
|
|
853
|
-
Object.values(node.decls).forEach((v) => v.forEach(markApi));
|
|
854
|
-
}
|
|
855
|
-
};
|
|
856
|
-
markApi(state.stack[0]);
|
|
857
1056
|
await getFileASTs(fnMap);
|
|
858
1057
|
Object.entries(fnMap).forEach(([name, value]) => {
|
|
859
1058
|
const { ast, parserError } = value;
|
|
@@ -866,8 +1065,28 @@ async function analyze(fnMap) {
|
|
|
866
1065
|
});
|
|
867
1066
|
delete state.shouldExclude;
|
|
868
1067
|
delete state.post;
|
|
869
|
-
processImports(allImports, state.lookup);
|
|
870
1068
|
collectClassInfo(state);
|
|
1069
|
+
const diagnosticType = config?.checkInvalidSymbols !== "OFF"
|
|
1070
|
+
? config?.checkInvalidSymbols || "WARNING"
|
|
1071
|
+
: null;
|
|
1072
|
+
if (diagnosticType &&
|
|
1073
|
+
!config?.compilerOptions?.includes("--Eno-invalid-symbol")) {
|
|
1074
|
+
const checkTypes = config?.typeCheckLevel && config.typeCheckLevel !== "Off";
|
|
1075
|
+
Object.entries(fnMap).forEach(([, v]) => {
|
|
1076
|
+
visitReferences(state, v.ast, null, false, (node, results, error) => {
|
|
1077
|
+
if (!error)
|
|
1078
|
+
return undefined;
|
|
1079
|
+
const nodeStr = formatAst(node);
|
|
1080
|
+
if (state.inType) {
|
|
1081
|
+
if (!checkTypes || nodeStr.match(/^Void|Null$/)) {
|
|
1082
|
+
return undefined;
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
diagnostic(state, node.loc, `Undefined symbol ${nodeStr}`, diagnosticType);
|
|
1086
|
+
return false;
|
|
1087
|
+
});
|
|
1088
|
+
});
|
|
1089
|
+
}
|
|
871
1090
|
return state;
|
|
872
1091
|
}
|
|
873
1092
|
function compareLiteralLike(a, b) {
|
|
@@ -877,11 +1096,11 @@ function compareLiteralLike(a, b) {
|
|
|
877
1096
|
b = b.left;
|
|
878
1097
|
return a.type === "Literal" && b.type === "Literal" && a.value === b.value;
|
|
879
1098
|
}
|
|
880
|
-
function getLiteralFromDecls(
|
|
881
|
-
if (!
|
|
1099
|
+
function getLiteralFromDecls(lookupDefns) {
|
|
1100
|
+
if (!lookupDefns.length)
|
|
882
1101
|
return null;
|
|
883
1102
|
let result = null;
|
|
884
|
-
if (
|
|
1103
|
+
if (lookupDefns.every((lookupDefn) => lookupDefn.results.every((d) => {
|
|
885
1104
|
if (d.type === "EnumStringMember" ||
|
|
886
1105
|
(d.type === "VariableDeclarator" && d.node.kind === "const")) {
|
|
887
1106
|
const init = getLiteralNode(d.type === "EnumStringMember" ? d.init : d.node.init);
|
|
@@ -896,7 +1115,7 @@ function getLiteralFromDecls(decls) {
|
|
|
896
1115
|
}
|
|
897
1116
|
}
|
|
898
1117
|
return false;
|
|
899
|
-
})) {
|
|
1118
|
+
}))) {
|
|
900
1119
|
return result;
|
|
901
1120
|
}
|
|
902
1121
|
return null;
|
|
@@ -1107,20 +1326,23 @@ function markFunctionCalled(state, func) {
|
|
|
1107
1326
|
}
|
|
1108
1327
|
pushUnique(state.calledFunctions[func.id.name], func);
|
|
1109
1328
|
}
|
|
1110
|
-
async function optimizeMonkeyC(fnMap) {
|
|
1329
|
+
async function optimizeMonkeyC(fnMap, barrelList, config) {
|
|
1111
1330
|
const state = {
|
|
1112
|
-
...(await analyze(fnMap)),
|
|
1331
|
+
...(await analyze(fnMap, barrelList, config)),
|
|
1113
1332
|
localsStack: [{}],
|
|
1114
1333
|
exposed: {},
|
|
1115
1334
|
calledFunctions: {},
|
|
1116
1335
|
};
|
|
1117
|
-
const replace = (node) => {
|
|
1336
|
+
const replace = (node, old) => {
|
|
1118
1337
|
if (node === false || node === null)
|
|
1119
1338
|
return node;
|
|
1120
1339
|
const rep = state.traverse(node);
|
|
1121
|
-
|
|
1340
|
+
if (rep === false || Array.isArray(rep))
|
|
1341
|
+
return rep;
|
|
1342
|
+
return { ...(rep || node), loc: old.loc, start: old.start, end: old.end };
|
|
1122
1343
|
};
|
|
1123
1344
|
const inPlaceReplacement = (node, obj) => {
|
|
1345
|
+
const { start, end, loc } = node;
|
|
1124
1346
|
for (const k of Object.keys(node)) {
|
|
1125
1347
|
delete node[k];
|
|
1126
1348
|
}
|
|
@@ -1128,13 +1350,16 @@ async function optimizeMonkeyC(fnMap) {
|
|
|
1128
1350
|
obj = {
|
|
1129
1351
|
type: "BinaryExpression",
|
|
1130
1352
|
operator: "as",
|
|
1131
|
-
left: obj,
|
|
1353
|
+
left: { ...obj, start, end, loc },
|
|
1132
1354
|
right: { type: "TypeSpecList", ts: [obj.enumType] },
|
|
1133
1355
|
};
|
|
1134
1356
|
}
|
|
1135
1357
|
for (const [k, v] of Object.entries(obj)) {
|
|
1136
1358
|
node[k] = v;
|
|
1137
1359
|
}
|
|
1360
|
+
node.loc = loc;
|
|
1361
|
+
node.start = start;
|
|
1362
|
+
node.end = end;
|
|
1138
1363
|
};
|
|
1139
1364
|
const lookupAndReplace = (node) => {
|
|
1140
1365
|
const [, objects] = state.lookup(node);
|
|
@@ -1192,7 +1417,7 @@ async function optimizeMonkeyC(fnMap) {
|
|
|
1192
1417
|
case "ConditionalExpression":
|
|
1193
1418
|
case "IfStatement":
|
|
1194
1419
|
case "DoWhileStatement":
|
|
1195
|
-
case "WhileStatement":
|
|
1420
|
+
case "WhileStatement": {
|
|
1196
1421
|
const test = (state.traverse(node.test) ||
|
|
1197
1422
|
node.test);
|
|
1198
1423
|
const [value, type] = getNodeValue(test);
|
|
@@ -1224,6 +1449,7 @@ async function optimizeMonkeyC(fnMap) {
|
|
|
1224
1449
|
}
|
|
1225
1450
|
}
|
|
1226
1451
|
return null;
|
|
1452
|
+
}
|
|
1227
1453
|
case "EnumDeclaration":
|
|
1228
1454
|
return false;
|
|
1229
1455
|
case "ForStatement": {
|
|
@@ -1253,6 +1479,37 @@ async function optimizeMonkeyC(fnMap) {
|
|
|
1253
1479
|
}
|
|
1254
1480
|
return ["init"];
|
|
1255
1481
|
}
|
|
1482
|
+
case "CatchClause":
|
|
1483
|
+
if (node.param) {
|
|
1484
|
+
state.localsStack.push({ node, map: { ...(topLocals().map || {}) } });
|
|
1485
|
+
const locals = topLocals();
|
|
1486
|
+
const map = locals.map;
|
|
1487
|
+
const declName = variableDeclarationName(node.param);
|
|
1488
|
+
const name = renameVariable(state, locals, declName);
|
|
1489
|
+
if (name) {
|
|
1490
|
+
if (node.param.type === "Identifier") {
|
|
1491
|
+
node.param.name = name;
|
|
1492
|
+
}
|
|
1493
|
+
else {
|
|
1494
|
+
node.param.left.name = name;
|
|
1495
|
+
}
|
|
1496
|
+
}
|
|
1497
|
+
else {
|
|
1498
|
+
map[declName] = true;
|
|
1499
|
+
}
|
|
1500
|
+
return ["body"];
|
|
1501
|
+
}
|
|
1502
|
+
break;
|
|
1503
|
+
case "BinaryExpression":
|
|
1504
|
+
if (node.operator === "has") {
|
|
1505
|
+
if (node.right.type === "UnaryExpression" &&
|
|
1506
|
+
node.right.operator === ":") {
|
|
1507
|
+
// Using `expr has :symbol` doesn't "expose"
|
|
1508
|
+
// symbol. So skip the right operand.
|
|
1509
|
+
return ["left"];
|
|
1510
|
+
}
|
|
1511
|
+
}
|
|
1512
|
+
break;
|
|
1256
1513
|
case "UnaryExpression":
|
|
1257
1514
|
if (node.operator == ":") {
|
|
1258
1515
|
// If we produce a Symbol, for a given name,
|
|
@@ -1335,7 +1592,7 @@ async function optimizeMonkeyC(fnMap) {
|
|
|
1335
1592
|
}
|
|
1336
1593
|
const opt = optimizeNode(node);
|
|
1337
1594
|
if (opt) {
|
|
1338
|
-
return replace(opt);
|
|
1595
|
+
return replace(opt, node);
|
|
1339
1596
|
}
|
|
1340
1597
|
switch (node.type) {
|
|
1341
1598
|
case "ConditionalExpression":
|
|
@@ -1345,7 +1602,7 @@ async function optimizeMonkeyC(fnMap) {
|
|
|
1345
1602
|
const rep = node.test.value ? node.consequent : node.alternate;
|
|
1346
1603
|
if (!rep)
|
|
1347
1604
|
return false;
|
|
1348
|
-
return replace(rep);
|
|
1605
|
+
return replace(rep, rep);
|
|
1349
1606
|
}
|
|
1350
1607
|
break;
|
|
1351
1608
|
case "WhileStatement":
|
|
@@ -1360,11 +1617,11 @@ async function optimizeMonkeyC(fnMap) {
|
|
|
1360
1617
|
break;
|
|
1361
1618
|
case "ReturnStatement":
|
|
1362
1619
|
if (node.argument && node.argument.type === "CallExpression") {
|
|
1363
|
-
return replace(optimizeCall(state, node.argument, node));
|
|
1620
|
+
return replace(optimizeCall(state, node.argument, node), node.argument);
|
|
1364
1621
|
}
|
|
1365
1622
|
break;
|
|
1366
1623
|
case "CallExpression": {
|
|
1367
|
-
return replace(optimizeCall(state, node, null));
|
|
1624
|
+
return replace(optimizeCall(state, node, null), node);
|
|
1368
1625
|
}
|
|
1369
1626
|
case "AssignmentExpression":
|
|
1370
1627
|
if (node.operator === "=" &&
|
|
@@ -1376,7 +1633,7 @@ async function optimizeMonkeyC(fnMap) {
|
|
|
1376
1633
|
break;
|
|
1377
1634
|
case "ExpressionStatement":
|
|
1378
1635
|
if (node.expression.type === "CallExpression") {
|
|
1379
|
-
return replace(optimizeCall(state, node.expression, node));
|
|
1636
|
+
return replace(optimizeCall(state, node.expression, node), node.expression);
|
|
1380
1637
|
}
|
|
1381
1638
|
else if (node.expression.type === "AssignmentExpression") {
|
|
1382
1639
|
if (node.expression.right.type === "CallExpression") {
|
|
@@ -1388,10 +1645,10 @@ async function optimizeMonkeyC(fnMap) {
|
|
|
1388
1645
|
}
|
|
1389
1646
|
if (!ok && node.expression.operator == "=") {
|
|
1390
1647
|
const [, result] = state.lookup(node.expression.left);
|
|
1391
|
-
ok = result
|
|
1648
|
+
ok = !!result;
|
|
1392
1649
|
}
|
|
1393
1650
|
if (ok) {
|
|
1394
|
-
return replace(optimizeCall(state, node.expression.right, node.expression));
|
|
1651
|
+
return replace(optimizeCall(state, node.expression.right, node.expression), node.expression.right);
|
|
1395
1652
|
}
|
|
1396
1653
|
}
|
|
1397
1654
|
}
|
|
@@ -1399,7 +1656,7 @@ async function optimizeMonkeyC(fnMap) {
|
|
|
1399
1656
|
const ret = unused(node.expression, true);
|
|
1400
1657
|
if (ret) {
|
|
1401
1658
|
return ret
|
|
1402
|
-
.map(replace)
|
|
1659
|
+
.map((r) => replace(r, r))
|
|
1403
1660
|
.flat(1)
|
|
1404
1661
|
.filter((s) => !!s);
|
|
1405
1662
|
}
|
|
@@ -1420,6 +1677,9 @@ async function optimizeMonkeyC(fnMap) {
|
|
|
1420
1677
|
delete state.post;
|
|
1421
1678
|
const cleanup = (node) => {
|
|
1422
1679
|
switch (node.type) {
|
|
1680
|
+
case "ThisExpression":
|
|
1681
|
+
node.text = "self";
|
|
1682
|
+
break;
|
|
1423
1683
|
case "EnumStringBody":
|
|
1424
1684
|
if (node.members.every((m) => {
|
|
1425
1685
|
const name = "name" in m ? m.name : m.id.name;
|
|
@@ -1484,6 +1744,19 @@ async function optimizeMonkeyC(fnMap) {
|
|
|
1484
1744
|
return false;
|
|
1485
1745
|
}
|
|
1486
1746
|
break;
|
|
1747
|
+
case "ClassDeclaration":
|
|
1748
|
+
case "ModuleDeclaration":
|
|
1749
|
+
// none of the attributes means anything on classes and
|
|
1750
|
+
// modules, and the new compiler complains about some
|
|
1751
|
+
// of them. Just drop them all.
|
|
1752
|
+
if (node.attrs && node.attrs.access) {
|
|
1753
|
+
if (node.attrs.attributes) {
|
|
1754
|
+
delete node.attrs.access;
|
|
1755
|
+
}
|
|
1756
|
+
else {
|
|
1757
|
+
delete node.attrs;
|
|
1758
|
+
}
|
|
1759
|
+
}
|
|
1487
1760
|
}
|
|
1488
1761
|
return null;
|
|
1489
1762
|
};
|
|
@@ -1499,9 +1772,12 @@ async function optimizeMonkeyC(fnMap) {
|
|
|
1499
1772
|
return state.diagnostics;
|
|
1500
1773
|
}
|
|
1501
1774
|
function optimizeCall(state, node, context) {
|
|
1502
|
-
const [name, results] = state.
|
|
1775
|
+
const [name, results] = state.lookupNonlocal(node.callee);
|
|
1503
1776
|
const callees = results &&
|
|
1504
|
-
results
|
|
1777
|
+
results
|
|
1778
|
+
.map((r) => r.results)
|
|
1779
|
+
.flat()
|
|
1780
|
+
.filter((c) => c.type === "FunctionDeclaration");
|
|
1505
1781
|
if (!callees || !callees.length) {
|
|
1506
1782
|
const n = name ||
|
|
1507
1783
|
("name" in node.callee && node.callee.name) ||
|
|
@@ -1606,6 +1882,10 @@ const external_sdk_util_cjs_namespaceObject = require("./sdk-util.cjs");
|
|
|
1606
1882
|
|
|
1607
1883
|
|
|
1608
1884
|
|
|
1885
|
+
|
|
1886
|
+
|
|
1887
|
+
|
|
1888
|
+
|
|
1609
1889
|
/*
|
|
1610
1890
|
* This is an unfortunate hack. I want to be able to extract things
|
|
1611
1891
|
* like the types of all of a Class's variables (in particular the type
|
|
@@ -1616,16 +1896,30 @@ const external_sdk_util_cjs_namespaceObject = require("./sdk-util.cjs");
|
|
|
1616
1896
|
* but those are at least in a standard format.
|
|
1617
1897
|
*/
|
|
1618
1898
|
// Extract all enum values from api.mir
|
|
1619
|
-
async function api_getApiMapping(state) {
|
|
1899
|
+
async function api_getApiMapping(state, barrelList) {
|
|
1620
1900
|
// get the path to the currently active sdk
|
|
1621
1901
|
const parser = (prettier_plugin_monkeyc_default()).parsers.monkeyc;
|
|
1622
1902
|
const sdk = await (0,external_sdk_util_cjs_namespaceObject.getSdkPath)();
|
|
1903
|
+
const rezDecl = `module Rez { ${[
|
|
1904
|
+
"Drawables",
|
|
1905
|
+
"Fonts",
|
|
1906
|
+
"JsonData",
|
|
1907
|
+
"Layouts",
|
|
1908
|
+
"Menus",
|
|
1909
|
+
"Strings",
|
|
1910
|
+
]
|
|
1911
|
+
.map((s) => ` module ${s} {}\n`)
|
|
1912
|
+
.join("")}}`;
|
|
1623
1913
|
const api = (await promises_namespaceObject.readFile(`${sdk}bin/api.mir`))
|
|
1624
1914
|
.toString()
|
|
1625
1915
|
.replace(/\r\n/g, "\n")
|
|
1626
1916
|
.replace(/^\s*\[.*?\]\s*$/gm, "")
|
|
1627
1917
|
//.replace(/(COLOR_TRANSPARENT|LAYOUT_[HV]ALIGN_\w+) = (\d+)/gm, "$1 = -$2")
|
|
1628
|
-
.replace(/^(\s*type)\s/gm, "$1def ")
|
|
1918
|
+
.replace(/^(\s*type)\s/gm, "$1def ") +
|
|
1919
|
+
(barrelList || [])
|
|
1920
|
+
.map((name) => `module ${name} { ${rezDecl} }`)
|
|
1921
|
+
.concat(rezDecl)
|
|
1922
|
+
.join("");
|
|
1629
1923
|
try {
|
|
1630
1924
|
const result = api_collectNamespaces(parser.parse(api, null, {
|
|
1631
1925
|
filepath: "api.mir",
|
|
@@ -1639,23 +1933,24 @@ async function api_getApiMapping(state) {
|
|
|
1639
1933
|
return decls[0];
|
|
1640
1934
|
}, result);
|
|
1641
1935
|
const value = api_isStateNode(vs) ? vs.node : vs;
|
|
1642
|
-
if (value
|
|
1643
|
-
(value.type !== "
|
|
1936
|
+
if (!value ||
|
|
1937
|
+
(value.type !== "EnumStringMember" &&
|
|
1938
|
+
(value.type !== "VariableDeclarator" || value.kind != "const"))) {
|
|
1644
1939
|
throw `Negative constant ${fixup} did not refer to a constant`;
|
|
1645
1940
|
}
|
|
1646
|
-
const init = value.init;
|
|
1941
|
+
const init = getLiteralNode(value.init);
|
|
1647
1942
|
if (!init || init.type !== "Literal") {
|
|
1648
1943
|
throw `Negative constant ${fixup} was not a Literal`;
|
|
1649
1944
|
}
|
|
1650
1945
|
if (typeof init.value !== "number") {
|
|
1651
|
-
console.log(`Negative fixup ${fixup} was
|
|
1946
|
+
console.log(`Negative fixup ${fixup} was not a number!`);
|
|
1652
1947
|
}
|
|
1653
1948
|
else if (init.value > 0) {
|
|
1654
1949
|
init.value = -init.value;
|
|
1655
1950
|
init.raw = "-" + init.raw;
|
|
1656
1951
|
}
|
|
1657
1952
|
else {
|
|
1658
|
-
console.log(`Negative fixup ${fixup} was already negative!`);
|
|
1953
|
+
// console.log(`Negative fixup ${fixup} was already negative!`);
|
|
1659
1954
|
}
|
|
1660
1955
|
});
|
|
1661
1956
|
return result;
|
|
@@ -1674,67 +1969,197 @@ function api_isStateNode(node) {
|
|
|
1674
1969
|
function api_variableDeclarationName(node) {
|
|
1675
1970
|
return ("left" in node ? node.left : node).name;
|
|
1676
1971
|
}
|
|
1677
|
-
function
|
|
1972
|
+
function lookupToStateNodeDecls(results) {
|
|
1973
|
+
return results.reduce((result, current) => current.results.length
|
|
1974
|
+
? result
|
|
1975
|
+
? result.concat(current.results)
|
|
1976
|
+
: current.results
|
|
1977
|
+
: result, null);
|
|
1978
|
+
}
|
|
1979
|
+
function checkOne(state, ns, decls, node, isStatic) {
|
|
1980
|
+
// follow the superchain, looking up node in each class
|
|
1981
|
+
const superChain = (cls) => {
|
|
1982
|
+
if (!cls.superClass || cls.superClass === true) {
|
|
1983
|
+
return null;
|
|
1984
|
+
}
|
|
1985
|
+
return cls.superClass.reduce((result, sup) => {
|
|
1986
|
+
const sdecls = sup[decls];
|
|
1987
|
+
const next = api_hasProperty(sdecls, node.name)
|
|
1988
|
+
? sdecls[node.name]
|
|
1989
|
+
: superChain(sup);
|
|
1990
|
+
return next ? (result ? result.concat(next) : next) : result;
|
|
1991
|
+
}, null);
|
|
1992
|
+
};
|
|
1993
|
+
const lookupInContext = (ns) => {
|
|
1994
|
+
const [, lkup] = lookup(state, decls, node, null, ns.stack);
|
|
1995
|
+
return lkup && lookupToStateNodeDecls(lkup);
|
|
1996
|
+
};
|
|
1997
|
+
// follow the superchain, looking up node in each class's scope
|
|
1998
|
+
const superChainScopes = (ns) => {
|
|
1999
|
+
const result = lookupInContext(ns);
|
|
2000
|
+
if (result)
|
|
2001
|
+
return result;
|
|
2002
|
+
if (!ns.superClass || ns.superClass === true) {
|
|
2003
|
+
return null;
|
|
2004
|
+
}
|
|
2005
|
+
return ns.superClass.reduce((result, sup) => {
|
|
2006
|
+
const next = superChainScopes(sup);
|
|
2007
|
+
return next ? (result ? result.concat(next) : next) : result;
|
|
2008
|
+
}, null);
|
|
2009
|
+
};
|
|
1678
2010
|
if (api_isStateNode(ns)) {
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
2011
|
+
const ndecls = ns[decls];
|
|
2012
|
+
if (api_hasProperty(ndecls, node.name)) {
|
|
2013
|
+
return ndecls[node.name];
|
|
2014
|
+
}
|
|
2015
|
+
switch (ns.type) {
|
|
2016
|
+
case "ClassDeclaration":
|
|
2017
|
+
if (!isStatic) {
|
|
2018
|
+
return superChain(ns) || superChainScopes(ns) || false;
|
|
2019
|
+
}
|
|
2020
|
+
// fall through
|
|
2021
|
+
case "ModuleDeclaration":
|
|
2022
|
+
return lookupInContext(ns) || false;
|
|
1690
2023
|
}
|
|
1691
2024
|
}
|
|
1692
2025
|
return null;
|
|
1693
2026
|
}
|
|
1694
|
-
function
|
|
1695
|
-
|
|
2027
|
+
function sameStateNodeDecl(a, b) {
|
|
2028
|
+
if (a === b)
|
|
2029
|
+
return true;
|
|
2030
|
+
if (!a || !b)
|
|
2031
|
+
return false;
|
|
2032
|
+
if (!api_isStateNode(a) || a.type !== b.type)
|
|
2033
|
+
return false;
|
|
2034
|
+
return (a.node === b.node ||
|
|
2035
|
+
a.type === "Program" ||
|
|
2036
|
+
(a.type === "ModuleDeclaration" && a.fullName === b.fullName));
|
|
2037
|
+
}
|
|
2038
|
+
function sameLookupDefinition(a, b) {
|
|
2039
|
+
return (
|
|
2040
|
+
// sameStateNodeDecl(a.parent, b.parent) &&
|
|
2041
|
+
(0,external_util_cjs_namespaceObject.sameArrays)(a.results, b.results, (ar, br) => sameStateNodeDecl(ar, br)));
|
|
2042
|
+
}
|
|
2043
|
+
function api_sameLookupResult(a, b) {
|
|
2044
|
+
return (0,external_util_cjs_namespaceObject.sameArrays)(a, b, sameLookupDefinition);
|
|
2045
|
+
}
|
|
2046
|
+
/**
|
|
2047
|
+
*
|
|
2048
|
+
* @param state - The ProgramState
|
|
2049
|
+
* @param decls - The field to use to look things up. either "decls" or "type_decls"
|
|
2050
|
+
* @param node - The node to lookup
|
|
2051
|
+
* @param name - Overrides the name of the node.
|
|
2052
|
+
* @param stack - if provided, use this stack, rather than the current
|
|
2053
|
+
* state.stack for the lookup
|
|
2054
|
+
* @param nonlocal - when true, a plain identifier will be looked up as a
|
|
2055
|
+
* non-local. This is needed when looking up a callee.
|
|
2056
|
+
* If the callee is a MemberExpression, the flag is ignored.
|
|
2057
|
+
* @returns
|
|
2058
|
+
* - [string, LookupDefinition[]] - if the lookup succeeds
|
|
2059
|
+
* - [false, false] - if the lookup fails, but its not an error because its not the kind of expression we can lookup
|
|
2060
|
+
* - [null, null] - if the lookup fails unexpectedly.
|
|
2061
|
+
*/
|
|
2062
|
+
function lookup(state, decls, node, name, maybeStack, nonlocal) {
|
|
2063
|
+
const stack = maybeStack || state.stack;
|
|
1696
2064
|
switch (node.type) {
|
|
1697
2065
|
case "MemberExpression": {
|
|
1698
2066
|
if (node.property.type != "Identifier" || node.computed)
|
|
1699
2067
|
break;
|
|
1700
|
-
const
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
2068
|
+
const property = node.property;
|
|
2069
|
+
let result;
|
|
2070
|
+
if (node.object.type === "ThisExpression") {
|
|
2071
|
+
[, result] = lookup(state, decls, node.property, name, stack, true);
|
|
2072
|
+
}
|
|
2073
|
+
else {
|
|
2074
|
+
const [, results] = lookup(state, decls, node.object, name, stack, false);
|
|
2075
|
+
if (results === false)
|
|
2076
|
+
break;
|
|
2077
|
+
if (!results)
|
|
2078
|
+
return [null, null];
|
|
2079
|
+
result = results.reduce((current, lookupDef) => {
|
|
2080
|
+
const items = lookupDef.results
|
|
2081
|
+
.map((module) => {
|
|
2082
|
+
const res = checkOne(state, module, decls, property, false);
|
|
2083
|
+
return res ? { parent: module, results: res } : null;
|
|
2084
|
+
})
|
|
2085
|
+
.filter((r) => r != null);
|
|
2086
|
+
if (!items.length)
|
|
2087
|
+
return current;
|
|
2088
|
+
return current ? current.concat(items) : items;
|
|
2089
|
+
}, null);
|
|
2090
|
+
if (!result &&
|
|
2091
|
+
results.some((ld) => ld.results.some((sn) => (api_isStateNode(sn) && sn.fullName?.match(/^\$\.(\w+\.)?Rez\./)) ||
|
|
2092
|
+
sn.type === "VariableDeclarator" ||
|
|
2093
|
+
sn.type === "Identifier" ||
|
|
2094
|
+
sn.type === "BinaryExpression" ||
|
|
2095
|
+
(sn.type === "ClassDeclaration" &&
|
|
2096
|
+
property.name === "initialize")))) {
|
|
2097
|
+
// - The Rez module can contain lots of things from the resource
|
|
2098
|
+
// compiler which we don't track.
|
|
2099
|
+
// - Variables, and formal parameters would require type tracking
|
|
2100
|
+
// which we don't yet do
|
|
2101
|
+
// - Its ok to call an undeclared initialize method.
|
|
2102
|
+
// Report them all as "expected failures".
|
|
2103
|
+
return [false, false];
|
|
1709
2104
|
}
|
|
1710
2105
|
}
|
|
1711
|
-
|
|
2106
|
+
if (!result)
|
|
2107
|
+
return [null, null];
|
|
2108
|
+
return [name || property.name, result];
|
|
1712
2109
|
}
|
|
1713
2110
|
case "ThisExpression": {
|
|
1714
|
-
for (let i = stack.length
|
|
2111
|
+
for (let i = stack.length;;) {
|
|
1715
2112
|
const si = stack[i];
|
|
1716
2113
|
if (si.type == "ModuleDeclaration" ||
|
|
1717
2114
|
si.type == "ClassDeclaration" ||
|
|
1718
2115
|
!i) {
|
|
1719
|
-
return [
|
|
2116
|
+
return [
|
|
2117
|
+
name || si.name,
|
|
2118
|
+
[{ parent: i ? stack[i - 1] : null, results: [si] }],
|
|
2119
|
+
];
|
|
1720
2120
|
}
|
|
1721
2121
|
}
|
|
1722
|
-
break;
|
|
1723
2122
|
}
|
|
1724
2123
|
case "Identifier": {
|
|
1725
2124
|
if (node.name == "$") {
|
|
1726
|
-
return [name || node.name, [stack[0]]
|
|
2125
|
+
return [name || node.name, [{ parent: null, results: [stack[0]] }]];
|
|
1727
2126
|
}
|
|
2127
|
+
let inStatic = false;
|
|
2128
|
+
let checkedImports = false;
|
|
1728
2129
|
for (let i = stack.length; i--;) {
|
|
1729
|
-
const
|
|
1730
|
-
|
|
1731
|
-
|
|
2130
|
+
const si = stack[i];
|
|
2131
|
+
switch (si.type) {
|
|
2132
|
+
case "ClassDeclaration":
|
|
2133
|
+
case "ModuleDeclaration":
|
|
2134
|
+
case "Program":
|
|
2135
|
+
if (!checkedImports) {
|
|
2136
|
+
checkedImports = true;
|
|
2137
|
+
const results = findUsingForNode(state, stack, i, node, decls === "type_decls");
|
|
2138
|
+
if (results) {
|
|
2139
|
+
return [name || node.name, [{ parent: si, results }]];
|
|
2140
|
+
}
|
|
2141
|
+
}
|
|
2142
|
+
break;
|
|
2143
|
+
case "FunctionDeclaration":
|
|
2144
|
+
inStatic = si.isStatic === true;
|
|
2145
|
+
// fall through
|
|
2146
|
+
default:
|
|
2147
|
+
if (nonlocal)
|
|
2148
|
+
continue;
|
|
2149
|
+
break;
|
|
2150
|
+
}
|
|
2151
|
+
const results = checkOne(state, si, decls, node, inStatic);
|
|
2152
|
+
if (results) {
|
|
2153
|
+
return [name || node.name, [{ parent: si, results }]];
|
|
2154
|
+
}
|
|
2155
|
+
else if (results === false) {
|
|
2156
|
+
break;
|
|
1732
2157
|
}
|
|
1733
2158
|
}
|
|
1734
|
-
|
|
2159
|
+
return [null, null];
|
|
1735
2160
|
}
|
|
1736
2161
|
}
|
|
1737
|
-
return [
|
|
2162
|
+
return [false, false];
|
|
1738
2163
|
}
|
|
1739
2164
|
function api_collectNamespaces(ast, stateIn) {
|
|
1740
2165
|
const state = (stateIn || {});
|
|
@@ -1750,14 +2175,15 @@ function api_collectNamespaces(ast, stateIn) {
|
|
|
1750
2175
|
let low = 0, high = ast.comments.length;
|
|
1751
2176
|
while (high > low) {
|
|
1752
2177
|
const mid = (low + high) >> 1;
|
|
1753
|
-
if (ast.comments[mid].start < node.start) {
|
|
2178
|
+
if ((ast.comments[mid].start || 0) < node.start) {
|
|
1754
2179
|
low = mid + 1;
|
|
1755
2180
|
}
|
|
1756
2181
|
else {
|
|
1757
2182
|
high = mid;
|
|
1758
2183
|
}
|
|
1759
2184
|
}
|
|
1760
|
-
while (high < ast.comments.length &&
|
|
2185
|
+
while (high < ast.comments.length &&
|
|
2186
|
+
(ast.comments[high].end || 0) < node.end) {
|
|
1761
2187
|
high++;
|
|
1762
2188
|
}
|
|
1763
2189
|
if (high > low) {
|
|
@@ -1766,10 +2192,14 @@ function api_collectNamespaces(ast, stateIn) {
|
|
|
1766
2192
|
}
|
|
1767
2193
|
};
|
|
1768
2194
|
state.lookup = (node, name, stack) => lookup(state, state.inType ? "type_decls" : "decls", node, name, stack);
|
|
2195
|
+
state.lookupNonlocal = (node, name, stack) => lookup(state, "decls", node, name, stack, true);
|
|
1769
2196
|
state.lookupValue = (node, name, stack) => lookup(state, "decls", node, name, stack);
|
|
1770
2197
|
state.lookupType = (node, name, stack) => lookup(state, "type_decls", node, name, stack);
|
|
2198
|
+
state.stackClone = () => state.stack.map((elm) => elm.type === "ModuleDeclaration" || elm.type === "Program"
|
|
2199
|
+
? { ...elm }
|
|
2200
|
+
: elm);
|
|
1771
2201
|
state.inType = false;
|
|
1772
|
-
state.traverse = (root) =>
|
|
2202
|
+
state.traverse = (root) => ast_traverseAst(root, (node) => {
|
|
1773
2203
|
try {
|
|
1774
2204
|
if (state.shouldExclude && state.shouldExclude(node)) {
|
|
1775
2205
|
// don't visit any children, but do call post
|
|
@@ -1780,14 +2210,60 @@ function api_collectNamespaces(ast, stateIn) {
|
|
|
1780
2210
|
if (state.stack.length != 1) {
|
|
1781
2211
|
throw new Error("Unexpected stack length for Program node");
|
|
1782
2212
|
}
|
|
2213
|
+
state.stack[0].node = node;
|
|
1783
2214
|
break;
|
|
1784
2215
|
case "TypeSpecList":
|
|
1785
2216
|
state.inType = true;
|
|
1786
2217
|
break;
|
|
2218
|
+
case "ImportModule":
|
|
2219
|
+
case "Using": {
|
|
2220
|
+
const [parent] = state.stack.slice(-1);
|
|
2221
|
+
if (!parent.usings) {
|
|
2222
|
+
parent.usings = {};
|
|
2223
|
+
}
|
|
2224
|
+
const name = (node.type === "Using" && node.as && node.as.name) ||
|
|
2225
|
+
(node.id.type === "Identifier"
|
|
2226
|
+
? node.id.name
|
|
2227
|
+
: node.id.property.name);
|
|
2228
|
+
const using = { node };
|
|
2229
|
+
parent.usings[name] = using;
|
|
2230
|
+
if (node.type == "ImportModule") {
|
|
2231
|
+
if (!parent.imports) {
|
|
2232
|
+
parent.imports = [using];
|
|
2233
|
+
}
|
|
2234
|
+
else {
|
|
2235
|
+
const index = parent.imports.findIndex((using) => (using.node.id.type === "Identifier"
|
|
2236
|
+
? using.node.id.name
|
|
2237
|
+
: using.node.id.property.name) === name);
|
|
2238
|
+
if (index >= 0)
|
|
2239
|
+
parent.imports.splice(index, 1);
|
|
2240
|
+
parent.imports.push(using);
|
|
2241
|
+
}
|
|
2242
|
+
}
|
|
2243
|
+
break;
|
|
2244
|
+
}
|
|
2245
|
+
case "CatchClause":
|
|
2246
|
+
if (node.param) {
|
|
2247
|
+
const [parent] = state.stack.slice(-1);
|
|
2248
|
+
if (!parent.decls)
|
|
2249
|
+
parent.decls = {};
|
|
2250
|
+
const id = node.param.type === "Identifier"
|
|
2251
|
+
? node.param
|
|
2252
|
+
: node.param.left;
|
|
2253
|
+
state.stack.push({
|
|
2254
|
+
type: "BlockStatement",
|
|
2255
|
+
fullName: undefined,
|
|
2256
|
+
name: undefined,
|
|
2257
|
+
node: node.body,
|
|
2258
|
+
decls: { [id.name]: [id] },
|
|
2259
|
+
});
|
|
2260
|
+
}
|
|
2261
|
+
break;
|
|
1787
2262
|
case "BlockStatement": {
|
|
1788
2263
|
const [parent] = state.stack.slice(-1);
|
|
1789
|
-
if (parent.
|
|
1790
|
-
parent.type != "
|
|
2264
|
+
if (parent.node === node ||
|
|
2265
|
+
(parent.type != "FunctionDeclaration" &&
|
|
2266
|
+
parent.type != "BlockStatement")) {
|
|
1791
2267
|
break;
|
|
1792
2268
|
}
|
|
1793
2269
|
// fall through
|
|
@@ -1833,6 +2309,9 @@ function api_collectNamespaces(ast, stateIn) {
|
|
|
1833
2309
|
parent.decls[name].push(elm);
|
|
1834
2310
|
if (node.type == "ModuleDeclaration" ||
|
|
1835
2311
|
node.type == "ClassDeclaration") {
|
|
2312
|
+
// Inject the class/module name into itself,
|
|
2313
|
+
// so you can say Graphics.Graphics.Graphics.COLOR_RED
|
|
2314
|
+
elm.decls = { [name]: [elm] };
|
|
1836
2315
|
if (!parent.type_decls)
|
|
1837
2316
|
parent.type_decls = {};
|
|
1838
2317
|
if (!api_hasProperty(parent.type_decls, name)) {
|
|
@@ -1880,7 +2359,7 @@ function api_collectNamespaces(ast, stateIn) {
|
|
|
1880
2359
|
if (!parent.decls)
|
|
1881
2360
|
parent.decls = {};
|
|
1882
2361
|
const decls = parent.decls;
|
|
1883
|
-
const stack = state.
|
|
2362
|
+
const stack = state.stackClone();
|
|
1884
2363
|
node.declarations.forEach((decl) => {
|
|
1885
2364
|
const name = api_variableDeclarationName(decl.id);
|
|
1886
2365
|
if (!api_hasProperty(decls, name)) {
|
|
@@ -1984,8 +2463,14 @@ function api_collectNamespaces(ast, stateIn) {
|
|
|
1984
2463
|
state.inType = true;
|
|
1985
2464
|
break;
|
|
1986
2465
|
}
|
|
1987
|
-
|
|
1988
|
-
|
|
2466
|
+
const [parent] = state.stack.slice(-1);
|
|
2467
|
+
if (parent.node === node ||
|
|
2468
|
+
(node.type === "CatchClause" && parent.node === node.body)) {
|
|
2469
|
+
delete parent.usings;
|
|
2470
|
+
delete parent.imports;
|
|
2471
|
+
if (node.type != "Program") {
|
|
2472
|
+
state.stack.pop();
|
|
2473
|
+
}
|
|
1989
2474
|
}
|
|
1990
2475
|
}
|
|
1991
2476
|
if (ret === false) {
|
|
@@ -2006,68 +2491,7 @@ function api_collectNamespaces(ast, stateIn) {
|
|
|
2006
2491
|
}
|
|
2007
2492
|
return state.stack[0];
|
|
2008
2493
|
}
|
|
2009
|
-
function
|
|
2010
|
-
return node ? typeof node === "object" && "type" in node : false;
|
|
2011
|
-
}
|
|
2012
|
-
/*
|
|
2013
|
-
* Traverse the ast rooted at node, calling pre before
|
|
2014
|
-
* visiting each node, and post after.
|
|
2015
|
-
*
|
|
2016
|
-
* - if pre returns false, the node is not traversed, and
|
|
2017
|
-
* post is not called;
|
|
2018
|
-
* - if pre returns a list of child nodes, only those will
|
|
2019
|
-
* be traversed
|
|
2020
|
-
* - otherwise all child nodes are traversed
|
|
2021
|
-
*
|
|
2022
|
-
* - if post returns false, the node it was called on is
|
|
2023
|
-
* removed.
|
|
2024
|
-
*/
|
|
2025
|
-
function api_traverseAst(node, pre, post) {
|
|
2026
|
-
const nodes = pre && pre(node);
|
|
2027
|
-
if (nodes === false)
|
|
2028
|
-
return;
|
|
2029
|
-
for (const key of nodes || Object.keys(node)) {
|
|
2030
|
-
const value = node[key];
|
|
2031
|
-
if (!value)
|
|
2032
|
-
continue;
|
|
2033
|
-
if (Array.isArray(value)) {
|
|
2034
|
-
const values = value;
|
|
2035
|
-
const deletions = values.reduce((state, obj, i) => {
|
|
2036
|
-
if (isMCTreeNode(obj)) {
|
|
2037
|
-
const repl = api_traverseAst(obj, pre, post);
|
|
2038
|
-
if (repl === false) {
|
|
2039
|
-
if (!state)
|
|
2040
|
-
state = {};
|
|
2041
|
-
state[i] = true;
|
|
2042
|
-
}
|
|
2043
|
-
else if (repl != null) {
|
|
2044
|
-
if (!state)
|
|
2045
|
-
state = {};
|
|
2046
|
-
values[i] = repl;
|
|
2047
|
-
}
|
|
2048
|
-
}
|
|
2049
|
-
return state;
|
|
2050
|
-
}, null);
|
|
2051
|
-
if (deletions) {
|
|
2052
|
-
values.splice(0, values.length, ...values.filter((obj, i) => deletions[i] !== true).flat(1));
|
|
2053
|
-
}
|
|
2054
|
-
}
|
|
2055
|
-
else if (isMCTreeNode(value)) {
|
|
2056
|
-
const repl = api_traverseAst(value, pre, post);
|
|
2057
|
-
if (repl === false) {
|
|
2058
|
-
delete node[key];
|
|
2059
|
-
}
|
|
2060
|
-
else if (repl != null) {
|
|
2061
|
-
if (Array.isArray(repl)) {
|
|
2062
|
-
throw new Error("Array returned by traverseAst in Node context");
|
|
2063
|
-
}
|
|
2064
|
-
node[key] = repl;
|
|
2065
|
-
}
|
|
2066
|
-
}
|
|
2067
|
-
}
|
|
2068
|
-
return post && post(node);
|
|
2069
|
-
}
|
|
2070
|
-
function formatAst(node, monkeyCSource = null) {
|
|
2494
|
+
function api_formatAst(node, monkeyCSource = null) {
|
|
2071
2495
|
/*
|
|
2072
2496
|
* The estree printer sometimes looks at the parent node without
|
|
2073
2497
|
* checking that there *is* a parent node (eg it assumes all
|
|
@@ -2108,7 +2532,7 @@ function handleException(state, node, exception) {
|
|
|
2108
2532
|
.filter((e) => e != null)
|
|
2109
2533
|
.join(".");
|
|
2110
2534
|
const location = node.loc && node.loc.source
|
|
2111
|
-
? `${node.loc.source}:${node.start || 0}:${node.end || 0}`
|
|
2535
|
+
? `${node.loc.source}:${node.loc.start.line || 0}:${node.loc.end.line || 0}`
|
|
2112
2536
|
: "<unknown>";
|
|
2113
2537
|
const message = `Got exception \`${exception instanceof Error
|
|
2114
2538
|
? exception.message
|
|
@@ -2120,9 +2544,65 @@ function handleException(state, node, exception) {
|
|
|
2120
2544
|
exception = new Error(message);
|
|
2121
2545
|
}
|
|
2122
2546
|
}
|
|
2123
|
-
|
|
2547
|
+
catch (ex) {
|
|
2124
2548
|
throw exception;
|
|
2125
2549
|
}
|
|
2550
|
+
throw exception;
|
|
2551
|
+
}
|
|
2552
|
+
function findUsing(state, stack, using) {
|
|
2553
|
+
if (using.module)
|
|
2554
|
+
return using.module;
|
|
2555
|
+
let module = stack[0];
|
|
2556
|
+
const find = (node) => {
|
|
2557
|
+
let name;
|
|
2558
|
+
if (node.type == "Identifier") {
|
|
2559
|
+
name = node.name;
|
|
2560
|
+
}
|
|
2561
|
+
else {
|
|
2562
|
+
find(node.object);
|
|
2563
|
+
name = node.property.name;
|
|
2564
|
+
}
|
|
2565
|
+
if (api_hasProperty(module.decls, name)) {
|
|
2566
|
+
const decls = module.decls[name];
|
|
2567
|
+
if (decls &&
|
|
2568
|
+
decls.length === 1 &&
|
|
2569
|
+
decls[0].type === "ModuleDeclaration") {
|
|
2570
|
+
module = decls[0];
|
|
2571
|
+
return true;
|
|
2572
|
+
}
|
|
2573
|
+
}
|
|
2574
|
+
return false;
|
|
2575
|
+
};
|
|
2576
|
+
if (find(using.node.id)) {
|
|
2577
|
+
using.module = module;
|
|
2578
|
+
return using.module;
|
|
2579
|
+
}
|
|
2580
|
+
if (state.config?.checkInvalidSymbols !== "OFF") {
|
|
2581
|
+
inliner_diagnostic(state, using.node.id.loc, `Unable to resolve import of ${api_formatAst(using.node.id)}`, state.config?.checkInvalidSymbols || "WARNING");
|
|
2582
|
+
}
|
|
2583
|
+
return null;
|
|
2584
|
+
}
|
|
2585
|
+
function findUsingForNode(state, stack, i, node, isType) {
|
|
2586
|
+
while (i >= 0) {
|
|
2587
|
+
const si = stack[i--];
|
|
2588
|
+
if (api_hasProperty(si.usings, node.name)) {
|
|
2589
|
+
const using = si.usings[node.name];
|
|
2590
|
+
const module = findUsing(state, stack, using);
|
|
2591
|
+
return module && [module];
|
|
2592
|
+
}
|
|
2593
|
+
if (si.imports && isType) {
|
|
2594
|
+
for (let j = si.imports.length; j--;) {
|
|
2595
|
+
const using = si.imports[j];
|
|
2596
|
+
const module = findUsing(state, stack, using);
|
|
2597
|
+
if (module) {
|
|
2598
|
+
if (api_hasProperty(module.type_decls, node.name)) {
|
|
2599
|
+
return module.type_decls[node.name];
|
|
2600
|
+
}
|
|
2601
|
+
}
|
|
2602
|
+
}
|
|
2603
|
+
}
|
|
2604
|
+
}
|
|
2605
|
+
return null;
|
|
2126
2606
|
}
|
|
2127
2607
|
|
|
2128
2608
|
var __webpack_export_target__ = exports;
|