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.setYapPrologSOURCEBOOT(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()