🚀 主要機能: • Everything is Box哲学による革新的アーキテクチャ • WebAssemblyブラウザー対応プレイグラウンド • アーティスト協同制作デモ - 複数Boxインスタンス実証 • 視覚的デバッグシステム - DebugBox完全統合 • static box Mainパターン - メモリ安全設計 ⚡ 言語機能: • NOT/AND/OR/除算演算子完全実装 • ジェネリクス/テンプレートシステム • 非同期処理(nowait/await) • try/catchエラーハンドリング • Canvas統合グラフィックス 🎨 ブラウザー体験: • 9種類のインタラクティブデモ • リアルタイムコード実行 • WebCanvas/WebConsole/WebDisplay • モバイル対応完了 🤖 Built with Claude Code collaboration Ready for public release!
7.5 KiB
7.5 KiB
🎯 Nyash LISP インタープリタ設計書
概要
Nyash上で動作するLISPインタープリタを実装する。「Everything is Box」哲学に基づき、LISPのS式をNyashのBoxで表現する。
🏗️ アーキテクチャ
1. コアBox実装
ConsBox - cons cell(ペア)
box ConsBox {
car // 最初の要素
cdr // 残りの要素(通常は別のConsBoxかNullBox)
init { car, cdr }
func getCar() { return me.car }
func getCdr() { return me.cdr }
func setCar(value) { me.car = value }
func setCdr(value) { me.cdr = value }
func toString() {
if (NullBox.isNull(me.cdr)) {
return "(" + me.car.toString() + ")"
}
// TODO: 適切なリスト表示
return "(" + me.car.toString() + " . " + me.cdr.toString() + ")"
}
}
SymbolBox - シンボル
box SymbolBox {
name
init { name }
func getName() { return me.name }
func toString() { return me.name }
}
LispEnvironment - 変数環境
box LispEnvironment {
bindings // MapBox: symbol name -> value
parent // 親環境(スコープチェーン用)
init { parent }
func define(symbol, value) {
me.bindings.set(symbol.getName(), value)
}
func lookup(symbol) {
name = symbol.getName()
if (me.bindings.has(name)) {
return me.bindings.get(name)
}
if (not NullBox.isNull(me.parent)) {
return me.parent.lookup(symbol)
}
return new ErrorBox("Unbound variable: " + name)
}
}
2. S式パーサー
box SExpressionParser {
tokens
position
init { input }
func parse() {
me.tokens = me.tokenize(input)
me.position = 0
return me.parseExpression()
}
func parseExpression() {
token = me.currentToken()
if (token == "(") {
return me.parseList()
}
if (token.isNumber()) {
return new IntegerBox(token.toNumber())
}
if (token.isString()) {
return new StringBox(token.getValue())
}
// シンボル
return new SymbolBox(token)
}
func parseList() {
me.consume("(")
elements = new ArrayBox()
loop(me.currentToken() != ")") {
elements.push(me.parseExpression())
}
me.consume(")")
return me.arrayToConsList(elements)
}
}
3. eval関数
box LispEvaluator {
globalEnv
init {}
func eval(expr, env) {
// 自己評価的な値
if (expr.isNumber() or expr.isString()) {
return expr
}
// シンボル
if (expr.isSymbol()) {
return env.lookup(expr)
}
// リスト(関数適用か特殊形式)
if (expr.isCons()) {
car = expr.getCar()
// 特殊形式のチェック
if (car.isSymbol()) {
name = car.getName()
if (name == "quote") {
return me.evalQuote(expr, env)
}
if (name == "if") {
return me.evalIf(expr, env)
}
if (name == "define") {
return me.evalDefine(expr, env)
}
if (name == "lambda") {
return me.evalLambda(expr, env)
}
// ... 他の特殊形式
}
// 通常の関数適用
func = me.eval(car, env)
args = me.evalList(expr.getCdr(), env)
return me.apply(func, args)
}
return expr
}
func apply(func, args) {
// プリミティブ関数
if (func.isPrimitive()) {
return func.applyPrimitive(args)
}
// ラムダ式
if (func.isLambda()) {
newEnv = new LispEnvironment(func.getEnv())
params = func.getParams()
// パラメータをバインド
// ... 実装
return me.eval(func.getBody(), newEnv)
}
return new ErrorBox("Not a function: " + func.toString())
}
}
4. 基本関数の実装
box LispPrimitives {
func setupGlobalEnv(env) {
// 算術演算
env.define(new SymbolBox("+"), new PrimitiveBox(me.add))
env.define(new SymbolBox("-"), new PrimitiveBox(me.subtract))
env.define(new SymbolBox("*"), new PrimitiveBox(me.multiply))
env.define(new SymbolBox("/"), new PrimitiveBox(me.divide))
// リスト操作
env.define(new SymbolBox("cons"), new PrimitiveBox(me.cons))
env.define(new SymbolBox("car"), new PrimitiveBox(me.car))
env.define(new SymbolBox("cdr"), new PrimitiveBox(me.cdr))
env.define(new SymbolBox("list"), new PrimitiveBox(me.list))
// 述語
env.define(new SymbolBox("null?"), new PrimitiveBox(me.isNull))
env.define(new SymbolBox("pair?"), new PrimitiveBox(me.isPair))
env.define(new SymbolBox("number?"), new PrimitiveBox(me.isNumber))
// 比較
env.define(new SymbolBox("="), new PrimitiveBox(me.equal))
env.define(new SymbolBox("<"), new PrimitiveBox(me.lessThan))
env.define(new SymbolBox(">"), new PrimitiveBox(me.greaterThan))
}
func add(args) {
sum = 0
current = args
loop(not NullBox.isNull(current)) {
sum = sum + current.getCar().getValue()
current = current.getCdr()
}
return new IntegerBox(sum)
}
// ... 他のプリミティブ関数
}
🎮 使用例
; Nyash LISPでの階乗計算
(define factorial
(lambda (n)
(if (= n 0)
1
(* n (factorial (- n 1))))))
(factorial 5) ; => 120
; リスト操作
(define map
(lambda (f lst)
(if (null? lst)
'()
(cons (f (car lst))
(map f (cdr lst))))))
(map (lambda (x) (* x x)) '(1 2 3 4 5)) ; => (1 4 9 16 25)
📋 実装ステップ
-
Phase 1: 基本データ構造
- ConsBox実装
- SymbolBox実装
- 基本的なリスト操作
-
Phase 2: パーサー
- トークナイザー
- S式パーサー
- 文字列→Box変換
-
Phase 3: 評価器
- eval関数の基本実装
- 環境(Environment)管理
- 特殊形式の処理
-
Phase 4: 基本関数
- 四則演算
- リスト操作(cons, car, cdr)
- 述語関数
-
Phase 5: 高度な機能
- lambda式
- クロージャ
- 再帰関数のサポート
-
Phase 6: 最適化とデバッグ
- DebugBoxとの統合
- エラーハンドリングの改善
- パフォーマンス最適化
🎯 成功基準
- 基本的なLISPプログラムが動作する
- 再帰関数が正しく実行される
- リスト操作が適切に機能する
- Nyashの他のBox機能と統合できる
💡 技術的課題
- 末尾再帰最適化: NyashはTCOをサポートしていないため、深い再帰でスタックオーバーフローの可能性
- ガベージコレクション: Nyashのfini()との統合方法
- マクロシステム: 将来的な実装検討事項
「Everything is Box」の究極の実証 - LISPインタープリタ on Nyash!