271 lines
7.1 KiB
Plaintext
271 lines
7.1 KiB
Plaintext
|
|
// 🚀 Enhanced LISP - 変数定義・条件分岐対応版
|
||
|
|
// define, if, quote などの特殊形式を実装
|
||
|
|
|
||
|
|
NIL = 0
|
||
|
|
|
||
|
|
// ===== データ構造 =====
|
||
|
|
box ConsBox {
|
||
|
|
car
|
||
|
|
cdr
|
||
|
|
init { car, cdr }
|
||
|
|
ConsBox(a, d) {
|
||
|
|
me.car = a
|
||
|
|
me.cdr = d
|
||
|
|
}
|
||
|
|
getCar() { return me.car }
|
||
|
|
getCdr() { return me.cdr }
|
||
|
|
toString() {
|
||
|
|
if me.cdr == NIL {
|
||
|
|
return "(" + me.car.toString() + ")"
|
||
|
|
} else {
|
||
|
|
if me.isConsBox(me.cdr) {
|
||
|
|
return "(" + me.car.toString() + " " + me.cdr.toStringList() + ")"
|
||
|
|
} else {
|
||
|
|
return "(" + me.car.toString() + " . " + me.cdr.toString() + ")"
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
toStringList() {
|
||
|
|
if me.cdr == NIL {
|
||
|
|
return me.car.toString()
|
||
|
|
} else {
|
||
|
|
if me.isConsBox(me.cdr) {
|
||
|
|
return me.car.toString() + " " + me.cdr.toStringList()
|
||
|
|
} else {
|
||
|
|
return me.car.toString() + " . " + me.cdr.toString()
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
isConsBox(obj) {
|
||
|
|
if obj == NIL { return false }
|
||
|
|
if obj == 0 { return false }
|
||
|
|
if obj == 1 { return false }
|
||
|
|
if obj == 2 { return false }
|
||
|
|
if obj == 3 { return false }
|
||
|
|
if obj == 4 { return false }
|
||
|
|
if obj == 5 { return false }
|
||
|
|
if obj == "+" { return false }
|
||
|
|
if obj == "-" { return false }
|
||
|
|
if obj == "*" { return false }
|
||
|
|
if obj == "x" { return false }
|
||
|
|
if obj == "y" { return false }
|
||
|
|
return true
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
box SymbolBox {
|
||
|
|
name
|
||
|
|
init { name }
|
||
|
|
SymbolBox(symbolName) {
|
||
|
|
me.name = symbolName
|
||
|
|
}
|
||
|
|
toString() { return me.name }
|
||
|
|
}
|
||
|
|
|
||
|
|
// ===== 環境管理(変数の保存・検索) =====
|
||
|
|
box Environment {
|
||
|
|
names
|
||
|
|
values
|
||
|
|
|
||
|
|
init { names, values }
|
||
|
|
|
||
|
|
Environment() {
|
||
|
|
me.names = NIL
|
||
|
|
me.values = NIL
|
||
|
|
}
|
||
|
|
|
||
|
|
// 変数を定義
|
||
|
|
define(name, value) {
|
||
|
|
me.names = cons(name, me.names)
|
||
|
|
me.values = cons(value, me.values)
|
||
|
|
}
|
||
|
|
|
||
|
|
// 変数を検索
|
||
|
|
lookup(targetName) {
|
||
|
|
return me.lookupHelper(targetName, me.names, me.values)
|
||
|
|
}
|
||
|
|
|
||
|
|
lookupHelper(target, nameList, valueList) {
|
||
|
|
if nameList == NIL {
|
||
|
|
return symbol("UNDEFINED")
|
||
|
|
}
|
||
|
|
|
||
|
|
// 安全なcar/cdr呼び出し
|
||
|
|
if nameList == NIL { return symbol("UNDEFINED") }
|
||
|
|
if valueList == NIL { return symbol("UNDEFINED") }
|
||
|
|
|
||
|
|
currentName = car(nameList)
|
||
|
|
currentValue = car(valueList)
|
||
|
|
|
||
|
|
if currentName == target {
|
||
|
|
return currentValue
|
||
|
|
}
|
||
|
|
|
||
|
|
nextNames = cdr(nameList)
|
||
|
|
nextValues = cdr(valueList)
|
||
|
|
return me.lookupHelper(target, nextNames, nextValues)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// ===== 基本関数 =====
|
||
|
|
function cons(a, d) { return new ConsBox(a, d) }
|
||
|
|
function car(pair) {
|
||
|
|
if pair == NIL { return NIL }
|
||
|
|
return pair.getCar()
|
||
|
|
}
|
||
|
|
function cdr(pair) {
|
||
|
|
if pair == NIL { return NIL }
|
||
|
|
return pair.getCdr()
|
||
|
|
}
|
||
|
|
function symbol(name) { return new SymbolBox(name) }
|
||
|
|
function list1(a) { return cons(a, NIL) }
|
||
|
|
function list2(a, b) { return cons(a, cons(b, NIL)) }
|
||
|
|
function list3(a, b, c) { return cons(a, cons(b, cons(c, NIL))) }
|
||
|
|
|
||
|
|
function atomP(obj) {
|
||
|
|
if obj == NIL { return true }
|
||
|
|
if obj == 0 or obj == 1 or obj == 2 or obj == 3 or obj == 4 { return true }
|
||
|
|
if obj == 5 or obj == 6 or obj == 7 or obj == 8 or obj == 9 { return true }
|
||
|
|
if obj == "+" or obj == "-" or obj == "*" { return true }
|
||
|
|
if obj == "x" or obj == "y" or obj == "hello" { return true }
|
||
|
|
return false
|
||
|
|
}
|
||
|
|
|
||
|
|
// ===== 拡張評価器 =====
|
||
|
|
function lispEval(expr, env) {
|
||
|
|
// アトムの場合
|
||
|
|
if atomP(expr) {
|
||
|
|
// 数値リテラル
|
||
|
|
if expr == 0 { return 0 }
|
||
|
|
if expr == 1 { return 1 }
|
||
|
|
if expr == 2 { return 2 }
|
||
|
|
if expr == 3 { return 3 }
|
||
|
|
if expr == 4 { return 4 }
|
||
|
|
if expr == 5 { return 5 }
|
||
|
|
if expr == 6 { return 6 }
|
||
|
|
if expr == 7 { return 7 }
|
||
|
|
if expr == 8 { return 8 }
|
||
|
|
if expr == 9 { return 9 }
|
||
|
|
|
||
|
|
// 文字列リテラル
|
||
|
|
if expr == "hello" { return "hello" }
|
||
|
|
if expr == "world" { return "world" }
|
||
|
|
if expr == "true" { return true }
|
||
|
|
if expr == "false" { return false }
|
||
|
|
|
||
|
|
// シンボル(変数)は環境から検索
|
||
|
|
return env.lookup(expr)
|
||
|
|
}
|
||
|
|
|
||
|
|
// リスト(関数呼び出し)の場合
|
||
|
|
operator = car(expr)
|
||
|
|
operands = cdr(expr)
|
||
|
|
|
||
|
|
// 特殊形式の処理
|
||
|
|
if operator == "quote" {
|
||
|
|
return car(operands)
|
||
|
|
}
|
||
|
|
|
||
|
|
if operator == "define" {
|
||
|
|
varName = car(operands)
|
||
|
|
value = lispEval(car(cdr(operands)), env)
|
||
|
|
env.define(varName, value)
|
||
|
|
return value
|
||
|
|
}
|
||
|
|
|
||
|
|
if operator == "if" {
|
||
|
|
condition = lispEval(car(operands), env)
|
||
|
|
thenExpr = car(cdr(operands))
|
||
|
|
elseExpr = car(cdr(cdr(operands)))
|
||
|
|
|
||
|
|
if condition != NIL and condition != false {
|
||
|
|
return lispEval(thenExpr, env)
|
||
|
|
} else {
|
||
|
|
return lispEval(elseExpr, env)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 通常の関数呼び出し
|
||
|
|
if operator == "+" {
|
||
|
|
arg1 = lispEval(car(operands), env)
|
||
|
|
arg2 = lispEval(car(cdr(operands)), env)
|
||
|
|
return arg1 + arg2
|
||
|
|
}
|
||
|
|
|
||
|
|
if operator == "-" {
|
||
|
|
arg1 = lispEval(car(operands), env)
|
||
|
|
arg2 = lispEval(car(cdr(operands)), env)
|
||
|
|
return arg1 - arg2
|
||
|
|
}
|
||
|
|
|
||
|
|
if operator == "*" {
|
||
|
|
arg1 = lispEval(car(operands), env)
|
||
|
|
arg2 = lispEval(car(cdr(operands)), env)
|
||
|
|
return arg1 * arg2
|
||
|
|
}
|
||
|
|
|
||
|
|
if operator == "=" {
|
||
|
|
arg1 = lispEval(car(operands), env)
|
||
|
|
arg2 = lispEval(car(cdr(operands)), env)
|
||
|
|
if arg1 == arg2 { return true } else { return false }
|
||
|
|
}
|
||
|
|
|
||
|
|
if operator == ">" {
|
||
|
|
arg1 = lispEval(car(operands), env)
|
||
|
|
arg2 = lispEval(car(cdr(operands)), env)
|
||
|
|
if arg1 > arg2 { return true } else { return false }
|
||
|
|
}
|
||
|
|
|
||
|
|
return symbol("UNKNOWN-OP")
|
||
|
|
}
|
||
|
|
|
||
|
|
// ===== テスト =====
|
||
|
|
print("🚀 === Enhanced LISP Test === 🚀")
|
||
|
|
print("")
|
||
|
|
|
||
|
|
// 環境を作成
|
||
|
|
env = new Environment()
|
||
|
|
|
||
|
|
print("1. Variable definition and lookup:")
|
||
|
|
// (define x 42)
|
||
|
|
defineExpr = list3("define", "x", 42)
|
||
|
|
print(" " + defineExpr.toString())
|
||
|
|
result = lispEval(defineExpr, env)
|
||
|
|
print(" → " + result)
|
||
|
|
|
||
|
|
// x を参照
|
||
|
|
print(" x")
|
||
|
|
xValue = lispEval("x", env)
|
||
|
|
print(" → " + xValue)
|
||
|
|
|
||
|
|
print("")
|
||
|
|
print("2. Using variables in expressions:")
|
||
|
|
// (+ x 10)
|
||
|
|
expr1 = list3("+", "x", 10)
|
||
|
|
print(" " + expr1.toString())
|
||
|
|
result1 = lispEval(expr1, env)
|
||
|
|
print(" → " + result1)
|
||
|
|
|
||
|
|
print("")
|
||
|
|
print("3. Conditional expressions:")
|
||
|
|
// (if (> x 40) "big" "small")
|
||
|
|
condition = list3(">", "x", 40)
|
||
|
|
ifExpr = list3("if", condition, "big") // else省略版
|
||
|
|
print(" (if (> x 40) \"big\")")
|
||
|
|
result2 = lispEval(ifExpr, env)
|
||
|
|
print(" → " + result2)
|
||
|
|
|
||
|
|
print("")
|
||
|
|
print("4. Quote (literal data):")
|
||
|
|
// (quote (1 2 3))
|
||
|
|
listData = list3(1, 2, 3)
|
||
|
|
quoteExpr = list2("quote", listData)
|
||
|
|
print(" " + quoteExpr.toString())
|
||
|
|
result3 = lispEval(quoteExpr, env)
|
||
|
|
print(" → " + result3.toString())
|
||
|
|
|
||
|
|
print("")
|
||
|
|
print("✅ Enhanced LISP interpreter working!")
|
||
|
|
print("🎯 Variables, conditionals, and quotes implemented!")
|