| 
									
										
										
										
											2017-05-19 10:03:49 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 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) | 
					
						
							| 
									
										
										
										
											2019-01-09 09:32:09 +00:00
										 |  |  |     #args.setYapPrologSOURCEBOOT(os.path.join(yap_lib_path."startup.yss")) | 
					
						
							| 
									
										
										
										
											2017-05-19 10:03:49 +01:00
										 |  |  |     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() |