@xnoxs/flux-lang 3.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/CHANGELOG.md +103 -0
  2. package/README.md +1089 -0
  3. package/bin/flux.js +1397 -0
  4. package/dist/flux.cjs.js +6664 -0
  5. package/dist/flux.esm.js +6674 -0
  6. package/dist/flux.min.js +263 -0
  7. package/index.d.ts +202 -0
  8. package/index.js +26 -0
  9. package/package.json +77 -0
  10. package/scripts/build.js +76 -0
  11. package/src/bundler.js +216 -0
  12. package/src/checker.js +322 -0
  13. package/src/codegen.js +785 -0
  14. package/src/css-preprocessor.js +399 -0
  15. package/src/formatter.js +140 -0
  16. package/src/jsx.js +480 -0
  17. package/src/lexer.js +518 -0
  18. package/src/linter.js +758 -0
  19. package/src/mangler.js +280 -0
  20. package/src/parser.js +1671 -0
  21. package/src/self/bundler.flux +167 -0
  22. package/src/self/bundler.js +187 -0
  23. package/src/self/checker.flux +249 -0
  24. package/src/self/checker.js +338 -0
  25. package/src/self/codegen.flux +555 -0
  26. package/src/self/codegen.js +784 -0
  27. package/src/self/css-preprocessor.flux +373 -0
  28. package/src/self/css-preprocessor.js +387 -0
  29. package/src/self/formatter.flux +93 -0
  30. package/src/self/formatter.js +114 -0
  31. package/src/self/jsx.flux +430 -0
  32. package/src/self/jsx.js +396 -0
  33. package/src/self/lexer.flux +529 -0
  34. package/src/self/lexer.js +709 -0
  35. package/src/self/lexer.stage2.js +700 -0
  36. package/src/self/linter.flux +515 -0
  37. package/src/self/linter.js +804 -0
  38. package/src/self/mangler.flux +253 -0
  39. package/src/self/mangler.js +348 -0
  40. package/src/self/parser.flux +1146 -0
  41. package/src/self/parser.js +1571 -0
  42. package/src/self/sourcemap.flux +66 -0
  43. package/src/self/sourcemap.js +72 -0
  44. package/src/self/stdlib.flux +356 -0
  45. package/src/self/stdlib.js +396 -0
  46. package/src/self/test-runner.flux +201 -0
  47. package/src/self/test-runner.js +132 -0
  48. package/src/self/transpiler.flux +123 -0
  49. package/src/self/transpiler.js +83 -0
  50. package/src/self/type-checker.flux +821 -0
  51. package/src/self/type-checker.js +1106 -0
  52. package/src/sourcemap.js +82 -0
  53. package/src/stdlib.js +436 -0
  54. package/src/test-runner.js +239 -0
  55. package/src/transpiler.js +172 -0
  56. package/src/type-checker.js +1206 -0
package/src/checker.js ADDED
@@ -0,0 +1,322 @@
1
+ 'use strict';
2
+
3
+ // ── Flux Static Checker ───────────────────────────────────────────────────────
4
+ // Stage 1: Val immutability analysis (fast, always runs)
5
+ // Stage 2: Full type inference & checking (runs via FluxTypeChecker)
6
+
7
+ class CheckError {
8
+ constructor(message, loc, hint = null) {
9
+ this.message = message;
10
+ this.loc = loc;
11
+ this.hint = hint;
12
+ this.name = 'CheckError';
13
+ if (loc) { this.line = loc.line; this.col = loc.col; }
14
+ }
15
+ }
16
+
17
+ class Scope {
18
+ constructor(parent = null) {
19
+ this.parent = parent;
20
+ this.vars = new Map(); // name → { kind:'val'|'var', loc }
21
+ }
22
+
23
+ define(name, kind, loc) { this.vars.set(name, { kind, loc }); }
24
+
25
+ lookup(name) {
26
+ let scope = this;
27
+ while (scope) {
28
+ if (scope.vars.has(name)) return scope.vars.get(name);
29
+ scope = scope.parent;
30
+ }
31
+ return null;
32
+ }
33
+
34
+ isVal(name) {
35
+ const entry = this.lookup(name);
36
+ return entry && entry.kind === 'val';
37
+ }
38
+ }
39
+
40
+ class Checker {
41
+ constructor() {
42
+ this.errors = [];
43
+ this.warnings = [];
44
+ }
45
+
46
+ check(ast) {
47
+ this.errors = [];
48
+ this.warnings = [];
49
+ const scope = new Scope();
50
+ this.walkStmts(ast.body, scope);
51
+ return { errors: this.errors, warnings: this.warnings };
52
+ }
53
+
54
+ error(msg, loc, hint = null) { this.errors.push(new CheckError(msg, loc, hint)); }
55
+ warn(msg, loc, hint = null) { this.warnings.push(new CheckError(msg, loc, hint)); }
56
+
57
+ walkStmts(stmts, scope) {
58
+ for (const node of stmts) this.walkStmt(node, scope);
59
+ }
60
+
61
+ walkStmt(node, scope) {
62
+ if (!node) return;
63
+ switch (node.type) {
64
+ case 'VarDecl':
65
+ if (node.init) this.walkExpr(node.init, scope);
66
+ scope.define(node.name, node.kind, node.loc);
67
+ break;
68
+
69
+ case 'DestructureDecl':
70
+ if (node.init) this.walkExpr(node.init, scope);
71
+ if (node.patternType === 'object') {
72
+ for (const p of node.pattern) scope.define(p.alias, node.kind, node.loc);
73
+ } else {
74
+ for (const p of node.pattern) { if (p) scope.define(p.name, node.kind, node.loc); }
75
+ }
76
+ break;
77
+
78
+ case 'FnDecl': {
79
+ const inner = new Scope(scope);
80
+ for (const p of node.params) inner.define(p.name, 'val', node.loc);
81
+ if (node.name) scope.define(node.name, 'val', node.loc);
82
+ if (node.inline) {
83
+ this.walkExpr(node.body, inner);
84
+ } else {
85
+ this.walkStmts(node.body, inner);
86
+ }
87
+ break;
88
+ }
89
+
90
+ case 'ClassDecl': {
91
+ scope.define(node.name, 'val', node.loc);
92
+ const cls = new Scope(scope);
93
+ for (const f of node.fields) cls.define(f.name, 'var', node.loc);
94
+ for (const m of node.methods) this.walkStmt(m, cls);
95
+ break;
96
+ }
97
+
98
+ case 'TypeDecl':
99
+ for (const v of node.variants) scope.define(v.name, 'val', node.loc);
100
+ break;
101
+
102
+ case 'InterfaceDecl':
103
+ scope.define(node.name, 'val', node.loc);
104
+ break;
105
+
106
+ case 'EnumDecl':
107
+ scope.define(node.name, 'val', node.loc);
108
+ break;
109
+
110
+ case 'IfStmt':
111
+ this.walkExpr(node.cond, scope);
112
+ this.walkStmts(node.then, new Scope(scope));
113
+ for (const ei of node.elseifs) {
114
+ this.walkExpr(ei.cond, scope);
115
+ this.walkStmts(ei.body, new Scope(scope));
116
+ }
117
+ if (node.else_) this.walkStmts(node.else_, new Scope(scope));
118
+ break;
119
+
120
+ case 'ForInStmt': {
121
+ this.walkExpr(node.iter, scope);
122
+ const inner = new Scope(scope);
123
+ inner.define(node.var, 'val', node.loc);
124
+ this.walkStmts(node.body, inner);
125
+ break;
126
+ }
127
+
128
+ case 'WhileStmt':
129
+ this.walkExpr(node.cond, scope);
130
+ this.walkStmts(node.body, new Scope(scope));
131
+ break;
132
+
133
+ case 'DoWhileStmt':
134
+ this.walkStmts(node.body, new Scope(scope));
135
+ this.walkExpr(node.cond, scope);
136
+ break;
137
+
138
+ case 'MatchStmt':
139
+ this.walkExpr(node.subject, scope);
140
+ for (const arm of node.arms) {
141
+ const inner = new Scope(scope);
142
+ if (arm.pattern.type === 'VariantPat') {
143
+ for (const b of arm.pattern.bindings) inner.define(b, 'val', node.loc);
144
+ }
145
+ if (arm.guard) this.walkExpr(arm.guard, inner);
146
+ this.walkStmts(arm.body, inner);
147
+ }
148
+ break;
149
+
150
+ case 'ReturnStmt':
151
+ if (node.value) this.walkExpr(node.value, scope);
152
+ break;
153
+
154
+ case 'ThrowStmt':
155
+ this.walkExpr(node.value, scope);
156
+ break;
157
+
158
+ case 'TryCatchStmt': {
159
+ this.walkStmts(node.tryBody, new Scope(scope));
160
+ if (node.catchBody) {
161
+ const inner = new Scope(scope);
162
+ if (node.catchParam) inner.define(node.catchParam, 'val', node.loc);
163
+ this.walkStmts(node.catchBody, inner);
164
+ }
165
+ if (node.finallyBody) this.walkStmts(node.finallyBody, new Scope(scope));
166
+ break;
167
+ }
168
+
169
+ case 'ImportDecl':
170
+ if (node.defaultName) scope.define(node.defaultName, 'val', node.loc);
171
+ if (node.namespaceName) scope.define(node.namespaceName, 'val', node.loc);
172
+ for (const n of node.names) scope.define(typeof n === 'string' ? n : n.alias, 'val', node.loc);
173
+ break;
174
+
175
+ case 'ExportDecl':
176
+ this.walkStmt(node.isDefault ? { type: 'ExprStmt', expr: node.decl } : node.decl, scope);
177
+ break;
178
+
179
+ case 'ExprStmt':
180
+ this.walkExpr(node.expr, scope);
181
+ break;
182
+
183
+ case 'BreakStmt':
184
+ case 'ContinueStmt':
185
+ break;
186
+
187
+ default:
188
+ // Unknown node — skip silently
189
+ }
190
+ }
191
+
192
+ walkExpr(node, scope) {
193
+ if (!node) return;
194
+ switch (node.type) {
195
+
196
+ case 'AssignExpr': {
197
+ const target = node.target;
198
+ if (target.type === 'Identifier') {
199
+ if (scope.isVal(target.name)) {
200
+ this.error(
201
+ `Cannot reassign 'val ${target.name}' — val is immutable`,
202
+ target.loc,
203
+ `Use 'var ${target.name}' if you need a mutable variable`
204
+ );
205
+ }
206
+ }
207
+ this.walkExpr(node.target, scope);
208
+ this.walkExpr(node.value, scope);
209
+ break;
210
+ }
211
+
212
+ case 'UpdateExpr':
213
+ if (node.operand.type === 'Identifier' && scope.isVal(node.operand.name)) {
214
+ this.error(
215
+ `Cannot apply '${node.op}' to 'val ${node.operand.name}' — val is immutable`,
216
+ node.operand.loc,
217
+ `Use 'var ${node.operand.name}' if you need a mutable variable`
218
+ );
219
+ }
220
+ this.walkExpr(node.operand, scope);
221
+ break;
222
+
223
+ case 'BinaryExpr':
224
+ case 'PipeExpr':
225
+ this.walkExpr(node.left, scope);
226
+ this.walkExpr(node.right, scope);
227
+ break;
228
+
229
+ case 'UnaryExpr':
230
+ case 'AwaitExpr':
231
+ case 'TypeofExpr':
232
+ this.walkExpr(node.operand, scope);
233
+ break;
234
+
235
+ case 'TernaryExpr':
236
+ this.walkExpr(node.cond, scope);
237
+ this.walkExpr(node.then, scope);
238
+ this.walkExpr(node.else_, scope);
239
+ break;
240
+
241
+ case 'CallExpr':
242
+ case 'OptCallExpr':
243
+ this.walkExpr(node.callee, scope);
244
+ for (const a of node.args) this.walkExpr(a, scope);
245
+ break;
246
+
247
+ case 'MemberExpr':
248
+ case 'OptMemberExpr':
249
+ this.walkExpr(node.obj, scope);
250
+ break;
251
+
252
+ case 'IndexExpr':
253
+ case 'OptIndexExpr':
254
+ this.walkExpr(node.obj, scope);
255
+ this.walkExpr(node.idx, scope);
256
+ break;
257
+
258
+ case 'NewExpr':
259
+ for (const a of node.args) this.walkExpr(a, scope);
260
+ break;
261
+
262
+ case 'ArrayExpr':
263
+ for (const i of node.items) if (i) this.walkExpr(i, scope);
264
+ break;
265
+
266
+ case 'ObjectExpr':
267
+ for (const p of node.pairs) if (p.value) this.walkExpr(p.value, scope);
268
+ break;
269
+
270
+ case 'SpreadExpr':
271
+ this.walkExpr(node.expr, scope);
272
+ break;
273
+
274
+ case 'LambdaExpr': {
275
+ const inner = new Scope(scope);
276
+ for (const p of node.params) inner.define(p.name, 'val', null);
277
+ this.walkExpr(node.body, inner);
278
+ break;
279
+ }
280
+
281
+ case 'FnDecl': {
282
+ const inner = new Scope(scope);
283
+ for (const p of node.params) inner.define(p.name, 'val', null);
284
+ if (node.inline) {
285
+ this.walkExpr(node.body, inner);
286
+ } else {
287
+ this.walkStmts(node.body, inner);
288
+ }
289
+ break;
290
+ }
291
+
292
+ case 'TemplateLit':
293
+ break;
294
+
295
+ case 'CastExpr':
296
+ case 'AsConstExpr':
297
+ case 'SatisfiesExpr':
298
+ case 'IsExpr':
299
+ case 'NonNullExpr':
300
+ this.walkExpr(node.expr, scope);
301
+ break;
302
+
303
+ case 'RangeExpr':
304
+ this.walkExpr(node.start, scope);
305
+ this.walkExpr(node.end, scope);
306
+ break;
307
+
308
+ case 'Identifier':
309
+ case 'NumberLit':
310
+ case 'BoolLit':
311
+ case 'NullLit':
312
+ case 'StringLit':
313
+ case 'SelfExpr':
314
+ break;
315
+
316
+ default:
317
+ // Unknown expression node — skip
318
+ }
319
+ }
320
+ }
321
+
322
+ module.exports = { Checker };