133 lines
3.7 KiB
Plaintext
133 lines
3.7 KiB
Plaintext
|
|
import yap
|
|
import os.path
|
|
import sys
|
|
# debugging support.
|
|
import pdb
|
|
from collections import namedtuple
|
|
|
|
yap_lib_path = os.path.dirname(__file__)
|
|
|
|
use_module = namedtuple( 'use_module', 'file')
|
|
bindvars = namedtuple( 'bindvars', 'list')
|
|
library = namedtuple( 'library', 'list')
|
|
v = namedtuple( '_', 'slot')
|
|
|
|
|
|
def numbervars( engine, l ):
|
|
rc = engine.fun(bindvars(l))
|
|
o = []
|
|
for i in rc:
|
|
if i[0] == "=":
|
|
o = o + [i[1]]
|
|
else:
|
|
o = o +[i]
|
|
return o
|
|
|
|
def query_prolog(engine, s):
|
|
|
|
def answer(q):
|
|
try:
|
|
return q.next()
|
|
except Exception as e:
|
|
print(e.args[1])
|
|
return False
|
|
|
|
#
|
|
# construct a query from a one-line string
|
|
# q is opaque to Python
|
|
q = engine.query(s)
|
|
# vs is the list of variables
|
|
# you can print it out, the left-side is the variable name,
|
|
# the right side wraps a handle to a variable
|
|
# pdb.set_trace()
|
|
vs = q.namedVars()
|
|
#pdb.set_trace()
|
|
# atom match either symbols, or if no symbol exists, sttrings, In this case
|
|
# variable names should match strings
|
|
#for eq in vs:
|
|
# if not isinstance(eq[0],str):
|
|
# print( "Error: Variable Name matches a Python Symbol")
|
|
# return
|
|
ask = True
|
|
# launch the query
|
|
while answer(q):
|
|
# this new vs should contain bindings to vars
|
|
vs= q.namedVars()
|
|
if vs != []:
|
|
gs = numbervars( engine, vs)
|
|
i=0
|
|
# iterate
|
|
for eq in gs:
|
|
name = eq[0]
|
|
binding = eq[1]
|
|
# this is tricky, we're going to bind the variables in the term so thay we can
|
|
# output X=Y. The Python way is to use dictionares.
|
|
#Instead, we use the T function to tranform the Python term back to Prolog
|
|
if name != binding:
|
|
print(name + " = " + str(binding))
|
|
#ok, that was Prolog code
|
|
else:
|
|
print("yes")
|
|
# deterministic = one solution
|
|
if q.deterministic():
|
|
# done
|
|
q.close()
|
|
return
|
|
if ask:
|
|
s = input("more(;), all(*), no(\\n), python(#) ?").lstrip()
|
|
if s.startswith(';') or s.startswith('y'):
|
|
continue
|
|
elif s.startswith('#'):
|
|
try:
|
|
exec(s.lstrip('#'))
|
|
except:
|
|
raise
|
|
elif s.startswith('*') or s.startswith('a'):
|
|
ask = False
|
|
continue
|
|
else:
|
|
break
|
|
print("No (more) answers")
|
|
q.close()
|
|
return
|
|
|
|
|
|
def live():
|
|
yap_lib_path = os.path.dirname(__file__)
|
|
args = yap.YAPEngineArgs()
|
|
args.setYapShareDir(os.path.join(yap_lib_path,"prolog"))
|
|
args.setYapLibDir(yap_lib_path)
|
|
#args.setYapPrologBootFile(os.path.join(yap_lib_path."startup.yss"))
|
|
engine = yap.YAPEngine(args)
|
|
engine.goal( use_module(library('yapi') ) )
|
|
loop = True
|
|
while loop:
|
|
try:
|
|
s = input("?- ")
|
|
if not s:
|
|
loop = False
|
|
else:
|
|
query_prolog(engine, s)
|
|
except SyntaxError as err:
|
|
print("Syntax Error error: {0}".format(err))
|
|
except EOFError:
|
|
return
|
|
except RuntimeError as err:
|
|
print("YAP Execution Error: {0}".format(err))
|
|
except ValueError:
|
|
print("Could not convert data to an integer.")
|
|
except:
|
|
print("Unexpected error:", sys.exc_info()[0])
|
|
raise
|
|
engine.close()
|
|
#
|
|
# initialize engine
|
|
# engine = yap.YAPEngine();
|
|
# engine = yap.YAPEngine(yap.YAPParams());
|
|
#
|
|
#
|
|
|
|
if __name__ == "__main__":
|
|
live()
|