naider 1.17.4 → 1.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +101 -2
- package/SPEC.naide +66 -0
- package/lsp/server.js +26 -4
- package/mcp/server.js +222 -0
- package/package.json +4 -2
- package/src/generator-c.js +65 -0
- package/src/generator-cpp.js +78 -0
- package/src/generator-csharp.js +68 -0
- package/src/generator-dart.js +74 -0
- package/src/generator-go.js +62 -0
- package/src/generator-java.js +75 -0
- package/src/generator-kotlin.js +63 -0
- package/src/generator-php.js +61 -0
- package/src/generator-python.js +86 -0
- package/src/generator-ruby.js +54 -0
- package/src/generator-rust.js +74 -0
- package/src/generator-swift.js +67 -0
- package/src/generator.js +54 -0
- package/src/parser.js +63 -1
- package/src/tokens.js +7 -0
- package/vscode-naide/syntaxes/naide.tmLanguage.json +3 -3
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
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 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.
|
|
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. 40+ built-in functions, syntax sugar (`unless`, `until`, `repeat`, `swap`, `is`/`isnt`, one-line functions, `auto` type inference, destructuring, pipe operator), and 55+ built-in features including servers, databases, authentication, bots, GraphQL, gRPC, WebRTC, blockchain, and more.
|
|
6
6
|
|
|
7
7
|
### Compilation Targets
|
|
8
8
|
|
|
@@ -136,9 +136,29 @@ any data = null
|
|
|
136
136
|
|
|
137
137
|
mut int counter = 0 # mutable (let)
|
|
138
138
|
mut str label = "init"
|
|
139
|
+
|
|
140
|
+
auto x = 42 # type inferred (const)
|
|
141
|
+
auto msg = "hello" # compiler infers str
|
|
142
|
+
mut auto counter2 = 0 # type inferred (let)
|
|
139
143
|
```
|
|
140
144
|
|
|
141
|
-
Types: `str`, `int`, `num`, `bool`, `list`, `map`, `any`, `json`, `void`
|
|
145
|
+
Types: `str`, `int`, `num`, `bool`, `list`, `map`, `any`, `json`, `void`, `auto` (inferred)
|
|
146
|
+
|
|
147
|
+
### Destructuring
|
|
148
|
+
|
|
149
|
+
```python
|
|
150
|
+
# Object destructuring
|
|
151
|
+
auto {name, age} = user
|
|
152
|
+
auto {name, age = 0} = user # with defaults
|
|
153
|
+
auto {name, ...rest} = user # with rest
|
|
154
|
+
mut {score, level} = gameState # mutable
|
|
155
|
+
|
|
156
|
+
# Array destructuring
|
|
157
|
+
auto [first, second] = items
|
|
158
|
+
auto [head, ...tail] = items # with rest
|
|
159
|
+
auto [x, y = 0] = coords # with defaults
|
|
160
|
+
mut [a, b] = pair # mutable
|
|
161
|
+
```
|
|
142
162
|
|
|
143
163
|
### String Interpolation
|
|
144
164
|
|
|
@@ -257,6 +277,28 @@ model Admin extends User:
|
|
|
257
277
|
ret ["read", "write", "delete"]
|
|
258
278
|
```
|
|
259
279
|
|
|
280
|
+
Schema inheritance with constructors and methods:
|
|
281
|
+
|
|
282
|
+
```python
|
|
283
|
+
schema Animal:
|
|
284
|
+
id auto
|
|
285
|
+
name str required
|
|
286
|
+
species str required
|
|
287
|
+
|
|
288
|
+
schema Dog extends Animal:
|
|
289
|
+
breed str optional
|
|
290
|
+
trained bool default(false)
|
|
291
|
+
|
|
292
|
+
init(str name, str breed):
|
|
293
|
+
self.name = name
|
|
294
|
+
self.breed = breed
|
|
295
|
+
|
|
296
|
+
fn bark() -> str:
|
|
297
|
+
ret "Woof! I'm {self.name}"
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
`init(params):` defines a constructor. `fn method():` defines methods. `extends` inherits all fields and methods from the parent.
|
|
301
|
+
|
|
260
302
|
### Pipe Operator
|
|
261
303
|
|
|
262
304
|
```python
|
|
@@ -264,8 +306,37 @@ list result = data
|
|
|
264
306
|
|> filter((x) => x.active)
|
|
265
307
|
|> map((x) => x.name)
|
|
266
308
|
|> sort()
|
|
309
|
+
|
|
310
|
+
int total = items
|
|
311
|
+
|> filter((x) => x > 0)
|
|
312
|
+
|> map((x) => x * 2)
|
|
313
|
+
|> reduce((a, b) => a + b, 0)
|
|
267
314
|
```
|
|
268
315
|
|
|
316
|
+
Chain operations left to right for readable data transformations.
|
|
317
|
+
|
|
318
|
+
### Optional Chaining & Null Coalescing
|
|
319
|
+
|
|
320
|
+
```python
|
|
321
|
+
str name = user?.name # safe property access
|
|
322
|
+
any val = data?.nested?.value # deep safe access
|
|
323
|
+
str display = user?.name ?? "Anonymous" # fallback on null/undefined
|
|
324
|
+
int port = config?.port ?? 3000
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
`?.` safely accesses properties (returns `undefined` if the left side is `null`/`undefined`). `??` provides a fallback value when the left side is `null` or `undefined`.
|
|
328
|
+
|
|
329
|
+
### Spread Operator
|
|
330
|
+
|
|
331
|
+
```python
|
|
332
|
+
list combined = [...listA, ...listB]
|
|
333
|
+
map merged = {...defaults, ...overrides}
|
|
334
|
+
list withExtra = [...items, 4, 5, 6]
|
|
335
|
+
map withDebug = {...config, debug: true}
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
Spread arrays and objects with `...`. Works in list literals, map literals, and function arguments.
|
|
339
|
+
|
|
269
340
|
### Imports / Exports
|
|
270
341
|
|
|
271
342
|
```python
|
|
@@ -888,6 +959,15 @@ Variables become constants. Missing `required` vars exit with an error.
|
|
|
888
959
|
## Syntax Sugar (Simpler than Python)
|
|
889
960
|
|
|
890
961
|
```python
|
|
962
|
+
# auto — type inference
|
|
963
|
+
auto x = 42
|
|
964
|
+
auto msg = "hello"
|
|
965
|
+
mut auto counter = 0
|
|
966
|
+
|
|
967
|
+
# destructuring
|
|
968
|
+
auto {name, age} = user
|
|
969
|
+
auto [first, ...rest] = items
|
|
970
|
+
|
|
891
971
|
# unless — negated if
|
|
892
972
|
unless x > 10:
|
|
893
973
|
log "small"
|
|
@@ -918,6 +998,16 @@ if y isnt null: log "exists"
|
|
|
918
998
|
# one-line functions
|
|
919
999
|
fn double(int x) -> int = x * 2
|
|
920
1000
|
|
|
1001
|
+
# pipe operator
|
|
1002
|
+
list result = items |> filter((x) => x > 0) |> map((x) => x * 2)
|
|
1003
|
+
|
|
1004
|
+
# optional chaining + null coalescing
|
|
1005
|
+
str name = user?.name ?? "Anonymous"
|
|
1006
|
+
|
|
1007
|
+
# spread
|
|
1008
|
+
list all = [...a, ...b]
|
|
1009
|
+
map merged = {...defaults, ...overrides}
|
|
1010
|
+
|
|
921
1011
|
# print alias
|
|
922
1012
|
print "hello world"
|
|
923
1013
|
```
|
|
@@ -955,6 +1045,15 @@ list flat_list = flat(nested)
|
|
|
955
1045
|
list zipped = zip(a, b)
|
|
956
1046
|
list chunks = chunk(items, 3)
|
|
957
1047
|
|
|
1048
|
+
# Functional ops (map/filter/reduce)
|
|
1049
|
+
list doubled = map(items, (x) => x * 2)
|
|
1050
|
+
list big = filter(items, (x) => x > 5)
|
|
1051
|
+
int total = reduce(items, (a, b) => a + b, 0)
|
|
1052
|
+
any found = find(items, (x) => x > 3)
|
|
1053
|
+
bool allPos = every(items, (x) => x > 0)
|
|
1054
|
+
bool hasNeg = some(items, (x) => x < 0)
|
|
1055
|
+
foreach(items, (x) => log x)
|
|
1056
|
+
|
|
958
1057
|
# Math
|
|
959
1058
|
num a = abs(-5)
|
|
960
1059
|
num r = round(3.7)
|
package/SPEC.naide
CHANGED
|
@@ -27,6 +27,26 @@ any data = null
|
|
|
27
27
|
mut int counter = 0
|
|
28
28
|
mut str label = "initial"
|
|
29
29
|
|
|
30
|
+
# auto 型推論 (コンパイラが型を推論)
|
|
31
|
+
auto x = 42 # const x = 42
|
|
32
|
+
auto msg = "hello" # const msg = "hello"
|
|
33
|
+
auto items = [1, 2, 3] # const items = [1, 2, 3]
|
|
34
|
+
mut auto counter2 = 0 # let counter2 = 0
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
# ---- 分割代入 (Destructuring) ----
|
|
38
|
+
# オブジェクト分割代入
|
|
39
|
+
auto {name2, age} = user
|
|
40
|
+
auto {name3, age2 = 0} = user # デフォルト値
|
|
41
|
+
auto {name4, ...rest} = user # レスト
|
|
42
|
+
mut {score, level} = gameState # 可変
|
|
43
|
+
|
|
44
|
+
# 配列分割代入
|
|
45
|
+
auto [first, second] = items
|
|
46
|
+
auto [head, ...tail] = items # レスト
|
|
47
|
+
auto [x2, y = 0] = coords # デフォルト値
|
|
48
|
+
mut [a3, b3] = pair # 可変
|
|
49
|
+
|
|
30
50
|
|
|
31
51
|
# ---- 文字列補間 ----
|
|
32
52
|
# ダブルクォートで {式} が自動展開
|
|
@@ -132,12 +152,29 @@ if err instanceof TypeError:
|
|
|
132
152
|
log "type error occurred"
|
|
133
153
|
|
|
134
154
|
|
|
155
|
+
# ---- map/filter/reduce ビルトイン ----
|
|
156
|
+
# コレクション操作の組み込み関数
|
|
157
|
+
list doubled = map(items, (x) => x * 2)
|
|
158
|
+
list big = filter(items, (x) => x > 5)
|
|
159
|
+
int total2 = reduce(items, (a, b) => a + b, 0)
|
|
160
|
+
any found = find(items, (x) => x > 3)
|
|
161
|
+
bool allBig = every(items, (x) => x > 0)
|
|
162
|
+
bool hasBig = some(items, (x) => x > 10)
|
|
163
|
+
foreach(items, (x) => log x)
|
|
164
|
+
|
|
165
|
+
|
|
135
166
|
# ---- パイプ演算子 ----
|
|
136
167
|
# データ変換チェーンが読みやすい
|
|
137
168
|
list result = [1, 2, 3, 4, 5]
|
|
138
169
|
|> filter((x) => x > 2)
|
|
139
170
|
|> map((x) => x * 10)
|
|
140
171
|
|
|
172
|
+
# パイプ + map/filter/reduce の組み合わせ
|
|
173
|
+
list names = users
|
|
174
|
+
|> filter((u) => u.active)
|
|
175
|
+
|> map((u) => u.name)
|
|
176
|
+
|> sort()
|
|
177
|
+
|
|
141
178
|
|
|
142
179
|
# ---- クラス (model) ----
|
|
143
180
|
model User:
|
|
@@ -159,6 +196,25 @@ model Admin extends User:
|
|
|
159
196
|
ret ["read", "write", "delete"]
|
|
160
197
|
|
|
161
198
|
|
|
199
|
+
# ---- スキーマ継承 (schema extends) ----
|
|
200
|
+
# schema も extends で継承可能
|
|
201
|
+
schema Animal:
|
|
202
|
+
id auto
|
|
203
|
+
name str required
|
|
204
|
+
species str required
|
|
205
|
+
|
|
206
|
+
schema Dog extends Animal:
|
|
207
|
+
breed str optional
|
|
208
|
+
trained bool default(false)
|
|
209
|
+
|
|
210
|
+
init(str name, str breed):
|
|
211
|
+
self.name = name
|
|
212
|
+
self.breed = breed
|
|
213
|
+
|
|
214
|
+
fn bark() -> str:
|
|
215
|
+
ret "Woof! I'm {self.name}"
|
|
216
|
+
|
|
217
|
+
|
|
162
218
|
# ---- データベース永続化 ----
|
|
163
219
|
# db ディレクトリパス → スキーマストアがJSONファイルに自動保存
|
|
164
220
|
db "data/"
|
|
@@ -436,7 +492,15 @@ pub str VERSION = "1.0.0"
|
|
|
436
492
|
|
|
437
493
|
|
|
438
494
|
# ---- null安全 ----
|
|
495
|
+
# オプショナルチェーニング (?.)
|
|
439
496
|
any val = data?.nested?.value ?? "default"
|
|
497
|
+
str userName = user?.name
|
|
498
|
+
any first = items?.[0]
|
|
499
|
+
any result2 = obj?.method?.()
|
|
500
|
+
|
|
501
|
+
# Null合体演算子 (??)
|
|
502
|
+
str displayName = user?.name ?? "Anonymous"
|
|
503
|
+
int port = config?.port ?? 3000
|
|
440
504
|
|
|
441
505
|
|
|
442
506
|
# ---- await.all (Promise.all) ----
|
|
@@ -446,6 +510,8 @@ any val = data?.nested?.value ?? "default"
|
|
|
446
510
|
# ---- スプレッド ----
|
|
447
511
|
list combined = [...items, 4, 5, 6]
|
|
448
512
|
map merged = {...config, debug: true}
|
|
513
|
+
list all = [...listA, ...listB]
|
|
514
|
+
map full = {...defaults, ...overrides}
|
|
449
515
|
|
|
450
516
|
|
|
451
517
|
# ---- ページ生成 (HTML) ----
|
package/lsp/server.js
CHANGED
|
@@ -107,7 +107,7 @@ function validateDocument(uri) {
|
|
|
107
107
|
const line = lines[i].trim();
|
|
108
108
|
if (!line || line.startsWith('#') || line.startsWith('--')) continue;
|
|
109
109
|
|
|
110
|
-
const typeMatch = line.match(/^(str|int|num|bool)\s+\w+\s*=\s*(.+)/);
|
|
110
|
+
const typeMatch = line.match(/^(str|int|num|bool|auto)\s+\w+\s*=\s*(.+)/);
|
|
111
111
|
if (typeMatch) {
|
|
112
112
|
const declType = typeMatch[1];
|
|
113
113
|
const val = typeMatch[2].trim();
|
|
@@ -163,7 +163,7 @@ function indexSymbols(uri, text) {
|
|
|
163
163
|
symbols.definitions.set(name, { line: i, col, kind: 'function' });
|
|
164
164
|
}
|
|
165
165
|
|
|
166
|
-
const varMatch = trimmed.match(/^(?:pub\s+)?(?:mut\s+)?(?:str|int|num|bool|list|map|any|json|void)\s+(\w+)\s*=/);
|
|
166
|
+
const varMatch = trimmed.match(/^(?:pub\s+)?(?:mut\s+)?(?:str|int|num|bool|list|map|any|json|void|auto)\s+(\w+)\s*=/);
|
|
167
167
|
if (varMatch) {
|
|
168
168
|
const name = varMatch[1];
|
|
169
169
|
const col = line.indexOf(name);
|
|
@@ -282,9 +282,9 @@ function getCompletions() {
|
|
|
282
282
|
'try', 'fail', 'ensure', 'server', 'model', 'schema', 'use', 'pub', 'mut',
|
|
283
283
|
'log', 'typeof', 'instanceof', 'not', 'and', 'or', 'break', 'continue',
|
|
284
284
|
'throw', 'new', 'await', 'test', 'assert', 'queue', 'job', 'db', 'env',
|
|
285
|
-
'get', 'post', 'put', 'del', 'patch', 'every', 'watch',
|
|
285
|
+
'get', 'post', 'put', 'del', 'patch', 'every', 'watch', 'extends', 'init',
|
|
286
286
|
];
|
|
287
|
-
const types = ['str', 'int', 'num', 'bool', 'list', 'map', 'any', 'json', 'void'];
|
|
287
|
+
const types = ['str', 'int', 'num', 'bool', 'list', 'map', 'any', 'json', 'void', 'auto'];
|
|
288
288
|
const features = [
|
|
289
289
|
'cors', 'auth', 'crud', 'limit', 'cookie', 'session', 'static', 'ws', 'sse',
|
|
290
290
|
'cache', 'view', 'upload', 'group', 'validate', 'openapi', 'error', 'mid', 'prompt',
|
|
@@ -355,6 +355,18 @@ function getCompletions() {
|
|
|
355
355
|
{ label: 'write(path, data)', detail: 'Write to file', insertText: 'write(' },
|
|
356
356
|
{ label: 'fetch_json(url)', detail: 'Fetch JSON from URL', insertText: 'fetch_json(' },
|
|
357
357
|
{ label: 'random(min, max)', detail: 'Random number', insertText: 'random(' },
|
|
358
|
+
{ label: 'map(list, fn)', detail: 'Transform each element', insertText: 'map(' },
|
|
359
|
+
{ label: 'filter(list, fn)', detail: 'Filter elements by condition', insertText: 'filter(' },
|
|
360
|
+
{ label: 'reduce(list, fn, init)', detail: 'Reduce list to single value', insertText: 'reduce(' },
|
|
361
|
+
{ label: 'find(list, fn)', detail: 'Find first matching element', insertText: 'find(' },
|
|
362
|
+
{ label: 'every(list, fn)', detail: 'Check if all match condition', insertText: 'every(' },
|
|
363
|
+
{ label: 'some(list, fn)', detail: 'Check if any match condition', insertText: 'some(' },
|
|
364
|
+
{ label: 'foreach(list, fn)', detail: 'Execute fn for each element', insertText: 'foreach(' },
|
|
365
|
+
{ label: 'auto', detail: 'Type inference (compiler infers type)', insertText: 'auto ' },
|
|
366
|
+
{ label: 'auto {a, b} = obj', detail: 'Object destructuring', insertText: 'auto {' },
|
|
367
|
+
{ label: 'auto [a, b] = list', detail: 'Array destructuring', insertText: 'auto [' },
|
|
368
|
+
{ label: 'extends', detail: 'Inherit from parent schema/model', insertText: 'extends ' },
|
|
369
|
+
{ label: 'init(params):', detail: 'Constructor method', insertText: 'init(' },
|
|
358
370
|
];
|
|
359
371
|
|
|
360
372
|
return [
|
|
@@ -409,6 +421,16 @@ const HOVER_DOCS = {
|
|
|
409
421
|
'is': '**is** — Equality comparison (===)\n```naide\nif x is 5: log "five"\n```',
|
|
410
422
|
'isnt': '**isnt** — Inequality comparison (!==)\n```naide\nif x isnt null: log "exists"\n```',
|
|
411
423
|
'print': '**print** — Alias for log\n```naide\nprint "hello world"\n```',
|
|
424
|
+
'auto': '**auto** — Type inference\n```naide\nauto x = 42 # compiler infers int\nauto msg = "hello" # compiler infers str\nmut auto counter = 0 # mutable, type inferred\n```\nThe compiler infers the type from the assigned value. Emits `const` (or `let` with `mut`).',
|
|
425
|
+
'extends': '**extends** — Inherit from parent\n```naide\nschema Dog extends Animal:\n breed str optional\n\nmodel Admin extends User:\n str role = "admin"\n```\nInherits all fields and methods from the parent schema or model.',
|
|
426
|
+
'init': '**init** — Constructor method\n```naide\nschema Dog extends Animal:\n init(str name, str breed):\n self.name = name\n self.breed = breed\n```\nDefines a constructor for schema/model classes.',
|
|
427
|
+
'map': '**map** — Transform each element\n```naide\nlist doubled = map(items, (x) => x * 2)\n```\nApplies a function to every element and returns a new list.',
|
|
428
|
+
'filter': '**filter** — Filter elements\n```naide\nlist big = filter(items, (x) => x > 5)\n```\nReturns a new list with only elements matching the condition.',
|
|
429
|
+
'reduce': '**reduce** — Reduce to single value\n```naide\nint total = reduce(items, (a, b) => a + b, 0)\n```\nAccumulates elements into a single value using a function and initial value.',
|
|
430
|
+
'find': '**find** — Find first match\n```naide\nany item = find(items, (x) => x > 3)\n```\nReturns the first element matching the condition, or `undefined`.',
|
|
431
|
+
'every': '**every** — Check all match\n```naide\nbool allPositive = every(items, (x) => x > 0)\n```\nReturns `true` if all elements match the condition.',
|
|
432
|
+
'some': '**some** — Check any match\n```naide\nbool hasNegative = some(items, (x) => x < 0)\n```\nReturns `true` if at least one element matches the condition.',
|
|
433
|
+
'foreach': '**foreach** — Iterate with side effects\n```naide\nforeach(items, (x) => log x)\n```\nExecutes a function for each element (no return value).',
|
|
412
434
|
};
|
|
413
435
|
|
|
414
436
|
function getHover(params) {
|
package/mcp/server.js
ADDED
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { createInterface } from 'readline';
|
|
4
|
+
import { resolve, dirname } from 'path';
|
|
5
|
+
import { readFileSync } from 'fs';
|
|
6
|
+
import { fileURLToPath } from 'url';
|
|
7
|
+
|
|
8
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
|
|
10
|
+
let compileModule = null;
|
|
11
|
+
async function getCompiler() {
|
|
12
|
+
if (!compileModule) {
|
|
13
|
+
compileModule = await import(resolve(__dirname, '..', 'src', 'index.js'));
|
|
14
|
+
}
|
|
15
|
+
return compileModule;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function send(msg) {
|
|
19
|
+
const json = JSON.stringify(msg);
|
|
20
|
+
const buf = Buffer.from(json, 'utf-8');
|
|
21
|
+
process.stdout.write(`Content-Length: ${buf.length}\r\n\r\n`);
|
|
22
|
+
process.stdout.write(buf);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function respond(id, result) {
|
|
26
|
+
send({ jsonrpc: '2.0', id, result });
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function respondError(id, code, message) {
|
|
30
|
+
send({ jsonrpc: '2.0', id, error: { code, message } });
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const TOOLS = [
|
|
34
|
+
{
|
|
35
|
+
name: 'naide_compile',
|
|
36
|
+
description: 'Compile NAIDE code to a target language. NAIDE is an AI-optimized language that transpiles to 15 targets.',
|
|
37
|
+
inputSchema: {
|
|
38
|
+
type: 'object',
|
|
39
|
+
properties: {
|
|
40
|
+
code: { type: 'string', description: 'NAIDE source code to compile' },
|
|
41
|
+
target: {
|
|
42
|
+
type: 'string',
|
|
43
|
+
description: 'Target language (default: node)',
|
|
44
|
+
enum: ['node', 'python', 'bun', 'typescript', 'go', 'java', 'rust', 'cpp', 'c', 'csharp', 'kotlin', 'swift', 'dart', 'php', 'ruby']
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
required: ['code']
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
name: 'naide_run',
|
|
52
|
+
description: 'Compile NAIDE code to JavaScript and execute it. Returns stdout output.',
|
|
53
|
+
inputSchema: {
|
|
54
|
+
type: 'object',
|
|
55
|
+
properties: {
|
|
56
|
+
code: { type: 'string', description: 'NAIDE source code to run' }
|
|
57
|
+
},
|
|
58
|
+
required: ['code']
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
name: 'naide_targets',
|
|
63
|
+
description: 'List all available NAIDE compilation targets with details.',
|
|
64
|
+
inputSchema: { type: 'object', properties: {} }
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
name: 'naide_spec',
|
|
68
|
+
description: 'Get the NAIDE language specification. Use this to understand NAIDE syntax before writing code.',
|
|
69
|
+
inputSchema: {
|
|
70
|
+
type: 'object',
|
|
71
|
+
properties: {
|
|
72
|
+
section: {
|
|
73
|
+
type: 'string',
|
|
74
|
+
description: 'Optional section to retrieve (e.g. "variables", "functions", "server"). Omit for full spec.'
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
];
|
|
80
|
+
|
|
81
|
+
const TARGETS_INFO = [
|
|
82
|
+
{ name: 'node', language: 'JavaScript (ES Modules)', server: 'Express', flag: 'default' },
|
|
83
|
+
{ name: 'python', language: 'Python', server: 'Flask', flag: '--target python' },
|
|
84
|
+
{ name: 'bun', language: 'JavaScript (Bun)', server: 'Bun.serve', flag: '--target bun' },
|
|
85
|
+
{ name: 'typescript', language: 'TypeScript', server: 'Express', flag: '--target ts' },
|
|
86
|
+
{ name: 'go', language: 'Go', server: 'net/http', flag: '--target go' },
|
|
87
|
+
{ name: 'java', language: 'Java', server: 'HttpServer', flag: '--target java' },
|
|
88
|
+
{ name: 'rust', language: 'Rust', server: 'actix-web', flag: '--target rust' },
|
|
89
|
+
{ name: 'cpp', language: 'C++', server: 'cpp-httplib', flag: '--target cpp' },
|
|
90
|
+
{ name: 'c', language: 'C', server: 'libmicrohttpd', flag: '--target c' },
|
|
91
|
+
{ name: 'csharp', language: 'C#', server: 'ASP.NET', flag: '--target csharp' },
|
|
92
|
+
{ name: 'kotlin', language: 'Kotlin', server: 'Ktor', flag: '--target kotlin' },
|
|
93
|
+
{ name: 'swift', language: 'Swift', server: 'Vapor', flag: '--target swift' },
|
|
94
|
+
{ name: 'dart', language: 'Dart', server: 'shelf', flag: '--target dart' },
|
|
95
|
+
{ name: 'php', language: 'PHP', server: 'Built-in / Laravel', flag: '--target php' },
|
|
96
|
+
{ name: 'ruby', language: 'Ruby', server: 'Sinatra', flag: '--target ruby' },
|
|
97
|
+
];
|
|
98
|
+
|
|
99
|
+
async function handleToolCall(name, args) {
|
|
100
|
+
const { compile, compileAsync } = await getCompiler();
|
|
101
|
+
|
|
102
|
+
switch (name) {
|
|
103
|
+
case 'naide_compile': {
|
|
104
|
+
const target = args.target || 'node';
|
|
105
|
+
try {
|
|
106
|
+
if (target === 'node') {
|
|
107
|
+
const result = compile(args.code);
|
|
108
|
+
return { content: [{ type: 'text', text: result.js }] };
|
|
109
|
+
}
|
|
110
|
+
const result = await compileAsync(args.code, { target });
|
|
111
|
+
return { content: [{ type: 'text', text: result.code }] };
|
|
112
|
+
} catch (e) {
|
|
113
|
+
return { content: [{ type: 'text', text: `Compilation error: ${e.message}` }], isError: true };
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
case 'naide_run': {
|
|
118
|
+
try {
|
|
119
|
+
const result = compile(args.code);
|
|
120
|
+
const AsyncFunction = Object.getPrototypeOf(async function(){}).constructor;
|
|
121
|
+
let output = '';
|
|
122
|
+
const fakeConsole = { log: (...a) => { output += a.map(String).join(' ') + '\n'; }, error: (...a) => { output += a.map(String).join(' ') + '\n'; } };
|
|
123
|
+
const fn = new AsyncFunction('console', result.js);
|
|
124
|
+
await fn(fakeConsole);
|
|
125
|
+
return { content: [{ type: 'text', text: output || '(no output)' }] };
|
|
126
|
+
} catch (e) {
|
|
127
|
+
return { content: [{ type: 'text', text: `Error: ${e.message}` }], isError: true };
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
case 'naide_targets': {
|
|
132
|
+
const text = TARGETS_INFO.map(t => `${t.name.padEnd(12)} ${t.language.padEnd(25)} ${t.server.padEnd(20)} ${t.flag}`).join('\n');
|
|
133
|
+
return { content: [{ type: 'text', text: `NAIDE Compilation Targets (15):\n\n${'Target'.padEnd(12)} ${'Language'.padEnd(25)} ${'Server'.padEnd(20)} Flag\n${'─'.repeat(75)}\n${text}` }] };
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
case 'naide_spec': {
|
|
137
|
+
try {
|
|
138
|
+
let spec = readFileSync(resolve(__dirname, '..', 'SPEC.naide'), 'utf-8');
|
|
139
|
+
if (args.section) {
|
|
140
|
+
const s = args.section.toLowerCase();
|
|
141
|
+
const lines = spec.split('\n');
|
|
142
|
+
const chunks = [];
|
|
143
|
+
let capturing = false;
|
|
144
|
+
for (const line of lines) {
|
|
145
|
+
if (line.startsWith('# ---- ') && line.toLowerCase().includes(s)) capturing = true;
|
|
146
|
+
else if (line.startsWith('# ---- ') && capturing) break;
|
|
147
|
+
if (capturing) chunks.push(line);
|
|
148
|
+
}
|
|
149
|
+
if (chunks.length > 0) spec = chunks.join('\n');
|
|
150
|
+
}
|
|
151
|
+
return { content: [{ type: 'text', text: spec }] };
|
|
152
|
+
} catch (e) {
|
|
153
|
+
return { content: [{ type: 'text', text: `Error reading spec: ${e.message}` }], isError: true };
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
default:
|
|
158
|
+
return { content: [{ type: 'text', text: `Unknown tool: ${name}` }], isError: true };
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
async function handleMessage(msg) {
|
|
163
|
+
switch (msg.method) {
|
|
164
|
+
case 'initialize':
|
|
165
|
+
respond(msg.id, {
|
|
166
|
+
protocolVersion: '2024-11-05',
|
|
167
|
+
capabilities: { tools: {} },
|
|
168
|
+
serverInfo: { name: 'naide-mcp', version: '1.18.0' }
|
|
169
|
+
});
|
|
170
|
+
break;
|
|
171
|
+
|
|
172
|
+
case 'notifications/initialized':
|
|
173
|
+
break;
|
|
174
|
+
|
|
175
|
+
case 'tools/list':
|
|
176
|
+
respond(msg.id, { tools: TOOLS });
|
|
177
|
+
break;
|
|
178
|
+
|
|
179
|
+
case 'tools/call':
|
|
180
|
+
try {
|
|
181
|
+
const result = await handleToolCall(msg.params.name, msg.params.arguments || {});
|
|
182
|
+
respond(msg.id, result);
|
|
183
|
+
} catch (e) {
|
|
184
|
+
respondError(msg.id, -32000, e.message);
|
|
185
|
+
}
|
|
186
|
+
break;
|
|
187
|
+
|
|
188
|
+
case 'ping':
|
|
189
|
+
respond(msg.id, {});
|
|
190
|
+
break;
|
|
191
|
+
|
|
192
|
+
default:
|
|
193
|
+
if (msg.id !== undefined) {
|
|
194
|
+
respondError(msg.id, -32601, `Method not found: ${msg.method}`);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
let buffer = '';
|
|
200
|
+
process.stdin.setEncoding('utf-8');
|
|
201
|
+
process.stdin.on('data', (chunk) => {
|
|
202
|
+
buffer += chunk;
|
|
203
|
+
while (true) {
|
|
204
|
+
const headerEnd = buffer.indexOf('\r\n\r\n');
|
|
205
|
+
if (headerEnd === -1) break;
|
|
206
|
+
const header = buffer.slice(0, headerEnd);
|
|
207
|
+
const match = header.match(/Content-Length:\s*(\d+)/i);
|
|
208
|
+
if (!match) { buffer = buffer.slice(headerEnd + 4); continue; }
|
|
209
|
+
const len = parseInt(match[1], 10);
|
|
210
|
+
const bodyStart = headerEnd + 4;
|
|
211
|
+
if (buffer.length < bodyStart + len) break;
|
|
212
|
+
const body = buffer.slice(bodyStart, bodyStart + len);
|
|
213
|
+
buffer = buffer.slice(bodyStart + len);
|
|
214
|
+
try {
|
|
215
|
+
handleMessage(JSON.parse(body));
|
|
216
|
+
} catch (e) {
|
|
217
|
+
process.stderr.write(`Parse error: ${e.message}\n`);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
process.stderr.write('NAIDE MCP Server running on stdio\n');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "naider",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.19.0",
|
|
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": {
|
|
@@ -8,13 +8,15 @@
|
|
|
8
8
|
"./runtime": "./src/runtime.js"
|
|
9
9
|
},
|
|
10
10
|
"bin": {
|
|
11
|
-
"naide": "bin/naide.js"
|
|
11
|
+
"naide": "bin/naide.js",
|
|
12
|
+
"naide-mcp": "mcp/server.js"
|
|
12
13
|
},
|
|
13
14
|
"type": "module",
|
|
14
15
|
"files": [
|
|
15
16
|
"bin/",
|
|
16
17
|
"src/",
|
|
17
18
|
"assets/",
|
|
19
|
+
"mcp/",
|
|
18
20
|
"lsp/",
|
|
19
21
|
"examples/",
|
|
20
22
|
"vscode-naide/",
|
package/src/generator-c.js
CHANGED
|
@@ -187,6 +187,8 @@ export class CGenerator {
|
|
|
187
187
|
case 'BlockchainDecl': return this.visitBlockchain(node);
|
|
188
188
|
case 'EnumDecl': return this.visitEnum(node);
|
|
189
189
|
case 'Swap': return this.visitSwap(node);
|
|
190
|
+
case 'Destructure': return this.visitDestructure(node);
|
|
191
|
+
case 'ClassDecl': return this.visitClassDecl(node);
|
|
190
192
|
default:
|
|
191
193
|
this.emit(`/* unknown: ${node.type} */`);
|
|
192
194
|
}
|
|
@@ -1000,6 +1002,62 @@ export class CGenerator {
|
|
|
1000
1002
|
this.emit(`{ typeof(${a}) ${tmp} = ${a}; ${a} = ${b}; ${b} = ${tmp}; }`);
|
|
1001
1003
|
}
|
|
1002
1004
|
|
|
1005
|
+
visitDestructure(node) {
|
|
1006
|
+
const val = this.expr(node.value);
|
|
1007
|
+
if (node.pattern === 'array') {
|
|
1008
|
+
node.names.forEach((n, i) => {
|
|
1009
|
+
if (!n.rest) {
|
|
1010
|
+
const varName = n.alias || n.name;
|
|
1011
|
+
this.emit(`auto ${varName} = ${val}[${i}];`);
|
|
1012
|
+
}
|
|
1013
|
+
});
|
|
1014
|
+
} else {
|
|
1015
|
+
for (const n of node.names) {
|
|
1016
|
+
if (!n.rest) {
|
|
1017
|
+
const varName = n.alias || n.name;
|
|
1018
|
+
this.emit(`auto ${varName} = ${val}["${n.name}"];`);
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
visitClassDecl(node) {
|
|
1025
|
+
this.emit(`/* C does not support classes; using struct + functions for ${node.name} */`);
|
|
1026
|
+
this.emit(`typedef struct {`);
|
|
1027
|
+
this.indent++;
|
|
1028
|
+
for (const field of node.fields) {
|
|
1029
|
+
this.emit(`void* ${field.name};`);
|
|
1030
|
+
}
|
|
1031
|
+
if (node.fields.length === 0) this.emit(`int __placeholder;`);
|
|
1032
|
+
this.indent--;
|
|
1033
|
+
this.emit(`} ${node.name};`);
|
|
1034
|
+
this.emitRaw('');
|
|
1035
|
+
if (node.init) {
|
|
1036
|
+
const params = node.init.params.map(p => `void* ${p.name}`).join(', ');
|
|
1037
|
+
this.emit(`${node.name} ${node.name}_create(${params || 'void'}) {`);
|
|
1038
|
+
this.indent++;
|
|
1039
|
+
this.emit(`${node.name} self;`);
|
|
1040
|
+
for (const stmt of node.init.body) this.visitStatement(stmt);
|
|
1041
|
+
this.emit(`return self;`);
|
|
1042
|
+
this.indent--;
|
|
1043
|
+
this.emit(`}`);
|
|
1044
|
+
this.emitRaw('');
|
|
1045
|
+
}
|
|
1046
|
+
for (const method of node.methods) {
|
|
1047
|
+
const params = [`${node.name}* self`, ...method.params.map(p => `void* ${p.name}`)].join(', ');
|
|
1048
|
+
this.emit(`void* ${node.name}_${method.name}(${params}) {`);
|
|
1049
|
+
this.indent++;
|
|
1050
|
+
if (method.body.length === 0) {
|
|
1051
|
+
this.emit('return NULL;');
|
|
1052
|
+
} else {
|
|
1053
|
+
for (const stmt of method.body) this.visitStatement(stmt);
|
|
1054
|
+
}
|
|
1055
|
+
this.indent--;
|
|
1056
|
+
this.emit(`}`);
|
|
1057
|
+
this.emitRaw('');
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1003
1061
|
generateBuiltin(name, args) {
|
|
1004
1062
|
switch (name) {
|
|
1005
1063
|
case 'len': return `(sizeof(${args[0]}) / sizeof(${args[0]}[0]))`;
|
|
@@ -1018,6 +1076,13 @@ export class CGenerator {
|
|
|
1018
1076
|
case 'sleep': { this.includes.add('<unistd.h>'); return `usleep(${args[0]} * 1000)`; }
|
|
1019
1077
|
case 'now': { this.includes.add('<time.h>'); return `(long long)time(NULL) * 1000`; }
|
|
1020
1078
|
case 'random': { this.includes.add('<stdlib.h>'); return args.length >= 2 ? `(rand() % (${args[1]} - ${args[0]} + 1) + ${args[0]})` : `rand()`; }
|
|
1079
|
+
case 'map': return `/* C: map requires manual loop over ${args[0]} with ${args[1]} */`;
|
|
1080
|
+
case 'filter': return `/* C: filter requires manual loop over ${args[0]} with ${args[1]} */`;
|
|
1081
|
+
case 'reduce': return `/* C: reduce requires manual loop over ${args[0]} with ${args[1]} */`;
|
|
1082
|
+
case 'find': return `/* C: find requires manual loop over ${args[0]} with ${args[1]} */`;
|
|
1083
|
+
case 'every': return `/* C: every requires manual loop over ${args[0]} with ${args[1]} */`;
|
|
1084
|
+
case 'some': return `/* C: some requires manual loop over ${args[0]} with ${args[1]} */`;
|
|
1085
|
+
case 'foreach': return `for (int _i = 0; _i < sizeof(${args[0]})/sizeof(${args[0]}[0]); _i++) { ${args[1]}(${args[0]}[_i]); }`;
|
|
1021
1086
|
default: return null;
|
|
1022
1087
|
}
|
|
1023
1088
|
}
|