#!/usr/local/bin/prologcgi

:-s_charset(_,utf8).
top_call:-
    get_params(A),
    html_call([
    "Content-Type: text/html; charset=utf-8

    <html lang='ja'><head><meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
    <title>式の展開</title></head>
    <body><center><H1> Hello Prolog World!!  <<式の展開>></H1>
       <a href='puttxt.exe?formula.cgi' target='source'>このページのソース表示</a><br>
       <INPUT TYPE='button' VALUE='RETURN' onClick='history.back()'><br><br>
     <table border='1' width='80%'><tr><td>
       <form action='formula.cgi' method='POST'>
         <input type='text' name = 'formula' value='",A,"'>
         <input type='submit' value='展開計算'>
       </form></td></tr><tr><td>",
        call(formulas(A)),
    "</td></tr></table></center></body></html>" ]).

formulas(A):-
    term_atom(T,A),simp(T,Y),zero(Y,Z),disp(Z,Z1),write(Z1),!.
formulas.

get_params(A):-get_param(formula,A),!.
get_params('(a+b)^2').

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% FORMULA.PL Copyright (C) 1983,85,86 by Kyoto Artificial Brain Associates %%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

formula(F):-see(F),repeat,read(X),form1(X),!,seen.

form1(end_of_file) :- !.
form1(X) :- abolish(vars,2),simp(X,Y),zero(Y,Z),disp(Z,Z1),write(Z1),nl,
        abolish(vars,2),!,fail.

simp(X,X) :- integer(X),!.
simp(X,Y) :- atom(X),!,rep(X,Y).
simp(T1+T2,X) :- !,simp(T1,S1),simp(T2,S2),plus(S1,S2,X).
simp(T1-T2,X) :- !,simp(T1,S1),simp(T2,S2),cmul(-1,S2,S3),plus(S1,S3,X).
simp(T1*T2,X) :- !,simp(T1,S1),simp(T2,S2),time(S1,S2,X).
simp(T1^T2,X) :- !,simp(T1,S1),simp(T2,S2),expt(S1,S2,X).

plus(X,Y,Z) :- integer(X),integer(Y),!,Z is X+Y.
plus(X,Y,Z) :- integer(X),!,plus([X],Y,Z).
plus(X,Y,Z) :- integer(Y),!,plus(X,[Y],Z).
plus([],Y,Y) :- !.
plus(X,[],X) :- !.
plus([X|Xs],[Y|Ys],[Z|Zs]) :- plus(X,Y,Z),plus(Xs,Ys,Zs).

cmul(0,X,0) :- !.
cmul(1,X,X) :- !.
cmul(C,X,Z) :- integer(X),!,Z is C*X.
cmul(C,[],[]) :- !.
cmul(C,[X|Xs],[Z|Zs]) :- cmul(C,X,Z),cmul(C,Xs,Zs).

time(X,Y,Z) :- integer(X),!,cmul(X,Y,Z).
time(X,Y,Z) :- integer(Y),!,cmul(Y,X,Z).
time([],Y,[]) :- !.
time([X|Xs],Y,Z) :- time1(Y,X,Y1),time(Xs,[0|Y],Z1),plus(Y1,Z1,Z).

time1([],C,[]) :- !.
time1([X|Xs],C,[Y|Ys]) :- time(X,C,Y),time1(Xs,C,Ys).

expt(X,0,1) :- !.
expt(X,1,X) :- !.
expt(X,N,Z) :- N1 is N-1,expt(X,N1,Z1),time(X,Z1,Z).

rep(X,Y) :- vars(X,N),!,rep1(N,Y).
rep(X,Y) :- clause(vars,2,N),N1 is N+1,asserta(vars(X,N1)),rep1(N1,Y).

rep1(1,[0,1]) :- !.
rep1(N,[X]) :- N1 is N-1,rep1(N1,X).

zero([],0) :- !.
zero(X,X) :- integer(X),!.
zero([X|Xs],Y) :- zero(X,X1),zero(Xs,Z),zero1(X1,Z,Y).

zero1(0,0,0) :- !.
zero1(X,0,[X]) :- !.
zero1(X,Y,[X|Y]).

disp([],0) :- !.
disp(X,X) :- integer(X),!.
disp(X,Y) :- disp1(X,Y1,[]),disp3(Y1,Y).

disp1(0,[],V) :- !.
disp1(X,[[X|V]],V) :- integer(X),!.
disp1(X,Y,V) :- disp2(X,Y,V,0).

disp2([],[],V,N) :- !.
disp2([X|Xs],Y,V,N) :-
     disp1(X,Y1,[N|V]),N1 is N+1,disp2(Xs,Y2,V,N1),append(Y1,Y2,Y).

disp3([X],Y) :- !,reverse(X,X1),disp4(X1,Y,1).
disp3([[0|As]|Xs],Ys) :- !,disp3(Xs,Ys).
disp3([[A|As]|Xs],Ys-Y) :- A<0,!,A1 is -A,reverse([A1|As],X1),disp4(X1,Y,1),
                disp3(Xs,Ys).
disp3([X|Xs],Ys+Y) :- reverse(X,X1),disp4(X1,Y,1),disp3(Xs,Ys).

disp4([X],X,N) :- !.
disp4([0|Xs],Y,N) :- !,N1 is N+1,disp4(Xs,Y,N1).
disp4([1|Xs],Y,N) :- !,vars(V,N),N1 is N+1,disp4(Xs,Y1,N1),disp5(Y1,V,Y).
disp4([X|Xs],Y,N) :- vars(V,N),N1 is N+1,disp4(Xs,Y1,N1),disp5(Y1,V^X,Y).

disp5(1,V,V) :- !.
disp5(X,V,X*V).

% append([],X,X) :- !.
% append([A|X],Y,[A|Z]) :- append(X,Y,Z).

reverse(X,Y) :- reverse1(X,[],Y).

reverse1([],Y,Y) :- !.
reverse1([X|Xs],Y,Z) :- reverse1(Xs,[X|Y],Z).
