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.
- package/README.md +161 -7
- package/SPEC.naide +102 -0
- package/lsp/server.js +48 -0
- package/package.json +2 -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-python.js +73 -0
- package/src/generator-ruby.js +69 -0
- package/src/generator-rust.js +61 -0
- package/src/generator-swift.js +67 -0
- package/src/generator.js +73 -0
- package/src/parser.js +111 -4
- package/src/tokens.js +15 -0
- package/vscode-naide/syntaxes/naide.tmLanguage.json +6 -2
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# NAIDE
|
|
2
2
|
|
|
3
|
-
**Node AI Development Environment** — A programming language designed for AI-speed code generation that transpiles to **15 languages**.
|
|
3
|
+
**Node AI Development Environment** — A programming language simpler than Python, designed for AI-speed code generation, that transpiles to **15 languages**.
|
|
4
4
|
|
|
5
|
-
NAIDE is built on
|
|
5
|
+
NAIDE is built on four principles: simpler than Python (built-in functions, syntax sugar, zero boilerplate), one way to write everything (zero ambiguity), keyword-driven intent (the first token decides meaning), and minimal token count (fewer tokens = faster AI generation). Write once, compile to any target. 35+ built-in functions, syntax sugar (`unless`, `until`, `repeat`, `swap`, `is`/`isnt`, one-line functions), and 47 built-in features including servers, databases, authentication, bots, GraphQL, gRPC, WebRTC, blockchain, and more.
|
|
6
6
|
|
|
7
7
|
### Compilation Targets
|
|
8
8
|
|
|
@@ -885,14 +885,97 @@ env:
|
|
|
885
885
|
|
|
886
886
|
Variables become constants. Missing `required` vars exit with an error.
|
|
887
887
|
|
|
888
|
+
## Syntax Sugar (Simpler than Python)
|
|
889
|
+
|
|
890
|
+
```python
|
|
891
|
+
# unless — negated if
|
|
892
|
+
unless x > 10:
|
|
893
|
+
log "small"
|
|
894
|
+
|
|
895
|
+
# until — negated while
|
|
896
|
+
until done:
|
|
897
|
+
process()
|
|
898
|
+
|
|
899
|
+
# repeat — simple counted loop
|
|
900
|
+
repeat 5:
|
|
901
|
+
log "hi"
|
|
902
|
+
repeat 10 as i:
|
|
903
|
+
log i
|
|
904
|
+
|
|
905
|
+
# enum
|
|
906
|
+
enum Color:
|
|
907
|
+
RED
|
|
908
|
+
GREEN
|
|
909
|
+
BLUE
|
|
910
|
+
|
|
911
|
+
# swap
|
|
912
|
+
swap a, b
|
|
913
|
+
|
|
914
|
+
# is / isnt — readable equality
|
|
915
|
+
if x is 5: log "five"
|
|
916
|
+
if y isnt null: log "exists"
|
|
917
|
+
|
|
918
|
+
# one-line functions
|
|
919
|
+
fn double(int x) -> int = x * 2
|
|
920
|
+
|
|
921
|
+
# print alias
|
|
922
|
+
print "hello world"
|
|
923
|
+
```
|
|
924
|
+
|
|
888
925
|
## Built-in Functions
|
|
889
926
|
|
|
890
927
|
```python
|
|
891
|
-
|
|
892
|
-
str
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
str token = sign({id: 1}
|
|
928
|
+
# Security
|
|
929
|
+
str id = uuid()
|
|
930
|
+
str hashed = hash("password")
|
|
931
|
+
bool ok = verify("password", hashed)
|
|
932
|
+
str token = sign({id: 1})
|
|
933
|
+
|
|
934
|
+
# Type conversions
|
|
935
|
+
str s = str(42)
|
|
936
|
+
int n = int("42")
|
|
937
|
+
num f = float("3.14")
|
|
938
|
+
|
|
939
|
+
# String ops
|
|
940
|
+
str u = upper("hello")
|
|
941
|
+
str l = lower("HELLO")
|
|
942
|
+
str t = trim(" hi ")
|
|
943
|
+
list parts = split("a,b,c", ",")
|
|
944
|
+
str joined = join(parts, "-")
|
|
945
|
+
bool has = contains("hello", "ell")
|
|
946
|
+
|
|
947
|
+
# Collection ops
|
|
948
|
+
int length = len(items)
|
|
949
|
+
list sorted = sort(items)
|
|
950
|
+
list r = range(10)
|
|
951
|
+
list k = keys(obj)
|
|
952
|
+
list v = values(obj)
|
|
953
|
+
list uniq = unique(items)
|
|
954
|
+
list flat_list = flat(nested)
|
|
955
|
+
list zipped = zip(a, b)
|
|
956
|
+
list chunks = chunk(items, 3)
|
|
957
|
+
|
|
958
|
+
# Math
|
|
959
|
+
num a = abs(-5)
|
|
960
|
+
num r = round(3.7)
|
|
961
|
+
num s = sqrt(16)
|
|
962
|
+
num p = pow(2, 10)
|
|
963
|
+
num total = sum(nums)
|
|
964
|
+
|
|
965
|
+
# JSON
|
|
966
|
+
any data = json_parse('{"a":1}')
|
|
967
|
+
str json = json_str(data)
|
|
968
|
+
|
|
969
|
+
# I/O
|
|
970
|
+
str answer = ask("Name?")
|
|
971
|
+
str content = read("file.txt")
|
|
972
|
+
write("out.txt", content)
|
|
973
|
+
|
|
974
|
+
# Time & misc
|
|
975
|
+
int ts = now()
|
|
976
|
+
str t = time()
|
|
977
|
+
sleep(1000)
|
|
978
|
+
exit(0)
|
|
896
979
|
```
|
|
897
980
|
|
|
898
981
|
Auto-imported from the runtime when used.
|
|
@@ -1322,6 +1405,76 @@ naide pkg list # list installed NAIDE packages
|
|
|
1322
1405
|
|
|
1323
1406
|
The `naide.pkg.json` manifest tracks NAIDE-specific metadata (main entry, exports, dependencies) while using npm as the underlying registry.
|
|
1324
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
|
+
|
|
1325
1478
|
## Why NAIDE?
|
|
1326
1479
|
|
|
1327
1480
|
AI code generation speed depends on:
|
|
@@ -1329,6 +1482,7 @@ AI code generation speed depends on:
|
|
|
1329
1482
|
1. **Token count** — fewer output tokens = faster generation
|
|
1330
1483
|
2. **Predictability** — one way to write everything = better next-token prediction
|
|
1331
1484
|
3. **Context window** — shorter code = more room for complex projects
|
|
1485
|
+
4. **Simplicity** — built-in functions mean zero imports and less boilerplate
|
|
1332
1486
|
|
|
1333
1487
|
NAIDE-X is designed as an **AI-internal representation** — the AI thinks in NAIDE-X, users receive standard JavaScript.
|
|
1334
1488
|
|
package/SPEC.naide
CHANGED
|
@@ -634,3 +634,105 @@ blockchain "eth":
|
|
|
634
634
|
contract "0x1234abcd..."
|
|
635
635
|
abi "contract-abi.json"
|
|
636
636
|
# usage: eth.getBalance("0x..."), eth.getBlock(), eth.sendTx(wallet, to, "0.1")
|
|
637
|
+
|
|
638
|
+
|
|
639
|
+
# ============================================
|
|
640
|
+
# シンプルシンタックス (Pythonより簡単)
|
|
641
|
+
# ============================================
|
|
642
|
+
|
|
643
|
+
# ---- unless (ifの逆) ----
|
|
644
|
+
unless x > 10:
|
|
645
|
+
log "xは10以下"
|
|
646
|
+
|
|
647
|
+
# ---- until (whileの逆) ----
|
|
648
|
+
mut int i = 0
|
|
649
|
+
until i > 10:
|
|
650
|
+
i = i + 1
|
|
651
|
+
|
|
652
|
+
# ---- repeat (簡単ループ) ----
|
|
653
|
+
repeat 5:
|
|
654
|
+
log "hello"
|
|
655
|
+
|
|
656
|
+
repeat 10 as i:
|
|
657
|
+
log i
|
|
658
|
+
|
|
659
|
+
# ---- enum (列挙型) ----
|
|
660
|
+
enum Color:
|
|
661
|
+
RED
|
|
662
|
+
GREEN
|
|
663
|
+
BLUE
|
|
664
|
+
|
|
665
|
+
# インライン形式
|
|
666
|
+
enum Status: ACTIVE, INACTIVE, PENDING
|
|
667
|
+
|
|
668
|
+
# ---- swap (値の交換) ----
|
|
669
|
+
mut int a = 1
|
|
670
|
+
mut int b = 2
|
|
671
|
+
swap a, b
|
|
672
|
+
|
|
673
|
+
# ---- is / isnt (比較演算子) ----
|
|
674
|
+
if x is 5:
|
|
675
|
+
log "xは5"
|
|
676
|
+
if y isnt null:
|
|
677
|
+
log "yはnullじゃない"
|
|
678
|
+
|
|
679
|
+
# ---- 一行関数 ----
|
|
680
|
+
fn double(int x) -> int = x * 2
|
|
681
|
+
fn greet(str name) -> str = "Hello, {name}!"
|
|
682
|
+
|
|
683
|
+
# ---- print (logのエイリアス) ----
|
|
684
|
+
print "hello world"
|
|
685
|
+
|
|
686
|
+
# ---- ビルトイン関数 ----
|
|
687
|
+
# 型変換
|
|
688
|
+
str s = str(42)
|
|
689
|
+
int n = int("42")
|
|
690
|
+
num f = float("3.14")
|
|
691
|
+
|
|
692
|
+
# 文字列操作
|
|
693
|
+
str u = upper("hello") # "HELLO"
|
|
694
|
+
str l = lower("HELLO") # "hello"
|
|
695
|
+
str t = trim(" hi ") # "hi"
|
|
696
|
+
list parts = split("a,b,c", ",") # ["a","b","c"]
|
|
697
|
+
str joined = join(parts, "-") # "a-b-c"
|
|
698
|
+
str replaced = replace("hello", "l", "r") # "herro"
|
|
699
|
+
bool has = contains("hello", "ell") # true
|
|
700
|
+
|
|
701
|
+
# コレクション操作
|
|
702
|
+
int length = len(items)
|
|
703
|
+
list sorted = sort(items)
|
|
704
|
+
list reversed = reverse(items)
|
|
705
|
+
list uniq = unique([1,1,2,3]) # [1,2,3]
|
|
706
|
+
list k = keys(obj)
|
|
707
|
+
list v = values(obj)
|
|
708
|
+
list e = entries(obj)
|
|
709
|
+
list r = range(10) # [0,1,...,9]
|
|
710
|
+
list chunks = chunk([1,2,3,4], 2) # [[1,2],[3,4]]
|
|
711
|
+
list zipped = zip([1,2], ["a","b"])
|
|
712
|
+
list flattened = flat([[1,2],[3,4]])
|
|
713
|
+
|
|
714
|
+
# 数学
|
|
715
|
+
num a2 = abs(-5)
|
|
716
|
+
num r2 = round(3.7)
|
|
717
|
+
num c = ceil(3.1)
|
|
718
|
+
num fl = floor(3.9)
|
|
719
|
+
num sq = sqrt(16)
|
|
720
|
+
num p = pow(2, 10)
|
|
721
|
+
num total = sum([1,2,3])
|
|
722
|
+
|
|
723
|
+
# JSON
|
|
724
|
+
any data2 = json_parse('{"a":1}')
|
|
725
|
+
str json = json_str(data2)
|
|
726
|
+
|
|
727
|
+
# 時間
|
|
728
|
+
int timestamp = now()
|
|
729
|
+
str timestr = time()
|
|
730
|
+
|
|
731
|
+
# I/O
|
|
732
|
+
str content = read("file.txt")
|
|
733
|
+
write("out.txt", content)
|
|
734
|
+
str answer = ask("名前は?")
|
|
735
|
+
|
|
736
|
+
# その他
|
|
737
|
+
sleep(1000)
|
|
738
|
+
exit(0)
|
package/lsp/server.js
CHANGED
|
@@ -291,6 +291,7 @@ function getCompletions() {
|
|
|
291
291
|
'page', 'cli', 'mail', 'graphql', 'desktop', 'screen',
|
|
292
292
|
'oauth', 'pay', 'storage', 'pdf', 'i18n', 'push', 'search', 'image',
|
|
293
293
|
'csv', 'logging', 'migrate', 'grpc', 'webrtc', 'blockchain',
|
|
294
|
+
'unless', 'until', 'repeat', 'enum', 'swap', 'is', 'isnt', 'print',
|
|
294
295
|
];
|
|
295
296
|
const builtins = [
|
|
296
297
|
{ label: 'uuid()', detail: 'Generate UUID v4', insertText: 'uuid()' },
|
|
@@ -315,6 +316,45 @@ function getCompletions() {
|
|
|
315
316
|
{ label: 'graphql "/path"', detail: 'GraphQL endpoint', insertText: 'graphql ' },
|
|
316
317
|
{ label: 'desktop name:', detail: 'Desktop app', insertText: 'desktop ' },
|
|
317
318
|
{ label: 'screen Name:', detail: 'Mobile screen', insertText: 'screen ' },
|
|
319
|
+
{ label: 'len(list)', detail: 'Get length', insertText: 'len(' },
|
|
320
|
+
{ label: 'sort(list)', detail: 'Sort a list', insertText: 'sort(' },
|
|
321
|
+
{ label: 'reverse(list)', detail: 'Reverse a list', insertText: 'reverse(' },
|
|
322
|
+
{ label: 'unique(list)', detail: 'Remove duplicates', insertText: 'unique(' },
|
|
323
|
+
{ label: 'upper(str)', detail: 'Uppercase string', insertText: 'upper(' },
|
|
324
|
+
{ label: 'lower(str)', detail: 'Lowercase string', insertText: 'lower(' },
|
|
325
|
+
{ label: 'trim(str)', detail: 'Trim whitespace', insertText: 'trim(' },
|
|
326
|
+
{ label: 'split(str, sep)', detail: 'Split string', insertText: 'split(' },
|
|
327
|
+
{ label: 'join(list, sep)', detail: 'Join list to string', insertText: 'join(' },
|
|
328
|
+
{ label: 'contains(list, item)', detail: 'Check if contains', insertText: 'contains(' },
|
|
329
|
+
{ label: 'replace(str, old, new)', detail: 'Replace in string', insertText: 'replace(' },
|
|
330
|
+
{ label: 'keys(map)', detail: 'Get map keys', insertText: 'keys(' },
|
|
331
|
+
{ label: 'values(map)', detail: 'Get map values', insertText: 'values(' },
|
|
332
|
+
{ label: 'entries(map)', detail: 'Get key-value pairs', insertText: 'entries(' },
|
|
333
|
+
{ label: 'range(n)', detail: 'Generate 0..n-1', insertText: 'range(' },
|
|
334
|
+
{ label: 'abs(num)', detail: 'Absolute value', insertText: 'abs(' },
|
|
335
|
+
{ label: 'round(num)', detail: 'Round number', insertText: 'round(' },
|
|
336
|
+
{ label: 'ceil(num)', detail: 'Round up', insertText: 'ceil(' },
|
|
337
|
+
{ label: 'floor(num)', detail: 'Round down', insertText: 'floor(' },
|
|
338
|
+
{ label: 'sqrt(num)', detail: 'Square root', insertText: 'sqrt(' },
|
|
339
|
+
{ label: 'pow(base, exp)', detail: 'Power', insertText: 'pow(' },
|
|
340
|
+
{ label: 'sum(list)', detail: 'Sum of list', insertText: 'sum(' },
|
|
341
|
+
{ label: 'flat(list)', detail: 'Flatten nested list', insertText: 'flat(' },
|
|
342
|
+
{ label: 'zip(a, b)', detail: 'Zip two lists', insertText: 'zip(' },
|
|
343
|
+
{ label: 'chunk(list, n)', detail: 'Split into chunks', insertText: 'chunk(' },
|
|
344
|
+
{ label: 'str(val)', detail: 'Convert to string', insertText: 'str(' },
|
|
345
|
+
{ label: 'int(val)', detail: 'Convert to integer', insertText: 'int(' },
|
|
346
|
+
{ label: 'float(val)', detail: 'Convert to float', insertText: 'float(' },
|
|
347
|
+
{ label: 'json_parse(str)', detail: 'Parse JSON string', insertText: 'json_parse(' },
|
|
348
|
+
{ label: 'json_str(val)', detail: 'Stringify to JSON', insertText: 'json_str(' },
|
|
349
|
+
{ label: 'now()', detail: 'Current timestamp ms', insertText: 'now()' },
|
|
350
|
+
{ label: 'time()', detail: 'Current ISO time', insertText: 'time()' },
|
|
351
|
+
{ label: 'ask(prompt)', detail: 'Read user input', insertText: 'ask(' },
|
|
352
|
+
{ label: 'sleep(ms)', detail: 'Wait milliseconds', insertText: 'sleep(' },
|
|
353
|
+
{ label: 'exit(code)', detail: 'Exit process', insertText: 'exit(' },
|
|
354
|
+
{ label: 'read(path)', detail: 'Read file contents', insertText: 'read(' },
|
|
355
|
+
{ label: 'write(path, data)', detail: 'Write to file', insertText: 'write(' },
|
|
356
|
+
{ label: 'fetch_json(url)', detail: 'Fetch JSON from URL', insertText: 'fetch_json(' },
|
|
357
|
+
{ label: 'random(min, max)', detail: 'Random number', insertText: 'random(' },
|
|
318
358
|
];
|
|
319
359
|
|
|
320
360
|
return [
|
|
@@ -361,6 +401,14 @@ const HOVER_DOCS = {
|
|
|
361
401
|
'grpc': '**grpc** — gRPC service\n```naide\ngrpc "users" port 50051:\n rpc getUser(id) -> user\n rpc createUser(data) -> user\n```',
|
|
362
402
|
'webrtc': '**webrtc** — WebRTC signaling\n```naide\nwebrtc "video":\n stun "stun:stun.l.google.com:19302"\n on offer(data):\n log "offer received"\n```',
|
|
363
403
|
'blockchain': '**blockchain** — Blockchain/Web3\n```naide\nblockchain "eth":\n network "ethereum"\n provider env.ETH_RPC\n contract "0x..."\n```\nUsage: `eth.getBalance(addr)`, `eth.getBlock()`',
|
|
404
|
+
'unless': '**unless** — Negated if (do X unless condition)\n```naide\nunless x > 10:\n log "small"\n```',
|
|
405
|
+
'until': '**until** — Negated while (loop until condition)\n```naide\nuntil done:\n process()\n```',
|
|
406
|
+
'repeat': '**repeat** — Simple counted loop\n```naide\nrepeat 5:\n log "hi"\nrepeat 10 as i:\n log i\n```',
|
|
407
|
+
'enum': '**enum** — Enumeration type\n```naide\nenum Color:\n RED\n GREEN\n BLUE\n```\nInline: `enum Status: ACTIVE, INACTIVE`',
|
|
408
|
+
'swap': '**swap** — Swap two variables\n```naide\nswap a, b\n```',
|
|
409
|
+
'is': '**is** — Equality comparison (===)\n```naide\nif x is 5: log "five"\n```',
|
|
410
|
+
'isnt': '**isnt** — Inequality comparison (!==)\n```naide\nif x isnt null: log "exists"\n```',
|
|
411
|
+
'print': '**print** — Alias for log\n```naide\nprint "hello world"\n```',
|
|
364
412
|
};
|
|
365
413
|
|
|
366
414
|
function getHover(params) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "naider",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "NAIDE -
|
|
3
|
+
"version": "1.17.0",
|
|
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": {
|
|
7
7
|
".": "./src/index.js",
|
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
|
}
|