#!/usr/bin/python
#####################################################################
#
#  Script to extract a file of rules from rules.db 
#
#####################################################################
#
#   Command Line Argument
#
#   1.  Name of the output file.
#
#####################################################################

import sys,os,sqlite3
from getpath import getpath

if len(sys.argv) < 2:
	print "Usage: selectrules <Output File>"
	raise SystemExit

Rules_File = sys.argv[1]
if os.path.isfile(Rules_File):
	choice = None
	while choice not in ["y","yes","n","no"]:
		print Rules_File, "exists"
		choice = raw_input("Overwrite it? (y/n) ")
	if choice in ["n","no"]:
		raise SystemExit

Rules_Database = getpath("rules.db")

if not Rules_Database:
	print "rules.db not found"
	raise SystemExit

def fprint_header(filename, pred_query):
	f = open(filename, "w")
	f.write("""\\input utility.tdf
\\input logic.tdf

\\centerline{\\bigrm Rules of Inference}
\\vskip 1in


		This is a file of rules of inference used by ProofCheck.
It is generated by two queries to the sqlite3 data-base file rules.db.
The sentence logic was extracted with the query:

		  %(sentence_query)s

The predicate logic was extracted with the query:

		  %(predicate_query)s

Each rule occupies one line.  Any lines in this
(source) file without {\\TeX} dollar
signs are comment lines.  

The variables in this file taken from the beginning of the alphabet
are to be taken as fixed in relation to unification.  This forces the
unifier to match them with free variables.
Thus the rule that `for all x, pbar(x)' may be inferred from pbar(a)
even though the logical implication `pbar(y) implies for all x, pbar(x)'
is not a valid formula.

The unifier may take advantage of commutative and associative properties.
These properties must be stored in a properties file, (the default is
"properties.tex").   The choice of rules to be stored in this file
depends upon the properties that are stored.  This file is based on
the assumption that the commutative and associative properties of
logical conjunction are stored but not logical disjunction.
\\lineb """
% { 'sentence_query': "prd=0", 'predicate_query': pred_query })
	f.close()



def count_ones(x):
	n = 0
	while x:
		n = n + (x & 1)
		x = x >> 1
	return n

oplist = ['And', 'Or', 'Not']
priority_list = range(1 << len(oplist))
priority_list.sort(key=count_ones)

def op_flags(rule,oplist):
	flag = 1
	retval = 0
	for op in oplist:
		if op in rule:
			retval = retval + flag
		flag = flag << 1
	return retval

def parentheticp(s):
	sstrip = s.strip()
	return sstrip[0] == "(" and sstrip[-1] == ")"

def listprint(filename, rulelist,oplist):
	f = open(filename,"a")
	total = 0
	priority_list = range(1 << len(oplist))
	priority_list.sort(key=count_ones)
	for t in priority_list:
		opsection = [rule for rule in rulelist if op_flags(rule,oplist)==t]
		if opsection == []:
			continue
		opsection.sort(key=len)
		f.write("\n\nRules with ")
		for k in range(len(oplist)):
			if (1 << k) & t :
				f.write(oplist[k] + ", ")
		f.write("\n")
		total = total + len(opsection)
		for rule in opsection:
			assert '$' in rule
			f.write("\n" + rule + "\n")
	f.close()


print "Select a predicate logic using a pre-defined query:"
print "1. Standard predicate logic (without equality)"
print "2. Standard predicate logic with equality"
print "3. Standard predicate logic with definite descriptions"
print "4. Standard predicate logic with definite and indefinite descriptions"
print "5. Free predicate logic (without equality)"
print "6. Free predicate logic with equality"
print "7. Free predicate logic with definite descriptions"
print "8. Free predicate logic with definite and indefinite descriptions"

choice = 0
while choice not in range(1,9):
	user_string = raw_input("Enter 1-8 or a data base query: ")
	if user_string.strip() == "":
		choice = 4
	elif user_string.isdigit():
		choice = int(user_string)
	else:
		break


if choice in range(1,9):
	pred_query = ['place_holder',
					 'std=1 and equ=0 and def=0 and idf=0',
					 'std=1 and def=0 and idf=0',
					 'std=1 and idf=0',
					 'std=1',
					 'fre=1 and equ=0 and def=0 and idf=0 and cas=0',
					 'fre=1 and def=0 and idf=0 and cas=0',
					 'fre=1 and idf=0',
					 'fre=1'][choice]
	sent_query = "prd=0"
elif parentheticp(choice):
	sent_query = "prd=0 and " + choice
	pred_query = "prd=1 and " + choice
else:
	sent_query = "prd=0 and (" + choice + ")"
	pred_query = "prd=1 and (" + choice + ")"


fprint_header(Rules_File, pred_query)


con=sqlite3.connect(Rules_Database)
c=con.cursor()

sentential_rules = []
for row in c.execute('select rid, rul from rules where ' + sent_query):
	sentential_rules.append(row[1])

predicate_rules = []
for row in c.execute('select rid, rul from rules where ' + pred_query):
	predicate_rules.append(row[1])
con.close()

listprint(Rules_File,sentential_rules, ['And','Or','Not'])
listprint(Rules_File,predicate_rules, ['Each', 'Some','Unq','One','The'])
f = open(Rules_File,"a")
f.write("\end")
f.close()

