├── README.md ├── bin ├── YPShell.exe ├── YPShell.py ├── YieldProlog.js └── queryEditor.html ├── doc ├── YieldProlog.js ├── benchmarks.html ├── index.html ├── queryEditor.html ├── tutorial1.html ├── tutorial2.html ├── tutorial3.html ├── tutorial4.html └── tutorial_toc.html └── source ├── csharp ├── Atom.cs ├── BagofAnswers.cs ├── Compiler.cs ├── FindallAnswers.cs ├── Functor.cs ├── Functor1.cs ├── Functor2.cs ├── Functor3.cs ├── IndexedAnswers.cs ├── ListPair.cs ├── Parser.cs ├── PrologException.cs ├── Variable.cs ├── YP.cs ├── examples │ ├── Benchmarks │ │ ├── IsoTestSuite.cs │ │ ├── NaiveQueens.cs │ │ ├── Queens.cs │ │ ├── YieldPrologBenchmarks.csproj │ │ ├── YieldPrologBenchmarks.csproj.user │ │ ├── YieldPrologBenchmarks.sln │ │ ├── YieldPrologBenchmarks.suo │ │ └── monomake.bat │ ├── YPShell │ │ ├── YPShell.cs │ │ ├── YPShell.csproj │ │ ├── YPShell.csproj.user │ │ ├── YPShell.sln │ │ ├── YPShell.suo │ │ └── monomake.bat │ └── YieldPrologTutorial │ │ ├── Tutorial1.cs │ │ ├── Tutorial2.cs │ │ ├── Tutorial3.cs │ │ ├── Tutorial4.cs │ │ ├── YieldPrologTutorial.csproj │ │ ├── YieldPrologTutorial.csproj.user │ │ ├── YieldPrologTutorial.sln │ │ ├── YieldPrologTutorial.suo │ │ └── monomake.bat └── update.bat ├── javascript ├── Atom.js ├── BagofAnswers.js ├── Compiler.js ├── FindallAnswers.js ├── Functor.js ├── Functor1.js ├── Functor2.js ├── Functor3.js ├── IndexedAnswers.js ├── ListPair.js ├── Parser.js ├── PrologException.js ├── Variable.js ├── YP.js ├── YieldProlog.js ├── endComment.js ├── examples │ ├── Benchmarks │ │ ├── isoTestSuite.html │ │ ├── isoTestSuite.js │ │ ├── naiveQueens.html │ │ ├── naiveQueens.js │ │ ├── queens.html │ │ └── queens.js │ └── YieldPrologTutorial │ │ ├── tutorial1.html │ │ ├── tutorial1.js │ │ ├── tutorial2.html │ │ ├── tutorial2.js │ │ ├── tutorial3.html │ │ ├── tutorial3.js │ │ ├── tutorial4.html │ │ └── tutorial4.js ├── makeYieldProlog.bat └── readme.js ├── prolog ├── compiler.P ├── isoTestSuite.P └── parser.P └── python ├── Atom.py ├── BagofAnswers.py ├── Compiler.py ├── FindallAnswers.py ├── Functor.py ├── Functor1.py ├── Functor2.py ├── Functor3.py ├── IndexedAnswers.py ├── ListPair.py ├── Parser.py ├── PrologException.py ├── Variable.py ├── YP.py └── examples ├── Benchmarks ├── isoTestSuite.py ├── naiveQueens.py └── queens.py └── YieldPrologTutorial ├── tutorial1.py ├── tutorial2.py ├── tutorial3.py └── tutorial4.py /README.md: -------------------------------------------------------------------------------- 1 | Yield Prolog 2 | ============ 3 | 4 | Welcome to Yield Prolog. This fork is based on the original YieldProlog project available here: 5 | http://yieldprolog.sourceforge.net/ 6 | 7 | Contents 8 | -------- 9 | 10 | - **bin** contains executables, including: 11 | - YPShell.exe - Yield Prolog for C# interactive shell for Windows. 12 | - queryEditor.html - Yield Prolog browser shell for Javascript. 13 | - YPShell.py - Yield Prolog for Python interactive shell. 14 | 15 | - **doc** contains a snapshot of the Yield Prolog web site including the tutorial. 16 | Open index.html in your browser. 17 | 18 | - **source** contains a folder for the source of each supported platform. 19 | The examples subfolder for each platform contains the YPShell, tutorial examples and benchmarks code. 20 | 21 | Make 22 | ---- 23 | 24 | Here are instructions to make and run Tutorial1 on various platforms. 25 | You can do something similar to make the other tutorials, the benchmarks, 26 | or your own Yield Prolog program. 27 | 28 | To make Tutorial1 under Visual C# 2008: 29 | - Open source\csharp\examples\YieldPrologTutorial\YieldPrologTutorial.sln 30 | - Make sure the Startup Object is set correctly, e.g. to Tutorial1 31 | - Press F5 to build and run 32 | 33 | To make Tutorial1 under Mono 1.9.1 in Windows: 34 | - On the Start menu, run Programs/Mono 1.9.1 for Windows/Mono-1.9.1 Command Prompt 35 | - Use cd to change directory to source\csharp\examples\YieldPrologTutorial 36 | - Enter: monomake Tutorial1.cs 37 | - Run Tutorial1.exe 38 | 39 | To make Tutorial1 under Python 2.6 for Windows: 40 | - On the Start menu, run Programs/Python 2.5/IDLE (Python GUI) 41 | - Select the menu File/Open and open source\python\examples\YieldPrologTutorial\tutorial1.py 42 | - Press F5 to run the module 43 | -------------------------------------------------------------------------------- /bin/YPShell.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vslab/YieldProlog/11f68cd05d55a8b56681b1c7572b9067e7816915/bin/YPShell.exe -------------------------------------------------------------------------------- /bin/YPShell.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2007-2008, Jeff Thompson 2 | # 3 | # All rights reserved. 4 | # 5 | # Redistribution and use in source and binary forms, with or without 6 | # modification, are permitted provided that the following conditions are met: 7 | # 8 | # * Redistributions of source code must retain the above copyright 9 | # notice, this list of conditions and the following disclaimer. 10 | # * Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer in the 12 | # documentation and/or other materials provided with the distribution. 13 | # * Neither the name of the copyright holder nor the names of its contributors 14 | # may be used to endorse or promote products derived from this software 15 | # without specific prior written permission. 16 | # 17 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 21 | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 22 | # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 | # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 24 | # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 25 | # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 26 | # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | import sys 30 | # Hack sys.path for imports. 31 | sys.path.append("../source/python") 32 | from YP import * 33 | from Atom import * 34 | from Compiler import * 35 | from ListPair import * 36 | from Variable import * 37 | 38 | def main(): 39 | print "Yield Prolog Shell. Enter ctrl-D to exit." 40 | 41 | while True: 42 | print "?- ", 43 | goalString = sys.stdin.readline() 44 | if goalString == "": 45 | break 46 | if goalString == "\n": 47 | print "Enter ctrl-D to exit." 48 | continue 49 | 50 | Goal = Variable() 51 | VariableList = Variable() 52 | for l1 in parseGoal(goalString, Goal, VariableList): 53 | try: 54 | gotMatch = False 55 | for l2 in YP.getIterator(Goal, None): 56 | gotMatch = True 57 | if YP.getValue(VariableList) != Atom.NIL: 58 | # We are showing values, so allow the user to enter ";" to display the next match. 59 | writeValues(VariableList) 60 | continuePrompt = sys.stdin.readline() 61 | if len(continuePrompt) > 0 and continuePrompt[0] != ';': 62 | break 63 | 64 | if gotMatch: 65 | if YP.getValue(VariableList) == Atom.NIL: 66 | # We didn't show any values. So just write true after matching (one or more times). 67 | print "true" 68 | else: 69 | print 70 | else: 71 | print "fail" 72 | except PrologException as exception: 73 | print str(exception._term) 74 | 75 | # Parse goalString and yield for each Goal, setting VariableList to a list of 76 | # (variableAtom = Var). 77 | def parseGoal(goalString, Goal, VariableList): 78 | # The parser requires a newline at the end. 79 | YP.see(YP.StringReader(goalString + '\n')) 80 | TermList = Variable() 81 | # parseInput sets TermList to a list of f(Goal, VariableList). 82 | for l1 in parseInput(TermList): 83 | # Close the input now before yielding. 84 | YP.seen() 85 | # Iterate through each member of TermList. 86 | TermList = YP.getValue(TermList) 87 | while isinstance(TermList, Functor2) and TermList._name == Atom.DOT: 88 | # Unify the head of the list with f(Goal, VariableList). 89 | for l2 in YP.unify(TermList._arg1, Functor2(Atom.F, Goal, VariableList)): 90 | yield False 91 | TermList = YP.getValue(TermList._arg2) 92 | return 93 | 94 | # Close the input in case parseInput failed. 95 | YP.seen() 96 | 97 | # Write out each entry in VariableList which is a list of (variableAtom = Var) 98 | def writeValues(VariableList): 99 | VariableList = YP.getValue(VariableList) 100 | while isinstance(VariableList, Functor2) and VariableList._name == Atom.DOT: 101 | variableAndValue = YP.getValue(VariableList._arg1) 102 | if isinstance(variableAndValue, Functor2): 103 | print 104 | print YP.getValue(variableAndValue._arg1), "=", YP.getValue(variableAndValue._arg2), 105 | VariableList = YP.getValue(VariableList._arg2) 106 | 107 | main() 108 | 109 | 110 | -------------------------------------------------------------------------------- /bin/queryEditor.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 89 | Yield Prolog Query Editor 90 | 91 | 92 | 94 | 95 | 96 | 99 | 103 | 104 | 105 |
^^Home
98 |
100 |

Yield Prolog Query Editor
101 |

102 |
106 | Congratulations! Your browser 107 | has just loaded the full-featured Prolog environment in YieldProlog.js, complete with a 109 | Prolog parser and compiler.
110 | Click one of the Samples or type some Prolog, then 111 | click Run to see the result. (Requires Firefox 3 or Seamonkey 114 | 2.)
115 |
116 |
Query:
118 |
119 | Samples: Hello 121 | world 2+2 assert 125 | uncle query 127 | uncle all 129 | Uncles 130 | (using setof) abolish 132 | uncle parse 134 | and call
135 |
136 |
137 | Output:
138 |
139 | 140 | 141 | -------------------------------------------------------------------------------- /doc/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | Yield Prolog 7 | 8 | 9 | 11 | 12 | 13 | 36 | 125 | 126 | 127 |
15 |

Yield Prolog

16 | Download
17 |
18 | Documentation
20 |
21 | Query Editor
22 |
23 | Benchmarks
24 |
25 | Report 27 | Bugs
28 |
29 | Sourceforge 30 | Project
31 |
32 | Sourceforge.net
35 |
Yield 37 | Prolog lets you embed 38 | Prolog programs directly in Python, C# [1] 39 | or Javascript [2] 40 | by using the yield 41 | keyword. For example, 42 | here is the classic "uncle" predicate in Prolog:
43 |
44 | 46 | 47 | 48 | 51 | 52 | 53 |
49 |
uncle(Person, Uncle) :-
parent(Person, Parent),
brother(Parent, Uncle).
50 |
54 |
55 | (This says that a person has an uncle if the person has a parent and 56 | that 57 | parent has a brother.) And here it is in Yield Prolog:
58 |
59 | 61 | 62 | 63 | 66 | 69 | 70 | 71 | 74 | 77 | 78 | 79 | 80 | 81 | 82 | 85 | 86 | 87 |
Python
65 |
C#
68 |
72 |
def uncle(Person, Uncle):
Parent = Variable()
for l1 in parent(Person, Parent):
for l2 in brother(Parent, Uncle):
yield False
73 |
75 |
IEnumerable<bool> uncle(object Person, object Uncle) {
Variable Parent = new Variable();
foreach (bool l1 in parent(Person, Parent)) {
foreach (bool l2 in brother(Parent, Uncle))
yield return false;
}
}
76 |
Javascript
83 |
function uncle(Person, Uncle) {
var Parent = new Variable();
for each (var l1 in parent(Person, Parent)) {
for each (var l2 in brother(Parent, Uncle))
yield false;
}
}
84 |
88 |
89 | As you can see, the flow of the code in Yield Prolog is similar to 90 | Prolog. The Tutorial explains how 91 | these 92 | examples work, without expecting you to know Prolog. And the benchmarks show that Yield Prolog in C# can 94 | be faster than efficient Prolog systems like Yap Prolog and XSB.
95 |
96 | Yield Prolog is made possible by the yield keyword, which 98 | automatically creates iterators that you can nest, combined with Yield 99 | Prolog's Variable class 100 | which can unify a variable with other values (just like in 101 | Prolog). There is no "API" standing between your code and Yield Prolog, 102 | because 103 | you just use the yield 104 | keyword to make "iterator functions" wherever you need them. Yield 105 | Prolog is part of your code, which can mix Prolog-style predicates 106 | directly with ordinary arrays, file I/O, GUI calls and all your own 107 | classes. Because it lets you mix these, Yield Prolog unifies the declarative 109 | and procedural 110 | programming models.
111 |
112 |
1. 113 | Tested 114 | with 115 | C# 116 | .NET 2008 and Mono 2.0.
117 | 2. 119 | Yield Prolog for Javascript is supported in Firefox 3 and Seamonkey 2, 122 | which fully supports the yield 123 | keyword in EcmaScript 3.1.
124 |
128 |
129 |
130 | 131 | 132 | -------------------------------------------------------------------------------- /doc/tutorial_toc.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | Yield Prolog Documentation 7 | 8 | 9 | 11 | 12 | 13 | 16 | 20 | 21 | 22 |
^^Home Tutorial 1 15 | >> 17 |

Yield Prolog Documentation
18 |

19 |
23 | For the change log of each release, see the Yield Prolog News.
25 |

Tutorial Table of Contents

26 |
    27 |
  1. Introduction
  2. 28 | 51 |
  3. Variable 52 | and "Cut"
  4. 53 | 61 |
  5. ListPair
  6. 62 | 68 |
  7. Compiler
  8. 69 | 86 |
87 | 88 | 89 | -------------------------------------------------------------------------------- /source/csharp/FindallAnswers.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2007-2008, Jeff Thompson 3 | * 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * * Neither the name of the copyright holder nor the names of its contributors 15 | * may be used to endorse or promote products derived from this software 16 | * without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 22 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | using System; 32 | using System.Collections; 33 | using System.Collections.Generic; 34 | 35 | namespace YieldProlog 36 | { 37 | /// 38 | /// A FindallAnswers holds answers for findall. 39 | /// 40 | public class FindallAnswers 41 | { 42 | private object _template; 43 | private List _bagArray; 44 | 45 | public FindallAnswers(object Template) 46 | { 47 | _template = Template; 48 | _bagArray = new List(); 49 | } 50 | 51 | public void add() 52 | { 53 | _bagArray.Add(YP.makeCopy(_template, new Variable.CopyStore())); 54 | } 55 | 56 | public List resultArray() 57 | { 58 | return _bagArray; 59 | } 60 | 61 | /// 62 | /// Unify Bag with the result. This frees the internal answers, so you can only call this once. 63 | /// 64 | /// 65 | /// 66 | public IEnumerable result(object Bag) 67 | { 68 | object result = ListPair.make(_bagArray); 69 | // Try to free the memory. 70 | _bagArray = null; 71 | return YP.unify(Bag, result); 72 | } 73 | 74 | /// 75 | /// This is a simplified findall when the goal is a single call. 76 | /// 77 | /// 78 | /// 79 | /// 80 | /// 81 | public static IEnumerable findall(object Template, IEnumerable goal, object Bag) 82 | { 83 | FindallAnswers findallAnswers = new FindallAnswers(Template); 84 | foreach (bool l1 in goal) 85 | findallAnswers.add(); 86 | return findallAnswers.result(Bag); 87 | } 88 | 89 | /// 90 | /// Like findall, except return an array of the results. 91 | /// 92 | /// 93 | /// 94 | /// 95 | public static List findallArray(object Template, IEnumerable goal) 96 | { 97 | FindallAnswers findallAnswers = new FindallAnswers(Template); 98 | foreach (bool l1 in goal) 99 | findallAnswers.add(); 100 | return findallAnswers.resultArray(); 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /source/csharp/Functor1.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2007-2008, Jeff Thompson 3 | * 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * * Neither the name of the copyright holder nor the names of its contributors 15 | * may be used to endorse or promote products derived from this software 16 | * without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 22 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | using System; 32 | using System.Collections.Generic; 33 | 34 | namespace YieldProlog 35 | { 36 | public class Functor1 : IUnifiable 37 | { 38 | public readonly Atom _name; 39 | public readonly object _arg1; 40 | 41 | public Functor1(Atom name, object arg1) 42 | { 43 | _name = name; 44 | _arg1 = arg1; 45 | } 46 | 47 | public Functor1(string name, object arg1) 48 | : this(Atom.a(name), arg1) 49 | { 50 | } 51 | 52 | /// 53 | /// If arg is another Functor1, then succeed (yield once) if this and arg have the 54 | /// same name and the functor args unify, otherwise fail (don't yield). 55 | /// If arg is a Variable, then call its unify to unify with this. 56 | /// Otherwise fail (don't yield). 57 | /// 58 | /// 59 | /// 60 | public IEnumerable unify(object arg) 61 | { 62 | arg = YP.getValue(arg); 63 | if (arg is Functor1) 64 | { 65 | Functor1 argFunctor = (Functor1)arg; 66 | if (_name.Equals(argFunctor._name)) 67 | { 68 | foreach (bool l1 in YP.unify(_arg1, argFunctor._arg1)) 69 | yield return false; 70 | } 71 | } 72 | else if (arg is Variable) 73 | { 74 | foreach (bool l1 in ((Variable)arg).unify(this)) 75 | yield return false; 76 | } 77 | } 78 | 79 | public override string ToString() 80 | { 81 | return _name + "(" + YP.getValue(_arg1) + ")"; 82 | } 83 | 84 | public bool termEqual(object term) 85 | { 86 | term = YP.getValue(term); 87 | if (term is Functor1) 88 | { 89 | Functor1 termFunctor = (Functor1)term; 90 | return _name.Equals(termFunctor._name) && YP.termEqual(_arg1, termFunctor._arg1); 91 | } 92 | return false; 93 | } 94 | 95 | public override int GetHashCode() 96 | { 97 | return _name.GetHashCode() ^ YP.getValue(_arg1).GetHashCode(); 98 | } 99 | 100 | public bool lessThan(Functor1 functor) 101 | { 102 | // Do the equal check first since it is faster. 103 | if (!_name.Equals(functor._name)) 104 | return _name.lessThan(functor._name); 105 | 106 | return YP.termLessThan(_arg1, functor._arg1); 107 | } 108 | 109 | public bool ground() 110 | { 111 | return YP.ground(_arg1); 112 | } 113 | 114 | public void addUniqueVariables(List variableSet) 115 | { 116 | YP.addUniqueVariables(_arg1, variableSet); 117 | } 118 | 119 | public object makeCopy(Variable.CopyStore copyStore) 120 | { 121 | return new Functor1(_name, YP.makeCopy(_arg1, copyStore)); 122 | } 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /source/csharp/Functor3.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2007-2008, Jeff Thompson 3 | * 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * * Neither the name of the copyright holder nor the names of its contributors 15 | * may be used to endorse or promote products derived from this software 16 | * without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 22 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | using System; 32 | using System.Collections.Generic; 33 | 34 | namespace YieldProlog 35 | { 36 | public class Functor3 : IUnifiable 37 | { 38 | public readonly Atom _name; 39 | public readonly object _arg1; 40 | public readonly object _arg2; 41 | public readonly object _arg3; 42 | 43 | public Functor3(Atom name, object arg1, object arg2, object arg3) 44 | { 45 | _name = name; 46 | _arg1 = arg1; 47 | _arg2 = arg2; 48 | _arg3 = arg3; 49 | } 50 | 51 | public Functor3(string name, object arg1, object arg2, object arg3) 52 | : this(Atom.a(name), arg1, arg2, arg3) 53 | { 54 | } 55 | 56 | /// If arg is another Functor3, then succeed (yield once) if this and arg have the 57 | /// same name and all functor args unify, otherwise fail (don't yield). 58 | /// If arg is a Variable, then call its unify to unify with this. 59 | /// Otherwise fail (don't yield). 60 | public IEnumerable unify(object arg) 61 | { 62 | arg = YP.getValue(arg); 63 | if (arg is Functor3) 64 | { 65 | Functor3 argFunctor = (Functor3)arg; 66 | if (_name.Equals(argFunctor._name)) 67 | { 68 | foreach (bool l1 in YP.unify(_arg1, argFunctor._arg1)) 69 | { 70 | foreach (bool l2 in YP.unify(_arg2, argFunctor._arg2)) 71 | { 72 | foreach (bool l3 in YP.unify(_arg3, argFunctor._arg3)) 73 | yield return false; 74 | } 75 | } 76 | } 77 | } 78 | else if (arg is Variable) 79 | { 80 | foreach (bool l1 in ((Variable)arg).unify(this)) 81 | yield return false; 82 | } 83 | } 84 | 85 | public override string ToString() 86 | { 87 | return _name + "(" + YP.getValue(_arg1) + ", " + YP.getValue(_arg2) + ", " + 88 | YP.getValue(_arg3) + ")"; 89 | } 90 | 91 | public bool termEqual(object term) 92 | { 93 | term = YP.getValue(term); 94 | if (term is Functor3) 95 | { 96 | Functor3 termFunctor = (Functor3)term; 97 | return _name.Equals(termFunctor._name) && YP.termEqual(_arg1, termFunctor._arg1) 98 | && YP.termEqual(_arg2, termFunctor._arg2) 99 | && YP.termEqual(_arg3, termFunctor._arg3); 100 | } 101 | return false; 102 | } 103 | 104 | public override int GetHashCode() 105 | { 106 | // Note: The infrequent collision where changing the order of args gives the same hash value is OK. 107 | return _name.GetHashCode() ^ YP.getValue(_arg1).GetHashCode() 108 | ^ YP.getValue(_arg2).GetHashCode() ^ YP.getValue(_arg3).GetHashCode(); 109 | } 110 | 111 | public bool lessThan(Functor3 functor) 112 | { 113 | // Do the equal check first since it is faster. 114 | if (!_name.Equals(functor._name)) 115 | return _name.lessThan(functor._name); 116 | 117 | if (!YP.termEqual(_arg1, functor._arg1)) 118 | return YP.termLessThan(_arg1, functor._arg1); 119 | 120 | if (!YP.termEqual(_arg2, functor._arg2)) 121 | return YP.termLessThan(_arg2, functor._arg2); 122 | 123 | return YP.termLessThan(_arg3, functor._arg3); 124 | } 125 | 126 | public bool ground() 127 | { 128 | return YP.ground(_arg1) && YP.ground(_arg2) && YP.ground(_arg3); 129 | } 130 | 131 | public void addUniqueVariables(List variableSet) 132 | { 133 | YP.addUniqueVariables(_arg1, variableSet); 134 | YP.addUniqueVariables(_arg2, variableSet); 135 | YP.addUniqueVariables(_arg3, variableSet); 136 | } 137 | 138 | public object makeCopy(Variable.CopyStore copyStore) 139 | { 140 | return new Functor3(_name, YP.makeCopy(_arg1, copyStore), 141 | YP.makeCopy(_arg2, copyStore), YP.makeCopy(_arg3, copyStore)); 142 | } 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /source/csharp/examples/Benchmarks/NaiveQueens.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using YieldProlog; 4 | 5 | namespace YieldPrologBenchmarks 6 | { 7 | class NaiveQueens 8 | { 9 | static void Main(string[] args) 10 | { 11 | long startTicks = DateTime.Now.Ticks; 12 | int nAnswers = 0; 13 | Variable Qs = new Variable(); 14 | foreach (bool l1 in queens(11, Qs)) 15 | { 16 | ++nAnswers; 17 | } 18 | long finishTicks = DateTime.Now.Ticks; 19 | Console.WriteLine("Naive queens: " + 20 | (finishTicks - startTicks) / 10000000.0 + " seconds, " + nAnswers + " answers"); 21 | 22 | Console.WriteLine("\nPress Enter to finish."); 23 | Console.ReadLine(); 24 | } 25 | 26 | static IEnumerable queens(object N, object Qs) 27 | { 28 | Variable Ns = new Variable(); 29 | foreach (bool l1 in rangeList(1, N, Ns)) 30 | { 31 | foreach (bool l2 in queens3(Ns, Atom.NIL, Qs)) 32 | yield return false; 33 | } 34 | } 35 | 36 | static IEnumerable queens3(object UnplacedQs, object SafeQs, object Qs) 37 | { 38 | Variable UnplacedQs1 = new Variable(); 39 | Variable Q = new Variable(); 40 | foreach (bool l1 in selectq(Q, UnplacedQs, UnplacedQs1)) 41 | { 42 | foreach (bool l2 in notHasAttack(Q, SafeQs)) 43 | { 44 | foreach (bool l3 in queens3(UnplacedQs1, new ListPair(Q, SafeQs), Qs)) 45 | yield return false; 46 | } 47 | } 48 | foreach (bool l1 in YP.unify(UnplacedQs, Atom.NIL)) 49 | { 50 | foreach (bool l2 in YP.unify(Qs, SafeQs)) 51 | yield return false; 52 | } 53 | } 54 | 55 | static IEnumerable notHasAttack(object X, object Xs) 56 | { 57 | foreach (bool l in attack(X, Xs)) 58 | yield break; 59 | 60 | yield return false; 61 | } 62 | 63 | static IEnumerable attack(object X, object Xs) 64 | { 65 | foreach (bool l in attack3(X, 1, Xs)) 66 | yield return false; 67 | } 68 | 69 | static IEnumerable attack3(object X, object N, object Arg3) 70 | { 71 | Variable Y = new Variable(); 72 | foreach (bool l in new ListPair(Y, new Variable()).unify(Arg3)) 73 | { 74 | if ((int)YP.getValue(X) == (int)Y.getValue() + (int)YP.getValue(N)) 75 | yield return false; 76 | if ((int)YP.getValue(X) == (int)Y.getValue() - (int)YP.getValue(N)) 77 | yield return false; 78 | } 79 | Variable Ys = new Variable(); 80 | Variable N1 = new Variable(); 81 | foreach (bool l1 in new ListPair(new Variable(), Ys).unify(Arg3)) 82 | { 83 | foreach (bool l2 in N1.unify((int)YP.getValue(N) + 1)) 84 | { 85 | foreach (bool l3 in attack3(X, N1, Ys)) 86 | yield return false; 87 | } 88 | } 89 | } 90 | 91 | static IEnumerable rangeList(object M, object N, object List) 92 | { 93 | if ((int)YP.getValue(M) >= (int)YP.getValue(N)) 94 | { 95 | foreach (bool l1 in YP.unify(List, new ListPair(N, Atom.NIL))) 96 | yield return false; 97 | } 98 | else 99 | { 100 | Variable Tail = new Variable(); 101 | foreach (bool l1 in rangeList((int)YP.getValue(M) + 1, (int)YP.getValue(N), Tail)) 102 | { 103 | foreach (bool l2 in YP.unify(List, new ListPair(M, Tail))) 104 | yield return false; 105 | } 106 | } 107 | } 108 | 109 | static IEnumerable selectq(object X, object Arg2, object Arg3) 110 | { 111 | foreach (bool l in new ListPair(X, Arg3).unify(Arg2)) 112 | yield return false; 113 | 114 | Variable Y = new Variable(); 115 | Variable Ys = new Variable(); 116 | Variable Zs = new Variable(); 117 | foreach (bool l1 in new ListPair(Y, Ys).unify(Arg2)) 118 | { 119 | foreach (bool l2 in new ListPair(Y, Zs).unify(Arg3)) 120 | { 121 | foreach (bool l3 in selectq(X, Ys, Zs)) 122 | yield return false; 123 | } 124 | } 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /source/csharp/examples/Benchmarks/Queens.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using YieldProlog; 4 | 5 | namespace YieldPrologBenchmarks 6 | { 7 | class Queens 8 | { 9 | static void Main(string[] args) 10 | { 11 | long startTicks = DateTime.Now.Ticks; 12 | int nAnswers = 0; 13 | Variable Qs = new Variable(); 14 | foreach (bool l1 in queens(11, Qs)) 15 | { 16 | ++nAnswers; 17 | } 18 | long finishTicks = DateTime.Now.Ticks; 19 | Console.WriteLine("Optimized queens: " + 20 | (finishTicks - startTicks) / 10000000.0 + " seconds, " + nAnswers + " answers"); 21 | 22 | Console.WriteLine("\nPress Enter to finish."); 23 | Console.ReadLine(); 24 | } 25 | 26 | static IEnumerable queens(int N, Variable Qs) 27 | { 28 | Variable Ns = new Variable(); 29 | foreach (bool l1 in rangeList(1, N, Ns)) 30 | { 31 | foreach (bool l2 in queens3(Ns, Atom.NIL, Qs)) 32 | yield return false; 33 | } 34 | } 35 | 36 | static IEnumerable queens3(object UnplacedQs, object SafeQs, Variable Qs) 37 | { 38 | ListPair UnplacedQsListPair = YP.getValue(UnplacedQs) as ListPair; 39 | if (UnplacedQsListPair != null) 40 | { 41 | Variable UnplacedQs1 = new Variable(); 42 | Variable Q = new Variable(); 43 | foreach (bool l1 in selectq(Q, UnplacedQsListPair, UnplacedQs1)) 44 | { 45 | if (!(SafeQs is ListPair && hasAttack((int)Q.getValue(), (ListPair)SafeQs))) 46 | { 47 | foreach (bool l2 in queens3(UnplacedQs1, new ListPair(Q, SafeQs), Qs)) 48 | yield return false; 49 | } 50 | } 51 | } 52 | else 53 | { 54 | foreach (bool l1 in Qs.unify(SafeQs)) 55 | yield return false; 56 | } 57 | } 58 | 59 | static bool hasAttack(int X, ListPair Xs) 60 | { 61 | return hasAttack3(X, 1, Xs); 62 | } 63 | 64 | static bool hasAttack3(int X, int N, ListPair Arg3) 65 | { 66 | if (X == (int)YP.getValue(Arg3._arg1) + N || X == (int)YP.getValue(Arg3._arg1) - N) 67 | return true; 68 | if (Arg3._arg2 is ListPair) 69 | return hasAttack3(X, N + 1, (ListPair)YP.getValue(Arg3._arg2)); 70 | else 71 | return false; 72 | } 73 | 74 | static IEnumerable rangeList(int M, int N, Variable List) 75 | { 76 | if (M >= N) 77 | { 78 | foreach (bool l1 in List.unify(new ListPair(N, Atom.NIL))) 79 | yield return false; 80 | } 81 | else 82 | { 83 | Variable Tail = new Variable(); 84 | foreach (bool l1 in rangeList(M + 1, N, Tail)) 85 | { 86 | foreach (bool l2 in List.unify(new ListPair(M, Tail))) 87 | yield return false; 88 | } 89 | } 90 | } 91 | 92 | static IEnumerable selectq(Variable X, ListPair Arg2, Variable Arg3) 93 | { 94 | foreach (bool l1 in X.unify(Arg2._arg1)) 95 | { 96 | foreach (bool l2 in Arg3.unify(Arg2._arg2)) 97 | yield return false; 98 | } 99 | 100 | ListPair Arg2Tail = YP.getValue(Arg2._arg2) as ListPair; 101 | if (Arg2Tail != null) 102 | { 103 | Variable Zs = new Variable(); 104 | foreach (bool l1 in selectq(X, Arg2Tail, Zs)) 105 | { 106 | foreach (bool l2 in Arg3.unify(new ListPair(Arg2._arg1, Zs))) 107 | yield return false; 108 | } 109 | } 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /source/csharp/examples/Benchmarks/YieldPrologBenchmarks.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | Debug 4 | AnyCPU 5 | 9.0.21022 6 | 2.0 7 | {5686A38F-64AD-40C0-99AD-9CD4322F6179} 8 | Exe 9 | Properties 10 | YieldPrologBenchmarks 11 | YieldPrologBenchmarks 12 | YieldPrologBenchmarks.Queens 13 | 14 | 15 | 2.0 16 | v2.0 17 | 18 | 19 | publish\ 20 | true 21 | Disk 22 | false 23 | Foreground 24 | 7 25 | Days 26 | false 27 | false 28 | true 29 | 0 30 | 1.0.0.%2a 31 | false 32 | false 33 | true 34 | 35 | 36 | true 37 | full 38 | false 39 | bin\Debug\ 40 | DEBUG;TRACE 41 | prompt 42 | 4 43 | 44 | 45 | pdbonly 46 | true 47 | bin\Release\ 48 | TRACE 49 | prompt 50 | 4 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | Atom.cs 60 | 61 | 62 | BagofAnswers.cs 63 | 64 | 65 | Compiler.cs 66 | 67 | 68 | FindallAnswers.cs 69 | 70 | 71 | Functor.cs 72 | 73 | 74 | Functor1.cs 75 | 76 | 77 | Functor2.cs 78 | 79 | 80 | Functor3.cs 81 | 82 | 83 | IndexedAnswers.cs 84 | 85 | 86 | ListPair.cs 87 | 88 | 89 | Parser.cs 90 | 91 | 92 | PrologException.cs 93 | 94 | 95 | Variable.cs 96 | 97 | 98 | YP.cs 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | False 107 | .NET Framework 2.0 %28x86%29 108 | false 109 | 110 | 111 | False 112 | .NET Framework 3.0 %28x86%29 113 | false 114 | 115 | 116 | False 117 | .NET Framework 3.5 118 | true 119 | 120 | 121 | False 122 | Windows Installer 3.1 123 | true 124 | 125 | 126 | 127 | 128 | 129 | 130 | 137 | -------------------------------------------------------------------------------- /source/csharp/examples/Benchmarks/YieldPrologBenchmarks.csproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | en-US 14 | false 15 | 16 | -------------------------------------------------------------------------------- /source/csharp/examples/Benchmarks/YieldPrologBenchmarks.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 10.00 3 | # Visual C# Express 2008 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YieldPrologBenchmarks", "YieldPrologBenchmarks.csproj", "{5686A38F-64AD-40C0-99AD-9CD4322F6179}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Any CPU = Debug|Any CPU 9 | Release|Any CPU = Release|Any CPU 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {5686A38F-64AD-40C0-99AD-9CD4322F6179}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 13 | {5686A38F-64AD-40C0-99AD-9CD4322F6179}.Debug|Any CPU.Build.0 = Debug|Any CPU 14 | {5686A38F-64AD-40C0-99AD-9CD4322F6179}.Release|Any CPU.ActiveCfg = Release|Any CPU 15 | {5686A38F-64AD-40C0-99AD-9CD4322F6179}.Release|Any CPU.Build.0 = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /source/csharp/examples/Benchmarks/YieldPrologBenchmarks.suo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vslab/YieldProlog/11f68cd05d55a8b56681b1c7572b9067e7816915/source/csharp/examples/Benchmarks/YieldPrologBenchmarks.suo -------------------------------------------------------------------------------- /source/csharp/examples/Benchmarks/monomake.bat: -------------------------------------------------------------------------------- 1 | rem This is a simple make file to compile a Yield Prolog program into a .exe file under Mono. 2 | rem For example, type: monomake YPShell.cs 3 | gmcs %1 ..\..\Atom.cs ..\..\BagofAnswers.cs ..\..\Compiler.cs ..\..\FindallAnswers.cs ..\..\Functor.cs ..\..\Functor1.cs ..\..\Functor2.cs ..\..\Functor3.cs ..\..\IndexedAnswers.cs ..\..\ListPair.cs ..\..\Parser.cs ..\..\PrologException.cs ..\..\Variable.cs ..\..\YP.cs -------------------------------------------------------------------------------- /source/csharp/examples/YPShell/YPShell.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Collections.Generic; 4 | using YieldProlog; 5 | 6 | /// 7 | /// YPShell has a Main function that provides a command prompt to evaluate Prolog statements 8 | /// and display the results. 9 | /// 10 | public class YPShell 11 | { 12 | static void Main(string[] args) 13 | { 14 | Console.WriteLine("Yield Prolog Shell. Enter ctrl-Z to exit."); 15 | 16 | while (true) 17 | { 18 | Console.Write("?- "); 19 | string goalString = Console.ReadLine(); 20 | if (goalString == null) 21 | break; 22 | if (goalString == "") 23 | { 24 | Console.WriteLine("Enter ctrl-Z to exit."); 25 | continue; 26 | } 27 | 28 | Variable Goal = new Variable(); 29 | Variable VariableList = new Variable(); 30 | foreach (bool l1 in parseGoal(goalString, Goal, VariableList)) 31 | { 32 | try 33 | { 34 | bool gotMatch = false; 35 | foreach (bool l2 in YP.getIterator(Goal, null)) 36 | { 37 | gotMatch = true; 38 | if (YP.getValue(VariableList) != Atom.NIL) 39 | { 40 | // We are showing values, so allow the user to enter ";" to display the next match. 41 | writeValues(VariableList); 42 | if (!Console.ReadLine().StartsWith(";")) 43 | break; 44 | } 45 | } 46 | 47 | if (gotMatch) 48 | { 49 | if (YP.getValue(VariableList) == Atom.NIL) 50 | // We didn't show any values. So just write true after matching (one or more times). 51 | Console.WriteLine("true"); 52 | } 53 | else 54 | Console.WriteLine("fail"); 55 | } 56 | catch (PrologException exception) 57 | { 58 | Console.WriteLine(exception._term.ToString()); 59 | } 60 | } 61 | } 62 | } 63 | 64 | /// 65 | /// Parse goalString and yield for each Goal, setting VariableList to a list of 66 | /// (variableAtom = Var). 67 | /// 68 | /// 69 | /// 70 | /// 71 | /// 72 | static IEnumerable parseGoal(string goalString, object Goal, object VariableList) 73 | { 74 | // The parser requires a newline at the end. 75 | YP.see(new StringReader(goalString + "\n")); 76 | object TermList = new Variable(); 77 | // parseInput set TermList to a list of f(Goal, VariableList). 78 | foreach (bool l1 in Parser.parseInput(TermList)) 79 | { 80 | // Close the input now before yielding. 81 | YP.seen(); 82 | // Iterate through each member of TermList. 83 | for (TermList = YP.getValue(TermList); 84 | TermList is Functor2 && ((Functor2)TermList)._name == Atom.DOT; 85 | TermList = YP.getValue(((Functor2)TermList)._arg2)) 86 | { 87 | // Unify the head of the list with f(Goal, VariableList). 88 | foreach (bool l2 in YP.unify 89 | (((Functor2)TermList)._arg1, new Functor2(Atom.F, Goal, VariableList))) 90 | yield return false; 91 | } 92 | yield break; 93 | } 94 | // Close the input in case parseInput failed. 95 | YP.seen(); 96 | } 97 | 98 | /// 99 | /// Write out each entry in VariableList which is a list of (variableAtom = Var) 100 | /// 101 | /// 102 | static void writeValues(object VariableList) 103 | { 104 | for (VariableList = YP.getValue(VariableList); 105 | VariableList is Functor2 && ((Functor2)VariableList)._name == Atom.DOT; 106 | VariableList = YP.getValue(((Functor2)VariableList)._arg2)) 107 | { 108 | Functor2 variableAndValue = YP.getValue(((Functor2)VariableList)._arg1) as Functor2; 109 | if (variableAndValue != null) 110 | { 111 | Console.WriteLine(""); 112 | Console.Write(YP.getValue(variableAndValue._arg1)); 113 | Console.Write(" = "); 114 | Console.Write(YP.getValue(variableAndValue._arg2)); 115 | } 116 | } 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /source/csharp/examples/YPShell/YPShell.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | Debug 4 | AnyCPU 5 | 9.0.21022 6 | 2.0 7 | {5686A38F-64AD-40C0-99AD-9CD4322F6179} 8 | Exe 9 | Properties 10 | YPShell 11 | YPShell 12 | YPShell 13 | 14 | 15 | 2.0 16 | v2.0 17 | 18 | 19 | false 20 | publish\ 21 | true 22 | Disk 23 | false 24 | Foreground 25 | 7 26 | Days 27 | false 28 | false 29 | true 30 | 0 31 | 1.0.0.%2a 32 | false 33 | true 34 | 35 | 36 | true 37 | full 38 | false 39 | bin\Debug\ 40 | DEBUG;TRACE 41 | prompt 42 | 4 43 | 44 | 45 | pdbonly 46 | true 47 | bin\Release\ 48 | TRACE 49 | prompt 50 | 4 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | Atom.cs 60 | 61 | 62 | BagofAnswers.cs 63 | 64 | 65 | Compiler.cs 66 | 67 | 68 | FindallAnswers.cs 69 | 70 | 71 | Functor.cs 72 | 73 | 74 | Functor1.cs 75 | 76 | 77 | Functor2.cs 78 | 79 | 80 | Functor3.cs 81 | 82 | 83 | IndexedAnswers.cs 84 | 85 | 86 | ListPair.cs 87 | 88 | 89 | Parser.cs 90 | 91 | 92 | PrologException.cs 93 | 94 | 95 | Variable.cs 96 | 97 | 98 | YP.cs 99 | 100 | 101 | 102 | 103 | 104 | False 105 | .NET Framework 2.0 %28x86%29 106 | false 107 | 108 | 109 | False 110 | .NET Framework 3.0 %28x86%29 111 | false 112 | 113 | 114 | False 115 | .NET Framework 3.5 116 | true 117 | 118 | 119 | False 120 | Windows Installer 3.1 121 | true 122 | 123 | 124 | 125 | 126 | 127 | 128 | 135 | -------------------------------------------------------------------------------- /source/csharp/examples/YPShell/YPShell.csproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | publish\ 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | en-US 13 | false 14 | 15 | -------------------------------------------------------------------------------- /source/csharp/examples/YPShell/YPShell.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 10.00 3 | # Visual C# Express 2008 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YPShell", "YPShell.csproj", "{5686A38F-64AD-40C0-99AD-9CD4322F6179}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Any CPU = Debug|Any CPU 9 | Release|Any CPU = Release|Any CPU 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {5686A38F-64AD-40C0-99AD-9CD4322F6179}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 13 | {5686A38F-64AD-40C0-99AD-9CD4322F6179}.Debug|Any CPU.Build.0 = Debug|Any CPU 14 | {5686A38F-64AD-40C0-99AD-9CD4322F6179}.Release|Any CPU.ActiveCfg = Release|Any CPU 15 | {5686A38F-64AD-40C0-99AD-9CD4322F6179}.Release|Any CPU.Build.0 = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /source/csharp/examples/YPShell/YPShell.suo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vslab/YieldProlog/11f68cd05d55a8b56681b1c7572b9067e7816915/source/csharp/examples/YPShell/YPShell.suo -------------------------------------------------------------------------------- /source/csharp/examples/YPShell/monomake.bat: -------------------------------------------------------------------------------- 1 | rem This is a simple make file to compile a Yield Prolog program into a .exe file under Mono. 2 | rem For example, type: monomake YPShell.cs 3 | gmcs %1 ..\..\Atom.cs ..\..\BagofAnswers.cs ..\..\Compiler.cs ..\..\FindallAnswers.cs ..\..\Functor.cs ..\..\Functor1.cs ..\..\Functor2.cs ..\..\Functor3.cs ..\..\IndexedAnswers.cs ..\..\ListPair.cs ..\..\Parser.cs ..\..\PrologException.cs ..\..\Variable.cs ..\..\YP.cs -------------------------------------------------------------------------------- /source/csharp/examples/YieldPrologTutorial/Tutorial2.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2007-2008, Jeff Thompson 3 | * 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * * Neither the name of the copyright holder nor the names of its contributors 15 | * may be used to endorse or promote products derived from this software 16 | * without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 22 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | using System; 32 | using System.Collections.Generic; 33 | using YieldProlog; 34 | 35 | // This is the code for tutorial2.html in the doc directory. 36 | class Tutorial2 37 | { 38 | static void Main(string[] args) 39 | { 40 | Console.WriteLine("Find relations:"); 41 | Variable Brother = new Variable(); 42 | foreach (bool l1 in brother("Hillary", Brother)) 43 | Console.WriteLine("Hillary has brother " + 44 | Brother.getValue() + "."); 45 | 46 | Console.WriteLine("Check if it is square:"); 47 | foreach (bool l1 in squaredRectangle(10, 10)) 48 | Console.WriteLine("10 by 10 rectangle is square."); 49 | 50 | Console.WriteLine("Make it square:"); 51 | Variable Width = new Variable(); 52 | Variable Height = new Variable(); 53 | foreach (bool l1 in Width.unify(10)) 54 | { 55 | foreach (bool l2 in squaredRectangle(Width, Height)) 56 | Console.WriteLine("A square of width " + 57 | Width.getValue() + " has height " + 58 | Height.getValue() + "."); 59 | } 60 | 61 | Console.WriteLine("Make it square before we know the width:"); 62 | foreach (bool l1 in squaredRectangle(Width, Height)) 63 | { 64 | foreach (bool l2 in Width.unify(10)) 65 | Console.WriteLine("A square of width " + 66 | Width.getValue() + " has height " + 67 | Height.getValue() + "."); 68 | } 69 | 70 | Console.WriteLine("Get one match:"); 71 | foreach (bool l1 in anyBrother("Hillary", Brother)) 72 | Console.WriteLine("Hillary has a brother " + 73 | Brother.getValue() + "."); 74 | foreach (bool l1 in anyBrother("Bill", Brother)) 75 | Console.WriteLine("Bill has a brother " + 76 | Brother.getValue() + "."); 77 | 78 | Console.WriteLine("Use cut for negation:"); 79 | foreach (bool l1 in noBrother("Hillary")) 80 | Console.WriteLine("Hillary has no brother."); 81 | foreach (bool l1 in noBrother("Chelsea")) 82 | Console.WriteLine("Chelsea has no brother."); 83 | 84 | Console.WriteLine("\nPress Enter to finish."); 85 | Console.ReadLine(); 86 | } 87 | 88 | static IEnumerable brother(object Person, object Brother) 89 | { 90 | foreach (bool l1 in YP.unify(Person, "Hillary")) 91 | { 92 | foreach (bool l2 in YP.unify(Brother, "Tony")) 93 | yield return false; 94 | foreach (bool l2 in YP.unify(Brother, "Hugh")) 95 | yield return false; 96 | } 97 | foreach (bool l1 in YP.unify(Person, "Bill")) 98 | { 99 | foreach (bool l2 in YP.unify(Brother, "Roger")) 100 | yield return false; 101 | } 102 | } 103 | 104 | static IEnumerable squaredRectangle(object Width, object Height) 105 | { 106 | foreach (bool l1 in YP.unify(Width, Height)) 107 | yield return false; 108 | } 109 | 110 | static IEnumerable anyBrother(object Person, object Brother) 111 | { 112 | foreach (bool l1 in brother(Person, Brother)) 113 | { 114 | yield return false; 115 | break; 116 | } 117 | } 118 | 119 | static IEnumerable noBrother(object Person) 120 | { 121 | Variable Brother = new Variable(); 122 | foreach (bool l1 in brother(Person, Brother)) 123 | yield break; 124 | yield return false; 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /source/csharp/examples/YieldPrologTutorial/Tutorial3.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2007-2008, Jeff Thompson 3 | * 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * * Neither the name of the copyright holder nor the names of its contributors 15 | * may be used to endorse or promote products derived from this software 16 | * without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 22 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | using System; 32 | using System.Collections.Generic; 33 | using YieldProlog; 34 | 35 | // This is the code for tutorial3.html in the doc directory. 36 | class Tutorial3 37 | { 38 | static void Main(string[] args) 39 | { 40 | Console.WriteLine("Return a list of 2 elements:"); 41 | Variable List = new Variable(); 42 | foreach (bool l1 in makeList("a", "b", List)) 43 | Console.WriteLine("List = " + List.getValue()); 44 | 45 | Console.WriteLine("Unify two lists:"); 46 | Variable Second = new Variable(); 47 | foreach (bool l1 in makeList("x", Second, new ListPair("x", new ListPair("y", Atom.NIL)))) 48 | Console.WriteLine("The second element is " + Second.getValue()); 49 | 50 | Console.WriteLine("\nPress Enter to finish."); 51 | Console.ReadLine(); 52 | } 53 | 54 | static IEnumerable makeList(object First, object Second, object List) 55 | { 56 | ListPair list1 = new ListPair(Second, Atom.NIL); 57 | ListPair result = new ListPair(First, list1); 58 | foreach (bool l1 in YP.unify(List, result)) 59 | yield return false; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /source/csharp/examples/YieldPrologTutorial/YieldPrologTutorial.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | Debug 4 | AnyCPU 5 | 9.0.21022 6 | 2.0 7 | {ACD390C7-09EB-4106-978F-26DF9DB2D03B} 8 | Exe 9 | Properties 10 | YieldPrologTutorial 11 | YieldPrologTutorial 12 | Tutorial1 13 | 14 | 15 | 2.0 16 | v2.0 17 | 18 | 19 | publish\ 20 | true 21 | Disk 22 | false 23 | Foreground 24 | 7 25 | Days 26 | false 27 | false 28 | true 29 | 0 30 | 1.0.0.%2a 31 | false 32 | false 33 | true 34 | 35 | 36 | true 37 | full 38 | false 39 | bin\Debug\ 40 | DEBUG;TRACE 41 | prompt 42 | 4 43 | 44 | 45 | pdbonly 46 | true 47 | bin\Release\ 48 | TRACE 49 | prompt 50 | 4 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | Atom.cs 60 | 61 | 62 | BagofAnswers.cs 63 | 64 | 65 | Compiler.cs 66 | 67 | 68 | FindallAnswers.cs 69 | 70 | 71 | Functor.cs 72 | 73 | 74 | Functor1.cs 75 | 76 | 77 | Functor2.cs 78 | 79 | 80 | Functor3.cs 81 | 82 | 83 | IndexedAnswers.cs 84 | 85 | 86 | ListPair.cs 87 | 88 | 89 | Parser.cs 90 | 91 | 92 | PrologException.cs 93 | 94 | 95 | Variable.cs 96 | 97 | 98 | YP.cs 99 | 100 | 101 | Code 102 | 103 | 104 | 105 | Code 106 | 107 | 108 | 109 | 110 | 111 | False 112 | .NET Framework 2.0 %28x86%29 113 | false 114 | 115 | 116 | False 117 | .NET Framework 3.0 %28x86%29 118 | false 119 | 120 | 121 | False 122 | .NET Framework 3.5 123 | true 124 | 125 | 126 | False 127 | Windows Installer 3.1 128 | true 129 | 130 | 131 | 132 | 133 | 134 | 135 | 142 | -------------------------------------------------------------------------------- /source/csharp/examples/YieldPrologTutorial/YieldPrologTutorial.csproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | en-US 14 | false 15 | 16 | -------------------------------------------------------------------------------- /source/csharp/examples/YieldPrologTutorial/YieldPrologTutorial.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 10.00 3 | # Visual C# Express 2008 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YieldPrologTutorial", "YieldPrologTutorial.csproj", "{ACD390C7-09EB-4106-978F-26DF9DB2D03B}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Any CPU = Debug|Any CPU 9 | Release|Any CPU = Release|Any CPU 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {ACD390C7-09EB-4106-978F-26DF9DB2D03B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 13 | {ACD390C7-09EB-4106-978F-26DF9DB2D03B}.Debug|Any CPU.Build.0 = Debug|Any CPU 14 | {ACD390C7-09EB-4106-978F-26DF9DB2D03B}.Release|Any CPU.ActiveCfg = Release|Any CPU 15 | {ACD390C7-09EB-4106-978F-26DF9DB2D03B}.Release|Any CPU.Build.0 = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /source/csharp/examples/YieldPrologTutorial/YieldPrologTutorial.suo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vslab/YieldProlog/11f68cd05d55a8b56681b1c7572b9067e7816915/source/csharp/examples/YieldPrologTutorial/YieldPrologTutorial.suo -------------------------------------------------------------------------------- /source/csharp/examples/YieldPrologTutorial/monomake.bat: -------------------------------------------------------------------------------- 1 | rem This is a simple make file to compile a Yield Prolog program into a .exe file under Mono. 2 | rem For example, type: monomake YPShell.cs 3 | gmcs %1 ..\..\Atom.cs ..\..\BagofAnswers.cs ..\..\Compiler.cs ..\..\FindallAnswers.cs ..\..\Functor.cs ..\..\Functor1.cs ..\..\Functor2.cs ..\..\Functor3.cs ..\..\IndexedAnswers.cs ..\..\ListPair.cs ..\..\Parser.cs ..\..\PrologException.cs ..\..\Variable.cs ..\..\YP.cs -------------------------------------------------------------------------------- /source/csharp/update.bat: -------------------------------------------------------------------------------- 1 | rem Copy makefiles from the main working directory YPShell. 2 | copy examples\YPShell\monomake.bat examples\Benchmarks 3 | copy examples\YPShell\monomake.bat examples\YieldPrologTutorial 4 | 5 | rem Copy executables to bin 6 | copy examples\YPShell\bin\Release\YPShell.exe ..\..\bin 7 | -------------------------------------------------------------------------------- /source/javascript/Atom.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2007-2008, Jeff Thompson 3 | * 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * * Neither the name of the copyright holder nor the names of its contributors 15 | * may be used to endorse or promote products derived from this software 16 | * without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 22 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | // You should not call this constructor, but use Atom.a instead. 32 | function Atom(name, module) { 33 | this._name = name; 34 | if (module == undefined) 35 | this._module = null; 36 | else 37 | this._module = module; 38 | } 39 | 40 | Atom._atomStore = new Object(); 41 | // Return an Atom object with the name and module. If module is null or Atom.NIL, 42 | // this behaves like Atom.a(name, undefined) and returns the unique object where the module is null. 43 | // If module is null or Atom.NIL, return a unique Atom object. 44 | // If module is not null or Atom.NIL, this may or may not be the same object as another Atom 45 | // with the same name and module. 46 | // You should use this to create an Atom instead of calling the Atom constructor. 47 | Atom.a = function(name, module) { 48 | if (module == undefined || module == null || module == Atom.NIL) { 49 | var atom = Atom._atomStore[name]; 50 | if (atom === undefined) { 51 | atom = new Atom(name); 52 | Atom._atomStore[name] = atom; 53 | } 54 | return atom; 55 | } 56 | else 57 | return new Atom(name, module); 58 | } 59 | 60 | // If Obj is an Atom unify its _module with Module. If the Atom's _module is null, use Atom.NIL. 61 | Atom.module = function(Obj, Module) { 62 | Obj = YP.getValue(Obj); 63 | if (Obj instanceof Atom) { 64 | if (Obj._module == null) 65 | return YP.unify(Module, Atom.NIL); 66 | else 67 | return YP.unify(Module, Obj._module); 68 | } 69 | return YP.fail(); 70 | } 71 | 72 | Atom.NIL = Atom.a("[]"); 73 | Atom.DOT = Atom.a("."); 74 | Atom.F = Atom.a("f"); 75 | Atom.SLASH = Atom.a("/"); 76 | Atom.HAT = Atom.a("^"); 77 | Atom.RULE = Atom.a(":-"); 78 | Atom.TRUE = Atom.a("true"); 79 | 80 | Atom.prototype.unify = function(arg) 81 | { 82 | arg = YP.getValue(arg); 83 | if (arg instanceof Atom) 84 | return this.equals(arg) ? YP.succeed() : YP.fail(); 85 | else if (arg instanceof Variable) 86 | return arg.unify(this); 87 | else 88 | return YP.fail(); 89 | } 90 | 91 | Atom.prototype.addUniqueVariables = function(variableSet) 92 | { 93 | // Atom does not contain variables. 94 | } 95 | 96 | Atom.prototype.makeCopy = function(copyStore) 97 | { 98 | // Atom does not contain variables that need to be copied. 99 | return this; 100 | } 101 | 102 | Atom.prototype.termEqual = function(term) 103 | { 104 | return this.equals(YP.getValue(term)); 105 | } 106 | 107 | Atom.prototype.ground = function() 108 | { 109 | // Atom is always ground. 110 | return true; 111 | } 112 | 113 | Atom.prototype.equals = function(obj) { 114 | if (obj instanceof Atom) { 115 | if (this._module == null && obj._module == null) 116 | // When _declaringClass is null, we always use an identical object from _atomStore. 117 | return this == obj; 118 | // Otherwise, ignore _declaringClass and do a normal string compare on the _name. 119 | return this._name == obj._name; 120 | } 121 | return false; 122 | } 123 | 124 | Atom.prototype.toString = function() { 125 | return this._name; 126 | } 127 | 128 | Atom.prototype.toQuotedString = function() { 129 | if (this._name.length == 0) 130 | return "''"; 131 | else if (this == Atom.NIL) 132 | return "[]"; 133 | 134 | var result = new Array(""); 135 | var useQuotes = false; 136 | for each (var c in this._name) { 137 | if (c == '\'') { 138 | result.push("''"); 139 | useQuotes = true; 140 | } 141 | else if (c == '_' || c >= 'a' && c <= 'z' || 142 | c >= 'A' && c <= 'Z' || c >= '0' && c <= '9') 143 | result.push(c); 144 | else { 145 | // Debug: Need to handle non-printable chars. 146 | result.push(c); 147 | useQuotes = true; 148 | } 149 | } 150 | 151 | if (!useQuotes && this._name[0] >= 'a' && this._name[0] <= 'z') 152 | return result.join(""); 153 | else 154 | // Surround in single quotes. 155 | result.push('\''); 156 | return "'" + result.join(""); 157 | } 158 | 159 | 160 | // Return true if _name is lexicographically less than atom._name. 161 | Atom.prototype.lessThan = function(atom) { 162 | return this._name < atom._name; 163 | } 164 | -------------------------------------------------------------------------------- /source/javascript/FindallAnswers.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2007-2008, Jeff Thompson 3 | * 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * * Neither the name of the copyright holder nor the names of its contributors 15 | * may be used to endorse or promote products derived from this software 16 | * without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 22 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | // A FindallAnswers holds answers for findall. 32 | function FindallAnswers(Template) { 33 | this._template = Template; 34 | this._bagArray = []; 35 | } 36 | 37 | FindallAnswers.prototype.add = function() { 38 | this._bagArray.push(YP.makeCopy(this._template, new Variable.CopyStore())); 39 | } 40 | 41 | FindallAnswers.prototype.resultArray = function() { 42 | return this._bagArray; 43 | } 44 | 45 | // Unify Bag with the result. This frees the internal answers, so you can only call this once. 46 | FindallAnswers.prototype.result = function(Bag) { 47 | var result = ListPair.make(this._bagArray); 48 | // Try to free the memory. 49 | this._bagArray = null; 50 | return YP.unify(Bag, result); 51 | } 52 | 53 | // This is a simplified findall when the goal is a single call. 54 | FindallAnswers.findall = function(Template, goal, Bag) { 55 | var findallAnswers = new FindallAnswers(Template); 56 | for each (var l1 in goal) 57 | findallAnswers.add(); 58 | return findallAnswers.result(Bag); 59 | } 60 | 61 | // Like findall, except return an array of the results. 62 | FindallAnswers.findallArray = function(Template, goal) { 63 | var findallAnswers = new FindallAnswers(Template); 64 | for each (var l1 in goal) 65 | findallAnswers.add(); 66 | return findallAnswers.resultArray(); 67 | } 68 | -------------------------------------------------------------------------------- /source/javascript/Functor.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2007-2008, Jeff Thompson 3 | * 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * * Neither the name of the copyright holder nor the names of its contributors 15 | * may be used to endorse or promote products derived from this software 16 | * without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 22 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | function Functor(name, args) { 32 | if (args.length < 3) 33 | { 34 | if (args.length == 0) 35 | throw "For arity 0 functor, just use name as an Atom"; 36 | else if (args.length == 1) 37 | throw "For arity 1 functor, use Functor1"; 38 | else if (args.length == 2) 39 | throw "For arity 2 functor, use Functor2"; 40 | else if (args.length == 3) 41 | throw "For arity 3 functor, use Functor3"; 42 | else 43 | // (This shouldn't happen, but include it for completeness. 44 | throw "Cannot create a Functor of arity " + args.length; 45 | } 46 | 47 | if (name instanceof Atom) 48 | this._name = name; 49 | else 50 | // Assume name is a string. 51 | this._name = Atom.a(name); 52 | this._args = args; 53 | } 54 | 55 | // Return an Atom, Functor1, Functor2, Functor3 or Functor depending on the 56 | // length of args. 57 | // Note that this is different than the Functor constructor which requires 58 | // the length of args to be greater than 3. 59 | Functor.make = function(name, args) { 60 | if (!(name instanceof Atom)) 61 | // Assume name is a string. 62 | name = Atom.a(name); 63 | 64 | if (args.length <= 0) 65 | return name; 66 | else if (args.length == 1) 67 | return new Functor1(name, args[0]); 68 | else if (args.length == 2) 69 | return new Functor2(name, args[0], args[1]); 70 | else if (args.length == 3) 71 | return new Functor3(name, args[0], args[1], args[2]); 72 | else 73 | return new Functor(name, args); 74 | } 75 | 76 | // If arg is another Functor, then succeed (yield once) if this and arg have the 77 | // same name and all functor args unify, otherwise fail (don't yield). 78 | // If arg is a Variable, then call its unify to unify with this. 79 | // Otherwise fail (don't yield). 80 | Functor.prototype.unify = function(arg) { 81 | arg = YP.getValue(arg); 82 | if (arg instanceof Functor) 83 | { 84 | if (this._name.equals(arg._name)) 85 | return YP.unifyArrays(this._args, arg._args); 86 | else 87 | return YP.fail(); 88 | } 89 | else if (arg instanceof Variable) 90 | return arg.unify(this); 91 | else 92 | return YP.fail(); 93 | } 94 | 95 | Functor.prototype.toString = function() { 96 | var result = this._name + "(" + YP.getValue(this._args[0]); 97 | for (var i = 1; i < this._args.length; ++i) 98 | result += ", " + YP.getValue(this._args[i]); 99 | result += ")"; 100 | return result; 101 | } 102 | 103 | Functor.prototype.termEqual = function(term) { 104 | term = YP.getValue(term); 105 | if (term instanceof Functor) { 106 | if (this._name.equals(term._name) && this._args.length == term._args.length) { 107 | for (var i = 0; i < this._args.length; ++i) 108 | { 109 | if (!YP.termEqual(this._args[i], term._args[i])) 110 | return false; 111 | } 112 | return true; 113 | } 114 | } 115 | return false; 116 | } 117 | 118 | Functor.prototype.lessThan = function(functor) { 119 | // Do the equal check first since it is faster. 120 | if (!this._name.equals(functor._name)) 121 | return this._name.lessThan(functor._name); 122 | 123 | if (this._args.length != functor._args.length) 124 | return this._args.length < functor._args.length; 125 | 126 | for (var i = 0; i < this._args.length; ++i) { 127 | if (!YP.termEqual(this._args[i], functor._args[i])) 128 | return YP.termLessThan(this._args[i], functor._args[i]); 129 | } 130 | 131 | return false; 132 | } 133 | 134 | Functor.prototype.ground = function() { 135 | for (var i = 0; i < this._args.length; ++i) { 136 | if (!YP.ground(this._args[i])) 137 | return false; 138 | } 139 | return true; 140 | } 141 | 142 | Functor.prototype.addUniqueVariables = function(variableSet) { 143 | for (var i = 0; i < this._args.length; ++i) 144 | YP.addUniqueVariables(this._args[i], variableSet); 145 | } 146 | 147 | Functor.prototype.makeCopy = function(copyStore) { 148 | var argsCopy = [YP.makeCopy(arg, copyStore) for each (arg in this._args)]; 149 | return new Functor(this._name, argsCopy); 150 | } 151 | 152 | -------------------------------------------------------------------------------- /source/javascript/Functor1.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2007-2008, Jeff Thompson 3 | * 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * * Neither the name of the copyright holder nor the names of its contributors 15 | * may be used to endorse or promote products derived from this software 16 | * without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 22 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | function Functor1(name, arg1) { 32 | if (name instanceof Atom) 33 | this._name = name; 34 | else 35 | // Assume name is a string. 36 | this._name = Atom.a(name); 37 | this._arg1 = arg1; 38 | } 39 | 40 | // If arg is another Functor1, then succeed (yield once) if this and arg have the 41 | // same name and the functor args unify, otherwise fail (don't yield). 42 | // If arg is a Variable, then call its unify to unify with this. 43 | // Otherwise fail (don't yield). 44 | Functor1.prototype.unify = function(arg) { 45 | arg = YP.getValue(arg); 46 | if (arg instanceof Functor1) 47 | { 48 | if (this._name.equals(arg._name)) { 49 | for each (var l1 in YP.unify(this._arg1, arg._arg1)) 50 | yield false; 51 | } 52 | } 53 | else if (arg instanceof Variable) { 54 | for each (var l1 in arg.unify(this)) 55 | yield false; 56 | } 57 | } 58 | 59 | Functor1.prototype.toString = function() { 60 | return this._name + "(" + YP.getValue(this._arg1) + ")"; 61 | } 62 | 63 | Functor1.prototype.termEqual = function(term) { 64 | term = YP.getValue(term); 65 | if (term instanceof Functor1) 66 | return this._name.equals(term._name) && YP.termEqual(this._arg1, term._arg1); 67 | return false; 68 | } 69 | 70 | Functor1.prototype.lessThan = function(functor) { 71 | // Do the equal check first since it is faster. 72 | if (!this._name.equals(functor._name)) 73 | return this._name.lessThan(functor._name); 74 | 75 | return YP.termLessThan(this._arg1, functor._arg1); 76 | } 77 | 78 | Functor1.prototype.ground = function() { 79 | return YP.ground(this._arg1); 80 | } 81 | 82 | Functor1.prototype.addUniqueVariables = function(variableSet) { 83 | YP.addUniqueVariables(this._arg1, variableSet); 84 | } 85 | 86 | Functor1.prototype.makeCopy = function(copyStore) { 87 | return new Functor1(this._name, YP.makeCopy(this._arg1, copyStore)); 88 | } 89 | 90 | -------------------------------------------------------------------------------- /source/javascript/Functor2.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2007-2008, Jeff Thompson 3 | * 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * * Neither the name of the copyright holder nor the names of its contributors 15 | * may be used to endorse or promote products derived from this software 16 | * without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 22 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | function Functor2(name, arg1, arg2) { 32 | if (name instanceof Atom) 33 | this._name = name; 34 | else 35 | // Assume name is a string. 36 | this._name = Atom.a(name); 37 | this._arg1 = arg1; 38 | this._arg2 = arg2; 39 | } 40 | 41 | // If arg is another Functor2, then succeed (yield once) if this and arg have the 42 | // same name and all functor args unify, otherwise fail (don't yield). 43 | // If arg is a Variable, then call its unify to unify with this. 44 | // Otherwise fail (don't yield). 45 | Functor2.prototype.unify = function(arg) { 46 | arg = YP.getValue(arg); 47 | if (arg instanceof Functor2) 48 | { 49 | if (this._name.equals(arg._name)) { 50 | for each (var l1 in YP.unify(this._arg1, arg._arg1)) { 51 | for each (var l1 in YP.unify(this._arg2, arg._arg2)) 52 | yield false; 53 | } 54 | } 55 | } 56 | else if (arg instanceof Variable) { 57 | for each (var l1 in arg.unify(this)) 58 | yield false; 59 | } 60 | } 61 | 62 | Functor2.prototype.toString = function() { 63 | if (this._name == Atom.DOT) 64 | return Functor2.listPairToString(this); 65 | else 66 | return this._name + "(" + YP.getValue(this._arg1) + ", " + YP.getValue(this._arg2) + ")"; 67 | } 68 | 69 | Functor2.prototype.termEqual = function(term) { 70 | term = YP.getValue(term); 71 | if (term instanceof Functor2) 72 | return this._name.equals(term._name) && YP.termEqual(this._arg1, term._arg1) && 73 | YP.termEqual(this._arg2, term._arg2); 74 | return false; 75 | } 76 | 77 | Functor2.prototype.lessThan = function(functor) { 78 | // Do the equal check first since it is faster. 79 | if (!this._name.equals(functor._name)) 80 | return this._name.lessThan(functor._name); 81 | 82 | if (!YP.termEqual(this._arg1, functor._arg1)) 83 | return YP.termLessThan(this._arg1, functor._arg1); 84 | 85 | return YP.termLessThan(this._arg2, functor._arg2); 86 | } 87 | 88 | Functor2.prototype.ground = function() { 89 | return YP.ground(this._arg1) && YP.ground(this._arg2); 90 | } 91 | 92 | Functor2.prototype.addUniqueVariables = function(variableSet) { 93 | YP.addUniqueVariables(this._arg1, variableSet); 94 | YP.addUniqueVariables(this._arg2, variableSet); 95 | } 96 | 97 | Functor2.prototype.makeCopy = function(copyStore) { 98 | return new Functor2(this._name, YP.makeCopy(this._arg1, copyStore), 99 | YP.makeCopy(this._arg2, copyStore)); 100 | } 101 | 102 | Functor2.listPairToString = function(listPair) { 103 | var result = "["; 104 | while (true) { 105 | var head = YP.getValue(listPair._arg1); 106 | var tail = YP.getValue(listPair._arg2); 107 | if (tail == Atom.NIL) { 108 | result += "" + head; 109 | break; 110 | } 111 | else if (tail instanceof Functor2 && tail._name == Atom.DOT) { 112 | result += head + ", "; 113 | listPair = tail; 114 | // Loop again. 115 | } 116 | else { 117 | // The list is not terminated with NIL. 118 | result += head + "|" + tail; 119 | break; 120 | } 121 | } 122 | 123 | result += "]"; 124 | return result; 125 | } 126 | 127 | -------------------------------------------------------------------------------- /source/javascript/Functor3.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2007-2008, Jeff Thompson 3 | * 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * * Neither the name of the copyright holder nor the names of its contributors 15 | * may be used to endorse or promote products derived from this software 16 | * without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 22 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | function Functor3(name, arg1, arg2, arg3) { 32 | if (name instanceof Atom) 33 | this._name = name; 34 | else 35 | // Assume name is a string. 36 | this._name = Atom.a(name); 37 | this._arg1 = arg1; 38 | this._arg2 = arg2; 39 | this._arg3 = arg3; 40 | } 41 | 42 | // If arg is another Functor3, then succeed (yield once) if this and arg have the 43 | // same name and all functor args unify, otherwise fail (don't yield). 44 | // If arg is a Variable, then call its unify to unify with this. 45 | // Otherwise fail (don't yield). 46 | Functor3.prototype.unify = function(arg) { 47 | arg = YP.getValue(arg); 48 | if (arg instanceof Functor3) 49 | { 50 | if (this._name.equals(arg._name)) { 51 | for each (var l1 in YP.unify(this._arg1, arg._arg1)) { 52 | for each (var l1 in YP.unify(this._arg2, arg._arg2)) { 53 | for each (var l1 in YP.unify(this._arg3, arg._arg3)) 54 | yield false; 55 | } 56 | } 57 | } 58 | } 59 | else if (arg instanceof Variable) { 60 | for each (var l1 in arg.unify(this)) 61 | yield false; 62 | } 63 | } 64 | 65 | Functor3.prototype.toString = function() { 66 | return this._name + "(" + YP.getValue(this._arg1) + ", " + YP.getValue(this._arg2) + ", " + 67 | YP.getValue(this._arg3) + ")"; 68 | } 69 | 70 | Functor3.prototype.termEqual = function(term) { 71 | term = YP.getValue(term); 72 | if (term instanceof Functor3) 73 | return this._name.equals(term._name) && YP.termEqual(this._arg1, term._arg1) && 74 | YP.termEqual(this._arg2, term._arg2) && YP.termEqual(this._arg3, term._arg3); 75 | return false; 76 | } 77 | 78 | Functor3.prototype.lessThan = function(functor) { 79 | // Do the equal check first since it is faster. 80 | if (!this._name.equals(functor._name)) 81 | return this._name.lessThan(functor._name); 82 | 83 | if (!YP.termEqual(this._arg1, functor._arg1)) 84 | return YP.termLessThan(this._arg1, functor._arg1); 85 | 86 | if (!YP.termEqual(this._arg2, functor._arg2)) 87 | return YP.termLessThan(this._arg2, functor._arg2); 88 | 89 | return YP.termLessThan(this._arg3, functor._arg3); 90 | } 91 | 92 | Functor3.prototype.ground = function() { 93 | return YP.ground(this._arg1) && YP.ground(this._arg2) && YP.ground(this._arg3); 94 | } 95 | 96 | Functor3.prototype.addUniqueVariables = function(variableSet) { 97 | YP.addUniqueVariables(this._arg1, variableSet); 98 | YP.addUniqueVariables(this._arg2, variableSet); 99 | YP.addUniqueVariables(this._arg3, variableSet); 100 | } 101 | 102 | Functor3.prototype.makeCopy = function(copyStore) { 103 | return new Functor3(this._name, YP.makeCopy(this._arg1, copyStore), 104 | YP.makeCopy(this._arg2, copyStore), YP.makeCopy(this._arg3, copyStore)); 105 | } 106 | 107 | -------------------------------------------------------------------------------- /source/javascript/ListPair.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2007-2008, Jeff Thompson 3 | * 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * * Neither the name of the copyright holder nor the names of its contributors 15 | * may be used to endorse or promote products derived from this software 16 | * without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 22 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | function ListPair(head, tail) { 32 | Functor2.call(this, Atom.DOT, head, tail); 33 | } 34 | 35 | ListPair.prototype = new Functor2; 36 | 37 | ListPair.make = function(arg1, arg2, arg3) { 38 | if (arg3 !== undefined) 39 | return new ListPair(arg1, new ListPair(arg2, new ListPair(arg3, Atom.NIL))); 40 | if (arg2 !== undefined) 41 | return new ListPair(arg1, new ListPair(arg2, Atom.NIL)); 42 | 43 | if (arg1 instanceof Array) { 44 | if (arg1.length <= 0) 45 | return Atom.NIL; 46 | 47 | var result = Atom.NIL; 48 | // Start from the end. 49 | for (var i = arg1.length - 1; i >= 0; --i) 50 | result = new ListPair(arg1[i], result); 51 | return result; 52 | } 53 | else 54 | return new ListPair(arg1, Atom.NIL); 55 | } 56 | 57 | // Return a ListPair version of array, where repeated elements (according to YP.termEqual) are removed. 58 | ListPair.makeWithoutRepeatedTerms = function(array) { 59 | if (array.length <= 0) 60 | return Atom.NIL; 61 | 62 | // Start from the end. 63 | var previousTerm = array[array.length - 1]; 64 | var result = new ListPair(previousTerm, Atom.NIL); 65 | for (var i = array.length - 2; i >= 0; --i) { 66 | var term = array[i]; 67 | if (YP.termEqual(term, previousTerm)) 68 | continue; 69 | result = new ListPair(term, result); 70 | previousTerm = term; 71 | } 72 | return result; 73 | } 74 | 75 | // Return an array of the elements in list or null if it is not 76 | // a proper list. If list is Atom.NIL, return an array of zero elements. 77 | // If the list or one of the tails of the list is Variable, raise an instantiation_error. 78 | // This does not call YP.getValue on each element. 79 | ListPair.toArray = function(list) { 80 | list = YP.getValue(list); 81 | if (list == Atom.NIL) 82 | return []; 83 | 84 | var result = []; 85 | var element = list; 86 | while(true) { 87 | if (element == Atom.NIL) 88 | break; 89 | if (element instanceof Variable) 90 | throw new PrologException(Atom.a("instantiation_error"), 91 | "List tail is an unbound variable"); 92 | if (!((element instanceof Functor2) && element._name == Atom.DOT)) 93 | // Not a proper list. 94 | return null; 95 | result.push(element._arg1); 96 | element = YP.getValue(element._arg2) 97 | } 98 | 99 | if (result.length <= 0) 100 | return null; 101 | return result; 102 | } 103 | -------------------------------------------------------------------------------- /source/javascript/PrologException.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2007-2008, Jeff Thompson 3 | * 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * * Neither the name of the copyright holder nor the names of its contributors 15 | * may be used to endorse or promote products derived from this software 16 | * without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 22 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | // A PrologException is used as the exception thrown by YP.throw(Term). 32 | // One argument: Create a PrologException with the given arg1 term. The printable exception message is 33 | // the full Term. 34 | // Two arguments: Create a PrologException where the Term is error(arg1, arg2). If arg2 is a string, this 35 | // converts it to an Atom so that Prolog code can use it. 36 | // This uses YP.makeCopy to copy the arguments so that they are valid after unbinding. 37 | function PrologException(arg1, arg2) { 38 | if (arg2 !== undefined) { 39 | arg2 = YP.getValue(arg2); 40 | this._message = arg2.toString(); 41 | if (typeof(arg2) == 'string') 42 | arg2 = Atom.a(arg2); 43 | this._term = YP.makeCopy(new Functor2(Atom.a("error"), arg1, arg2), new Variable.CopyStore()); 44 | } 45 | else if (arg1 !== undefined) { 46 | this._message = YP.getValue(arg1).toString(); 47 | this._term = YP.makeCopy(arg1, new Variable.CopyStore()); 48 | } 49 | } 50 | 51 | PrologException.prototype.toString = function() { 52 | return this._message; 53 | } 54 | 55 | PrologException.TypeErrorInfo = function(Type, Culprit, Message) { 56 | this._Type = Type; 57 | this._Culprit = Culprit; 58 | this._Message = Message; 59 | } 60 | 61 | // Return the TypeErrorInfo for this exception, or null if _term does not match 62 | // error(type_error(Type, Culprit), Message). 63 | PrologException.prototype.getTypeErrorInfo = function() { 64 | if (!(this._term instanceof Functor2 && this._term._name._name == "error")) 65 | return null; 66 | var errorTerm = this._term._arg1; 67 | if (!(errorTerm instanceof Functor2 && errorTerm._name._name == "type_error")) 68 | return null; 69 | if (!(errorTerm._arg1 instanceof Atom)) 70 | return null; 71 | return new PrologException.TypeErrorInfo(errorTerm._arg1, errorTerm._arg2, this._term._arg2); 72 | } 73 | 74 | PrologException.ExistenceErrorInfo = function(Type, Culprit, Message) { 75 | this._Type = Type; 76 | this._Culprit = Culprit; 77 | this._Message = Message; 78 | } 79 | 80 | // If _Type is procedure and _Culprit is name/artity, return the name. Otherwise return null. 81 | PrologException.ExistenceErrorInfo.prototype.getProcedureName = function() { 82 | if (!(this._Type._name == "procedure" && 83 | this._Culprit instanceof Functor2 && this._Culprit._name == Atom.SLASH)) 84 | return null; 85 | return this._Culprit._arg1; 86 | } 87 | 88 | // If _Type is procedure and _Culprit is name/arity and arity is an integer, return the arity. 89 | // Otherwise return -1. 90 | PrologException.ExistenceErrorInfo.prototype.getProcedureArity = function() { 91 | if (!(this._Type._name == "procedure" && 92 | this._Culprit instanceof Functor2 && this._Culprit._name == Atom.SLASH)) 93 | return -1; 94 | if (typeof(this._Culprit._arg2) != "number") 95 | return -1; 96 | return this._Culprit._arg2; 97 | } 98 | 99 | // Return the ExistenceErrorInfo for this exception, or null if _term does not match 100 | // error(existence_error(Type, Culprit), Message). If the returned ExistenceErrorInfo _Culprit is 101 | // procedure, you can use its getProcedureName and getProcedureArity. 102 | PrologException.prototype.getExistenceErrorInfo = function() { 103 | if (!(this._term instanceof Functor2 && this._term._name._name == "error")) 104 | return null; 105 | var errorTerm = this._term._arg1; 106 | if (!(errorTerm instanceof Functor2 && errorTerm._name._name == "existence_error")) 107 | return null; 108 | if (!(errorTerm._arg1 instanceof Atom)) 109 | return null; 110 | return new PrologException.ExistenceErrorInfo(errorTerm._arg1, errorTerm._arg2, this._term._arg2); 111 | } 112 | -------------------------------------------------------------------------------- /source/javascript/Variable.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2007-2008, Jeff Thompson 3 | * 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * * Neither the name of the copyright holder nor the names of its contributors 15 | * may be used to endorse or promote products derived from this software 16 | * without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 22 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | function Variable() { 32 | // Use _isBound separate from _value so that it can be bound to any value, 33 | // including null. 34 | this._isBound = false; 35 | } 36 | 37 | // If this Variable is unbound, then just return this Variable. 38 | // Otherwise, if this has been bound to a value with unify, return the value. 39 | // If the bound value is another Variable, this follows the "variable chain" 40 | // to the end and returns the final value, or the final Variable if it is unbound. 41 | // For more details, see http://yieldprolog.sourceforge.net/tutorial1.html 42 | Variable.prototype.getValue = function() { 43 | if (!this._isBound) 44 | return this; 45 | 46 | var result = this._value; 47 | while (result instanceof Variable) { 48 | if (!result._isBound) 49 | return result; 50 | 51 | // Keep following the Variable chain. 52 | result = result._value; 53 | } 54 | 55 | return result; 56 | } 57 | 58 | // If this Variable is bound, then just call YP.unify to unify this with arg. 59 | // (Note that if arg is an unbound Variable, then YP.unify will bind it to 60 | // this Variable's value.) 61 | // Otherwise, bind this Variable to YP.getValue(arg) and yield once. After the 62 | // yield, return this Variable to the unbound state. 63 | // For more details, see http://yieldprolog.sourceforge.net/tutorial1.html 64 | Variable.prototype.unify = function(arg) { 65 | if (!this._isBound) { 66 | this._value = YP.getValue(arg); 67 | if (this._value == this) 68 | // We are unifying this unbound variable with itself, so leave it unbound. 69 | yield false; 70 | else { 71 | this._isBound = true; 72 | try { 73 | yield false; 74 | } finally { 75 | // Remove the binding. 76 | this._isBound = false; 77 | } 78 | } 79 | } 80 | else { 81 | for each (var l1 in YP.unify(this, arg)) 82 | yield false; 83 | } 84 | } 85 | 86 | Variable.prototype.toString = function() { 87 | var value = this.getValue(); 88 | if (value === this) 89 | return "_Variable"; 90 | else 91 | return value.toString(); 92 | } 93 | 94 | // If bound, call YP.addUniqueVariables on the value. Otherwise, if this unbound 95 | // variable is not already in variableSet, add it. 96 | Variable.prototype.addUniqueVariables = function(variableSet) { 97 | if (this._isBound) 98 | YP.addUniqueVariables(this.getValue(), variableSet); 99 | else { 100 | if (variableSet.indexOf(this) < 0) 101 | variableSet.push(this); 102 | } 103 | } 104 | 105 | // If bound, return YP.makeCopy for the value, else return copyStore.getCopy(this). 106 | // However, if copyStore is null, just return this. 107 | Variable.prototype.makeCopy = function(copyStore) { 108 | if (this._isBound) 109 | return YP.makeCopy(this.getValue(), copyStore); 110 | else 111 | return copyStore == null ? this : copyStore.getCopy(this); 112 | } 113 | 114 | Variable.prototype.termEqual = function(term) { 115 | if (this._isBound) 116 | return YP.termEqual(this.getValue(), term); 117 | else 118 | return this === YP.getValue(term); 119 | } 120 | 121 | Variable.prototype.ground = function() { 122 | if (this._isBound) 123 | // This is usually called by YP.ground which already did getValue, so this 124 | // should never be reached, but check anyway. 125 | return YP.ground(this.getValue()); 126 | else 127 | return false; 128 | } 129 | 130 | // A CopyStore is used by makeCopy to track which Variable objects have 131 | // been copied. 132 | Variable.CopyStore = function() { 133 | this._inVariableList = [] 134 | this._outVariableList = [] 135 | } 136 | 137 | // If inVariable has already been copied, return its copy. Otherwise, 138 | // return a fresh Variable associated with inVariable. 139 | Variable.CopyStore.prototype.getCopy = function(inVariable) { 140 | var index = this._inVariableList.indexOf(inVariable); 141 | if (index >= 0) 142 | return this._outVariableList[index]; 143 | else { 144 | var outVariable = new Variable(); 145 | this._inVariableList.push(inVariable); 146 | this._outVariableList.push(outVariable); 147 | return outVariable; 148 | } 149 | } 150 | 151 | // Return the number of unique variables that have been copied. 152 | Variable.CopyStore.prototype.getNUniqueVariables = function() { 153 | return this._inVariableList.length; 154 | } 155 | -------------------------------------------------------------------------------- /source/javascript/endComment.js: -------------------------------------------------------------------------------- 1 | */ 2 | -------------------------------------------------------------------------------- /source/javascript/examples/Benchmarks/isoTestSuite.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /source/javascript/examples/Benchmarks/naiveQueens.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /source/javascript/examples/Benchmarks/naiveQueens.js: -------------------------------------------------------------------------------- 1 | function main() { 2 | var startTime = new Date().getTime(); 3 | var nAnswers = 0; 4 | var Qs = new Variable(); 5 | for each (var l1 in queens(11, Qs)) 6 | nAnswers += 1; 7 | var finishTime = new Date().getTime(); 8 | document.write("Naive queens: " + 9 | (finishTime - startTime) / 1000.0 + " seconds, " + 10 | nAnswers + " answers
"); 11 | } 12 | 13 | function queens(N, Qs) { 14 | var Ns = new Variable(); 15 | for each (var l1 in rangeList(1, N, Ns)) { 16 | for each (var l2 in queens3(Ns, Atom.NIL, Qs)) 17 | yield false; 18 | } 19 | } 20 | 21 | function queens3(UnplacedQs, SafeQs, Qs) { 22 | var UnplacedQs1 = new Variable(); 23 | var Q = new Variable(); 24 | for each (var l1 in selectq(Q, UnplacedQs, UnplacedQs1)) { 25 | for each (var l2 in notHasAttack(Q, SafeQs)) { 26 | for each (var l3 in queens3(UnplacedQs1, new ListPair(Q, SafeQs), Qs)) 27 | yield false; 28 | } 29 | } 30 | for each (var l1 in YP.unify(UnplacedQs, Atom.NIL)) { 31 | for each (var l2 in YP.unify(Qs, SafeQs)) 32 | yield false; 33 | } 34 | } 35 | 36 | function notHasAttack(X, Xs) { 37 | for each (var l1 in attack(X, Xs)) 38 | return; 39 | 40 | yield false; 41 | } 42 | 43 | function attack(X, Xs) { 44 | for each (var l1 in attack3(X, 1, Xs)) 45 | yield false; 46 | } 47 | 48 | function attack3(X, N, Arg3) { 49 | var Y = new Variable(); 50 | for each (var l1 in new ListPair(Y, new Variable()).unify(Arg3)) { 51 | if (YP.getValue(X) == Y.getValue() + YP.getValue(N)) 52 | yield false; 53 | if (YP.getValue(X) == Y.getValue() - YP.getValue(N)) 54 | yield false; 55 | } 56 | 57 | var Ys = new Variable(); 58 | var N1 = new Variable(); 59 | for each (var l1 in new ListPair(new Variable(), Ys).unify(Arg3)) { 60 | for each (var l2 in N1.unify(YP.getValue(N) + 1)) { 61 | for each (var l3 in attack3(X, N1, Ys)) 62 | yield false; 63 | } 64 | } 65 | } 66 | 67 | function rangeList(M, N, List) { 68 | if (YP.getValue(M) >= YP.getValue(N)) { 69 | for each (var l1 in YP.unify(List, new ListPair(N, Atom.NIL))) 70 | yield false; 71 | } 72 | else { 73 | var Tail = new Variable(); 74 | for each (var l1 in rangeList(YP.getValue(M) + 1, YP.getValue(N), Tail)) { 75 | for each (var l2 in YP.unify(List, new ListPair(M, Tail))) 76 | yield false; 77 | } 78 | } 79 | } 80 | 81 | function selectq(X, Arg2, Arg3) { 82 | for each (var l1 in new ListPair(X, Arg3).unify(Arg2)) 83 | yield false; 84 | 85 | var Y = new Variable(); 86 | var Ys = new Variable(); 87 | var Zs = new Variable(); 88 | for each (var l1 in new ListPair(Y, Ys).unify(Arg2)) { 89 | for each (var l2 in new ListPair(Y, Zs).unify(Arg3)) { 90 | for each (var l3 in selectq(X, Ys, Zs)) 91 | yield false; 92 | } 93 | } 94 | } 95 | 96 | main() 97 | -------------------------------------------------------------------------------- /source/javascript/examples/Benchmarks/queens.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /source/javascript/examples/Benchmarks/queens.js: -------------------------------------------------------------------------------- 1 | function main() { 2 | var startTime = new Date().getTime(); 3 | var nAnswers = 0; 4 | var Qs = new Variable(); 5 | for each (var l1 in queens(11, Qs)) 6 | nAnswers += 1; 7 | var finishTime = new Date().getTime(); 8 | document.write("Optimized queens: " + 9 | (finishTime - startTime) / 1000.0 + " seconds, " + 10 | nAnswers + " answers
"); 11 | } 12 | 13 | function queens(N, Qs) { 14 | var Ns = new Variable(); 15 | for each (var l1 in rangeList(1, N, Ns)) { 16 | for each (var l2 in queens3(Ns, Atom.NIL, Qs)) 17 | yield false; 18 | } 19 | } 20 | 21 | function queens3(UnplacedQs, SafeQs, Qs) { 22 | var UnplacedQsListPair = YP.getValue(UnplacedQs); 23 | if (UnplacedQsListPair instanceof ListPair) { 24 | var UnplacedQs1 = new Variable(); 25 | var Q = new Variable(); 26 | for each (var l1 in selectq(Q, UnplacedQsListPair, UnplacedQs1)) { 27 | if (!((SafeQs instanceof ListPair) && hasAttack(Q.getValue(), SafeQs))) { 28 | for each (var l2 in queens3(UnplacedQs1, new ListPair(Q, SafeQs), Qs)) 29 | yield false; 30 | } 31 | } 32 | } 33 | else { 34 | for each (var l1 in Qs.unify(SafeQs)) 35 | yield false; 36 | } 37 | } 38 | 39 | function hasAttack(X, Xs) { 40 | return hasAttack3(X, 1, Xs); 41 | } 42 | 43 | function hasAttack3(X, N, Arg3) { 44 | if (X == YP.getValue(Arg3._arg1) + N || X == YP.getValue(Arg3._arg1) - N) 45 | return true; 46 | if (Arg3._arg2 instanceof ListPair) 47 | return hasAttack3(X, N + 1, YP.getValue(Arg3._arg2)); 48 | else 49 | return false; 50 | } 51 | 52 | function rangeList(M, N, List) { 53 | if (M >= N) { 54 | for each (var l1 in List.unify(new ListPair(N, Atom.NIL))) 55 | yield false; 56 | } 57 | else { 58 | var Tail = new Variable(); 59 | for each (var l1 in rangeList(M + 1, N, Tail)) { 60 | for each (var l2 in List.unify(new ListPair(M, Tail))) 61 | yield false; 62 | } 63 | } 64 | } 65 | 66 | function selectq(X, Arg2, Arg3) { 67 | for each (var l1 in X.unify(Arg2._arg1)) { 68 | for each (var l2 in Arg3.unify(Arg2._arg2)) 69 | yield false; 70 | } 71 | 72 | var Arg2Tail = YP.getValue(Arg2._arg2); 73 | if (Arg2Tail instanceof ListPair) { 74 | var Zs = new Variable(); 75 | for each (var l1 in selectq(X, Arg2Tail, Zs)) { 76 | for each (var l2 in Arg3.unify(new ListPair(Arg2._arg1, Zs))) 77 | yield false; 78 | } 79 | } 80 | } 81 | 82 | main(); 83 | 84 | 85 | -------------------------------------------------------------------------------- /source/javascript/examples/YieldPrologTutorial/tutorial1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /source/javascript/examples/YieldPrologTutorial/tutorial2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /source/javascript/examples/YieldPrologTutorial/tutorial2.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2007-2008, Jeff Thompson 3 | * 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * * Neither the name of the copyright holder nor the names of its contributors 15 | * may be used to endorse or promote products derived from this software 16 | * without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 22 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | function main() { 32 | document.write("Find relations:
"); 33 | var Brother = new Variable(); 34 | for each (var l1 in brother("Hillary", Brother)) 35 | document.write("Hillary has brother " + 36 | Brother.getValue() + ".
"); 37 | 38 | document.write("Check if it is square:
"); 39 | for each (var l1 in squaredRectangle(10, 10)) 40 | document.write("10 by 10 rectangle is square.
"); 41 | 42 | document.write("Make it square:
"); 43 | var Width = new Variable(); 44 | var Height = new Variable(); 45 | for each (var l1 in Width.unify(10)) { 46 | for each (var l2 in squaredRectangle(Width, Height)) 47 | document.write("A square of width " + 48 | Width.getValue() + " has height " + 49 | Height.getValue() + ".
"); 50 | } 51 | 52 | document.write("Make it square before we know the width:
"); 53 | for each (var l1 in squaredRectangle(Width, Height)) { 54 | for each (var l2 in Width.unify(10)) 55 | document.write("A square of width " + 56 | Width.getValue() + " has height " + 57 | Height.getValue() + ".
"); 58 | } 59 | 60 | document.write("Get one match:
"); 61 | for each (var l1 in anyBrother("Hillary", Brother)) 62 | document.write("Hillary has a brother " + 63 | Brother.getValue() + ".
"); 64 | for each (var l1 in anyBrother("Bill", Brother)) 65 | document.write("Bill has a brother " + 66 | Brother.getValue() + ".
"); 67 | 68 | document.write("Use cut for negation:
"); 69 | for each (var l1 in noBrother("Hillary")) 70 | document.write("Hillary has no brother.
"); 71 | for each (var l1 in noBrother("Chelsea")) 72 | document.write("Chelsea has no brother.
"); 73 | } 74 | 75 | function brother(Person, Brother) { 76 | for each (var l1 in YP.unify(Person, "Hillary")) { 77 | for each (var l2 in YP.unify(Brother, "Tony")) 78 | yield false; 79 | for each (var l2 in YP.unify(Brother, "Hugh")) 80 | yield false; 81 | } 82 | for each (var l1 in YP.unify(Person, "Bill")) { 83 | for each (var l2 in YP.unify(Brother, "Roger")) 84 | yield false; 85 | } 86 | } 87 | 88 | function squaredRectangle(Width, Height) { 89 | for each (var l1 in YP.unify(Width, Height)) 90 | yield false; 91 | } 92 | 93 | function anyBrother(Person, Brother) { 94 | for each (var l1 in brother(Person, Brother)) { 95 | yield false; 96 | break; 97 | } 98 | } 99 | 100 | function noBrother(Person) { 101 | var Brother = new Variable(); 102 | for each (var l1 in brother(Person, Brother)) 103 | return; 104 | yield false; 105 | } 106 | 107 | main(); 108 | 109 | 110 | -------------------------------------------------------------------------------- /source/javascript/examples/YieldPrologTutorial/tutorial3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /source/javascript/examples/YieldPrologTutorial/tutorial3.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2007-2008, Jeff Thompson 3 | * 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * * Neither the name of the copyright holder nor the names of its contributors 15 | * may be used to endorse or promote products derived from this software 16 | * without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 22 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | function main() { 32 | document.write("Return a list of 2 elements:
"); 33 | var List = new Variable(); 34 | for each (var l1 in makeList("a", "b", List)) 35 | document.write("List = " + 36 | List.getValue() + ".
"); 37 | 38 | document.write("Unify two lists:
"); 39 | var Second = new Variable(); 40 | for each (var l1 in makeList("x", Second, 41 | new ListPair("x", new ListPair("y", Atom.NIL)))) 42 | document.write("The second element is " + 43 | Second.getValue() + ".
"); 44 | } 45 | 46 | function makeList(First, Second, List) { 47 | var list1 = new ListPair(Second, Atom.NIL); 48 | var result = new ListPair(First, list1); 49 | for each (var l1 in YP.unify(List, result)) 50 | yield false; 51 | } 52 | 53 | main(); 54 | 55 | 56 | -------------------------------------------------------------------------------- /source/javascript/examples/YieldPrologTutorial/tutorial4.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /source/javascript/examples/YieldPrologTutorial/tutorial4.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2007-2008, Jeff Thompson 3 | * 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * * Neither the name of the copyright holder nor the names of its contributors 15 | * may be used to endorse or promote products derived from this software 16 | * without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 22 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | function main() { 32 | YP.assertFact(Atom.a("brother"), 33 | [Atom.a("Hillary"), Atom.a("Hugh")]); 34 | YP.assertFact(Atom.a("brother"), 35 | [Atom.a("Hillary"), Atom.a("Tony")]); 36 | YP.assertFact(Atom.a("brother"), 37 | [Atom.a("Bill"), Atom.a("Roger")]); 38 | 39 | var Brother = new Variable(); 40 | document.write("Using dynamic assert:
"); 41 | for each (var l1 in YP.matchDynamic 42 | (Atom.a("brother"), 43 | [Atom.a("Hillary"), Brother])) 44 | document.write("Hillary has brother " + 45 | Brother.getValue() + ".
"); 46 | 47 | var prologCode = 48 | "uncle(Person, Uncle) :- \n" + 49 | " parent(Person, Parent), \n" + 50 | " brother(Parent, Uncle). \n"; 51 | document.write("
// Compiled code:
"); 52 | compileAndWrite(prologCode); 53 | 54 | prologCode = 55 | ":- import('', [parent/2]). \n" + 56 | "uncle(Person, Uncle) :- \n" + 57 | " parent(Person, Parent), \n" + 58 | " brother(Parent, Uncle). \n"; 59 | document.write("// Calling an imported function:
"); 60 | compileAndWrite(prologCode); 61 | 62 | prologCode = 63 | "parent('Chelsea', 'Hillary'). \n" + 64 | "parent('Chelsea', 'Bill'). \n" + 65 | 66 | "uncle(Person, Uncle) :- \n" + 67 | " parent(Person, Parent), \n" + 68 | " brother(Parent, Uncle). \n"; 69 | document.write("// Calling a locally-defined function:
"); 70 | compileAndWrite(prologCode); 71 | 72 | prologCode = 73 | ":- import('', [parent/2]). \n" + 74 | "uncle(Person, Uncle) :- \n" + 75 | " Goal = parent(Person, Parent), \n" + 76 | " Goal, \n" + 77 | " brother(Parent, Uncle). \n"; 78 | document.write("// Calling a dynamic goal:
"); 79 | compileAndWrite(prologCode); 80 | 81 | document.write 82 | ("Calling compiled code having a dynamic goal:
"); 83 | var Person = new Variable(); 84 | var Uncle = new Variable(); 85 | for each (var l1 in uncle(Person, Uncle)) 86 | document.write(Person.getValue() + 87 | " has uncle " + Uncle.getValue() + ".
"); 88 | } 89 | 90 | function compileAndWrite(prologCode) { 91 | YP.see(new YP.StringReader(prologCode)); 92 | var output = new YP.StringWriter(); 93 | YP.tell(output); 94 | var TermList = new Variable(); 95 | var PseudoCode = new Variable(); 96 | for each (var l1 in parseInput(TermList)) { 97 | for each (var l2 in makeFunctionPseudoCode 98 | (TermList, PseudoCode)) 99 | convertFunctionJavascript(PseudoCode); 100 | } 101 | YP.seen(); 102 | YP.told(); 103 | document.write 104 | (output.toString().replace 105 | (/\n/g,"
").replace(/ /g," ")); 106 | } 107 | 108 | function getDeclaringClass() { return null; } 109 | 110 | function parent(Person, Parent) { 111 | for each (var l2 in YP.unify 112 | (Person, Atom.a("Chelsea"))) { 113 | for each (var l3 in YP.unify 114 | (Parent, Atom.a("Hillary"))) { 115 | yield false; 116 | } 117 | } 118 | for each (var l2 in YP.unify 119 | (Person, Atom.a("Chelsea"))) { 120 | for each (var l3 in YP.unify 121 | (Parent, Atom.a("Bill"))) { 122 | yield false; 123 | } 124 | } 125 | } 126 | 127 | function uncle(Person, Uncle) { 128 | { 129 | var Goal = new Variable(); 130 | var Parent = new Variable(); 131 | for each (var l2 in YP.unify 132 | (Goal, new Functor2 133 | (Atom.a("parent", Atom.a("")), 134 | Person, Parent))) { 135 | for each (var l3 in YP.getIterator 136 | (Goal, getDeclaringClass())) { 137 | for each (var l4 in YP.matchDynamic 138 | (Atom.a("brother"), [Parent, Uncle])) { 139 | yield false; 140 | } 141 | } 142 | } 143 | } 144 | } 145 | 146 | main(); 147 | 148 | 149 | -------------------------------------------------------------------------------- /source/javascript/makeYieldProlog.bat: -------------------------------------------------------------------------------- 1 | copy /B readme.js + makeYieldProlog.bat + endComment.js + ^ 2 | YP.js + ^ 3 | Variable.js + ^ 4 | Atom.js + ^ 5 | Functor1.js + ^ 6 | Functor2.js + ^ 7 | Functor3.js + ^ 8 | Functor.js + ^ 9 | ListPair.js + ^ 10 | PrologException.js + ^ 11 | IndexedAnswers.js + ^ 12 | FindallAnswers.js + ^ 13 | BagofAnswers.js + ^ 14 | Parser.js + ^ 15 | Compiler.js ^ 16 | YieldProlog.js 17 | rem Copy the result to the web interface and bin. 18 | copy YieldProlog.js ..\..\doc 19 | copy YieldProlog.js ..\..\bin 20 | copy ..\..\doc\queryEditor.html ..\..\bin 21 | -------------------------------------------------------------------------------- /source/javascript/readme.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2007-2008, Jeff Thompson 3 | * 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * * Neither the name of the copyright holder nor the names of its contributors 15 | * may be used to endorse or promote products derived from this software 16 | * without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 22 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | This file is a concatenation of all the source files for Yield Prolog so 31 | that you only need to include one file. 32 | 33 | This file was created with the following script (see file "makeYieldProlog.bat"): 34 | -------------------------------------------------------------------------------- /source/python/Atom.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2007-2008, Jeff Thompson 2 | # 3 | # All rights reserved. 4 | # 5 | # Redistribution and use in source and binary forms, with or without 6 | # modification, are permitted provided that the following conditions are met: 7 | # 8 | # * Redistributions of source code must retain the above copyright 9 | # notice, this list of conditions and the following disclaimer. 10 | # * Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer in the 12 | # documentation and/or other materials provided with the distribution. 13 | # * Neither the name of the copyright holder nor the names of its contributors 14 | # may be used to endorse or promote products derived from this software 15 | # without specific prior written permission. 16 | # 17 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 21 | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 22 | # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 | # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 24 | # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 25 | # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 26 | # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | import StringIO 30 | from YP import * 31 | from Variable import * 32 | 33 | class Atom(IUnifiable): 34 | # You should not call this constructor, but use Atom.a(name) instead. 35 | def __init__(self, name, module = None): 36 | self._name = name 37 | self._module = module 38 | 39 | # Return an Atom object with the name and module. If module is null or Atom.NIL, 40 | # this behaves like Atom.a(name, None) and returns the unique object where the module is None. 41 | # If module is None or Atom.NIL, return a unique Atom object. 42 | # If module is not None or Atom.NIL, this may or may not be the same object as another Atom 43 | # with the same name and module. 44 | # You should use this to create an Atom instead of calling the Atom constructor. 45 | @staticmethod 46 | def a(name, module = None): 47 | if module == None or module == Atom.NIL: 48 | atom = Atom._atomStore.get(name, False) 49 | if atom == False: 50 | atom = Atom(name) 51 | Atom._atomStore[name] = atom 52 | return atom 53 | else: 54 | return Atom(name, module) 55 | 56 | # If Obj is an Atom unify its _module with Module. If the Atom's _module is None, use Atom.NIL. 57 | @staticmethod 58 | def module(Obj, Module): 59 | Obj = YP.getValue(Obj) 60 | if isinstance(Obj, Atom): 61 | if Obj._module == None: 62 | return YP.unify(Module, Atom.NIL) 63 | else: 64 | return YP.unify(Module, Obj._module) 65 | 66 | return YP.fail() 67 | 68 | def unify(self, arg): 69 | arg = YP.getValue(arg) 70 | if isinstance(arg, Atom): 71 | if self.equals(arg): 72 | return YP.succeed() 73 | else: 74 | return YP.fail() 75 | elif isinstance(arg, Variable): 76 | return arg.unify(self) 77 | else: 78 | return YP.fail() 79 | 80 | def addUniqueVariables(self, variableSet): 81 | # Atom does not contain variables. 82 | pass 83 | 84 | def makeCopy(self, copyStore): 85 | # Atom does not contain variables that need to be copied. 86 | return self 87 | 88 | def termEqual(self, term): 89 | return self.equals(YP.getValue(term)) 90 | 91 | def ground(self): 92 | # Atom is always ground. 93 | return True 94 | 95 | def equals(self, obj): 96 | if isinstance(obj, Atom): 97 | if self._module == None and obj._module == None: 98 | # When _declaringClass is None, we always use an identical object from _atomStore. 99 | return self == obj 100 | # Otherwise, ignore _declaringClass and do a normal string compare on the _name. 101 | return self._name == obj._name 102 | 103 | return False 104 | 105 | def __str__(self): 106 | return self._name 107 | 108 | def __hash__(self): 109 | return hash(self._name) 110 | 111 | def toQuotedString(self): 112 | if len(self._name) == 0: 113 | return "''" 114 | elif self == Atom.NIL: 115 | return "[]" 116 | 117 | result = StringIO.StringIO() 118 | useQuotes = False 119 | for c in self._name: 120 | cInt = ord(c) 121 | if c == '\'': 122 | result.write("''") 123 | useQuotes = True 124 | elif c == '_' or cInt >= ord('a') and cInt <= ord('z') or \ 125 | cInt >= ord('A') and cInt <= ord('Z') or cInt >= ord('0') and cInt <= ord('9'): 126 | result.write(c) 127 | else: 128 | # Debug: Need to handle non-printable chars. 129 | result.write(c) 130 | useQuotes = True 131 | 132 | if not useQuotes and ord(self._name[0]) >= ord('a') and ord(self._name[0]) <= ord('z'): 133 | return result.getvalue() 134 | else: 135 | # Surround in single quotes. 136 | result.write('\'') 137 | return "'" + result.getvalue() 138 | 139 | # Return true if _name is lexicographically less than atom._name. 140 | def lessThan(self, atom): 141 | return self._name < atom._name 142 | 143 | _atomStore = {} 144 | 145 | # We will set these below after Atom is defined 146 | NIL = None 147 | DOT = None 148 | F = None 149 | SLASH = None 150 | HAT = None 151 | RULE = None 152 | TRUE = None 153 | 154 | Atom.NIL = Atom.a("[]") 155 | Atom.DOT = Atom.a(".") 156 | Atom.F = Atom.a("f") 157 | Atom.SLASH = Atom.a("/") 158 | Atom.HAT = Atom.a("^") 159 | Atom.RULE = Atom.a(":-") 160 | Atom.TRUE = Atom.a("true") 161 | -------------------------------------------------------------------------------- /source/python/FindallAnswers.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2007-2008, Jeff Thompson 2 | # 3 | # All rights reserved. 4 | # 5 | # Redistribution and use in source and binary forms, with or without 6 | # modification, are permitted provided that the following conditions are met: 7 | # 8 | # * Redistributions of source code must retain the above copyright 9 | # notice, this list of conditions and the following disclaimer. 10 | # * Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer in the 12 | # documentation and/or other materials provided with the distribution. 13 | # * Neither the name of the copyright holder nor the names of its contributors 14 | # may be used to endorse or promote products derived from this software 15 | # without specific prior written permission. 16 | # 17 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 21 | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 22 | # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 | # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 24 | # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 25 | # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 26 | # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | from YP import * 30 | from ListPair import * 31 | from Variable import * 32 | 33 | # A FindallAnswers holds answers for findall. 34 | class FindallAnswers(object): 35 | def __init__(self, Template): 36 | self._template = Template; 37 | self._bagArray = []; 38 | 39 | def add(self): 40 | self._bagArray.append(YP.makeCopy(self._template, Variable.CopyStore())) 41 | 42 | def resultArray(self): 43 | return self._bagArray 44 | 45 | # Unify Bag with the result. This frees the internal answers, so you can only call this once. 46 | def result(self, Bag): 47 | value = ListPair.make(self._bagArray) 48 | # Try to free the memory. 49 | self._bagArray = None 50 | return YP.unify(Bag, value) 51 | 52 | # This is a simplified findall when the goal is a single call. 53 | @staticmethod 54 | def findall(Template, goal, Bag): 55 | findallAnswers = FindallAnswers(Template) 56 | for l1 in goal: 57 | findallAnswers.add() 58 | return findallAnswers.result(Bag) 59 | 60 | # Like findall, except return an array of the results. 61 | @staticmethod 62 | def findallArray(Template, goal): 63 | findallAnswers = FindallAnswers(Template) 64 | for l1 in goal: 65 | findallAnswers.add() 66 | return findallAnswers.resultArray() 67 | 68 | -------------------------------------------------------------------------------- /source/python/Functor.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2007-2008, Jeff Thompson 2 | # 3 | # All rights reserved. 4 | # 5 | # Redistribution and use in source and binary forms, with or without 6 | # modification, are permitted provided that the following conditions are met: 7 | # 8 | # * Redistributions of source code must retain the above copyright 9 | # notice, this list of conditions and the following disclaimer. 10 | # * Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer in the 12 | # documentation and/or other materials provided with the distribution. 13 | # * Neither the name of the copyright holder nor the names of its contributors 14 | # may be used to endorse or promote products derived from this software 15 | # without specific prior written permission. 16 | # 17 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 21 | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 22 | # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 | # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 24 | # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 25 | # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 26 | # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | from YP import * 30 | from Atom import * 31 | from Functor1 import * 32 | from Functor2 import * 33 | from Functor3 import * 34 | from Variable import * 35 | 36 | class Functor(IUnifiable): 37 | def __init__(self, name, args): 38 | if len(args) <= 3: 39 | if len(args) == 0: 40 | raise Exception("For arity 0 functor, just use name as an Atom") 41 | elif len(args) == 1: 42 | raise Exception("For arity 1 functor, use Functor1") 43 | elif len(args) == 2: 44 | raise Exception("For arity 2 functor, use Functor2") 45 | elif len(args) == 3: 46 | raise Exception("For arity 3 functor, use Functor3") 47 | else: 48 | # (This shouldn't happen, but include it for completeness. 49 | raise Exception("Cannot create a Functor of arity " + str(len(args))) 50 | 51 | if isinstance(name, Atom): 52 | self._name = name 53 | else: 54 | # Assume name is a string. 55 | self._name = Atom.a(name) 56 | self._args = args 57 | 58 | 59 | # Return an Atom, Functor1, Functor2, Functor3 or Functor depending on the 60 | # length of args. 61 | # Note that this is different than the Functor constructor which requires 62 | # the length of args to be greater than 3. 63 | @staticmethod 64 | def make(name, args): 65 | if not isinstance(name, Atom): 66 | # Assume name is a string. 67 | name = Atom.a(name) 68 | 69 | if len(args) <= 0: 70 | return name 71 | elif len(args) == 1: 72 | return Functor1(name, args[0]) 73 | elif len(args) == 2: 74 | return Functor2(name, args[0], args[1]) 75 | elif len(args) == 3: 76 | return Functor3(name, args[0], args[1], args[2]) 77 | else: 78 | return Functor(name, args) 79 | 80 | # If arg is another Functor, then succeed (yield once) if this and arg have the 81 | # same name and all functor args unify, otherwise fail (don't yield). 82 | # If arg is a Variable, then call its unify to unify with this. 83 | # Otherwise fail (don't yield). 84 | def unify(self, arg): 85 | arg = YP.getValue(arg) 86 | if isinstance(arg, Functor): 87 | if self._name.equals(arg._name): 88 | return YP.unifyArrays(self._args, arg._args) 89 | else: 90 | return YP.fail() 91 | elif isinstance(arg, Variable): 92 | return arg.unify(self) 93 | else: 94 | return YP.fail() 95 | 96 | def __str__(self): 97 | result = str(self._name) + "(" + str(YP.getValue(self._args[0])) 98 | for i in range(1, len(self._args)): 99 | result += ", " + str(YP.getValue(self._args[i])) 100 | result += ")" 101 | return result 102 | 103 | def termEqual(self, term): 104 | term = YP.getValue(term) 105 | if isinstance(term, Functor1): 106 | if self._name.equals(term._name) and len(self._args) == len(term._arg): 107 | for i in range(0, len(self._args)): 108 | if not YP.termEqual(self._args[i], term._args[i]): 109 | return False 110 | return True 111 | return False 112 | 113 | def lessThan(self, functor): 114 | # Do the equal check first since it is faster. 115 | if not self._name.equals(functor._name): 116 | return _name.lessThan(functor._name) 117 | 118 | if len(self._args) != len(functor._args): 119 | return len(self._args) < len(functor._args) 120 | 121 | for i in range(0, len(self._args)): 122 | if not YP.termEqual(self._args[i], functor._args[i]): 123 | return YP.termLessThan(self._args[i], functor._args[i]) 124 | return False 125 | 126 | def ground(self): 127 | for i in range(0, len(self._args)): 128 | if not YP.ground(self._args[i]): 129 | return False 130 | return True 131 | 132 | def addUniqueVariables(self, variableSet): 133 | for i in range(0, len(self._args)): 134 | YP.addUniqueVariables(self._args[i], variableSet) 135 | 136 | def makeCopy(self, copyStore): 137 | argsCopy = [YP.makeCopy(arg, copyStore) for arg in self._args] 138 | return Functor(self._name, argsCopy) 139 | -------------------------------------------------------------------------------- /source/python/Functor1.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2007-2008, Jeff Thompson 2 | # 3 | # All rights reserved. 4 | # 5 | # Redistribution and use in source and binary forms, with or without 6 | # modification, are permitted provided that the following conditions are met: 7 | # 8 | # * Redistributions of source code must retain the above copyright 9 | # notice, this list of conditions and the following disclaimer. 10 | # * Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer in the 12 | # documentation and/or other materials provided with the distribution. 13 | # * Neither the name of the copyright holder nor the names of its contributors 14 | # may be used to endorse or promote products derived from this software 15 | # without specific prior written permission. 16 | # 17 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 21 | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 22 | # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 | # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 24 | # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 25 | # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 26 | # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | from YP import * 30 | from Variable import * 31 | from Atom import * 32 | 33 | class Functor1(IUnifiable): 34 | def __init__(self, name, arg1): 35 | if isinstance(name, Atom): 36 | self._name = name 37 | else: 38 | self._name = Atom.a(name) 39 | self._arg1 = arg1 40 | 41 | # If arg is another Functor1, then succeed (yield once) if this and arg have the 42 | # same name and the functor args unify, otherwise fail (don't yield). 43 | # If arg is a Variable, then call its unify to unify with this. 44 | # Otherwise fail (don't yield). 45 | def unify(self, arg): 46 | arg = YP.getValue(arg) 47 | if isinstance(arg, Functor1): 48 | if self._name.equals(arg._name): 49 | for l1 in YP.unify(self._arg1, arg._arg1): 50 | yield False 51 | elif isinstance(arg, Variable): 52 | for l1 in arg.unify(self): 53 | yield False 54 | 55 | def __str__(self): 56 | return str(self._name) + "(" + str(YP.getValue(self._arg1)) + ")" 57 | 58 | def termEqual(self, term): 59 | term = YP.getValue(term) 60 | if isinstance(term, Functor1): 61 | return self._name.equals(term._name) and YP.termEqual(self._arg1, term._arg1) 62 | return False 63 | 64 | def lessThan(self, functor): 65 | # Do the equal check first since it is faster. 66 | if not self._name.equals(functor._name): 67 | return self._name.lessThan(functor._name) 68 | 69 | return YP.termLessThan(self._arg1, functor._arg1) 70 | 71 | def ground(self): 72 | return YP.ground(self._arg1) 73 | 74 | def addUniqueVariables(self, variableSet): 75 | YP.addUniqueVariables(self._arg1, variableSet) 76 | 77 | def makeCopy(self, copyStore): 78 | return Functor1(self._name, YP.makeCopy(self._arg1, copyStore)) 79 | -------------------------------------------------------------------------------- /source/python/Functor2.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2007-2008, Jeff Thompson 2 | # 3 | # All rights reserved. 4 | # 5 | # Redistribution and use in source and binary forms, with or without 6 | # modification, are permitted provided that the following conditions are met: 7 | # 8 | # * Redistributions of source code must retain the above copyright 9 | # notice, this list of conditions and the following disclaimer. 10 | # * Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer in the 12 | # documentation and/or other materials provided with the distribution. 13 | # * Neither the name of the copyright holder nor the names of its contributors 14 | # may be used to endorse or promote products derived from this software 15 | # without specific prior written permission. 16 | # 17 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 21 | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 22 | # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 | # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 24 | # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 25 | # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 26 | # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | from YP import * 30 | from Variable import * 31 | from Atom import * 32 | 33 | class Functor2(IUnifiable): 34 | def __init__(self, name, arg1, arg2): 35 | if isinstance(name, Atom): 36 | self._name = name 37 | else: 38 | self._name = Atom.a(name) 39 | self._arg1 = arg1 40 | self._arg2 = arg2 41 | 42 | # If arg is another Functor2, then succeed (yield once) if this and arg have the 43 | # same name and all functor args unify, otherwise fail (don't yield). 44 | # If arg is a Variable, then call its unify to unify with this. 45 | # Otherwise fail (don't yield). 46 | def unify(self, arg): 47 | arg = YP.getValue(arg) 48 | if isinstance(arg, Functor2): 49 | if self._name.equals(arg._name): 50 | for l1 in YP.unify(self._arg1, arg._arg1): 51 | for l2 in YP.unify(self._arg2, arg._arg2): 52 | yield False 53 | elif isinstance(arg, Variable): 54 | for l1 in arg.unify(self): 55 | yield False 56 | 57 | def __str__(self): 58 | if self._name == Atom.DOT: 59 | return Functor2.listPairToString(self) 60 | else: 61 | return str(self._name) + "(" + str(YP.getValue(self._arg1)) + ", " + \ 62 | str(YP.getValue(self._arg2)) + ")" 63 | 64 | def termEqual(self, term): 65 | term = YP.getValue(term) 66 | if isinstance(term, Functor2): 67 | return self._name.equals(term._name) and YP.termEqual(self._arg1, term._arg1) \ 68 | and YP.termEqual(self._arg2, term._arg2) 69 | return False 70 | 71 | def lessThan(self, functor): 72 | # Do the equal check first since it is faster. 73 | if not self._name.equals(functor._name): 74 | return self._name.lessThan(functor._name) 75 | 76 | if not YP.termEqual(self._arg1, functor._arg1): 77 | return YP.termLessThan(self._arg1, functor._arg1) 78 | 79 | return YP.termLessThan(self._arg2, functor._arg2) 80 | 81 | def ground(self): 82 | return YP.ground(self._arg1) and YP.ground(self._arg2) 83 | 84 | def addUniqueVariables(self, variableSet): 85 | YP.addUniqueVariables(self._arg1, variableSet) 86 | YP.addUniqueVariables(self._arg2, variableSet) 87 | 88 | def makeCopy(self, copyStore): 89 | return Functor2(self._name, YP.makeCopy(self._arg1, copyStore), \ 90 | YP.makeCopy(self._arg2, copyStore)) 91 | 92 | @staticmethod 93 | def listPairToString(listPair): 94 | result = "[" 95 | while True: 96 | head = YP.getValue(listPair._arg1) 97 | tail = YP.getValue(listPair._arg2) 98 | if tail == Atom.NIL: 99 | result += str(head) 100 | break 101 | elif isinstance(tail, Functor2) and tail._name == Atom.DOT: 102 | result += str(head) + ", " 103 | listPair = tail 104 | # Loop again. 105 | else: 106 | # The list is not terminated with NIL. 107 | result += str(head) + "|" + str(tail) 108 | break 109 | 110 | result += "]" 111 | return result 112 | -------------------------------------------------------------------------------- /source/python/Functor3.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2007-2008, Jeff Thompson 2 | # 3 | # All rights reserved. 4 | # 5 | # Redistribution and use in source and binary forms, with or without 6 | # modification, are permitted provided that the following conditions are met: 7 | # 8 | # * Redistributions of source code must retain the above copyright 9 | # notice, this list of conditions and the following disclaimer. 10 | # * Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer in the 12 | # documentation and/or other materials provided with the distribution. 13 | # * Neither the name of the copyright holder nor the names of its contributors 14 | # may be used to endorse or promote products derived from this software 15 | # without specific prior written permission. 16 | # 17 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 21 | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 22 | # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 | # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 24 | # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 25 | # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 26 | # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | from YP import * 30 | from Variable import * 31 | from Atom import * 32 | 33 | class Functor3(IUnifiable): 34 | def __init__(self, name, arg1, arg2, arg3): 35 | if isinstance(name, Atom): 36 | self._name = name 37 | else: 38 | self._name = Atom.a(name) 39 | self._arg1 = arg1 40 | self._arg2 = arg2 41 | self._arg3 = arg3 42 | 43 | # If arg is another Functor3, then succeed (yield once) if this and arg have the 44 | # same name and all functor args unify, otherwise fail (don't yield). 45 | # If arg is a Variable, then call its unify to unify with this. 46 | # Otherwise fail (don't yield). 47 | def unify(self, arg): 48 | arg = YP.getValue(arg) 49 | if isinstance(arg, Functor3): 50 | if self._name.equals(arg._name): 51 | for l1 in YP.unify(self._arg1, arg._arg1): 52 | for l2 in YP.unify(self._arg2, arg._arg2): 53 | for l3 in YP.unify(self._arg3, arg._arg3): 54 | yield False 55 | elif isinstance(arg, Variable): 56 | for l1 in arg.unify(self): 57 | yield False 58 | 59 | def __str__(self): 60 | return str(self._name) + "(" + str(YP.getValue(self._arg1)) + ", " + \ 61 | str(YP.getValue(self._arg2)) + ", " + str(YP.getValue(self._arg3)) + ")" 62 | 63 | def termEqual(self, term): 64 | term = YP.getValue(term) 65 | if isinstance(term, Functor3): 66 | return self._name.equals(term._name) and YP.termEqual(self._arg1, term._arg1) \ 67 | and YP.termEqual(self._arg2, term._arg2) \ 68 | and YP.termEqual(self._arg3, term._arg3) 69 | return False 70 | 71 | def lessThan(self, functor): 72 | # Do the equal check first since it is faster. 73 | if not self._name.equals(functor._name): 74 | return self._name.lessThan(functor._name) 75 | 76 | if not YP.termEqual(self._arg1, functor._arg1): 77 | return YP.termLessThan(self._arg1, functor._arg1) 78 | 79 | if not YP.termEqual(self._arg2, functor._arg2): 80 | return YP.termLessThan(self._arg2, functor._arg2) 81 | 82 | return YP.termLessThan(self._arg3, functor._arg3) 83 | 84 | def ground(self): 85 | return YP.ground(self._arg1) and YP.ground(self._arg2) and YP.ground(self._arg3) 86 | 87 | def addUniqueVariables(self, variableSet): 88 | YP.addUniqueVariables(self._arg1, variableSet) 89 | YP.addUniqueVariables(self._arg2, variableSet) 90 | YP.addUniqueVariables(self._arg3, variableSet) 91 | 92 | def makeCopy(self, copyStore): 93 | return Functor3(self._name, YP.makeCopy(self._arg1, copyStore), \ 94 | YP.makeCopy(self._arg2, copyStore), \ 95 | YP.makeCopy(self._arg3, copyStore)) 96 | -------------------------------------------------------------------------------- /source/python/ListPair.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2007-2008, Jeff Thompson 2 | # 3 | # All rights reserved. 4 | # 5 | # Redistribution and use in source and binary forms, with or without 6 | # modification, are permitted provided that the following conditions are met: 7 | # 8 | # * Redistributions of source code must retain the above copyright 9 | # notice, this list of conditions and the following disclaimer. 10 | # * Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer in the 12 | # documentation and/or other materials provided with the distribution. 13 | # * Neither the name of the copyright holder nor the names of its contributors 14 | # may be used to endorse or promote products derived from this software 15 | # without specific prior written permission. 16 | # 17 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 21 | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 22 | # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 | # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 24 | # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 25 | # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 26 | # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | from YP import * 30 | from Functor2 import * 31 | 32 | class ListPair(Functor2): 33 | def __init__(self, head, tail): 34 | Functor2.__init__(self, Atom.DOT, head, tail) 35 | 36 | @staticmethod 37 | def make(arg1, arg2 = None, arg3 = None): 38 | if arg3 != None: 39 | return ListPair(arg1, ListPair(arg2, ListPair(arg3, Atom.NIL))) 40 | if arg2 != None: 41 | return ListPair(arg1, ListPair(arg2, Atom.NIL)) 42 | 43 | if isinstance(arg1, list): 44 | if len(arg1) <= 0: 45 | return Atom.NIL 46 | 47 | result = Atom.NIL 48 | # Start from the end. 49 | for i in range(len(arg1) - 1, -1, -1): 50 | result = ListPair(arg1[i], result) 51 | return result 52 | else: 53 | return ListPair(arg1, Atom.NIL) 54 | 55 | # Return a ListPair version of array, where repeated elements (according to YP.termEqual) are removed. 56 | @staticmethod 57 | def makeWithoutRepeatedTerms(array): 58 | if len(array) <= 0: 59 | return Atom.NIL 60 | 61 | # Start from the end. 62 | previousTerm = array[len(array) - 1] 63 | result = ListPair(previousTerm, Atom.NIL) 64 | for i in range(len(array) - 2, -1, -1): 65 | term = array[i] 66 | if YP.termEqual(term, previousTerm): 67 | continue 68 | result = ListPair(term, result) 69 | previousTerm = term 70 | 71 | return result 72 | 73 | # Return an array of the elements in list or null if it is not 74 | # a proper list. If list is Atom.NIL, return an array of zero elements. 75 | # If the list or one of the tails of the list is Variable, raise an instantiation_error. 76 | # This does not call YP.getValue on each element. 77 | @staticmethod 78 | def toArray(list): 79 | list = YP.getValue(list) 80 | if list == Atom.NIL: 81 | return [] 82 | 83 | result = [] 84 | element = list 85 | while True: 86 | if element == Atom.NIL: 87 | break 88 | if isinstance(element, Variable): 89 | raise PrologException(Atom.a("instantiation_error"), "List tail is an unbound variable") 90 | if not (isinstance(element, Functor2) and element._name == Atom.DOT): 91 | # Not a proper list. 92 | return None 93 | result.append(element._arg1) 94 | element = YP.getValue(element._arg2) 95 | 96 | if len(result) <= 0: 97 | return None 98 | return result 99 | -------------------------------------------------------------------------------- /source/python/PrologException.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2007-2008, Jeff Thompson 2 | # 3 | # All rights reserved. 4 | # 5 | # Redistribution and use in source and binary forms, with or without 6 | # modification, are permitted provided that the following conditions are met: 7 | # 8 | # * Redistributions of source code must retain the above copyright 9 | # notice, this list of conditions and the following disclaimer. 10 | # * Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer in the 12 | # documentation and/or other materials provided with the distribution. 13 | # * Neither the name of the copyright holder nor the names of its contributors 14 | # may be used to endorse or promote products derived from this software 15 | # without specific prior written permission. 16 | # 17 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 21 | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 22 | # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 | # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 24 | # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 25 | # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 26 | # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | from YP import * 30 | from Functor2 import * 31 | 32 | # A PrologException is used as the exception thrown by YP.throw(Term). 33 | # One argument: Create a PrologException with the given arg1 term. The printable exception message is the full Term. 34 | # Two arguments: Create a PrologException where the Term is error(arg1, arg2). If arg2 is a string, this 35 | # converts it to an Atom so that Prolog code can use it. 36 | # This uses YP.makeCopy to copy the arguments so that they are valid after unbinding. 37 | class PrologException(Exception): 38 | def __init__(self, arg1, arg2 = None): 39 | if arg2 != None: 40 | arg2 = YP.getValue(arg2); 41 | Exception.__init__(self, str(arg2)) 42 | if isinstance(arg2, str): 43 | arg2 = Atom.a(arg2) 44 | self._term = YP.makeCopy(Functor2(Atom.a("error"), arg1, arg2), Variable.CopyStore()) 45 | else: 46 | Exception.__init__(self, str(YP.getValue(arg1))) 47 | self._term = YP.makeCopy(arg1, Variable.CopyStore()) 48 | 49 | class TypeErrorInfo(object): 50 | def __init__(self, Type, Culprit, Message): 51 | self._Type = Type 52 | self._Culprit = Culprit 53 | self._Message = Message 54 | 55 | # Return the TypeErrorInfo for this exception, or None if _term does not match 56 | # error(type_error(Type, Culprit), Message). 57 | def getTypeErrorInfo(self): 58 | if not (isinstance(self._term, Functor2) and self._term._name._name == "error"): 59 | return None 60 | errorTerm = self._term._arg1 61 | if not (isinstance(errorTerm, Functor2) and errorTerm._name._name == "type_error"): 62 | return None 63 | if not isinstance(errorTerm._arg1, Atom): 64 | return None 65 | return PrologException.TypeErrorInfo(errorTerm._arg1, errorTerm._arg2, self._term._arg2) 66 | 67 | class ExistenceErrorInfo(object): 68 | def __init__(self, Type, Culprit, Message): 69 | self._Type = Type 70 | self._Culprit = Culprit 71 | self._Message = Message 72 | 73 | # If _Type is procedure and _Culprit is name/artity, return the name. Otherwise return null. 74 | def getProcedureName(self): 75 | if not (self._Type._name == "procedure" and \ 76 | isinstance(self._Culprit, Functor2) and self._Culprit._name == Atom.SLASH): 77 | return None 78 | return self._Culprit._arg1 79 | 80 | # If _Type is procedure and _Culprit is name/arity and arity is an integer, return the arity. 81 | # Otherwise return -1. 82 | def getProcedureArity(self): 83 | if not (self._Type._name == "procedure" and \ 84 | isinstance(self._Culprit, Functor2) and self._Culprit._name == Atom.SLASH): 85 | return -1 86 | if not isinstance(self._Culprit._arg2, int): 87 | return -1 88 | return self._Culprit._arg2 89 | 90 | # Return the ExistenceErrorInfo for this exception, or None if _term does not match 91 | # error(existence_error(Type, Culprit), Message). If the returned ExistenceErrorInfo _Culprit is 92 | # procedure, you can use its getProcedureName and getProcedureArity. 93 | def getExistenceErrorInfo(self): 94 | if not (isinstance(self._term, Functor2) and self._term._name._name == "error"): 95 | return None 96 | errorTerm = self._term._arg1 97 | if not (isinstance(errorTerm, Functor2) and errorTerm._name._name == "existence_error"): 98 | return None 99 | if not isinstance(errorTerm._arg1, Atom): 100 | return None 101 | return PrologException.ExistenceErrorInfo(errorTerm._arg1, errorTerm._arg2, self._term._arg2) 102 | -------------------------------------------------------------------------------- /source/python/Variable.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2007-2008, Jeff Thompson 2 | # 3 | # All rights reserved. 4 | # 5 | # Redistribution and use in source and binary forms, with or without 6 | # modification, are permitted provided that the following conditions are met: 7 | # 8 | # * Redistributions of source code must retain the above copyright 9 | # notice, this list of conditions and the following disclaimer. 10 | # * Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer in the 12 | # documentation and/or other materials provided with the distribution. 13 | # * Neither the name of the copyright holder nor the names of its contributors 14 | # may be used to endorse or promote products derived from this software 15 | # without specific prior written permission. 16 | # 17 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 21 | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 22 | # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 | # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 24 | # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 25 | # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 26 | # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | from YP import * 30 | 31 | class IUnifiable(object): 32 | pass 33 | 34 | class Variable(IUnifiable): 35 | def __init__(self): 36 | # Use _isBound separate from _value so that it can be bound to any value, 37 | # including None. 38 | self._isBound = False 39 | 40 | # If this Variable is unbound, then just return this Variable. 41 | # Otherwise, if this has been bound to a value with unify, return the value. 42 | # If the bound value is another Variable, this follows the "variable chain" 43 | # to the end and returns the final value, or the final Variable if it is unbound. 44 | # For more details, see http://yieldprolog.sourceforge.net/tutorial1.html 45 | def getValue(self): 46 | if not self._isBound: 47 | return self 48 | 49 | result = self._value 50 | while isinstance(result, Variable): 51 | if not result._isBound: 52 | return result 53 | 54 | # Keep following the Variable chain. 55 | result = result._value 56 | 57 | return result 58 | 59 | # If this Variable is bound, then just call YP.unify to unify this with arg. 60 | # (Note that if arg is an unbound Variable, then YP.unify will bind it to 61 | # this Variable's value.) 62 | # Otherwise, bind this Variable to YP.getValue(arg) and yield once. After the 63 | # yield, return this Variable to the unbound state. 64 | # For more details, see http://yieldprolog.sourceforge.net/tutorial1.html 65 | def unify(self, arg): 66 | if not self._isBound: 67 | self._value = YP.getValue(arg) 68 | if self._value == self: 69 | # We are unifying this unbound variable with itself, so leave it unbound. 70 | yield False 71 | else: 72 | self._isBound = True 73 | try: 74 | yield False 75 | finally: 76 | # Remove the binding. 77 | self._isBound = False 78 | else: 79 | for l1 in YP.unify(self, arg): 80 | yield False 81 | 82 | # If bound, call YP.addUniqueVariables on the value. Otherwise, if this unbound 83 | # variable is not already in variableSet, add it. 84 | def addUniqueVariables(self, variableSet): 85 | if self._isBound: 86 | YP.addUniqueVariables(self.getValue(), variableSet) 87 | else: 88 | if variableSet.count(self) == 0: 89 | variableSet.append(self) 90 | 91 | def __str__(self): 92 | value = self.getValue() 93 | if value == self: 94 | return "_Variable" 95 | else: 96 | return value.__str__() 97 | 98 | # If bound, return YP.makeCopy for the value, else return copyStore.getCopy(this). 99 | # However, if copyStore is None, just return this. 100 | def makeCopy(self, copyStore): 101 | if self._isBound: 102 | return YP.makeCopy(self.getValue(), copyStore) 103 | else: 104 | if copyStore == None: 105 | return self 106 | else: 107 | return copyStore.getCopy(self) 108 | 109 | def termEqual(self, term): 110 | if self._isBound: 111 | return YP.termEqual(self.getValue(), term) 112 | else: 113 | return self == YP.getValue(term) 114 | 115 | def ground(self): 116 | if this._isBound: 117 | # This is usually called by YP.ground which already did getValue, so this 118 | # should never be reached, but check anyway. 119 | return YP.ground(self.getValue()) 120 | else: 121 | return False 122 | 123 | # A CopyStore is used by makeCopy to track which Variable objects have 124 | # been copied. 125 | class CopyStore(object): 126 | def __init__(self): 127 | self._inVariableList = [] 128 | self._outVariableList = [] 129 | 130 | # If inVariable has already been copied, return its copy. Otherwise, 131 | # return a fresh Variable associated with inVariable. 132 | def getCopy(self, inVariable): 133 | if self._inVariableList.count(inVariable) > 0: 134 | return self._outVariableList[self._inVariableList.index(inVariable)] 135 | else: 136 | outVariable = Variable() 137 | self._inVariableList.append(inVariable) 138 | self._outVariableList.append(outVariable) 139 | return outVariable 140 | 141 | # Return the number of unique variables that have been copied. 142 | def getNUniqueVariables(self): 143 | return len(self._inVariableList) 144 | 145 | -------------------------------------------------------------------------------- /source/python/examples/Benchmarks/naiveQueens.py: -------------------------------------------------------------------------------- 1 | import sys 2 | # Hack sys.path for the examples. 3 | sys.path.append("../..") 4 | from YP import * 5 | from Variable import * 6 | from Atom import * 7 | from ListPair import * 8 | from time import * 9 | 10 | def main(): 11 | startTime = clock() 12 | nAnswers = 0 13 | Qs = Variable() 14 | for l1 in queens(11, Qs): 15 | nAnswers += 1 16 | finishTime = clock() 17 | print "Naive queens:", (finishTime - startTime), "seconds,", \ 18 | nAnswers, "answers" 19 | 20 | def queens(N, Qs): 21 | Ns = Variable() 22 | for l1 in rangeList(1, N, Ns): 23 | for l2 in queens3(Ns, Atom.NIL, Qs): 24 | yield False 25 | 26 | def queens3(UnplacedQs, SafeQs, Qs): 27 | UnplacedQs1 = Variable() 28 | Q = Variable() 29 | for l1 in selectq(Q, UnplacedQs, UnplacedQs1): 30 | for l2 in notHasAttack(Q, SafeQs): 31 | for l3 in queens3(UnplacedQs1, ListPair(Q, SafeQs), Qs): 32 | yield False 33 | for l1 in YP.unify(UnplacedQs, Atom.NIL): 34 | for l2 in YP.unify(Qs, SafeQs): 35 | yield False 36 | 37 | def notHasAttack(X, Xs): 38 | for l1 in attack(X, Xs): 39 | return 40 | yield False 41 | 42 | def attack(X, Xs): 43 | for l1 in attack3(X, 1, Xs): 44 | yield False 45 | 46 | def attack3(X, N, Arg3): 47 | Y = Variable() 48 | for l1 in ListPair(Y, Variable()).unify(Arg3): 49 | if YP.getValue(X) == Y.getValue() + YP.getValue(N): 50 | yield False 51 | if YP.getValue(X) == Y.getValue() - YP.getValue(N): 52 | yield False 53 | 54 | Ys = Variable() 55 | N1 = Variable() 56 | for l1 in ListPair(Variable(), Ys).unify(Arg3): 57 | for l2 in N1.unify(YP.getValue(N) + 1): 58 | for l3 in attack3(X, N1, Ys): 59 | yield False 60 | 61 | def rangeList(M, N, List): 62 | if YP.getValue(M) >= YP.getValue(N): 63 | for l1 in YP.unify(List, ListPair(N, Atom.NIL)): 64 | yield False 65 | else: 66 | Tail = Variable() 67 | for l1 in rangeList(YP.getValue(M) + 1, YP.getValue(N), Tail): 68 | for l2 in YP.unify(List, ListPair(M, Tail)): 69 | yield False 70 | 71 | 72 | def selectq(X, Arg2, Arg3): 73 | for l1 in ListPair(X, Arg3).unify(Arg2): 74 | yield False 75 | 76 | Y = Variable() 77 | Ys = Variable() 78 | Zs = Variable() 79 | for l1 in ListPair(Y, Ys).unify(Arg2): 80 | for l2 in ListPair(Y, Zs).unify(Arg3): 81 | for l3 in selectq(X, Ys, Zs): 82 | yield False 83 | 84 | main() 85 | 86 | 87 | -------------------------------------------------------------------------------- /source/python/examples/Benchmarks/queens.py: -------------------------------------------------------------------------------- 1 | import sys 2 | # Hack sys.path for the examples. 3 | sys.path.append("../..") 4 | from YP import * 5 | from Variable import * 6 | from Atom import * 7 | from ListPair import * 8 | from time import * 9 | 10 | def main(): 11 | startTime = clock() 12 | nAnswers = 0 13 | Qs = Variable() 14 | for l1 in queens(11, Qs): 15 | nAnswers += 1 16 | finishTime = clock() 17 | print "Optimized queens:", (finishTime - startTime), "seconds,", \ 18 | nAnswers, "answers" 19 | 20 | def queens(N, Qs): 21 | Ns = Variable() 22 | for l1 in rangeList(1, N, Ns): 23 | for l2 in queens3(Ns, Atom.NIL, Qs): 24 | yield False 25 | 26 | def queens3(UnplacedQs, SafeQs, Qs): 27 | UnplacedQsListPair = YP.getValue(UnplacedQs) 28 | if isinstance(UnplacedQsListPair, ListPair): 29 | UnplacedQs1 = Variable() 30 | Q = Variable() 31 | for l1 in selectq(Q, UnplacedQsListPair, UnplacedQs1): 32 | if not (isinstance(SafeQs, ListPair) and hasAttack(Q.getValue(), SafeQs)): 33 | for l2 in queens3(UnplacedQs1, ListPair(Q, SafeQs), Qs): 34 | yield False 35 | else: 36 | for l1 in Qs.unify(SafeQs): 37 | yield False 38 | 39 | def hasAttack(X, Xs): 40 | return hasAttack3(X, 1, Xs) 41 | 42 | def hasAttack3(X, N, Arg3): 43 | if X == YP.getValue(Arg3._arg1) + N or X == YP.getValue(Arg3._arg1) - N: 44 | return True 45 | if isinstance(Arg3._arg2, ListPair): 46 | return hasAttack3(X, N + 1, YP.getValue(Arg3._arg2)) 47 | else: 48 | return False 49 | 50 | def rangeList(M, N, List): 51 | if M >= N: 52 | for l1 in List.unify(ListPair(N, Atom.NIL)): 53 | yield False 54 | else: 55 | Tail = Variable() 56 | for l1 in rangeList(M + 1, N, Tail): 57 | for l2 in List.unify(ListPair(M, Tail)): 58 | yield False 59 | 60 | def selectq(X, Arg2, Arg3): 61 | for l1 in X.unify(Arg2._arg1): 62 | for l2 in Arg3.unify(Arg2._arg2): 63 | yield False 64 | 65 | Arg2Tail = YP.getValue(Arg2._arg2) 66 | if isinstance(Arg2Tail, ListPair): 67 | Zs = Variable() 68 | for l1 in selectq(X, Arg2Tail, Zs): 69 | for l2 in Arg3.unify(ListPair(Arg2._arg1, Zs)): 70 | yield False 71 | 72 | main() 73 | 74 | 75 | -------------------------------------------------------------------------------- /source/python/examples/YieldPrologTutorial/tutorial1.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2007-2008, Jeff Thompson 2 | # 3 | # All rights reserved. 4 | # 5 | # Redistribution and use in source and binary forms, with or without 6 | # modification, are permitted provided that the following conditions are met: 7 | # 8 | # * Redistributions of source code must retain the above copyright 9 | # notice, this list of conditions and the following disclaimer. 10 | # * Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer in the 12 | # documentation and/or other materials provided with the distribution. 13 | # * Neither the name of the copyright holder nor the names of its contributors 14 | # may be used to endorse or promote products derived from this software 15 | # without specific prior written permission. 16 | # 17 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 21 | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 22 | # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 | # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 24 | # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 25 | # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 26 | # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | def main(): 30 | print("Names using a return value:") 31 | for p in personWithReturnValue(): 32 | print(p) 33 | 34 | print("Names using SimpleVariable:") 35 | P = SimpleVariable() 36 | for l1 in personWithSimpleVariable(P): 37 | print(P._value) 38 | 39 | print("Names using UnifyingVariable:") 40 | Person = UnifyingVariable() 41 | for l1 in personWithUnify(Person): 42 | print(Person._value) 43 | 44 | print("Use unify to check a person:") 45 | for l1 in Person.unify("Hillary"): 46 | for l2 in personWithUnify(Person): 47 | print("Hillary is a person.") 48 | for l1 in Person.unify("Buddy"): 49 | for l2 in personWithUnify(Person): 50 | # This won't print. 51 | print("Buddy is a person.") 52 | 53 | print("Use generalUnify to check a person:") 54 | for l1 in person("Hillary"): 55 | print("Hillary is a person.") 56 | for l1 in person("Buddy"): 57 | # This won't print. 58 | print ("Buddy is a person.") 59 | 60 | print("Find relations:") 61 | Brother = UnifyingVariable() 62 | for l1 in brother("Hillary", Brother): 63 | print("Hillary has brother " + Brother._value + ".") 64 | 65 | print("Joining functions:") 66 | Uncle = UnifyingVariable() 67 | for l1 in uncle(Person, Uncle): 68 | print(Person._value + " has uncle " + Uncle._value + ".") 69 | 70 | def personWithReturnValue(): 71 | yield "Chelsea" 72 | yield "Hillary" 73 | yield "Bill" 74 | 75 | class SimpleVariable: 76 | pass 77 | 78 | def personWithSimpleVariable(Person): 79 | Person._value = "Chelsea" 80 | yield False 81 | Person._value = "Hillary" 82 | yield False 83 | Person._value = "Bill" 84 | yield False 85 | 86 | class UnifyingVariable: 87 | def __init__(self): 88 | self._isBound = False 89 | 90 | def unify(self, arg): 91 | if not self._isBound: 92 | self._value = arg 93 | self._isBound = True 94 | yield False 95 | # Remove the binding. 96 | self._isBound = False 97 | elif self._value == arg: 98 | yield False 99 | 100 | def personWithUnify(Person): 101 | for l1 in Person.unify("Chelsea"): 102 | yield False 103 | for l1 in Person.unify("Hillary"): 104 | yield False 105 | for l1 in Person.unify("Bill"): 106 | yield False 107 | 108 | def generalGetValue(value): 109 | if isinstance(value, UnifyingVariable): 110 | if not value._isBound: 111 | return value 112 | else: 113 | return value._value 114 | else: 115 | return value 116 | 117 | def generalUnify(arg1, arg2): 118 | arg1Value = generalGetValue(arg1) 119 | arg2Value = generalGetValue(arg2) 120 | if isinstance(arg1Value, UnifyingVariable): 121 | for l1 in arg1Value.unify(arg2Value): 122 | yield False 123 | elif isinstance(arg2Value, UnifyingVariable): 124 | for l1 in arg2Value.unify(arg1Value): 125 | yield False 126 | else: 127 | # Arguments are "normal" types. 128 | if arg1Value == arg2Value: 129 | yield False 130 | 131 | def person(Person): 132 | for l1 in generalUnify(Person, "Chelsea"): 133 | yield False 134 | for l1 in generalUnify(Person, "Hillary"): 135 | yield False 136 | for l1 in generalUnify(Person, "Bill"): 137 | yield False 138 | 139 | def brother(Person, Brother): 140 | for l1 in generalUnify(Person, "Hillary"): 141 | for l2 in generalUnify(Brother, "Tony"): 142 | yield False 143 | for l2 in generalUnify(Brother, "Hugh"): 144 | yield False 145 | for l1 in generalUnify(Person, "Bill"): 146 | for l2 in generalUnify(Brother, "Roger"): 147 | yield False 148 | 149 | def parent(Person, Parent): 150 | for l1 in generalUnify(Person, "Chelsea"): 151 | for l2 in generalUnify(Parent, "Hillary"): 152 | yield False 153 | for l1 in generalUnify(Person, "Chelsea"): 154 | for l2 in generalUnify(Parent, "Bill"): 155 | yield False 156 | 157 | def uncle(Person, Uncle): 158 | Parent = UnifyingVariable() 159 | for l1 in parent(Person, Parent): 160 | for l2 in brother(Parent, Uncle): 161 | yield False 162 | 163 | main() 164 | -------------------------------------------------------------------------------- /source/python/examples/YieldPrologTutorial/tutorial2.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2007-2008, Jeff Thompson 2 | # 3 | # All rights reserved. 4 | # 5 | # Redistribution and use in source and binary forms, with or without 6 | # modification, are permitted provided that the following conditions are met: 7 | # 8 | # * Redistributions of source code must retain the above copyright 9 | # notice, this list of conditions and the following disclaimer. 10 | # * Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer in the 12 | # documentation and/or other materials provided with the distribution. 13 | # * Neither the name of the copyright holder nor the names of its contributors 14 | # may be used to endorse or promote products derived from this software 15 | # without specific prior written permission. 16 | # 17 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 21 | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 22 | # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 | # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 24 | # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 25 | # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 26 | # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | import sys 30 | # Hack sys.path for the examples. 31 | sys.path.append("../..") 32 | from YP import * 33 | from Variable import * 34 | 35 | def main(): 36 | Brother = Variable() 37 | print "Find relations:" 38 | for l1 in brother("Hillary", Brother): 39 | print "Hillary has brother", \ 40 | Brother.getValue(), "." 41 | 42 | print "Check if it is square:" 43 | for l1 in squaredRectangle(10, 10): 44 | print "10 by 10 rectangle is square." 45 | 46 | print "Make it square:" 47 | Width = Variable() 48 | Height = Variable() 49 | for l1 in Width.unify(10): 50 | for l2 in squaredRectangle(Width, Height): 51 | print "A square of width", \ 52 | Width.getValue(), "has height", \ 53 | Height.getValue(), "." 54 | 55 | print "Make it square before we know the width:" 56 | for l1 in squaredRectangle(Width, Height): 57 | for l2 in Width.unify(10): 58 | print "A square of width", \ 59 | Width.getValue(), "has height", \ 60 | Height.getValue(), "." 61 | 62 | print "Get one match:" 63 | for l1 in anyBrother("Hillary", Brother): 64 | print "Hillary has a brother", \ 65 | Brother.getValue(), "." 66 | for l1 in anyBrother("Bill", Brother): 67 | print "Bill has a brother", \ 68 | Brother.getValue(), "." 69 | 70 | print "Use cut for negation:" 71 | for l1 in noBrother("Hillary"): 72 | print "Hillary has no brother." 73 | for l1 in noBrother("Chelsea"): 74 | print "Chelsea has no brother." 75 | 76 | def brother(Person, Brother): 77 | for l1 in YP.unify(Person, "Hillary"): 78 | for l2 in YP.unify(Brother, "Tony"): 79 | yield False 80 | for l2 in YP.unify(Brother, "Hugh"): 81 | yield False 82 | for l1 in YP.unify(Person, "Bill"): 83 | for l2 in YP.unify(Brother, "Roger"): 84 | yield False 85 | 86 | def squaredRectangle(Width, Height): 87 | for l1 in YP.unify(Width, Height): 88 | yield False 89 | 90 | def anyBrother(Person, Brother): 91 | for l1 in brother(Person, Brother): 92 | yield False 93 | break 94 | 95 | def noBrother(Person): 96 | Brother = Variable() 97 | for l1 in brother(Person, Brother): 98 | return 99 | yield False 100 | 101 | main() 102 | 103 | 104 | -------------------------------------------------------------------------------- /source/python/examples/YieldPrologTutorial/tutorial3.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2007-2008, Jeff Thompson 2 | # 3 | # All rights reserved. 4 | # 5 | # Redistribution and use in source and binary forms, with or without 6 | # modification, are permitted provided that the following conditions are met: 7 | # 8 | # * Redistributions of source code must retain the above copyright 9 | # notice, this list of conditions and the following disclaimer. 10 | # * Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer in the 12 | # documentation and/or other materials provided with the distribution. 13 | # * Neither the name of the copyright holder nor the names of its contributors 14 | # may be used to endorse or promote products derived from this software 15 | # without specific prior written permission. 16 | # 17 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 21 | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 22 | # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 | # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 24 | # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 25 | # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 26 | # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | import sys 30 | # Hack sys.path for the examples. 31 | sys.path.append("../..") 32 | from YP import * 33 | from Variable import * 34 | from Atom import * 35 | from ListPair import * 36 | 37 | def main(): 38 | print "Return a list of 2 elements:" 39 | List = Variable() 40 | for l1 in makeList("a", "b", List): 41 | print "List =", List.getValue() 42 | 43 | print "Unify two lists:" 44 | Second = Variable() 45 | for l1 in makeList("x", Second, 46 | ListPair("x", ListPair("y", Atom.NIL))): 47 | print "The second element is", Second.getValue() 48 | 49 | def makeList(First, Second, List): 50 | list1 = ListPair(Second, Atom.NIL) 51 | result = ListPair(First, list1) 52 | for l1 in YP.unify(List, result): 53 | yield False 54 | 55 | main() 56 | 57 | 58 | -------------------------------------------------------------------------------- /source/python/examples/YieldPrologTutorial/tutorial4.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2007-2008, Jeff Thompson 2 | # 3 | # All rights reserved. 4 | # 5 | # Redistribution and use in source and binary forms, with or without 6 | # modification, are permitted provided that the following conditions are met: 7 | # 8 | # * Redistributions of source code must retain the above copyright 9 | # notice, this list of conditions and the following disclaimer. 10 | # * Redistributions in binary form must reproduce the above copyright 11 | # notice, this list of conditions and the following disclaimer in the 12 | # documentation and/or other materials provided with the distribution. 13 | # * Neither the name of the copyright holder nor the names of its contributors 14 | # may be used to endorse or promote products derived from this software 15 | # without specific prior written permission. 16 | # 17 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 21 | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 22 | # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 | # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 24 | # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 25 | # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 26 | # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | import sys 30 | # Hack sys.path for the examples. 31 | sys.path.append("../..") 32 | from YP import * 33 | from Atom import * 34 | from Compiler import * 35 | from ListPair import * 36 | from Variable import * 37 | 38 | def main(): 39 | YP.assertFact(Atom.a("brother"), \ 40 | [Atom.a("Hillary"), Atom.a("Hugh")]) 41 | YP.assertFact(Atom.a("brother"), \ 42 | [Atom.a("Hillary"), Atom.a("Tony")]) 43 | YP.assertFact(Atom.a("brother"), \ 44 | [Atom.a("Bill"), Atom.a("Roger")]) 45 | 46 | Brother = Variable() 47 | print "Using dynamic assert:" 48 | for l1 in YP.matchDynamic \ 49 | (Atom.a("brother"), \ 50 | [Atom.a("Hillary"), Brother]): 51 | print "Hillary has brother", \ 52 | Brother.getValue() 53 | 54 | prologCode = \ 55 | "uncle(Person, Uncle) :- \n" + \ 56 | " parent(Person, Parent), \n" + \ 57 | " brother(Parent, Uncle). \n" 58 | print "# Compiled code:" 59 | compileAndWrite(prologCode) 60 | 61 | prologCode = \ 62 | ":- import('', [parent/2]). \n" + \ 63 | "uncle(Person, Uncle) :- \n" + \ 64 | " parent(Person, Parent), \n" + \ 65 | " brother(Parent, Uncle). \n" 66 | print "# Calling an imported function:" 67 | compileAndWrite(prologCode) 68 | 69 | prologCode = \ 70 | "parent('Chelsea', 'Hillary'). \n" + \ 71 | "parent('Chelsea', 'Bill'). \n" + \ 72 | \ 73 | "uncle(Person, Uncle) :- \n" + \ 74 | " parent(Person, Parent), \n" + \ 75 | " brother(Parent, Uncle). \n" 76 | print "# Calling a locally-defined function:" 77 | compileAndWrite(prologCode) 78 | 79 | prologCode = \ 80 | ":- import('', [parent/2]). \n" + \ 81 | "uncle(Person, Uncle) :- \n" + \ 82 | " Goal = parent(Person, Parent), \n" + \ 83 | " Goal, \n" + \ 84 | " brother(Parent, Uncle). \n" 85 | print "# Calling a dynamic goal:" 86 | compileAndWrite(prologCode) 87 | 88 | print "Calling compiled code having a dynamic goal:" 89 | Person = Variable() 90 | Uncle = Variable() 91 | for l1 in uncle(Person, Uncle): 92 | print Person.getValue(), "has uncle", \ 93 | Uncle.getValue() 94 | 95 | def compileAndWrite(prologCode): 96 | YP.tell(sys.stdout) 97 | YP.see(YP.StringReader(prologCode)) 98 | TermList = Variable() 99 | PseudoCode = Variable() 100 | for l1 in parseInput(TermList): 101 | for l2 in makeFunctionPseudoCode \ 102 | (TermList, PseudoCode): 103 | convertFunctionPython(PseudoCode) 104 | YP.seen() 105 | 106 | def getDeclaringClass(): 107 | return globals() 108 | 109 | def parent(arg1, arg2): 110 | for l1 in YP.unify \ 111 | (arg1, Atom.a("Chelsea")): 112 | for l2 in YP.unify \ 113 | (arg2, Atom.a("Hillary")): 114 | yield False 115 | for l1 in YP.unify \ 116 | (arg1, Atom.a("Chelsea")): 117 | for l2 in YP.unify \ 118 | (arg2, Atom.a("Bill")): 119 | yield False 120 | 121 | def uncle(Person, Uncle): 122 | Goal = Variable() 123 | Parent = Variable() 124 | for l1 in YP.unify \ 125 | (Goal, Functor2 \ 126 | (Atom.a("parent", Atom.a("")), \ 127 | Person, Parent)): 128 | for l2 in YP.getIterator \ 129 | (Goal, getDeclaringClass()): 130 | for l3 in YP.matchDynamic \ 131 | (Atom.a("brother"), [Parent, Uncle]): 132 | yield False 133 | 134 | main() 135 | 136 | 137 | --------------------------------------------------------------------------------