naider 1.16.0 → 1.17.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +71 -0
- package/bin/postinstall.js +132 -0
- package/package.json +3 -2
- package/src/generator-c.js +48 -0
- package/src/generator-cpp.js +53 -0
- package/src/generator-csharp.js +67 -0
- package/src/generator-dart.js +69 -0
- package/src/generator-go.js +62 -0
- package/src/generator-java.js +61 -0
- package/src/generator-kotlin.js +67 -0
- package/src/generator-php.js +69 -0
- package/src/generator-ruby.js +69 -0
- package/src/generator-rust.js +61 -0
- package/src/generator-swift.js +67 -0
- package/src/parser.js +12 -1
package/README.md
CHANGED
|
@@ -1405,6 +1405,76 @@ naide pkg list # list installed NAIDE packages
|
|
|
1405
1405
|
|
|
1406
1406
|
The `naide.pkg.json` manifest tracks NAIDE-specific metadata (main entry, exports, dependencies) while using npm as the underlying registry.
|
|
1407
1407
|
|
|
1408
|
+
## NAIDE vs Python — Side by Side
|
|
1409
|
+
|
|
1410
|
+
**Read a file, process lines, write result:**
|
|
1411
|
+
|
|
1412
|
+
```python
|
|
1413
|
+
# Python (8 lines)
|
|
1414
|
+
with open("input.txt") as f:
|
|
1415
|
+
lines = f.read().strip().split("\n")
|
|
1416
|
+
upper_lines = [line.upper() for line in lines]
|
|
1417
|
+
result = "\n".join(upper_lines)
|
|
1418
|
+
with open("output.txt", "w") as f:
|
|
1419
|
+
f.write(result)
|
|
1420
|
+
print(f"Processed {len(upper_lines)} lines")
|
|
1421
|
+
```
|
|
1422
|
+
|
|
1423
|
+
```python
|
|
1424
|
+
# NAIDE (4 lines)
|
|
1425
|
+
list lines = split(trim(read("input.txt")), "\n")
|
|
1426
|
+
list upper_lines = [upper(line) for line in lines]
|
|
1427
|
+
write("output.txt", join(upper_lines, "\n"))
|
|
1428
|
+
print "Processed {len(upper_lines)} lines"
|
|
1429
|
+
```
|
|
1430
|
+
|
|
1431
|
+
**Sort, deduplicate, and swap:**
|
|
1432
|
+
|
|
1433
|
+
```python
|
|
1434
|
+
# Python (5 lines)
|
|
1435
|
+
items = [3, 1, 4, 1, 5]
|
|
1436
|
+
items = sorted(set(items))
|
|
1437
|
+
a, b = 1, 2
|
|
1438
|
+
a, b = b, a
|
|
1439
|
+
print(f"a={a}, b={b}")
|
|
1440
|
+
```
|
|
1441
|
+
|
|
1442
|
+
```python
|
|
1443
|
+
# NAIDE (5 lines)
|
|
1444
|
+
list items = unique(sort([3, 1, 4, 1, 5]))
|
|
1445
|
+
mut int a = 1
|
|
1446
|
+
mut int b = 2
|
|
1447
|
+
swap a, b
|
|
1448
|
+
print "a={a}, b={b}"
|
|
1449
|
+
```
|
|
1450
|
+
|
|
1451
|
+
**Simple API server:**
|
|
1452
|
+
|
|
1453
|
+
```python
|
|
1454
|
+
# Python + Flask (12 lines)
|
|
1455
|
+
from flask import Flask, jsonify
|
|
1456
|
+
app = Flask(__name__)
|
|
1457
|
+
|
|
1458
|
+
@app.route("/")
|
|
1459
|
+
def index():
|
|
1460
|
+
return jsonify({"message": "Hello"})
|
|
1461
|
+
|
|
1462
|
+
@app.route("/health")
|
|
1463
|
+
def health():
|
|
1464
|
+
return jsonify({"status": "ok"})
|
|
1465
|
+
|
|
1466
|
+
app.run(port=3000)
|
|
1467
|
+
```
|
|
1468
|
+
|
|
1469
|
+
```python
|
|
1470
|
+
# NAIDE (5 lines)
|
|
1471
|
+
server app port 3000:
|
|
1472
|
+
get "/":
|
|
1473
|
+
ret {message: "Hello"}
|
|
1474
|
+
get "/health":
|
|
1475
|
+
ret {status: "ok"}
|
|
1476
|
+
```
|
|
1477
|
+
|
|
1408
1478
|
## Why NAIDE?
|
|
1409
1479
|
|
|
1410
1480
|
AI code generation speed depends on:
|
|
@@ -1412,6 +1482,7 @@ AI code generation speed depends on:
|
|
|
1412
1482
|
1. **Token count** — fewer output tokens = faster generation
|
|
1413
1483
|
2. **Predictability** — one way to write everything = better next-token prediction
|
|
1414
1484
|
3. **Context window** — shorter code = more room for complex projects
|
|
1485
|
+
4. **Simplicity** — built-in functions mean zero imports and less boilerplate
|
|
1415
1486
|
|
|
1416
1487
|
NAIDE-X is designed as an **AI-internal representation** — the AI thinks in NAIDE-X, users receive standard JavaScript.
|
|
1417
1488
|
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { execSync } from 'child_process';
|
|
4
|
+
import { existsSync, writeFileSync, mkdirSync, readFileSync } from 'fs';
|
|
5
|
+
import { resolve, dirname, join } from 'path';
|
|
6
|
+
import { fileURLToPath } from 'url';
|
|
7
|
+
|
|
8
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
+
const __dirname = dirname(__filename);
|
|
10
|
+
|
|
11
|
+
const platform = process.platform;
|
|
12
|
+
const naideBin = resolve(__dirname, 'naide.js');
|
|
13
|
+
|
|
14
|
+
function run(cmd, opts = {}) {
|
|
15
|
+
try {
|
|
16
|
+
execSync(cmd, { stdio: 'pipe', ...opts });
|
|
17
|
+
return true;
|
|
18
|
+
} catch {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function registerWindows() {
|
|
24
|
+
const nodePath = process.execPath;
|
|
25
|
+
const npmGlobal = resolve(dirname(nodePath), 'node_modules', 'naider', 'bin', 'naide.js');
|
|
26
|
+
const binPath = existsSync(npmGlobal) ? npmGlobal : naideBin;
|
|
27
|
+
|
|
28
|
+
const nodeEsc = nodePath.replace(/\\/g, '\\\\');
|
|
29
|
+
const binEsc = binPath.replace(/\\/g, '\\\\');
|
|
30
|
+
const cmd = `"${nodePath}" "${binPath}" "%1" %*`;
|
|
31
|
+
|
|
32
|
+
const regAdd = (key, value) => run(`reg add "${key}" /ve /d "${value}" /f`);
|
|
33
|
+
|
|
34
|
+
regAdd('HKCU\\Software\\Classes\\.naide', 'NAIDEFile');
|
|
35
|
+
regAdd('HKCU\\Software\\Classes\\.nx', 'NAIDEXFile');
|
|
36
|
+
regAdd('HKCU\\Software\\Classes\\NAIDEFile', 'NAIDE Source File');
|
|
37
|
+
regAdd('HKCU\\Software\\Classes\\NAIDEXFile', 'NAIDE-X Source File');
|
|
38
|
+
regAdd('HKCU\\Software\\Classes\\NAIDEFile\\shell\\open\\command', cmd);
|
|
39
|
+
regAdd('HKCU\\Software\\Classes\\NAIDEXFile\\shell\\open\\command', cmd);
|
|
40
|
+
|
|
41
|
+
run(`reg add "HKCU\\Software\\Classes\\NAIDEFile\\DefaultIcon" /ve /d "${nodeEsc},0" /f`);
|
|
42
|
+
run(`reg add "HKCU\\Software\\Classes\\NAIDEXFile\\DefaultIcon" /ve /d "${nodeEsc},0" /f`);
|
|
43
|
+
|
|
44
|
+
console.log(' .naide and .nx file associations registered (Windows)');
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function registerMacOS() {
|
|
48
|
+
const plistDir = resolve(process.env.HOME, 'Library', 'LaunchAgents');
|
|
49
|
+
if (!existsSync(plistDir)) mkdirSync(plistDir, { recursive: true });
|
|
50
|
+
|
|
51
|
+
const handlerApp = resolve(process.env.HOME, '.naide', 'NAIDE.app');
|
|
52
|
+
const contentsDir = join(handlerApp, 'Contents');
|
|
53
|
+
const macosDir = join(contentsDir, 'MacOS');
|
|
54
|
+
|
|
55
|
+
mkdirSync(macosDir, { recursive: true });
|
|
56
|
+
|
|
57
|
+
writeFileSync(join(contentsDir, 'Info.plist'), `<?xml version="1.0" encoding="UTF-8"?>
|
|
58
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
59
|
+
<plist version="1.0">
|
|
60
|
+
<dict>
|
|
61
|
+
<key>CFBundleName</key><string>NAIDE</string>
|
|
62
|
+
<key>CFBundleIdentifier</key><string>com.naide.runner</string>
|
|
63
|
+
<key>CFBundleVersion</key><string>1.0</string>
|
|
64
|
+
<key>CFBundleExecutable</key><string>naide-run</string>
|
|
65
|
+
<key>CFBundleDocumentTypes</key>
|
|
66
|
+
<array>
|
|
67
|
+
<dict>
|
|
68
|
+
<key>CFBundleTypeExtensions</key><array><string>naide</string><string>nx</string></array>
|
|
69
|
+
<key>CFBundleTypeName</key><string>NAIDE Source</string>
|
|
70
|
+
<key>CFBundleTypeRole</key><string>Editor</string>
|
|
71
|
+
</dict>
|
|
72
|
+
</array>
|
|
73
|
+
</dict>
|
|
74
|
+
</plist>`);
|
|
75
|
+
|
|
76
|
+
writeFileSync(join(macosDir, 'naide-run'), `#!/bin/bash\nexec node "${naideBin}" "$@"\n`);
|
|
77
|
+
run(`chmod +x "${join(macosDir, 'naide-run')}"`);
|
|
78
|
+
|
|
79
|
+
run(`/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -f "${handlerApp}"`);
|
|
80
|
+
|
|
81
|
+
console.log(' .naide and .nx file associations registered (macOS)');
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function registerLinux() {
|
|
85
|
+
const mimeDir = resolve(process.env.HOME, '.local', 'share', 'mime', 'packages');
|
|
86
|
+
const appDir = resolve(process.env.HOME, '.local', 'share', 'applications');
|
|
87
|
+
mkdirSync(mimeDir, { recursive: true });
|
|
88
|
+
mkdirSync(appDir, { recursive: true });
|
|
89
|
+
|
|
90
|
+
writeFileSync(join(mimeDir, 'naide.xml'), `<?xml version="1.0" encoding="UTF-8"?>
|
|
91
|
+
<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
|
|
92
|
+
<mime-type type="text/x-naide">
|
|
93
|
+
<comment>NAIDE Source File</comment>
|
|
94
|
+
<glob pattern="*.naide"/>
|
|
95
|
+
</mime-type>
|
|
96
|
+
<mime-type type="text/x-naidex">
|
|
97
|
+
<comment>NAIDE-X Source File</comment>
|
|
98
|
+
<glob pattern="*.nx"/>
|
|
99
|
+
</mime-type>
|
|
100
|
+
</mime-info>`);
|
|
101
|
+
|
|
102
|
+
writeFileSync(join(appDir, 'naide.desktop'), `[Desktop Entry]
|
|
103
|
+
Type=Application
|
|
104
|
+
Name=NAIDE
|
|
105
|
+
Exec=node "${naideBin}" %f
|
|
106
|
+
MimeType=text/x-naide;text/x-naidex;
|
|
107
|
+
Terminal=true
|
|
108
|
+
Categories=Development;
|
|
109
|
+
`);
|
|
110
|
+
|
|
111
|
+
run('update-mime-database ~/.local/share/mime');
|
|
112
|
+
run('xdg-mime default naide.desktop text/x-naide');
|
|
113
|
+
run('xdg-mime default naide.desktop text/x-naidex');
|
|
114
|
+
|
|
115
|
+
console.log(' .naide and .nx file associations registered (Linux)');
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
console.log('NAIDE: Registering file extensions...');
|
|
119
|
+
|
|
120
|
+
try {
|
|
121
|
+
if (platform === 'win32') {
|
|
122
|
+
registerWindows();
|
|
123
|
+
} else if (platform === 'darwin') {
|
|
124
|
+
registerMacOS();
|
|
125
|
+
} else {
|
|
126
|
+
registerLinux();
|
|
127
|
+
}
|
|
128
|
+
} catch (e) {
|
|
129
|
+
console.log(` Skipped file association (${e.message}). You can still run: naide <file.naide>`);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
console.log('NAIDE: Installation complete! Run "naide --help" to get started.');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "naider",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.17.1",
|
|
4
4
|
"description": "NAIDE - Simpler than Python, compiles to 15 targets. AI-specialized language with 35+ built-in functions, syntax sugar (unless/until/repeat/swap/is/isnt), and 47 features. Targets: Node.js, Python, TypeScript, C, C++, Java, Go, Rust, PHP, Ruby, Kotlin, Swift, Dart, C#, Bun.",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"exports": {
|
|
@@ -25,7 +25,8 @@
|
|
|
25
25
|
"scripts": {
|
|
26
26
|
"test": "node --test test/test.js",
|
|
27
27
|
"example": "node bin/naide.js examples/hello.naide",
|
|
28
|
-
"example:x": "node bin/naide.js examples/hello.nx"
|
|
28
|
+
"example:x": "node bin/naide.js examples/hello.nx",
|
|
29
|
+
"postinstall": "node bin/postinstall.js"
|
|
29
30
|
},
|
|
30
31
|
"keywords": [
|
|
31
32
|
"ai",
|
package/src/generator-c.js
CHANGED
|
@@ -185,6 +185,8 @@ export class CGenerator {
|
|
|
185
185
|
case 'GrpcDecl': return this.visitGrpc(node);
|
|
186
186
|
case 'WebrtcDecl': return this.visitWebrtc(node);
|
|
187
187
|
case 'BlockchainDecl': return this.visitBlockchain(node);
|
|
188
|
+
case 'EnumDecl': return this.visitEnum(node);
|
|
189
|
+
case 'Swap': return this.visitSwap(node);
|
|
188
190
|
default:
|
|
189
191
|
this.emit(`/* unknown: ${node.type} */`);
|
|
190
192
|
}
|
|
@@ -873,6 +875,12 @@ export class CGenerator {
|
|
|
873
875
|
generateCall(node) {
|
|
874
876
|
const args = node.args.map(a => this.expr(a)).join(', ');
|
|
875
877
|
|
|
878
|
+
if (node.callee.type === 'Identifier') {
|
|
879
|
+
const argList = node.args.map(a => this.expr(a));
|
|
880
|
+
const b = this.generateBuiltin(node.callee.name, argList);
|
|
881
|
+
if (b) return b;
|
|
882
|
+
}
|
|
883
|
+
|
|
876
884
|
if (node.callee.type === 'Identifier') {
|
|
877
885
|
const name = node.callee.name;
|
|
878
886
|
if (name === 'parseInt') return `atoi(${args})`;
|
|
@@ -974,6 +982,46 @@ export class CGenerator {
|
|
|
974
982
|
return result;
|
|
975
983
|
}
|
|
976
984
|
|
|
985
|
+
visitEnum(node) {
|
|
986
|
+
this.emit(`typedef enum {`);
|
|
987
|
+
this.indent++;
|
|
988
|
+
node.values.forEach((v, i) => {
|
|
989
|
+
this.emit(`${node.name}_${v} = ${i},`);
|
|
990
|
+
});
|
|
991
|
+
this.indent--;
|
|
992
|
+
this.emit(`} ${node.name};`);
|
|
993
|
+
this.emitRaw('');
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
visitSwap(node) {
|
|
997
|
+
const a = this.expr(node.a);
|
|
998
|
+
const b = this.expr(node.b);
|
|
999
|
+
const tmp = `_tmp_${a.replace(/[^a-zA-Z0-9]/g, '')}`;
|
|
1000
|
+
this.emit(`{ typeof(${a}) ${tmp} = ${a}; ${a} = ${b}; ${b} = ${tmp}; }`);
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
generateBuiltin(name, args) {
|
|
1004
|
+
switch (name) {
|
|
1005
|
+
case 'len': return `(sizeof(${args[0]}) / sizeof(${args[0]}[0]))`;
|
|
1006
|
+
case 'abs': return `abs(${args[0]})`;
|
|
1007
|
+
case 'sqrt': { this.includes.add('<math.h>'); return `sqrt(${args[0]})`; }
|
|
1008
|
+
case 'pow': { this.includes.add('<math.h>'); return `pow(${args[0]}, ${args[1]})`; }
|
|
1009
|
+
case 'ceil': { this.includes.add('<math.h>'); return `ceil(${args[0]})`; }
|
|
1010
|
+
case 'floor': { this.includes.add('<math.h>'); return `floor(${args[0]})`; }
|
|
1011
|
+
case 'round': { this.includes.add('<math.h>'); return `round(${args[0]})`; }
|
|
1012
|
+
case 'exit': { this.includes.add('<stdlib.h>'); return `exit(${args[0] || '0'})`; }
|
|
1013
|
+
case 'str': return `snprintf(_buf, sizeof(_buf), "%d", ${args[0]})`;
|
|
1014
|
+
case 'int': { this.includes.add('<stdlib.h>'); return `atoi(${args[0]})`; }
|
|
1015
|
+
case 'float': { this.includes.add('<stdlib.h>'); return `atof(${args[0]})`; }
|
|
1016
|
+
case 'upper': { this.includes.add('<ctype.h>'); return `toupper(${args[0]})`; }
|
|
1017
|
+
case 'lower': { this.includes.add('<ctype.h>'); return `tolower(${args[0]})`; }
|
|
1018
|
+
case 'sleep': { this.includes.add('<unistd.h>'); return `usleep(${args[0]} * 1000)`; }
|
|
1019
|
+
case 'now': { this.includes.add('<time.h>'); return `(long long)time(NULL) * 1000`; }
|
|
1020
|
+
case 'random': { this.includes.add('<stdlib.h>'); return args.length >= 2 ? `(rand() % (${args[1]} - ${args[0]} + 1) + ${args[0]})` : `rand()`; }
|
|
1021
|
+
default: return null;
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
|
|
977
1025
|
rawString(strData) {
|
|
978
1026
|
if (!strData) return '';
|
|
979
1027
|
if (strData.raw !== null && strData.raw !== undefined) return strData.raw;
|
package/src/generator-cpp.js
CHANGED
|
@@ -186,6 +186,8 @@ export class CppGenerator {
|
|
|
186
186
|
case 'GrpcDecl': return this.visitGrpc(node);
|
|
187
187
|
case 'WebrtcDecl': return this.visitWebrtc(node);
|
|
188
188
|
case 'BlockchainDecl': return this.visitBlockchain(node);
|
|
189
|
+
case 'EnumDecl': return this.visitEnum(node);
|
|
190
|
+
case 'Swap': return this.visitSwap(node);
|
|
189
191
|
default:
|
|
190
192
|
this.emit(`/* unknown: ${node.type} */`);
|
|
191
193
|
}
|
|
@@ -983,6 +985,10 @@ export class CppGenerator {
|
|
|
983
985
|
const args = node.args.map(a => this.expr(a)).join(', ');
|
|
984
986
|
|
|
985
987
|
if (node.callee.type === 'Identifier') {
|
|
988
|
+
const argList = node.args.map(a => this.expr(a));
|
|
989
|
+
const b = this.generateBuiltin(node.callee.name, argList);
|
|
990
|
+
if (b) return b;
|
|
991
|
+
|
|
986
992
|
const name = node.callee.name;
|
|
987
993
|
if (name === 'parseInt') return `stoi(${args})`;
|
|
988
994
|
if (name === 'parseFloat') return `stod(${args})`;
|
|
@@ -1208,4 +1214,51 @@ export class CppGenerator {
|
|
|
1208
1214
|
this.inFunction = saved;
|
|
1209
1215
|
return result;
|
|
1210
1216
|
}
|
|
1217
|
+
|
|
1218
|
+
visitEnum(node) {
|
|
1219
|
+
this.emit(`enum class ${node.name} {`);
|
|
1220
|
+
this.indent++;
|
|
1221
|
+
node.values.forEach((v, i) => {
|
|
1222
|
+
this.emit(`${v} = ${i},`);
|
|
1223
|
+
});
|
|
1224
|
+
this.indent--;
|
|
1225
|
+
this.emit(`};`);
|
|
1226
|
+
this.emitRaw('');
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
visitSwap(node) {
|
|
1230
|
+
this.includes.add('<utility>');
|
|
1231
|
+
const a = this.expr(node.a);
|
|
1232
|
+
const b = this.expr(node.b);
|
|
1233
|
+
this.emit(`std::swap(${a}, ${b});`);
|
|
1234
|
+
}
|
|
1235
|
+
|
|
1236
|
+
generateBuiltin(name, args) {
|
|
1237
|
+
switch (name) {
|
|
1238
|
+
case 'len': return `${args[0]}.size()`;
|
|
1239
|
+
case 'sort': { this.includes.add('<algorithm>'); return `([&](){ auto _v = ${args[0]}; std::sort(_v.begin(), _v.end()); return _v; }())`; }
|
|
1240
|
+
case 'reverse': { this.includes.add('<algorithm>'); return `([&](){ auto _v = ${args[0]}; std::reverse(_v.begin(), _v.end()); return _v; }())`; }
|
|
1241
|
+
case 'contains': return `(std::find(${args[0]}.begin(), ${args[0]}.end(), ${args[1]}) != ${args[0]}.end())`;
|
|
1242
|
+
case 'abs': { this.includes.add('<cmath>'); return `std::abs(${args[0]})`; }
|
|
1243
|
+
case 'sqrt': { this.includes.add('<cmath>'); return `std::sqrt(${args[0]})`; }
|
|
1244
|
+
case 'pow': { this.includes.add('<cmath>'); return `std::pow(${args[0]}, ${args[1]})`; }
|
|
1245
|
+
case 'ceil': { this.includes.add('<cmath>'); return `std::ceil(${args[0]})`; }
|
|
1246
|
+
case 'floor': { this.includes.add('<cmath>'); return `std::floor(${args[0]})`; }
|
|
1247
|
+
case 'round': { this.includes.add('<cmath>'); return `std::round(${args[0]})`; }
|
|
1248
|
+
case 'str': return `std::to_string(${args[0]})`;
|
|
1249
|
+
case 'int': return `std::stoi(${args[0]})`;
|
|
1250
|
+
case 'float': return `std::stof(${args[0]})`;
|
|
1251
|
+
case 'upper': { this.includes.add('<algorithm>'); this.includes.add('<cctype>'); return `([&](){ auto _s = ${args[0]}; std::transform(_s.begin(), _s.end(), _s.begin(), ::toupper); return _s; }())`; }
|
|
1252
|
+
case 'lower': { this.includes.add('<algorithm>'); this.includes.add('<cctype>'); return `([&](){ auto _s = ${args[0]}; std::transform(_s.begin(), _s.end(), _s.begin(), ::tolower); return _s; }())`; }
|
|
1253
|
+
case 'trim': return `([&](){ auto _s = ${args[0]}; _s.erase(0, _s.find_first_not_of(" \\t\\n\\r")); _s.erase(_s.find_last_not_of(" \\t\\n\\r") + 1); return _s; }())`;
|
|
1254
|
+
case 'keys': return `([&](){ std::vector<std::string> _k; for (auto& [k,v] : ${args[0]}) _k.push_back(k); return _k; }())`;
|
|
1255
|
+
case 'values': return `([&](){ std::vector<auto> _v; for (auto& [k,v] : ${args[0]}) _v.push_back(v); return _v; }())`;
|
|
1256
|
+
case 'exit': return `exit(${args[0] || '0'})`;
|
|
1257
|
+
case 'sleep': { this.includes.add('<thread>'); this.includes.add('<chrono>'); return `std::this_thread::sleep_for(std::chrono::milliseconds(${args[0]}))`; }
|
|
1258
|
+
case 'now': { this.includes.add('<chrono>'); return `std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count()`; }
|
|
1259
|
+
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
|
+
case 'sum': return `([&](){ auto _v = ${args[0]}; return std::accumulate(_v.begin(), _v.end(), 0); }())`;
|
|
1261
|
+
default: return null;
|
|
1262
|
+
}
|
|
1263
|
+
}
|
|
1211
1264
|
}
|
package/src/generator-csharp.js
CHANGED
|
@@ -178,6 +178,8 @@ export class CSharpGenerator {
|
|
|
178
178
|
case 'GrpcDecl': return this.visitGrpc(node);
|
|
179
179
|
case 'WebrtcDecl': return this.visitWebrtc(node);
|
|
180
180
|
case 'BlockchainDecl': return this.visitBlockchain(node);
|
|
181
|
+
case 'EnumDecl': return this.visitEnum(node);
|
|
182
|
+
case 'Swap': return this.visitSwap(node);
|
|
181
183
|
default:
|
|
182
184
|
this.emit(`// unknown: ${node.type}`);
|
|
183
185
|
}
|
|
@@ -1431,6 +1433,12 @@ export class CSharpGenerator {
|
|
|
1431
1433
|
generateCall(node) {
|
|
1432
1434
|
const args = node.args.map(a => this.expr(a)).join(', ');
|
|
1433
1435
|
|
|
1436
|
+
if (node.callee.type === 'Identifier') {
|
|
1437
|
+
const argList = node.args.map(a => this.expr(a));
|
|
1438
|
+
const b = this.generateBuiltin(node.callee.name, argList);
|
|
1439
|
+
if (b) return b;
|
|
1440
|
+
}
|
|
1441
|
+
|
|
1434
1442
|
if (node.callee.type === 'Identifier') {
|
|
1435
1443
|
const name = node.callee.name;
|
|
1436
1444
|
if (name === 'parseInt') return `int.Parse(${args})`;
|
|
@@ -1630,4 +1638,63 @@ export class CSharpGenerator {
|
|
|
1630
1638
|
this.indent = savedIndent;
|
|
1631
1639
|
return result;
|
|
1632
1640
|
}
|
|
1641
|
+
|
|
1642
|
+
visitEnum(node) {
|
|
1643
|
+
this.emit(`enum ${node.name} {`);
|
|
1644
|
+
this.indent++;
|
|
1645
|
+
this.emit(node.values.join(', '));
|
|
1646
|
+
this.indent--;
|
|
1647
|
+
this.emit(`}`);
|
|
1648
|
+
this.emitRaw('');
|
|
1649
|
+
}
|
|
1650
|
+
|
|
1651
|
+
visitSwap(node) {
|
|
1652
|
+
const a = this.expr(node.a);
|
|
1653
|
+
const b = this.expr(node.b);
|
|
1654
|
+
this.emit(`(${a}, ${b}) = (${b}, ${a});`);
|
|
1655
|
+
}
|
|
1656
|
+
|
|
1657
|
+
generateBuiltin(name, args) {
|
|
1658
|
+
switch (name) {
|
|
1659
|
+
case 'len': return `${args[0]}.Count`;
|
|
1660
|
+
case 'sort': return `${args[0]}.OrderBy(x => x).ToList()`;
|
|
1661
|
+
case 'reverse': return `${args[0]}.AsEnumerable().Reverse().ToList()`;
|
|
1662
|
+
case 'unique': return `${args[0]}.Distinct().ToList()`;
|
|
1663
|
+
case 'upper': return `${args[0]}.ToUpper()`;
|
|
1664
|
+
case 'lower': return `${args[0]}.ToLower()`;
|
|
1665
|
+
case 'trim': return `${args[0]}.Trim()`;
|
|
1666
|
+
case 'split': return `${args[0]}.Split(${args[1] || '","'}).ToList()`;
|
|
1667
|
+
case 'join': return `string.Join(${args[1] || '","'}, ${args[0]})`;
|
|
1668
|
+
case 'contains': return `${args[0]}.Contains(${args[1]})`;
|
|
1669
|
+
case 'replace': return `${args[0]}.Replace(${args[1]}, ${args[2]})`;
|
|
1670
|
+
case 'keys': return `${args[0]}.Keys.ToList()`;
|
|
1671
|
+
case 'values': return `${args[0]}.Values.ToList()`;
|
|
1672
|
+
case 'entries': return `${args[0]}.ToList()`;
|
|
1673
|
+
case 'range': return args.length >= 2 ? `Enumerable.Range(${args[0]}, ${args[1]} - ${args[0]}).ToList()` : `Enumerable.Range(0, ${args[0]}).ToList()`;
|
|
1674
|
+
case 'abs': return `Math.Abs(${args[0]})`;
|
|
1675
|
+
case 'sqrt': return `Math.Sqrt(${args[0]})`;
|
|
1676
|
+
case 'pow': return `Math.Pow(${args[0]}, ${args[1]})`;
|
|
1677
|
+
case 'ceil': return `Math.Ceiling((double)${args[0]})`;
|
|
1678
|
+
case 'floor': return `Math.Floor((double)${args[0]})`;
|
|
1679
|
+
case 'round': return `Math.Round((double)${args[0]})`;
|
|
1680
|
+
case 'sum': return `${args[0]}.Sum()`;
|
|
1681
|
+
case 'flat': return `${args[0]}.SelectMany(x => x).ToList()`;
|
|
1682
|
+
case 'zip': return `${args[0]}.Zip(${args[1]}).ToList()`;
|
|
1683
|
+
case 'chunk': return `${args[0]}.Chunk(${args[1]}).Select(c => c.ToList()).ToList()`;
|
|
1684
|
+
case 'str': return `${args[0]}.ToString()`;
|
|
1685
|
+
case 'int': return `int.Parse(${args[0]})`;
|
|
1686
|
+
case 'float': return `double.Parse(${args[0]})`;
|
|
1687
|
+
case 'json_parse': return `System.Text.Json.JsonSerializer.Deserialize<object>(${args[0]})`;
|
|
1688
|
+
case 'json_str': return `System.Text.Json.JsonSerializer.Serialize(${args[0]})`;
|
|
1689
|
+
case 'now': return `DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()`;
|
|
1690
|
+
case 'time': return `DateTime.Now.ToString("o")`;
|
|
1691
|
+
case 'exit': return `Environment.Exit(${args[0] || '0'})`;
|
|
1692
|
+
case 'sleep': return `Thread.Sleep(${args[0]})`;
|
|
1693
|
+
case 'random': return args.length >= 2 ? `new Random().Next(${args[0]}, ${args[1]} + 1)` : `new Random().NextDouble()`;
|
|
1694
|
+
case 'read': return `File.ReadAllText(${args[0]})`;
|
|
1695
|
+
case 'write': return `File.WriteAllText(${args[0]}, ${args[1]})`;
|
|
1696
|
+
case 'ask': return `(Console.Write(${args[0] || '""'}), Console.ReadLine() ?? "").Item2`;
|
|
1697
|
+
default: return null;
|
|
1698
|
+
}
|
|
1699
|
+
}
|
|
1633
1700
|
}
|
package/src/generator-dart.js
CHANGED
|
@@ -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
|
}
|
package/src/generator-go.js
CHANGED
|
@@ -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
|
}
|
package/src/generator-java.js
CHANGED
|
@@ -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
|
}
|
package/src/generator-kotlin.js
CHANGED
|
@@ -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
|
}
|
package/src/generator-php.js
CHANGED
|
@@ -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
|
}
|
package/src/generator-ruby.js
CHANGED
|
@@ -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
|
}
|
package/src/generator-rust.js
CHANGED
|
@@ -207,6 +207,8 @@ export class RustGenerator {
|
|
|
207
207
|
case 'GrpcDecl': return this.visitGrpc(node);
|
|
208
208
|
case 'WebrtcDecl': return this.visitWebrtc(node);
|
|
209
209
|
case 'BlockchainDecl': return this.visitBlockchain(node);
|
|
210
|
+
case 'EnumDecl': return this.visitEnum(node);
|
|
211
|
+
case 'Swap': return this.visitSwap(node);
|
|
210
212
|
default:
|
|
211
213
|
this.emit(`/* unknown: ${node.type} */`);
|
|
212
214
|
}
|
|
@@ -1707,6 +1709,12 @@ export class RustGenerator {
|
|
|
1707
1709
|
}
|
|
1708
1710
|
|
|
1709
1711
|
generateCall(node) {
|
|
1712
|
+
if (node.callee.type === 'Identifier') {
|
|
1713
|
+
const argList = node.args.map(a => this.expr(a));
|
|
1714
|
+
const b = this.generateBuiltin(node.callee.name, argList);
|
|
1715
|
+
if (b) return b;
|
|
1716
|
+
}
|
|
1717
|
+
|
|
1710
1718
|
const args = node.args.map(a => this.expr(a)).join(', ');
|
|
1711
1719
|
|
|
1712
1720
|
// Map common JS global functions to Rust
|
|
@@ -1884,4 +1892,57 @@ export class RustGenerator {
|
|
|
1884
1892
|
this.indent = savedIndent;
|
|
1885
1893
|
return result;
|
|
1886
1894
|
}
|
|
1895
|
+
|
|
1896
|
+
visitEnum(node) {
|
|
1897
|
+
this.emit(`#[derive(Debug, Clone, Copy, PartialEq)]`);
|
|
1898
|
+
this.emit(`enum ${node.name} {`);
|
|
1899
|
+
this.indent++;
|
|
1900
|
+
node.values.forEach(v => {
|
|
1901
|
+
this.emit(`${v},`);
|
|
1902
|
+
});
|
|
1903
|
+
this.indent--;
|
|
1904
|
+
this.emit(`}`);
|
|
1905
|
+
this.emitRaw('');
|
|
1906
|
+
}
|
|
1907
|
+
|
|
1908
|
+
visitSwap(node) {
|
|
1909
|
+
const a = this.expr(node.a);
|
|
1910
|
+
const b = this.expr(node.b);
|
|
1911
|
+
this.emit(`std::mem::swap(&mut ${a}, &mut ${b});`);
|
|
1912
|
+
}
|
|
1913
|
+
|
|
1914
|
+
generateBuiltin(name, args) {
|
|
1915
|
+
switch (name) {
|
|
1916
|
+
case 'len': return `${args[0]}.len()`;
|
|
1917
|
+
case 'str': return `${args[0]}.to_string()`;
|
|
1918
|
+
case 'int': return `${args[0]}.parse::<i64>().unwrap_or(0)`;
|
|
1919
|
+
case 'float': return `${args[0]}.parse::<f64>().unwrap_or(0.0)`;
|
|
1920
|
+
case 'upper': return `${args[0]}.to_uppercase()`;
|
|
1921
|
+
case 'lower': return `${args[0]}.to_lowercase()`;
|
|
1922
|
+
case 'trim': return `${args[0]}.trim().to_string()`;
|
|
1923
|
+
case 'split': return `${args[0]}.split(${args[1] || '","'}).collect::<Vec<&str>>()`;
|
|
1924
|
+
case 'join': return `${args[0]}.join(${args[1] || '","'})`;
|
|
1925
|
+
case 'contains': return `${args[0]}.contains(${args[1]})`;
|
|
1926
|
+
case 'replace': return `${args[0]}.replace(${args[1]}, ${args[2]})`;
|
|
1927
|
+
case 'sort': return `{ let mut v = ${args[0]}.clone(); v.sort(); v }`;
|
|
1928
|
+
case 'reverse': return `{ let mut v = ${args[0]}.clone(); v.reverse(); v }`;
|
|
1929
|
+
case 'abs': return `${args[0]}.abs()`;
|
|
1930
|
+
case 'sqrt': return `(${args[0]} as f64).sqrt()`;
|
|
1931
|
+
case 'pow': return `(${args[0]} as f64).powi(${args[1]} as i32)`;
|
|
1932
|
+
case 'ceil': return `(${args[0]} as f64).ceil()`;
|
|
1933
|
+
case 'floor': return `(${args[0]} as f64).floor()`;
|
|
1934
|
+
case 'round': return `(${args[0]} as f64).round()`;
|
|
1935
|
+
case 'sum': return `${args[0]}.iter().sum::<i64>()`;
|
|
1936
|
+
case 'unique': return `{ let mut v = ${args[0]}.clone(); v.sort(); v.dedup(); v }`;
|
|
1937
|
+
case 'exit': return `std::process::exit(${args[0] || '0'})`;
|
|
1938
|
+
case 'sleep': return `std::thread::sleep(std::time::Duration::from_millis(${args[0]} as u64))`;
|
|
1939
|
+
case 'now': return `std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_millis() as i64`;
|
|
1940
|
+
case 'random': return args.length >= 2 ? `rand::thread_rng().gen_range(${args[0]}..=${args[1]})` : `rand::random::<f64>()`;
|
|
1941
|
+
case 'keys': return `${args[0]}.keys().cloned().collect::<Vec<_>>()`;
|
|
1942
|
+
case 'values': return `${args[0]}.values().cloned().collect::<Vec<_>>()`;
|
|
1943
|
+
case 'range': return args.length >= 2 ? `(${args[0]}..${args[1]}).collect::<Vec<_>>()` : `(0..${args[0]}).collect::<Vec<_>>()`;
|
|
1944
|
+
case 'flat': return `${args[0]}.into_iter().flatten().collect::<Vec<_>>()`;
|
|
1945
|
+
default: return null;
|
|
1946
|
+
}
|
|
1947
|
+
}
|
|
1887
1948
|
}
|
package/src/generator-swift.js
CHANGED
|
@@ -139,6 +139,8 @@ export class SwiftGenerator {
|
|
|
139
139
|
case 'GrpcDecl': return this.visitGrpc(node);
|
|
140
140
|
case 'WebrtcDecl': return this.visitWebrtc(node);
|
|
141
141
|
case 'BlockchainDecl': return this.visitBlockchain(node);
|
|
142
|
+
case 'EnumDecl': return this.visitEnum(node);
|
|
143
|
+
case 'Swap': return this.visitSwap(node);
|
|
142
144
|
default:
|
|
143
145
|
this.emit(`// unknown: ${node.type}`);
|
|
144
146
|
}
|
|
@@ -1555,6 +1557,12 @@ export class SwiftGenerator {
|
|
|
1555
1557
|
}
|
|
1556
1558
|
|
|
1557
1559
|
generateCall(node) {
|
|
1560
|
+
if (node.callee.type === 'Identifier') {
|
|
1561
|
+
const argList = node.args.map(a => this.expr(a));
|
|
1562
|
+
const b = this.generateBuiltin(node.callee.name, argList);
|
|
1563
|
+
if (b) return b;
|
|
1564
|
+
}
|
|
1565
|
+
|
|
1558
1566
|
const args = node.args.map(a => this.expr(a)).join(', ');
|
|
1559
1567
|
|
|
1560
1568
|
if (node.callee.type === 'Identifier') {
|
|
@@ -1732,4 +1740,63 @@ export class SwiftGenerator {
|
|
|
1732
1740
|
this.indent = savedIndent;
|
|
1733
1741
|
return result;
|
|
1734
1742
|
}
|
|
1743
|
+
|
|
1744
|
+
visitEnum(node) {
|
|
1745
|
+
this.emit(`enum ${node.name}: Int, CaseIterable {`);
|
|
1746
|
+
this.indent++;
|
|
1747
|
+
node.values.forEach((v, i) => {
|
|
1748
|
+
this.emit(`case ${v.toLowerCase()} = ${i}`);
|
|
1749
|
+
});
|
|
1750
|
+
this.indent--;
|
|
1751
|
+
this.emit(`}`);
|
|
1752
|
+
this.emitRaw('');
|
|
1753
|
+
}
|
|
1754
|
+
|
|
1755
|
+
visitSwap(node) {
|
|
1756
|
+
const a = this.expr(node.a);
|
|
1757
|
+
const b = this.expr(node.b);
|
|
1758
|
+
this.emit(`swap(&${a}, &${b})`);
|
|
1759
|
+
}
|
|
1760
|
+
|
|
1761
|
+
generateBuiltin(name, args) {
|
|
1762
|
+
switch (name) {
|
|
1763
|
+
case 'len': return `${args[0]}.count`;
|
|
1764
|
+
case 'sort': return `${args[0]}.sorted()`;
|
|
1765
|
+
case 'reverse': return `${args[0]}.reversed()`;
|
|
1766
|
+
case 'unique': return `Array(Set(${args[0]}))`;
|
|
1767
|
+
case 'upper': return `${args[0]}.uppercased()`;
|
|
1768
|
+
case 'lower': return `${args[0]}.lowercased()`;
|
|
1769
|
+
case 'trim': return `${args[0]}.trimmingCharacters(in: .whitespacesAndNewlines)`;
|
|
1770
|
+
case 'split': return `${args[0]}.components(separatedBy: ${args[1] || '","'})`;
|
|
1771
|
+
case 'join': return `${args[0]}.joined(separator: ${args[1] || '","'})`;
|
|
1772
|
+
case 'contains': return `${args[0]}.contains(${args[1]})`;
|
|
1773
|
+
case 'replace': return `${args[0]}.replacingOccurrences(of: ${args[1]}, with: ${args[2]})`;
|
|
1774
|
+
case 'keys': return `Array(${args[0]}.keys)`;
|
|
1775
|
+
case 'values': return `Array(${args[0]}.values)`;
|
|
1776
|
+
case 'range': return args.length >= 2 ? `Array(${args[0]}..<${args[1]})` : `Array(0..<${args[0]})`;
|
|
1777
|
+
case 'abs': return `abs(${args[0]})`;
|
|
1778
|
+
case 'sqrt': { this.addImport('Foundation'); return `sqrt(Double(${args[0]}))`; }
|
|
1779
|
+
case 'pow': { this.addImport('Foundation'); return `pow(Double(${args[0]}), Double(${args[1]}))`; }
|
|
1780
|
+
case 'ceil': { this.addImport('Foundation'); return `ceil(Double(${args[0]}))`; }
|
|
1781
|
+
case 'floor': { this.addImport('Foundation'); return `floor(Double(${args[0]}))`; }
|
|
1782
|
+
case 'round': { this.addImport('Foundation'); return `round(Double(${args[0]}))`; }
|
|
1783
|
+
case 'sum': return `${args[0]}.reduce(0, +)`;
|
|
1784
|
+
case 'flat': return `${args[0]}.flatMap { $0 }`;
|
|
1785
|
+
case 'zip': return `Array(zip(${args[0]}, ${args[1]}))`;
|
|
1786
|
+
case 'chunk': return `stride(from: 0, to: ${args[0]}.count, by: ${args[1]}).map { Array(${args[0]}[$0..<min($0+${args[1]}, ${args[0]}.count)]) }`;
|
|
1787
|
+
case 'str': return `String(${args[0]})`;
|
|
1788
|
+
case 'int': return `Int(${args[0]}) ?? 0`;
|
|
1789
|
+
case 'float': return `Double(${args[0]}) ?? 0.0`;
|
|
1790
|
+
case 'json_parse': { this.addImport('Foundation'); return `try? JSONSerialization.jsonObject(with: ${args[0]}.data(using: .utf8)!, options: [])`; }
|
|
1791
|
+
case 'json_str': { this.addImport('Foundation'); return `String(data: try! JSONSerialization.data(withJSONObject: ${args[0]}), encoding: .utf8)!`; }
|
|
1792
|
+
case 'now': { this.addImport('Foundation'); return `Int(Date().timeIntervalSince1970 * 1000)`; }
|
|
1793
|
+
case 'time': { this.addImport('Foundation'); return `ISO8601DateFormatter().string(from: Date())`; }
|
|
1794
|
+
case 'exit': { this.addImport('Foundation'); return `exit(${args[0] || '0'})`; }
|
|
1795
|
+
case 'sleep': { this.addImport('Foundation'); return `Thread.sleep(forTimeInterval: Double(${args[0]}) / 1000.0)`; }
|
|
1796
|
+
case 'random': return args.length >= 2 ? `Int.random(in: ${args[0]}...${args[1]})` : `Double.random(in: 0...1)`;
|
|
1797
|
+
case 'read': return `try! String(contentsOfFile: ${args[0]})`;
|
|
1798
|
+
case 'write': return `try! ${args[1]}.write(toFile: ${args[0]}, atomically: true, encoding: .utf8)`;
|
|
1799
|
+
default: return null;
|
|
1800
|
+
}
|
|
1801
|
+
}
|
|
1735
1802
|
}
|
package/src/parser.js
CHANGED
|
@@ -135,7 +135,18 @@ export class Parser {
|
|
|
135
135
|
|
|
136
136
|
error(msg, tok) {
|
|
137
137
|
const t = tok || this.peek();
|
|
138
|
-
|
|
138
|
+
let hint = '';
|
|
139
|
+
const v = t.value;
|
|
140
|
+
if (v === 'unless') hint = '\n Hint: unless <condition>:';
|
|
141
|
+
else if (v === 'until') hint = '\n Hint: until <condition>:';
|
|
142
|
+
else if (v === 'repeat') hint = '\n Hint: repeat <count>: or repeat <count> as <var>:';
|
|
143
|
+
else if (v === 'swap') hint = '\n Hint: swap <a>, <b>';
|
|
144
|
+
else if (v === 'enum') hint = '\n Hint: enum <Name>: then indent values';
|
|
145
|
+
else if (v === 'fn') hint = '\n Hint: fn <name>(<params>) -> <type>: or fn <name>(<params>) -> <type> = <expr>';
|
|
146
|
+
else if (v === 'if') hint = '\n Hint: if <condition>:';
|
|
147
|
+
else if (v === 'for') hint = '\n Hint: for <var> in <iterable>:';
|
|
148
|
+
else if (v === 'while') hint = '\n Hint: while <condition>:';
|
|
149
|
+
return new Error(`[NAIDE Parse Error] ${msg} at line ${t.line}:${t.col}${hint}`);
|
|
139
150
|
}
|
|
140
151
|
|
|
141
152
|
skipNewlines() {
|