@Override public List getTerm() { if (immutable) { return this; } else { Term newHead = head.getTerm(); Term newTail = tail.getTerm(); if (newHead == head && newTail == tail) { return this; } else { return new List(newHead, newTail, newHead.isImmutable() && newTail.isImmutable()); } } }
public boolean char_code_2(Term arg0, Term arg1) throws PrologError { arg0 = arg0.getTerm(); arg1 = arg1.getTerm(); if (arg1 instanceof Var) { if (arg0.isAtom()) { String st = ((Struct) arg0).getName(); if (st.length() <= 1) return unify(arg1, new Int(st.charAt(0))); else throw PrologError.type_error(engine.getEngineManager(), 1, "character", arg0); } else throw PrologError.type_error(engine.getEngineManager(), 1, "character", arg0); } else if ((arg1 instanceof Int) || (arg1 instanceof alice.tuprolog.Long)) { char c = (char) ((Number) arg1).intValue(); return unify(arg0, new Struct("" + c)); } else throw PrologError.type_error(engine.getEngineManager(), 2, "integer", arg1); }
public boolean atom_length_2(Term arg0, Term len) throws PrologError { arg0 = arg0.getTerm(); if (arg0 instanceof Var) throw PrologError.instantiation_error(engine.getEngineManager(), 1); if (!arg0.isAtom()) throw PrologError.type_error(engine.getEngineManager(), 1, "atom", arg0); Struct atom = (Struct) arg0; return unify(len, new Int(atom.getName().length())); }
/** * var unification. * * <p>First, verify the Term eventually already unified with the same Var if the Term exist, unify * var with that term, in order to handle situation as (A = p(X) , A = p(1)) which must produce * X/1. * * <p>If instead the var is not already unified, then: * * <p>if the Term is a var bound to X, then try unification with X so for example if A=1, B=A then * B is unified to 1 and not to A (note that it's coherent with chronological backtracking: the * eventually backtracked A unification is always after backtracking of B unification. * * <p>if are the same Var, unification must succeed, but without any new bindings (to avoid cycles * for extends in A = B, B = A) * * <p>if the term is a number, then it's a success and new link is created (retractable by means * of a code) * * <p>if the term is a compound, then occur check test is executed: the var must not appear in the * compound ( avoid X=p(X), or p(X,X)=p(Y,f(Y)) ); if occur check is ok then it's success and a * new link is created (retractable by a code) */ boolean unify(List vl1, List vl2, Term t) { Term tt = getTerm(); if (tt == this) { t = t.getTerm(); if (t instanceof Var) { if (this == t) { try { vl1.add(this); } catch (NullPointerException e) { /* vl1==null mean nothing intresting for the caller */ } return true; } } else if (t instanceof Struct) { // occur-check if (occurCheck(vl2, (Struct) t)) { return false; } } else if (!(t instanceof Number)) { return false; } link = t; try { vl1.add(this); } catch (NullPointerException e) { /* vl1==null mean nothing intresting for the caller */ } // System.out.println("VAR "+name+" BOUND to "+link+" - time: "+time+" - mark: "+mark); return true; } else { return (tt.unify(vl1, vl2, t)); } }
// Updates indexes, deleting informations about the last removed clause public void unregister(ClauseInfo ci) { Term clause = ci.getHead(); if (clause instanceof Struct) { Struct g = (Struct) clause.getTerm(); if (g.getArity() == 0) { return; } Term t = g.getArg(0).getTerm(); if (t instanceof Var) { numCompClausesIndex.removeShared(ci); constantCompClausesIndex.removeShared(ci); structCompClausesIndex.removeShared(ci); listCompClausesList.remove(ci); } else if (t.isAtomic()) { if (t instanceof Number) { numCompClausesIndex.delete((Number) t, ci); } else if (t instanceof Struct) { constantCompClausesIndex.delete(((Struct) t).getName(), ci); } } else if (t instanceof Struct) { if (t.isList()) { listCompClausesList.remove(ci); } else { structCompClausesIndex.delete(((Struct) t).getPredicateIndicator(), ci); } } } }
public boolean isEqual(Term t) { Term tt = getTerm(); if (tt == this) { t = t.getTerm(); return (t instanceof Var && timestamp == ((Var) t).timestamp); } else { return tt.isEqual(t); } }
public boolean atom_chars_2(Term arg0, Term arg1) throws PrologError { arg0 = arg0.getTerm(); arg1 = arg1.getTerm(); if (arg0 instanceof Var) { if (!arg1.isList()) { throw PrologError.type_error(engine.getEngineManager(), 2, "list", arg1); } Struct list = (Struct) arg1; if (list.isEmptyList()) { return unify(arg0, new Struct("")); } String st = ""; while (!(list.isEmptyList())) { String st1 = list.getTerm(0).toString(); try { if (st1.startsWith("'") && st1.endsWith("'")) { st1 = st1.substring(1, st1.length() - 1); } } catch (Exception ex) { } ; st = st.concat(st1); list = (Struct) list.getTerm(1); } return unify(arg0, new Struct(st)); } else { if (!arg0.isAtom()) { throw PrologError.type_error(engine.getEngineManager(), 1, "atom", arg0); } String st = ((Struct) arg0).getName(); Term[] tlist = new Term[st.length()]; for (int i = 0; i < st.length(); i++) { tlist[i] = new Struct(new String(new char[] {st.charAt(i)})); } Struct list = new Struct(tlist); /* * for (int i=0; i<st.length(); i++){ Struct ch=new Struct(new * String(new char[]{ st.charAt(st.length()-i-1)} )); list=new * Struct( ch, list); } */ return unify(arg1, list); } }
/** * Retrieves a sublist of all the clauses of the same family as the goal and which, in all * probability, could match with the given goal * * @param goal The goal to be resolved * @return The list of goal-compatible predicates */ public List<ClauseInfo> get(Term goal) { // Gets the correct list and encapsulates it in ReadOnlyLinkedList if (goal instanceof Struct) { Struct g = (Struct) goal.getTerm(); /* * If no arguments no optimization can be applied * (and probably no optimization is needed) */ if (g.getArity() == 0) { return new ReadOnlyLinkedList<>(this); } /* Retrieves first argument and checks type */ Term t = g.getArg(0).getTerm(); if (t instanceof Var) { /* * if first argument is an unbounded variable, * no reasoning is possible, all family must be returned */ return new ReadOnlyLinkedList<>(this); } else if (t.isAtomic()) { if (t instanceof Number) { /* retrieves clauses whose first argument is numeric (or Var) * and same as goal's first argument, if no clauses * are retrieved, all clauses with a variable * as first argument */ return new ReadOnlyLinkedList<>(numCompClausesIndex.get((Number) t)); } else if (t instanceof Struct) { /* retrieves clauses whose first argument is a constant (or Var) * and same as goal's first argument, if no clauses * are retrieved, all clauses with a variable * as first argument */ return new ReadOnlyLinkedList<>(constantCompClausesIndex.get(((Struct) t).getName())); } } else if (t instanceof Struct) { if (isAList((Struct) t)) { /* retrieves clauses which has a list (or Var) as first argument */ return new ReadOnlyLinkedList<>(listCompClausesList); } else { /* retrieves clauses whose first argument is a struct (or Var) * and same as goal's first argument, if no clauses * are retrieved, all clauses with a variable * as first argument */ return new ReadOnlyLinkedList<>( structCompClausesIndex.get(((Struct) t).getPredicateIndicator())); } } } /* Default behaviour: no optimization done */ return new ReadOnlyLinkedList<>(this); }
public boolean isGreater(Term t) { Term tt = getTerm(); if (tt == this) { t = t.getTerm(); if (!(t instanceof Var)) return false; return timestamp > ((Var) t).timestamp; } else { return tt.isGreater(t); } }
// Updates indexes, storing informations about the last added clause private void register(ClauseInfo ci, boolean first) { // See FamilyClausesList.get(Term): same concept Term clause = ci.getHead(); if (clause instanceof Struct) { Struct g = (Struct) clause.getTerm(); if (g.getArity() == 0) { return; } Term t = g.getArg(0).getTerm(); if (t instanceof Var) { numCompClausesIndex.insertAsShared(ci, first); constantCompClausesIndex.insertAsShared(ci, first); structCompClausesIndex.insertAsShared(ci, first); if (first) { listCompClausesList.addFirst(ci); } else { listCompClausesList.addLast(ci); } } else if (t.isAtomic()) { if (t instanceof Number) { numCompClausesIndex.insert((Number) t, ci, first); } else if (t instanceof Struct) { constantCompClausesIndex.insert(((Struct) t).getName(), ci, first); } } else if (t instanceof Struct) { if (isAList((Struct) t)) { if (first) { listCompClausesList.addFirst(ci); } else { listCompClausesList.addLast(ci); } } else { structCompClausesIndex.insert(((Struct) t).getPredicateIndicator(), ci, first); } } } }
public boolean sub_atom_guard_5(Term arg0, Term arg1, Term arg2, Term arg3, Term arg4) throws PrologError { arg0 = arg0.getTerm(); if (!arg0.isAtom()) throw PrologError.type_error(engine.getEngineManager(), 1, "atom", arg0); return true; }
private void javaException(Engine e) { Term exceptionTerm = e.currentContext.currentGoal.getArg(0); e.currentContext = e.currentContext.fatherCtx; if (e.currentContext == null) { // passo nello stato HALT se l?errore non pu? essere gestito (sono // arrivato alla radice dell'albero di risoluzione) e.nextState = c.END_HALT; return; } while (true) { // visito all'indietro l'albero di risoluzione alla ricerca di un // subgoal java_catch/3 che abbia un catcher unificabile con // l'argomento dell'eccezione lanciata if (e.currentContext.currentGoal.match(javaCatchTerm) && javaMatch(e.currentContext.currentGoal.getArg(1), exceptionTerm)) { // ho identificato l?ExecutionContext con il corretto subgoal // java_catch/3 // taglio tutti i punti di scelta generati da JavaGoal c.cut(); // unifico l'argomento di java_throw/1 con il catcher // appropriato e recupero l'handler corrispondente List<Var> unifiedVars = e.currentContext.trailingVars.getHead(); Term handlerTerm = javaUnify(e.currentContext.currentGoal.getArg(1), exceptionTerm, unifiedVars); if (handlerTerm == null) { e.nextState = c.END_FALSE; return; } // inserisco il gestore e il finally (se presente) in testa alla // lista dei subgoal da eseguire. I due predicati devono inoltre // essere preparati per l?esecuzione, mantenendo le sostituzioni // effettuate durante il processo di unificazione tra // l'eccezione e il catcher Term curHandlerTerm = handlerTerm.getTerm(); if (!(curHandlerTerm instanceof Struct)) { e.nextState = c.END_FALSE; return; } Term finallyTerm = e.currentContext.currentGoal.getArg(2); Term curFinallyTerm = finallyTerm.getTerm(); // verifico se c'? il blocco finally boolean isFinally = true; if (curFinallyTerm instanceof Int) { Int finallyInt = (Int) curFinallyTerm; if (finallyInt.intValue() == 0) isFinally = false; else { // errore di sintassi, esco e.nextState = c.END_FALSE; return; } } else if (!(curFinallyTerm instanceof Struct)) { e.nextState = c.END_FALSE; return; } // Code inserted to allow evaluation of meta-clause // such as p(X) :- X. When evaluating directly terms, // they are converted to execution of a call/1 predicate. // This enables the dynamic linking of built-ins for // terms coming from outside the demonstration context. if (handlerTerm != curHandlerTerm) handlerTerm = new Struct("call", curHandlerTerm); if (finallyTerm != curFinallyTerm) finallyTerm = new Struct("call", curFinallyTerm); Struct handler = (Struct) handlerTerm; c.identify(handler); SubGoalTree sgt = new SubGoalTree(); sgt.addChild(handler); if (isFinally) { Struct finallyStruct = (Struct) finallyTerm; c.identify(finallyStruct); sgt.addChild(finallyStruct); } c.pushSubGoal(sgt); e.currentContext.currentGoal = handler; // passo allo stato GOAL_SELECTION e.nextState = c.GOAL_SELECTION; return; } else { // passo all'ExecutionContext successivo e.currentContext = e.currentContext.fatherCtx; if (e.currentContext == null) { // passo nello stato HALT se l?errore non pu? essere gestito // (sono arrivato alla radice dell'albero di risoluzione) e.nextState = c.END_HALT; return; } } } }
private void prologError(Engine e) { Term errorTerm = e.currentContext.currentGoal.getArg(0); e.currentContext = e.currentContext.fatherCtx; if (e.currentContext == null) { // passo nello stato HALT se l?errore non pu? essere gestito (sono // arrivato alla radice dell'albero di risoluzione) e.nextState = c.END_HALT; return; } while (true) { // visito all'indietro l'albero di risoluzione alla ricerca di un // subgoal catch/3 il cui secondo argomento unifica con l?argomento // dell?eccezione lanciata if (e.currentContext.currentGoal.match(catchTerm) && e.currentContext.currentGoal.getArg(1).match(errorTerm)) { // ho identificato l?ExecutionContext con il corretto subgoal // catch/3 // taglio tutti i punti di scelta generati da Goal c.cut(); // unifico l'argomento di throw/1 con il secondo argomento di // catch/3 List<Var> unifiedVars = e.currentContext.trailingVars.getHead(); e.currentContext.currentGoal.getArg(1).unify(unifiedVars, unifiedVars, errorTerm); // inserisco il gestore dell?errore in testa alla lista dei // subgoal da eseguire, come definito dal terzo argomento di // catch/3. Il gestore deve inoltre essere preparato per // l?esecuzione, mantenendo le sostituzioni effettuate durante // il processo di unificazione tra l?argomento di throw/1 e il // secondo argomento di catch/3 Term handlerTerm = e.currentContext.currentGoal.getArg(2); Term curHandlerTerm = handlerTerm.getTerm(); if (!(curHandlerTerm instanceof Struct)) { e.nextState = c.END_FALSE; return; } // Code inserted to allow evaluation of meta-clause // such as p(X) :- X. When evaluating directly terms, // they are converted to execution of a call/1 predicate. // This enables the dynamic linking of built-ins for // terms coming from outside the demonstration context. if (handlerTerm != curHandlerTerm) handlerTerm = new Struct("call", curHandlerTerm); Struct handler = (Struct) handlerTerm; c.identify(handler); SubGoalTree sgt = new SubGoalTree(); sgt.addChild(handler); c.pushSubGoal(sgt); e.currentContext.currentGoal = handler; // passo allo stato GOAL_SELECTION e.nextState = c.GOAL_SELECTION; return; } else { // passo all'ExecutionContext successivo e.currentContext = e.currentContext.fatherCtx; if (e.currentContext == null) { // passo nello stato HALT se l?errore non pu? essere gestito // (sono arrivato alla radice dell'albero di risoluzione) e.nextState = c.END_HALT; return; } } } }