stone-lang 0.1.0

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 (68) hide show
  1. package/README.md +52 -0
  2. package/StoneEngine.js +879 -0
  3. package/StoneEngineService.js +1727 -0
  4. package/adapters/FileSystemAdapter.js +230 -0
  5. package/adapters/OutputAdapter.js +208 -0
  6. package/adapters/index.js +6 -0
  7. package/cli/CLIOutputAdapter.js +196 -0
  8. package/cli/DaemonClient.js +349 -0
  9. package/cli/JSONOutputAdapter.js +135 -0
  10. package/cli/ReplSession.js +567 -0
  11. package/cli/ViewerServer.js +590 -0
  12. package/cli/commands/check.js +84 -0
  13. package/cli/commands/daemon.js +189 -0
  14. package/cli/commands/kill.js +66 -0
  15. package/cli/commands/package.js +713 -0
  16. package/cli/commands/ps.js +65 -0
  17. package/cli/commands/run.js +537 -0
  18. package/cli/entry.js +169 -0
  19. package/cli/index.js +14 -0
  20. package/cli/stonec.js +358 -0
  21. package/cli/test-compiler.js +181 -0
  22. package/cli/viewer/index.html +495 -0
  23. package/daemon/IPCServer.js +455 -0
  24. package/daemon/ProcessManager.js +327 -0
  25. package/daemon/ProcessRunner.js +307 -0
  26. package/daemon/daemon.js +398 -0
  27. package/daemon/index.js +16 -0
  28. package/frontend/analysis/index.js +5 -0
  29. package/frontend/analysis/livenessAnalyzer.js +568 -0
  30. package/frontend/analysis/treeShaker.js +265 -0
  31. package/frontend/index.js +20 -0
  32. package/frontend/parsing/astBuilder.js +2196 -0
  33. package/frontend/parsing/index.js +7 -0
  34. package/frontend/parsing/sonParser.js +592 -0
  35. package/frontend/parsing/stoneAstTypes.js +703 -0
  36. package/frontend/parsing/terminal-registry.js +435 -0
  37. package/frontend/parsing/tokenizer.js +692 -0
  38. package/frontend/type-checker/OverloadedFunctionType.js +43 -0
  39. package/frontend/type-checker/TypeEnvironment.js +165 -0
  40. package/frontend/type-checker/bidirectionalInference.js +149 -0
  41. package/frontend/type-checker/index.js +10 -0
  42. package/frontend/type-checker/moduleAnalysis.js +248 -0
  43. package/frontend/type-checker/operatorMappings.js +35 -0
  44. package/frontend/type-checker/overloadResolution.js +605 -0
  45. package/frontend/type-checker/typeChecker.js +452 -0
  46. package/frontend/type-checker/typeCompatibility.js +389 -0
  47. package/frontend/type-checker/visitors/controlFlow.js +483 -0
  48. package/frontend/type-checker/visitors/functions.js +604 -0
  49. package/frontend/type-checker/visitors/index.js +38 -0
  50. package/frontend/type-checker/visitors/literals.js +341 -0
  51. package/frontend/type-checker/visitors/modules.js +159 -0
  52. package/frontend/type-checker/visitors/operators.js +109 -0
  53. package/frontend/type-checker/visitors/statements.js +768 -0
  54. package/frontend/types/index.js +5 -0
  55. package/frontend/types/operatorMap.js +134 -0
  56. package/frontend/types/types.js +2046 -0
  57. package/frontend/utils/errorCollector.js +244 -0
  58. package/frontend/utils/index.js +5 -0
  59. package/frontend/utils/moduleResolver.js +479 -0
  60. package/package.json +50 -0
  61. package/packages/browserCache.js +359 -0
  62. package/packages/fetcher.js +236 -0
  63. package/packages/index.js +130 -0
  64. package/packages/lockfile.js +271 -0
  65. package/packages/manifest.js +291 -0
  66. package/packages/packageResolver.js +356 -0
  67. package/packages/resolver.js +310 -0
  68. package/packages/semver.js +635 -0
@@ -0,0 +1,389 @@
1
+ /**
2
+ * Type Compatibility Methods - mixin for TypeChecker
3
+ *
4
+ * Methods for type comparison, promotion, unification, and conversion
5
+ * between class-based and structured type representations.
6
+ */
7
+
8
+ import {
9
+ PrimitiveType,
10
+ FunctionType,
11
+ RecordType,
12
+ ArrayType,
13
+ TypeVariable,
14
+ PromotedType,
15
+ NUM,
16
+ BOOL,
17
+ STRING,
18
+ UNIT,
19
+ freshTypeVar,
20
+ typeEquals,
21
+ } from "../types/types.js";
22
+
23
+ /**
24
+ * Type compatibility methods to be mixed into TypeChecker.prototype
25
+ */
26
+ export const typeCompatibilityMethods = {
27
+ /**
28
+ * Check if a class-based type contains unresolved type variables
29
+ */
30
+ containsUnresolvedTypeVar(type) {
31
+ if (!type) return false;
32
+ if (type instanceof TypeVariable) {
33
+ const resolved = type.resolve();
34
+ if (resolved instanceof TypeVariable) return true;
35
+ return this.containsUnresolvedTypeVar(resolved);
36
+ }
37
+ if (type instanceof ArrayType) {
38
+ return this.containsUnresolvedTypeVar(type.elementType);
39
+ }
40
+ if (type instanceof FunctionType) {
41
+ if (type.paramTypes.some(p => this.containsUnresolvedTypeVar(p))) return true;
42
+ return this.containsUnresolvedTypeVar(type.returnType);
43
+ }
44
+ if (type instanceof RecordType) {
45
+ for (const fieldType of type.fields.values()) {
46
+ if (this.containsUnresolvedTypeVar(fieldType)) return true;
47
+ }
48
+ }
49
+ return false;
50
+ },
51
+
52
+ /**
53
+ * Check if a type is "incomplete" - contains unresolved TypeVariables
54
+ * Incomplete types need to be inferred from context (e.g., empty arrays)
55
+ */
56
+ isIncompleteType(type) {
57
+ if (type instanceof TypeVariable) {
58
+ const resolved = type.resolve();
59
+ return resolved instanceof TypeVariable;
60
+ }
61
+ if (type instanceof ArrayType) {
62
+ return this.isIncompleteType(type.elementType);
63
+ }
64
+ if (type instanceof RecordType) {
65
+ for (const fieldType of type.fields.values()) {
66
+ if (this.isIncompleteType(fieldType)) return true;
67
+ }
68
+ }
69
+ return false;
70
+ },
71
+
72
+ /**
73
+ * Convert a class-based type to a structured type object for matching
74
+ * @param {Object} type - Class-based type (PrimitiveType, ArrayType, etc.)
75
+ * @returns {Object} Structured type object
76
+ */
77
+ toStructuredType(type) {
78
+ if (!type) return { kind: "unknown" };
79
+
80
+ // Already a plain structured object (not a class instance)
81
+ // Check for constructor being Object to distinguish from class instances
82
+ if (type.kind && type.constructor === Object) {
83
+ return type;
84
+ }
85
+
86
+ if (type instanceof PrimitiveType) {
87
+ return { kind: "primitive", name: type.name };
88
+ }
89
+
90
+ if (type instanceof ArrayType) {
91
+ return {
92
+ kind: "array",
93
+ elem: this.toStructuredType(type.elementType), // Use 'elem' to match parseTypeString format
94
+ rank: type.rank,
95
+ };
96
+ }
97
+
98
+ if (type instanceof RecordType) {
99
+ const fields = new Map();
100
+ for (const [name, fieldType] of type.fields) {
101
+ fields.set(name, this.toStructuredType(fieldType));
102
+ }
103
+ return { kind: "record", fields, open: type.open };
104
+ }
105
+
106
+ if (type instanceof FunctionType) {
107
+ return {
108
+ kind: "function",
109
+ params: type.paramTypes.map(t => this.toStructuredType(t)),
110
+ ret: this.toStructuredType(type.returnType),
111
+ };
112
+ }
113
+
114
+ if (type instanceof TypeVariable) {
115
+ const resolved = type.resolve();
116
+ if (resolved !== type) {
117
+ return this.toStructuredType(resolved);
118
+ }
119
+ // Track the TypeVariable object for later unification
120
+ this.typeVarMap.set(type.id, type);
121
+ return { kind: "typevar", id: type.id, resolved: null };
122
+ }
123
+
124
+ return { kind: "unknown" };
125
+ },
126
+
127
+ /**
128
+ * Check if a structured type contains unresolved type variables
129
+ */
130
+ hasUnresolvedTypeVars(type) {
131
+ if (!type) return false;
132
+ if (type.kind === "typevar" && !type.resolved) return true;
133
+ if (type.kind === "unknown") return true;
134
+ if (type.kind === "array") return this.hasUnresolvedTypeVars(type.elem);
135
+ if (type.kind === "list") return this.hasUnresolvedTypeVars(type.elem);
136
+ if (type.kind === "function") {
137
+ if (type.params?.some(p => this.hasUnresolvedTypeVars(p))) return true;
138
+ return this.hasUnresolvedTypeVars(type.ret);
139
+ }
140
+ return false;
141
+ },
142
+
143
+ /**
144
+ * Check if two function types can unify, treating type variables as wildcards.
145
+ * This is used for matching function arguments with type variables against
146
+ * expected function parameter types.
147
+ * E.g., (T1, T2) -> array<num,1> can unify with (num, array<num,1>) -> array<num,1>
148
+ */
149
+ canUnifyFunctionTypes(expected, actual) {
150
+ if (!(expected instanceof FunctionType) || !(actual instanceof FunctionType)) {
151
+ return false;
152
+ }
153
+
154
+ // Must have same arity
155
+ if (expected.paramTypes.length !== actual.paramTypes.length) {
156
+ return false;
157
+ }
158
+
159
+ // Check each parameter type
160
+ for (let i = 0; i < expected.paramTypes.length; i++) {
161
+ const expParam = expected.paramTypes[i];
162
+ const actParam = actual.paramTypes[i];
163
+
164
+ // Type variable can match anything
165
+ if (expParam instanceof TypeVariable || actParam instanceof TypeVariable) {
166
+ continue;
167
+ }
168
+
169
+ // Both must be the same type or unifiable
170
+ if (!this.typesEqual(expParam, actParam) && !this.canUnifyTypes(expParam, actParam)) {
171
+ return false;
172
+ }
173
+ }
174
+
175
+ // Check return type (type variable in return is also allowed)
176
+ const expRet = expected.returnType;
177
+ const actRet = actual.returnType;
178
+
179
+ if (expRet instanceof TypeVariable || actRet instanceof TypeVariable) {
180
+ return true;
181
+ }
182
+
183
+ return this.typesEqual(expRet, actRet) || this.canUnifyTypes(expRet, actRet);
184
+ },
185
+
186
+ /**
187
+ * Check if two types can unify (type variables match anything)
188
+ */
189
+ canUnifyTypes(a, b) {
190
+ if (a instanceof TypeVariable || b instanceof TypeVariable) {
191
+ return true;
192
+ }
193
+ if (a instanceof ArrayType && b instanceof ArrayType) {
194
+ return this.canUnifyTypes(a.elementType, b.elementType);
195
+ }
196
+ if (a instanceof FunctionType && b instanceof FunctionType) {
197
+ return this.canUnifyFunctionTypes(a, b);
198
+ }
199
+ return this.typesEqual(a, b);
200
+ },
201
+
202
+ /**
203
+ * Check if two types are equal
204
+ * For PromotedType, compares against the target type or source type
205
+ */
206
+ typesEqual(a, b) {
207
+ if (a === b) return true;
208
+ if (!a || !b) return false;
209
+
210
+ // Handle PromotedType: compare against target type or source type
211
+ if (a instanceof PromotedType) {
212
+ // If b matches target type, it's equal (no promotion needed)
213
+ if (this.typesEqual(a.targetType, b)) return true;
214
+ // If b matches source type, it's also considered equal for overload matching
215
+ // (the actual promotion will be handled by canPromote)
216
+ if (a.sourceType && this.typesEqual(a.sourceType, b)) return true;
217
+ return false;
218
+ }
219
+ if (b instanceof PromotedType) {
220
+ // Symmetric case
221
+ if (this.typesEqual(a, b.targetType)) return true;
222
+ if (b.sourceType && this.typesEqual(a, b.sourceType)) return true;
223
+ return false;
224
+ }
225
+
226
+ if (a.constructor !== b.constructor) return false;
227
+
228
+ if (a instanceof ArrayType) {
229
+ return this.typesEqual(a.elementType, b.elementType) && a.rank === b.rank;
230
+ }
231
+
232
+ if (a instanceof FunctionType) {
233
+ if (a.paramTypes.length !== b.paramTypes.length) return false;
234
+ for (let i = 0; i < a.paramTypes.length; i++) {
235
+ if (!this.typesEqual(a.paramTypes[i], b.paramTypes[i])) return false;
236
+ }
237
+ return this.typesEqual(a.returnType, b.returnType);
238
+ }
239
+
240
+ if (a instanceof RecordType) {
241
+ if (a.fields.size !== b.fields.size) return false;
242
+ for (const [name, type] of a.fields) {
243
+ if (!b.fields.has(name) || !this.typesEqual(type, b.fields.get(name))) {
244
+ return false;
245
+ }
246
+ }
247
+ return true;
248
+ }
249
+
250
+ // Primitive types - compare by reference (NUM, BOOL, etc.)
251
+ return a === b;
252
+ },
253
+
254
+ /**
255
+ * Check if a type is the complex record type {re: num, im: num}
256
+ */
257
+ isComplexRecordType(type) {
258
+ if (!(type instanceof RecordType)) return false;
259
+ if (type.fields.size !== 2) return false;
260
+ const reType = type.fields.get("re");
261
+ const imType = type.fields.get("im");
262
+ if (!reType || !imType) return false;
263
+ return reType === NUM && imType === NUM;
264
+ },
265
+
266
+ /**
267
+ * Check if argType can be promoted to paramType.
268
+ * Supports both built-in promotions (num → complex) and user-defined
269
+ * promotions via PromotedType.
270
+ *
271
+ * @param {Object} argType - Argument type (class-based)
272
+ * @param {Object} paramType - Parameter type (may be PromotedType)
273
+ * @returns {{can: boolean, converter: string|null}} Promotion result
274
+ */
275
+ canPromote(argType, paramType) {
276
+ // Handle PromotedType: check if argType matches the sourceType
277
+ if (paramType instanceof PromotedType) {
278
+ // If sourceType is set (validated), check if argType matches it
279
+ if (paramType.sourceType && typeEquals(argType, paramType.sourceType)) {
280
+ return { can: true, converter: paramType.converterFunc };
281
+ }
282
+ // Also check if argType matches the target type (no conversion needed)
283
+ if (typeEquals(argType, paramType.targetType)) {
284
+ return { can: false, converter: null }; // No promotion needed - exact match
285
+ }
286
+ return { can: false, converter: null };
287
+ }
288
+
289
+ // Built-in: num -> complex (complex is now {re: num, im: num} record)
290
+ if (argType === NUM && this.isComplexRecordType(paramType)) {
291
+ return { can: true, converter: "to_complex" };
292
+ }
293
+ // Built-in: array<num> -> array<complex> promotion
294
+ if (argType instanceof ArrayType && paramType instanceof ArrayType) {
295
+ if (argType.rank === paramType.rank) {
296
+ const elemResult = this.canPromote(argType.elementType, paramType.elementType);
297
+ return elemResult;
298
+ }
299
+ }
300
+ return { can: false, converter: null };
301
+ },
302
+
303
+ /**
304
+ * Check if types are compatible (looser than equal)
305
+ */
306
+ typesCompatible(paramType, argType) {
307
+ // Arrays with same element type but different ranks might be compatible
308
+ // depending on context - be lenient here
309
+ if (paramType instanceof ArrayType && argType instanceof ArrayType) {
310
+ return this.typesEqual(paramType.elementType, argType.elementType) ||
311
+ this.typesCompatible(paramType.elementType, argType.elementType);
312
+ }
313
+ // Records with subset of fields
314
+ if (paramType instanceof RecordType && argType instanceof RecordType) {
315
+ for (const [name, type] of paramType.fields) {
316
+ if (!argType.fields.has(name)) return false;
317
+ if (!this.typesCompatible(type, argType.fields.get(name))) return false;
318
+ }
319
+ return true;
320
+ }
321
+ return false;
322
+ },
323
+
324
+ /**
325
+ * Check if types are compatible or can unify (for Phase 1.5 filtering)
326
+ */
327
+ typesCompatibleOrUnifiable(actual, expected) {
328
+ if (actual instanceof TypeVariable || expected instanceof TypeVariable) {
329
+ return true;
330
+ }
331
+ if (this.typesEqual(actual, expected)) {
332
+ return true;
333
+ }
334
+ if (this.canPromote(actual, expected).can) {
335
+ return true;
336
+ }
337
+ if (this.typesCompatible(expected, actual)) {
338
+ return true;
339
+ }
340
+ if (actual instanceof ArrayType && expected instanceof ArrayType) {
341
+ return this.typesCompatibleOrUnifiable(actual.elementType, expected.elementType);
342
+ }
343
+ return false;
344
+ },
345
+
346
+ /**
347
+ * Convert structured type back to class-based type
348
+ * @param {Object} type - Structured type object
349
+ * @returns {Object} Class-based type
350
+ */
351
+ fromStructuredType(type) {
352
+ if (!type) return freshTypeVar();
353
+
354
+ if (type.kind === "primitive") {
355
+ switch (type.name) {
356
+ case "num": return NUM;
357
+ case "bool": return BOOL;
358
+ case "string": return STRING;
359
+ case "unit": return UNIT;
360
+ // Note: "complex" is no longer a primitive - it's a record {re: num, im: num}
361
+ // The "record" case below will handle it
362
+ default: return freshTypeVar();
363
+ }
364
+ }
365
+
366
+ if (type.kind === "array") {
367
+ const elemType = this.fromStructuredType(type.elem);
368
+ return new ArrayType(elemType, type.rank);
369
+ }
370
+
371
+ // list<T> is deprecated - treat as array<T,1> for backwards compatibility
372
+ if (type.kind === "list") {
373
+ const elemType = this.fromStructuredType(type.elem);
374
+ return new ArrayType(elemType, 1);
375
+ }
376
+
377
+ if (type.kind === "record") {
378
+ const fields = new Map();
379
+ if (type.fields instanceof Map) {
380
+ for (const [name, fieldType] of type.fields) {
381
+ fields.set(name, this.fromStructuredType(fieldType));
382
+ }
383
+ }
384
+ return new RecordType(fields, type.open || false);
385
+ }
386
+
387
+ return freshTypeVar();
388
+ },
389
+ };