#はじめに
Prologで書いたLispモドキです。O-Prologのテストを兼ねて書きました。S式の代わりにPrologのリストを使います。Prologで遊びつつLispの内部構造をお楽しみください。実用性はまったくありません。遊びです。
#使い方
起動はreplです。終了は[quit]です。
| ?- repl.
> [defun,foo,[a,b],[*,a,b]].
t
> [foo,10,2].
20
> [setq,x,2].
t
> x.
2
> [quit].
t
yes
|
#拡張
四則演算しか実装していません。いろいろ追加して遊んでください。
#コード
%Lisp in Prolog
repl :-
repeat,
write('> '),
read(X),
eval(X,Y,[]),
write(Y),nl,
(X=[quit]->true;fail).
eval(X,X,E) :-
integer(X).
eval(X,X,E) :-
float(X).
eval(X,Y,E) :-
atom(X),
assoc(X,E,Y).
eval(X,Y,E) :-
atom(X),
global(X,Y).
eval([quit],t,E).
eval([defun,F,A,B],t,E) :-
assert(fun(F,A,B)).
eval([setq,X,Y],t,E) :-
eval(Y,Z,E),
assert(global(X,Z)).
eval(X,Y,E) :-
funcall(X,Y,E).
funcall([F|A1],Z,E) :-
fun(F,A,B),
argument(A,A1,Y),
append(Y,E,E1),
eval(B,Z,E1).
funcall([+,X,Y],Z,E) :-
eval(X,X1,E),
eval(Y,Y1,E),
Z is X1+Y1.
funcall([-,X,Y],Z,E) :-
eval(X,X1,E),
eval(Y,Y1,E),
Z is X1-Y1.
funcall([*,X,Y],Z,E) :-
eval(X,X1,E),
eval(Y,Y1,E),
Z is X1*Y1.
funcall([/,X,Y],Z,E) :-
eval(X,X1,E),
eval(Y,Y1,E),
Z is X1/Y1.
assoc(X,[],Z) :- fail.
assoc(X,[[X|Y]|Ys],Y).
assoc(X,[_|Ys],Z) :-
assoc(X,Ys,Z).
argument([X],[Y],[X|Y]).
argument([X|Xs],[Y|Ys],[[X|Y],Z]) :-
argument(Xs,Ys,Z).
global(t,t).
global(nil,nil).
:- dynamic(fun/3).
fun(dummy,a,b).