271 lines
6.8 KiB
Plaintext
271 lines
6.8 KiB
Plaintext
|
|
// ⚙️ LISP Evaluator - eval/apply/環境管理
|
|||
|
|
// 簡易版LISP評価エンジン
|
|||
|
|
|
|||
|
|
NIL = 0
|
|||
|
|
|
|||
|
|
// ===== LISP Core関数の再実装(簡単版) =====
|
|||
|
|
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() { return "(" + me.car.toString() + " . " + me.cdr.toString() + ")" }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
box SymbolBox {
|
|||
|
|
name
|
|||
|
|
init { name }
|
|||
|
|
SymbolBox(symbolName) {
|
|||
|
|
me.name = symbolName
|
|||
|
|
}
|
|||
|
|
getName() { return me.name }
|
|||
|
|
toString() { return me.name }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
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 == "a" or obj == "b" or obj == "c" { return true }
|
|||
|
|
return false
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function nullP(obj) { return obj == NIL }
|
|||
|
|
|
|||
|
|
// ===== 簡易環境管理(MapBox代替) =====
|
|||
|
|
box Environment {
|
|||
|
|
names, values, count
|
|||
|
|
|
|||
|
|
init { names, values, count }
|
|||
|
|
|
|||
|
|
Environment() {
|
|||
|
|
me.names = cons(NIL, NIL) // 変数名のリスト
|
|||
|
|
me.values = cons(NIL, NIL) // 値のリスト
|
|||
|
|
me.count = 0 // 変数の数
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 変数を定義
|
|||
|
|
define(name, value) {
|
|||
|
|
me.names = cons(name, me.names)
|
|||
|
|
me.values = cons(value, me.values)
|
|||
|
|
me.count = me.count + 1
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 変数を検索
|
|||
|
|
lookup(name) {
|
|||
|
|
return me.lookupHelper(name, me.names, me.values)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
lookupHelper(target, nameList, valueList) {
|
|||
|
|
if nullP(nameList) { return symbol("UNDEFINED") }
|
|||
|
|
|
|||
|
|
currentName = car(nameList)
|
|||
|
|
currentValue = car(valueList)
|
|||
|
|
|
|||
|
|
// 名前が一致するかチェック
|
|||
|
|
if currentName == target {
|
|||
|
|
return currentValue
|
|||
|
|
}
|
|||
|
|
if currentName.toString() == target {
|
|||
|
|
return currentValue
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return me.lookupHelper(target, cdr(nameList), cdr(valueList))
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ===== 基本的な評価関数 =====
|
|||
|
|
|
|||
|
|
// eval - 式を評価
|
|||
|
|
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 == "a" { return "a" }
|
|||
|
|
if expr == "b" { return "b" }
|
|||
|
|
if expr == "c" { return "c" }
|
|||
|
|
if expr == "hello" { return "hello" }
|
|||
|
|
if expr == "world" { return "world" }
|
|||
|
|
|
|||
|
|
// シンボル(変数)は環境から検索
|
|||
|
|
return env.lookup(expr.toString())
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// リスト(関数呼び出し)の場合
|
|||
|
|
operator = car(expr)
|
|||
|
|
operands = cdr(expr)
|
|||
|
|
|
|||
|
|
// 特殊形式の処理
|
|||
|
|
opName = operator.toString()
|
|||
|
|
|
|||
|
|
// quote - リテラル
|
|||
|
|
if opName == "quote" {
|
|||
|
|
return car(operands)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// if - 条件分岐
|
|||
|
|
if opName == "if" {
|
|||
|
|
condition = lispEval(car(operands), env)
|
|||
|
|
if not nullP(condition) {
|
|||
|
|
return lispEval(car(cdr(operands)), env) // then節
|
|||
|
|
} else {
|
|||
|
|
return lispEval(car(cdr(cdr(operands))), env) // else節
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// define - 変数定義
|
|||
|
|
if opName == "define" {
|
|||
|
|
varName = car(operands).toString()
|
|||
|
|
value = lispEval(car(cdr(operands)), env)
|
|||
|
|
env.define(varName, value)
|
|||
|
|
return value
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 通常の関数呼び出し
|
|||
|
|
func = lispEval(operator, env)
|
|||
|
|
args = lispEvalList(operands, env)
|
|||
|
|
return lispApply(func, args, env)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 引数リストを評価
|
|||
|
|
function lispEvalList(exprs, env) {
|
|||
|
|
if nullP(exprs) { return NIL }
|
|||
|
|
first = lispEval(car(exprs), env)
|
|||
|
|
rest = lispEvalList(cdr(exprs), env)
|
|||
|
|
return cons(first, rest)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// apply - 関数適用
|
|||
|
|
function lispApply(func, args, env) {
|
|||
|
|
funcName = func.toString()
|
|||
|
|
|
|||
|
|
// 組み込み関数
|
|||
|
|
if funcName == "+" {
|
|||
|
|
return lispAdd(args)
|
|||
|
|
}
|
|||
|
|
if funcName == "-" {
|
|||
|
|
return lispSub(args)
|
|||
|
|
}
|
|||
|
|
if funcName == "*" {
|
|||
|
|
return lispMul(args)
|
|||
|
|
}
|
|||
|
|
if funcName == "car" {
|
|||
|
|
return car(car(args))
|
|||
|
|
}
|
|||
|
|
if funcName == "cdr" {
|
|||
|
|
return cdr(car(args))
|
|||
|
|
}
|
|||
|
|
if funcName == "cons" {
|
|||
|
|
return cons(car(args), car(cdr(args)))
|
|||
|
|
}
|
|||
|
|
if funcName == "atom?" {
|
|||
|
|
return atomP(car(args))
|
|||
|
|
}
|
|||
|
|
if funcName == "null?" {
|
|||
|
|
return nullP(car(args))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return symbol("UNKNOWN-FUNCTION")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 算術演算の実装
|
|||
|
|
function lispAdd(args) {
|
|||
|
|
if nullP(args) { return 0 }
|
|||
|
|
return car(args) + lispAdd(cdr(args))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function lispSub(args) {
|
|||
|
|
if nullP(args) { return 0 }
|
|||
|
|
if nullP(cdr(args)) { return 0 - car(args) } // 単項マイナス
|
|||
|
|
return car(args) - lispAdd(cdr(args))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function lispMul(args) {
|
|||
|
|
if nullP(args) { return 1 }
|
|||
|
|
return car(args) * lispMul(cdr(args))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ===== グローバル環境初期化 =====
|
|||
|
|
function makeGlobalEnv() {
|
|||
|
|
env = new Environment()
|
|||
|
|
|
|||
|
|
// 組み込み関数を定義
|
|||
|
|
env.define("+", symbol("+"))
|
|||
|
|
env.define("-", symbol("-"))
|
|||
|
|
env.define("*", symbol("*"))
|
|||
|
|
env.define("car", symbol("car"))
|
|||
|
|
env.define("cdr", symbol("cdr"))
|
|||
|
|
env.define("cons", symbol("cons"))
|
|||
|
|
env.define("atom?", symbol("atom?"))
|
|||
|
|
env.define("null?", symbol("null?"))
|
|||
|
|
|
|||
|
|
// 特殊値
|
|||
|
|
env.define("nil", NIL)
|
|||
|
|
env.define("t", true)
|
|||
|
|
|
|||
|
|
return env
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ===== 簡易パーサー(手動構築版) =====
|
|||
|
|
function parseManual() {
|
|||
|
|
// (+ 1 2) を手動構築
|
|||
|
|
expr1 = list3(symbol("+"), 1, 2)
|
|||
|
|
return expr1
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ===== テスト =====
|
|||
|
|
print("⚙️ === LISP Evaluator Test === ⚙️")
|
|||
|
|
print("")
|
|||
|
|
|
|||
|
|
// 環境準備
|
|||
|
|
globalEnv = makeGlobalEnv()
|
|||
|
|
|
|||
|
|
print("1. Simple arithmetic:")
|
|||
|
|
// (+ 1 2)
|
|||
|
|
expr = list3(symbol("+"), 1, 2)
|
|||
|
|
print(" Expression: " + expr.toString())
|
|||
|
|
result = lispEval(expr, globalEnv)
|
|||
|
|
print(" Result: " + result)
|
|||
|
|
|
|||
|
|
print("")
|
|||
|
|
print("2. Nested expression:")
|
|||
|
|
// (+ 1 (* 2 3))
|
|||
|
|
inner = list3(symbol("*"), 2, 3)
|
|||
|
|
expr2 = list3(symbol("+"), 1, inner)
|
|||
|
|
print(" Expression: " + expr2.toString())
|
|||
|
|
result2 = lispEval(expr2, globalEnv)
|
|||
|
|
print(" Result: " + result2)
|
|||
|
|
|
|||
|
|
print("")
|
|||
|
|
print("✅ LISP Evaluator test completed!")
|
|||
|
|
print("🎯 Ready for full LISP interpreter!")
|