228 lines
5.4 KiB
Plaintext
228 lines
5.4 KiB
Plaintext
|
|
// 📦 ConsBox - LISPのcons cell実装
|
|||
|
|
// ペア(car, cdr)を表現する基本データ構造
|
|||
|
|
|
|||
|
|
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 isList() {
|
|||
|
|
// cdrがNullBoxならリストの終端
|
|||
|
|
if (NullBox.check_null(me.cdr)) {
|
|||
|
|
return true
|
|||
|
|
}
|
|||
|
|
// cdrがConsBoxなら再帰的にチェック
|
|||
|
|
// TODO: 型チェックの別の方法が必要
|
|||
|
|
// 暫定的にtrueを返す
|
|||
|
|
return true
|
|||
|
|
// それ以外はドット対
|
|||
|
|
return false
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// リストの長さを取得
|
|||
|
|
func length() {
|
|||
|
|
if (not me.isList()) {
|
|||
|
|
return -1 // リストでない場合は-1
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
count = 0
|
|||
|
|
current = me
|
|||
|
|
loop(not NullBox.check_null(current)) {
|
|||
|
|
count = count + 1
|
|||
|
|
current = current.getCdr()
|
|||
|
|
}
|
|||
|
|
return count
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// n番目の要素を取得(0ベース)
|
|||
|
|
func nth(n) {
|
|||
|
|
if (n < 0) {
|
|||
|
|
return new NullBox()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
current = me
|
|||
|
|
i = 0
|
|||
|
|
loop(i < n) {
|
|||
|
|
if (NullBox.check_null(current)) {
|
|||
|
|
return new NullBox()
|
|||
|
|
}
|
|||
|
|
current = current.getCdr()
|
|||
|
|
i = i + 1
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (NullBox.check_null(current)) {
|
|||
|
|
return new NullBox()
|
|||
|
|
}
|
|||
|
|
return current.getCar()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// リストを配列に変換
|
|||
|
|
func toArray() {
|
|||
|
|
result = new ArrayBox()
|
|||
|
|
current = me
|
|||
|
|
|
|||
|
|
loop(not NullBox.check_null(current)) {
|
|||
|
|
result.push(current.getCar())
|
|||
|
|
cdr = current.getCdr()
|
|||
|
|
|
|||
|
|
// ドット対の場合
|
|||
|
|
// TODO: 型チェックの別の方法が必要
|
|||
|
|
// 暫定的にスキップ
|
|||
|
|
|
|||
|
|
current = cdr
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return result
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 文字列表現
|
|||
|
|
func toString() {
|
|||
|
|
// 空リスト
|
|||
|
|
if (NullBox.check_null(me.car) and NullBox.check_null(me.cdr)) {
|
|||
|
|
return "()"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
result = "("
|
|||
|
|
current = me
|
|||
|
|
first = true
|
|||
|
|
|
|||
|
|
loop(not NullBox.check_null(current)) {
|
|||
|
|
if (not first) {
|
|||
|
|
result = result + " "
|
|||
|
|
}
|
|||
|
|
first = false
|
|||
|
|
|
|||
|
|
// carの表示
|
|||
|
|
car = current.getCar()
|
|||
|
|
if (NullBox.check_null(car)) {
|
|||
|
|
result = result + "nil"
|
|||
|
|
} else {
|
|||
|
|
result = result + car.toString()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// cdrの確認
|
|||
|
|
cdr = current.getCdr()
|
|||
|
|
if (NullBox.check_null(cdr)) {
|
|||
|
|
break
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ドット対の場合
|
|||
|
|
// TODO: 型チェックの別の方法が必要
|
|||
|
|
// 暫定的にスキップ
|
|||
|
|
|
|||
|
|
current = cdr
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
result = result + ")"
|
|||
|
|
return result
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// デバッグ用の詳細表示
|
|||
|
|
func debugPrint() {
|
|||
|
|
print("ConsBox {")
|
|||
|
|
print(" car: " + me.car.toString())
|
|||
|
|
print(" cdr: " + me.cdr.toString())
|
|||
|
|
print(" isList: " + me.isList())
|
|||
|
|
if (me.isList()) {
|
|||
|
|
print(" length: " + me.length())
|
|||
|
|
}
|
|||
|
|
print("}")
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ヘルパー関数:配列からリストを作成
|
|||
|
|
function arrayToList(arr) {
|
|||
|
|
if (arr.length() == 0) {
|
|||
|
|
return new NullBox()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 逆順に構築
|
|||
|
|
result = new NullBox()
|
|||
|
|
i = arr.length() - 1
|
|||
|
|
loop(i >= 0) {
|
|||
|
|
result = new ConsBox(arr.get(i), result)
|
|||
|
|
i = i - 1
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return result
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ヘルパー関数:可変長引数でリストを作成
|
|||
|
|
function list() {
|
|||
|
|
// TODO: 可変長引数のサポートが必要
|
|||
|
|
// 現在は固定数の引数での実装例
|
|||
|
|
return new NullBox()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// テストコード
|
|||
|
|
print("🎯 === ConsBox Test ===")
|
|||
|
|
|
|||
|
|
// 基本的なペア
|
|||
|
|
print("📦 基本的なペア (1 . 2):")
|
|||
|
|
pair = new ConsBox(new IntegerBox(1), new IntegerBox(2))
|
|||
|
|
print(pair.toString())
|
|||
|
|
pair.debugPrint()
|
|||
|
|
|
|||
|
|
// リスト (1 2 3)
|
|||
|
|
print("\n📋 リスト (1 2 3):")
|
|||
|
|
list123 = new ConsBox(
|
|||
|
|
new IntegerBox(1),
|
|||
|
|
new ConsBox(
|
|||
|
|
new IntegerBox(2),
|
|||
|
|
new ConsBox(
|
|||
|
|
new IntegerBox(3),
|
|||
|
|
new NullBox()
|
|||
|
|
)
|
|||
|
|
)
|
|||
|
|
)
|
|||
|
|
print(list123.toString())
|
|||
|
|
print("Length: " + list123.length())
|
|||
|
|
print("2nd element: " + list123.nth(1).toString())
|
|||
|
|
|
|||
|
|
// 配列からリストを作成
|
|||
|
|
print("\n🔄 配列からリスト作成:")
|
|||
|
|
arr = new ArrayBox()
|
|||
|
|
arr.push(new StringBox("hello"))
|
|||
|
|
arr.push(new StringBox("world"))
|
|||
|
|
arr.push(new IntegerBox(42))
|
|||
|
|
listFromArray = arrayToList(arr)
|
|||
|
|
print(listFromArray.toString())
|
|||
|
|
|
|||
|
|
// ネストしたリスト ((1 2) (3 4))
|
|||
|
|
print("\n🎯 ネストしたリスト:")
|
|||
|
|
innerList1 = new ConsBox(
|
|||
|
|
new IntegerBox(1),
|
|||
|
|
new ConsBox(new IntegerBox(2), new NullBox())
|
|||
|
|
)
|
|||
|
|
innerList2 = new ConsBox(
|
|||
|
|
new IntegerBox(3),
|
|||
|
|
new ConsBox(new IntegerBox(4), new NullBox())
|
|||
|
|
)
|
|||
|
|
nestedList = new ConsBox(
|
|||
|
|
innerList1,
|
|||
|
|
new ConsBox(innerList2, new NullBox())
|
|||
|
|
)
|
|||
|
|
print(nestedList.toString())
|
|||
|
|
|
|||
|
|
print("\n✅ ConsBox implementation completed!")
|