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. 段階的に導入(基本形→拡張形)
|
||
|
||
================================================================================ |