package tarau.jinni; import java.util.*; import java.io.Reader; /** Implements a Term and Clause objects based blackboard (database). */ public class DataBase extends BlackBoard { public DataBase() { super(); } private static Const yes=Const.aYes; private static Const no=Const.aNo; /** Removes a matching Term from the blackboards and signals failure if no such term is found. */ public Term cin(String k,Term pattern) { Term found=take(k,pattern); //if(found!=null) { // found=found.matching_copy(pattern); //} if(found==null) found=no; else found=new Fun("the",found.copy()); return found; } /** Adds a Term to the blackboard */ public Term out(String k,Term pattern,boolean copying) { add(k,copying?pattern.copy():pattern); return yes; } /** Adds a copy of a Term to the blackboard */ synchronized public Term out(String key,Term pattern) { return out(key,pattern,true); //copies pattern } private void all0(int max,Vector To,String k,Term FXs) { if(0==max) max=-1; Queue Q=(Queue)get(k); if(Q==null) return; // todo: use always the same "server's" trail for(Enumeration e=Q.toEnumeration();e.hasMoreElements();) { Term t=(Term)e.nextElement(); if(null==t) break; t=t.matching_copy(FXs); if(t!=null && 0!=max--) To.addElement(t); } } private Term all1(int max,Term FXs) { Vector To=new Vector(); for(Enumeration e=keys();e.hasMoreElements();) { all0(max,To,(String)e.nextElement(),FXs); } Fun R=new Fun("$",To.size()); //IO.mes("RR"+R); To.copyInto(R.args); return ((Cons)R.listify()).args[1]; } private Term all2(int max,String k,Term FXs) { if(k==null) { //IO.mes("expensive operation: all/2 with unknown key"); return all1(max,FXs); } Vector To=new Vector(); all0(max,To,k,FXs); if(To.size()==0) return Const.aNil; Fun R=new Fun("$",To.size()); To.copyInto(R.args); Term T=((Cons)R.listify()).args[1]; return T; } /** Returns a (possibly empty) list of matching Term objects */ public Term all(String k,Term FX) { FX=all2(0,k,FX); return FX; } /** Gives an Enumeration view to the Queue of Term or Clause objects stored at key k @see Queue @see Term @see Clause */ public Enumeration toEnumerationFor(String k) { Enumeration E=super.toEnumerationFor(k); return E; } /** Returns a formatted String representation of this PrologBlackboard object */ public String pprint() { StringBuffer s=new StringBuffer(name()); Enumeration e=keys(); while(e.hasMoreElements()) { s.append(pred_to_string((String)e.nextElement())); s.append("\n"); } return s.toString(); } public String pred_to_string(String key) { Queue Q=(Queue)get(key); if(null==Q) return null; Enumeration e=Q.toEnumeration(); StringBuffer s=new StringBuffer("% "+key+"\n\n"); while(e.hasMoreElements()) { s.append(((Term)e.nextElement()).pprint(true)); s.append(".\n"); } s.append("\n"); return s.toString(); } /** consults or reconsults a Prolog file by adding or overriding existing predicates to be extended to load from URLs transparently */ static public boolean fromFile(String f,boolean overwrite) { IO.trace("last consulted file was: "+lastFile); boolean ok=fileToProg(f,overwrite); if(ok) { IO.trace("last consulted file set to: "+f); lastFile=f; } else IO.errmes("error in consulting file: "+f); return ok; } /** reconsults a file by overwritting similar predicates in memory */ static public boolean fromFile(String f) { return fromFile(f,true); } private static String lastFile="tarau/jinni/lib.pro"; /** reconsults the last reconsulted file */ static public boolean fromFile() { IO.println("begin('"+lastFile+"')"); boolean ok=fromFile(lastFile); if(ok) IO.println("end('"+lastFile+"')"); return ok; } static private boolean fileToProg(String fname,boolean overwrite) { Reader sname=IO.toFileReader(fname); if(null==sname) return false; return streamToProg(fname,sname,overwrite); } /** Reads a set of clauses from a stream and adds them to the blackboard. Overwrites old predicates if asked to. Returns true if all went well. */ static public boolean streamToProg(Reader sname,boolean overwrite) { return streamToProg(sname.toString(),sname,overwrite); } static private boolean streamToProg(String fname,Reader sname,boolean overwrite) { BlackBoard ktable=overwrite?(BlackBoard)Init.default_db.clone():null; //Clause Err=new Clause(new Const("error"),new Var()); try{ Parser p=new Parser(sname); apply_parser(p,fname,ktable); } catch(Exception e) { // already catched by readClause IO.errmes("unexpected error in streamToProg",e); return false; } return true; } static private void apply_parser(Parser p,String fname,BlackBoard ktable) { for(;;) { if(p.atEOF()) return; int begins_at=p.lineno(); Clause C=p.readClause(); if(null==C) return; if(Parser.isError(C)) Parser.showError(C); else { //IO.mes("ADDING= "+C.pprint()); processClause(C,ktable); C.setFile(fname,begins_at,p.lineno()); } } } /** adds a Clause to the joint Linda and Predicate table */ static public void addClause(Clause C,HashDict ktable) { String k=C.getKey(); // overwrites previous definitions if(null!=ktable && null!=ktable.get(k)) { ktable.remove(k); Init.default_db.remove(k); } Init.default_db.out(k,C,false); } /** adds a Clause to the joint Linda and Predicate table @see Clause */ static public void processClause(Clause C,HashDict ktable) { if(C.getHead().matches(new Const("init"))) { //IO.mes("init: "+C.getBody()); Prog.firstSolution(C.getHead(),C.getBody()); } else { //IO.mes("ADDING= "+C.pprint()); addClause(C,ktable); } } }