#!/usr/local/bin/perl
#                      Copyright(C)1997  Sigeki Fukuta
#                                        Mitsuru Ishizuka
#                                 Dept. of Information & Commun. Eng. 
#                                 School of Eng. 
#                                 Univ. of Tokyo

#*********************************************************************
#               runqsqr Ver 1.10 ('97/6/25)
#               Programed by Shigeki Fukuta
#         This program will run on Perl 4.0 or up.
#*********************************************************************

#DEFINE of filenames and Parameter####################################
$TRY = 1;			# load qsqr $TRY times.(for time check)
$PROLOG = '/usr/local/bin/sicstus'; 
				# place of prolog.
$NBP = 'nbp';	# place of nbp.
$TEST3 = '/home/futada/master/test3';
				# place of test3 (Programed by Futada)
$EXSORT = '/home/futada/master/exsort/exsort';
				# place of exsort (Programed by Futada)
$PROGRAM = 'qsqr.plg';
				# qsqr program written by prolog.


$DATAFILE = 'rundata';		# input file to prolog.
$DATAFILE2 = 'qsqr.nod';	# output file from prolog.
$DATAFILE3 = 'tmp.lst';		# input file to nbp.
$TEST3TMP = 'test3.tmp';	# tmporary file for test3 
$CALL = 1;			# if don't call nbp, change this false.
$FUTADA = 0;			# if call test3, change this true.
$NEWLINE = 5;			# number of hypothesis and fact in a line.
$DEPTH = 6;			# depth of searching tree.
$INC = 1;			# If $INC = 0, inc format is "inc :- bodys."
######################################################################


#variable declaration (unnecessary)###################################
%hyp = ();			# $hyp{hypothesis} = "vallue"
@fact = ();			# $fact[n] = "a fact"
@inc = ();			# $inc[n] = "inc1,inc2,..."
@data = ();			# input filenaemes to runqsqr.
######################################################################

&readarg(*data);

foreach $data (@data) {
	%hyp = ();
	@fact = ();
	@inc = ();
	$depth = $DEPTH;

	print "try $data\n";
	$inc = &convforprolog($data,*fact,*hyp,*inc);
	$inc && print "inc exist!\n";
	for( $i=0 ; $i<$TRY ; $i++ ) {
		&run($DATAFILE,$depth,$inc);
	}

	&convfornbp(*fact,*hyp);

	$CALL && &callnbp;
	$FUTADA && &calltest3

}




#/////////////////////////////////////////////////////////////////////
# text convert for nbp.
sub convfornbp {
local(*fact,*hyp,$inc) = @_;
local($tmp,$comma,@line,@inc) = ();
open(FILE,"$DATAFILE2") || die "open $DATAFILE2 file failed\n";

#read $DATAFILE2.
while (<FILE>) {
	chop;
	s/([^)])\,/$1\_/g;
	s/([^)])\./$1\@/g;
	s/[\[\]]//g;
	if (/^inc /o) {
		$INC && s/^inc /0 /o;
		push(@inc,$_."\.\n");
		next;
	}
	push(@line,$_."\.\n");
}
close(FILE);

#sort lines.
@line = sort (@line);

#write $DATAFILE3.
open(OUT ,">$DATAFILE3") || die "open $DATAFILE3 file failed\n";

#print goal.
print OUT "1 :- goal.\n";

#print rules.
foreach (@line) {
	print OUT;
}
@line = ();

#print inc.
foreach (@inc) {
	print OUT;
}

#print facts.
if (scalar @fact) {
	print OUT ">";
	foreach (@fact) {
		if($comma == $NEWLINE) {
			print OUT ".\n>" ;
			$comma = 0;
		} elsif ($comma) {
			print OUT ",";
		}
		s/([^)])\,/$1\_/g;
		s/([^)])\./$1\@/g;
		print OUT "$_";
		$comma++;
	}
	print OUT ".\n";
}
$comma = 0;

#print hypothesis.
if (scalar %hyp) {
	print OUT "\$";
	foreach (keys %hyp) {
		if($comma == $NEWLINE) {
			print OUT ".\n\$" ;
			$comma =0;
		} elsif ($comma) {
			print OUT ",";
		}
		$tmp = $hyp{$_};
		s/([^)])\,/$1\_/g;
		s/([^)])\./$1\@/g;
		print OUT "$_/$tmp";
		$comma++;
	}
	print OUT ".\n";
}

close(OUT);
}
#/////////////////////////////////////////////////////////////////////
# call test3.
sub calltest3 {
	print "call exsort\n";
	system("cat tmp.lst | $EXSORT | $EXSORT -2 >$TEST3TMP");
	wait;
	print "call test3\n";
	print "$TEST3 $TEST3TMP\n";
	system("$TEST3 $TEST3TMP");
}

#/////////////////////////////////////////////////////////////////////
# call nbp.
sub callnbp {
	open(NBP,"| $NBP $DATAFILE3");
	print NBP "0\n2\n";
	close(NBP);
}
#/////////////////////////////////////////////////////////////////////
# call Prolog and $PROGRAM.
sub run{
	local($data,$depth) = @_;
	open(SICS, "| $PROLOG");
	print SICS <<EOF;
assert(lemma(dummy)).
assert(qu(dummy)).
assert(ansx(0,dummy)).
compile('$PROGRAM').
compile('$data').
tell('$DATAFILE2').
main(goal,$depth).
EOF
	$inc && print SICS "main(inc,$depth).\n";

	print SICS "told.\n";
	close(SICS);
	wait;
}
#/////////////////////////////////////////////////////////////////////
# text convert for Prolog.
sub convforprolog{
	local($file,*fact,*hyp) = @_;
	local(@inc);
	open(FILE,$file) || die "open failed in $file at read\n";
	while(<FILE>) {
		s/#.*//go;
		s/\s//go;
		if (/[1\?]:?\-(.*)\./) {
			push(@rule,"rule(goal,[$1]).");
		} elsif (/inc\:?\-(.+)\./) {
			push(@inc,$1);
		} elsif (/0\:?\-(.+)\./) {
			push(@inc,$1);
		} elsif (/(.+)\:\-(.+)\./) {
			push(@rule,"rule($1,[$2]).");
		} elsif (/(.+)\-(.+)\./) {
			push(@rule,"rule($1,[$2]).");
		} elsif (/\$?(.+)\/(\d*).*\./) {
			$hyp{$1} = $2;
		} elsif (/[\>\!]?(.+)\./) {
			push(@fact,$1);
		}
	}
	close(FILE);
	$" = "\n";
	open(FILE,">$DATAFILE") || die "open failed in rundata at write\n";
	print FILE "@rule\n";
	foreach (@fact) {
		print FILE "fact($_).\n";
	}
	foreach (keys %hyp) {
		print FILE "fact($_).\n";
	}
	foreach (@inc) {
		print FILE "rule(inc,[$_]).\n";
	}
	close(FILE);
	scalar(@inc);
}
#/////////////////////////////////////////////////////////////////////
# read parameters.
sub readarg {
	local(*data) = @_;
	if (@ARGV) {
		foreach(@ARGV) {
			if (/-n/) {
				$CALL = 0;
			} elsif (/-t(\d+)/) {
				$TRY = $1;
			} elsif (/-l(\d+)/) {
				$NEWLINE = $1;
			} elsif (/-d(\d+)/) {
				$DEPTH = $1;
			} elsif (/-f/) {
				$CALL = 0;
				$FUTADA =1;
			} elsif (/-i/) {
				$INC = 0;
			} else{
				push(@data,$_);
			}
		}
	} else {
		die <<EOF;
Usage: runqsqr [option] <datafile> [<datafile>...]
 options
 -n		:Don't call NBP(only output tmp.lst).
 -i		:inc format changes to "inc :- bodys."
 -d[numbers]	:depth of searching tree.
 -l[numbers]	:number of hypothesis and fact in a line.
 -t[numbers]	:load prolog <numbers> times(for time check).

 If numbers are omitted, programs run as default.

EOF
	}
}
