Archive

Posts Tagged ‘scripting’

Scripting JSoar

August 30th, 2010 No comments

In simpler times (say 2001) Soar was just Tcl. That is to say, Soar was a module, dynamically loaded into a Tcl interpreter at run-time. When loaded, Soar added a bunch of useful commands to the interpreter. Like run, matches, preferences, and probably most importantly, the sp command. When you “sourced” a Soar file, the Tcl interpreter just executed commands, loading rules, setting watch levels, etc.

The main drawback to this whole situation was that Tcl didn’t always lend itself to friendly embedding in other programs. It had funny rules about threads and, if Tk was involved, demanded to have its message queue pumped. And, of course, very few people get to know Tcl enough to like it :)

On the other hand, you could create macros for repetitive Soar structures, define new RHS functions, manipulate I/O. In short, you had the power of a full programming language mixed in with your Soar code.

With Soar 8.6 Soar’s tight integration with Tcl was broken, replaced by SML and a stricter command interpreter. It still looked like Tcl commands, but there were no Tcl control structures, variables, etc. Way it goes. When I initially started work on JSoar, I needed to quickly bootstrap a command interpreter so I could load existing code into the kernel. I turned to Tcl, in the form of Jacl, a Java implementation of Tcl. It saved a lot of time and, since Soar’s syntax was still basically Tcl, no one would really notice.

Of course, as I mentioned, no one wants Tcl, so over the last couple weeks, I’ve added a new scripting layer to JSoar. This time, I’m taking advantage of the Java Scripting API, JSR-223. This allows any scripting language with a JSR-223 implementation to be pretty seamlessly accessed from Java (and vice versa). With this new capability, it’s now possible to automate Soar agents, implement simple agent environments, and extend SoarUnit testing to include I/O, all from within a Soar source file. All with a variety of languages including Ruby, JavaScript, Python, Clojure, Groovy, etc.

A scripting engine (a language implementation) is invoked with the script command:

script javascript {
   soar.onInput(function(e) {
      soar.wmes.add("my-input", "hello");
   });
   soar.onOutputCommand("say", function(e) {
      soar.print("The agent says: " + e.greeting);
   });
}

This little bit of code sets up an input phase callback and creates a WME on the agen’ts input-link. It also handles an output command called “say”. The equivalent Java code would be … more ceremonious. Not to mention setting up a new project, compiling, etc, etc is a major hassle.

As an example, I’ve implemented a simple waterjugs environment in JavaScript, Ruby, and Python. Here are some things you can do:

  • Generate input
  • Handle output commands
  • Auto-convert hashes (JavaScript objects, Python dicts, or Ruby hashes) to input structures
  • Install new RHS functions
  • Add new commands
  • and on and on

Also, with maybe a little more work, I might have a pretty good story for dealing with I/O in SoarUnit tests. Stay tuned.

More detailed info on JSoar scripting support can be found on the JSoar wiki.

Remedial Scala: Interpreting Scala from Scala

January 25th, 2009 1 comment

For my “learning Scala” project, rooscaloo, I needed to dynamically generate and compile Scala code as rules are loaded into the engine. I had initially intended to do this as an internal DSL, but I honestly couldn’t think of a way to handle the fact that variables are bound at match time in the rete network. This is a learning project anyway, so I decided to just generate code and compile it.  Now, I could have sworn I had seen a Scala scripting example using JSR-223 in a blog somewhere, but couldn’t find it again.  I only found one very basic example of how to do this, in the Scala bug tracker. So I figured I’d write down what I came up with.

Note that this code makes use of the scala.tools.nsc package which is not part of the standard Scala library. Thus, it may change in future versions of Scala. Also note that after the fact, I was able to track down two partial JSR-223 implementations here and here. It’s comforting that I ended up in basically the same place.

The example given in the bug tracker works, but it’s very simple and there are two things it doesn’t do. First, it prints all its output to stdout, including error information. Second, it doesn’t show how to retrieve results from executing scripts. That is, code goes in, but nothing comes out. These are both solved pretty easily.  In the first case, we simply supply our own PrintWriter when instantiating the internal Scala interpreter:

  private val writer = new java.io.StringWriter()
  private val interpreter = new ScalaInterpreter(new Settings(), 
                                                 new PrintWriter(writer));

  ...

  def exec(code : String) {
    // Clear the previous output buffer
    writer.getBuffer.setLength(0)

    // Execute the code and catch the result
    val ir = interpreter.interpret(code);

    // Return value or throw an exception based on result
    ir match {
      case Success => ()
      case Error => throw new ScriptException("error in: '" +
                                              code + "'\n" + writer toString)
      case Incomplete => throw new ScriptException("incomplete in :'" + 
                                                   code + "'\n" + writer toString)
    }
  }

For the second issue, returning results, I had to think a little longer, probably longer than necessary. scala.tools.nsc.Interpreter doesn’t return anything besides Success, Error, or Incomplete as seen above. But, you can pass objects in, so I ended up creating a container object to hold the result:

class ResultHolder(var value : Any)

  ...

  def eval(code : String) : Any = {
    // Clear the previous output buffer
    writer.getBuffer.setLength(0)

    // Create an object to hold the result and bind in the interpreter
    val holder = new ResultHolder(null)
    bind("$result__", holder);

    // Execute the code and catch the result
    val ir = interpreter.interpret("$result__.value = " + code);

    // Return value or throw an exception based on result
    ir match {
      case Success => holder.value
      case Error => throw new ScriptException("error in: '" + 
                                              code + "'\n" + writer toString)
      case Incomplete => throw new ScriptException("incomplete in :'" + 
                                                   code + "'\n" + writer toString)
    }
  }

As you can see, I ended up with two separate routines. exec executes a Scala statement, ignoring its return value. This is useful for imports, class declarations, anything that does not evaluate to a value.  eval executes a Scala statement, catches the result and returns it.

Anyway, that’s about it. It seems that full JSR-223 support is in the plan for Scala. Until then, what I have here works for me and it was a good learning experience. Here’s the full source for my solution.

Categories: scala Tags: ,