2018-02-26 21:38:19 +00:00
|
|
|
import readline
|
2018-03-18 00:44:08 +00:00
|
|
|
from yap4py.yap import *
|
2018-03-17 10:38:56 +00:00
|
|
|
from os.path import join, dirname
|
|
|
|
from collections import namedtuple
|
|
|
|
import sys
|
|
|
|
|
|
|
|
yap_lib_path = dirname(__file__)
|
|
|
|
|
|
|
|
compile = namedtuple('compile', 'file')
|
|
|
|
bindvars = namedtuple('bindvars', 'list')
|
|
|
|
library = namedtuple('library', 'list')
|
|
|
|
v0 = namedtuple('v', 'slot')
|
|
|
|
yap_query = namedtuple('yap_query', 'query owner')
|
|
|
|
jupyter_query = namedtuple('jupyter_query', 'vars dict')
|
|
|
|
python_query = namedtuple('python_query', 'vars dict')
|
|
|
|
yapi_query = namedtuple('yapi_query', 'vars dict')
|
|
|
|
show_answer = namedtuple('show_answer', 'vars dict')
|
|
|
|
set_prolog_flag = namedtuple('set_prolog_flag', 'flag new_value')
|
2017-09-06 02:15:22 +01:00
|
|
|
|
|
|
|
|
|
|
|
class Engine( YAPEngine ):
|
2017-11-09 12:14:41 +00:00
|
|
|
|
2018-01-27 10:17:27 +00:00
|
|
|
def __init__(self, args=None,self_contained=False,**kwargs):
|
2017-09-06 02:15:22 +01:00
|
|
|
# type: (object) -> object
|
|
|
|
if not args:
|
|
|
|
args = EngineArgs(**kwargs)
|
2018-01-27 10:17:27 +00:00
|
|
|
if self_contained:
|
2018-03-17 10:38:56 +00:00
|
|
|
yap_lib_path = dirname(__file__)
|
|
|
|
args.setYapShareDir(join(yap_lib_path, "prolog"))
|
2018-03-02 21:18:24 +00:00
|
|
|
args.setYapPLDIR(yap_lib_path)
|
2018-03-17 10:38:56 +00:00
|
|
|
args.setSavedState(join(yap_lib_path, "startup.yss"))
|
2017-11-09 12:14:41 +00:00
|
|
|
YAPEngine.__init__(self, args)
|
2018-05-26 00:22:27 +01:00
|
|
|
self.goal(set_prolog_flag('verbose', 'silent'),True)
|
|
|
|
self.goal(compile(library('yapi')), True)
|
|
|
|
self.goal(set_prolog_flag('verbose', 'normal'), True)
|
2017-09-06 02:15:22 +01:00
|
|
|
|
2018-05-25 12:30:31 +01:00
|
|
|
def run(self, g, m=None, release=False):
|
2017-09-06 02:15:22 +01:00
|
|
|
if m:
|
2018-05-26 00:22:27 +01:00
|
|
|
self.mgoal(g, m, release)
|
2017-09-06 02:15:22 +01:00
|
|
|
else:
|
2018-05-26 00:22:27 +01:00
|
|
|
self.goal(release)
|
2017-09-06 02:15:22 +01:00
|
|
|
|
|
|
|
|
|
|
|
class EngineArgs( YAPEngineArgs ):
|
|
|
|
""" Interface to Engine Options class"""
|
|
|
|
def __init__(self, args=None,**kwargs):
|
|
|
|
super().__init__()
|
|
|
|
|
|
|
|
|
|
|
|
class Predicate( YAPPredicate ):
|
|
|
|
""" Interface to Generic Predicate"""
|
|
|
|
|
2018-02-26 21:38:19 +00:00
|
|
|
def __init__(self, t, module=None):
|
|
|
|
super().__init__(t)
|
2017-09-06 02:15:22 +01:00
|
|
|
|
2018-03-17 10:38:56 +00:00
|
|
|
class Query:
|
2018-02-26 21:38:19 +00:00
|
|
|
"""Goal is a predicate instantiated under a specific environment """
|
2018-03-02 21:18:24 +00:00
|
|
|
def __init__(self, engine, g):
|
2018-05-29 09:59:28 +01:00
|
|
|
engine.reSet()
|
|
|
|
self.engine = engine
|
2018-03-17 10:38:56 +00:00
|
|
|
self.q = engine.query(g)
|
|
|
|
if self.q:
|
|
|
|
self.port = "call"
|
|
|
|
self.bindings = None
|
|
|
|
self.engine = engine
|
|
|
|
self.answer = {}
|
2017-09-06 02:15:22 +01:00
|
|
|
|
|
|
|
def __iter__(self):
|
|
|
|
return self
|
|
|
|
|
2018-02-26 21:38:19 +00:00
|
|
|
def __next__(self):
|
|
|
|
if not self.q:
|
2018-05-30 21:54:12 +01:00
|
|
|
raise RuntimeError()
|
2018-05-30 13:07:45 +01:00
|
|
|
if self.port == "exit":
|
|
|
|
return
|
2017-09-06 02:15:22 +01:00
|
|
|
else:
|
2018-05-30 21:54:12 +01:00
|
|
|
if self.q.next():
|
|
|
|
return self.port,self.answer
|
|
|
|
else:
|
2018-02-26 21:38:19 +00:00
|
|
|
self.close()
|
2017-09-06 02:15:22 +01:00
|
|
|
|
2018-03-17 10:38:56 +00:00
|
|
|
def close( self ):
|
2018-05-26 00:22:27 +01:00
|
|
|
if self.q:
|
|
|
|
self.q.close()
|
|
|
|
self.q = None
|
2018-02-26 21:38:19 +00:00
|
|
|
|
2017-09-06 02:15:22 +01:00
|
|
|
|
2018-03-17 10:38:56 +00:00
|
|
|
def name( name, arity):
|
2017-11-08 09:29:01 +00:00
|
|
|
try:
|
2018-03-17 10:38:56 +00:00
|
|
|
if arity > 0 and name.isidentifier(): # and not keyword.iskeyword(name):
|
2017-11-08 09:29:01 +00:00
|
|
|
s = []
|
|
|
|
for i in range(arity):
|
|
|
|
s += ["A" + str(i)]
|
2018-03-17 10:38:56 +00:00
|
|
|
return namedtuple(name, s)
|
2017-11-08 09:29:01 +00:00
|
|
|
except:
|
2018-03-17 10:38:56 +00:00
|
|
|
return None
|
2017-11-08 09:29:01 +00:00
|
|
|
|
|
|
|
class PrologPredicate( YAPPrologPredicate ):
|
|
|
|
""" Interface to Prolog Predicate"""
|
|
|
|
|
2018-03-17 10:38:56 +00:00
|
|
|
class v(YAPVarTerm,v0):
|
2017-09-06 02:15:22 +01:00
|
|
|
def __init__(self):
|
2018-03-17 10:38:56 +00:00
|
|
|
YAPVarTerm.__init__()
|
2017-09-06 02:15:22 +01:00
|
|
|
|
|
|
|
def binding(self):
|
|
|
|
return self.term()
|
|
|
|
|
|
|
|
|
|
|
|
class YAPShell:
|
2018-05-25 12:30:31 +01:00
|
|
|
|
2018-03-17 10:38:56 +00:00
|
|
|
def numbervars( self ):
|
|
|
|
Dict = {}
|
2018-05-26 00:22:27 +01:00
|
|
|
self.engine.goal(show_answer( self, Dict), True)
|
2018-03-17 10:38:56 +00:00
|
|
|
return Dict
|
|
|
|
# rc = self.q.namedVarsVector()
|
|
|
|
# self.q.r = self.q.goal().numbervars()
|
|
|
|
# o = []
|
|
|
|
# for i in rc:
|
|
|
|
# if len(i) == 2:
|
|
|
|
# do = str(i[0]) + " = " + str( i[1] ) + "\n"
|
|
|
|
# o += do
|
|
|
|
# else:
|
|
|
|
# do = str(i[0]) + " = " + str( i[1] ) + "\n"
|
|
|
|
# o += do
|
|
|
|
# return o
|
|
|
|
|
|
|
|
|
|
|
|
def query_prolog(self, query):
|
2018-05-25 12:30:31 +01:00
|
|
|
g = None
|
2018-03-02 21:18:24 +00:00
|
|
|
#import pdb; pdb.set_trace()
|
2017-09-06 02:15:22 +01:00
|
|
|
#
|
|
|
|
# construct a query from a one-line string
|
|
|
|
# q is opaque to Python
|
|
|
|
#
|
2018-02-26 21:38:19 +00:00
|
|
|
#q = engine.query(python_query(self, s))
|
2017-09-06 02:15:22 +01:00
|
|
|
#
|
|
|
|
# # 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
|
2018-05-30 21:54:12 +01:00
|
|
|
import pdb; pdb.set_trace()
|
2017-09-06 02:15:22 +01:00
|
|
|
# #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
|
2018-03-24 22:56:52 +00:00
|
|
|
try:
|
|
|
|
engine = self.engine
|
2018-05-29 09:59:28 +01:00
|
|
|
bindings = []
|
2018-03-24 22:56:52 +00:00
|
|
|
loop = False
|
2018-05-25 12:30:31 +01:00
|
|
|
if g:
|
|
|
|
g.release()
|
2018-03-24 22:56:52 +00:00
|
|
|
g = python_query(self, query)
|
2018-05-25 12:30:31 +01:00
|
|
|
self.q = Query( engine, g )
|
2018-05-30 21:54:12 +01:00
|
|
|
for port,bind in self.q:
|
2018-03-24 22:56:52 +00:00
|
|
|
bindings += [bind]
|
2018-05-30 21:54:12 +01:00
|
|
|
if port == "exit":
|
|
|
|
break
|
2018-03-24 22:56:52 +00:00
|
|
|
if loop:
|
|
|
|
continue
|
2018-05-30 21:54:12 +01:00
|
|
|
s = input("more(;), all(*), no(\\n), python(#)? ").lstrip()
|
2018-03-24 22:56:52 +00:00
|
|
|
if s.startswith(';') or s.startswith('y'):
|
|
|
|
continue
|
|
|
|
elif s.startswith('#'):
|
|
|
|
try:
|
|
|
|
exec(s.lstrip('#'))
|
|
|
|
except:
|
|
|
|
raise
|
|
|
|
elif s.startswith('*') or s.startswith('a'):
|
|
|
|
loop = True
|
|
|
|
continue
|
|
|
|
else:
|
|
|
|
break
|
2018-05-25 12:30:31 +01:00
|
|
|
if self.q:
|
2018-05-29 09:59:28 +01:00
|
|
|
self.q.close()
|
2018-05-30 08:12:51 +01:00
|
|
|
self.q = None
|
2018-03-24 22:56:52 +00:00
|
|
|
if bindings:
|
|
|
|
return True,bindings
|
|
|
|
print("No (more) answers")
|
|
|
|
return False, None
|
2018-03-26 11:03:08 +01:00
|
|
|
except Exception as e:
|
2018-05-25 12:30:31 +01:00
|
|
|
if not self.q:
|
2018-05-24 12:00:10 +01:00
|
|
|
return False, None
|
2018-05-29 09:59:28 +01:00
|
|
|
self.q.close()
|
2018-05-30 08:12:51 +01:00
|
|
|
self.q = None
|
|
|
|
print("Exception",e)
|
|
|
|
e.errorNo = 0
|
2018-05-30 13:07:45 +01:00
|
|
|
raise
|
2017-09-06 02:15:22 +01:00
|
|
|
|
|
|
|
def live(self, engine, **kwargs):
|
|
|
|
loop = True
|
2018-02-26 21:38:19 +00:00
|
|
|
self.q = None
|
2017-09-06 02:15:22 +01:00
|
|
|
while loop:
|
|
|
|
try:
|
|
|
|
s = input("?- ")
|
|
|
|
if not s:
|
2018-05-30 08:12:51 +01:00
|
|
|
continue
|
2017-09-06 02:15:22 +01:00
|
|
|
else:
|
2018-05-30 08:12:51 +01:00
|
|
|
print(s)
|
2018-03-17 10:38:56 +00:00
|
|
|
self.query_prolog(s)
|
2017-09-06 02:15:22 +01:00
|
|
|
except SyntaxError as err:
|
|
|
|
print("Syntax Error error: {0}".format(err))
|
2018-05-30 13:07:45 +01:00
|
|
|
continue
|
2017-09-06 02:15:22 +01:00
|
|
|
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());
|
|
|
|
#
|
|
|
|
def __init__(self, engine, **kwargs):
|
2018-03-17 10:38:56 +00:00
|
|
|
self.engine = engine
|
2018-05-24 21:45:38 +01:00
|
|
|
|
2018-03-17 10:38:56 +00:00
|
|
|
self.live(engine)
|
2018-05-24 12:00:10 +01:00
|
|
|
self.q = None
|
2017-09-06 02:15:22 +01:00
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
engine = Engine()
|
|
|
|
YAPShell(engine)
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
main()
|