297 lines
8.4 KiB
Plaintext
297 lines
8.4 KiB
Plaintext
|
|
================================================================================
|
|||
|
|
Nyash つよつよ糖衣構文提案 - 自己ホスティングに向けて
|
|||
|
|
2025-09-03
|
|||
|
|
================================================================================
|
|||
|
|
|
|||
|
|
【背景】
|
|||
|
|
自己ホスティング(NyashでNyashコンパイラを書く)を実現するため、
|
|||
|
|
コード量を劇的に削減できる強力な糖衣構文を検討する。
|
|||
|
|
|
|||
|
|
================================================================================
|
|||
|
|
1. パイプライン演算子 |> (優先度:最高)
|
|||
|
|
================================================================================
|
|||
|
|
|
|||
|
|
【現在の問題】
|
|||
|
|
// ネストが深くて読みにくい
|
|||
|
|
local result = trim(uppercase(replace(input, "cat", "nyan")))
|
|||
|
|
|
|||
|
|
【提案構文】
|
|||
|
|
local result = input
|
|||
|
|
|> replace($, "cat", "nyan")
|
|||
|
|
|> uppercase($)
|
|||
|
|
|> trim($)
|
|||
|
|
|
|||
|
|
// $ は前の結果を表す特殊変数
|
|||
|
|
// または第一引数に自動挿入も可
|
|||
|
|
local result = input
|
|||
|
|
|> replace("cat", "nyan") // 第一引数に自動挿入
|
|||
|
|
|> uppercase()
|
|||
|
|
|> trim()
|
|||
|
|
|
|||
|
|
【効果】
|
|||
|
|
- AST変換処理が非常に読みやすくなる
|
|||
|
|
- 関数合成が直感的
|
|||
|
|
- デバッグ時に中間結果を確認しやすい
|
|||
|
|
|
|||
|
|
================================================================================
|
|||
|
|
2. 分割代入(Destructuring)(優先度:高)
|
|||
|
|
================================================================================
|
|||
|
|
|
|||
|
|
【基本形】
|
|||
|
|
// タプル分割
|
|||
|
|
local (x, y, z) = getCoordinates()
|
|||
|
|
|
|||
|
|
// Box分割
|
|||
|
|
local { name, age, email } = getUserInfo()
|
|||
|
|
|
|||
|
|
// 配列分割
|
|||
|
|
local [first, second, ...rest] = items
|
|||
|
|
|
|||
|
|
【peek内での構造体パターン】
|
|||
|
|
peek ast {
|
|||
|
|
BinaryOp(left, op, right) => {
|
|||
|
|
// left, op, right が自動的に変数として使える
|
|||
|
|
compile(left) + compile(op) + compile(right)
|
|||
|
|
}
|
|||
|
|
UnaryOp(op, expr) => {
|
|||
|
|
compile(op) + compile(expr)
|
|||
|
|
}
|
|||
|
|
Literal(value) => value.toString()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
【効果】
|
|||
|
|
- パーサー実装で威力発揮
|
|||
|
|
- ASTノードの処理が簡潔に
|
|||
|
|
- ボイラープレートコード削減
|
|||
|
|
|
|||
|
|
================================================================================
|
|||
|
|
3. null安全演算子 ?. と ?? (優先度:高)
|
|||
|
|
================================================================================
|
|||
|
|
|
|||
|
|
【?.(null安全アクセス)】
|
|||
|
|
// 現在
|
|||
|
|
local name
|
|||
|
|
if user != null {
|
|||
|
|
if user.profile != null {
|
|||
|
|
if user.profile.name != null {
|
|||
|
|
name = user.profile.name
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 提案
|
|||
|
|
local name = user?.profile?.name
|
|||
|
|
|
|||
|
|
【??(null合体演算子)】
|
|||
|
|
local displayName = user?.name ?? "Anonymous"
|
|||
|
|
local port = config?.server?.port ?? 8080
|
|||
|
|
|
|||
|
|
【組み合わせ】
|
|||
|
|
local result = getData()?.process()?.format() ?? "default"
|
|||
|
|
|
|||
|
|
【効果】
|
|||
|
|
- null/undefinedエラーの防止
|
|||
|
|
- 防御的プログラミングが簡潔に
|
|||
|
|
- 設定値の読み込みで特に有用
|
|||
|
|
|
|||
|
|
================================================================================
|
|||
|
|
4. 文字列テンプレート強化(優先度:高)
|
|||
|
|
================================================================================
|
|||
|
|
|
|||
|
|
【基本テンプレート】
|
|||
|
|
// 現在
|
|||
|
|
local msg = "Error at line " + line + ", column " + col + ": " + error
|
|||
|
|
|
|||
|
|
// 提案
|
|||
|
|
local msg = `Error at line ${line}, column ${col}: ${error}`
|
|||
|
|
|
|||
|
|
【複数行テンプレート】
|
|||
|
|
local code = ```
|
|||
|
|
fn ${name}(${params.join(", ")}) {
|
|||
|
|
${body.indent(4)}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
【タグ付きテンプレート(将来)】
|
|||
|
|
local sql = SQL`SELECT * FROM users WHERE id = ${userId}`
|
|||
|
|
local regex = RE`\d{3}-\d{4}` // エスケープ不要
|
|||
|
|
|
|||
|
|
【効果】
|
|||
|
|
- コード生成が劇的に簡単に
|
|||
|
|
- SQLやHTML生成で安全性向上
|
|||
|
|
- 可読性の大幅改善
|
|||
|
|
|
|||
|
|
================================================================================
|
|||
|
|
5. リスト内包表記(優先度:中)
|
|||
|
|
================================================================================
|
|||
|
|
|
|||
|
|
【基本形】
|
|||
|
|
// 現在
|
|||
|
|
local result = new ArrayBox()
|
|||
|
|
for item in list {
|
|||
|
|
if item.isValid() {
|
|||
|
|
result.push(item.process())
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 提案
|
|||
|
|
local result = [item.process() for item in list if item.isValid()]
|
|||
|
|
|
|||
|
|
【ネスト】
|
|||
|
|
local pairs = [(x, y) for x in xs for y in ys if x != y]
|
|||
|
|
|
|||
|
|
【辞書内包】
|
|||
|
|
local map = {key: value.process() for (key, value) in entries}
|
|||
|
|
|
|||
|
|
【効果】
|
|||
|
|
- 変換処理が1行で書ける
|
|||
|
|
- 関数型プログラミングスタイル
|
|||
|
|
- メモリ効率的な実装も可能
|
|||
|
|
|
|||
|
|
================================================================================
|
|||
|
|
6. for式(値を返すfor)(優先度:中)
|
|||
|
|
================================================================================
|
|||
|
|
|
|||
|
|
【基本形】
|
|||
|
|
local tokens = for token in input yield parseToken(token)
|
|||
|
|
|
|||
|
|
【フィルタ付き】
|
|||
|
|
local validTokens = for token in tokens if token.isValid() yield token
|
|||
|
|
|
|||
|
|
【変換付き】
|
|||
|
|
local ast = for line in lines {
|
|||
|
|
local trimmed = line.trim()
|
|||
|
|
if trimmed.length() > 0 {
|
|||
|
|
yield parseLine(trimmed)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
【効果】
|
|||
|
|
- リスト内包より複雑な処理に対応
|
|||
|
|
- 中間変数を使える
|
|||
|
|
- yieldで明示的
|
|||
|
|
|
|||
|
|
================================================================================
|
|||
|
|
7. スプレッド演算子 ... (優先度:中)
|
|||
|
|
================================================================================
|
|||
|
|
|
|||
|
|
【配列展開】
|
|||
|
|
local combined = [...array1, ...array2, newItem]
|
|||
|
|
local clone = [...original]
|
|||
|
|
|
|||
|
|
【Box展開】
|
|||
|
|
local updated = { ...oldConfig, debug: true, port: 8080 }
|
|||
|
|
|
|||
|
|
【関数引数展開】
|
|||
|
|
processItems(...args)
|
|||
|
|
local max = Math.max(...numbers)
|
|||
|
|
|
|||
|
|
【効果】
|
|||
|
|
- 配列・オブジェクト操作が簡潔
|
|||
|
|
- イミュータブルな更新が簡単
|
|||
|
|
- 可変長引数の処理
|
|||
|
|
|
|||
|
|
================================================================================
|
|||
|
|
8. with文(リソース管理)(優先度:低)
|
|||
|
|
================================================================================
|
|||
|
|
|
|||
|
|
【基本形】
|
|||
|
|
with file = openFile("data.txt") {
|
|||
|
|
local content = file.read()
|
|||
|
|
process(content)
|
|||
|
|
} // 自動的にfile.close()
|
|||
|
|
|
|||
|
|
【複数リソース】
|
|||
|
|
with db = connectDB(), file = openLog() {
|
|||
|
|
db.query("SELECT...")
|
|||
|
|
file.write(result)
|
|||
|
|
} // 両方自動クローズ
|
|||
|
|
|
|||
|
|
【効果】
|
|||
|
|
- リソースリークの防止
|
|||
|
|
- finally不要
|
|||
|
|
- RAII的な管理
|
|||
|
|
|
|||
|
|
================================================================================
|
|||
|
|
9. 関数合成演算子(優先度:低)
|
|||
|
|
================================================================================
|
|||
|
|
|
|||
|
|
【合成 >>】
|
|||
|
|
local processLine = trim >> lowercase >> tokenize
|
|||
|
|
local result = processLine(input)
|
|||
|
|
|
|||
|
|
【部分適用】
|
|||
|
|
local add5 = add(5, _)
|
|||
|
|
local result = add5(10) // 15
|
|||
|
|
|
|||
|
|
【カリー化】
|
|||
|
|
local multiply = fn(a)(b) => a * b
|
|||
|
|
local double = multiply(2)
|
|||
|
|
|
|||
|
|
【効果】
|
|||
|
|
- 関数型プログラミング支援
|
|||
|
|
- 高階関数の活用
|
|||
|
|
- コードの再利用性向上
|
|||
|
|
|
|||
|
|
================================================================================
|
|||
|
|
10. 強力なpeekパターン拡張(優先度:中)
|
|||
|
|
================================================================================
|
|||
|
|
|
|||
|
|
【ガード】
|
|||
|
|
peek value {
|
|||
|
|
n if n > 0 => "positive"
|
|||
|
|
n if n < 0 => "negative"
|
|||
|
|
0 => "zero"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
【範囲】
|
|||
|
|
peek score {
|
|||
|
|
0..60 => "F"
|
|||
|
|
60..70 => "D"
|
|||
|
|
70..80 => "C"
|
|||
|
|
80..90 => "B"
|
|||
|
|
90..100 => "A"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
【深いパターン】
|
|||
|
|
peek ast {
|
|||
|
|
If({ condition: BinaryOp(_, "==", _), then, else }) => {
|
|||
|
|
optimizeEquality(condition, then, else)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
【効果】
|
|||
|
|
- より表現力豊かな分岐
|
|||
|
|
- コンパイラ実装で必須
|
|||
|
|
- コードの意図が明確
|
|||
|
|
|
|||
|
|
================================================================================
|
|||
|
|
実装優先順位まとめ
|
|||
|
|
================================================================================
|
|||
|
|
|
|||
|
|
【Phase 13(次フェーズ)】
|
|||
|
|
1. パイプライン演算子 |>
|
|||
|
|
2. 分割代入(基本形のみ)
|
|||
|
|
3. null安全演算子 ?. と ??
|
|||
|
|
4. 文字列テンプレート `${}`
|
|||
|
|
|
|||
|
|
【Phase 14】
|
|||
|
|
5. リスト内包表記
|
|||
|
|
6. for式
|
|||
|
|
7. peekパターン拡張(ガード)
|
|||
|
|
|
|||
|
|
【Phase 15以降】
|
|||
|
|
8. スプレッド演算子
|
|||
|
|
9. with文
|
|||
|
|
10. 関数合成演算子
|
|||
|
|
|
|||
|
|
================================================================================
|
|||
|
|
実装時の注意点
|
|||
|
|
================================================================================
|
|||
|
|
|
|||
|
|
1. 各糖衣構文は既存構文へのデシュガーとして実装
|
|||
|
|
2. エラーメッセージは元の構文で表示
|
|||
|
|
3. デバッガーでのステップ実行に配慮
|
|||
|
|
4. 段階的に導入(基本形→拡張形)
|
|||
|
|
|
|||
|
|
================================================================================
|