naidejs 1.0.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/LICENSE +21 -0
- package/README.md +171 -0
- package/SPEC-X.nx +144 -0
- package/SPEC.naide +182 -0
- package/bin/naide.js +124 -0
- package/examples/async.naide +50 -0
- package/examples/async.nx +40 -0
- package/examples/crud.naide +79 -0
- package/examples/crud.nx +64 -0
- package/examples/hello.naide +33 -0
- package/examples/hello.nx +29 -0
- package/examples/model.naide +44 -0
- package/examples/server.naide +28 -0
- package/examples/server.nx +27 -0
- package/package.json +46 -0
- package/src/generator.js +573 -0
- package/src/index.js +23 -0
- package/src/lexer.js +389 -0
- package/src/parser.js +1079 -0
- package/src/preprocess.js +286 -0
- package/src/tokens.js +162 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
-- NAIDE-X async/await
|
|
2
|
+
|
|
3
|
+
~f fetchData(s:url)a
|
|
4
|
+
a:res=~fetch(url)
|
|
5
|
+
a:data=~res.json()
|
|
6
|
+
>data
|
|
7
|
+
|
|
8
|
+
~f getTopUsers()l
|
|
9
|
+
a:data=~fetchData("https://jsonplaceholder.typicode.com/users")
|
|
10
|
+
l:result=data
|
|
11
|
+
|>filter((u)=>u.name.length>5)
|
|
12
|
+
|>map((u)=>({name:u.name,email:u.email}))
|
|
13
|
+
>result
|
|
14
|
+
|
|
15
|
+
~f safeFetch(s:url)m
|
|
16
|
+
!
|
|
17
|
+
a:data=~fetchData(url)
|
|
18
|
+
>{ok:true,data:data}
|
|
19
|
+
!!e
|
|
20
|
+
log.e"Fetch failed: {e.message}"
|
|
21
|
+
>{ok:false,error:e.message}
|
|
22
|
+
|
|
23
|
+
~f loadDash()m
|
|
24
|
+
l:urls=[
|
|
25
|
+
"https://jsonplaceholder.typicode.com/users",
|
|
26
|
+
"https://jsonplaceholder.typicode.com/posts",
|
|
27
|
+
"https://jsonplaceholder.typicode.com/todos"
|
|
28
|
+
]
|
|
29
|
+
l:results=~~urls.map((url)=>fetchData(url))
|
|
30
|
+
>{users:results[0],posts:results[1],todos:results[2]}
|
|
31
|
+
|
|
32
|
+
~f main()
|
|
33
|
+
log"Fetching data..."
|
|
34
|
+
m:dash=~safeFetch("https://jsonplaceholder.typicode.com/users")
|
|
35
|
+
?dash.ok
|
|
36
|
+
log"Got {dash.data.length} items"
|
|
37
|
+
:
|
|
38
|
+
log.e dash.error
|
|
39
|
+
|
|
40
|
+
main()
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# NAIDE - Full CRUD Application
|
|
2
|
+
# モデル定義 + サーバー + エラーハンドリング
|
|
3
|
+
|
|
4
|
+
# データモデル
|
|
5
|
+
model Todo:
|
|
6
|
+
str id
|
|
7
|
+
str title
|
|
8
|
+
bool done = false
|
|
9
|
+
str createdAt
|
|
10
|
+
|
|
11
|
+
fn toggle():
|
|
12
|
+
self.done = not self.done
|
|
13
|
+
|
|
14
|
+
fn toJSON() -> map:
|
|
15
|
+
ret {
|
|
16
|
+
id: self.id,
|
|
17
|
+
title: self.title,
|
|
18
|
+
done: self.done,
|
|
19
|
+
createdAt: self.createdAt
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
# インメモリストア
|
|
23
|
+
mut list todos = []
|
|
24
|
+
mut int nextId = 1
|
|
25
|
+
|
|
26
|
+
# ヘルパー関数
|
|
27
|
+
fn findTodo(str id) -> any:
|
|
28
|
+
each todo in todos:
|
|
29
|
+
if todo.id == id:
|
|
30
|
+
ret todo
|
|
31
|
+
ret null
|
|
32
|
+
|
|
33
|
+
fn generateId() -> str:
|
|
34
|
+
str id = "todo_{nextId}"
|
|
35
|
+
nextId += 1
|
|
36
|
+
ret id
|
|
37
|
+
|
|
38
|
+
# APIサーバー
|
|
39
|
+
server app port 8080:
|
|
40
|
+
|
|
41
|
+
get "/api/todos":
|
|
42
|
+
ret {todos: todos, count: todos.length}
|
|
43
|
+
|
|
44
|
+
get "/api/todos/:id" (req, res):
|
|
45
|
+
any todo = findTodo(req.params.id)
|
|
46
|
+
if todo == null:
|
|
47
|
+
ret.status 404 {error: "Todo not found"}
|
|
48
|
+
ret todo
|
|
49
|
+
|
|
50
|
+
post "/api/todos" (req, res):
|
|
51
|
+
map body = req.body
|
|
52
|
+
if not body.title:
|
|
53
|
+
ret.status 400 {error: "Title is required"}
|
|
54
|
+
map todo = {
|
|
55
|
+
id: generateId(),
|
|
56
|
+
title: body.title,
|
|
57
|
+
done: false,
|
|
58
|
+
createdAt: new Date().toISOString()
|
|
59
|
+
}
|
|
60
|
+
todos.push(todo)
|
|
61
|
+
ret.status 201 todo
|
|
62
|
+
|
|
63
|
+
put "/api/todos/:id" (req, res):
|
|
64
|
+
any todo = findTodo(req.params.id)
|
|
65
|
+
if todo == null:
|
|
66
|
+
ret.status 404 {error: "Todo not found"}
|
|
67
|
+
map body = req.body
|
|
68
|
+
if body.title:
|
|
69
|
+
todo.title = body.title
|
|
70
|
+
if body.done != null:
|
|
71
|
+
todo.done = body.done
|
|
72
|
+
ret todo
|
|
73
|
+
|
|
74
|
+
del "/api/todos/:id" (req, res):
|
|
75
|
+
int idx = todos.findIndex((t) => t.id == req.params.id)
|
|
76
|
+
if idx == -1:
|
|
77
|
+
ret.status 404 {error: "Todo not found"}
|
|
78
|
+
todos.splice(idx, 1)
|
|
79
|
+
ret {status: "deleted"}
|
package/examples/crud.nx
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
-- NAIDE-X full CRUD
|
|
2
|
+
|
|
3
|
+
^Todo
|
|
4
|
+
s:id
|
|
5
|
+
s:title
|
|
6
|
+
b:done=false
|
|
7
|
+
s:createdAt
|
|
8
|
+
|
|
9
|
+
f toggle()
|
|
10
|
+
self.done=not self.done
|
|
11
|
+
|
|
12
|
+
f toJSON()m
|
|
13
|
+
>{id:self.id,title:self.title,done:self.done,createdAt:self.createdAt}
|
|
14
|
+
|
|
15
|
+
~l:todos=[]
|
|
16
|
+
~i:nextId=1
|
|
17
|
+
|
|
18
|
+
f findTodo(s:id)a
|
|
19
|
+
@todo<todos
|
|
20
|
+
?todo.id==id
|
|
21
|
+
>todo
|
|
22
|
+
>null
|
|
23
|
+
|
|
24
|
+
f genId()s
|
|
25
|
+
s:id="todo_{nextId}"
|
|
26
|
+
nextId+=1
|
|
27
|
+
>id
|
|
28
|
+
|
|
29
|
+
$app:8080
|
|
30
|
+
|
|
31
|
+
G"/api/todos"
|
|
32
|
+
>{todos:todos,count:todos.length}
|
|
33
|
+
|
|
34
|
+
G"/api/todos/:id"(req,res)
|
|
35
|
+
a:todo=findTodo(req.params.id)
|
|
36
|
+
?todo==null
|
|
37
|
+
>.s 404 {error:"Todo not found"}
|
|
38
|
+
>todo
|
|
39
|
+
|
|
40
|
+
P"/api/todos"(req,res)
|
|
41
|
+
m:body=req.body
|
|
42
|
+
?not body.title
|
|
43
|
+
>.s 400 {error:"Title is required"}
|
|
44
|
+
m:todo={id:genId(),title:body.title,done:false,createdAt:new Date().toISOString()}
|
|
45
|
+
todos.push(todo)
|
|
46
|
+
>.s 201 todo
|
|
47
|
+
|
|
48
|
+
U"/api/todos/:id"(req,res)
|
|
49
|
+
a:todo=findTodo(req.params.id)
|
|
50
|
+
?todo==null
|
|
51
|
+
>.s 404 {error:"Todo not found"}
|
|
52
|
+
m:body=req.body
|
|
53
|
+
?body.title
|
|
54
|
+
todo.title=body.title
|
|
55
|
+
?body.done!=null
|
|
56
|
+
todo.done=body.done
|
|
57
|
+
>todo
|
|
58
|
+
|
|
59
|
+
D"/api/todos/:id"(req,res)
|
|
60
|
+
i:idx=todos.findIndex((t)=>t.id==req.params.id)
|
|
61
|
+
?idx==-1
|
|
62
|
+
>.s 404 {error:"Todo not found"}
|
|
63
|
+
todos.splice(idx,1)
|
|
64
|
+
>{status:"deleted"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# NAIDE - Hello World
|
|
2
|
+
# AIが最速で生成できる言語
|
|
3
|
+
|
|
4
|
+
str name = "World"
|
|
5
|
+
int count = 3
|
|
6
|
+
|
|
7
|
+
fn greet(str who) -> str:
|
|
8
|
+
ret "Hello, {who}!"
|
|
9
|
+
|
|
10
|
+
for i in 0..count:
|
|
11
|
+
str message = greet(name)
|
|
12
|
+
log message
|
|
13
|
+
|
|
14
|
+
# 条件分岐
|
|
15
|
+
if count > 5:
|
|
16
|
+
log "many"
|
|
17
|
+
elif count > 2:
|
|
18
|
+
log "a few"
|
|
19
|
+
else:
|
|
20
|
+
log "few"
|
|
21
|
+
|
|
22
|
+
# リスト操作
|
|
23
|
+
list items = ["apple", "banana", "cherry"]
|
|
24
|
+
|
|
25
|
+
each fruit in items:
|
|
26
|
+
log "I like {fruit}"
|
|
27
|
+
|
|
28
|
+
# マッチ
|
|
29
|
+
str status = "ok"
|
|
30
|
+
match status:
|
|
31
|
+
"ok": log "All good"
|
|
32
|
+
"error": log "Something went wrong"
|
|
33
|
+
_: log "Unknown status"
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
-- NAIDE-X hello world
|
|
2
|
+
|
|
3
|
+
s:name="World"
|
|
4
|
+
i:count=3
|
|
5
|
+
|
|
6
|
+
f greet(s:who)s
|
|
7
|
+
>"Hello, {who}!"
|
|
8
|
+
|
|
9
|
+
@i<0..count
|
|
10
|
+
s:msg=greet(name)
|
|
11
|
+
log msg
|
|
12
|
+
|
|
13
|
+
?count>5
|
|
14
|
+
log"many"
|
|
15
|
+
|count>2
|
|
16
|
+
log"a few"
|
|
17
|
+
:
|
|
18
|
+
log"few"
|
|
19
|
+
|
|
20
|
+
l:items=["apple","banana","cherry"]
|
|
21
|
+
|
|
22
|
+
@fruit<items
|
|
23
|
+
log"I like {fruit}"
|
|
24
|
+
|
|
25
|
+
s:status="ok"
|
|
26
|
+
%status
|
|
27
|
+
"ok": log "All good"
|
|
28
|
+
"error": log "Something went wrong"
|
|
29
|
+
_: log "Unknown"
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# NAIDE - Model (Class) の例
|
|
2
|
+
# AIがクラスを最速で書ける構文
|
|
3
|
+
|
|
4
|
+
model Animal:
|
|
5
|
+
str name
|
|
6
|
+
str sound
|
|
7
|
+
int age = 0
|
|
8
|
+
|
|
9
|
+
fn speak() -> str:
|
|
10
|
+
ret "{self.name} says {self.sound}!"
|
|
11
|
+
|
|
12
|
+
fn isOld() -> bool:
|
|
13
|
+
ret self.age > 10
|
|
14
|
+
|
|
15
|
+
model Dog extends Animal:
|
|
16
|
+
str breed
|
|
17
|
+
|
|
18
|
+
fn fetch(str item) -> str:
|
|
19
|
+
ret "{self.name} fetched the {item}!"
|
|
20
|
+
|
|
21
|
+
# インスタンス作成
|
|
22
|
+
any dog = new Dog("Rex", "Woof", 5, "Labrador")
|
|
23
|
+
log dog.speak()
|
|
24
|
+
log dog.fetch("ball")
|
|
25
|
+
|
|
26
|
+
if dog.isOld():
|
|
27
|
+
log "{dog.name} is old"
|
|
28
|
+
else:
|
|
29
|
+
log "{dog.name} is young"
|
|
30
|
+
|
|
31
|
+
# リスト操作 + パイプ
|
|
32
|
+
list animals = [
|
|
33
|
+
new Animal("Cat", "Meow", 3),
|
|
34
|
+
new Animal("Bird", "Tweet", 12),
|
|
35
|
+
new Animal("Fish", "Blub", 1)
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
list oldAnimals = animals
|
|
39
|
+
|> filter((a) => a.age > 5)
|
|
40
|
+
|> map((a) => a.name)
|
|
41
|
+
|
|
42
|
+
log "Old animals:"
|
|
43
|
+
each name in oldAnimals:
|
|
44
|
+
log " - {name}"
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# NAIDE - REST API Server
|
|
2
|
+
# 従来のExpressだと30行以上 → NAIDEなら直感的
|
|
3
|
+
|
|
4
|
+
server app port 3000:
|
|
5
|
+
|
|
6
|
+
get "/":
|
|
7
|
+
ret {message: "Welcome to NAIDE API"}
|
|
8
|
+
|
|
9
|
+
get "/users":
|
|
10
|
+
list users = [
|
|
11
|
+
{id: 1, name: "Alice", age: 30},
|
|
12
|
+
{id: 2, name: "Bob", age: 25}
|
|
13
|
+
]
|
|
14
|
+
ret users
|
|
15
|
+
|
|
16
|
+
get "/users/:id" (req, res):
|
|
17
|
+
str id = req.params.id
|
|
18
|
+
ret {id: id, name: "User {id}"}
|
|
19
|
+
|
|
20
|
+
post "/users" (req, res):
|
|
21
|
+
map body = req.body
|
|
22
|
+
log "Creating user: {body.name}"
|
|
23
|
+
ret {status: "created", user: body}
|
|
24
|
+
|
|
25
|
+
del "/users/:id" (req, res):
|
|
26
|
+
str id = req.params.id
|
|
27
|
+
log "Deleting user {id}"
|
|
28
|
+
ret {status: "deleted", id: id}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
-- NAIDE-X REST API server
|
|
2
|
+
|
|
3
|
+
$app:3000
|
|
4
|
+
|
|
5
|
+
G"/"
|
|
6
|
+
>{message:"Welcome to NAIDE-X API"}
|
|
7
|
+
|
|
8
|
+
G"/users"
|
|
9
|
+
l:users=[
|
|
10
|
+
{id:1,name:"Alice",age:30},
|
|
11
|
+
{id:2,name:"Bob",age:25}
|
|
12
|
+
]
|
|
13
|
+
>users
|
|
14
|
+
|
|
15
|
+
G"/users/:id"(req,res)
|
|
16
|
+
s:id=req.params.id
|
|
17
|
+
>{id:id,name:"User {id}"}
|
|
18
|
+
|
|
19
|
+
P"/users"(req,res)
|
|
20
|
+
m:body=req.body
|
|
21
|
+
log"Creating user: {body.name}"
|
|
22
|
+
>{status:"created",user:body}
|
|
23
|
+
|
|
24
|
+
D"/users/:id"(req,res)
|
|
25
|
+
s:id=req.params.id
|
|
26
|
+
log"Deleting user {id}"
|
|
27
|
+
>{status:"deleted",id:id}
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "naidejs",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "NAIDE - Node AI Development Environment. A language optimized for AI code generation that transpiles to Node.js. Standard mode (~40% fewer tokens) and X mode (~80% fewer tokens).",
|
|
5
|
+
"main": "src/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"naide": "bin/naide.js"
|
|
8
|
+
},
|
|
9
|
+
"type": "module",
|
|
10
|
+
"files": [
|
|
11
|
+
"bin/",
|
|
12
|
+
"src/",
|
|
13
|
+
"examples/",
|
|
14
|
+
"SPEC.naide",
|
|
15
|
+
"SPEC-X.nx",
|
|
16
|
+
"README.md",
|
|
17
|
+
"LICENSE"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"test": "node --test test/test.js",
|
|
21
|
+
"example": "node bin/naide.js examples/hello.naide",
|
|
22
|
+
"example:x": "node bin/naide.js examples/hello.nx"
|
|
23
|
+
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"ai",
|
|
26
|
+
"language",
|
|
27
|
+
"transpiler",
|
|
28
|
+
"nodejs",
|
|
29
|
+
"code-generation",
|
|
30
|
+
"llm",
|
|
31
|
+
"claude",
|
|
32
|
+
"chatgpt",
|
|
33
|
+
"naide",
|
|
34
|
+
"dsl"
|
|
35
|
+
],
|
|
36
|
+
"author": "pirikari.sena@gmail.com",
|
|
37
|
+
"license": "MIT",
|
|
38
|
+
"repository": {
|
|
39
|
+
"type": "git",
|
|
40
|
+
"url": "https://github.com/pirikari/naide"
|
|
41
|
+
},
|
|
42
|
+
"homepage": "https://github.com/pirikari/naide#readme",
|
|
43
|
+
"engines": {
|
|
44
|
+
"node": ">=18.0.0"
|
|
45
|
+
}
|
|
46
|
+
}
|