naider 1.17.4 → 1.19.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/lsp/server.js +26 -4
- package/mcp/server.js +222 -0
- package/package.json +4 -2
- 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-cpp.js
CHANGED
|
@@ -188,6 +188,8 @@ export class CppGenerator {
|
|
|
188
188
|
case 'BlockchainDecl': return this.visitBlockchain(node);
|
|
189
189
|
case 'EnumDecl': return this.visitEnum(node);
|
|
190
190
|
case 'Swap': return this.visitSwap(node);
|
|
191
|
+
case 'Destructure': return this.visitDestructure(node);
|
|
192
|
+
case 'ClassDecl': return this.visitClassDecl(node);
|
|
191
193
|
default:
|
|
192
194
|
this.emit(`/* unknown: ${node.type} */`);
|
|
193
195
|
}
|
|
@@ -1233,6 +1235,75 @@ export class CppGenerator {
|
|
|
1233
1235
|
this.emit(`std::swap(${a}, ${b});`);
|
|
1234
1236
|
}
|
|
1235
1237
|
|
|
1238
|
+
visitDestructure(node) {
|
|
1239
|
+
const val = this.expr(node.value);
|
|
1240
|
+
if (node.pattern === 'array') {
|
|
1241
|
+
if (node.names.every(n => !n.rest && !n.defaultValue)) {
|
|
1242
|
+
this.includes.add('<tuple>');
|
|
1243
|
+
const names = node.names.map(n => n.alias || n.name).join(', ');
|
|
1244
|
+
this.emit(`auto [${names}] = ${val};`);
|
|
1245
|
+
} else {
|
|
1246
|
+
node.names.forEach((n, i) => {
|
|
1247
|
+
if (!n.rest) {
|
|
1248
|
+
const varName = n.alias || n.name;
|
|
1249
|
+
if (n.defaultValue) {
|
|
1250
|
+
this.emit(`auto ${varName} = (${i} < ${val}.size()) ? ${val}[${i}] : ${this.expr(n.defaultValue)};`);
|
|
1251
|
+
} else {
|
|
1252
|
+
this.emit(`auto ${varName} = ${val}[${i}];`);
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
});
|
|
1256
|
+
}
|
|
1257
|
+
} else {
|
|
1258
|
+
for (const n of node.names) {
|
|
1259
|
+
if (!n.rest) {
|
|
1260
|
+
const varName = n.alias || n.name;
|
|
1261
|
+
if (n.defaultValue) {
|
|
1262
|
+
this.emit(`auto ${varName} = ${val}.count("${n.name}") ? ${val}["${n.name}"] : ${this.expr(n.defaultValue)};`);
|
|
1263
|
+
} else {
|
|
1264
|
+
this.emit(`auto ${varName} = ${val}["${n.name}"];`);
|
|
1265
|
+
}
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
|
|
1271
|
+
visitClassDecl(node) {
|
|
1272
|
+
const ext = node.parent ? ` : public ${node.parent}` : '';
|
|
1273
|
+
this.emit(`class ${node.name}${ext} {`);
|
|
1274
|
+
this.emit(`public:`);
|
|
1275
|
+
this.indent++;
|
|
1276
|
+
for (const field of node.fields) {
|
|
1277
|
+
if (field.defaultValue) {
|
|
1278
|
+
this.emit(`auto ${field.name} = ${this.expr(field.defaultValue)};`);
|
|
1279
|
+
}
|
|
1280
|
+
}
|
|
1281
|
+
if (node.init) {
|
|
1282
|
+
const params = node.init.params.map(p => `auto ${p.name}`).join(', ');
|
|
1283
|
+
this.emit(`${node.name}(${params}) {`);
|
|
1284
|
+
this.indent++;
|
|
1285
|
+
if (node.parent) this.emit(`${node.parent}();`);
|
|
1286
|
+
for (const stmt of node.init.body) this.visitStatement(stmt);
|
|
1287
|
+
this.indent--;
|
|
1288
|
+
this.emit('}');
|
|
1289
|
+
}
|
|
1290
|
+
for (const method of node.methods) {
|
|
1291
|
+
const params = method.params.map(p => `auto ${p.name}`).join(', ');
|
|
1292
|
+
this.emit(`auto ${method.name}(${params}) {`);
|
|
1293
|
+
this.indent++;
|
|
1294
|
+
if (method.body.length === 0) {
|
|
1295
|
+
this.emit('return 0;');
|
|
1296
|
+
} else {
|
|
1297
|
+
for (const stmt of method.body) this.visitStatement(stmt);
|
|
1298
|
+
}
|
|
1299
|
+
this.indent--;
|
|
1300
|
+
this.emit('}');
|
|
1301
|
+
}
|
|
1302
|
+
this.indent--;
|
|
1303
|
+
this.emit('};');
|
|
1304
|
+
this.emitRaw('');
|
|
1305
|
+
}
|
|
1306
|
+
|
|
1236
1307
|
generateBuiltin(name, args) {
|
|
1237
1308
|
switch (name) {
|
|
1238
1309
|
case 'len': return `${args[0]}.size()`;
|
|
@@ -1258,6 +1329,13 @@ export class CppGenerator {
|
|
|
1258
1329
|
case 'now': { this.includes.add('<chrono>'); return `std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count()`; }
|
|
1259
1330
|
case 'random': { this.includes.add('<random>'); return args.length >= 2 ? `([](int a, int b){ std::random_device rd; std::mt19937 gen(rd()); std::uniform_int_distribution<> dis(a,b); return dis(gen); })(${args[0]}, ${args[1]})` : `([]{ std::random_device rd; return rd(); }())`; }
|
|
1260
1331
|
case 'sum': return `([&](){ auto _v = ${args[0]}; return std::accumulate(_v.begin(), _v.end(), 0); }())`;
|
|
1332
|
+
case 'map': { this.includes.add('<algorithm>'); return `([&](){ auto _v = ${args[0]}; std::vector<decltype(${args[1]}(_v[0]))> _r; std::transform(_v.begin(), _v.end(), std::back_inserter(_r), ${args[1]}); return _r; }())`; }
|
|
1333
|
+
case 'filter': { this.includes.add('<algorithm>'); return `([&](){ auto _v = ${args[0]}; decltype(_v) _r; std::copy_if(_v.begin(), _v.end(), std::back_inserter(_r), ${args[1]}); return _r; }())`; }
|
|
1334
|
+
case 'reduce': { this.includes.add('<numeric>'); return `std::accumulate(${args[0]}.begin(), ${args[0]}.end(), ${args[2] || '0'}, ${args[1]})`; }
|
|
1335
|
+
case 'find': { this.includes.add('<algorithm>'); return `(*std::find_if(${args[0]}.begin(), ${args[0]}.end(), ${args[1]}))`; }
|
|
1336
|
+
case 'every': { this.includes.add('<algorithm>'); return `std::all_of(${args[0]}.begin(), ${args[0]}.end(), ${args[1]})`; }
|
|
1337
|
+
case 'some': { this.includes.add('<algorithm>'); return `std::any_of(${args[0]}.begin(), ${args[0]}.end(), ${args[1]})`; }
|
|
1338
|
+
case 'foreach': { this.includes.add('<algorithm>'); return `std::for_each(${args[0]}.begin(), ${args[0]}.end(), ${args[1]})`; }
|
|
1261
1339
|
default: return null;
|
|
1262
1340
|
}
|
|
1263
1341
|
}
|
package/src/generator-csharp.js
CHANGED
|
@@ -180,6 +180,8 @@ export class CSharpGenerator {
|
|
|
180
180
|
case 'BlockchainDecl': return this.visitBlockchain(node);
|
|
181
181
|
case 'EnumDecl': return this.visitEnum(node);
|
|
182
182
|
case 'Swap': return this.visitSwap(node);
|
|
183
|
+
case 'Destructure': return this.visitDestructure(node);
|
|
184
|
+
case 'ClassDecl': return this.visitClassDecl(node);
|
|
183
185
|
default:
|
|
184
186
|
this.emit(`// unknown: ${node.type}`);
|
|
185
187
|
}
|
|
@@ -1654,6 +1656,65 @@ export class CSharpGenerator {
|
|
|
1654
1656
|
this.emit(`(${a}, ${b}) = (${b}, ${a});`);
|
|
1655
1657
|
}
|
|
1656
1658
|
|
|
1659
|
+
visitDestructure(node) {
|
|
1660
|
+
const val = this.expr(node.value);
|
|
1661
|
+
if (node.pattern === 'array') {
|
|
1662
|
+
const names = node.names.filter(n => !n.rest).map(n => n.alias || n.name);
|
|
1663
|
+
const indexedVals = names.map((name, i) => `${val}[${i}]`);
|
|
1664
|
+
this.emit(`var (${names.join(', ')}) = (${indexedVals.join(', ')});`);
|
|
1665
|
+
} else {
|
|
1666
|
+
for (const n of node.names) {
|
|
1667
|
+
if (!n.rest) {
|
|
1668
|
+
const varName = n.alias || n.name;
|
|
1669
|
+
if (n.defaultValue) {
|
|
1670
|
+
this.emit(`var ${varName} = ${val}.ContainsKey("${n.name}") ? ${val}["${n.name}"] : ${this.expr(n.defaultValue)};`);
|
|
1671
|
+
} else {
|
|
1672
|
+
this.emit(`var ${varName} = ${val}["${n.name}"];`);
|
|
1673
|
+
}
|
|
1674
|
+
}
|
|
1675
|
+
}
|
|
1676
|
+
}
|
|
1677
|
+
}
|
|
1678
|
+
|
|
1679
|
+
visitClassDecl(node) {
|
|
1680
|
+
const ext = node.parent ? ` : ${node.parent}` : '';
|
|
1681
|
+
this.emit(`class ${node.name}${ext} {`);
|
|
1682
|
+
this.indent++;
|
|
1683
|
+
for (const field of node.fields) {
|
|
1684
|
+
if (field.defaultValue) {
|
|
1685
|
+
this.emit(`public dynamic ${field.name} = ${this.expr(field.defaultValue)};`);
|
|
1686
|
+
} else {
|
|
1687
|
+
this.emit(`public dynamic ${field.name};`);
|
|
1688
|
+
}
|
|
1689
|
+
}
|
|
1690
|
+
if (node.init) {
|
|
1691
|
+
const params = node.init.params.map(p => `dynamic ${p.name}`).join(', ');
|
|
1692
|
+
const baseCall = node.parent ? ' : base()' : '';
|
|
1693
|
+
this.emit(`public ${node.name}(${params})${baseCall} {`);
|
|
1694
|
+
this.indent++;
|
|
1695
|
+
for (const stmt of node.init.body) this.visitStatement(stmt);
|
|
1696
|
+
this.indent--;
|
|
1697
|
+
this.emit('}');
|
|
1698
|
+
}
|
|
1699
|
+
for (const method of node.methods) {
|
|
1700
|
+
const params = method.params.map(p => `dynamic ${p.name}`).join(', ');
|
|
1701
|
+
const asyncKw = method.isAsync ? 'async ' : '';
|
|
1702
|
+
const returnType = method.isAsync ? 'async Task<dynamic>' : 'dynamic';
|
|
1703
|
+
this.emit(`public ${returnType} ${method.name}(${params}) {`);
|
|
1704
|
+
this.indent++;
|
|
1705
|
+
if (method.body.length === 0) {
|
|
1706
|
+
this.emit('return null;');
|
|
1707
|
+
} else {
|
|
1708
|
+
for (const stmt of method.body) this.visitStatement(stmt);
|
|
1709
|
+
}
|
|
1710
|
+
this.indent--;
|
|
1711
|
+
this.emit('}');
|
|
1712
|
+
}
|
|
1713
|
+
this.indent--;
|
|
1714
|
+
this.emit('}');
|
|
1715
|
+
this.emitRaw('');
|
|
1716
|
+
}
|
|
1717
|
+
|
|
1657
1718
|
generateBuiltin(name, args) {
|
|
1658
1719
|
switch (name) {
|
|
1659
1720
|
case 'len': return `${args[0]}.Count`;
|
|
@@ -1694,6 +1755,13 @@ export class CSharpGenerator {
|
|
|
1694
1755
|
case 'read': return `File.ReadAllText(${args[0]})`;
|
|
1695
1756
|
case 'write': return `File.WriteAllText(${args[0]}, ${args[1]})`;
|
|
1696
1757
|
case 'ask': return `(Console.Write(${args[0] || '""'}), Console.ReadLine() ?? "").Item2`;
|
|
1758
|
+
case 'map': return `${args[0]}.Select(x => ${args[1]}(x)).ToList()`;
|
|
1759
|
+
case 'filter': return `${args[0]}.Where(x => ${args[1]}(x)).ToList()`;
|
|
1760
|
+
case 'reduce': return `${args[0]}.Aggregate(${args[2] || '0'}, (acc, x) => ${args[1]}(acc, x))`;
|
|
1761
|
+
case 'find': return `${args[0]}.FirstOrDefault(x => ${args[1]}(x))`;
|
|
1762
|
+
case 'every': return `${args[0]}.All(x => ${args[1]}(x))`;
|
|
1763
|
+
case 'some': return `${args[0]}.Any(x => ${args[1]}(x))`;
|
|
1764
|
+
case 'foreach': return `${args[0]}.ForEach(x => ${args[1]}(x))`;
|
|
1697
1765
|
default: return null;
|
|
1698
1766
|
}
|
|
1699
1767
|
}
|
package/src/generator-dart.js
CHANGED
|
@@ -164,6 +164,8 @@ export class DartGenerator {
|
|
|
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
|
}
|
|
@@ -1592,6 +1594,71 @@ export class DartGenerator {
|
|
|
1592
1594
|
this.emit(`{ final _tmp = ${a}; ${a} = ${b}; ${b} = _tmp; }`);
|
|
1593
1595
|
}
|
|
1594
1596
|
|
|
1597
|
+
visitDestructure(node) {
|
|
1598
|
+
const val = this.expr(node.value);
|
|
1599
|
+
const keyword = node.isMut ? 'var' : 'final';
|
|
1600
|
+
if (node.pattern === 'array') {
|
|
1601
|
+
node.names.forEach((n, i) => {
|
|
1602
|
+
if (!n.rest) {
|
|
1603
|
+
const varName = n.alias || n.name;
|
|
1604
|
+
this.emit(`${keyword} ${varName} = ${val}[${i}];`);
|
|
1605
|
+
} else {
|
|
1606
|
+
this.emit(`${keyword} ${n.name} = ${val}.sublist(${i});`);
|
|
1607
|
+
}
|
|
1608
|
+
});
|
|
1609
|
+
} else {
|
|
1610
|
+
for (const n of node.names) {
|
|
1611
|
+
if (!n.rest) {
|
|
1612
|
+
const varName = n.alias || n.name;
|
|
1613
|
+
if (n.defaultValue) {
|
|
1614
|
+
this.emit(`${keyword} ${varName} = ${val}['${n.name}'] ?? ${this.expr(n.defaultValue)};`);
|
|
1615
|
+
} else {
|
|
1616
|
+
this.emit(`${keyword} ${varName} = ${val}['${n.name}'];`);
|
|
1617
|
+
}
|
|
1618
|
+
}
|
|
1619
|
+
}
|
|
1620
|
+
}
|
|
1621
|
+
}
|
|
1622
|
+
|
|
1623
|
+
visitClassDecl(node) {
|
|
1624
|
+
const ext = node.parent ? ` extends ${node.parent}` : '';
|
|
1625
|
+
this.emit(`class ${node.name}${ext} {`);
|
|
1626
|
+
this.indent++;
|
|
1627
|
+
for (const field of node.fields) {
|
|
1628
|
+
if (field.defaultValue) {
|
|
1629
|
+
this.emit(`var ${field.name} = ${this.expr(field.defaultValue)};`);
|
|
1630
|
+
} else {
|
|
1631
|
+
this.emit(`dynamic ${field.name};`);
|
|
1632
|
+
}
|
|
1633
|
+
}
|
|
1634
|
+
if (node.init) {
|
|
1635
|
+
const params = node.init.params.map(p => `dynamic ${p.name}`).join(', ');
|
|
1636
|
+
this.emit(`${node.name}(${params}) {`);
|
|
1637
|
+
this.indent++;
|
|
1638
|
+
if (node.parent) this.emit('super();');
|
|
1639
|
+
for (const stmt of node.init.body) this.visitStatement(stmt);
|
|
1640
|
+
this.indent--;
|
|
1641
|
+
this.emit('}');
|
|
1642
|
+
}
|
|
1643
|
+
for (const method of node.methods) {
|
|
1644
|
+
const params = method.params.map(p => `dynamic ${p.name}`).join(', ');
|
|
1645
|
+
const asyncKw = method.isAsync ? 'async ' : '';
|
|
1646
|
+
const returnType = method.isAsync ? 'Future<dynamic>' : 'dynamic';
|
|
1647
|
+
this.emit(`${returnType} ${method.name}(${params}) ${asyncKw}{`);
|
|
1648
|
+
this.indent++;
|
|
1649
|
+
if (method.body.length === 0) {
|
|
1650
|
+
this.emit('return null;');
|
|
1651
|
+
} else {
|
|
1652
|
+
for (const stmt of method.body) this.visitStatement(stmt);
|
|
1653
|
+
}
|
|
1654
|
+
this.indent--;
|
|
1655
|
+
this.emit('}');
|
|
1656
|
+
}
|
|
1657
|
+
this.indent--;
|
|
1658
|
+
this.emit('}');
|
|
1659
|
+
this.emitRaw('');
|
|
1660
|
+
}
|
|
1661
|
+
|
|
1595
1662
|
generateBuiltin(name, args) {
|
|
1596
1663
|
switch (name) {
|
|
1597
1664
|
case 'len': return `${args[0]}.length`;
|
|
@@ -1632,6 +1699,13 @@ export class DartGenerator {
|
|
|
1632
1699
|
case 'read': { this.addImport('dart:io'); return `File(${args[0]}).readAsStringSync()`; }
|
|
1633
1700
|
case 'write': { this.addImport('dart:io'); return `File(${args[0]}).writeAsStringSync(${args[1]})`; }
|
|
1634
1701
|
case 'ask': { this.addImport('dart:io'); return `((){stdout.write(${args[0] || '""'}); return stdin.readLineSync() ?? "";}())`; }
|
|
1702
|
+
case 'map': return `${args[0]}.map((e) => ${args[1]}(e)).toList()`;
|
|
1703
|
+
case 'filter': return `${args[0]}.where((e) => ${args[1]}(e)).toList()`;
|
|
1704
|
+
case 'reduce': return `${args[0]}.fold(${args[2] || 'null'}, (acc, e) => ${args[1]}(acc, e))`;
|
|
1705
|
+
case 'find': return `${args[0]}.firstWhere((e) => ${args[1]}(e), orElse: () => null)`;
|
|
1706
|
+
case 'every': return `${args[0]}.every((e) => ${args[1]}(e))`;
|
|
1707
|
+
case 'some': return `${args[0]}.any((e) => ${args[1]}(e))`;
|
|
1708
|
+
case 'foreach': return `${args[0]}.forEach((e) => ${args[1]}(e))`;
|
|
1635
1709
|
default: return null;
|
|
1636
1710
|
}
|
|
1637
1711
|
}
|
package/src/generator-go.js
CHANGED
|
@@ -118,6 +118,8 @@ export class GoGenerator {
|
|
|
118
118
|
case 'BlockchainDecl': return this.visitBlockchain(node);
|
|
119
119
|
case 'EnumDecl': return this.visitEnum(node);
|
|
120
120
|
case 'Swap': return this.visitSwap(node);
|
|
121
|
+
case 'Destructure': return this.visitDestructure(node);
|
|
122
|
+
case 'ClassDecl': return this.visitClassDecl(node);
|
|
121
123
|
default:
|
|
122
124
|
this.emit(`// unknown: ${node.type}`);
|
|
123
125
|
}
|
|
@@ -1809,6 +1811,59 @@ export class GoGenerator {
|
|
|
1809
1811
|
this.emit(`${a}, ${b} = ${b}, ${a}`);
|
|
1810
1812
|
}
|
|
1811
1813
|
|
|
1814
|
+
visitDestructure(node) {
|
|
1815
|
+
const val = this.expr(node.value);
|
|
1816
|
+
if (node.pattern === 'array') {
|
|
1817
|
+
const names = node.names.filter(n => !n.rest).map(n => n.alias || n.name);
|
|
1818
|
+
const indexedVals = names.map((name, i) => `${val}[${i}]`);
|
|
1819
|
+
this.emit(`${names.join(', ')} := ${indexedVals.join(', ')}`);
|
|
1820
|
+
} else {
|
|
1821
|
+
for (const n of node.names) {
|
|
1822
|
+
if (!n.rest) {
|
|
1823
|
+
const varName = n.alias || n.name;
|
|
1824
|
+
this.emit(`${varName} := ${val}["${n.name}"]`);
|
|
1825
|
+
}
|
|
1826
|
+
}
|
|
1827
|
+
}
|
|
1828
|
+
}
|
|
1829
|
+
|
|
1830
|
+
visitClassDecl(node) {
|
|
1831
|
+
// Go uses struct + methods
|
|
1832
|
+
this.emit(`type ${node.name} struct {`);
|
|
1833
|
+
this.indent++;
|
|
1834
|
+
if (node.parent) this.emit(`${node.parent}`);
|
|
1835
|
+
for (const field of node.fields) {
|
|
1836
|
+
this.emit(`${field.name.charAt(0).toUpperCase() + field.name.slice(1)} interface{}`);
|
|
1837
|
+
}
|
|
1838
|
+
this.indent--;
|
|
1839
|
+
this.emit(`}`);
|
|
1840
|
+
this.emitRaw('');
|
|
1841
|
+
if (node.init) {
|
|
1842
|
+
const params = node.init.params.map(p => `${p.name} interface{}`).join(', ');
|
|
1843
|
+
this.emit(`func New${node.name}(${params}) *${node.name} {`);
|
|
1844
|
+
this.indent++;
|
|
1845
|
+
this.emit(`self := &${node.name}{}`);
|
|
1846
|
+
for (const stmt of node.init.body) this.visitStatement(stmt);
|
|
1847
|
+
this.emit(`return self`);
|
|
1848
|
+
this.indent--;
|
|
1849
|
+
this.emit(`}`);
|
|
1850
|
+
this.emitRaw('');
|
|
1851
|
+
}
|
|
1852
|
+
for (const method of node.methods) {
|
|
1853
|
+
const params = method.params.map(p => `${p.name} interface{}`).join(', ');
|
|
1854
|
+
this.emit(`func (self *${node.name}) ${method.name.charAt(0).toUpperCase() + method.name.slice(1)}(${params}) interface{} {`);
|
|
1855
|
+
this.indent++;
|
|
1856
|
+
if (method.body.length === 0) {
|
|
1857
|
+
this.emit('return nil');
|
|
1858
|
+
} else {
|
|
1859
|
+
for (const stmt of method.body) this.visitStatement(stmt);
|
|
1860
|
+
}
|
|
1861
|
+
this.indent--;
|
|
1862
|
+
this.emit(`}`);
|
|
1863
|
+
this.emitRaw('');
|
|
1864
|
+
}
|
|
1865
|
+
}
|
|
1866
|
+
|
|
1812
1867
|
generateBuiltin(name, args) {
|
|
1813
1868
|
switch (name) {
|
|
1814
1869
|
case 'len': return `len(${args[0]})`;
|
|
@@ -1837,6 +1892,13 @@ export class GoGenerator {
|
|
|
1837
1892
|
case 'random': { this.addImport('math/rand'); return args.length >= 2 ? `rand.Intn(${args[1]}-${args[0]}+1)+${args[0]}` : `rand.Float64()`; }
|
|
1838
1893
|
case 'sort': { this.addImport('sort'); return `func() []int { s := make([]int, len(${args[0]})); copy(s, ${args[0]}); sort.Ints(s); return s }()`; }
|
|
1839
1894
|
case 'reverse': return `func() []interface{} { s := make([]interface{}, len(${args[0]})); copy(s, ${args[0]}); for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 { s[i], s[j] = s[j], s[i] }; return s }()`;
|
|
1895
|
+
case 'map': return `func() []interface{} { _r := make([]interface{}, len(${args[0]})); for _i, _v := range ${args[0]} { _r[_i] = ${args[1]}(_v) }; return _r }()`;
|
|
1896
|
+
case 'filter': return `func() []interface{} { var _r []interface{}; for _, _v := range ${args[0]} { if ${args[1]}(_v) { _r = append(_r, _v) } }; return _r }()`;
|
|
1897
|
+
case 'reduce': return `func() interface{} { _acc := ${args[2] || '0'}; for _, _v := range ${args[0]} { _acc = ${args[1]}(_acc, _v) }; return _acc }()`;
|
|
1898
|
+
case 'find': return `func() interface{} { for _, _v := range ${args[0]} { if ${args[1]}(_v) { return _v } }; return nil }()`;
|
|
1899
|
+
case 'every': return `func() bool { for _, _v := range ${args[0]} { if !${args[1]}(_v) { return false } }; return true }()`;
|
|
1900
|
+
case 'some': return `func() bool { for _, _v := range ${args[0]} { if ${args[1]}(_v) { return true } }; return false }()`;
|
|
1901
|
+
case 'foreach': return `func() { for _, _v := range ${args[0]} { ${args[1]}(_v) } }()`;
|
|
1840
1902
|
default: return null;
|
|
1841
1903
|
}
|
|
1842
1904
|
}
|
package/src/generator-java.js
CHANGED
|
@@ -228,6 +228,8 @@ export class JavaGenerator {
|
|
|
228
228
|
case 'BlockchainDecl': return this.visitBlockchain(node);
|
|
229
229
|
case 'EnumDecl': return this.visitEnum(node);
|
|
230
230
|
case 'Swap': return this.visitSwap(node);
|
|
231
|
+
case 'Destructure': return this.visitDestructure(node);
|
|
232
|
+
case 'ClassDecl': return this.visitClassDecl(node);
|
|
231
233
|
default:
|
|
232
234
|
this.emit(`/* unknown: ${node.type} */`);
|
|
233
235
|
}
|
|
@@ -1835,6 +1837,72 @@ export class JavaGenerator {
|
|
|
1835
1837
|
this.emit(`{ var _tmp = ${a}; ${a} = ${b}; ${b} = _tmp; }`);
|
|
1836
1838
|
}
|
|
1837
1839
|
|
|
1840
|
+
visitDestructure(node) {
|
|
1841
|
+
const val = this.expr(node.value);
|
|
1842
|
+
if (node.pattern === 'array') {
|
|
1843
|
+
node.names.forEach((n, i) => {
|
|
1844
|
+
if (n.rest) {
|
|
1845
|
+
this.emit(`var ${n.name} = ${val}.subList(${i}, ${val}.size());`);
|
|
1846
|
+
} else {
|
|
1847
|
+
const varName = n.alias || n.name;
|
|
1848
|
+
if (n.defaultValue) {
|
|
1849
|
+
this.emit(`var ${varName} = ${i} < ${val}.size() ? ${val}.get(${i}) : ${this.expr(n.defaultValue)};`);
|
|
1850
|
+
} else {
|
|
1851
|
+
this.emit(`var ${varName} = ${val}.get(${i});`);
|
|
1852
|
+
}
|
|
1853
|
+
}
|
|
1854
|
+
});
|
|
1855
|
+
} else {
|
|
1856
|
+
for (const n of node.names) {
|
|
1857
|
+
if (n.rest) {
|
|
1858
|
+
this.emit(`var ${n.name} = new java.util.HashMap<>(${val}); ${node.names.filter(x => !x.rest).forEach(x => `${n.name}.remove(${JSON.stringify(x.name)})`)};`);
|
|
1859
|
+
} else {
|
|
1860
|
+
const varName = n.alias || n.name;
|
|
1861
|
+
if (n.defaultValue) {
|
|
1862
|
+
this.emit(`var ${varName} = ${val}.getOrDefault(${JSON.stringify(n.name)}, ${this.expr(n.defaultValue)});`);
|
|
1863
|
+
} else {
|
|
1864
|
+
this.emit(`var ${varName} = ${val}.get(${JSON.stringify(n.name)});`);
|
|
1865
|
+
}
|
|
1866
|
+
}
|
|
1867
|
+
}
|
|
1868
|
+
}
|
|
1869
|
+
}
|
|
1870
|
+
|
|
1871
|
+
visitClassDecl(node) {
|
|
1872
|
+
const ext = node.parent ? ` extends ${node.parent}` : '';
|
|
1873
|
+
this.emit(`static class ${node.name}${ext} {`);
|
|
1874
|
+
this.indent++;
|
|
1875
|
+
for (const field of node.fields) {
|
|
1876
|
+
if (field.defaultValue) {
|
|
1877
|
+
this.emit(`Object ${field.name} = ${this.expr(field.defaultValue)};`);
|
|
1878
|
+
}
|
|
1879
|
+
}
|
|
1880
|
+
if (node.init) {
|
|
1881
|
+
const params = node.init.params.map(p => `Object ${p.name}`).join(', ');
|
|
1882
|
+
this.emit(`${node.name}(${params}) {`);
|
|
1883
|
+
this.indent++;
|
|
1884
|
+
if (node.parent) this.emit('super();');
|
|
1885
|
+
for (const stmt of node.init.body) this.visitStatement(stmt);
|
|
1886
|
+
this.indent--;
|
|
1887
|
+
this.emit('}');
|
|
1888
|
+
}
|
|
1889
|
+
for (const method of node.methods) {
|
|
1890
|
+
const params = method.params.map(p => `Object ${p.name}`).join(', ');
|
|
1891
|
+
this.emit(`Object ${method.name}(${params}) {`);
|
|
1892
|
+
this.indent++;
|
|
1893
|
+
if (method.body.length === 0) {
|
|
1894
|
+
this.emit('return null;');
|
|
1895
|
+
} else {
|
|
1896
|
+
for (const stmt of method.body) this.visitStatement(stmt);
|
|
1897
|
+
}
|
|
1898
|
+
this.indent--;
|
|
1899
|
+
this.emit('}');
|
|
1900
|
+
}
|
|
1901
|
+
this.indent--;
|
|
1902
|
+
this.emit('}');
|
|
1903
|
+
this.emitRaw('');
|
|
1904
|
+
}
|
|
1905
|
+
|
|
1838
1906
|
generateBuiltin(name, args) {
|
|
1839
1907
|
switch (name) {
|
|
1840
1908
|
case 'len': return `${args[0]}.size()`;
|
|
@@ -1869,6 +1937,13 @@ export class JavaGenerator {
|
|
|
1869
1937
|
case 'json_parse': return `new com.google.gson.Gson().fromJson(${args[0]}, Object.class)`;
|
|
1870
1938
|
case 'json_str': return `new com.google.gson.Gson().toJson(${args[0]})`;
|
|
1871
1939
|
case 'range': return args.length >= 2 ? `java.util.stream.IntStream.range(${args[0]}, ${args[1]}).boxed().collect(java.util.stream.Collectors.toList())` : `java.util.stream.IntStream.range(0, ${args[0]}).boxed().collect(java.util.stream.Collectors.toList())`;
|
|
1940
|
+
case 'map': { this.addImport('java.util.stream.Collectors'); return `${args[0]}.stream().map(${args[1]}).collect(Collectors.toList())`; }
|
|
1941
|
+
case 'filter': { this.addImport('java.util.stream.Collectors'); return `${args[0]}.stream().filter(${args[1]}).collect(Collectors.toList())`; }
|
|
1942
|
+
case 'reduce': return args[2] ? `${args[0]}.stream().reduce(${args[2]}, ${args[1]})` : `${args[0]}.stream().reduce(${args[1]}).orElse(null)`;
|
|
1943
|
+
case 'find': return `${args[0]}.stream().filter(${args[1]}).findFirst().orElse(null)`;
|
|
1944
|
+
case 'every': return `${args[0]}.stream().allMatch(${args[1]})`;
|
|
1945
|
+
case 'some': return `${args[0]}.stream().anyMatch(${args[1]})`;
|
|
1946
|
+
case 'foreach': return `${args[0]}.forEach(${args[1]})`;
|
|
1872
1947
|
default: return null;
|
|
1873
1948
|
}
|
|
1874
1949
|
}
|
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
|
}
|