LoginSignup
1
0

More than 5 years have passed since last update.

Prologの新しいシンタックスの提案 3

Posted at

前回の提案の話を Twitter でしたところ、尾崎さん(通称Prologおじさん)に勝手にしろ。などと突き放されてしまいました。
わかったよ。勝手にするよ。このわからずや。こんな家出ていってやる。うぉー。っていうのも有りです。青春です。

しかしながら、DCG も最初から受け入れられていたわけではないでしょうし、DCGは --> 演算子を使って導入したことで、他の構文とも同居出来たように、新たな構文も同居可能なのではないでしょうか?
そのような考えから、:> 演算子を導入して :> を使った文のみを変換するよう改良してみました。

実行例

% eval6.npl

eval(Γ,X, V) :- member(X = V, Γ).
eval(,_i,_i) :- integer(_i).
eval(,a_+_b, v) :> eval(Γ, a,_v),eval(Γ, b,_v1),v_ is v + v1.
eval(,a_*_b, v) :> eval(Γ, a,_v),eval(Γ, b,_v1),v_ is v * v1.
eval(,x_=_a;_b, v) :> eval(Γ, a,_v),eval([x = v|Γ], b,_v).

t(,_x,t) :> atom(x),member(x:t_, Γ).
t(,_i,Int) :> integer(i).
t(,a_+_b,Int) :> t(Γ,a,Int),t(Γ,b,Int).
t(,a_*_b,Int) :> t(Γ,a,Int),t(Γ,b,Int).
t(,x_=_a;_b,t) :> t(Γ,a,_t),t([x:t|Γ],b,_t).

run(_e, r, t) :> t([], e,_t), eval([], e,_r).
:> run(x = 1 * 2 + 3 * 4; x,_r,_t), writeln(r:t).
:> a_ = 1, a_ is a+1, a_ is a+1, writeln(a).
:> a_:Int = x:_t, writeln(a:t).
:- halt.

今回は最初の2行は今までどおり :-/2 の記述が可能です。
3行目以降は :>/2 を使っているので、新たな記法が使えます。
:>/1 :-/1 も使うことが出来ます。

実装

% npl3.pl
:- op(1200,fx,[:>]).
:- op(1200,xfx,[:>]).
read_file_terms(F,R) :-
    open(F,read,FP),read_terms(FP,R,[]),close(FP).
read_terms(FP, Terms, Tail) :-
    read_term(FP, C1, [variable_names(Vs)]),read_terms_conv(C1,Vs),
    read_terms(C1, FP, Terms, Tail).
read_terms(end_of_file, _, Tail, Tail) :- !.
read_terms(C, FP, [C|T], Tail) :-
    read_term(FP, C2, [variable_names(Vs)]),read_terms_conv(C2,Vs),
    read_terms(C2, FP, T, Tail).
read_terms_conv((:> _),Vs) :- maplist(call,Vs).
read_terms_conv((_ :> _),Vs) :- maplist(call,Vs).
read_terms_conv(_,_).
% 述語1つを変換

conv_terms(_,[],[],I,I) :- !.
conv_terms(E,[C|Cs],[C2|Cs2],I,I2) :- conv_goal(E,C,C2,I,I1),conv_terms(E,Cs,Cs2,I1,I2).

conv_goal(_,V,V,I,I) :- var(V),!.
conv_goal(_,V,V3,I,I) :- atom(V),(concat('_',V2,V);concat(V2,'_',V)),memberchk(V2=V3,I),!.
conv_goal(_,V,V3,I,[V2=V3|I]) :- atom(V),(concat('_',V2,V);concat(V2,'_',V)).
conv_goal(E,V,V2,I,I) :- atom(V),memberchk(V=V2,E),!.
conv_goal(_,V,V,I,I) :- atomic(V),!.
conv_goal(E,V,V2,I,I2) :- V=..[C|Cs], conv_terms(E,Cs,Cs2,I,I2), V2=..[C|Cs2].

simpl(I1,I2) :- simpl([],I1,I2).
simpl(E,[],E).
simpl(E,[X=_|I1],I2) :- memberchk(X=_,E),simpl(E,I1,I2).
simpl(E,[V|I1],I2) :- simpl([V|E],I1,I2).

merge(S1,[],S1).
merge(S1,[X=V|S2],S3) :- member(X=V,S1),merge(S1,S2,S3).
merge(S1,[X=V|S2],S3) :- merge([X=V|S1],S2,S3).

conv_goals((A,B),(A1,B1)) --> conv_goals(A,A1),conv_goals(B,B1).
conv_goals((A;B),(A1;B1),I,I3) :-
    conv_goal(I,A,A1,[],I1),conv_goal(I,B,B1,[],I2),
    simpl(I1,S1),simpl(I2,S2),merge(S1,S2,S3),append(S3,I,I3).
conv_goals(A,A1,I,I2) :- conv_goal(I,A,A1,[],I1),append(I1,I,I2).

% 文を変換
conv_stmt((:> V),(:- V2)) :- !,conv_goals(V,V2,[],_).
conv_stmt((H :> V),(H3 :- V2)) :- !,conv_goals((H,V),(H2,V2),[],I),!,
  conv_goals(H2,H3,I,_).
conv_stmt(V,V).
% 文のリストを変換
conv_stmts(Vs,Vs2) :- maplist(conv_stmt,Vs,Vs2).

assert1(:- V) :- call(V).
assert1(V) :- assertz(V).
consult1(F) :- read_file_terms(F,R),conv_stmts(R,R2),maplist(assert1,R2).
:- current_prolog_flag(argv, Argv),maplist(consult1,Argv).

:> 演算子を使った場合だけ変換するよう変更しました。

まとめ

新たな構文を既存文法に加え混在できるように修正しました。
これならば従来のPrologの資産を生かしつつ新規ユーザーは新しい構文で記述することが出来ます。
今までの資産を切り捨てることなく新しい構文を利用できます。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0