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 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 three principles: 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. 47 built-in features including servers, databases, authentication, bots, GraphQL, gRPC, WebRTC, blockchain, and more.
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
- str id = uuid() # UUID
892
- str hashed = hash("password") # scrypt hash
893
- bool ok = verify("password", hashed) # timing-safe verify
894
- str token = sign({id: 1}) # JWT (uses auth secret)
895
- str token = sign({id: 1}, "my-secret") # JWT (explicit secret)
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.15.0",
4
- "description": "NAIDE - Node AI Development Environment. AI-specialized language transpiling to 15 targets: Node.js, Python, Bun, TypeScript, C, C++, Java, Go, Rust, PHP, Ruby, Kotlin, Swift, Dart, C#. Built-in server, auth, DB, AI/LLM, bots, GraphQL, gRPC, WebRTC, blockchain, and 47 more features.",
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",
@@ -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;
@@ -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
  }
@@ -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
  }