naider 1.15.0 → 1.17.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.
@@ -162,6 +162,8 @@ export class DartGenerator {
162
162
  case 'GrpcDecl': return this.visitGrpc(node);
163
163
  case 'WebrtcDecl': return this.visitWebrtc(node);
164
164
  case 'BlockchainDecl': return this.visitBlockchain(node);
165
+ case 'EnumDecl': return this.visitEnum(node);
166
+ case 'Swap': return this.visitSwap(node);
165
167
  default:
166
168
  this.emit(`// unknown: ${node.type}`);
167
169
  }
@@ -1364,6 +1366,12 @@ export class DartGenerator {
1364
1366
  generateCall(node) {
1365
1367
  const args = node.args.map(a => this.expr(a)).join(', ');
1366
1368
 
1369
+ if (node.callee.type === 'Identifier') {
1370
+ const argList = node.args.map(a => this.expr(a));
1371
+ const b = this.generateBuiltin(node.callee.name, argList);
1372
+ if (b) return b;
1373
+ }
1374
+
1367
1375
  if (node.callee.type === 'Identifier') {
1368
1376
  const name = node.callee.name;
1369
1377
  if (name === 'parseInt') return `int.parse(${args})`;
@@ -1566,4 +1574,65 @@ export class DartGenerator {
1566
1574
  this.inFunction = wasInFunction;
1567
1575
  return result;
1568
1576
  }
1577
+
1578
+ visitEnum(node) {
1579
+ this.emit(`enum ${node.name} {`);
1580
+ this.indent++;
1581
+ node.values.forEach(v => {
1582
+ this.emit(`${v.toLowerCase()},`);
1583
+ });
1584
+ this.indent--;
1585
+ this.emit(`}`);
1586
+ this.emitRaw('');
1587
+ }
1588
+
1589
+ visitSwap(node) {
1590
+ const a = this.expr(node.a);
1591
+ const b = this.expr(node.b);
1592
+ this.emit(`{ final _tmp = ${a}; ${a} = ${b}; ${b} = _tmp; }`);
1593
+ }
1594
+
1595
+ generateBuiltin(name, args) {
1596
+ switch (name) {
1597
+ case 'len': return `${args[0]}.length`;
1598
+ case 'sort': return `(List.from(${args[0]})..sort())`;
1599
+ case 'reverse': return `${args[0]}.reversed.toList()`;
1600
+ case 'unique': return `${args[0]}.toSet().toList()`;
1601
+ case 'upper': return `${args[0]}.toUpperCase()`;
1602
+ case 'lower': return `${args[0]}.toLowerCase()`;
1603
+ case 'trim': return `${args[0]}.trim()`;
1604
+ case 'split': return `${args[0]}.split(${args[1] || '","'})`;
1605
+ case 'join': return `${args[0]}.join(${args[1] || '","'})`;
1606
+ case 'contains': return `${args[0]}.contains(${args[1]})`;
1607
+ case 'replace': return `${args[0]}.replaceAll(${args[1]}, ${args[2]})`;
1608
+ case 'keys': return `${args[0]}.keys.toList()`;
1609
+ case 'values': return `${args[0]}.values.toList()`;
1610
+ case 'entries': return `${args[0]}.entries.toList()`;
1611
+ case 'range': return args.length >= 2 ? `List.generate(${args[1]} - ${args[0]}, (i) => i + ${args[0]})` : `List.generate(${args[0]}, (i) => i)`;
1612
+ case 'abs': return `${args[0]}.abs()`;
1613
+ case 'sqrt': { this.addImport('dart:math'); return `sqrt(${args[0]}.toDouble())`; }
1614
+ case 'pow': { this.addImport('dart:math'); return `pow(${args[0]}, ${args[1]})`; }
1615
+ case 'ceil': return `${args[0]}.ceil()`;
1616
+ case 'floor': return `${args[0]}.floor()`;
1617
+ case 'round': return `${args[0]}.round()`;
1618
+ case 'sum': return `${args[0]}.reduce((a, b) => a + b)`;
1619
+ case 'flat': return `${args[0]}.expand((x) => x).toList()`;
1620
+ case 'zip': return `List.generate(${args[0]}.length, (i) => [${args[0]}[i], ${args[1]}[i]])`;
1621
+ case 'chunk': return `[for (var i = 0; i < ${args[0]}.length; i += ${args[1]}) ${args[0]}.sublist(i, i + ${args[1]} > ${args[0]}.length ? ${args[0]}.length : i + ${args[1]})]`;
1622
+ case 'str': return `${args[0]}.toString()`;
1623
+ case 'int': return `int.parse(${args[0]})`;
1624
+ case 'float': return `double.parse(${args[0]})`;
1625
+ case 'json_parse': { this.addImport('dart:convert'); return `jsonDecode(${args[0]})`; }
1626
+ case 'json_str': { this.addImport('dart:convert'); return `jsonEncode(${args[0]})`; }
1627
+ case 'now': return `DateTime.now().millisecondsSinceEpoch`;
1628
+ case 'time': return `DateTime.now().toIso8601String()`;
1629
+ case 'exit': return `exit(${args[0] || '0'})`;
1630
+ case 'sleep': return `await Future.delayed(Duration(milliseconds: ${args[0]}))`;
1631
+ case 'random': { this.addImport('dart:math'); return args.length >= 2 ? `(Random().nextInt(${args[1]} - ${args[0]} + 1) + ${args[0]})` : `Random().nextDouble()`; }
1632
+ case 'read': { this.addImport('dart:io'); return `File(${args[0]}).readAsStringSync()`; }
1633
+ case 'write': { this.addImport('dart:io'); return `File(${args[0]}).writeAsStringSync(${args[1]})`; }
1634
+ case 'ask': { this.addImport('dart:io'); return `((){stdout.write(${args[0] || '""'}); return stdin.readLineSync() ?? "";}())`; }
1635
+ default: return null;
1636
+ }
1637
+ }
1569
1638
  }
@@ -116,6 +116,8 @@ export class GoGenerator {
116
116
  case 'GrpcDecl': return this.visitGrpc(node);
117
117
  case 'WebrtcDecl': return this.visitWebrtc(node);
118
118
  case 'BlockchainDecl': return this.visitBlockchain(node);
119
+ case 'EnumDecl': return this.visitEnum(node);
120
+ case 'Swap': return this.visitSwap(node);
119
121
  default:
120
122
  this.emit(`// unknown: ${node.type}`);
121
123
  }
@@ -1614,6 +1616,12 @@ export class GoGenerator {
1614
1616
  }
1615
1617
 
1616
1618
  generateCall(node) {
1619
+ if (node.callee.type === 'Identifier') {
1620
+ const argList = node.args.map(a => this.expr(a));
1621
+ const b = this.generateBuiltin(node.callee.name, argList);
1622
+ if (b) return b;
1623
+ }
1624
+
1617
1625
  const args = node.args.map(a => this.expr(a)).join(', ');
1618
1626
 
1619
1627
  // Map common JS global functions to Go
@@ -1778,4 +1786,58 @@ export class GoGenerator {
1778
1786
  this.indent = savedIndent;
1779
1787
  return result;
1780
1788
  }
1789
+
1790
+ visitEnum(node) {
1791
+ this.emit(`type ${node.name} int`);
1792
+ this.emit(`const (`);
1793
+ this.indent++;
1794
+ node.values.forEach((v, i) => {
1795
+ if (i === 0) {
1796
+ this.emit(`${v} ${node.name} = iota`);
1797
+ } else {
1798
+ this.emit(`${v}`);
1799
+ }
1800
+ });
1801
+ this.indent--;
1802
+ this.emit(`)`);
1803
+ this.emitRaw('');
1804
+ }
1805
+
1806
+ visitSwap(node) {
1807
+ const a = this.expr(node.a);
1808
+ const b = this.expr(node.b);
1809
+ this.emit(`${a}, ${b} = ${b}, ${a}`);
1810
+ }
1811
+
1812
+ generateBuiltin(name, args) {
1813
+ switch (name) {
1814
+ case 'len': return `len(${args[0]})`;
1815
+ case 'str': { this.addImport('strconv'); return `strconv.Itoa(${args[0]})`; }
1816
+ case 'int': { this.addImport('strconv'); return `func() int { v, _ := strconv.Atoi(${args[0]}); return v }()`; }
1817
+ case 'float': { this.addImport('strconv'); return `func() float64 { v, _ := strconv.ParseFloat(${args[0]}, 64); return v }()`; }
1818
+ case 'upper': { this.addImport('strings'); return `strings.ToUpper(${args[0]})`; }
1819
+ case 'lower': { this.addImport('strings'); return `strings.ToLower(${args[0]})`; }
1820
+ case 'trim': { this.addImport('strings'); return `strings.TrimSpace(${args[0]})`; }
1821
+ case 'split': { this.addImport('strings'); return `strings.Split(${args[0]}, ${args[1] || '","'})`; }
1822
+ case 'join': { this.addImport('strings'); return `strings.Join(${args[0]}, ${args[1] || '","'})`; }
1823
+ case 'contains': { this.addImport('strings'); return `strings.Contains(${args[0]}, ${args[1]})`; }
1824
+ case 'replace': { this.addImport('strings'); return `strings.ReplaceAll(${args[0]}, ${args[1]}, ${args[2]})`; }
1825
+ case 'abs': { this.addImport('math'); return `math.Abs(${args[0]})`; }
1826
+ case 'sqrt': { this.addImport('math'); return `math.Sqrt(${args[0]})`; }
1827
+ case 'pow': { this.addImport('math'); return `math.Pow(${args[0]}, ${args[1]})`; }
1828
+ case 'ceil': { this.addImport('math'); return `math.Ceil(${args[0]})`; }
1829
+ case 'floor': { this.addImport('math'); return `math.Floor(${args[0]})`; }
1830
+ case 'round': { this.addImport('math'); return `math.Round(${args[0]})`; }
1831
+ case 'exit': { this.addImport('os'); return `os.Exit(${args[0] || '0'})`; }
1832
+ case 'sleep': { this.addImport('time'); return `time.Sleep(time.Duration(${args[0]}) * time.Millisecond)`; }
1833
+ case 'now': { this.addImport('time'); return `time.Now().UnixMilli()`; }
1834
+ case 'time': { this.addImport('time'); return `time.Now().Format(time.RFC3339)`; }
1835
+ case 'json_parse': { this.addImport('encoding/json'); return `func() interface{} { var v interface{}; json.Unmarshal([]byte(${args[0]}), &v); return v }()`; }
1836
+ case 'json_str': { this.addImport('encoding/json'); return `func() string { b, _ := json.Marshal(${args[0]}); return string(b) }()`; }
1837
+ case 'random': { this.addImport('math/rand'); return args.length >= 2 ? `rand.Intn(${args[1]}-${args[0]}+1)+${args[0]}` : `rand.Float64()`; }
1838
+ case 'sort': { this.addImport('sort'); return `func() []int { s := make([]int, len(${args[0]})); copy(s, ${args[0]}); sort.Ints(s); return s }()`; }
1839
+ 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 }()`;
1840
+ default: return null;
1841
+ }
1842
+ }
1781
1843
  }
@@ -226,6 +226,8 @@ export class JavaGenerator {
226
226
  case 'GrpcDecl': return this.visitGrpc(node);
227
227
  case 'WebrtcDecl': return this.visitWebrtc(node);
228
228
  case 'BlockchainDecl': return this.visitBlockchain(node);
229
+ case 'EnumDecl': return this.visitEnum(node);
230
+ case 'Swap': return this.visitSwap(node);
229
231
  default:
230
232
  this.emit(`/* unknown: ${node.type} */`);
231
233
  }
@@ -1598,6 +1600,12 @@ export class JavaGenerator {
1598
1600
  }
1599
1601
 
1600
1602
  generateCall(node) {
1603
+ if (node.callee.type === 'Identifier') {
1604
+ const argList = node.args.map(a => this.expr(a));
1605
+ const b = this.generateBuiltin(node.callee.name, argList);
1606
+ if (b) return b;
1607
+ }
1608
+
1601
1609
  const args = node.args.map(a => this.expr(a)).join(', ');
1602
1610
 
1603
1611
  if (node.callee.type === 'Identifier') {
@@ -1811,4 +1819,57 @@ export class JavaGenerator {
1811
1819
  this.indent = savedIndent;
1812
1820
  return result;
1813
1821
  }
1822
+
1823
+ visitEnum(node) {
1824
+ this.emit(`enum ${node.name} {`);
1825
+ this.indent++;
1826
+ this.emit(node.values.join(', ') + ';');
1827
+ this.indent--;
1828
+ this.emit(`}`);
1829
+ this.emitRaw('');
1830
+ }
1831
+
1832
+ visitSwap(node) {
1833
+ const a = this.expr(node.a);
1834
+ const b = this.expr(node.b);
1835
+ this.emit(`{ var _tmp = ${a}; ${a} = ${b}; ${b} = _tmp; }`);
1836
+ }
1837
+
1838
+ generateBuiltin(name, args) {
1839
+ switch (name) {
1840
+ case 'len': return `${args[0]}.size()`;
1841
+ case 'sort': return `${args[0]}.stream().sorted().collect(java.util.stream.Collectors.toList())`;
1842
+ case 'reverse': return `{ var _l = new java.util.ArrayList<>(${args[0]}); java.util.Collections.reverse(_l); return _l; }`;
1843
+ case 'contains': return `${args[0]}.contains(${args[1]})`;
1844
+ case 'keys': return `new java.util.ArrayList<>(${args[0]}.keySet())`;
1845
+ case 'values': return `new java.util.ArrayList<>(${args[0]}.values())`;
1846
+ case 'entries': return `new java.util.ArrayList<>(${args[0]}.entrySet())`;
1847
+ case 'abs': return `Math.abs(${args[0]})`;
1848
+ case 'sqrt': return `Math.sqrt(${args[0]})`;
1849
+ case 'pow': return `Math.pow(${args[0]}, ${args[1]})`;
1850
+ case 'ceil': return `Math.ceil(${args[0]})`;
1851
+ case 'floor': return `Math.floor(${args[0]})`;
1852
+ case 'round': return `Math.round(${args[0]})`;
1853
+ case 'random': return args.length >= 2 ? `new java.util.Random().nextInt(${args[1]} - ${args[0]} + 1) + ${args[0]}` : `Math.random()`;
1854
+ case 'str': return `String.valueOf(${args[0]})`;
1855
+ case 'int': return `Integer.parseInt(${args[0]})`;
1856
+ case 'float': return `Double.parseDouble(${args[0]})`;
1857
+ case 'upper': return `${args[0]}.toUpperCase()`;
1858
+ case 'lower': return `${args[0]}.toLowerCase()`;
1859
+ case 'trim': return `${args[0]}.trim()`;
1860
+ case 'split': return `java.util.Arrays.asList(${args[0]}.split(${args[1] || '","'}))`;
1861
+ case 'join': return `String.join(${args[1] || '","'}, ${args[0]})`;
1862
+ case 'replace': return `${args[0]}.replace(${args[1]}, ${args[2]})`;
1863
+ case 'sum': return `${args[0]}.stream().mapToInt(Integer::intValue).sum()`;
1864
+ case 'unique': return `new java.util.ArrayList<>(new java.util.LinkedHashSet<>(${args[0]}))`;
1865
+ case 'exit': return `System.exit(${args[0] || '0'})`;
1866
+ case 'sleep': return `Thread.sleep(${args[0]})`;
1867
+ case 'now': return `System.currentTimeMillis()`;
1868
+ case 'time': return `java.time.LocalDateTime.now().toString()`;
1869
+ case 'json_parse': return `new com.google.gson.Gson().fromJson(${args[0]}, Object.class)`;
1870
+ case 'json_str': return `new com.google.gson.Gson().toJson(${args[0]})`;
1871
+ 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())`;
1872
+ default: return null;
1873
+ }
1874
+ }
1814
1875
  }
@@ -137,6 +137,8 @@ export class KotlinGenerator {
137
137
  case 'GrpcDecl': return this.visitGrpc(node);
138
138
  case 'WebrtcDecl': return this.visitWebrtc(node);
139
139
  case 'BlockchainDecl': return this.visitBlockchain(node);
140
+ case 'EnumDecl': return this.visitEnum(node);
141
+ case 'Swap': return this.visitSwap(node);
140
142
  default:
141
143
  this.emit(`// unknown: ${node.type}`);
142
144
  }
@@ -1641,6 +1643,12 @@ export class KotlinGenerator {
1641
1643
  generateCall(node) {
1642
1644
  const args = node.args.map(a => this.expr(a)).join(', ');
1643
1645
 
1646
+ if (node.callee.type === 'Identifier') {
1647
+ const argList = node.args.map(a => this.expr(a));
1648
+ const b = this.generateBuiltin(node.callee.name, argList);
1649
+ if (b) return b;
1650
+ }
1651
+
1644
1652
  if (node.callee.type === 'Identifier') {
1645
1653
  const name = node.callee.name;
1646
1654
  if (name === 'parseInt') return `(${args}).toInt()`;
@@ -1816,4 +1824,63 @@ export class KotlinGenerator {
1816
1824
  this.indent = savedIndent;
1817
1825
  return result;
1818
1826
  }
1827
+
1828
+ visitEnum(node) {
1829
+ this.emit(`enum class ${node.name} {`);
1830
+ this.indent++;
1831
+ this.emit(node.values.join(', '));
1832
+ this.indent--;
1833
+ this.emit(`}`);
1834
+ this.emitRaw('');
1835
+ }
1836
+
1837
+ visitSwap(node) {
1838
+ const a = this.expr(node.a);
1839
+ const b = this.expr(node.b);
1840
+ this.emit(`${a} = ${b}.also { ${b} = ${a} }`);
1841
+ }
1842
+
1843
+ generateBuiltin(name, args) {
1844
+ switch (name) {
1845
+ case 'len': return `${args[0]}.size`;
1846
+ case 'sort': return `${args[0]}.sorted()`;
1847
+ case 'reverse': return `${args[0]}.reversed()`;
1848
+ case 'unique': return `${args[0]}.distinct()`;
1849
+ case 'upper': return `${args[0]}.uppercase()`;
1850
+ case 'lower': return `${args[0]}.lowercase()`;
1851
+ case 'trim': return `${args[0]}.trim()`;
1852
+ case 'split': return `${args[0]}.split(${args[1] || '","'})`;
1853
+ case 'join': return `${args[0]}.joinToString(${args[1] || '","'})`;
1854
+ case 'contains': return `${args[0]}.contains(${args[1]})`;
1855
+ case 'replace': return `${args[0]}.replace(${args[1]}, ${args[2]})`;
1856
+ case 'keys': return `${args[0]}.keys.toList()`;
1857
+ case 'values': return `${args[0]}.values.toList()`;
1858
+ case 'entries': return `${args[0]}.entries.toList()`;
1859
+ case 'range': return args.length >= 2 ? `(${args[0]} until ${args[1]}).toList()` : `(0 until ${args[0]}).toList()`;
1860
+ case 'abs': return `kotlin.math.abs(${args[0]})`;
1861
+ case 'sqrt': return `kotlin.math.sqrt(${args[0]}.toDouble())`;
1862
+ case 'pow': return `kotlin.math.pow(${args[0]}.toDouble(), ${args[1]}.toDouble())`;
1863
+ case 'ceil': return `kotlin.math.ceil(${args[0]}.toDouble())`;
1864
+ case 'floor': return `kotlin.math.floor(${args[0]}.toDouble())`;
1865
+ case 'round': return `kotlin.math.round(${args[0]}.toDouble())`;
1866
+ case 'sum': return `${args[0]}.sum()`;
1867
+ case 'flat': return `${args[0]}.flatten()`;
1868
+ case 'zip': return `${args[0]}.zip(${args[1]})`;
1869
+ case 'chunk': return `${args[0]}.chunked(${args[1]})`;
1870
+ case 'str': return `${args[0]}.toString()`;
1871
+ case 'int': return `${args[0]}.toInt()`;
1872
+ case 'float': return `${args[0]}.toDouble()`;
1873
+ case 'json_parse': return `com.google.gson.Gson().fromJson(${args[0]}, Any::class.java)`;
1874
+ case 'json_str': return `com.google.gson.Gson().toJson(${args[0]})`;
1875
+ case 'now': return `System.currentTimeMillis()`;
1876
+ case 'time': return `java.time.LocalDateTime.now().toString()`;
1877
+ case 'exit': return `kotlin.system.exitProcess(${args[0] || '0'})`;
1878
+ case 'sleep': return `Thread.sleep(${args[0]}.toLong())`;
1879
+ case 'random': return args.length >= 2 ? `(${args[0]}..${args[1]}).random()` : `kotlin.random.Random.nextDouble()`;
1880
+ case 'read': return `java.io.File(${args[0]}).readText()`;
1881
+ case 'write': return `java.io.File(${args[0]}).writeText(${args[1]})`;
1882
+ case 'ask': return `(print(${args[0] || '""'}); readLine() ?: "")`;
1883
+ default: return null;
1884
+ }
1885
+ }
1819
1886
  }
@@ -103,6 +103,8 @@ export class PhpGenerator {
103
103
  case 'GrpcDecl': return this.visitGrpc(node);
104
104
  case 'WebrtcDecl': return this.visitWebrtc(node);
105
105
  case 'BlockchainDecl': return this.visitBlockchain(node);
106
+ case 'EnumDecl': return this.visitEnum(node);
107
+ case 'Swap': return this.visitSwap(node);
106
108
  default:
107
109
  this.emit(`/* unknown: ${node.type} */`);
108
110
  }
@@ -1366,6 +1368,12 @@ export class PhpGenerator {
1366
1368
  }
1367
1369
 
1368
1370
  generateCall(node) {
1371
+ if (node.callee.type === 'Identifier') {
1372
+ const argList = node.args.map(a => this.expr(a));
1373
+ const b = this.generateBuiltin(node.callee.name, argList);
1374
+ if (b) return b;
1375
+ }
1376
+
1369
1377
  const args = node.args.map(a => this.expr(a)).join(', ');
1370
1378
 
1371
1379
  // Map global function calls
@@ -1573,4 +1581,65 @@ export class PhpGenerator {
1573
1581
  this.indent = savedIndent;
1574
1582
  return result;
1575
1583
  }
1584
+
1585
+ visitEnum(node) {
1586
+ this.emit(`class ${node.name} {`);
1587
+ this.indent++;
1588
+ node.values.forEach((v, i) => {
1589
+ this.emit(`const ${v} = ${i};`);
1590
+ });
1591
+ this.indent--;
1592
+ this.emit(`}`);
1593
+ this.emitRaw('');
1594
+ }
1595
+
1596
+ visitSwap(node) {
1597
+ const a = this.expr(node.a);
1598
+ const b = this.expr(node.b);
1599
+ this.emit(`[$${a.replace('$','')}, $${b.replace('$','')}] = [$${b.replace('$','')}, $${a.replace('$','')}];`);
1600
+ }
1601
+
1602
+ generateBuiltin(name, args) {
1603
+ switch (name) {
1604
+ case 'len': return `count(${args[0]})`;
1605
+ case 'sort': return `(function($a) { sort($a); return $a; })(${args[0]})`;
1606
+ case 'reverse': return `array_reverse(${args[0]})`;
1607
+ case 'unique': return `array_values(array_unique(${args[0]}))`;
1608
+ case 'upper': return `strtoupper(${args[0]})`;
1609
+ case 'lower': return `strtolower(${args[0]})`;
1610
+ case 'trim': return `trim(${args[0]})`;
1611
+ case 'split': return `explode(${args[1] || '","'}, ${args[0]})`;
1612
+ case 'join': return `implode(${args[1] || '","'}, ${args[0]})`;
1613
+ case 'contains': return `in_array(${args[1]}, ${args[0]})`;
1614
+ case 'replace': return `str_replace(${args[1]}, ${args[2]}, ${args[0]})`;
1615
+ case 'keys': return `array_keys(${args[0]})`;
1616
+ case 'values': return `array_values(${args[0]})`;
1617
+ case 'entries': return `array_map(null, array_keys(${args[0]}), array_values(${args[0]}))`;
1618
+ case 'range': return args.length >= 2 ? `range(${args[0]}, ${args[1]} - 1)` : `range(0, ${args[0]} - 1)`;
1619
+ case 'abs': return `abs(${args[0]})`;
1620
+ case 'round': return `round(${args[0]})`;
1621
+ case 'ceil': return `ceil(${args[0]})`;
1622
+ case 'floor': return `floor(${args[0]})`;
1623
+ case 'sqrt': return `sqrt(${args[0]})`;
1624
+ case 'pow': return `pow(${args[0]}, ${args[1]})`;
1625
+ case 'sum': return `array_sum(${args[0]})`;
1626
+ case 'flat': return `array_merge(...${args[0]})`;
1627
+ case 'str': return `strval(${args[0]})`;
1628
+ case 'int': return `intval(${args[0]})`;
1629
+ case 'float': return `floatval(${args[0]})`;
1630
+ case 'json_parse': return `json_decode(${args[0]}, true)`;
1631
+ case 'json_str': return `json_encode(${args[0]})`;
1632
+ case 'now': return `(int)(microtime(true) * 1000)`;
1633
+ case 'time': return `date('c')`;
1634
+ case 'exit': return `exit(${args[0] || '0'})`;
1635
+ case 'sleep': return `usleep(${args[0]} * 1000)`;
1636
+ case 'random': return args.length >= 2 ? `random_int(${args[0]}, ${args[1]})` : `(mt_rand() / mt_getrandmax())`;
1637
+ case 'read': return `file_get_contents(${args[0]})`;
1638
+ case 'write': return `file_put_contents(${args[0]}, ${args[1]})`;
1639
+ case 'ask': return `readline(${args[0] || '""'})`;
1640
+ case 'chunk': return `array_chunk(${args[0]}, ${args[1]})`;
1641
+ case 'zip': return `array_map(null, ${args[0]}, ${args[1]})`;
1642
+ default: return null;
1643
+ }
1644
+ }
1576
1645
  }
@@ -162,6 +162,8 @@ export class PythonGenerator {
162
162
  case 'GrpcDecl': return this.visitGrpc(node);
163
163
  case 'WebrtcDecl': return this.visitWebrtc(node);
164
164
  case 'BlockchainDecl': return this.visitBlockchain(node);
165
+ case 'EnumDecl': return this.visitEnum(node);
166
+ case 'Swap': return this.visitSwap(node);
165
167
  default:
166
168
  this.emit(`# unknown: ${node.type}`);
167
169
  }
@@ -1068,6 +1070,12 @@ export class PythonGenerator {
1068
1070
  generateCall(node) {
1069
1071
  const args = node.args.map(a => this.expr(a)).join(', ');
1070
1072
 
1073
+ if (node.callee.type === 'Identifier') {
1074
+ const argList = node.args.map(a => this.expr(a));
1075
+ const b = this.generateBuiltin(node.callee.name, argList);
1076
+ if (b !== null) return b;
1077
+ }
1078
+
1071
1079
  // Map common JS global functions to Python
1072
1080
  if (node.callee.type === 'Identifier') {
1073
1081
  const name = node.callee.name;
@@ -2466,4 +2474,69 @@ export class PythonGenerator {
2466
2474
  this.emit(`${name.replace(/\W/g, '_')} = ${name.charAt(0).toUpperCase() + name.slice(1).replace(/\W/g, '_')}()`);
2467
2475
  this.emitRaw('');
2468
2476
  }
2477
+
2478
+ // ===== Enum =====
2479
+ visitEnum(node) {
2480
+ this.addFromImport('enum', 'Enum');
2481
+ this.emit(`class ${node.name}(Enum):`);
2482
+ this.indent++;
2483
+ node.values.forEach((v, i) => {
2484
+ this.emit(`${v} = ${i}`);
2485
+ });
2486
+ this.indent--;
2487
+ this.emitRaw('');
2488
+ }
2489
+
2490
+ // ===== Swap =====
2491
+ visitSwap(node) {
2492
+ const a = this.expr(node.a);
2493
+ const b = this.expr(node.b);
2494
+ this.emit(`${a}, ${b} = ${b}, ${a}`);
2495
+ }
2496
+
2497
+ // ===== Builtins =====
2498
+ generateBuiltin(name, args) {
2499
+ switch (name) {
2500
+ case 'ask': return `input(${args[0] || '""'})`;
2501
+ case 'sleep': { this.addImport('time'); return `time.sleep(${args[0]} / 1000)`; }
2502
+ case 'exit': { this.addImport('sys'); return `sys.exit(${args[0] || '0'})`; }
2503
+ case 'read': return `open(${args[0]}).read()`;
2504
+ case 'write': return `open(${args[0]}, 'w').write(${args[1]})`;
2505
+ case 'fetch_json': { this.addImport('requests'); return `requests.get(${args[0]}).json()`; }
2506
+ case 'random': { this.addImport('random'); return args.length >= 2 ? `random.randint(${args[0]}, ${args[1]})` : `random.random()`; }
2507
+ case 'sort': return `sorted(${args[0]})`;
2508
+ case 'reverse': return `list(reversed(${args[0]}))`;
2509
+ case 'unique': return `list(set(${args[0]}))`;
2510
+ case 'len': return `len(${args[0]})`;
2511
+ case 'upper': return `${args[0]}.upper()`;
2512
+ case 'lower': return `${args[0]}.lower()`;
2513
+ case 'trim': return `${args[0]}.strip()`;
2514
+ case 'split': return `${args[0]}.split(${args[1] || ''})`;
2515
+ case 'join': return `${args[1] || '","'}.join(${args[0]})`;
2516
+ case 'contains': return `(${args[1]} in ${args[0]})`;
2517
+ case 'replace': return `${args[0]}.replace(${args[1]}, ${args[2]})`;
2518
+ case 'keys': return `list(${args[0]}.keys())`;
2519
+ case 'values': return `list(${args[0]}.values())`;
2520
+ case 'entries': return `list(${args[0]}.items())`;
2521
+ case 'range': return args.length >= 2 ? `list(range(${args[0]}, ${args[1]}))` : `list(range(${args[0]}))`;
2522
+ case 'abs': return `abs(${args[0]})`;
2523
+ case 'round': return `round(${args[0]})`;
2524
+ case 'ceil': { this.addImport('math'); return `math.ceil(${args[0]})`; }
2525
+ case 'floor': { this.addImport('math'); return `math.floor(${args[0]})`; }
2526
+ case 'sqrt': { this.addImport('math'); return `math.sqrt(${args[0]})`; }
2527
+ case 'pow': return `${args[0]} ** ${args[1]}`;
2528
+ case 'sum': return `sum(${args[0]})`;
2529
+ case 'flat': return `[x for sub in ${args[0]} for x in sub]`;
2530
+ case 'zip': return `list(zip(${args[0]}, ${args[1]}))`;
2531
+ case 'str': return `str(${args[0]})`;
2532
+ case 'int': return `int(${args[0]})`;
2533
+ case 'float': return `float(${args[0]})`;
2534
+ case 'json_parse': { this.addImport('json'); return `json.loads(${args[0]})`; }
2535
+ case 'json_str': { this.addImport('json'); return `json.dumps(${args[0]})`; }
2536
+ case 'now': { this.addImport('time'); return `int(time.time() * 1000)`; }
2537
+ case 'time': { this.addFromImport('datetime', 'datetime'); return `datetime.now().isoformat()`; }
2538
+ case 'chunk': return `[${args[0]}[i:i+${args[1]}] for i in range(0, len(${args[0]}), ${args[1]})]`;
2539
+ default: return null;
2540
+ }
2541
+ }
2469
2542
  }
@@ -111,6 +111,8 @@ export class RubyGenerator {
111
111
  case 'GrpcDecl': return this.visitGrpc(node);
112
112
  case 'WebrtcDecl': return this.visitWebrtc(node);
113
113
  case 'BlockchainDecl': return this.visitBlockchain(node);
114
+ case 'EnumDecl': return this.visitEnum(node);
115
+ case 'Swap': return this.visitSwap(node);
114
116
  default:
115
117
  this.emit(`# unknown: ${node.type}`);
116
118
  }
@@ -1330,6 +1332,12 @@ export class RubyGenerator {
1330
1332
  }
1331
1333
 
1332
1334
  generateCall(node) {
1335
+ if (node.callee.type === 'Identifier') {
1336
+ const argList = node.args.map(a => this.expr(a));
1337
+ const b = this.generateBuiltin(node.callee.name, argList);
1338
+ if (b) return b;
1339
+ }
1340
+
1333
1341
  const args = node.args.map(a => this.expr(a)).join(', ');
1334
1342
 
1335
1343
  // Map global function calls
@@ -1527,4 +1535,65 @@ export class RubyGenerator {
1527
1535
  this.indent = savedIndent;
1528
1536
  return result;
1529
1537
  }
1538
+
1539
+ visitEnum(node) {
1540
+ this.emit(`module ${node.name}`);
1541
+ this.indent++;
1542
+ node.values.forEach((v, i) => {
1543
+ this.emit(`${v} = ${i}`);
1544
+ });
1545
+ this.indent--;
1546
+ this.emit(`end`);
1547
+ this.emitRaw('');
1548
+ }
1549
+
1550
+ visitSwap(node) {
1551
+ const a = this.expr(node.a);
1552
+ const b = this.expr(node.b);
1553
+ this.emit(`${a}, ${b} = ${b}, ${a}`);
1554
+ }
1555
+
1556
+ generateBuiltin(name, args) {
1557
+ switch (name) {
1558
+ case 'len': return `${args[0]}.length`;
1559
+ case 'sort': return `${args[0]}.sort`;
1560
+ case 'reverse': return `${args[0]}.reverse`;
1561
+ case 'unique': return `${args[0]}.uniq`;
1562
+ case 'upper': return `${args[0]}.upcase`;
1563
+ case 'lower': return `${args[0]}.downcase`;
1564
+ case 'trim': return `${args[0]}.strip`;
1565
+ case 'split': return `${args[0]}.split(${args[1] || '","'})`;
1566
+ case 'join': return `${args[0]}.join(${args[1] || '","'})`;
1567
+ case 'contains': return `${args[0]}.include?(${args[1]})`;
1568
+ case 'replace': return `${args[0]}.gsub(${args[1]}, ${args[2]})`;
1569
+ case 'keys': return `${args[0]}.keys`;
1570
+ case 'values': return `${args[0]}.values`;
1571
+ case 'entries': return `${args[0]}.to_a`;
1572
+ case 'range': return args.length >= 2 ? `(${args[0]}...${args[1]}).to_a` : `(0...${args[0]}).to_a`;
1573
+ case 'abs': return `${args[0]}.abs`;
1574
+ case 'round': return `${args[0]}.round`;
1575
+ case 'ceil': return `${args[0]}.ceil`;
1576
+ case 'floor': return `${args[0]}.floor`;
1577
+ case 'sqrt': return `Math.sqrt(${args[0]})`;
1578
+ case 'pow': return `${args[0]} ** ${args[1]}`;
1579
+ case 'sum': return `${args[0]}.sum`;
1580
+ case 'flat': return `${args[0]}.flatten`;
1581
+ case 'zip': return `${args[0]}.zip(${args[1]})`;
1582
+ case 'chunk': return `${args[0]}.each_slice(${args[1]}).to_a`;
1583
+ case 'str': return `${args[0]}.to_s`;
1584
+ case 'int': return `${args[0]}.to_i`;
1585
+ case 'float': return `${args[0]}.to_f`;
1586
+ case 'json_parse': return `JSON.parse(${args[0]})`;
1587
+ case 'json_str': return `JSON.generate(${args[0]})`;
1588
+ case 'now': return `(Time.now.to_f * 1000).to_i`;
1589
+ case 'time': return `Time.now.iso8601`;
1590
+ case 'exit': return `exit(${args[0] || '0'})`;
1591
+ case 'sleep': return `sleep(${args[0]} / 1000.0)`;
1592
+ case 'random': return args.length >= 2 ? `rand(${args[0]}..${args[1]})` : `rand`;
1593
+ case 'read': return `File.read(${args[0]})`;
1594
+ case 'write': return `File.write(${args[0]}, ${args[1]})`;
1595
+ case 'ask': return `(print(${args[0] || '""'}); gets.chomp)`;
1596
+ default: return null;
1597
+ }
1598
+ }
1530
1599
  }