[Opensim-dev] Yield Prolog ported to OpenSim scripting

kino at daxtron.com kino at daxtron.com
Sun May 18 20:31:20 UTC 2008


Hello,

I recently submitted a patch for Prolog as a scripting language.
http://opensimulator.org/mantis/view.php?id=1314

It uses a //YP section to indicate the prolog code section followed by a //CS section.

The current system is about the power of original Turbo Prolog. It compiles the Prolog into C# that is compatible with the existing C# scripting. It does support dynamic data but not dynamic rules yet. It does support most of the basic functionality of Prolog, being able to do declaritive programming and logic.

Currently Jeff Thompson would like it to keep the "static" declarations which I strip out. However, the compiler can also generates Javascript or Python, each of which are part of the Opensim language set (or will be). So if dynamic rules cannot be supported without a "static" declaration in C# , it could be by generating say Python, without affecting any created scripts.

Below is the core of the Readme.txt file (and the mantis entry). 

I think this might be something that people doing virtual data centers and NPC might be interested in.

Bests,
Kino Coursey
Daxtron Labs


====================================
YPOS: YieldProlog for OpenSim

 a compiler from Prolog to OpenSim compatible C# scripts

Ported by Kino Coursey and Douglas Miles at Daxtron Labs.
Based on Jeff Thompson Yield Prolog,  http://yieldprolog.sourceforge.net/
For Prolog see  http://en.wikipedia.org/wiki/Prolog


INTRODUCTION

This folder contains code to implement a Prolog compiler using the "Yield Statement" found in C#, Javascript, and Python.
The original Yield Prolog system can transform Prolog programs into C# code.
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").
The YP code is transformed to C# and prepended to the "//CS" section, and passed as a bundel to the existing C# compiler.
The end result is Prolog can interface to OpenSim using the existing "//CS" functionality, and C# can call the compiled Prolog.
As such YP allows both declaritive and procedural programming in a 3D script enabled environment.

FEATURES
* Allows implementation of logic programming for objects and agents.
* C#/Javascript/Python as intermediate language
* Yield Prolog has relatively high speed of execution which is important in OpenSim.  http://yieldprolog.sourceforge.net/benchmarks.html
* It is compatable with the existing C#/Mono based system.
* Yield Prolog is BSD license
* Calling Prolog from C# scripts
* Calling C# functions (with LSL and OS functions) from Prolog
* Prolog dynamic database
* Edinburgh, Cocksin & Mellish style syntax.
* Compiler is generated by compiling the Prolog descrition of itself into C#
* Same script entry interface as LSL


TODO 
* Utilize ability to generate Javascript and Python code
* Integrate Prolog database with Sim
* Translation error reporting back to the editor
* Communications via message passing
* Interface to external inference engines

POSSIBILITIES
* Inworld expert systems
* Parallel logic programming and expert systems
* Ontology based processing
* Knowledge based alerting, accessing and business rules
   For instance, listen on channel x, filter the events and broadcast alerts on channel y
     or send IM, emails etc.


USAGE:

Add "yp" as an allowed compiler
 
OpenSim.ini 
[ScriptEngine.DotNetEngine]
AllowedCompilers=lsl,cs,js,vb,yp

Enter scripts using the inworld editing process. Scripts have the following format.
The first line of a file must have "//yp".

//yp
<PROLOG CODE>
//CS
<CS CODE>


C# code calling a Prolog Predicate:
-----------------------------------
The Prolog predicate is transformed into a C# boolean function. So the general calling format is:
	foreach( bool var in  prolog_predicate(ARGS)) {};

I/O is via using a string reader and writer in conjunction with YP.See() and YP.Tell()

            StringWriter PrologOutuput= new StringWriter();
            StringReader PrologInput= new StringReader(myInputString);
            YP.see(PrologInput);
            YP.tell(PrologOutuput);
	    <CALL PROLOG CODE HERE>
	    YP.seen();
	    YP.told();
	    StringBuilder builder = PrologOutput.GetStringBuilder();
	    string finaloutput = builder.ToString();

Any prolog reads and writes will be to the passed StringReader and StringWriter. In fact any TextReader/TextWriter class can be used.

Strings in Prolog are stored as Atom's and you need to use an Atom object to match.

\\yp
wanted('bob').
\\cs
string Who="bob";
foreach( bool ans in wanted(Atom.a(Who) )){};


Prolog code calling a C# function:
-----------------------------------
The prolog code uses the script_event('name_of_function',ARGS) builtin, which is transformed into the function call.
The C# function called uses "PrologCallback" and returns a boolean.


Dynamic database assertions:
-----------------------------------

void assertdb2(string predicate, string arg1, string arg2)
{
        name = Atom.a(predicate);
        YP.assertFact(name, new object[] { arg1, arg2 });
}

void retractdb2(string predicate, string arg1, string arg2)
{
        name = Atom.a(predicate);
        YP.retractFact(name, new object[] { arg1, arg2 });
}


========================= APPENDIX A: touch test ================================

 ===================================
Input YP Code
 ===================================
//yp
 mydb('field2','field1').
 mydb('andy','jane').
 mydb('carl','dan').
 mydb('andy','bill').
 mydb('andy','betty').
 
 call_me(X):-mydb(X,Y) , respond(Y).
 respond(X):- script_event('sayit',X).

//cs
  public void default_event_touch_start(int N ) 
  {
      llSay(0,"pstart1");
      foreach( bool ans in call_me(Atom.a(@"andy") )){};
      llSay(0,"pstop2");
  }
  
  public void default_event_state_entry()
  {
     llSay(0,"prolog tester active.");  
  }

PrologCallback sayit(object ans)
  {
      llSay(0,"sayit1");
      string msg = "one answer is :"+((Variable)ans).getValue();  
      llSay(0,msg); 
      yield return false;
  }


 
========================= APPENDIX B:SENSOR INFORMED SCRIPT =====================


 ===================================
Input YP Code
 ===================================
//yp

nop.

good('Daxxon Kinoc').
good('Fluffy Kitty').

bad('Eric Evil').
bad('Spikey Plant').

prolog_notify(X) :- good(X) , script_event('accept',X).
prolog_notify(X) :- bad(X) , script_event('reject',X).


//cs

public void default_event_state_entry()
  {
     llSay(0,"prolog sensor tester active.");

    // Start a sensor looking for Agents
     llSensorRepeat("","",AGENT, 10, PI,20); 

  }

public void default_event_sensor(int number_detected )
{
  int i;
  for(i=0;i< number_detected ;i++)
   {
    string dName = llDetectedName(i);
    string dOwner = llDetectedName(i);
    foreach(bool response in prolog_notify(Atom.a(dName)) ){};
    foreach(bool response in prolog_notify(dOwner) ){};
    llSay(0,"Saw "+dName);
   }
}

string decodeToString(object obj)
{
    if (obj is Variable) { return (string) ((Variable)obj).getValue();}
    if (obj is Atom) { return (string) ((Atom)obj)._name;}
    return "unknown type";
}

PrologCallback accept(object ans)
  {
      string msg = "Welcoming :"+decodeToString(ans);  
      llSay(0,msg); 
      yield return false;
  }

PrologCallback reject(object ans)
  {
      string msg = "Watching :"+decodeToString(ans);  
      llSay(0,msg); 
      yield return false;
  }


 



More information about the Opensim-dev mailing list