lumos-language 1.1.2 → 2.0.2

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 (63) hide show
  1. package/.github/FUNDING.yml +1 -0
  2. package/.npmrc.ci-backup +3 -0
  3. package/LICENSE +0 -29
  4. package/Lumos.png +0 -0
  5. package/README.md +284 -126
  6. package/STRUCTURE.md +216 -0
  7. package/examples/hello.lumos +5 -0
  8. package/index.cjs +125 -125
  9. package/index.html +120 -274
  10. package/package.json +20 -10
  11. package/src/backends/assembly/arm.js +39 -0
  12. package/src/backends/assembly/wasm.js +39 -0
  13. package/src/backends/assembly/x86.js +39 -0
  14. package/src/backends/compiled/c.js +39 -0
  15. package/src/backends/compiled/cpp.js +39 -0
  16. package/src/backends/compiled/csharp.js +39 -0
  17. package/src/backends/compiled/go.js +39 -0
  18. package/src/backends/compiled/java.js +39 -0
  19. package/src/backends/compiled/rust.js +39 -0
  20. package/src/backends/compiled/swift.js +39 -0
  21. package/src/backends/database/mongodb.js +39 -0
  22. package/src/backends/database/mysql.js +39 -0
  23. package/src/backends/database/postgresql.js +39 -0
  24. package/src/backends/database/sql.js +39 -0
  25. package/src/backends/database/sqlite.js +39 -0
  26. package/src/backends/functional/clojure.js +39 -0
  27. package/src/backends/functional/elixir.js +39 -0
  28. package/src/backends/functional/erlang.js +39 -0
  29. package/src/backends/functional/fsharp.js +39 -0
  30. package/src/backends/functional/haskell.js +39 -0
  31. package/src/backends/functional/scala.js +39 -0
  32. package/src/backends/interpreted/lua.js +39 -0
  33. package/src/backends/interpreted/perl.js +39 -0
  34. package/src/backends/interpreted/php.js +39 -0
  35. package/src/backends/interpreted/python.js +356 -0
  36. package/src/backends/interpreted/ruby.js +222 -0
  37. package/src/backends/scripting/bash.js +39 -0
  38. package/src/backends/scripting/javascript.js +39 -0
  39. package/src/backends/scripting/powershell.js +39 -0
  40. package/src/backends/scripting/typescript.js +39 -0
  41. package/src/backends/scripting/vbscript.js +39 -0
  42. package/src/backends/specialized/ada.js +39 -0
  43. package/src/backends/specialized/cobol.js +39 -0
  44. package/src/backends/specialized/fortran.js +39 -0
  45. package/src/backends/specialized/lisp.js +39 -0
  46. package/src/backends/specialized/mlang.js +39 -0
  47. package/src/backends/specialized/prolog.js +39 -0
  48. package/src/backends/web/css.js +39 -0
  49. package/src/backends/web/html.js +39 -0
  50. package/src/backends/web/jsx.js +39 -0
  51. package/src/backends/web/vue.js +39 -0
  52. package/src/cli/fileRunner.js +82 -0
  53. package/src/cli/repl.js +244 -0
  54. package/src/compiler/core/compiler.js +1350 -0
  55. package/src/compiler/framework-integrator.js +846 -0
  56. package/src/compiler/generators/dynamic-languages.js +620 -0
  57. package/src/compiler/generators/system-languages.js +1184 -0
  58. package/src/core/compiler.js +181 -0
  59. package/src/core/evaluator.js +408 -0
  60. package/src/core/lexer.js +251 -0
  61. package/src/core/parser.js +452 -0
  62. package/src/core/runtime.js +173 -0
  63. package/tests/run-tests.js +243 -0
@@ -0,0 +1,1350 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ class LumosCompiler {
5
+ constructor() {
6
+ this.ast = null;
7
+ this.tokens = [];
8
+ this.targetLanguages = [
9
+ 'javascript', 'typescript', 'python', 'php', 'ruby', 'go',
10
+ 'rust', 'c', 'cpp', 'csharp', 'java', 'kotlin', 'swift',
11
+ 'elixir', 'fsharp', 'ada', 'dlang', 'assembly', 'llvm'
12
+ ];
13
+ this.symbolTable = new Map();
14
+ this.typeSystem = new TypeSystem();
15
+ }
16
+
17
+ compile(sourceCode, targetLang = 'javascript') {
18
+ try {
19
+ this.tokens = this.tokenize(sourceCode);
20
+ this.ast = this.parse(this.tokens);
21
+ this.semanticAnalysis(this.ast);
22
+ const ir = this.generateIR(this.ast);
23
+ const optimizedIR = this.optimize(ir);
24
+ return this.codeGen(optimizedIR, targetLang);
25
+ } catch (error) {
26
+ throw new CompilationError(`Compilation failed: ${error.message}`, error);
27
+ }
28
+ }
29
+
30
+ tokenize(source) {
31
+ const tokens = [];
32
+ const patterns = {
33
+ KEYWORD: /\b(let|def|for|while|if|elsif|else|break|continue|return|class|import|export|async|await|match|case|try|catch|finally|throw|yield|lambda|const|var|type|interface|struct|enum|trait|impl|mod|use|pub|fn|mut)\b/,
34
+ IDENTIFIER: /\b[a-zA-Z_][a-zA-Z0-9_]*\b/,
35
+ NUMBER: /\b\d+(\.\d+)?\b/,
36
+ STRING: /"([^"\\]|\\.)*"|'([^'\\]|\\.)*'/,
37
+ OPERATOR: /[+\-*\/%=<>!&|^~]+/,
38
+ DELIMITER: /[{}()\[\];,.:]/,
39
+ WHITESPACE: /\s+/,
40
+ COMMENT: /\/\/.*|\/\*[\s\S]*?\*\//,
41
+ ANNOTATION: /@[a-zA-Z_][a-zA-Z0-9_]*/,
42
+ TEMPLATE: /`([^`\\]|\\.)*`/
43
+ };
44
+
45
+ let position = 0;
46
+ const lines = source.split('\n');
47
+
48
+ for (let lineNum = 0; lineNum < lines.length; lineNum++) {
49
+ let line = lines[lineNum];
50
+ let column = 0;
51
+
52
+ while (column < line.length) {
53
+ let matched = false;
54
+
55
+ for (const [type, pattern] of Object.entries(patterns)) {
56
+ const regex = new RegExp(`^${pattern.source}`);
57
+ const match = line.substring(column).match(regex);
58
+
59
+ if (match) {
60
+ if (type !== 'WHITESPACE' && type !== 'COMMENT') {
61
+ tokens.push({
62
+ type,
63
+ value: match[0],
64
+ line: lineNum + 1,
65
+ column: column + 1,
66
+ position: position
67
+ });
68
+ }
69
+ column += match[0].length;
70
+ position += match[0].length;
71
+ matched = true;
72
+ break;
73
+ }
74
+ }
75
+
76
+ if (!matched) {
77
+ throw new SyntaxError(`Unexpected character '${line[column]}' at line ${lineNum + 1}, column ${column + 1}`);
78
+ }
79
+ }
80
+ position++;
81
+ }
82
+
83
+ return tokens;
84
+ }
85
+
86
+ parse(tokens) {
87
+ const parser = new Parser(tokens);
88
+ return parser.parseProgram();
89
+ }
90
+
91
+ semanticAnalysis(ast) {
92
+ const analyzer = new SemanticAnalyzer(this.symbolTable, this.typeSystem);
93
+ analyzer.analyze(ast);
94
+ }
95
+
96
+ generateIR(ast) {
97
+ const generator = new IRGenerator(this.symbolTable);
98
+ return generator.generate(ast);
99
+ }
100
+
101
+ optimize(ir) {
102
+ const optimizer = new Optimizer();
103
+ return optimizer.optimize(ir);
104
+ }
105
+
106
+ codeGen(ir, targetLang) {
107
+ const generators = {
108
+ javascript: new JavaScriptGenerator(),
109
+ typescript: new TypeScriptGenerator(),
110
+ python: new PythonGenerator(),
111
+ php: new PHPGenerator(),
112
+ ruby: new RubyGenerator(),
113
+ go: new GoGenerator(),
114
+ rust: new RustGenerator(),
115
+ c: new CGenerator(),
116
+ cpp: new CppGenerator(),
117
+ csharp: new CSharpGenerator(),
118
+ java: new JavaGenerator(),
119
+ elixir: new ElixirGenerator(),
120
+ fsharp: new FSharpGenerator(),
121
+ ada: new AdaGenerator(),
122
+ dlang: new DlangGenerator(),
123
+ assembly: new AssemblyGenerator(),
124
+ llvm: new LLVMGenerator()
125
+ };
126
+
127
+ const generator = generators[targetLang];
128
+ if (!generator) {
129
+ throw new Error(`Unsupported target language: ${targetLang}`);
130
+ }
131
+
132
+ return generator.generate(ir);
133
+ }
134
+ }
135
+
136
+ class Parser {
137
+ constructor(tokens) {
138
+ this.tokens = tokens;
139
+ this.current = 0;
140
+ }
141
+
142
+ parseProgram() {
143
+ const program = {
144
+ type: 'Program',
145
+ body: [],
146
+ sourceType: 'module'
147
+ };
148
+
149
+ while (!this.isAtEnd()) {
150
+ program.body.push(this.parseStatement());
151
+ }
152
+
153
+ return program;
154
+ }
155
+
156
+ parseStatement() {
157
+ const token = this.peek();
158
+
159
+ if (token.type === 'KEYWORD') {
160
+ switch (token.value) {
161
+ case 'let':
162
+ case 'const':
163
+ case 'var':
164
+ return this.parseVariableDeclaration();
165
+ case 'def':
166
+ case 'fn':
167
+ case 'function':
168
+ return this.parseFunctionDeclaration();
169
+ case 'class':
170
+ return this.parseClassDeclaration();
171
+ case 'if':
172
+ return this.parseIfStatement();
173
+ case 'for':
174
+ return this.parseForStatement();
175
+ case 'while':
176
+ return this.parseWhileStatement();
177
+ case 'return':
178
+ return this.parseReturnStatement();
179
+ case 'break':
180
+ return this.parseBreakStatement();
181
+ case 'continue':
182
+ return this.parseContinueStatement();
183
+ case 'import':
184
+ return this.parseImportStatement();
185
+ case 'export':
186
+ return this.parseExportStatement();
187
+ case 'try':
188
+ return this.parseTryStatement();
189
+ case 'match':
190
+ return this.parseMatchStatement();
191
+ case 'type':
192
+ case 'interface':
193
+ return this.parseTypeDeclaration();
194
+ default:
195
+ return this.parseExpressionStatement();
196
+ }
197
+ }
198
+
199
+ return this.parseExpressionStatement();
200
+ }
201
+
202
+ parseVariableDeclaration() {
203
+ const keyword = this.advance();
204
+ const identifier = this.consume('IDENTIFIER', 'Expected variable name');
205
+
206
+ let init = null;
207
+ if (this.match('OPERATOR', '=')) {
208
+ this.advance();
209
+ init = this.parseExpression();
210
+ }
211
+
212
+ return {
213
+ type: 'VariableDeclaration',
214
+ kind: keyword.value,
215
+ declarations: [{
216
+ type: 'VariableDeclarator',
217
+ id: { type: 'Identifier', name: identifier.value },
218
+ init
219
+ }]
220
+ };
221
+ }
222
+
223
+ parseFunctionDeclaration() {
224
+ this.advance();
225
+ const name = this.consume('IDENTIFIER', 'Expected function name');
226
+ this.consume('DELIMITER', '(');
227
+
228
+ const params = [];
229
+ while (!this.check('DELIMITER', ')')) {
230
+ params.push({
231
+ type: 'Identifier',
232
+ name: this.consume('IDENTIFIER', 'Expected parameter name').value
233
+ });
234
+ if (!this.check('DELIMITER', ')')) {
235
+ this.consume('DELIMITER', ',');
236
+ }
237
+ }
238
+
239
+ this.consume('DELIMITER', ')');
240
+ this.consume('DELIMITER', '{');
241
+
242
+ const body = [];
243
+ while (!this.check('DELIMITER', '}')) {
244
+ body.push(this.parseStatement());
245
+ }
246
+
247
+ this.consume('DELIMITER', '}');
248
+
249
+ return {
250
+ type: 'FunctionDeclaration',
251
+ id: { type: 'Identifier', name: name.value },
252
+ params,
253
+ body: { type: 'BlockStatement', body }
254
+ };
255
+ }
256
+
257
+ parseClassDeclaration() {
258
+ this.advance();
259
+ const name = this.consume('IDENTIFIER', 'Expected class name');
260
+
261
+ let superClass = null;
262
+ if (this.match('OPERATOR', '<') || this.match('KEYWORD', 'extends')) {
263
+ this.advance();
264
+ superClass = {
265
+ type: 'Identifier',
266
+ name: this.consume('IDENTIFIER', 'Expected superclass name').value
267
+ };
268
+ }
269
+
270
+ this.consume('DELIMITER', '{');
271
+
272
+ const body = [];
273
+ while (!this.check('DELIMITER', '}')) {
274
+ if (this.check('KEYWORD', 'def') || this.check('KEYWORD', 'fn')) {
275
+ body.push(this.parseFunctionDeclaration());
276
+ } else {
277
+ body.push(this.parseStatement());
278
+ }
279
+ }
280
+
281
+ this.consume('DELIMITER', '}');
282
+
283
+ return {
284
+ type: 'ClassDeclaration',
285
+ id: { type: 'Identifier', name: name.value },
286
+ superClass,
287
+ body: { type: 'ClassBody', body }
288
+ };
289
+ }
290
+
291
+ parseIfStatement() {
292
+ this.advance();
293
+ this.consume('DELIMITER', '(');
294
+ const test = this.parseExpression();
295
+ this.consume('DELIMITER', ')');
296
+ this.consume('DELIMITER', '{');
297
+
298
+ const consequent = [];
299
+ while (!this.check('DELIMITER', '}')) {
300
+ consequent.push(this.parseStatement());
301
+ }
302
+ this.consume('DELIMITER', '}');
303
+
304
+ let alternate = null;
305
+ if (this.match('KEYWORD', 'elsif')) {
306
+ alternate = this.parseIfStatement();
307
+ } else if (this.match('KEYWORD', 'else')) {
308
+ this.advance();
309
+ this.consume('DELIMITER', '{');
310
+ const elseBody = [];
311
+ while (!this.check('DELIMITER', '}')) {
312
+ elseBody.push(this.parseStatement());
313
+ }
314
+ this.consume('DELIMITER', '}');
315
+ alternate = { type: 'BlockStatement', body: elseBody };
316
+ }
317
+
318
+ return {
319
+ type: 'IfStatement',
320
+ test,
321
+ consequent: { type: 'BlockStatement', body: consequent },
322
+ alternate
323
+ };
324
+ }
325
+
326
+ parseForStatement() {
327
+ this.advance();
328
+ const variable = this.consume('IDENTIFIER', 'Expected loop variable');
329
+ this.consume('OPERATOR', '=');
330
+ const start = this.parseExpression();
331
+ this.consume('KEYWORD', 'to');
332
+ const end = this.parseExpression();
333
+ this.consume('DELIMITER', '{');
334
+
335
+ const body = [];
336
+ while (!this.check('DELIMITER', '}')) {
337
+ body.push(this.parseStatement());
338
+ }
339
+ this.consume('DELIMITER', '}');
340
+
341
+ return {
342
+ type: 'ForStatement',
343
+ init: {
344
+ type: 'VariableDeclaration',
345
+ kind: 'let',
346
+ declarations: [{
347
+ type: 'VariableDeclarator',
348
+ id: { type: 'Identifier', name: variable.value },
349
+ init: start
350
+ }]
351
+ },
352
+ test: {
353
+ type: 'BinaryExpression',
354
+ operator: '<=',
355
+ left: { type: 'Identifier', name: variable.value },
356
+ right: end
357
+ },
358
+ update: {
359
+ type: 'UpdateExpression',
360
+ operator: '++',
361
+ prefix: false,
362
+ argument: { type: 'Identifier', name: variable.value }
363
+ },
364
+ body: { type: 'BlockStatement', body }
365
+ };
366
+ }
367
+
368
+ parseWhileStatement() {
369
+ this.advance();
370
+ this.consume('DELIMITER', '(');
371
+ const test = this.parseExpression();
372
+ this.consume('DELIMITER', ')');
373
+ this.consume('DELIMITER', '{');
374
+
375
+ const body = [];
376
+ while (!this.check('DELIMITER', '}')) {
377
+ body.push(this.parseStatement());
378
+ }
379
+ this.consume('DELIMITER', '}');
380
+
381
+ return {
382
+ type: 'WhileStatement',
383
+ test,
384
+ body: { type: 'BlockStatement', body }
385
+ };
386
+ }
387
+
388
+ parseReturnStatement() {
389
+ this.advance();
390
+ let argument = null;
391
+ if (!this.isAtEnd() && !this.check('DELIMITER', '}')) {
392
+ argument = this.parseExpression();
393
+ }
394
+ return {
395
+ type: 'ReturnStatement',
396
+ argument
397
+ };
398
+ }
399
+
400
+ parseBreakStatement() {
401
+ this.advance();
402
+ return { type: 'BreakStatement' };
403
+ }
404
+
405
+ parseContinueStatement() {
406
+ this.advance();
407
+ return { type: 'ContinueStatement' };
408
+ }
409
+
410
+ parseImportStatement() {
411
+ this.advance();
412
+ const specifiers = [];
413
+
414
+ if (this.check('DELIMITER', '{')) {
415
+ this.advance();
416
+ while (!this.check('DELIMITER', '}')) {
417
+ const imported = this.consume('IDENTIFIER', 'Expected import name');
418
+ let local = imported;
419
+ if (this.match('KEYWORD', 'as')) {
420
+ this.advance();
421
+ local = this.consume('IDENTIFIER', 'Expected alias name');
422
+ }
423
+ specifiers.push({
424
+ type: 'ImportSpecifier',
425
+ imported: { type: 'Identifier', name: imported.value },
426
+ local: { type: 'Identifier', name: local.value }
427
+ });
428
+ if (!this.check('DELIMITER', '}')) {
429
+ this.consume('DELIMITER', ',');
430
+ }
431
+ }
432
+ this.consume('DELIMITER', '}');
433
+ } else {
434
+ const name = this.consume('IDENTIFIER', 'Expected module name');
435
+ specifiers.push({
436
+ type: 'ImportDefaultSpecifier',
437
+ local: { type: 'Identifier', name: name.value }
438
+ });
439
+ }
440
+
441
+ this.consume('KEYWORD', 'from');
442
+ const source = this.consume('STRING', 'Expected module path');
443
+
444
+ return {
445
+ type: 'ImportDeclaration',
446
+ specifiers,
447
+ source: { type: 'Literal', value: source.value.slice(1, -1) }
448
+ };
449
+ }
450
+
451
+ parseExportStatement() {
452
+ this.advance();
453
+ const declaration = this.parseStatement();
454
+ return {
455
+ type: 'ExportNamedDeclaration',
456
+ declaration
457
+ };
458
+ }
459
+
460
+ parseTryStatement() {
461
+ this.advance();
462
+ this.consume('DELIMITER', '{');
463
+
464
+ const block = [];
465
+ while (!this.check('DELIMITER', '}')) {
466
+ block.push(this.parseStatement());
467
+ }
468
+ this.consume('DELIMITER', '}');
469
+
470
+ let handler = null;
471
+ if (this.match('KEYWORD', 'catch')) {
472
+ this.advance();
473
+ this.consume('DELIMITER', '(');
474
+ const param = this.consume('IDENTIFIER', 'Expected exception variable');
475
+ this.consume('DELIMITER', ')');
476
+ this.consume('DELIMITER', '{');
477
+
478
+ const catchBody = [];
479
+ while (!this.check('DELIMITER', '}')) {
480
+ catchBody.push(this.parseStatement());
481
+ }
482
+ this.consume('DELIMITER', '}');
483
+
484
+ handler = {
485
+ type: 'CatchClause',
486
+ param: { type: 'Identifier', name: param.value },
487
+ body: { type: 'BlockStatement', body: catchBody }
488
+ };
489
+ }
490
+
491
+ let finalizer = null;
492
+ if (this.match('KEYWORD', 'finally')) {
493
+ this.advance();
494
+ this.consume('DELIMITER', '{');
495
+
496
+ const finallyBody = [];
497
+ while (!this.check('DELIMITER', '}')) {
498
+ finallyBody.push(this.parseStatement());
499
+ }
500
+ this.consume('DELIMITER', '}');
501
+
502
+ finalizer = { type: 'BlockStatement', body: finallyBody };
503
+ }
504
+
505
+ return {
506
+ type: 'TryStatement',
507
+ block: { type: 'BlockStatement', body: block },
508
+ handler,
509
+ finalizer
510
+ };
511
+ }
512
+
513
+ parseMatchStatement() {
514
+ this.advance();
515
+ this.consume('DELIMITER', '(');
516
+ const discriminant = this.parseExpression();
517
+ this.consume('DELIMITER', ')');
518
+ this.consume('DELIMITER', '{');
519
+
520
+ const cases = [];
521
+ while (!this.check('DELIMITER', '}')) {
522
+ this.consume('KEYWORD', 'case');
523
+ const test = this.parseExpression();
524
+ this.consume('OPERATOR', '=>');
525
+ this.consume('DELIMITER', '{');
526
+
527
+ const consequent = [];
528
+ while (!this.check('DELIMITER', '}')) {
529
+ consequent.push(this.parseStatement());
530
+ }
531
+ this.consume('DELIMITER', '}');
532
+
533
+ cases.push({
534
+ type: 'SwitchCase',
535
+ test,
536
+ consequent
537
+ });
538
+ }
539
+ this.consume('DELIMITER', '}');
540
+
541
+ return {
542
+ type: 'SwitchStatement',
543
+ discriminant,
544
+ cases
545
+ };
546
+ }
547
+
548
+ parseTypeDeclaration() {
549
+ const keyword = this.advance();
550
+ const name = this.consume('IDENTIFIER', 'Expected type name');
551
+
552
+ this.consume('OPERATOR', '=');
553
+ const definition = this.parseTypeExpression();
554
+
555
+ return {
556
+ type: 'TypeAliasDeclaration',
557
+ id: { type: 'Identifier', name: name.value },
558
+ typeAnnotation: definition
559
+ };
560
+ }
561
+
562
+ parseTypeExpression() {
563
+ const types = [];
564
+ types.push(this.parseBasicType());
565
+
566
+ while (this.match('OPERATOR', '|')) {
567
+ this.advance();
568
+ types.push(this.parseBasicType());
569
+ }
570
+
571
+ if (types.length === 1) {
572
+ return types[0];
573
+ }
574
+
575
+ return {
576
+ type: 'UnionType',
577
+ types
578
+ };
579
+ }
580
+
581
+ parseBasicType() {
582
+ if (this.check('IDENTIFIER')) {
583
+ const name = this.advance();
584
+ return { type: 'TypeReference', name: name.value };
585
+ }
586
+
587
+ if (this.check('DELIMITER', '{')) {
588
+ this.advance();
589
+ const properties = [];
590
+
591
+ while (!this.check('DELIMITER', '}')) {
592
+ const key = this.consume('IDENTIFIER', 'Expected property name');
593
+ this.consume('DELIMITER', ':');
594
+ const valueType = this.parseTypeExpression();
595
+
596
+ properties.push({
597
+ type: 'PropertySignature',
598
+ key: { type: 'Identifier', name: key.value },
599
+ typeAnnotation: valueType
600
+ });
601
+
602
+ if (!this.check('DELIMITER', '}')) {
603
+ this.consume('DELIMITER', ',');
604
+ }
605
+ }
606
+ this.consume('DELIMITER', '}');
607
+
608
+ return {
609
+ type: 'ObjectType',
610
+ properties
611
+ };
612
+ }
613
+
614
+ throw new Error('Expected type expression');
615
+ }
616
+
617
+ parseExpressionStatement() {
618
+ const expr = this.parseExpression();
619
+ return {
620
+ type: 'ExpressionStatement',
621
+ expression: expr
622
+ };
623
+ }
624
+
625
+ parseExpression() {
626
+ return this.parseAssignment();
627
+ }
628
+
629
+ parseAssignment() {
630
+ const expr = this.parseLogicalOr();
631
+
632
+ if (this.match('OPERATOR', '=')) {
633
+ this.advance();
634
+ const value = this.parseAssignment();
635
+ return {
636
+ type: 'AssignmentExpression',
637
+ operator: '=',
638
+ left: expr,
639
+ right: value
640
+ };
641
+ }
642
+
643
+ return expr;
644
+ }
645
+
646
+ parseLogicalOr() {
647
+ let expr = this.parseLogicalAnd();
648
+
649
+ while (this.match('OPERATOR', '||')) {
650
+ const operator = this.advance();
651
+ const right = this.parseLogicalAnd();
652
+ expr = {
653
+ type: 'LogicalExpression',
654
+ operator: operator.value,
655
+ left: expr,
656
+ right
657
+ };
658
+ }
659
+
660
+ return expr;
661
+ }
662
+
663
+ parseLogicalAnd() {
664
+ let expr = this.parseEquality();
665
+
666
+ while (this.match('OPERATOR', '&&')) {
667
+ const operator = this.advance();
668
+ const right = this.parseEquality();
669
+ expr = {
670
+ type: 'LogicalExpression',
671
+ operator: operator.value,
672
+ left: expr,
673
+ right
674
+ };
675
+ }
676
+
677
+ return expr;
678
+ }
679
+
680
+ parseEquality() {
681
+ let expr = this.parseComparison();
682
+
683
+ while (this.match('OPERATOR', '==') || this.match('OPERATOR', '!=')) {
684
+ const operator = this.advance();
685
+ const right = this.parseComparison();
686
+ expr = {
687
+ type: 'BinaryExpression',
688
+ operator: operator.value,
689
+ left: expr,
690
+ right
691
+ };
692
+ }
693
+
694
+ return expr;
695
+ }
696
+
697
+ parseComparison() {
698
+ let expr = this.parseAdditive();
699
+
700
+ while (this.match('OPERATOR', '<') || this.match('OPERATOR', '>') ||
701
+ this.match('OPERATOR', '<=') || this.match('OPERATOR', '>=')) {
702
+ const operator = this.advance();
703
+ const right = this.parseAdditive();
704
+ expr = {
705
+ type: 'BinaryExpression',
706
+ operator: operator.value,
707
+ left: expr,
708
+ right
709
+ };
710
+ }
711
+
712
+ return expr;
713
+ }
714
+
715
+ parseAdditive() {
716
+ let expr = this.parseMultiplicative();
717
+
718
+ while (this.match('OPERATOR', '+') || this.match('OPERATOR', '-')) {
719
+ const operator = this.advance();
720
+ const right = this.parseMultiplicative();
721
+ expr = {
722
+ type: 'BinaryExpression',
723
+ operator: operator.value,
724
+ left: expr,
725
+ right
726
+ };
727
+ }
728
+
729
+ return expr;
730
+ }
731
+
732
+ parseMultiplicative() {
733
+ let expr = this.parseUnary();
734
+
735
+ while (this.match('OPERATOR', '*') || this.match('OPERATOR', '/') || this.match('OPERATOR', '%')) {
736
+ const operator = this.advance();
737
+ const right = this.parseUnary();
738
+ expr = {
739
+ type: 'BinaryExpression',
740
+ operator: operator.value,
741
+ left: expr,
742
+ right
743
+ };
744
+ }
745
+
746
+ return expr;
747
+ }
748
+
749
+ parseUnary() {
750
+ if (this.match('OPERATOR', '!') || this.match('OPERATOR', '-') || this.match('OPERATOR', '+')) {
751
+ const operator = this.advance();
752
+ const argument = this.parseUnary();
753
+ return {
754
+ type: 'UnaryExpression',
755
+ operator: operator.value,
756
+ prefix: true,
757
+ argument
758
+ };
759
+ }
760
+
761
+ return this.parsePostfix();
762
+ }
763
+
764
+ parsePostfix() {
765
+ let expr = this.parsePrimary();
766
+
767
+ while (true) {
768
+ if (this.check('DELIMITER', '(')) {
769
+ this.advance();
770
+ const args = [];
771
+
772
+ while (!this.check('DELIMITER', ')')) {
773
+ args.push(this.parseExpression());
774
+ if (!this.check('DELIMITER', ')')) {
775
+ this.consume('DELIMITER', ',');
776
+ }
777
+ }
778
+
779
+ this.consume('DELIMITER', ')');
780
+ expr = {
781
+ type: 'CallExpression',
782
+ callee: expr,
783
+ arguments: args
784
+ };
785
+ } else if (this.check('DELIMITER', '[')) {
786
+ this.advance();
787
+ const property = this.parseExpression();
788
+ this.consume('DELIMITER', ']');
789
+ expr = {
790
+ type: 'MemberExpression',
791
+ object: expr,
792
+ property,
793
+ computed: true
794
+ };
795
+ } else if (this.check('DELIMITER', '.')) {
796
+ this.advance();
797
+ const property = this.consume('IDENTIFIER', 'Expected property name');
798
+ expr = {
799
+ type: 'MemberExpression',
800
+ object: expr,
801
+ property: { type: 'Identifier', name: property.value },
802
+ computed: false
803
+ };
804
+ } else {
805
+ break;
806
+ }
807
+ }
808
+
809
+ return expr;
810
+ }
811
+
812
+ parsePrimary() {
813
+ if (this.check('NUMBER')) {
814
+ const token = this.advance();
815
+ return {
816
+ type: 'Literal',
817
+ value: parseFloat(token.value),
818
+ raw: token.value
819
+ };
820
+ }
821
+
822
+ if (this.check('STRING')) {
823
+ const token = this.advance();
824
+ return {
825
+ type: 'Literal',
826
+ value: token.value.slice(1, -1),
827
+ raw: token.value
828
+ };
829
+ }
830
+
831
+ if (this.check('IDENTIFIER')) {
832
+ const token = this.advance();
833
+ return {
834
+ type: 'Identifier',
835
+ name: token.value
836
+ };
837
+ }
838
+
839
+ if (this.check('DELIMITER', '(')) {
840
+ this.advance();
841
+ const expr = this.parseExpression();
842
+ this.consume('DELIMITER', ')');
843
+ return expr;
844
+ }
845
+
846
+ if (this.check('DELIMITER', '[')) {
847
+ this.advance();
848
+ const elements = [];
849
+
850
+ while (!this.check('DELIMITER', ']')) {
851
+ elements.push(this.parseExpression());
852
+ if (!this.check('DELIMITER', ']')) {
853
+ this.consume('DELIMITER', ',');
854
+ }
855
+ }
856
+
857
+ this.consume('DELIMITER', ']');
858
+ return {
859
+ type: 'ArrayExpression',
860
+ elements
861
+ };
862
+ }
863
+
864
+ if (this.check('DELIMITER', '{')) {
865
+ this.advance();
866
+ const properties = [];
867
+
868
+ while (!this.check('DELIMITER', '}')) {
869
+ const key = this.consume('IDENTIFIER', 'Expected property name');
870
+ this.consume('DELIMITER', ':');
871
+ const value = this.parseExpression();
872
+
873
+ properties.push({
874
+ type: 'Property',
875
+ key: { type: 'Identifier', name: key.value },
876
+ value,
877
+ kind: 'init'
878
+ });
879
+
880
+ if (!this.check('DELIMITER', '}')) {
881
+ this.consume('DELIMITER', ',');
882
+ }
883
+ }
884
+
885
+ this.consume('DELIMITER', '}');
886
+ return {
887
+ type: 'ObjectExpression',
888
+ properties
889
+ };
890
+ }
891
+
892
+ throw new Error(`Unexpected token: ${this.peek().value}`);
893
+ }
894
+
895
+ peek() {
896
+ return this.tokens[this.current];
897
+ }
898
+
899
+ advance() {
900
+ if (!this.isAtEnd()) {
901
+ this.current++;
902
+ }
903
+ return this.tokens[this.current - 1];
904
+ }
905
+
906
+ check(type, value = null) {
907
+ if (this.isAtEnd()) return false;
908
+ const token = this.peek();
909
+ if (token.type !== type) return false;
910
+ if (value !== null && token.value !== value) return false;
911
+ return true;
912
+ }
913
+
914
+ match(type, value = null) {
915
+ return this.check(type, value);
916
+ }
917
+
918
+ consume(type, message) {
919
+ if (this.check(type)) {
920
+ return this.advance();
921
+ }
922
+ throw new Error(message);
923
+ }
924
+
925
+ isAtEnd() {
926
+ return this.current >= this.tokens.length;
927
+ }
928
+ }
929
+
930
+ class TypeSystem {
931
+ constructor() {
932
+ this.types = new Map();
933
+ this.initializePrimitiveTypes();
934
+ }
935
+
936
+ initializePrimitiveTypes() {
937
+ const primitives = ['int', 'float', 'string', 'bool', 'void', 'any', 'number', 'object', 'array'];
938
+ primitives.forEach(type => {
939
+ this.types.set(type, { kind: 'primitive', name: type });
940
+ });
941
+ }
942
+
943
+ defineType(name, definition) {
944
+ this.types.set(name, definition);
945
+ }
946
+
947
+ getType(name) {
948
+ return this.types.get(name);
949
+ }
950
+
951
+ inferType(node) {
952
+ switch (node.type) {
953
+ case 'Literal':
954
+ if (typeof node.value === 'number') return 'number';
955
+ if (typeof node.value === 'string') return 'string';
956
+ if (typeof node.value === 'boolean') return 'bool';
957
+ return 'any';
958
+ case 'Identifier':
959
+ return 'any';
960
+ case 'BinaryExpression':
961
+ return this.inferBinaryType(node);
962
+ case 'CallExpression':
963
+ return 'any';
964
+ default:
965
+ return 'any';
966
+ }
967
+ }
968
+
969
+ inferBinaryType(node) {
970
+ const leftType = this.inferType(node.left);
971
+ const rightType = this.inferType(node.right);
972
+
973
+ if (['+', '-', '*', '/', '%'].includes(node.operator)) {
974
+ if (leftType === 'number' && rightType === 'number') return 'number';
975
+ if (node.operator === '+' && (leftType === 'string' || rightType === 'string')) return 'string';
976
+ return 'any';
977
+ }
978
+
979
+ if (['==', '!=', '<', '>', '<=', '>='].includes(node.operator)) {
980
+ return 'bool';
981
+ }
982
+
983
+ return 'any';
984
+ }
985
+
986
+ checkTypeCompatibility(type1, type2) {
987
+ if (type1 === 'any' || type2 === 'any') return true;
988
+ return type1 === type2;
989
+ }
990
+ }
991
+
992
+ class SemanticAnalyzer {
993
+ constructor(symbolTable, typeSystem) {
994
+ this.symbolTable = symbolTable;
995
+ this.typeSystem = typeSystem;
996
+ this.scopes = [new Map()];
997
+ this.errors = [];
998
+ }
999
+
1000
+ analyze(ast) {
1001
+ this.visitProgram(ast);
1002
+ if (this.errors.length > 0) {
1003
+ throw new Error(`Semantic errors:\n${this.errors.join('\n')}`);
1004
+ }
1005
+ }
1006
+
1007
+ visitProgram(node) {
1008
+ node.body.forEach(stmt => this.visitNode(stmt));
1009
+ }
1010
+
1011
+ visitNode(node) {
1012
+ const visitor = `visit${node.type}`;
1013
+ if (this[visitor]) {
1014
+ return this[visitor](node);
1015
+ }
1016
+ return null;
1017
+ }
1018
+
1019
+ visitVariableDeclaration(node) {
1020
+ node.declarations.forEach(decl => {
1021
+ const name = decl.id.name;
1022
+ const currentScope = this.scopes[this.scopes.length - 1];
1023
+
1024
+ if (currentScope.has(name)) {
1025
+ this.errors.push(`Variable '${name}' is already declared in this scope`);
1026
+ }
1027
+
1028
+ let type = 'any';
1029
+ if (decl.init) {
1030
+ type = this.visitNode(decl.init);
1031
+ }
1032
+
1033
+ currentScope.set(name, { type, kind: node.kind });
1034
+ this.symbolTable.set(name, { type, kind: node.kind });
1035
+ });
1036
+ }
1037
+
1038
+ visitFunctionDeclaration(node) {
1039
+ const name = node.id.name;
1040
+ const currentScope = this.scopes[this.scopes.length - 1];
1041
+
1042
+ currentScope.set(name, { type: 'function', params: node.params });
1043
+ this.symbolTable.set(name, { type: 'function', params: node.params });
1044
+
1045
+ this.scopes.push(new Map());
1046
+
1047
+ node.params.forEach(param => {
1048
+ this.scopes[this.scopes.length - 1].set(param.name, { type: 'any', kind: 'param' });
1049
+ });
1050
+
1051
+ this.visitNode(node.body);
1052
+
1053
+ this.scopes.pop();
1054
+ }
1055
+
1056
+ visitBlockStatement(node) {
1057
+ node.body.forEach(stmt => this.visitNode(stmt));
1058
+ }
1059
+
1060
+ visitExpressionStatement(node) {
1061
+ return this.visitNode(node.expression);
1062
+ }
1063
+
1064
+ visitBinaryExpression(node) {
1065
+ const leftType = this.visitNode(node.left);
1066
+ const rightType = this.visitNode(node.right);
1067
+ return this.typeSystem.inferBinaryType(node);
1068
+ }
1069
+
1070
+ visitCallExpression(node) {
1071
+ const calleeType = this.visitNode(node.callee);
1072
+ node.arguments.forEach(arg => this.visitNode(arg));
1073
+ return 'any';
1074
+ }
1075
+
1076
+ visitIdentifier(node) {
1077
+ for (let i = this.scopes.length - 1; i >= 0; i--) {
1078
+ if (this.scopes[i].has(node.name)) {
1079
+ return this.scopes[i].get(node.name).type;
1080
+ }
1081
+ }
1082
+ return 'any';
1083
+ }
1084
+
1085
+ visitLiteral(node) {
1086
+ return this.typeSystem.inferType(node);
1087
+ }
1088
+
1089
+ visitIfStatement(node) {
1090
+ this.visitNode(node.test);
1091
+ this.visitNode(node.consequent);
1092
+ if (node.alternate) {
1093
+ this.visitNode(node.alternate);
1094
+ }
1095
+ }
1096
+
1097
+ visitForStatement(node) {
1098
+ this.scopes.push(new Map());
1099
+ this.visitNode(node.init);
1100
+ this.visitNode(node.test);
1101
+ this.visitNode(node.update);
1102
+ this.visitNode(node.body);
1103
+ this.scopes.pop();
1104
+ }
1105
+
1106
+ visitWhileStatement(node) {
1107
+ this.visitNode(node.test);
1108
+ this.visitNode(node.body);
1109
+ }
1110
+
1111
+ visitReturnStatement(node) {
1112
+ if (node.argument) {
1113
+ return this.visitNode(node.argument);
1114
+ }
1115
+ return 'void';
1116
+ }
1117
+ }
1118
+
1119
+ class IRGenerator {
1120
+ constructor(symbolTable) {
1121
+ this.symbolTable = symbolTable;
1122
+ this.instructions = [];
1123
+ this.nextTemp = 0;
1124
+ this.nextLabel = 0;
1125
+ }
1126
+
1127
+ generate(ast) {
1128
+ this.visitProgram(ast);
1129
+ return this.instructions;
1130
+ }
1131
+
1132
+ newTemp() {
1133
+ return `t${this.nextTemp++}`;
1134
+ }
1135
+
1136
+ newLabel() {
1137
+ return `L${this.nextLabel++}`;
1138
+ }
1139
+
1140
+ emit(op, arg1 = null, arg2 = null, result = null) {
1141
+ this.instructions.push({ op, arg1, arg2, result });
1142
+ }
1143
+
1144
+ visitProgram(node) {
1145
+ node.body.forEach(stmt => this.visitNode(stmt));
1146
+ }
1147
+
1148
+ visitNode(node) {
1149
+ const visitor = `visit${node.type}`;
1150
+ if (this[visitor]) {
1151
+ return this[visitor](node);
1152
+ }
1153
+ return null;
1154
+ }
1155
+
1156
+ visitVariableDeclaration(node) {
1157
+ node.declarations.forEach(decl => {
1158
+ if (decl.init) {
1159
+ const value = this.visitNode(decl.init);
1160
+ this.emit('assign', value, null, decl.id.name);
1161
+ }
1162
+ });
1163
+ }
1164
+
1165
+ visitFunctionDeclaration(node) {
1166
+ this.emit('function', node.id.name);
1167
+ node.params.forEach(param => {
1168
+ this.emit('param', param.name);
1169
+ });
1170
+ this.visitNode(node.body);
1171
+ this.emit('end_function');
1172
+ }
1173
+
1174
+ visitBlockStatement(node) {
1175
+ node.body.forEach(stmt => this.visitNode(stmt));
1176
+ }
1177
+
1178
+ visitExpressionStatement(node) {
1179
+ return this.visitNode(node.expression);
1180
+ }
1181
+
1182
+ visitBinaryExpression(node) {
1183
+ const left = this.visitNode(node.left);
1184
+ const right = this.visitNode(node.right);
1185
+ const result = this.newTemp();
1186
+ this.emit(node.operator, left, right, result);
1187
+ return result;
1188
+ }
1189
+
1190
+ visitCallExpression(node) {
1191
+ const args = node.arguments.map(arg => this.visitNode(arg));
1192
+ args.forEach(arg => {
1193
+ this.emit('push', arg);
1194
+ });
1195
+ const result = this.newTemp();
1196
+ this.emit('call', this.visitNode(node.callee), args.length, result);
1197
+ return result;
1198
+ }
1199
+
1200
+ visitIdentifier(node) {
1201
+ return node.name;
1202
+ }
1203
+
1204
+ visitLiteral(node) {
1205
+ return node.value;
1206
+ }
1207
+
1208
+ visitIfStatement(node) {
1209
+ const test = this.visitNode(node.test);
1210
+ const elseLabel = this.newLabel();
1211
+ const endLabel = this.newLabel();
1212
+
1213
+ this.emit('if_false', test, null, elseLabel);
1214
+ this.visitNode(node.consequent);
1215
+ this.emit('goto', null, null, endLabel);
1216
+
1217
+ this.emit('label', elseLabel);
1218
+ if (node.alternate) {
1219
+ this.visitNode(node.alternate);
1220
+ }
1221
+
1222
+ this.emit('label', endLabel);
1223
+ }
1224
+
1225
+ visitForStatement(node) {
1226
+ const startLabel = this.newLabel();
1227
+ const endLabel = this.newLabel();
1228
+
1229
+ this.visitNode(node.init);
1230
+ this.emit('label', startLabel);
1231
+
1232
+ const test = this.visitNode(node.test);
1233
+ this.emit('if_false', test, null, endLabel);
1234
+
1235
+ this.visitNode(node.body);
1236
+ this.visitNode(node.update);
1237
+ this.emit('goto', null, null, startLabel);
1238
+
1239
+ this.emit('label', endLabel);
1240
+ }
1241
+
1242
+ visitWhileStatement(node) {
1243
+ const startLabel = this.newLabel();
1244
+ const endLabel = this.newLabel();
1245
+
1246
+ this.emit('label', startLabel);
1247
+ const test = this.visitNode(node.test);
1248
+ this.emit('if_false', test, null, endLabel);
1249
+
1250
+ this.visitNode(node.body);
1251
+ this.emit('goto', null, null, startLabel);
1252
+
1253
+ this.emit('label', endLabel);
1254
+ }
1255
+
1256
+ visitReturnStatement(node) {
1257
+ if (node.argument) {
1258
+ const value = this.visitNode(node.argument);
1259
+ this.emit('return', value);
1260
+ } else {
1261
+ this.emit('return');
1262
+ }
1263
+ }
1264
+
1265
+ visitAssignmentExpression(node) {
1266
+ const value = this.visitNode(node.right);
1267
+ const target = node.left.name;
1268
+ this.emit('assign', value, null, target);
1269
+ return target;
1270
+ }
1271
+ }
1272
+
1273
+ class Optimizer {
1274
+ optimize(instructions) {
1275
+ let optimized = instructions;
1276
+ optimized = this.constantFolding(optimized);
1277
+ optimized = this.deadCodeElimination(optimized);
1278
+ optimized = this.commonSubexpressionElimination(optimized);
1279
+ return optimized;
1280
+ }
1281
+
1282
+ constantFolding(instructions) {
1283
+ return instructions.map(inst => {
1284
+ if (['+', '-', '*', '/', '%'].includes(inst.op)) {
1285
+ if (typeof inst.arg1 === 'number' && typeof inst.arg2 === 'number') {
1286
+ let value;
1287
+ switch (inst.op) {
1288
+ case '+': value = inst.arg1 + inst.arg2; break;
1289
+ case '-': value = inst.arg1 - inst.arg2; break;
1290
+ case '*': value = inst.arg1 * inst.arg2; break;
1291
+ case '/': value = inst.arg1 / inst.arg2; break;
1292
+ case '%': value = inst.arg1 % inst.arg2; break;
1293
+ }
1294
+ return { op: 'assign', arg1: value, arg2: null, result: inst.result };
1295
+ }
1296
+ }
1297
+ return inst;
1298
+ });
1299
+ }
1300
+
1301
+ deadCodeElimination(instructions) {
1302
+ const used = new Set();
1303
+ const labels = new Set();
1304
+
1305
+ instructions.forEach(inst => {
1306
+ if (inst.op === 'label' || inst.op === 'goto' || inst.op === 'if_false') {
1307
+ if (inst.result) labels.add(inst.result);
1308
+ if (inst.arg1 && typeof inst.arg1 === 'string') labels.add(inst.arg1);
1309
+ }
1310
+ });
1311
+
1312
+ for (let i = instructions.length - 1; i >= 0; i--) {
1313
+ const inst = instructions[i];
1314
+ if (inst.result) used.add(inst.result);
1315
+ if (inst.arg1 && typeof inst.arg1 === 'string') used.add(inst.arg1);
1316
+ if (inst.arg2 && typeof inst.arg2 === 'string') used.add(inst.arg2);
1317
+ }
1318
+
1319
+ return instructions.filter(inst => {
1320
+ if (inst.op === 'label') return labels.has(inst.arg1);
1321
+ if (!inst.result) return true;
1322
+ return used.has(inst.result);
1323
+ });
1324
+ }
1325
+
1326
+ commonSubexpressionElimination(instructions) {
1327
+ const expressions = new Map();
1328
+
1329
+ return instructions.map(inst => {
1330
+ if (['+', '-', '*', '/', '%'].includes(inst.op)) {
1331
+ const key = `${inst.op}:${inst.arg1}:${inst.arg2}`;
1332
+ if (expressions.has(key)) {
1333
+ return { op: 'assign', arg1: expressions.get(key), arg2: null, result: inst.result };
1334
+ }
1335
+ expressions.set(key, inst.result);
1336
+ }
1337
+ return inst;
1338
+ });
1339
+ }
1340
+ }
1341
+
1342
+ class CompilationError extends Error {
1343
+ constructor(message, originalError) {
1344
+ super(message);
1345
+ this.name = 'CompilationError';
1346
+ this.originalError = originalError;
1347
+ }
1348
+ }
1349
+
1350
+ module.exports = { LumosCompiler, Parser, TypeSystem, SemanticAnalyzer, IRGenerator, Optimizer, CompilationError };