naider 1.17.2 → 1.18.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.
- package/README.md +101 -2
- package/SPEC.naide +66 -0
- package/assets/naide.ico +0 -0
- package/assets/naide_check.png +0 -0
- package/assets/nx.ico +0 -0
- package/assets/nx_check.png +0 -0
- package/bin/generate-icons.js +169 -140
- package/bin/postinstall.js +4 -4
- package/lsp/server.js +26 -4
- package/package.json +1 -1
- package/src/generator-c.js +65 -0
- package/src/generator-cpp.js +78 -0
- package/src/generator-csharp.js +68 -0
- package/src/generator-dart.js +74 -0
- package/src/generator-go.js +62 -0
- package/src/generator-java.js +75 -0
- package/src/generator-kotlin.js +63 -0
- package/src/generator-php.js +61 -0
- package/src/generator-python.js +86 -0
- package/src/generator-ruby.js +54 -0
- package/src/generator-rust.js +74 -0
- package/src/generator-swift.js +67 -0
- package/src/generator.js +54 -0
- package/src/parser.js +63 -1
- package/src/tokens.js +7 -0
- package/vscode-naide/syntaxes/naide.tmLanguage.json +3 -3
package/src/generator-kotlin.js
CHANGED
|
@@ -139,6 +139,8 @@ export class KotlinGenerator {
|
|
|
139
139
|
case 'BlockchainDecl': return this.visitBlockchain(node);
|
|
140
140
|
case 'EnumDecl': return this.visitEnum(node);
|
|
141
141
|
case 'Swap': return this.visitSwap(node);
|
|
142
|
+
case 'Destructure': return this.visitDestructure(node);
|
|
143
|
+
case 'ClassDecl': return this.visitClassDecl(node);
|
|
142
144
|
default:
|
|
143
145
|
this.emit(`// unknown: ${node.type}`);
|
|
144
146
|
}
|
|
@@ -1840,6 +1842,60 @@ export class KotlinGenerator {
|
|
|
1840
1842
|
this.emit(`${a} = ${b}.also { ${b} = ${a} }`);
|
|
1841
1843
|
}
|
|
1842
1844
|
|
|
1845
|
+
visitDestructure(node) {
|
|
1846
|
+
const val = this.expr(node.value);
|
|
1847
|
+
const keyword = node.isMut ? 'var' : 'val';
|
|
1848
|
+
if (node.pattern === 'array') {
|
|
1849
|
+
const names = node.names.filter(n => !n.rest).map(n => n.alias || n.name);
|
|
1850
|
+
this.emit(`${keyword} (${names.join(', ')}) = ${val}`);
|
|
1851
|
+
} else {
|
|
1852
|
+
for (const n of node.names) {
|
|
1853
|
+
if (!n.rest) {
|
|
1854
|
+
const varName = n.alias || n.name;
|
|
1855
|
+
if (n.defaultValue) {
|
|
1856
|
+
this.emit(`${keyword} ${varName} = ${val}["${n.name}"] ?: ${this.expr(n.defaultValue)}`);
|
|
1857
|
+
} else {
|
|
1858
|
+
this.emit(`${keyword} ${varName} = ${val}["${n.name}"]`);
|
|
1859
|
+
}
|
|
1860
|
+
}
|
|
1861
|
+
}
|
|
1862
|
+
}
|
|
1863
|
+
}
|
|
1864
|
+
|
|
1865
|
+
visitClassDecl(node) {
|
|
1866
|
+
const ext = node.parent ? ` : ${node.parent}()` : '';
|
|
1867
|
+
const initParams = node.init ? node.init.params.map(p => `${p.name}: Any`).join(', ') : '';
|
|
1868
|
+
this.emit(`open class ${node.name}(${initParams})${ext} {`);
|
|
1869
|
+
this.indent++;
|
|
1870
|
+
for (const field of node.fields) {
|
|
1871
|
+
if (field.defaultValue) {
|
|
1872
|
+
this.emit(`var ${field.name} = ${this.expr(field.defaultValue)}`);
|
|
1873
|
+
}
|
|
1874
|
+
}
|
|
1875
|
+
if (node.init) {
|
|
1876
|
+
this.emit(`init {`);
|
|
1877
|
+
this.indent++;
|
|
1878
|
+
for (const stmt of node.init.body) this.visitStatement(stmt);
|
|
1879
|
+
this.indent--;
|
|
1880
|
+
this.emit(`}`);
|
|
1881
|
+
}
|
|
1882
|
+
for (const method of node.methods) {
|
|
1883
|
+
const params = method.params.map(p => `${p.name}: Any`).join(', ');
|
|
1884
|
+
this.emit(`fun ${method.name}(${params}): Any? {`);
|
|
1885
|
+
this.indent++;
|
|
1886
|
+
if (method.body.length === 0) {
|
|
1887
|
+
this.emit('return null');
|
|
1888
|
+
} else {
|
|
1889
|
+
for (const stmt of method.body) this.visitStatement(stmt);
|
|
1890
|
+
}
|
|
1891
|
+
this.indent--;
|
|
1892
|
+
this.emit('}');
|
|
1893
|
+
}
|
|
1894
|
+
this.indent--;
|
|
1895
|
+
this.emit('}');
|
|
1896
|
+
this.emitRaw('');
|
|
1897
|
+
}
|
|
1898
|
+
|
|
1843
1899
|
generateBuiltin(name, args) {
|
|
1844
1900
|
switch (name) {
|
|
1845
1901
|
case 'len': return `${args[0]}.size`;
|
|
@@ -1880,6 +1936,13 @@ export class KotlinGenerator {
|
|
|
1880
1936
|
case 'read': return `java.io.File(${args[0]}).readText()`;
|
|
1881
1937
|
case 'write': return `java.io.File(${args[0]}).writeText(${args[1]})`;
|
|
1882
1938
|
case 'ask': return `(print(${args[0] || '""'}); readLine() ?: "")`;
|
|
1939
|
+
case 'map': return `${args[0]}.map { ${args[1]}(it) }`;
|
|
1940
|
+
case 'filter': return `${args[0]}.filter { ${args[1]}(it) }`;
|
|
1941
|
+
case 'reduce': return args.length >= 3 ? `${args[0]}.fold(${args[2]}) { acc, it -> ${args[1]}(acc, it) }` : `${args[0]}.reduce { acc, it -> ${args[1]}(acc, it) }`;
|
|
1942
|
+
case 'find': return `${args[0]}.find { ${args[1]}(it) }`;
|
|
1943
|
+
case 'every': return `${args[0]}.all { ${args[1]}(it) }`;
|
|
1944
|
+
case 'some': return `${args[0]}.any { ${args[1]}(it) }`;
|
|
1945
|
+
case 'foreach': return `${args[0]}.forEach { ${args[1]}(it) }`;
|
|
1883
1946
|
default: return null;
|
|
1884
1947
|
}
|
|
1885
1948
|
}
|
package/src/generator-php.js
CHANGED
|
@@ -105,6 +105,8 @@ export class PhpGenerator {
|
|
|
105
105
|
case 'BlockchainDecl': return this.visitBlockchain(node);
|
|
106
106
|
case 'EnumDecl': return this.visitEnum(node);
|
|
107
107
|
case 'Swap': return this.visitSwap(node);
|
|
108
|
+
case 'Destructure': return this.visitDestructure(node);
|
|
109
|
+
case 'ClassDecl': return this.visitClassDecl(node);
|
|
108
110
|
default:
|
|
109
111
|
this.emit(`/* unknown: ${node.type} */`);
|
|
110
112
|
}
|
|
@@ -1599,6 +1601,58 @@ export class PhpGenerator {
|
|
|
1599
1601
|
this.emit(`[$${a.replace('$','')}, $${b.replace('$','')}] = [$${b.replace('$','')}, $${a.replace('$','')}];`);
|
|
1600
1602
|
}
|
|
1601
1603
|
|
|
1604
|
+
visitDestructure(node) {
|
|
1605
|
+
const val = this.expr(node.value);
|
|
1606
|
+
if (node.pattern === 'array') {
|
|
1607
|
+
const names = node.names.map(n => {
|
|
1608
|
+
if (n.rest) return `...$${n.name}`;
|
|
1609
|
+
return `$${n.alias || n.name}`;
|
|
1610
|
+
});
|
|
1611
|
+
this.emit(`[${names.join(', ')}] = ${val};`);
|
|
1612
|
+
} else {
|
|
1613
|
+
const parts = node.names.filter(n => !n.rest).map(n => {
|
|
1614
|
+
const varName = n.alias || n.name;
|
|
1615
|
+
return `'${n.name}' => $${varName}`;
|
|
1616
|
+
});
|
|
1617
|
+
this.emit(`[${parts.join(', ')}] = ${val};`);
|
|
1618
|
+
}
|
|
1619
|
+
}
|
|
1620
|
+
|
|
1621
|
+
visitClassDecl(node) {
|
|
1622
|
+
const ext = node.parent ? ` extends ${node.parent}` : '';
|
|
1623
|
+
this.emit(`class ${node.name}${ext} {`);
|
|
1624
|
+
this.indent++;
|
|
1625
|
+
for (const field of node.fields) {
|
|
1626
|
+
if (field.defaultValue) {
|
|
1627
|
+
this.emit(`public $${field.name} = ${this.expr(field.defaultValue)};`);
|
|
1628
|
+
}
|
|
1629
|
+
}
|
|
1630
|
+
if (node.init) {
|
|
1631
|
+
const params = node.init.params.map(p => `$${p.name}`).join(', ');
|
|
1632
|
+
this.emit(`public function __construct(${params}) {`);
|
|
1633
|
+
this.indent++;
|
|
1634
|
+
if (node.parent) this.emit('parent::__construct();');
|
|
1635
|
+
for (const stmt of node.init.body) this.visitStatement(stmt);
|
|
1636
|
+
this.indent--;
|
|
1637
|
+
this.emit('}');
|
|
1638
|
+
}
|
|
1639
|
+
for (const method of node.methods) {
|
|
1640
|
+
const params = method.params.map(p => `$${p.name}`).join(', ');
|
|
1641
|
+
this.emit(`public function ${method.name}(${params}) {`);
|
|
1642
|
+
this.indent++;
|
|
1643
|
+
if (method.body.length === 0) {
|
|
1644
|
+
this.emit('// empty');
|
|
1645
|
+
} else {
|
|
1646
|
+
for (const stmt of method.body) this.visitStatement(stmt);
|
|
1647
|
+
}
|
|
1648
|
+
this.indent--;
|
|
1649
|
+
this.emit('}');
|
|
1650
|
+
}
|
|
1651
|
+
this.indent--;
|
|
1652
|
+
this.emit('}');
|
|
1653
|
+
this.emitRaw('');
|
|
1654
|
+
}
|
|
1655
|
+
|
|
1602
1656
|
generateBuiltin(name, args) {
|
|
1603
1657
|
switch (name) {
|
|
1604
1658
|
case 'len': return `count(${args[0]})`;
|
|
@@ -1639,6 +1693,13 @@ export class PhpGenerator {
|
|
|
1639
1693
|
case 'ask': return `readline(${args[0] || '""'})`;
|
|
1640
1694
|
case 'chunk': return `array_chunk(${args[0]}, ${args[1]})`;
|
|
1641
1695
|
case 'zip': return `array_map(null, ${args[0]}, ${args[1]})`;
|
|
1696
|
+
case 'map': return `array_map(${args[1]}, ${args[0]})`;
|
|
1697
|
+
case 'filter': return `array_values(array_filter(${args[0]}, ${args[1]}))`;
|
|
1698
|
+
case 'reduce': return `array_reduce(${args[0]}, ${args[1]}, ${args[2] || 'null'})`;
|
|
1699
|
+
case 'find': return `current(array_filter(${args[0]}, ${args[1]}))`;
|
|
1700
|
+
case 'every': return `count(array_filter(${args[0]}, ${args[1]})) === count(${args[0]})`;
|
|
1701
|
+
case 'some': return `count(array_filter(${args[0]}, ${args[1]})) > 0`;
|
|
1702
|
+
case 'foreach': return `array_walk(${args[0]}, ${args[1]})`;
|
|
1642
1703
|
default: return null;
|
|
1643
1704
|
}
|
|
1644
1705
|
}
|
package/src/generator-python.js
CHANGED
|
@@ -164,6 +164,8 @@ export class PythonGenerator {
|
|
|
164
164
|
case 'BlockchainDecl': return this.visitBlockchain(node);
|
|
165
165
|
case 'EnumDecl': return this.visitEnum(node);
|
|
166
166
|
case 'Swap': return this.visitSwap(node);
|
|
167
|
+
case 'Destructure': return this.visitDestructure(node);
|
|
168
|
+
case 'ClassDecl': return this.visitClassDecl(node);
|
|
167
169
|
default:
|
|
168
170
|
this.emit(`# unknown: ${node.type}`);
|
|
169
171
|
}
|
|
@@ -2494,6 +2496,83 @@ export class PythonGenerator {
|
|
|
2494
2496
|
this.emit(`${a}, ${b} = ${b}, ${a}`);
|
|
2495
2497
|
}
|
|
2496
2498
|
|
|
2499
|
+
// ===== Destructure =====
|
|
2500
|
+
visitDestructure(node) {
|
|
2501
|
+
const val = this.expr(node.value);
|
|
2502
|
+
if (node.pattern === 'array') {
|
|
2503
|
+
const names = node.names.map(n => {
|
|
2504
|
+
if (n.rest) return `*${n.name}`;
|
|
2505
|
+
return n.name;
|
|
2506
|
+
});
|
|
2507
|
+
this.emit(`${names.join(', ')} = ${val}`);
|
|
2508
|
+
// Handle defaults for array destructuring
|
|
2509
|
+
for (const n of node.names) {
|
|
2510
|
+
if (n.defaultValue && !n.rest) {
|
|
2511
|
+
this.emit(`${n.name} = ${n.name} if ${n.name} is not None else ${this.expr(n.defaultValue)}`);
|
|
2512
|
+
}
|
|
2513
|
+
}
|
|
2514
|
+
} else {
|
|
2515
|
+
// object destructuring — per-field assignment
|
|
2516
|
+
for (const n of node.names) {
|
|
2517
|
+
if (n.rest) {
|
|
2518
|
+
this.emit(`${n.name} = {k: v for k, v in ${val}.items() if k not in {${node.names.filter(x => !x.rest).map(x => JSON.stringify(x.name)).join(', ')}}}`);
|
|
2519
|
+
} else {
|
|
2520
|
+
const varName = n.alias || n.name;
|
|
2521
|
+
if (n.defaultValue) {
|
|
2522
|
+
this.emit(`${varName} = ${val}.get(${JSON.stringify(n.name)}, ${this.expr(n.defaultValue)})`);
|
|
2523
|
+
} else {
|
|
2524
|
+
this.emit(`${varName} = ${val}[${JSON.stringify(n.name)}]`);
|
|
2525
|
+
}
|
|
2526
|
+
}
|
|
2527
|
+
}
|
|
2528
|
+
}
|
|
2529
|
+
}
|
|
2530
|
+
|
|
2531
|
+
// ===== ClassDecl =====
|
|
2532
|
+
visitClassDecl(node) {
|
|
2533
|
+
const ext = node.parent ? `(${node.parent})` : '';
|
|
2534
|
+
this.emit(`class ${node.name}${ext}:`);
|
|
2535
|
+
this.indent++;
|
|
2536
|
+
if (node.init) {
|
|
2537
|
+
const params = node.init.params.map(p => p.name).join(', ');
|
|
2538
|
+
const selfParams = params ? `self, ${params}` : 'self';
|
|
2539
|
+
this.emit(`def __init__(${selfParams}):`);
|
|
2540
|
+
this.indent++;
|
|
2541
|
+
if (node.parent) this.emit('super().__init__()');
|
|
2542
|
+
if (node.init.body.length === 0 && !node.parent) {
|
|
2543
|
+
this.emit('pass');
|
|
2544
|
+
} else {
|
|
2545
|
+
for (const stmt of node.init.body) this.visitStatement(stmt);
|
|
2546
|
+
}
|
|
2547
|
+
this.indent--;
|
|
2548
|
+
this.emitRaw('');
|
|
2549
|
+
}
|
|
2550
|
+
for (const field of node.fields) {
|
|
2551
|
+
if (field.defaultValue) {
|
|
2552
|
+
this.emit(`${field.name} = ${this.expr(field.defaultValue)}`);
|
|
2553
|
+
}
|
|
2554
|
+
}
|
|
2555
|
+
for (const method of node.methods) {
|
|
2556
|
+
const async = method.isAsync ? 'async ' : '';
|
|
2557
|
+
const params = method.params.map(p => p.name).join(', ');
|
|
2558
|
+
const selfParams = params ? `self, ${params}` : 'self';
|
|
2559
|
+
this.emit(`${async}def ${method.name}(${selfParams}):`);
|
|
2560
|
+
this.indent++;
|
|
2561
|
+
if (method.body.length === 0) {
|
|
2562
|
+
this.emit('pass');
|
|
2563
|
+
} else {
|
|
2564
|
+
for (const stmt of method.body) this.visitStatement(stmt);
|
|
2565
|
+
}
|
|
2566
|
+
this.indent--;
|
|
2567
|
+
this.emitRaw('');
|
|
2568
|
+
}
|
|
2569
|
+
if (!node.init && node.fields.length === 0 && node.methods.length === 0) {
|
|
2570
|
+
this.emit('pass');
|
|
2571
|
+
}
|
|
2572
|
+
this.indent--;
|
|
2573
|
+
this.emitRaw('');
|
|
2574
|
+
}
|
|
2575
|
+
|
|
2497
2576
|
// ===== Builtins =====
|
|
2498
2577
|
generateBuiltin(name, args) {
|
|
2499
2578
|
switch (name) {
|
|
@@ -2536,6 +2615,13 @@ export class PythonGenerator {
|
|
|
2536
2615
|
case 'now': { this.addImport('time'); return `int(time.time() * 1000)`; }
|
|
2537
2616
|
case 'time': { this.addFromImport('datetime', 'datetime'); return `datetime.now().isoformat()`; }
|
|
2538
2617
|
case 'chunk': return `[${args[0]}[i:i+${args[1]}] for i in range(0, len(${args[0]}), ${args[1]})]`;
|
|
2618
|
+
case 'map': return `list(map(${args[1]}, ${args[0]}))`;
|
|
2619
|
+
case 'filter': return `list(filter(${args[1]}, ${args[0]}))`;
|
|
2620
|
+
case 'reduce': { this.addFromImport('functools', 'reduce'); return args[2] ? `reduce(${args[1]}, ${args[0]}, ${args[2]})` : `reduce(${args[1]}, ${args[0]})`; }
|
|
2621
|
+
case 'find': return `next((x for x in ${args[0]} if ${args[1]}(x)), None)`;
|
|
2622
|
+
case 'every': return `all(${args[1]}(x) for x in ${args[0]})`;
|
|
2623
|
+
case 'some': return `any(${args[1]}(x) for x in ${args[0]})`;
|
|
2624
|
+
case 'foreach': return `[${args[1]}(x) for x in ${args[0]}]`;
|
|
2539
2625
|
default: return null;
|
|
2540
2626
|
}
|
|
2541
2627
|
}
|
package/src/generator-ruby.js
CHANGED
|
@@ -113,6 +113,8 @@ export class RubyGenerator {
|
|
|
113
113
|
case 'BlockchainDecl': return this.visitBlockchain(node);
|
|
114
114
|
case 'EnumDecl': return this.visitEnum(node);
|
|
115
115
|
case 'Swap': return this.visitSwap(node);
|
|
116
|
+
case 'Destructure': return this.visitDestructure(node);
|
|
117
|
+
case 'ClassDecl': return this.visitClassDecl(node);
|
|
116
118
|
default:
|
|
117
119
|
this.emit(`# unknown: ${node.type}`);
|
|
118
120
|
}
|
|
@@ -1553,6 +1555,51 @@ export class RubyGenerator {
|
|
|
1553
1555
|
this.emit(`${a}, ${b} = ${b}, ${a}`);
|
|
1554
1556
|
}
|
|
1555
1557
|
|
|
1558
|
+
visitDestructure(node) {
|
|
1559
|
+
const val = this.expr(node.value);
|
|
1560
|
+
if (node.pattern === 'array') {
|
|
1561
|
+
const names = node.names.map(n => {
|
|
1562
|
+
if (n.rest) return `*${n.name}`;
|
|
1563
|
+
return n.alias || n.name;
|
|
1564
|
+
});
|
|
1565
|
+
this.emit(`${names.join(', ')} = ${val}`);
|
|
1566
|
+
} else {
|
|
1567
|
+
const keys = node.names.filter(n => !n.rest).map(n => `:${n.name}`);
|
|
1568
|
+
const vars = node.names.filter(n => !n.rest).map(n => n.alias || n.name);
|
|
1569
|
+
this.emit(`${vars.join(', ')} = ${val}.values_at(${keys.join(', ')})`);
|
|
1570
|
+
}
|
|
1571
|
+
}
|
|
1572
|
+
|
|
1573
|
+
visitClassDecl(node) {
|
|
1574
|
+
const ext = node.parent ? ` < ${node.parent}` : '';
|
|
1575
|
+
this.emit(`class ${node.name}${ext}`);
|
|
1576
|
+
this.indent++;
|
|
1577
|
+
if (node.init) {
|
|
1578
|
+
const params = node.init.params.map(p => p.name).join(', ');
|
|
1579
|
+
this.emit(`def initialize(${params})`);
|
|
1580
|
+
this.indent++;
|
|
1581
|
+
if (node.parent) this.emit('super()');
|
|
1582
|
+
for (const stmt of node.init.body) this.visitStatement(stmt);
|
|
1583
|
+
this.indent--;
|
|
1584
|
+
this.emit('end');
|
|
1585
|
+
}
|
|
1586
|
+
for (const method of node.methods) {
|
|
1587
|
+
const params = method.params.map(p => p.name).join(', ');
|
|
1588
|
+
this.emit(`def ${method.name}(${params})`);
|
|
1589
|
+
this.indent++;
|
|
1590
|
+
if (method.body.length === 0) {
|
|
1591
|
+
this.emit('nil');
|
|
1592
|
+
} else {
|
|
1593
|
+
for (const stmt of method.body) this.visitStatement(stmt);
|
|
1594
|
+
}
|
|
1595
|
+
this.indent--;
|
|
1596
|
+
this.emit('end');
|
|
1597
|
+
}
|
|
1598
|
+
this.indent--;
|
|
1599
|
+
this.emit('end');
|
|
1600
|
+
this.emitRaw('');
|
|
1601
|
+
}
|
|
1602
|
+
|
|
1556
1603
|
generateBuiltin(name, args) {
|
|
1557
1604
|
switch (name) {
|
|
1558
1605
|
case 'len': return `${args[0]}.length`;
|
|
@@ -1593,6 +1640,13 @@ export class RubyGenerator {
|
|
|
1593
1640
|
case 'read': return `File.read(${args[0]})`;
|
|
1594
1641
|
case 'write': return `File.write(${args[0]}, ${args[1]})`;
|
|
1595
1642
|
case 'ask': return `(print(${args[0] || '""'}); gets.chomp)`;
|
|
1643
|
+
case 'map': return `${args[0]}.map { |_x| ${args[1]}.call(_x) }`;
|
|
1644
|
+
case 'filter': return `${args[0]}.select { |_x| ${args[1]}.call(_x) }`;
|
|
1645
|
+
case 'reduce': return args.length >= 3 ? `${args[0]}.reduce(${args[2]}) { |_acc, _x| ${args[1]}.call(_acc, _x) }` : `${args[0]}.reduce { |_acc, _x| ${args[1]}.call(_acc, _x) }`;
|
|
1646
|
+
case 'find': return `${args[0]}.find { |_x| ${args[1]}.call(_x) }`;
|
|
1647
|
+
case 'every': return `${args[0]}.all? { |_x| ${args[1]}.call(_x) }`;
|
|
1648
|
+
case 'some': return `${args[0]}.any? { |_x| ${args[1]}.call(_x) }`;
|
|
1649
|
+
case 'foreach': return `${args[0]}.each { |_x| ${args[1]}.call(_x) }`;
|
|
1596
1650
|
default: return null;
|
|
1597
1651
|
}
|
|
1598
1652
|
}
|
package/src/generator-rust.js
CHANGED
|
@@ -209,6 +209,8 @@ export class RustGenerator {
|
|
|
209
209
|
case 'BlockchainDecl': return this.visitBlockchain(node);
|
|
210
210
|
case 'EnumDecl': return this.visitEnum(node);
|
|
211
211
|
case 'Swap': return this.visitSwap(node);
|
|
212
|
+
case 'Destructure': return this.visitDestructure(node);
|
|
213
|
+
case 'ClassDecl': return this.visitClassDecl(node);
|
|
212
214
|
default:
|
|
213
215
|
this.emit(`/* unknown: ${node.type} */`);
|
|
214
216
|
}
|
|
@@ -1911,6 +1913,71 @@ export class RustGenerator {
|
|
|
1911
1913
|
this.emit(`std::mem::swap(&mut ${a}, &mut ${b});`);
|
|
1912
1914
|
}
|
|
1913
1915
|
|
|
1916
|
+
visitDestructure(node) {
|
|
1917
|
+
const val = this.expr(node.value);
|
|
1918
|
+
const keyword = node.isMut ? 'let mut' : 'let';
|
|
1919
|
+
if (node.pattern === 'array') {
|
|
1920
|
+
const names = node.names.filter(n => !n.rest).map(n => n.alias || n.name);
|
|
1921
|
+
const indexedVals = names.map((name, i) => `${val}[${i}]`);
|
|
1922
|
+
this.emit(`${keyword} (${names.join(', ')}) = (${indexedVals.join(', ')});`);
|
|
1923
|
+
} else {
|
|
1924
|
+
for (const n of node.names) {
|
|
1925
|
+
if (!n.rest) {
|
|
1926
|
+
const varName = n.alias || n.name;
|
|
1927
|
+
if (n.defaultValue) {
|
|
1928
|
+
this.emit(`${keyword} ${varName} = ${val}.get("${n.name}").unwrap_or(&${this.expr(n.defaultValue)});`);
|
|
1929
|
+
} else {
|
|
1930
|
+
this.emit(`${keyword} ${varName} = ${val}["${n.name}"];`);
|
|
1931
|
+
}
|
|
1932
|
+
}
|
|
1933
|
+
}
|
|
1934
|
+
}
|
|
1935
|
+
}
|
|
1936
|
+
|
|
1937
|
+
visitClassDecl(node) {
|
|
1938
|
+
// Rust uses struct + impl
|
|
1939
|
+
this.emit(`struct ${node.name} {`);
|
|
1940
|
+
this.indent++;
|
|
1941
|
+
for (const field of node.fields) {
|
|
1942
|
+
this.emit(`${field.name}: Box<dyn std::any::Any>,`);
|
|
1943
|
+
}
|
|
1944
|
+
if (node.fields.length === 0) this.emit(`_marker: (),`);
|
|
1945
|
+
this.indent--;
|
|
1946
|
+
this.emit(`}`);
|
|
1947
|
+
this.emitRaw('');
|
|
1948
|
+
this.emit(`impl ${node.name} {`);
|
|
1949
|
+
this.indent++;
|
|
1950
|
+
if (node.init) {
|
|
1951
|
+
const params = node.init.params.map(p => `${p.name}: impl std::any::Any`).join(', ');
|
|
1952
|
+
this.emit(`fn new(${params}) -> Self {`);
|
|
1953
|
+
this.indent++;
|
|
1954
|
+
for (const stmt of node.init.body) this.visitStatement(stmt);
|
|
1955
|
+
if (node.fields.length > 0) {
|
|
1956
|
+
this.emit(`${node.name} { ${node.fields.map(f => f.name).join(', ')} }`);
|
|
1957
|
+
} else {
|
|
1958
|
+
this.emit(`${node.name} { _marker: () }`);
|
|
1959
|
+
}
|
|
1960
|
+
this.indent--;
|
|
1961
|
+
this.emit(`}`);
|
|
1962
|
+
}
|
|
1963
|
+
for (const method of node.methods) {
|
|
1964
|
+
const mutable = method.body.some(s => JSON.stringify(s).includes('"Assignment"')) ? '&mut self' : '&self';
|
|
1965
|
+
const params = method.params.length > 0 ? `, ${method.params.map(p => `${p.name}: impl std::any::Any`).join(', ')}` : '';
|
|
1966
|
+
this.emit(`fn ${method.name}(${mutable}${params}) {`);
|
|
1967
|
+
this.indent++;
|
|
1968
|
+
if (method.body.length === 0) {
|
|
1969
|
+
this.emit('// empty');
|
|
1970
|
+
} else {
|
|
1971
|
+
for (const stmt of method.body) this.visitStatement(stmt);
|
|
1972
|
+
}
|
|
1973
|
+
this.indent--;
|
|
1974
|
+
this.emit(`}`);
|
|
1975
|
+
}
|
|
1976
|
+
this.indent--;
|
|
1977
|
+
this.emit(`}`);
|
|
1978
|
+
this.emitRaw('');
|
|
1979
|
+
}
|
|
1980
|
+
|
|
1914
1981
|
generateBuiltin(name, args) {
|
|
1915
1982
|
switch (name) {
|
|
1916
1983
|
case 'len': return `${args[0]}.len()`;
|
|
@@ -1942,6 +2009,13 @@ export class RustGenerator {
|
|
|
1942
2009
|
case 'values': return `${args[0]}.values().cloned().collect::<Vec<_>>()`;
|
|
1943
2010
|
case 'range': return args.length >= 2 ? `(${args[0]}..${args[1]}).collect::<Vec<_>>()` : `(0..${args[0]}).collect::<Vec<_>>()`;
|
|
1944
2011
|
case 'flat': return `${args[0]}.into_iter().flatten().collect::<Vec<_>>()`;
|
|
2012
|
+
case 'map': return `${args[0]}.iter().map(${args[1]}).collect::<Vec<_>>()`;
|
|
2013
|
+
case 'filter': return `${args[0]}.iter().filter(${args[1]}).collect::<Vec<_>>()`;
|
|
2014
|
+
case 'reduce': return `${args[0]}.iter().fold(${args[2] || '0'}, ${args[1]})`;
|
|
2015
|
+
case 'find': return `${args[0]}.iter().find(${args[1]})`;
|
|
2016
|
+
case 'every': return `${args[0]}.iter().all(${args[1]})`;
|
|
2017
|
+
case 'some': return `${args[0]}.iter().any(${args[1]})`;
|
|
2018
|
+
case 'foreach': return `${args[0]}.iter().for_each(${args[1]})`;
|
|
1945
2019
|
default: return null;
|
|
1946
2020
|
}
|
|
1947
2021
|
}
|
package/src/generator-swift.js
CHANGED
|
@@ -141,6 +141,8 @@ export class SwiftGenerator {
|
|
|
141
141
|
case 'BlockchainDecl': return this.visitBlockchain(node);
|
|
142
142
|
case 'EnumDecl': return this.visitEnum(node);
|
|
143
143
|
case 'Swap': return this.visitSwap(node);
|
|
144
|
+
case 'Destructure': return this.visitDestructure(node);
|
|
145
|
+
case 'ClassDecl': return this.visitClassDecl(node);
|
|
144
146
|
default:
|
|
145
147
|
this.emit(`// unknown: ${node.type}`);
|
|
146
148
|
}
|
|
@@ -1758,6 +1760,64 @@ export class SwiftGenerator {
|
|
|
1758
1760
|
this.emit(`swap(&${a}, &${b})`);
|
|
1759
1761
|
}
|
|
1760
1762
|
|
|
1763
|
+
visitDestructure(node) {
|
|
1764
|
+
const val = this.expr(node.value);
|
|
1765
|
+
const keyword = node.isMut ? 'var' : 'let';
|
|
1766
|
+
if (node.pattern === 'array') {
|
|
1767
|
+
const names = node.names.filter(n => !n.rest).map(n => n.alias || n.name);
|
|
1768
|
+
const indexedVals = names.map((name, i) => `${val}[${i}]`);
|
|
1769
|
+
this.emit(`${keyword} (${names.join(', ')}) = (${indexedVals.join(', ')})`);
|
|
1770
|
+
} else {
|
|
1771
|
+
for (const n of node.names) {
|
|
1772
|
+
if (!n.rest) {
|
|
1773
|
+
const varName = n.alias || n.name;
|
|
1774
|
+
if (n.defaultValue) {
|
|
1775
|
+
this.emit(`${keyword} ${varName} = ${val}["${n.name}"] ?? ${this.expr(n.defaultValue)}`);
|
|
1776
|
+
} else {
|
|
1777
|
+
this.emit(`${keyword} ${varName} = ${val}["${n.name}"]`);
|
|
1778
|
+
}
|
|
1779
|
+
}
|
|
1780
|
+
}
|
|
1781
|
+
}
|
|
1782
|
+
}
|
|
1783
|
+
|
|
1784
|
+
visitClassDecl(node) {
|
|
1785
|
+
const ext = node.parent ? `: ${node.parent}` : '';
|
|
1786
|
+
this.emit(`class ${node.name}${ext ? ' ' + ext : ''} {`);
|
|
1787
|
+
this.indent++;
|
|
1788
|
+
for (const field of node.fields) {
|
|
1789
|
+
if (field.defaultValue) {
|
|
1790
|
+
this.emit(`var ${field.name}: Any = ${this.expr(field.defaultValue)}`);
|
|
1791
|
+
} else {
|
|
1792
|
+
this.emit(`var ${field.name}: Any?`);
|
|
1793
|
+
}
|
|
1794
|
+
}
|
|
1795
|
+
if (node.init) {
|
|
1796
|
+
const params = node.init.params.map(p => `_ ${p.name}: Any`).join(', ');
|
|
1797
|
+
this.emit(`init(${params}) {`);
|
|
1798
|
+
this.indent++;
|
|
1799
|
+
if (node.parent) this.emit('super.init()');
|
|
1800
|
+
for (const stmt of node.init.body) this.visitStatement(stmt);
|
|
1801
|
+
this.indent--;
|
|
1802
|
+
this.emit('}');
|
|
1803
|
+
}
|
|
1804
|
+
for (const method of node.methods) {
|
|
1805
|
+
const params = method.params.map(p => `_ ${p.name}: Any`).join(', ');
|
|
1806
|
+
this.emit(`func ${method.name}(${params}) -> Any? {`);
|
|
1807
|
+
this.indent++;
|
|
1808
|
+
if (method.body.length === 0) {
|
|
1809
|
+
this.emit('return nil');
|
|
1810
|
+
} else {
|
|
1811
|
+
for (const stmt of method.body) this.visitStatement(stmt);
|
|
1812
|
+
}
|
|
1813
|
+
this.indent--;
|
|
1814
|
+
this.emit('}');
|
|
1815
|
+
}
|
|
1816
|
+
this.indent--;
|
|
1817
|
+
this.emit('}');
|
|
1818
|
+
this.emitRaw('');
|
|
1819
|
+
}
|
|
1820
|
+
|
|
1761
1821
|
generateBuiltin(name, args) {
|
|
1762
1822
|
switch (name) {
|
|
1763
1823
|
case 'len': return `${args[0]}.count`;
|
|
@@ -1796,6 +1856,13 @@ export class SwiftGenerator {
|
|
|
1796
1856
|
case 'random': return args.length >= 2 ? `Int.random(in: ${args[0]}...${args[1]})` : `Double.random(in: 0...1)`;
|
|
1797
1857
|
case 'read': return `try! String(contentsOfFile: ${args[0]})`;
|
|
1798
1858
|
case 'write': return `try! ${args[1]}.write(toFile: ${args[0]}, atomically: true, encoding: .utf8)`;
|
|
1859
|
+
case 'map': return `${args[0]}.map { ${args[1]}($0) }`;
|
|
1860
|
+
case 'filter': return `${args[0]}.filter { ${args[1]}($0) }`;
|
|
1861
|
+
case 'reduce': return `${args[0]}.reduce(${args[2] || '0'}) { ${args[1]}($0, $1) }`;
|
|
1862
|
+
case 'find': return `${args[0]}.first { ${args[1]}($0) }`;
|
|
1863
|
+
case 'every': return `${args[0]}.allSatisfy { ${args[1]}($0) }`;
|
|
1864
|
+
case 'some': return `${args[0]}.contains { ${args[1]}($0) }`;
|
|
1865
|
+
case 'foreach': return `${args[0]}.forEach { ${args[1]}($0) }`;
|
|
1799
1866
|
default: return null;
|
|
1800
1867
|
}
|
|
1801
1868
|
}
|
package/src/generator.js
CHANGED
|
@@ -94,6 +94,8 @@ export class Generator {
|
|
|
94
94
|
case 'ReturnStatus': return this.visitReturnStatus(node);
|
|
95
95
|
case 'ReturnMethod': return this.visitReturnMethod(node);
|
|
96
96
|
case 'TypedVar': return this.visitTypedVar(node);
|
|
97
|
+
case 'Destructure': return this.visitDestructure(node);
|
|
98
|
+
case 'ClassDecl': return this.visitClassDecl(node);
|
|
97
99
|
case 'If': return this.visitIf(node);
|
|
98
100
|
case 'Each': return this.visitEach(node);
|
|
99
101
|
case 'For': return this.visitFor(node);
|
|
@@ -244,6 +246,51 @@ export class Generator {
|
|
|
244
246
|
this.emit(`${exp}${keyword} ${node.name} = ${this.expr(node.value)};`);
|
|
245
247
|
}
|
|
246
248
|
|
|
249
|
+
visitDestructure(node) {
|
|
250
|
+
const keyword = node.isMut ? 'let' : 'const';
|
|
251
|
+
const parts = node.names.map(n => {
|
|
252
|
+
if (n.rest) return `...${n.name}`;
|
|
253
|
+
let s = n.name;
|
|
254
|
+
if (n.alias) s += `: ${n.alias}`;
|
|
255
|
+
if (n.defaultValue) s += ` = ${this.expr(n.defaultValue)}`;
|
|
256
|
+
return s;
|
|
257
|
+
});
|
|
258
|
+
const open = node.pattern === 'object' ? '{ ' : '[ ';
|
|
259
|
+
const close = node.pattern === 'object' ? ' }' : ' ]';
|
|
260
|
+
this.emit(`${keyword} ${open}${parts.join(', ')}${close} = ${this.expr(node.value)};`);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
visitClassDecl(node) {
|
|
264
|
+
const ext = node.parent ? ` extends ${node.parent}` : '';
|
|
265
|
+
this.emit(`class ${node.name}${ext} {`);
|
|
266
|
+
this.indent++;
|
|
267
|
+
if (node.init) {
|
|
268
|
+
const params = node.init.params.map(p => p.name).join(', ');
|
|
269
|
+
this.emit(`constructor(${params}) {`);
|
|
270
|
+
this.indent++;
|
|
271
|
+
if (node.parent) this.emit('super();');
|
|
272
|
+
for (const stmt of node.init.body) this.visitStatement(stmt);
|
|
273
|
+
this.indent--;
|
|
274
|
+
this.emit('}');
|
|
275
|
+
}
|
|
276
|
+
for (const field of node.fields) {
|
|
277
|
+
if (field.defaultValue) {
|
|
278
|
+
this.emit(`${field.name} = ${this.expr(field.defaultValue)};`);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
for (const method of node.methods) {
|
|
282
|
+
const async = method.isAsync ? 'async ' : '';
|
|
283
|
+
const params = method.params.map(p => p.name).join(', ');
|
|
284
|
+
this.emit(`${async}${method.name}(${params}) {`);
|
|
285
|
+
this.indent++;
|
|
286
|
+
for (const stmt of method.body) this.visitStatement(stmt);
|
|
287
|
+
this.indent--;
|
|
288
|
+
this.emit('}');
|
|
289
|
+
}
|
|
290
|
+
this.indent--;
|
|
291
|
+
this.emit('}');
|
|
292
|
+
}
|
|
293
|
+
|
|
247
294
|
visitAssignment(node) {
|
|
248
295
|
const target = this.expr(node.target);
|
|
249
296
|
const value = this.expr(node.value);
|
|
@@ -2464,6 +2511,13 @@ export class Generator {
|
|
|
2464
2511
|
case 'now': return `Date.now()`;
|
|
2465
2512
|
case 'time': return `new Date().toISOString()`;
|
|
2466
2513
|
case 'chunk': return `Array.from({length: Math.ceil(${args[0]}.length / ${args[1]})}, (_, i) => ${args[0]}.slice(i * ${args[1]}, (i + 1) * ${args[1]}))`;
|
|
2514
|
+
case 'map': return `${args[0]}.map(${args[1]})`;
|
|
2515
|
+
case 'filter': return `${args[0]}.filter(${args[1]})`;
|
|
2516
|
+
case 'reduce': return args[2] ? `${args[0]}.reduce(${args[1]}, ${args[2]})` : `${args[0]}.reduce(${args[1]})`;
|
|
2517
|
+
case 'find': return `${args[0]}.find(${args[1]})`;
|
|
2518
|
+
case 'every': return `${args[0]}.every(${args[1]})`;
|
|
2519
|
+
case 'some': return `${args[0]}.some(${args[1]})`;
|
|
2520
|
+
case 'foreach': return `${args[0]}.forEach(${args[1]})`;
|
|
2467
2521
|
default: return null;
|
|
2468
2522
|
}
|
|
2469
2523
|
}
|