jslike 1.4.0 → 1.4.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.
@@ -0,0 +1,531 @@
1
+ /**
2
+ * Wang Metadata API
3
+ * Comprehensive metadata collection during compilation, interpretation, and execution
4
+ */
5
+
6
+ export class WangMetadata {
7
+ constructor() {
8
+ // Compilation phase metadata
9
+ this.compilation = {
10
+ source: '',
11
+ sourceLength: 0,
12
+ tokenCount: 0,
13
+ tokens: [],
14
+ tokenTypes: new Map(),
15
+ nodeCount: 0,
16
+ maxDepth: 0,
17
+ nodeTypes: new Map(),
18
+ parseStartTime: null,
19
+ parseEndTime: null,
20
+ parseErrors: [],
21
+ sourceMap: new Map(),
22
+ };
23
+
24
+ // Interpretation phase metadata
25
+ this.interpretation = {
26
+ moduleResolutions: [],
27
+ moduleDependencies: new Map(),
28
+ symbols: {
29
+ variables: new Map(),
30
+ functions: new Map(),
31
+ classes: new Map(),
32
+ imports: new Map(),
33
+ exports: new Map(),
34
+ },
35
+ scopes: [],
36
+ };
37
+
38
+ // Execution phase metadata
39
+ this.execution = {
40
+ state: 'idle', // idle, running, completed, failed
41
+ startTime: null,
42
+ endTime: null,
43
+ callCount: 0,
44
+ callHistory: [],
45
+ callStack: [],
46
+ maxCallDepth: 0,
47
+ variableReads: new Map(),
48
+ variableWrites: new Map(),
49
+ variableTypes: new Map(),
50
+ branchesExecuted: [],
51
+ loopIterations: new Map(),
52
+ errors: [],
53
+ };
54
+
55
+ // Runtime metadata (current state)
56
+ this.runtime = {
57
+ currentLine: null,
58
+ currentColumn: null,
59
+ currentNode: null,
60
+ currentFunction: null,
61
+ executionPath: [],
62
+ liveVariables: new Map(),
63
+ nodeVisitOrder: [],
64
+ events: [],
65
+ };
66
+
67
+ this._callIdCounter = 0;
68
+ this._scopeIdCounter = 0;
69
+ }
70
+
71
+ // Compilation methods
72
+ recordNode(node, depth) {
73
+ this.compilation.nodeCount++;
74
+ this.compilation.maxDepth = Math.max(this.compilation.maxDepth, depth);
75
+
76
+ const count = this.compilation.nodeTypes.get(node.type) || 0;
77
+ this.compilation.nodeTypes.set(node.type, count + 1);
78
+
79
+ if (node.location) {
80
+ this.compilation.sourceMap.set(node, {
81
+ startLine: node.location.startLine,
82
+ startColumn: node.location.startColumn,
83
+ endLine: node.location.endLine,
84
+ endColumn: node.location.endColumn,
85
+ });
86
+ }
87
+ }
88
+
89
+ // Interpretation methods
90
+ recordSymbol(category, name, info) {
91
+ this.interpretation.symbols[category].set(name, info);
92
+ }
93
+
94
+ recordScope(scope) {
95
+ if (!scope.id && scope.type === 'global') {
96
+ scope.id = `scope_${this._scopeIdCounter++}`;
97
+ } else if (!scope.id) {
98
+ scope.id = `scope_${this._scopeIdCounter++}`;
99
+ }
100
+
101
+ if (scope.parent && scope.parent.id) {
102
+ this.interpretation.scopes.push({
103
+ ...scope,
104
+ parent: scope.parent.id,
105
+ });
106
+ } else {
107
+ this.interpretation.scopes.push({
108
+ ...scope,
109
+ parent: null,
110
+ });
111
+ }
112
+ }
113
+
114
+ // Execution methods
115
+ recordCall(name, args, node) {
116
+ const callId = `call_${this._callIdCounter++}`;
117
+
118
+ this.execution.callCount++;
119
+ this.execution.callStack.push(name); // Store function name, not callId
120
+ this.execution.maxCallDepth = Math.max(
121
+ this.execution.maxCallDepth,
122
+ this.execution.callStack.length
123
+ );
124
+
125
+ const call = {
126
+ id: callId,
127
+ name,
128
+ args: this._serializeArgs(args),
129
+ line: node?.location?.startLine || null,
130
+ column: node?.location?.startColumn || null,
131
+ timestamp: Date.now(),
132
+ returnValue: null,
133
+ };
134
+
135
+ this.execution.callHistory.push(call);
136
+ return callId;
137
+ }
138
+
139
+ recordReturn(callId, value) {
140
+ // Find the call to get its name
141
+ const call = this.execution.callHistory.find(c => c.id === callId);
142
+ if (call) {
143
+ call.returnValue = this._serializeValue(value);
144
+ // Remove from call stack by name
145
+ const index = this.execution.callStack.indexOf(call.name);
146
+ if (index !== -1) {
147
+ this.execution.callStack.splice(index, 1);
148
+ }
149
+ }
150
+ }
151
+
152
+ recordEvent(type, data) {
153
+ this.runtime.events.push({
154
+ type,
155
+ data,
156
+ timestamp: Date.now(),
157
+ currentLine: this.runtime.currentLine,
158
+ currentColumn: this.runtime.currentColumn,
159
+ callStack: [...this.execution.callStack],
160
+ });
161
+ }
162
+
163
+ // Query methods
164
+ getDependencyGraph() {
165
+ const nodes = new Set();
166
+ const edges = [];
167
+
168
+ for (const [from, deps] of this.interpretation.moduleDependencies.entries()) {
169
+ for (const to of deps) {
170
+ nodes.add(to);
171
+ edges.push({ from, to });
172
+ }
173
+ }
174
+
175
+ return {
176
+ nodes: Array.from(nodes),
177
+ edges,
178
+ };
179
+ }
180
+
181
+ getHotFunctions(limit = 10) {
182
+ const callCounts = new Map();
183
+
184
+ for (const call of this.execution.callHistory) {
185
+ const count = callCounts.get(call.name) || 0;
186
+ callCounts.set(call.name, count + 1);
187
+ }
188
+
189
+ return Array.from(callCounts.entries())
190
+ .map(([name, count]) => ({ name, count }))
191
+ .sort((a, b) => b.count - a.count)
192
+ .slice(0, limit);
193
+ }
194
+
195
+ getHotVariables(limit = 10) {
196
+ const varCounts = new Map();
197
+
198
+ for (const [name, reads] of this.execution.variableReads.entries()) {
199
+ const writes = this.execution.variableWrites.get(name) || 0;
200
+ varCounts.set(name, {
201
+ name,
202
+ reads,
203
+ writes,
204
+ count: reads + writes,
205
+ });
206
+ }
207
+
208
+ return Array.from(varCounts.values())
209
+ .sort((a, b) => b.count - a.count)
210
+ .slice(0, limit);
211
+ }
212
+
213
+ getCompilationSummary() {
214
+ return {
215
+ sourceSize: this.compilation.sourceLength,
216
+ tokenCount: this.compilation.tokenCount,
217
+ uniqueTokenTypes: this.compilation.tokenTypes.size,
218
+ nodeCount: this.compilation.nodeCount,
219
+ maxDepth: this.compilation.maxDepth,
220
+ errors: this.compilation.parseErrors.length,
221
+ parseTime: this.compilation.parseEndTime - this.compilation.parseStartTime,
222
+ };
223
+ }
224
+
225
+ getInterpretationSummary() {
226
+ const successful = this.interpretation.moduleResolutions.filter(r => r.success).length;
227
+ const failed = this.interpretation.moduleResolutions.filter(r => !r.success).length;
228
+
229
+ return {
230
+ modulesLoaded: successful,
231
+ modulesFailed: failed,
232
+ definedVariables: this.interpretation.symbols.variables.size,
233
+ definedFunctions: this.interpretation.symbols.functions.size,
234
+ definedClasses: this.interpretation.symbols.classes.size,
235
+ imports: this.interpretation.symbols.imports.size,
236
+ exports: this.interpretation.symbols.exports.size,
237
+ };
238
+ }
239
+
240
+ getExecutionSummary() {
241
+ const varReads = Array.from(this.execution.variableReads.values()).reduce((a, b) => a + b, 0);
242
+ const varWrites = Array.from(this.execution.variableWrites.values()).reduce((a, b) => a + b, 0);
243
+
244
+ return {
245
+ state: this.execution.state,
246
+ executionTime: this.execution.endTime - this.execution.startTime,
247
+ totalCalls: this.execution.callCount,
248
+ maxCallDepth: this.execution.maxCallDepth,
249
+ variableReads: varReads,
250
+ variableWrites: varWrites,
251
+ branchesExecuted: this.execution.branchesExecuted.length,
252
+ pipelineOperations: 0, // Pipelines not supported in Wang
253
+ errors: this.execution.errors.length,
254
+ };
255
+ }
256
+
257
+ getCurrentState() {
258
+ return {
259
+ line: this.runtime.currentLine,
260
+ column: this.runtime.currentColumn,
261
+ function: this.runtime.currentFunction,
262
+ liveVariableCount: this.runtime.liveVariables.size,
263
+ callStackDepth: this.execution.callStack.length,
264
+ };
265
+ }
266
+
267
+ getExecutionPath(last = null) {
268
+ if (last === null) {
269
+ return this.runtime.executionPath;
270
+ }
271
+ return this.runtime.executionPath.slice(-last);
272
+ }
273
+
274
+ // Serialization
275
+ toJSON() {
276
+ return {
277
+ compilation: {
278
+ ...this.compilation,
279
+ tokenTypes: Array.from(this.compilation.tokenTypes.entries()),
280
+ nodeTypes: Array.from(this.compilation.nodeTypes.entries()),
281
+ sourceMap: null, // Skip source map in JSON
282
+ },
283
+ interpretation: {
284
+ ...this.interpretation,
285
+ moduleDependencies: Array.from(this.interpretation.moduleDependencies.entries()),
286
+ symbols: {
287
+ variables: Array.from(this.interpretation.symbols.variables.entries()),
288
+ functions: Array.from(this.interpretation.symbols.functions.entries()),
289
+ classes: Array.from(this.interpretation.symbols.classes.entries()),
290
+ imports: Array.from(this.interpretation.symbols.imports.entries()),
291
+ exports: Array.from(this.interpretation.symbols.exports.entries()),
292
+ },
293
+ },
294
+ execution: {
295
+ ...this.execution,
296
+ variableReads: Array.from(this.execution.variableReads.entries()),
297
+ variableWrites: Array.from(this.execution.variableWrites.entries()),
298
+ variableTypes: Array.from(this.execution.variableTypes.entries()).map(([k, v]) => [
299
+ k,
300
+ Array.from(v),
301
+ ]),
302
+ loopIterations: Array.from(this.execution.loopIterations.entries()),
303
+ },
304
+ runtime: {
305
+ ...this.runtime,
306
+ liveVariables: Array.from(this.runtime.liveVariables.entries()),
307
+ },
308
+ summary: {
309
+ compilation: this.getCompilationSummary(),
310
+ interpretation: this.getInterpretationSummary(),
311
+ execution: this.getExecutionSummary(),
312
+ current: this.getCurrentState(),
313
+ },
314
+ };
315
+ }
316
+
317
+ _serializeValue(value, depth = 0, maxDepth = 3) {
318
+ if (depth > maxDepth) {
319
+ return '...';
320
+ }
321
+
322
+ if (value === null) return 'null';
323
+ if (value === undefined) return 'undefined';
324
+
325
+ const type = typeof value;
326
+
327
+ if (type === 'string') {
328
+ return value.length > 50 ? value.substring(0, 50) + '...' : value;
329
+ }
330
+
331
+ if (type === 'number' || type === 'boolean') {
332
+ return String(value);
333
+ }
334
+
335
+ if (type === 'function') {
336
+ return `[Function: ${value.name || 'anonymous'}]`;
337
+ }
338
+
339
+ if (Array.isArray(value)) {
340
+ const items = value.slice(0, 10).map(v => this._serializeValue(v, depth + 1, maxDepth));
341
+ return `[${items.join(', ')}${value.length > 10 ? ', ...' : ''}]`;
342
+ }
343
+
344
+ if (type === 'object') {
345
+ const entries = Object.entries(value).slice(0, 10);
346
+ const items = entries.map(([k, v]) => `${k}: ${this._serializeValue(v, depth + 1, maxDepth)}`);
347
+ return `{ ${items.join(', ')}${Object.keys(value).length > 10 ? ', ...' : ''} }`;
348
+ }
349
+
350
+ return String(value);
351
+ }
352
+
353
+ _serializeArgs(args) {
354
+ return args.map(arg => ({
355
+ type: typeof arg,
356
+ value: this._serializeValue(arg),
357
+ }));
358
+ }
359
+ }
360
+
361
+ export class MetadataCollector {
362
+ constructor(metadata = null) {
363
+ this.metadata = metadata || new WangMetadata();
364
+ this.enabled = true;
365
+ }
366
+
367
+ // Compilation events
368
+ onTokenize(token) {
369
+ if (!this.enabled) return;
370
+
371
+ this.metadata.compilation.tokenCount++;
372
+ this.metadata.compilation.tokens.push(token);
373
+
374
+ const count = this.metadata.compilation.tokenTypes.get(token.type) || 0;
375
+ this.metadata.compilation.tokenTypes.set(token.type, count + 1);
376
+ }
377
+
378
+ onParseStart(source) {
379
+ if (!this.enabled) return;
380
+
381
+ this.metadata.compilation.source = source;
382
+ this.metadata.compilation.sourceLength = source.length;
383
+ this.metadata.compilation.parseStartTime = Date.now();
384
+ }
385
+
386
+ onParseEnd(ast) {
387
+ if (!this.enabled) return;
388
+
389
+ this.metadata.compilation.parseEndTime = Date.now();
390
+ }
391
+
392
+ onParseError(error) {
393
+ if (!this.enabled) return;
394
+
395
+ this.metadata.compilation.parseErrors.push(error);
396
+ }
397
+
398
+ onNodeVisit(node, depth) {
399
+ if (!this.enabled) return;
400
+
401
+ this.metadata.recordNode(node, depth);
402
+
403
+ // Update runtime state
404
+ if (node.location) {
405
+ this.metadata.runtime.currentLine = node.location.startLine;
406
+ this.metadata.runtime.currentColumn = node.location.startColumn;
407
+ this.metadata.runtime.currentNode = node;
408
+ this.metadata.runtime.executionPath.push(node.location.startLine);
409
+ } else {
410
+ this.metadata.runtime.currentLine = null;
411
+ this.metadata.runtime.currentColumn = null;
412
+ this.metadata.runtime.currentNode = node;
413
+ }
414
+
415
+ this.metadata.runtime.nodeVisitOrder.push(node.type);
416
+ }
417
+
418
+ // Interpretation events
419
+ onModuleResolve(from, specifier, resolved) {
420
+ if (!this.enabled) return;
421
+
422
+ this.metadata.interpretation.moduleResolutions.push({
423
+ from,
424
+ specifier,
425
+ resolved,
426
+ success: resolved !== null,
427
+ });
428
+
429
+ if (resolved) {
430
+ if (!this.metadata.interpretation.moduleDependencies.has(from)) {
431
+ this.metadata.interpretation.moduleDependencies.set(from, new Set());
432
+ }
433
+ this.metadata.interpretation.moduleDependencies.get(from).add(resolved);
434
+ }
435
+ }
436
+
437
+ // Execution events
438
+ onExecutionStart() {
439
+ if (!this.enabled) return;
440
+
441
+ this.metadata.execution.state = 'running';
442
+ this.metadata.execution.startTime = Date.now();
443
+ }
444
+
445
+ onExecutionEnd() {
446
+ if (!this.enabled) return;
447
+
448
+ this.metadata.execution.state = 'completed';
449
+ this.metadata.execution.endTime = Date.now();
450
+ }
451
+
452
+ onFunctionCall(name, args, node) {
453
+ if (!this.enabled) return '';
454
+
455
+ return this.metadata.recordCall(name, args, node);
456
+ }
457
+
458
+ onFunctionReturn(callId, value) {
459
+ if (!this.enabled) return;
460
+
461
+ this.metadata.recordReturn(callId, value);
462
+ }
463
+
464
+ onVariableAccess(name, type, value = undefined) {
465
+ if (!this.enabled) return;
466
+
467
+ if (type === 'read') {
468
+ const count = this.metadata.execution.variableReads.get(name) || 0;
469
+ this.metadata.execution.variableReads.set(name, count + 1);
470
+ } else if (type === 'write') {
471
+ const count = this.metadata.execution.variableWrites.get(name) || 0;
472
+ this.metadata.execution.variableWrites.set(name, count + 1);
473
+
474
+ // Track variable types
475
+ const valueType = typeof value;
476
+ if (!this.metadata.execution.variableTypes.has(name)) {
477
+ this.metadata.execution.variableTypes.set(name, new Set());
478
+ }
479
+ this.metadata.execution.variableTypes.get(name).add(valueType);
480
+
481
+ // Update live variables
482
+ this.metadata.runtime.liveVariables.set(name, value);
483
+ }
484
+ }
485
+
486
+ onBranch(type, condition, taken, node) {
487
+ if (!this.enabled) return;
488
+
489
+ this.metadata.execution.branchesExecuted.push({
490
+ type,
491
+ condition,
492
+ taken,
493
+ result: taken,
494
+ line: node?.location?.startLine || null,
495
+ column: node?.location?.startColumn || null,
496
+ });
497
+ }
498
+
499
+ onError(error, node) {
500
+ if (!this.enabled) return;
501
+
502
+ this.metadata.execution.errors.push({
503
+ type: error.constructor.name,
504
+ message: error.message,
505
+ line: node?.location?.startLine || null,
506
+ column: node?.location?.startColumn || null,
507
+ timestamp: Date.now(),
508
+ });
509
+ }
510
+
511
+ // Utility methods
512
+ getSummary() {
513
+ return {
514
+ compilation: this.metadata.getCompilationSummary(),
515
+ interpretation: this.metadata.getInterpretationSummary(),
516
+ execution: this.metadata.getExecutionSummary(),
517
+ current: this.metadata.getCurrentState(),
518
+ };
519
+ }
520
+
521
+ export() {
522
+ return this.metadata.toJSON();
523
+ }
524
+
525
+ getMetadata() {
526
+ return this.metadata;
527
+ }
528
+ }
529
+
530
+ // Export for integration with interpreter
531
+ export { WangMetadata as default };