/* *********************************************************
        upload module
********************************************************** */

:- import ins/1, asrt/1, db/1 from 'updates.pl'.
:- import wff/2 from 'parser.pl'.
:- import append/3 from basics.

:- op(500, fx, [updatable]).

% upload a program into transaction base.
%
comp_trans(File) :-  
                in_filename(File,File1),
		see(File1), 
	      	out_filename(File1,FileOut),	
                unix('rm -f FileOut 2>/dev/null', R1),
	        tell(FileOut), 
		repeat_read_and_compile(File1,FileOut),
		seen, told,
		insert_file(FileOut).

/* parsing rules repeatedly */
repeat_read_and_compile(FileIn,FileOut) :-
	read(Term),
	(
	(Term == end_of_file) -> true
	;
	read_and_write_rule(Term,FileIn,FileOut), 
	repeat_read_and_compile(FileIn,FileOut)  ).


/* translation of a clause */
read_and_write_rule(':-'(Lhs,Rhs),_,_) :-
        write('trans('),
        write(Lhs),
        write(')'),
        write(' :-  '),
        wff(Rhs, PRhs),
        write(PRhs),
        write('.'), nl,
        write(Lhs),
        write(' :- fail.'), nl.

/* translation of a transaction atom */
read_and_write_rule(Term,_,_) :-
	not(Term = ':-'(_,_)),
        write(Term),
        write('.'), nl.

% upload a program into database.
% (similar to load_dyn)
comp_db(File) :- 
                db_filename(File,File2),
		see(File2),
		read(Term),
                tmp_filename(File,File3),
                unix('rm -f File3 2>/dev/null', R1),
                tell(File3),
		write_a_line(Term,File2,File3),
		seen,
                told,
                see(File3),
                read(T),
                load_a_line(T,File3),
                seen.
%               insert_file(File3).

write_a_line(updatable(Name/Num),File2,File3) :-
                db_mod(Name,Num,Arg),
                write(Arg), nl,
                db_ins(Name,Num,Argi),
                write(Argi), nl,
                read(Next), !,
                write_a_line(Next,File2,File3).

write_a_line((Lhs :- Rhs),File2,File3) :-
                write(Lhs),
                write(' :- '),
                write(Rhs),
                write('.'), nl,
                read(Next), !,
                write_a_line(Next,File2,File3).

write_a_line(Term,File2,File3) :-
                not(Term = updatable(_)),
                write_and_assert(Term,File2,File3).

load_a_line(modif(P),File3) :-
                asrt(P),
                read(Next), !,
                load_a_line(Next,File3).

% insert a clause to database
load_a_line((Lhs :- Rhs),File3) :-
                assert((Lhs :- Rhs)),
                read(Next), !,
                load_a_line(Next,File3).
                
% insert a new tuple to database
load_a_line(Term,File3) :-
                not(Term = modif(_)),
                read_and_assert(Term,File3).

write_and_assert(Term,File2,File3) :-
                (Term == end_of_file), !, true
                ;
                write(Term), 
                write('.'), nl,
                read(Next), !,
                write_a_line(Next,File2,File3).

% insert a new tuple(by create)
read_and_assert(Term,File3) :-
                (Term == end_of_file), !, true   
                ;
                ins(Term),
                read(Next), !,
                load_a_line(Next,File3).

% create the clause p(X) = db(p(X)).
db_ins(Name,Num,Argj) :- name(Name,Namel),
                        db_name(Namel,Name1),
                        db_arg(Name1,Num,Argj).
                        

db_name(Namel,Name1) :- append(Namel,"(",Name1).

db_arg(Name1,0,Argj) :- append(Name1,")",Arg1),
                       append(Arg1," :- db(",Arg2),
                       append(Arg2,Arg1,Arg3),   
                       append(Arg3,").",Argl),
                       name(Argj,Argl).

db_arg(Name1,Num,Argj) :- name(Num,L),
                         append("X",L,Argi),
                         append(Name1,Argi,Tmp1),
                         Num1 is Num - 1, 
                         (Num1 = 0,
                         db_arg(Tmp1,Num1,Argj)
                         ;
                         append(Tmp1,",",Tmp2),
                         db_arg(Tmp2,Num1,Argj)).

% create the clause p(X) = db(p(X)).
db_mod(Name,Num,Arg) :- name(Name,Namel),
                        db_name1(Namel,Name1),
                        db_arg1(Name1,Num,Arg).
                
                 
db_name1(Namel,Name1) :- append("modif(",Namel,Namel1),
                         append(Namel1,"(",Name1).
                
db_arg1(Name1,0,Arg) :- append(Name1,")).",Arg1),
                        name(Arg,Arg1).

db_arg1(Name1,Num,Arg) :- name(Num,L),
                          append("X",L,Argi),
                          append(Name1,Argi,Tmp1),
                          Num1 is Num - 1,
                          (Num1 = 0,
                          db_arg1(Tmp1,Num1,Arg)
                          ;
                          append(Tmp1,",",Tmp2),
                          db_arg1(Tmp2,Num1,Arg)).
                                               
% create the names for files
in_filename(FileIn,FileOut) :-
        name(FileIn,NameIn),
        append(NameIn,".ctr",NameOut),
        name(FileOut,NameOut).

out_filename(FileIn,FileOut) :-
        name(FileIn,NameIn),
        append(NameIn,".o",NameOut),
        name(FileOut,NameOut).

db_filename(FileIn,FileOut) :-
        name(FileIn,NameIn),
        append(NameIn,".db",NameOut),
        name(FileOut,NameOut).

tmp_filename(FileIn,FileOut) :-
        name(FileIn,NameIn),      
        append(NameIn,".db.o",NameOut),
        name(FileOut,NameOut).

insert_file(FileName) :-
        seeing(X),   
        see(FileName),
        read_and_add_line,
        see(X).

read_and_add_line :-
        read(Line),
        (
        (Line == end_of_file)   -> true
        ;
        assert(Line),
        read_and_add_line ).



