diff options
author | Charles Krinke | 2008-05-31 17:52:44 +0000 |
---|---|---|
committer | Charles Krinke | 2008-05-31 17:52:44 +0000 |
commit | 25b7d9944d5875e1887eed156f31dd5779761265 (patch) | |
tree | 2c4f6f066ef2b5f60d399ab4862ed7b9dbe0c78f /OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/YieldProlog/README.TXT | |
parent | * Implements UserServer logoff in a few situations (diff) | |
download | opensim-SC_OLD-25b7d9944d5875e1887eed156f31dd5779761265.zip opensim-SC_OLD-25b7d9944d5875e1887eed156f31dd5779761265.tar.gz opensim-SC_OLD-25b7d9944d5875e1887eed156f31dd5779761265.tar.bz2 opensim-SC_OLD-25b7d9944d5875e1887eed156f31dd5779761265.tar.xz |
Mantis#1314. Thank you kindly, Kinoc for YieldProlog.
I have added everything *except* the patch to
.../LSL/Compiler.cs. The Compiler.cs patch has a
namespace issue. Lets make a second patch to close
the gap.
Diffstat (limited to 'OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/YieldProlog/README.TXT')
-rw-r--r-- | OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/YieldProlog/README.TXT | 405 |
1 files changed, 405 insertions, 0 deletions
diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/YieldProlog/README.TXT b/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/YieldProlog/README.TXT new file mode 100644 index 0000000..05186f1 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/YieldProlog/README.TXT | |||
@@ -0,0 +1,405 @@ | |||
1 | YPOS: YieldProlog for OpenSim | ||
2 | |||
3 | a compiler from Prolog to OpenSim compatible C# scripts | ||
4 | |||
5 | Ported by Kino Coursey and Douglas Miles at Daxtron Labs. | ||
6 | Based on Jeff Thompson Yield Prolog, http://yieldprolog.sourceforge.net/ | ||
7 | For Prolog see http://en.wikipedia.org/wiki/Prolog | ||
8 | |||
9 | |||
10 | INTRODUCTION | ||
11 | |||
12 | This folder contains code to implement a Prolog compiler using the "Yield Statement" found in C#, Javascript, and Python. | ||
13 | The original Yield Prolog system can transform Prolog programs into C# code. | ||
14 | In this system we detect and extract YieldProlog code (with "//YP" as the first four characters in the script) and seperate it from any c# code ("marked by "//CS"). | ||
15 | The YP code is transformed to C# and prepended to the "//CS" section, and passed as a bundel to the existing C# compiler. | ||
16 | The end result is Prolog can interface to OpenSim using the existing "//CS" functionality, and C# can call the compiled Prolog. | ||
17 | As such YP allows both declaritive and procedural programming in a 3D script enabled environment. | ||
18 | |||
19 | FEATURES | ||
20 | * Allows implementation of logic programming for objects and agents. | ||
21 | * C#/Javascript/Python as intermediate language | ||
22 | * Yield Prolog has relatively high speed of execution which is important in OpenSim. http://yieldprolog.sourceforge.net/benchmarks.html | ||
23 | * It is compatable with the existing C#/Mono based system. | ||
24 | * Yield Prolog is BSD license | ||
25 | * Calling Prolog from C# scripts | ||
26 | * Calling C# functions (with LSL and OS functions) from Prolog | ||
27 | * Prolog dynamic database | ||
28 | * Edinburgh, Cocksin & Mellish style syntax. | ||
29 | * Compiler is generated by compiling the Prolog descrition of itself into C# | ||
30 | * Same script entry interface as LSL | ||
31 | |||
32 | |||
33 | TODO | ||
34 | * Utilize ability to generate Javascript and Python code | ||
35 | * Integrate Prolog database with Sim | ||
36 | * Translation error reporting back to the editor | ||
37 | * Communications via message passing | ||
38 | * Interface to external inference engines | ||
39 | |||
40 | POSSIBILITIES | ||
41 | * Inworld expert systems | ||
42 | * Parallel logic programming and expert systems | ||
43 | * Ontology based processing | ||
44 | * Knowledge based alerting, accessing and business rules | ||
45 | For instance, listen on channel x, filter the events and broadcast alerts on channel y | ||
46 | or send IM, emails etc. | ||
47 | |||
48 | |||
49 | USAGE: | ||
50 | |||
51 | Add "yp" as an allowed compiler | ||
52 | |||
53 | OpenSim.ini | ||
54 | [ScriptEngine.DotNetEngine] | ||
55 | AllowedCompilers=lsl,cs,js,vb,yp | ||
56 | |||
57 | Enter scripts using the inworld editing process. Scripts have the following format. | ||
58 | The first line of a file must have "//yp". | ||
59 | |||
60 | //yp | ||
61 | <PROLOG CODE> | ||
62 | //CS | ||
63 | <CS CODE> | ||
64 | |||
65 | |||
66 | |||
67 | |||
68 | |||
69 | |||
70 | C# code calling a Prolog Predicate: | ||
71 | ----------------------------------- | ||
72 | The Prolog predicate is transformed into a C# boolean function. So the general calling format is: | ||
73 | foreach( bool var in prolog_predicate(ARGS)) {}; | ||
74 | |||
75 | I/O is via using a string reader and writer in conjunction with YP.See() and YP.Tell() | ||
76 | |||
77 | StringWriter PrologOutuput= new StringWriter(); | ||
78 | StringReader PrologInput= new StringReader(myInputString); | ||
79 | YP.see(PrologInput); | ||
80 | YP.tell(PrologOutuput); | ||
81 | <CALL PROLOG CODE HERE> | ||
82 | YP.seen(); | ||
83 | YP.told(); | ||
84 | StringBuilder builder = PrologOutput.GetStringBuilder(); | ||
85 | string finaloutput = builder.ToString(); | ||
86 | |||
87 | Any prolog reads and writes will be to the passed StringReader and StringWriter. In fact any TextReader/TextWriter class can be used. | ||
88 | |||
89 | Strings in Prolog are stored as Atom's and you need to use an Atom object to match. | ||
90 | |||
91 | \\yp | ||
92 | wanted('bob'). | ||
93 | \\cs | ||
94 | string Who="bob"; | ||
95 | foreach( bool ans in wanted(Atom.a(Who) )){}; | ||
96 | |||
97 | |||
98 | Prolog code calling a C# function: | ||
99 | ----------------------------------- | ||
100 | The prolog code uses the script_event('name_of_function',ARGS) builtin, which is transformed into the function call. | ||
101 | The C# function called uses "PrologCallback" and returns a boolean. | ||
102 | |||
103 | |||
104 | |||
105 | Dynamic database assertions: | ||
106 | ----------------------------------- | ||
107 | |||
108 | void assertdb2(string predicate, string arg1, string arg2) | ||
109 | { | ||
110 | name = Atom.a(predicate); | ||
111 | YP.assertFact(name, new object[] { arg1, arg2 }); | ||
112 | } | ||
113 | |||
114 | void retractdb2(string predicate, string arg1, string arg2) | ||
115 | { | ||
116 | name = Atom.a(predicate); | ||
117 | YP.retractFact(name, new object[] { arg1, arg2 }); | ||
118 | } | ||
119 | |||
120 | |||
121 | ========================= APPENDIX A: touch test ================================ | ||
122 | |||
123 | |||
124 | =================================== | ||
125 | Input YP Code | ||
126 | =================================== | ||
127 | //yp | ||
128 | mydb('field2','field1'). | ||
129 | mydb('andy','jane'). | ||
130 | mydb('carl','dan'). | ||
131 | mydb('andy','bill'). | ||
132 | mydb('andy','betty'). | ||
133 | |||
134 | call_me(X):-mydb(X,Y) , respond(Y). | ||
135 | respond(X):- script_event('sayit',X). | ||
136 | |||
137 | //cs | ||
138 | public void default_event_touch_start(int N ) | ||
139 | { | ||
140 | llSay(0,"pstart1"); | ||
141 | foreach( bool ans in call_me(Atom.a(@"andy") )){}; | ||
142 | llSay(0,"pstop2"); | ||
143 | } | ||
144 | |||
145 | public void default_event_state_entry() | ||
146 | { | ||
147 | llSay(0,"prolog tester active."); | ||
148 | } | ||
149 | |||
150 | PrologCallback sayit(object ans) | ||
151 | { | ||
152 | llSay(0,"sayit1"); | ||
153 | string msg = "one answer is :"+((Variable)ans).getValue(); | ||
154 | llSay(0,msg); | ||
155 | yield return false; | ||
156 | } | ||
157 | |||
158 | |||
159 | =================================== | ||
160 | Generated CS Code | ||
161 | =================================== | ||
162 | using OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.YieldProlog;using OpenSim.Region.ScriptEngine.Common; using System.Collections.Generic; | ||
163 | namespace SecondLife { public class Script : OpenSim.Region.ScriptEngine.Common.BuiltIn_Commands_BaseClass { | ||
164 | static OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.YieldProlog.YP YP=null;public Script() { YP= new OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.YieldProlog.YP(); } | ||
165 | //cs | ||
166 | public void default_event_touch_start(int N ) | ||
167 | { | ||
168 | llSay(0,"pstart1"); | ||
169 | foreach( bool ans in call_me(Atom.a(@"carl") )){}; | ||
170 | llSay(0,"pstop2"); | ||
171 | } | ||
172 | |||
173 | public void default_event_state_entry() | ||
174 | { | ||
175 | llSay(0,"prolog tester active."); | ||
176 | } | ||
177 | |||
178 | public IEnumerable<bool> sayit(object ans) | ||
179 | { | ||
180 | llSay(0,"sayit1"); | ||
181 | string msg = "one answer is :"+((Variable)ans).getValue(); | ||
182 | llSay(0,msg); | ||
183 | yield return false; | ||
184 | } | ||
185 | |||
186 | |||
187 | //YPEncoded | ||
188 | public IEnumerable<bool> mydb(object arg1, object arg2) { | ||
189 | { | ||
190 | foreach (bool l2 in YP.unify(arg1, Atom.a(@"carl"))) { | ||
191 | foreach (bool l3 in YP.unify(arg2, Atom.a(@"dan"))) { | ||
192 | yield return false; | ||
193 | } | ||
194 | } | ||
195 | } | ||
196 | { | ||
197 | foreach (bool l2 in YP.unify(arg1, Atom.a(@"andy"))) { | ||
198 | foreach (bool l3 in YP.unify(arg2, Atom.a(@"bill"))) { | ||
199 | yield return false; | ||
200 | } | ||
201 | } | ||
202 | } | ||
203 | { | ||
204 | foreach (bool l2 in YP.unify(arg1, Atom.a(@"andy"))) { | ||
205 | foreach (bool l3 in YP.unify(arg2, Atom.a(@"betty"))) { | ||
206 | yield return false; | ||
207 | } | ||
208 | } | ||
209 | } | ||
210 | } | ||
211 | |||
212 | public IEnumerable<bool> call_me(object X) { | ||
213 | { | ||
214 | Variable Y = new Variable(); | ||
215 | foreach (bool l2 in mydb(X, Y)) { | ||
216 | foreach (bool l3 in respond(Y)) { | ||
217 | yield return false; | ||
218 | } | ||
219 | } | ||
220 | } | ||
221 | } | ||
222 | |||
223 | public IEnumerable<bool> respond(object X) { | ||
224 | { | ||
225 | foreach (bool l2 in this.sayit( X)) { | ||
226 | yield return false; | ||
227 | } | ||
228 | } | ||
229 | } | ||
230 | |||
231 | } } | ||
232 | |||
233 | |||
234 | |||
235 | ========================= APPENDIX B:SENSOR INFORMED SCRIPT ===================== | ||
236 | |||
237 | |||
238 | =================================== | ||
239 | Input YP Code | ||
240 | =================================== | ||
241 | //yp | ||
242 | |||
243 | nop. | ||
244 | |||
245 | good('Daxxon Kinoc'). | ||
246 | good('Fluffy Kitty'). | ||
247 | |||
248 | bad('Eric Evil'). | ||
249 | bad('Spikey Plant'). | ||
250 | |||
251 | prolog_notify(X) :- good(X) , script_event('accept',X). | ||
252 | prolog_notify(X) :- bad(X) , script_event('reject',X). | ||
253 | |||
254 | |||
255 | //cs | ||
256 | |||
257 | public void default_event_state_entry() | ||
258 | { | ||
259 | llSay(0,"prolog sensor tester active."); | ||
260 | |||
261 | // Start a sensor looking for Agents | ||
262 | llSensorRepeat("","",AGENT, 10, PI,20); | ||
263 | |||
264 | } | ||
265 | |||
266 | public void default_event_sensor(int number_detected ) | ||
267 | { | ||
268 | int i; | ||
269 | for(i=0;i< number_detected ;i++) | ||
270 | { | ||
271 | string dName = llDetectedName(i); | ||
272 | string dOwner = llDetectedName(i); | ||
273 | foreach(bool response in prolog_notify(Atom.a(dName)) ){}; | ||
274 | foreach(bool response in prolog_notify(dOwner) ){}; | ||
275 | llSay(0,"Saw "+dName); | ||
276 | } | ||
277 | } | ||
278 | |||
279 | string decodeToString(object obj) | ||
280 | { | ||
281 | if (obj is Variable) { return (string) ((Variable)obj).getValue();} | ||
282 | if (obj is Atom) { return (string) ((Atom)obj)._name;} | ||
283 | return "unknown type"; | ||
284 | } | ||
285 | |||
286 | PrologCallback accept(object ans) | ||
287 | { | ||
288 | string msg = "Welcoming :"+decodeToString(ans); | ||
289 | llSay(0,msg); | ||
290 | yield return false; | ||
291 | } | ||
292 | |||
293 | PrologCallback reject(object ans) | ||
294 | { | ||
295 | string msg = "Watching :"+decodeToString(ans); | ||
296 | llSay(0,msg); | ||
297 | yield return false; | ||
298 | } | ||
299 | |||
300 | |||
301 | =================================== | ||
302 | Generated CS Code | ||
303 | =================================== | ||
304 | |||
305 | using OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.YieldProlog; using OpenSim.Region.ScriptEngine.Common; using System.Collections.Generic; | ||
306 | namespace SecondLife { public class Script : OpenSim.Region.ScriptEngine.Common.BuiltIn_Commands_BaseClass { | ||
307 | static OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.YieldProlog.YP YP=null; public Script() { YP= new OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.YieldProlog.YP(); } | ||
308 | //cs | ||
309 | |||
310 | public void default_event_state_entry() | ||
311 | { | ||
312 | llSay(0,"prolog sensor tester active."); | ||
313 | |||
314 | // Start a sensor looking for Agents | ||
315 | llSensorRepeat("","",AGENT, 10, PI,20); | ||
316 | |||
317 | } | ||
318 | |||
319 | public void default_event_sensor(int number_detected ) | ||
320 | { | ||
321 | int i; | ||
322 | for(i=0;i< number_detected ;i++) | ||
323 | { | ||
324 | string dName = llDetectedName(i); | ||
325 | string dOwner = llDetectedName(i); | ||
326 | foreach(bool response in prolog_notify(Atom.a(dName)) ){}; | ||
327 | foreach(bool response in prolog_notify(dOwner) ){}; | ||
328 | llSay(0,"Saw "+dName); | ||
329 | } | ||
330 | } | ||
331 | |||
332 | string decodeToString(object obj) | ||
333 | { | ||
334 | if (obj is Variable) { return (string) ((Variable)obj).getValue();} | ||
335 | if (obj is Atom) { return (string) ((Atom)obj)._name;} | ||
336 | return "unknown type"; | ||
337 | } | ||
338 | |||
339 | public IEnumerable<bool> accept(object ans) | ||
340 | { | ||
341 | string msg = "Welcoming :"+decodeToString(ans); | ||
342 | llSay(0,msg); | ||
343 | yield return false; | ||
344 | } | ||
345 | |||
346 | public IEnumerable<bool> reject(object ans) | ||
347 | { | ||
348 | string msg = "Watching :"+decodeToString(ans); | ||
349 | llSay(0,msg); | ||
350 | yield return false; | ||
351 | } | ||
352 | |||
353 | |||
354 | //YPEncoded | ||
355 | public IEnumerable<bool> yp_nop_header_nop() { | ||
356 | { | ||
357 | yield return false; | ||
358 | } | ||
359 | } | ||
360 | |||
361 | public IEnumerable<bool> good(object arg1) { | ||
362 | { | ||
363 | foreach (bool l2 in YP.unify(arg1, Atom.a(@"Daxxon Kinoc"))) { | ||
364 | yield return false; | ||
365 | } | ||
366 | } | ||
367 | { | ||
368 | foreach (bool l2 in YP.unify(arg1, Atom.a(@"Fluffy Kitty"))) { | ||
369 | yield return false; | ||
370 | } | ||
371 | } | ||
372 | } | ||
373 | |||
374 | public IEnumerable<bool> bad(object arg1) { | ||
375 | { | ||
376 | foreach (bool l2 in YP.unify(arg1, Atom.a(@"Eric Evil"))) { | ||
377 | yield return false; | ||
378 | } | ||
379 | } | ||
380 | { | ||
381 | foreach (bool l2 in YP.unify(arg1, Atom.a(@"Spikey Plant"))) { | ||
382 | yield return false; | ||
383 | } | ||
384 | } | ||
385 | } | ||
386 | |||
387 | public IEnumerable<bool> prolog_notify(object X) { | ||
388 | { | ||
389 | foreach (bool l2 in good(X)) { | ||
390 | foreach (bool l3 in this.accept( X)) { | ||
391 | yield return false; | ||
392 | } | ||
393 | } | ||
394 | } | ||
395 | { | ||
396 | foreach (bool l2 in bad(X)) { | ||
397 | foreach (bool l3 in this.reject( X)) { | ||
398 | yield return false; | ||
399 | } | ||
400 | } | ||
401 | } | ||
402 | } | ||
403 | |||
404 | } } | ||
405 | |||