public ClauseNode(Term t, TermNode body, double p, long ts) : this(t, body) { timestamp = ts; prob = p; }
public TermNode(Term t, TermNode n) { term = t; nextNode = n; }
public ClauseNode(Term t, TermNode body, double p) : this(t, body) { timestamp = DateTime.Now.Ticks; prob = p; }
bool succeeds; // indicates whether the cached fact results in a failure or in a success #endregion Fields #region Constructors public CachedClauseNode(BaseTerm t, TermNode body, bool succeeds) : base(t, body) { this.succeeds = succeeds; }
private static void DCGGoal(Term t, ref TermNode body, ref Term remainder, ref bool embedded) { Term temp; if (t.IsString || t is Cut) body.Append(t); else if (t.Functor == Parser.CURL) { while (t.Arity == 2) { body.Append(t.Arg(0)); t = t.Arg(1); embedded = true; } } else if (t.IsList) { temp = new Term(); if (t == NULLLIST) t = temp; else t.SetRightmostArg(temp); if (embedded) { body.Append(new Term(Parser.EQ, remainder, t, FType.comp, OType.xfx, 700)); embedded = false; } else remainder.Bind(t); // in this case, nothing is appended to body, which may be left empty (e.g. t-->[x]) remainder = temp; } else if (t.IsAtom || t.IsCompound) { t = new DCGTerm(t, ref remainder); body.Append(t); } else if (t.IsVar) PrologIO.Error("Variable not allowed in DCG-clause: {0}", t.VarName()); else PrologIO.Error("Illegal term in DCG-clause: {0}", t); }
public TermNode(BaseTerm term, TermNode nextNode) { this.term = term; this.nextNode = nextNode; }
public void Clear() { term = null; nextNode = null; nextClause = null; level = 0; }
// returns true if choice point was found public bool CanBacktrack(bool local) { Object o; ChoicePoint cp; findFirstClause = false; // to prevent resetting to the first clause upon re-entering ExecuteGoalList while (varStack.Count != 0) { o = varStack.Pop(); lastCp = o; if (reporting && o is SpyPoint) { if (local && ((SpyPoint)o).Port == SpyPort.fail) Debugger(SpyPort.fail, ((SpyPoint)o).SaveGoal, null, false, 6); // may reset goalNode } else if (o is Term) ((Term)o).Unbind(); else if (o is ChoicePoint && ((ChoicePoint)o).IsActive) { goalNode = (cp = (ChoicePoint)o).Goal; if (cp.currProb < 1 && probDebugLevel >= 2) Console.WriteLine("Returning to choice point prob:" + cp.currProb); resProb = cp.currProb; if (cp.ClauseNode == null) findFirstClause = true; // find predicate belonging to the goal list (-head) else goalNode.NextClause = cp.ClauseNode; // next predicate value to be tried return true; } } return false; }
// findFirstClause: find defining predicate public bool ExecuteGoalList() { ElapsedTime(); ProcessorTime(); //uCount= 0; //CallNo = 0; redo = false; // set by CanBacktrack if a choice point was found // variables declaration used in goal loop to save stack space int stackTop; Term goal; TermNode currClause; Term cleanClauseHead; BI builtinId; int level; Term t; TermNode spyGoal; TermNode p; TermNode pHead; TermNode pTail; TermNode tn0; TermNode tn1; bool pFirst; while (goalNode != null) { if (goalNode is SpyPoint) { TermNode sp = ((SpyPoint)goalNode).SaveGoal; if (!Debugger(SpyPort.exit, sp, null, false, 1)) goalNode = sp.NextNode; // debugger resets goalNode and returns true if user enters r(etry) or f(ail) continue; } stackTop = varStack.Count; // varStack reflects the current program state if (findFirstClause && !goalNode.FindPredicateDefinition(ps)) // no defining predicate found { if ( #if persistent !goalNode.IsPersistent && // if persistent, the predicate is defined but no matching database fact was found #endif PrologIO.Verbose) { goal = goalNode.Term; switch (ps.ActionWhenUndefined(goal.Functor, goal.Arity)) { case PredicateStorage.UndefAction.fail: break; case PredicateStorage.UndefAction.error: return PrologIO.Error("Undefined predicate: {0}/{1}", goal.Functor, goal.Arity); default: PrologIO.Warning("Undefined predicate: {0}/{1}", goal.Functor, goal.Arity); break; } } if (!(redo = CanBacktrack(true))) return false; // redo is set if a choice point was found } findFirstClause = false; // i.e. advance to the next clause upon backtracking currClause = goalNode.NextClause; // definition in program if (reporting) varStack.Push(new SpyPoint(SpyPort.call, goalNode)); // to be able to retry goal etc. if (currClause.NextClause != null) // currClause.NextClause will be tried upon backtracking varStack.Push(currentCp = new ChoicePoint(goalNode, currClause.NextClause, resProb)); else if (reporting) varStack.Push(new SpyPoint(SpyPort.fail, goalNode)); // to be able to detect failure in CanBacktrack cleanClauseHead = currClause.Term.CleanCopy(); // vars must be retained for clause body level = goalNode.Level; spyGoal = goalNode; // remember the original goalNode (which may be NextNode-ed, see below) if (reporting && Debugger(redo ? SpyPort.redo : SpyPort.call, goalNode, cleanClauseHead, currClause.NextNode == null, 2)) continue; // Debugger may return some previous version of goalNode (retry- or fail-command) // UNIFICATION if (cleanClauseHead.Unify(goalNode.Term, varStack)) { currClause = currClause.NextNode; // body - if any - of defining clause (= matching clause of defining predicate) // FACT if (currClause == null) // defining clause body is null, so matching was against a fact { if (reporting && Debugger(SpyPort.exit, goalNode, null, false, 3)) continue; if (probDebugLevel>=2) System.Console.WriteLine("Prob for " + goalNode.Term.Functor + " is " + goalNode.NextClause.Prob); if (goalNode.NextClause.Timestamp > 0) { double decay = decayFunction(DateTime.Now.Ticks - goalNode.NextClause.Timestamp); if (decay < 0.001d) { ps.RetractAll(goalNode.NextClause.Term, varStack); resProb = 0; return true; } else { resProb *= decay * goalNode.NextClause.Prob; } } else resProb *= goalNode.NextClause.Prob; goalNode = goalNode.NextNode; findFirstClause = true; } // BUILTIN else if ((builtinId = currClause.BuiltinId) != BI.none) { if (builtinId == BI.call) { t = goalNode.Term.Arg(0); if (t.IsVar) return PrologIO.Error("Unbound variable '{0}' in goal list", t.VarName()); tn0 = t.ToGoalList(stackTop, goalNode.Level + 1); if (reporting) tn0.Append(new SpyPoint(SpyPort.exit, spyGoal)); goalNode = (goalNode == null) ? tn0 : tn0.Append(goalNode.NextNode); findFirstClause = true; } else if (builtinId == BI.or) { if (reporting) { varStack.Pop(); varStack.Pop(); } tn1 = goalNode.Term.Arg(1).ToGoalList(stackTop, goalNode.Level); varStack.Push(new ChoicePoint((goalNode == null) ? tn1 : tn1.Append(goalNode.NextNode), null, resProb)); tn0 = goalNode.Term.Arg(0).ToGoalList(stackTop, goalNode.Level); goalNode = (goalNode == null) ? tn0 : tn0.Append(goalNode.NextNode); findFirstClause = true; } else if (DoBuiltin(builtinId, out findFirstClause)) { if (reporting && Debugger(SpyPort.exit, spyGoal, null, false, 5)) { findFirstClause = true; continue; } } else if (!(redo = CanBacktrack(true))) return false; } // PREDICATE RULE else // replace goal by body of matching clause of defining predicate { pHead = null; pTail = null; pFirst = true; while (currClause != null) { if (currClause.Term is Cut) p = new TermNode(new Cut(stackTop), goalNode.Level + 1); // save the pre-Unification state else // false: keep the varNo constant over all terms of the predicate head+body p = new TermNode(currClause.Term.CleanCopy(false), goalNode.Level + 1); if (pFirst) { pFirst = false; pHead = p; } else pTail.NextNode = p; pTail = p; currClause = currClause.NextNode; } if (reporting) { pTail.NextNode = new SpyPoint(SpyPort.exit, spyGoal); pTail = pTail.NextNode; } pTail.NextNode = goalNode.NextNode; goalNode = pHead; // zal nooit een spypoint zijn findFirstClause = true; } } else if (!(redo = CanBacktrack(true))) return false; // Unify failed - try backtracking firstGoal = false; } if (resProb < 1.0d) { if (probDebugLevel >= 1) Console.WriteLine("\nProb for this answer:" + resProb); //resProb = 1; } return true; }
private bool DoDebuggingAction(SpyPort port, string lmar, TermNode goalNode) { const string prompt = "| TODO: "; const string filler = "| "; int level; string cmd; int n = INF; int leap = 0; // difference between current level and new level while (true) { level = goalNode.Level; while (true) { PrologIO.Write(lmar + prompt); cmd = Console.ReadLine().Replace(" ", ""); if (cmd.Length > 1) { string cmd0 = cmd.Substring(0, 1); try { n = Int32.Parse(cmd.Substring(1)); } catch { break; } if ("sr".IndexOf(cmd0) != -1 && Math.Abs(n) > level) PrologIO.WriteLine(lmar + filler + "*** Illegal value {0} -- must be in the range -{1}..{1}", n, level); else { if (n != INF && "cloqfgan+-.?h".IndexOf(cmd0) != -1) PrologIO.WriteLine(lmar + filler + "*** Unexpected argument {0}", n); else { if (n < 0) { level += n; leap = -n; } else { leap = level - n; level = n; } cmd = cmd0; break; } } } else { leap = 0; if (cmd != "") cmd = cmd.Substring(0, 1); break; } } switch (cmd) { case "": // creap case "c": // ... return false; case "l": // leap SetSwitch("Tracing", ref trace, false); return false; case "s": // skip if (n == INF) levelMax = level; else levelMax = n + 1; return false; case "o": // out (skip to exit or fail) PrologIO.WriteLine(lmar + filler + "*** NOT YET IMPLEMENTED"); break; case "q": // q-skip (skip subgoals except if a spypoint was set) levelMax = level; qskip = true; return false; case "r": // retry if (port == SpyPort.call && leap == 0) { PrologIO.WriteLine(lmar + filler + "*** retry command has no effect here"); return false; } else { RetryCurrentGoal(level); if (xmlTrace) { XmlTraceWriteElement("RETRY", (n == INF) ? "Retry entered by user" : String.Format("Retry to level {0} entered by user", level)); XmlTraceWriteEnds(leap); } return true; } case "f": // fail if (port == SpyPort.fail) { PrologIO.WriteLine(lmar + filler + "*** fail command has no effect here"); return false; } else { if (!CanBacktrack(true)) throw new AbortQueryException(); if (xmlTrace) { XmlTraceWriteElement("FAILED", (n == INF) ? "Goal failed by user" : String.Format("Retry to level {0} entered by user", level)); XmlTraceWriteEnds(leap); } return true; } case "g": // ancestors ShowAncestorGoals(lmar + filler); break; case "n": // nodebug SetSwitch("Debugging", ref debug, false); return false; case "a": if (xmlTrace) XmlTraceWriteElement("ABORT", "Session aborted by user"); throw new AbortQueryException(); case "+": // spy this goalNode.PredDescr.SetSpy(true, goalNode.Term.Functor, goalNode.Term.Arity, SpyPort.full, false); return false; case "-": // nospy this goalNode.PredDescr.SetSpy(false, goalNode.Term.Functor, goalNode.Term.Arity, SpyPort.full, false); return false; case ".": // run to completion rushToEnd = true; return false; case "?": // help case "h": // ... string[] help = new string[] { "c, CR creep Single-step to the next port", "l leap Resume running, switch tracing off; stop at the next spypoint.", "s [<N>] skip If integer N provided: skip to Exit or Fail port of level N.", "o out NOT YET IMPLEMENTED. Skip to the Exit or Fail port of the ancestor.", "q quasi-skip Same as skip, but will stop if an intermediate spypoint is found.", "r [<N>] retry Transfer control back to the Call port at level N.", "f fail Fail the current goal.", "g ancestors Show ancestor goals.", "n nodebug Switch the debugger off.", "a abort Abort the execution of the current query.", "+ spy this Set a spypoint on the current goal.", "- nospy this Remove the spypoint for the current goal, if it exists.", ". rush Run to completion without furder prompting.", "?, h help Show this text." }; foreach (string line in help) PrologIO.WriteLine(lmar + filler + line); break; default: PrologIO.WriteLine(lmar + filler + "*** Unknown command '{0}' -- enter ? or h for help", cmd); break; } } }
public ClauseChoicePoint(TermNode g, ClauseNode c, ClauseNode nextClause) { goal = g; clause = c; active = true; this.nextClause = nextClause; }
/* public ChoicePoint(TermNode g, ClauseNode c) { goal = g; clause = c; active = true; } */ public ChoicePoint(TermNode g, ClauseNode c, double cp) { goal = g; clause = c; active = true; currProb = cp; }
public Term TermSeq(TermNode list) { if (list.NextNode == null) // last Term of TermNode return list.Term; else return new Term(Parser.COMMA, list.Term, TermSeq(list.NextNode), FType.comp, OType.xfy, 1000); }
public TermNode ToGoalList(int stackTop, int level) // called during execution (when there is a stack) { TermNode result = null; Term t0, t1; FType ft = this.FType; OType ot = this.OType; int pr = this.Precedence; if (this is Cut) { if (stackTop == 0) return new TermNode(this, level); else return new TermNode(new Cut(stackTop), level); } switch (this.Functor) { case Parser.IMPLIES: t0 = Arg(0); if (!t0.IsGoal) PrologIO.Error("Illegal predicate head: {0}", t0); t1 = Arg(1); result = new TermNode(t0, t1.ToGoalList(stackTop, level)); break; case Parser.DCGIMPL: t0 = Arg(0); if (!t0.IsGoal) PrologIO.Error("Illegal DCG head: {0}", t0); t1 = Arg(1); result = new TermNode(t0, t1.ToGoalList(stackTop, level)); break; case Parser.COMMA: t0 = Arg(0); t1 = Arg(1); result = t0.ToGoalList(stackTop, level); result.Append(t1.ToGoalList(stackTop, level)); break; case Parser.DOT: t0 = Arg(0); t1 = Arg(1); if (readingDCGClause) result = (new ListTerm(t0, t1)).ToGoalList(stackTop, level); else result = (new Term("consult", new ListTerm(t0, t1), OType.fy, 0)).ToGoalList(stackTop, level); break; case Parser.CURL: if (readingDCGClause) { t0 = Arg(0); result = t0.ToGoalList(stackTop, level); } else PrologIO.Error("Curly brackets only allowed in a DCG-clause: {0}", this); break; default: if (this.IsVar) result = new TermNode(new Term("'$metacall'", this), level); else if (this.IsGoal) result = new TermNode(this, level); else PrologIO.Error("Illegal term {0} in goal list", this); break; } return result; }
private void PrologCode(TerminalSet _TS) { inQueryMode = false; try { SeeEndOfLine = false; GetSymbol(_TS.Union(LeftParen, Identifier, IntLiteral, RealLiteral, StringLiteral, Operator, Atom, Anonymous, CutSym, LSqBracket, LCuBracket, OpSym, BuiltinSym, ProgramSym, ReadingSym, PrologString, QMark), false, true); if (symbol.IsMemberOf(LeftParen, Identifier, IntLiteral, RealLiteral, StringLiteral, Operator, Atom, Anonymous, CutSym, LSqBracket, LCuBracket, OpSym, BuiltinSym, ProgramSym, ReadingSym, PrologString, QMark)) { GetSymbol(new TerminalSet(LeftParen, Identifier, IntLiteral, RealLiteral, StringLiteral, Operator, Atom, Anonymous, CutSym, LSqBracket, LCuBracket, OpSym, BuiltinSym, ProgramSym, ReadingSym, PrologString, QMark), false, true); if (symbol.Terminal == BuiltinSym) { symbol.SetProcessed(); parseMode = ParseMode.Builtin; Initialize(); Predefineds(_TS); } else if (symbol.Terminal == ProgramSym) { symbol.SetProcessed(); parseMode = ParseMode.Program; Initialize(); Program(_TS); } else if (symbol.Terminal == ReadingSym) { symbol.SetProcessed(); parseMode = ParseMode.Reading; ClauseSequence(_TS); } else { Globals.EraseVariables(); parseMode = ParseMode.Query; inQueryMode = true; GetSymbol(new TerminalSet(LeftParen, Identifier, IntLiteral, RealLiteral, StringLiteral, Operator, Atom, Anonymous, CutSym, LSqBracket, LCuBracket, OpSym, PrologString, QMark), false, true); if (symbol.IsMemberOf(LeftParen, Identifier, IntLiteral, RealLiteral, StringLiteral, Operator, Atom, Anonymous, CutSym, LSqBracket, LCuBracket, PrologString, QMark)) { terminalTable[DOT] = Dot; Set1000Operators(true); Query(new TerminalSet(Dot), out queryNode); } else { OperatorDefinition(new TerminalSet(Dot), true); queryNode = null; } GetSymbol(new TerminalSet(Dot), true, true); } } } finally { terminalTable[COMMA] = Operator; terminalTable[OP] = OpSym; terminalTable[DOT] = Dot; Terminate(); } }
public bool ExecuteQuery(ref string query) { bool result = false; if (!cmdBuf.PreprocessQuery(ref query)) return true; if (query == "/") { halted = true; return true; } // TEMP ElapsedTime(); ProcessorTime(); parser.StreamIn = query; rushToEnd = false; xmlFile = null; xmlMaxEl = INF; xmlTrace = false; levelMin = 0; levelMax = INF; prevLevel = -1; firstGoal = true; lastCp = null; goalNode = parser.QueryNode; if (goalNode == null) return true; varStack.Clear(); try { resProb = 1; findFirstClause = true; result = queryTimeout == 0 ? ExecuteGoalList() : StartExecuteGoalListThread(); } catch (AbortQueryException) { result = false; } //catch //(Exception e) //{ // throw; //} finally { XmlTraceClose(); } return result; }
private void Query(TerminalSet _TS, out TermNode body) { Term t = null; GetSymbol(new TerminalSet(LeftParen, Identifier, IntLiteral, RealLiteral, StringLiteral, Operator, Atom, Anonymous, CutSym, LSqBracket, LCuBracket, PrologString, QMark), false, true); if (symbol.IsMemberOf(LeftParen, Identifier, IntLiteral, RealLiteral, StringLiteral, Operator, Atom, Anonymous, CutSym, LSqBracket, LCuBracket, PrologString)) { PrologTerm(_TS, out t); body = t.ToGoalList(); } else { symbol.SetProcessed(); body = Term.TREEROOT.ToGoalList(); TreeConstruction(_TS); } }
public void RetryCurrentGoal(int level) { Object o; while (varStack.Count != 0) { o = varStack.Pop(); if (o is SpyPoint && ((SpyPoint)o).Port == SpyPort.call) { goalNode = ((SpyPoint)o).SaveGoal; //Console.WriteLine ("RetryCurrentGoal found goalNode {0} at level {1}", goalNode, goalNode.Level); if (goalNode.Level == level) { goalNode.FindPredicateDefinition(ps); // nextClause had been forwarded -- reset it //Console.WriteLine ("Picked this goalNode"); return; } } else if (o is Term) ((Term)o).Unbind(); } }
public TermNode Append(TermNode t) { TermNode tail = this; TermNode next = nextNode; while (next != null) // get the last TermNode { tail = next; next = next.nextNode; } tail.nextNode = t; return this; }
private bool Debugger(SpyPort port, TermNode goalNode, Term currClause, bool isFact, int callNo) { if (!reporting) return false; // only called if reporting = true. This means that at least one of the following conditions hold: // (1) debug is true. This means that trace = true and/or we must check whether this port has a spypoint // (2) xmlTrace = true. // Console-interaction will only occur if debug && (trace || spied) bool spied = false; bool console; string s; int free = 0; string lmar; if (!trace) // determine spied-status { if (goalNode.PredDescr == null) goalNode.FindPredicateDefinition(ps); spied = (goalNode.Spied && (goalNode.SpyPort | port) == goalNode.SpyPort); } console = debug && (trace || spied); // continue only if either trace or spied, or if an XML-trace is to be constructed if (!console && !xmlTrace) return false; lmar = null; Term goal = goalNode.Term; int level = goalNode.Level; if (@"\tdebug\tnodebug\tspy\tnospy\tnospyall\tconsult\ttrace\tnotrace\txmltrace\t".IndexOf(goal.Functor) != -1) return false; if (console) // this part is not required for xmlTrace { if (!qskip && level >= levelMax) return false; levelMax = INF; // recover from (q)s(kip) command qskip = false; // ... const int widthMin = 20; // minimal width of writeable portion of line #if mswindows int width = Utils.NumCols - 10; #else int width = 140; #endif int indent = 3 * (level - levelMin); int condensedLevel = 0; while (indent > width - widthMin) { indent -= width - widthMin; condensedLevel++; } if (condensedLevel == 0) { lmar = Utils.RepeatString("| ", level).Substring(0, indent); free = width - indent; } else { string dots = "| ... "; lmar = dots + Utils.RepeatString("| ", level).Substring(0, indent); free = width - indent - dots.Length; } PrologIO.Write(lmar); } switch (port) { case SpyPort.call: if (console) { s = Utils.WrapWithMargin(goal.ToString(), lmar + "| ", free); PrologIO.Write("{0,2:d2} Goal: {1}", level, s); s = Utils.WrapWithMargin(currClause.ToString(), lmar, free); PrologIO.Write("{0}{1,2:d2} {2}: {3}", lmar, level, "Try ", s); } if (xmlTrace) { if (level > prevLevel) { xtw.WriteStartElement("body"); xtw.WriteAttributeString("goal", goal.ToString()); xtw.WriteAttributeString("level", level.ToString()); } else if (level < prevLevel) xtw.WriteEndElement(); else XmlTraceWriteTerm("goal", "goal", goal); XmlTraceWriteTerm("try", isFact ? "fact" : "pred", currClause); } break; case SpyPort.redo: if (console) { s = Utils.WrapWithMargin(currClause.ToString(), lmar + "| ", free); PrologIO.Write("{0,2:d2} {1}: {2}", level, "Try ", s); // fact or clause } if (xmlTrace) { if (level < prevLevel) xtw.WriteEndElement(); XmlTraceWriteTerm("try", isFact ? "fact" : "clause", currClause); } break; case SpyPort.fail: if (console) { //s = Utils.WrapWithMargin (" ", lmar + " ", free); //IO.Write ("{0,2:d2} Fail {1}", level, s); s = Utils.WrapWithMargin(goal.ToString(), lmar + "| ", free); PrologIO.Write("{0,2:d2} Fail: {1}", level, s); } if (xmlTrace) { if (level < prevLevel) xtw.WriteEndElement(); XmlTraceWriteTerm("fail", "goal", goal); } break; case SpyPort.exit: if (console) { s = Utils.WrapWithMargin(goal.ToString(), lmar + " ", free); PrologIO.Write("{0,2:d2} Exit: {1}", level, s); } if (xmlTrace) { if (level < prevLevel) xtw.WriteEndElement(); XmlTraceWriteTerm("exit", "match", goal); } break; } prevLevel = level; redo = false; if (rushToEnd || !console) return false; return DoDebuggingAction(port, lmar, goalNode); }
public SpyPoint(SpyPort p, TermNode g) : base() { port = p; saveGoal = g; level = g.Level; }
private bool DoBuiltin(BI biId, out bool findFirstClause) { findFirstClause = false; //Console.WriteLine ("DoBuiltin case {0} current goal \n{1}", biId, goalNode.Term); Term term = goalNode.Term; Term t0, t1, t2, t3; TermSet ts; int n, y, m, d, h, s; int arity; string functor; char ch; bool result; switch (biId) { case BI.cut: // ! varStack.DisableChoices(term.VarNo); break; case BI.fail: return false; case BI.or: PrologIO.Error("Serious error -- or-operator (;) not handled properly"); // should not occur return false; case BI.consult: // individual file or list of files t0 = term.Arg(0); if (t0.IsList) { int lines = 0; int files = 0; while (t0.Arity == 2) { string fName = Utils.FileNameFromTerm(t0.Arg(0), ".pl"); if (fName == null) return false; lines += ps.Consult(fName); files++; t0 = t0.Arg(1); } if (files > 1) PrologIO.Message("Grand total is {0} lines", lines); ps.ResolveIndices(); break; } if (t0.IsAtom || t0.IsString) { string fName = Utils.FileNameFromTerm(t0, ".pl"); if (fName == null) return false; PrologIO.Write("--- Consulting {0} ... ", fName); ps.Consult(fName); PrologIO.WriteLine("{0} lines read", parser.LineCount); ps.ResolveIndices(); break; } return PrologIO.Error("Not a valid file name: '{0}'", t0); case BI.asserta: ps.Assert(term.Arg(0), true); // true: at beginning break; case BI.assert: case BI.assertz: ps.Assert(term.Arg(0), false); break; case BI.retract: if (ps.Retract(term.Arg(0), varStack, null)) currentCp.ClauseNode = retractClause; else { CanBacktrack(true); return false; } break; case BI.retractall: // retractall if (!ps.RetractAll(term.Arg(0), varStack)) return false; break; case BI.spy: // leash modes [call, exit, redo, fail] case BI.nospy: result = true; t0 = term.Arg(0); if (term.Arity == 2) t3 = term.Arg(1); else t3 = null; // leash list if (t0.Functor == "/" && t0.Arity == 2 && (t1 = t0.Arg(0)).IsAtom && (t2 = t0.Arg(1)).IsInteger) result = ps.SetSpy(term.Functor == "spy", t1.Functor, t2.ExprValue.AsInteger, t3); else if (t0.Arity == 0) result = ps.SetSpy(term.Functor == "spy", t0.Functor, -1, t3); if (!result) return false; if (!debug) { debug = true; PrologIO.Message("Debugging switched on"); } break; case BI.nospyall: ps.SetNoSpyAll(); break; case BI.verbose: PrologIO.Verbose = true; break; case BI.noverbose: case BI.silent: PrologIO.Verbose = false; break; case BI.trace: case BI.notrace: SetSwitch("Tracing", ref trace, term.Functor == "trace"); if (trace) debug = true; reporting = debug || xmlTrace; break; case BI.debug: case BI.nodebug: SetSwitch("Debugging", ref debug, term.Functor == "debug"); reporting = debug || xmlTrace; break; case BI.setof_init: term.Arg(0).Unify(new ObjectTerm(new TermSet(DupMode.dupIgnore)), varStack); break; case BI.setof_add: ts = (TermSet)((ObjectTerm)term.Arg(0).Value).Value; t1 = term.Arg(1); if (t1.IsVar) return false; t2 = t1.CleanUp(); ts.Insert(t2); break; case BI.setof_exit: ts = (TermSet)((ObjectTerm)term.Arg(0).Value).Value; if (ts.Count == 0) return false; // setof must fail if the Generator yields no matches term.Arg(1).Unify(ts.ToList(), varStack); break; case BI.current_op_init: int pr = -1; string op = null; OType ot = OType.noop; OType ot1; t0 = term.Arg(0); if (t0.IsInteger) pr = Convert.ToInt16(t0.ExprValue.AsInteger); else if (!t0.IsVar) return false; t1 = term.Arg(1); if (t1.IsAtom) try { ot = (OType)Enum.Parse(typeof(OType), t1.Functor); } catch { return false; } else if (!t1.IsVar) return false; t2 = term.Arg(2); if (t2.IsAtom) op = t2.Functor; else if (!t2.IsVar) return false; ArrayList ta = parser.TerminalList; ArrayList oa = new ArrayList(); int pr1; string op1; for (int i = 0; i < ta.Count; i++) // expand all operator descriptors into array oa { if (ta[i] is OperatorDescr) { OperatorDescr od = (OperatorDescr)ta[i]; if (od.IsDefinedAsPrefix(out op1, out pr1, out ot1) && (pr == -1 || pr == pr1) && (op == null || op == op1) && (ot == OType.noop || ot == ot1)) oa.Add(new OpRec(pr1, ot1, op1)); if (od.IsDefinedAsInfix(out op1, out pr1, out ot1) && (pr == -1 || pr == pr1) && (op == null || op == op1) && (ot == OType.noop || ot == ot1)) oa.Add(new OpRec(pr1, ot1, op1)); if (od.IsDefinedAsPostfix(out op1, out pr1, out ot1) && (pr == -1 || pr == pr1) && (op == null || op == op1) && (ot == OType.noop || ot == ot1)) oa.Add(new OpRec(pr1, ot1, op1)); } } if (oa.Count == 0) return false; term.Arg(3).Bind(new ObjectTerm(oa)); // bind the operator array to the penultimate argument term.Arg(4).Bind(new Term((oa.Count - 1).ToString(), FType.number)); // bind the array count to the last argument break; case BI.next_op: // '$next_op'(S, I, P, F, N) t0 = term.Arg(0); oa = (ArrayList)((ObjectTerm)term.Arg(0).Value).Value; t1 = term.Arg(1); // index of current entry in oa n = t1.ExprValue.AsInteger; OpRec oprec = (OpRec)oa[n]; term.Arg(1).Functor = (--n).ToString(); term.Arg(2).Unify(new Term(oprec.Pr.ToString(), FType.number), varStack); term.Arg(3).Unify(new Term(oprec.Fx, FType.atom), varStack); term.Arg(4).Unify(new Term(oprec.Op, FType.atom), varStack); break; case BI.version: // version(V, R) if (!term.Arg(0).Unify(new Term(Utils.MakeAtom(VERSION), FType.atom), varStack)) return false; if (!term.Arg(1).Unify(new Term(Utils.MakeAtom(RELEASE), FType.atom), varStack)) return false; break; case BI.halt: case BI.quit: case BI.abort: halted = true; break; case BI.length: // length(L, N) t0 = term.Arg(0); if (t0.HasValue) { if (!t0.IsList) return false; n = 0; while (t0.Arity == 2) { n++; t0 = t0.Arg(1); } if (!term.Arg(1).Unify(new Term(n.ToString(), FType.number), varStack)) return false; } else // create a list with N elements { t1 = term.Arg(1); if (!t1.HasValue) return false; arity = Convert.ToInt16(t1.ExprValue.AsInteger); Term[] args = new Term[arity]; t1 = Term.NULLLIST; // [] for (int i = 0; i < arity; i++) t1 = new Term(Parser.DOT, new Term(), t1, FType.comp, OType.xfy, 100); t0.Unify(t1, varStack); } break; case BI.sort: // sort(L, S) t0 = term.Arg(0); t1 = term.Arg(1); if (t0.IsList) { if (!(t1.IsList || t1.IsVar)) return false; TermSet tlist = new TermSet(t0); tlist.Sort(); if (!t1.Unify(tlist.ToList(), varStack)) return false; } else return false; break; case BI.functor: // functor(T, F, N) t0 = term.Arg(0); if (t0.HasValue) { if (!term.Arg(1).Unify(new Term(t0.Functor, 0), varStack)) return false; if (!term.Arg(2).Unify(new Term(t0.Arity.ToString(), FType.number), varStack)) return false; break; } else // Term (t0) is unbound { t1 = term.Arg(1); if (t1.HasValue) functor = t1.Functor; else return false; t2 = term.Arg(2); if (t2.HasValue) arity = Convert.ToInt16(t2.ExprValue.AsInteger); else return false; Term[] args = new Term[arity]; for (int i = 0; i < arity; i++) args[i] = new Term(); if (arity == 0) t2 = (functor == Parser.DOT) ? Term.NULLLIST : new Term(functor); else if (arity > 2) t2 = new Term(functor, args); else { OperatorDescr od = Parser.GetOperatorDescr(functor); if (od == null) t2 = new Term(functor, args); else if (arity == 1 && (od.IsDefinedAsPrefix(out functor, out pr, out ot) || od.IsDefinedAsPostfix(out functor, out pr, out ot))) t2 = new Term(functor, od, args, ot, pr); else if (arity == 2 && od.IsDefinedAsInfix(out functor, out pr, out ot)) t2 = new Term(functor, od, args, ot, pr); else t2 = new Term(functor, args); } if (!t0.Unify(t2, varStack)) return false; break; } case BI.arg: // arg( N, Term, A) t1 = term.Arg(1); n = term.Arg(1).NArgs; if (n <= 0) return false; n = Convert.ToInt32(term.Arg(0).ExprValue.AsInteger); Term arg = t1.Arg(n - 1); // N is 1-based if (arg == null || !arg.Unify(term.Arg(2), varStack)) return false; break; case BI.abolish: // abolish( X/N) t0 = term.Arg(0); result = true; if (t0.Functor == "/" && t0.Arity == 2 && t0.Arg(0).IsAtom && t0.Arg(1).IsInteger) result = ps.Abolish(t0.Arg(0).Functor, t0.Arg(1).Functor); else result = false; if (!result) return false; break; case BI.gensym: // gensym( X) t0 = new Term("v" + gensymInt++, 0); if (t0.Unify(term.Arg(0), varStack)) break; else return false; case BI.var: if (term.Arg(0).IsVar) break; return false; case BI.nonvar: if (term.Arg(0).IsNonVar) break; return false; case BI.atom_: if (term.Arg(0).IsAtom) break; return false; case BI.atomic: if (term.Arg(0).IsAtomic) break; return false; case BI.integer: if (term.Arg(0).IsInteger) break; return false; case BI.float_: if (term.Arg(0).IsFloat) break; return false; case BI.number: if (term.Arg(0).IsNumber) break; return false; case BI.compound: if (term.Arg(0).IsCompound) break; return false; case BI.list: if (term.Arg(0).IsList) break; return false; case BI.string_: if (term.Arg(0).IsString) break; return false; case BI.isdatetime: if (term.Arg(0).IsDateTime) break; return false; case BI.istimespan: if (term.Arg(0).IsTimeSpan) break; return false; case BI.is_: // X is Y t0 = new Term(term.Arg(1).ExprValue); if (term.Arg(0).Unify(t0, varStack)) break; return false; case BI.ne_uni: // X \= Y if (term.Arg(0).Unify(term.Arg(1), varStack)) return false; break; case BI.eq_num: // X =:= if (term.Arg(0).ExprValue.AsNumber == term.Arg(1).ExprValue.AsNumber) break; return false; case BI.ne_num: // X =\= Y if (term.Arg(0).ExprValue.AsNumber != term.Arg(1).ExprValue.AsNumber) break; return false; case BI.lt_num: // X < Y if (term.Arg(0).ExprValue.AsNumber < term.Arg(1).ExprValue.AsNumber) break; return false; case BI.le_num: // X =< Y if (term.Arg(0).ExprValue.AsNumber <= term.Arg(1).ExprValue.AsNumber) break; return false; case BI.gt_num: // X > Y if (term.Arg(0).ExprValue.AsNumber > term.Arg(1).ExprValue.AsNumber) break; return false; case BI.ge_num: // X >= Y if (term.Arg(0).ExprValue.AsNumber >= term.Arg(1).ExprValue.AsNumber) break; return false; case BI.eq_str: // X == Y if (term.Arg(0).CompareTo(term.Arg(1)) == 0) break; return false; case BI.ne_str: // X \== Y if (term.Arg(0).CompareTo(term.Arg(1)) != 0) break; return false; case BI.lt_ord: // X @< Y if (term.Arg(0).CompareTo(term.Arg(1)) < 0) break; return false; case BI.le_ord: // X @=< Y if (term.Arg(0).CompareTo(term.Arg(1)) <= 0) break; return false; case BI.gt_ord: // X @> Y if (term.Arg(0).CompareTo(term.Arg(1)) > 0) break; return false; case BI.ge_ord: // X @>= Y if (term.Arg(0).CompareTo(term.Arg(1)) >= 0) break; return false; case BI.univ: // X =.. Y t0 = term.Arg(0); if (t0.HasValue) // create a list representation of the lhs and unify that with the rhs { functor = t0.Functor; arity = t0.Arity; Term[] args = new Term[arity]; t1 = Term.NULLLIST; // [] for (int i = arity; i > 0; i--) t1 = new Term(Parser.DOT, t0.Arg(i - 1), t1, FType.comp, OType.xfy, 100); // [arg1, arg2, ...] t1 = new Term(Parser.DOT, new Term(functor), t1, FType.comp, OType.yfx, 0); // [functor, arg1, arg2, ...] if (!t1.Unify(term.Arg(1), varStack)) return false; break; } else // Term is unbound. Create a function representation of the list rhs, and bind that to the lhs { t1 = term.Arg(1); if (!t1.HasValue || !t1.IsList) return false; if (t1.Arg(0) == null) return false; // empty list functor = t1.Arg(0).Functor; // convert rest of list to arguments: calculate arity first t1 = t1.Arg(1); arity = 0; t2 = t1; while (t2.Arity == 2) { arity++; t2 = t2.Arg(1); } // create arguments Term[] args = new Term[arity]; for (int i = 0; i < arity; i++) { args[i] = t1.Arg(0); t1 = t1.Arg(1); } t1 = new Term(functor, args); t0.Unify(t1, varStack); break; } case BI.unifiable: // X can be unified with Y, but without variable bindings if (!term.Arg(0).Unifiable(term.Arg(1), varStack)) return false; break; case BI.see: // see(X) currentInputName = Utils.FileNameFromTerm(term.Arg(0), ".pl"); if (currentInputName == null) return false; currentInputReader = new StreamReader(currentInputName); Console.SetIn(currentInputReader); break; /* case BI.see: // see(X) // ORIGINAL VERSION, INTENDED FOR USE WITH read/1 try { currentInputName = null; while (seeParserThread.IsAlive) { Utils.WriteLine ("Waiting to abort"); seeParserThread.Interrupt (); seeParserThread.Abort (); } } catch {} currentInputName = Utils.FileNameFromTerm (term.Arg (0), ".pl"); if (currentInputName == null) return false; Utils.WriteLine ("File {0}", currentInputName); Monitor.Enter (TermMonitor); Utils.WriteLine ("see: Monitor entered"); seeParserRun = new ThreadStart (RunSeeParser); seeParserThread = new Thread (seeParserRun); seeParserThread.IsBackground = true; // nodig? seeParserThread.Start (); Utils.WriteLine ("see: Thread started"); break; */ case BI.read: // read(X) try { if (currentInputName == null) return false; // Monitor.Enter () was issued in see (F) Monitor.Pulse(TermMonitor); if (Monitor.Wait(TermMonitor, 2000)) { t0 = term.Arg(0); if (!t0.Unify(parser/*seeParser*/.ReadTerm, varStack)) return false; } else // time-out { Utils.WriteLine("read: Monitor.Wait () timed out"); return false; } } finally { if (parser/*seeParser*/.AtEndOfInput) { currentInputName = null; try { Monitor.Exit(TermMonitor); } catch { } } } break; case BI.get0: // get0(C): any character n = (char)Console.ReadKey().KeyChar; if (!term.Arg(0).Unify(new Term(n.ToString(), FType.number), varStack)) return false; break; case BI.get: // get( C): skip non-printables do { n = Console.ReadKey().KeyChar; if (!Char.IsControl((char)n)) break; // break if printable } while (true); if (!term.Arg(0).Unify(new Term(n.ToString(), FType.number), varStack)) return false; break; case BI.seek: // seek( N, C) n = Convert.ToInt32(term.Arg(0).ExprValue.AsInteger); if (!parser/*seeParser*/.StreamInChar(n, out ch)) return false; if (!term.Arg(0).Unify(new Term(ch.ToString()), varStack)) return false; break; case BI.seen: // seen currentInputName = null; if (seeParserThread != null) seeParserThread.Abort(); seeParserThread = null; // implicitly set by Abort? break; case BI.tell: // tell( F) if (!Globals.SetCurrentOutput(Utils.FileNameFromTerm(term.Arg(0), ".pl"))) return false; break; case BI.write: // write( X) PrologIO.PrologPrint(term.Arg(0)); break; case BI.writeq: // writeq( X) PrologIO.PrologPrint(term.Arg(0).ToStringQ()); break; case BI.writeln: // writeln( X) PrologIO.PrologPrint(term.Arg(0)); PrologIO.PrologPrint(Environment.NewLine); break; case BI.put: // put( C) n = Convert.ToInt32(term.Arg(0).ExprValue.AsInteger); PrologIO.PrologPrint(((char)n).ToString()); break; case BI.nl: PrologIO.PrologPrint(Environment.NewLine); break; case BI.tab: // tab( +N) ////////////////////////// testen op Int n = Convert.ToInt32(term.Arg(0).ExprValue.AsInteger); PrologIO.PrologPrint(new String(' ', n)); break; case BI.display: // like writeln ( X), but always to standard ouput Globals.SetStandardOutput(); PrologIO.PrologPrint(term.Arg(0)); PrologIO.PrologPrint(Environment.NewLine); Globals.RevertToCurrentOutput(); break; case BI.told: Globals.TryCloseCurrentOutput(); break; case BI.atom_chars: // name( ?A, ?L) case BI.name: // name( ?A, ?L) t1 = term.Arg(1); if (t1.HasValue) { FType fType; string a; if (t1.IsList) { StringBuilder sb = new StringBuilder(); while (t1.Arity == 2) { t2 = t1.Arg(0); if (!t2.IsInteger) return false; sb.Append((char)t2.ExprValue.AsInteger); t1 = t1.Arg(1); } a = Utils.MakeAtom_ic(sb.ToString(), true, out fType); if (!term.Arg(0).Unify(new Term(a, fType), varStack)) return false; } else if (t1.IsString) { a = Utils.MakeAtom_ic(t1.Functor, true, out fType); if (!term.Arg(0).Unify(new Term(a, fType), varStack)) return false; } else return false; } else // create a list containing A's character codes { t0 = term.Arg(0); if (!t0.IsAtomic) return false; char[] chars = t0.Functor.ToCharArray(); t0 = Term.NULLLIST; // [] for (int i = chars.Length - 1; i >= 0; i--) { t2 = new Term(((int)chars[i]).ToString(), FType.number); t0 = new Term(Parser.DOT, t2, t0, FType.comp, OType.xfy, 100); } t1.Unify(t0, varStack); } break; case BI.expand_term: // expand_term( +(P-->Q), -R) t0 = term.Arg(0); // P-->Q t1 = term.Arg(1); // R Term head = t0.Arg(0); TermNode body = t0.Arg(1).ToDCG(ref head); t2 = new Term(new ClauseNode(head, body)).CleanUp(); if (!t1.Unify(t2, varStack)) return false; break; case BI.numbervars: // numbervars(+X, +B, -E) t0 = term.Arg(0); t1 = term.Arg(1); t2 = term.Arg(2); if (!t1.IsInteger || t2.HasValue) return false; int k = (int)t1.ExprValue.AsInteger; t0.NumberVars(ref k, varStack); t2.Unify(new Term(k.ToString(), FType.number), varStack); break; case BI.writef0: // writef( S, L) t0 = term.Arg(0); t1 = term.Arg(1); if (!t0.IsString) return false; ArrayList al = new ArrayList(); while (t1.Arity == 2) { t2 = t1.Arg(0); string a = null; if (t2.Functor == "tree" && t2.Arity == 1) a = t2.Arg(0).ToTree(); else if (t2.Functor == "raw" && t2.Arity == 1) a = t2.Arg(0).ToRaw(); al.Add((a == null) ? t2.ToString() : a); t1 = t1.Arg(1); } PrologIO.WriteLine(t0.Functor, al.ToArray()); break; case BI.writef: // writef( S) t0 = term.Arg(0); if (!t0.IsString) return false; PrologIO.WriteLine(t0.Functor); break; case BI.username: // username( X) if (!term.Arg(0).Unify(new Term(Environment.UserName), varStack)) return false; break; case BI.shell: // shell( X [,Args]) t0 = term.Arg(0); if (!(t0.IsString || t0.IsAtom)) return false; else if (term.Arity == 1) Process.Start(t0.Functor); else if (!((t1 = term.Arg(1)).IsString || t1.IsAtom)) return false; else Process.Start(t0.Functor, Utils.Dequoted(t1.Functor)); break; /* namespace MyProcessSample { /// <summary> /// Shell for the sample. /// </summary> class MyProcess { // These are the Win32 error code for file not found or access denied. const int ERROR_FILE_NOT_FOUND =2; const int ERROR_ACCESS_DENIED = 5; /// <summary> /// Prints a file with a .doc extension. /// </summary> void PrintDoc() { Process myProcess = new Process(); try { // Get the path that stores user documents. string myDocumentsPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal); myProcess.StartInfo.FileName = myDocumentsPath + "\\MyFile.doc"; myProcess.StartInfo.Verb = "Print"; myProcess.StartInfo.CreateNoWindow = true; myProcess.Start(); } catch (Win32Exception e) { if(e.NativeErrorCode == ERROR_FILE_NOT_FOUND) { Console.WriteLine(e.Message + ". Check the path."); } else if (e.NativeErrorCode == ERROR_ACCESS_DENIED) { // Note that if your word processor might generate exceptions // such as this, which are handled first. Console.WriteLine(e.Message + ". You do not have permission to print this file."); } } } */ case BI.predicatePN: // predicate( +P/N) t0 = term.Arg(0); result = true; if (t0.Functor == "/" && t0.Arity == 2 && t0.Arg(0).IsAtom && t0.Arg(1).IsInteger) result = ps.IsPredicate(t0.Arg(0).Functor, (int)t0.Arg(1).ExprValue.AsInteger); else result = false; if (!result) return false; break; case BI.predicateX: // predicate( +T) t0 = term.Arg(0); if (t0.IsVar || !ps.IsPredicate(t0.Functor, t0.NArgs)) return false; break; #if persistent case BI.retract_where: // retract(X) where Y -- for persistent predicates only. No backtracking, delete the whole shebang in one go t0 = term.Arg (0).Arg (0); // X if (!ps.IsPersistent (t0)) IO.Error ("retract/1: 'where' not allowed on non-persistent predicate {0}", t0.KbKey); t1 = term.Arg (1); // Y if (!ps.Retract (t0, varStack, t1)) return false; break; case BI.persistent: // persistent( +P/N) t0 = term.Arg (0); result = true; if (t0.Functor == "/" && t0.Arity == 2 && t0.Arg (0).IsAtom && t0.Arg (1).IsInteger) result = ps.IsPersistent (t0.Arg (0).Functor, (int)t0.Arg (1).ExprValue.AsInteger); else result = false; if (!result) return false; break; case BI.whereXY: // X where Y t0 = term.Arg (0); // X if (!ps.IsPersistent (t0)) IO.Error ("'where' not allowed on non-persistent predicate {0}", t0.KbKey); t1 = term.Arg (1); // Y // insert the goal in the argument into the current goalNode goalNode = t0.ToGoalList ().Append (goalNode.NextNode); goalNode.FindPredicateDefinition (ps, t1); return true; case BI.persistent_info: // persistent_info( X/N, L) -- give a list with a description of each column t0 = term.Arg (0); t1 = term.Arg (1); t2 = null; if (t0.Functor == "/" && t0.Arity == 2 && t0.Arg (0).IsAtom && t0.Arg (1).IsInteger) t2 = ps.PersistentInfo (t0.Arg (0).Functor, t0.Arg (1).Functor); else return false; if (!t1.Unify (t2, varStack)) return false; // t1 is output-arg break; case BI.persistent_uncache: // persistent_uncache( X/N) -- empty persistent predicate X/N's cache t0 = term.Arg (0); t1 = term.Arg (1); PredicateDescr pd; if (t0.Functor == "/" && t0.Arity == 2 && t0.Arg (0).IsAtom && t0.Arg (1).IsInteger) pd = ps [Term.Key (t0.Arg (0).Functor, t0.Arg (1).Functor)]; else return false; if (pd == null || !(pd is PersistentPredDescr)) { IO.Warning ("Predicate '{0}/{1}' was not declared as persistent", t0.Arg (0).Functor, t0.Arg (1).Functor); return false; } ((PersistentPredDescr)pd).InvalidateCache (); break; #endif case BI.ground: // ground( +T) if (!term.Arg(0).IsGround()) return false; break; case BI.today: // date( ?Y, ?M, ?D) y = DateTime.Today.Year; m = DateTime.Today.Month; d = DateTime.Today.Day; if (!term.Arg(0).Unify(new Term(y.ToString(), FType.number), varStack)) return false; if (!term.Arg(1).Unify(new Term(m.ToString(), FType.number), varStack)) return false; if (!term.Arg(2).Unify(new Term(d.ToString(), FType.number), varStack)) return false; break; case BI.now: // time( ?H, ?M, ?S) h = DateTime.Now.Hour; m = DateTime.Now.Minute; s = DateTime.Now.Second; if (!term.Arg(0).Unify(new Term(h.ToString(), FType.number), varStack)) return false; if (!term.Arg(1).Unify(new Term(m.ToString(), FType.number), varStack)) return false; if (!term.Arg(2).Unify(new Term(s.ToString(), FType.number), varStack)) return false; break; case BI.validdate: // validdate( +Y, +M, +D) t0 = term.Arg(0); if (t0.IsInteger) y = (int)t0.ExprValue.AsInteger; else return false; t1 = term.Arg(1); if (t1.IsInteger) m = (int)t1.ExprValue.AsInteger; else return false; t2 = term.Arg(2); if (t2.IsInteger) d = (int)t2.ExprValue.AsInteger; else return false; try { new DateTime(y, m, d); } catch { return false; } break; case BI.validtime: // validtime( +H, +M, +S) t0 = term.Arg(0); if (t0.IsInteger) h = (int)t0.ExprValue.AsInteger; else return false; t1 = term.Arg(1); if (t1.IsInteger) m = (int)t1.ExprValue.AsInteger; else return false; t2 = term.Arg(2); if (t2.IsInteger) s = (int)t2.ExprValue.AsInteger; else return false; try { new DateTime(2000, 1, 1, h, m, s); } catch { return false; } break; case BI.dayname: // dayname( +Y, +M, +D, ?N) DayOfWeek dow; t0 = term.Arg(0); if (t0.IsInteger) y = (int)t0.ExprValue.AsInteger; else return false; t1 = term.Arg(1); if (t1.IsInteger) m = (int)t1.ExprValue.AsInteger; else return false; t2 = term.Arg(2); if (t2.IsInteger) d = (int)t2.ExprValue.AsInteger; else return false; try { dow = new DateTime(y, m, d).DayOfWeek; } catch { return false; } if (!term.Arg(3).Unify(new Term(dow.ToString("G"), FType.text), varStack)) return false; break; case BI.dayofweek: // dayofweek( +Y, +M, +D, ?N) t0 = term.Arg(0); if (t0.IsInteger) y = (int)t0.ExprValue.AsInteger; else return false; t1 = term.Arg(1); if (t1.IsInteger) m = (int)t1.ExprValue.AsInteger; else return false; t2 = term.Arg(2); if (t2.IsInteger) d = (int)t2.ExprValue.AsInteger; else return false; try { n = (int)new DateTime(y, m, d).DayOfWeek; } catch { return false; } if (!term.Arg(3).Unify(new Term(n.ToString(), FType.number), varStack)) return false; break; case BI.dayofyear: // dayofyear( +Y, +M, +D, ?N) t0 = term.Arg(0); if (t0.IsInteger) y = (int)t0.ExprValue.AsInteger; else return false; t1 = term.Arg(1); if (t1.IsInteger) m = (int)t1.ExprValue.AsInteger; else return false; t2 = term.Arg(2); if (t2.IsInteger) d = (int)t2.ExprValue.AsInteger; else return false; try { n = (int)new DateTime(y, m, d).DayOfYear; } catch { return false; } if (!term.Arg(3).Unify(new Term(n.ToString(), FType.number), varStack)) return false; break; case BI.leapyear: // leapyear( +Y) t0 = term.Arg(0); if (t0.IsInteger) y = (int)t0.ExprValue.AsInteger; else return false; if (!DateTime.IsLeapYear(y)) return false; break; case BI.weekno: // weekno(+Y, +M, +D, ?N) // week number of date Y-M-D, or current week number if (term.Arity == 4) { t0 = term.Arg(0); if (t0.IsInteger) y = (int)t0.ExprValue.AsInteger; else return false; t1 = term.Arg(1); if (t1.IsInteger) m = (int)t1.ExprValue.AsInteger; else return false; t2 = term.Arg(2); if (t2.IsInteger) d = (int)t2.ExprValue.AsInteger; else return false; try { n = Utils.WeekNo(new DateTime(y, m, d)); } catch { return false; } // invalid date } else n = Utils.WeekNo(DateTime.Today); if (!term.Arg(term.Arity - 1).Unify(new Term(n.ToString(), FType.number), varStack)) return false; break; case BI.prob: if (!term.Arg(0).Unify(new Term(new Prolog.Term.NumberValue(new decimal(resProb))), varStack)) return false; break; case BI.probdebuglevel: t0 = term.Arg(0); if (t0.IsInteger) probDebugLevel = (int)t0.ExprValue.AsInteger; PrologIO.WriteLine("Probability debug level:" + probDebugLevel); break; case BI.probtimedecay: t0 = term.Arg(0); if (!t0.IsString || t0.Functor == null) return false; timeDecayEnabled = ("yes".Equals(t0.Functor.ToLower()) || "y".Equals(t0.Functor.ToLower())); PrologIO.WriteLine("Probability time decay:" + timeDecayEnabled); break; case BI.xml_term: // xml_term( [C,] ?X, ?P) converts between XML and Prolog representation string x; Term ss = null; bool settings = (term.Arity == 3); if (settings) { ss = term.Arg(0); t0 = term.Arg(1); t1 = term.Arg(2); } else { t0 = term.Arg(0); t1 = term.Arg(1); } if (t0.HasValue) { x = t0.Functor; bool inFile = (t0.Arity == 1 && x == "see"); // is it the name of a source file containing the XML structure? bool outFile = (t0.Arity == 1 && x == "tell"); // ... or the name of a destination file containing the XML structure? if (inFile || outFile) { x = Utils.FileNameFromTerm(t0.Arg(0), ".xml"); if (x == null) return false; } if (outFile) { if (!t1.HasValue) return false; if (!Node.TermToXml(ss, t1, ref x)) return false; } else { t2 = Node.XmlToTerm(x, inFile); //Console.WriteLine (t2.ToTree ()); if (!t1.Unify(t2, varStack)) return false; } break; } else if (t1.HasValue) { x = null; if (!Node.TermToXml(ss, t1, ref x)) return false; t2 = new Term(x, FType.text); if (!t0.Unify(t2, varStack)) return false; break; } else return false; case BI.listing: // listing if (!ps.ListAll(null, -1, false, true)) return false; // i.e. no predefined, all user break; case BI.listingXN: // listing( X/N) t0 = term.Arg(0); result = true; if (t0.Functor == "/" && t0.Arity == 2 && t0.Arg(0).IsAtom && t0.Arg(1).IsInteger) result = ps.ListAll(t0.Arg(0).Functor, t0.Arg(1).ExprValue.AsInteger, false, true); else result = false; if (!result) return false; break; case BI.listingX: // listing( X) -- list all predicates X/N (i.e. for each N) t0 = term.Arg(0); if (!t0.IsAtom) return false; if (!ps.ListAll(t0.Functor, -1, false, true)) return false; break; case BI.listing0: // listing0 if (!ps.ListAll(null, -1, true, false)) return false; // i.e. no user, all predefined break; case BI.listing0XN: // listing0( X/N) t0 = term.Arg(0); result = true; if (t0.Functor == "/" && t0.Arity == 2 && t0.Arg(0).IsAtom && t0.Arg(1).IsInteger) result = ps.ListAll(t0.Arg(0).Functor, t0.Arg(1).ExprValue.AsInteger, true, false); else result = false; if (!result) return false; break; case BI.listing0X: // listing0( X) t0 = term.Arg(0); if (!t0.IsAtom) return false; if (!ps.ListAll(t0.Functor, -1, true, false)) return false; break; case BI.pp_defines: // pp_defines( X) -- preprocessor symbol definitions -- mainly useful for debugging in nested calls t0 = term.Arg(0); if (!t0.IsVar) return false; t1 = Term.NULLLIST; // [] //Console.WriteLine ("Parser.PpSymbols.count = {0}", Parser.PpSymbols.Count); foreach (DictionaryEntry de in Parser.PpSymbols) t1 = new Term(Utils.MakeAtom(de.Key as string), new Term(), t1, FType.comp, OType.xfy, 100); t0.Unify(t1, varStack); break; case BI.undefineds: ps.FindUndefineds(); break; case BI.copy_term: // copy_term( X, Y) if (!term.Arg(1).Unify(term.Arg(0).CleanCopy(), varStack)) return false; break; case BI.undef_pred_action: // undef_pred_action( X/1, A) t0 = term.Arg(0); t1 = term.Arg(1); t2 = new Term(Parser.COMMA, t0, t1, FType.comp, OType.xfy, 1000); if (!ps.SetUndefPredAction(t2, false)) return false; break; case BI.clearall: // clearall ReadBuiltinPredicates(); break; case BI.spypoints: // spypoints ps.ShowSpypoints(); break; case BI.clause: // clause(Head,Body) t0 = term.Arg(0); // head t1 = term.Arg(1); // body if (!t0.HasValue) { // head is not instantiated --> no predicate specified // changed from Console.Writeln to general warning LI 2009/10/07 PrologIO.Warning("ERROR: Arguments are not sufficiently instantiated for clause/2."); return false; } // find predicate PredicateDescr pdsc = ps[t0.KbKey]; if (pdsc == null) return false; // get current clause for it TermNode tn = ((lastCp != null) && (lastCp is ClauseChoicePoint)) ? ((ClauseChoicePoint)lastCp).NextClause : pdsc.GetClauseList(t0, null); if (tn == null) return false; // prepare for redo //maybe only needed if further tn clause existent? varStack.Push(new ClauseChoicePoint(goalNode, goalNode.NextClause, tn.NextClause)); findFirstClause = true; // unify t0 with the head and t1 with the clause if (!tn.Term.Unify(t0, varStack)) return false; TermNode tm = tn.NextNode; if ((tm == null) || (tm.BuiltinId != BI.none)) { // No body for the clause. Either a fact (unify t1 with TRUE) or a buildin predicate. if (!t1.Unify(new Term(Utils.MakeAtom(tm == null ? "true" : "builtin predicate"), FType.atom), varStack)) return false; } else if (tm.NextNode == null) { // body consists of one single goal. if (!tm.Term.Unify(t1, varStack)) return false; } else { t0 = t0.TermSeq(tm); if (!t0.Unify(t1, varStack)) return false; } break; case BI.member: // member( X, L, Rest) if (!(t0 = term.Arg(0)).HasValue || !(t1 = term.Arg(1)).IsList) return false; result = false; while (t1.Arity == 2) { if (result = t0.Unify(t1.Arg(0), varStack)) break; t1 = t1.Arg(1); } currentCp.Kill(); // no backtracking to follow -> remove the choicepoint for the alternative clauses if (!result) return false; break; // BACKTRACKING VERSION // while (t1.Arity == 2) // { // if (result = t0.Unify (t1.Arg (0), varStack)) // { // if ((t0 = t1.Arg (1)).Arity == 0) // empty list // currentCp.Kill (); // no backtracking to follow -> remove the choicepoint for the alternative clauses // else // term.Arg (2).Bind (t0); // set Rest to remainder of list (for backtracking) // // break; // } // t1 = t1.Arg (1); // } case BI.append: // append( [_|_], [_|_], L) if (!(t0 = term.Arg(0)).IsList || !(t1 = term.Arg(1)).IsList) return false; currentCp.Kill(); // no backtracking to follow -> remove the choicepoint for the alternative clauses if (!term.Arg(2).Unify(t0.AppendList(t1), varStack)) return false; break; case BI.match_regex: // regex( +Source, +Pattern, ?Result, ?Options) if (!((t0 = term.Arg(0)).IsString || t0.IsAtom) || !((t1 = term.Arg(1)).IsString || !t1.IsAtom)) return false; Match[] matches = Utils.FindRegexMatches(t0.Functor, t1.Functor, false); if (matches.Length == 0) return false; //foreach (Match mt in matches) Console.WriteLine ("index {0} match {1}", mt.Index, mt.Value); t2 = Term.NULLLIST; // [] bool asAtom = true; for (int i = matches.Length - 1; i >= 0; i--) t2 = new Term(Parser.DOT, Term.MakeMatchTerm(matches[i], asAtom), t2, FType.comp, OType.xfy, 100); if (!term.Arg(2).Unify(t2, varStack)) return false; break; case BI.xmltrace: // xmltrace( X) -- send the execution tree of the next query to file X // Must be the first goal of a query, in order to avoid problems that // arise when it gets involved in backtracking. if (xmlTrace) PrologIO.Error("Execution trace is already being logged in {0}", xmlFile); else if (!(t0 = term.Arg(0)).IsAtom && !t0.IsString) PrologIO.Error("Not a valid file name: '{0}'", t0); else if (!firstGoal) { PrologIO.WriteLine("{0}*** {1}/1/2 must be the first goal of the query -- ignored{0}", Environment.NewLine, term.Functor); break; } else if ((xmlFile = Utils.FileNameFromTerm(t0, ".xml")) == null) return false; n = (term.Arity == 2) ? term.Arg(1).ExprValue.AsInteger : INF; if (n < 1) PrologIO.Error("Maximum number of elements must exceed 0"); XmlTraceOpen(term.Functor, n); break; case BI.numcols: // numcols( N) -- number of columns in the DOS-box #if mswindows if (!term.Arg(0).Unify(new Term(Utils.NumCols.ToString(), FType.number), varStack)) return false; break; #else return false; #endif case BI.userroles: #if mswindows WindowsIdentity ident = WindowsIdentity.GetCurrent(); WindowsPrincipal principal = new WindowsPrincipal(ident); //bool admin = principal.IsInRole (WindowsBuiltInRole.Administrator); PrologIO.Message("{0} belongs to: ", principal.Identity.Name.ToString()); Array wbirFields = Enum.GetValues(typeof(WindowsBuiltInRole)); foreach (object roleName in wbirFields) { try { PrologIO.Message("{0}? {1}.", roleName, principal.IsInRole((WindowsBuiltInRole)roleName)); } catch (Exception) { PrologIO.Message("Could not obtain role for RID {0}", roleName); } } #else PrologIO.Error ("userroles only available if compiler symbol mswindows is defined"); #endif break; case BI.statistics: // statistics( X, [MSec,_]) // this version actually only returns the current time t1 = term.Arg(1).Arg(0); long time = ClockTicksMSecs(); if (!t1.Unify(new Term(time.ToString(), FType.number), varStack)) return false; break; case BI.environment: // environment( X, Y) -- unify Y with atom value of environment variable X t0 = term.Arg(0); if (!t0.IsAtom) return false; string es; switch (t0.Functor.ToLower()) { case "applicationdata": es = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); break; case "localapplicationdata": es = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); break; case "cookies": es = Environment.GetFolderPath(Environment.SpecialFolder.Cookies); break; case "desktopdirectory": es = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory); break; case "internetcache": es = Environment.GetFolderPath(Environment.SpecialFolder.InternetCache); break; case "programfiles": es = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles); break; case "startup": es = Environment.GetFolderPath(Environment.SpecialFolder.Startup); break; case "commandline": es = Environment.CommandLine; break; case "currentdirectory": es = Environment.CurrentDirectory; break; case "machinename": es = Environment.MachineName; break; case "newline": es = Environment.NewLine; break; case "osversion": es = Environment.OSVersion.ToString(); break; case "stacktrace": es = Environment.StackTrace; break; case "systemdirectory": es = Environment.SystemDirectory; break; case "tickcount": es = Environment.TickCount.ToString(); break; case "userdomainname": es = Environment.UserDomainName; break; case "userinteractive": es = Environment.UserInteractive.ToString(); break; case "username": es = Environment.UserName; break; case "version": es = Environment.Version.ToString(); break; case "workingset": es = Environment.WorkingSet.ToString(); break; default: return false; } if (!term.Arg(1).Unify(new Term(es), varStack)) return false; break; case BI.query_timeout: t0 = term.Arg(0); if (t0.IsVar) { t0.Unify(new Term(queryTimeout.ToString(), FType.number), varStack); break; } if (!t0.IsInteger || (queryTimeout = t0.ExprValue.AsInteger) < 0) return false; break; case BI.inc_counter: // inc_counter( N) -- value of N is increased at each redo!! t0 = term.Arg(0); if (!t0.IsInteger) return false; t0.Functor = (t0.ExprValue.AsInteger + 1).ToString(); break; // case BI.vvv: // PredicateDescr p = ps [Term.Key ("value", 2)]; // p.DumpClauseList (); // break; default: return PrologIO.Error("Undefined built-in: {0}", term); } goalNode = goalNode.NextNode; if (reporting) // advance the goalList until a non-spypoint is encountered. Show spy(-exit)-info. { TermNode sp = null; while (goalNode is SpyPoint) { sp = ((SpyPoint)goalNode).SaveGoal; if (Debugger(SpyPort.exit, sp, null, false, 1)) break; goalNode = sp.NextNode; } } findFirstClause = true; return true; }
public ClauseNode(BaseTerm t, TermNode body) : base(t, body) { }
// DCG stuff public TermNode ToDCG(ref Term lhs) // cf. Side Notes SN3 { TermNode body = new TermNode(); Term result = null; Term inVar = new Term(); Term inVarSave = inVar; Term outVar = inVar; lhs = new DCGTerm(lhs, ref outVar); // outVar becomes new term Term remainder; try { readingDCGClause = true; ArrayList alternatives = AlternativesToArrayList(); for (int i = 0; i < alternatives.Count; i++) { Term alt = (Term)alternatives[i]; bool embedded = (alternatives.Count > 1); ArrayList terms = alt.ArgumentsToArrayList(true); // flatten clause such as X --> (A, B), C. body.Clear(); remainder = inVarSave; for (int ii = 0; ii < terms.Count; ii++) DCGGoal((Term)terms[ii], ref body, ref remainder, ref embedded); // create a term-tree from the array if (i == 0) result = TermSeq(body); else result = new Term(Parser.SEMI, result, TermSeq(body), FType.comp, OType.xfy, 1100); remainder.Bind(outVar); } } finally { readingDCGClause = false; } return (result == null) ? null : result.ToGoalList(); // empty body treated similar to null }