Jim Driscoll's Blog

Notes on Technology and the Web

Archive for November 2012

Turtle Graphics DSL Implementation, part 2

leave a comment »

In the previous post, I described the first part of how Napili implements a simple Turtle Graphics DSL.  Please follow the link to download the whole program, if you want to see the code in context.  This time, we’ll cover the Binding class.

As I’ve talked about before, the Binding class provides default values to variables.  I’ve also previously discussed Property Dispatch, as well as a trick in using the Binding to work around the problem of optional parenthesis only being possible for methods with arguments.  I’ll go over all of that again here, but just in case you’re joining us for the first time, rereading those older posts might be handy.

The BasicBinding class in Napili serves several purposes – it creates the Turtle object, and serves it out to either the user directly or via the BaseScript (as I covered in the previous post).  It also handles the “out” Binding variable (more on that later).  And it handles no-arg methods on the Turtle object.  Let’s go through the class, section by section, and we’ll discuss how it does that.

private static class BasicBinding extends Binding {
  Turtle turtle

  public BasicBinding() {
    super();
    turtle = new Turtle()
  }

This part should be self expanitory – the constructor  creates the Turtle object which is used to draw, and saves that for later use.

The next method, getVariable, provides the Binding variables to the user scripts.

  public Object getVariable(String name) {
    if (name == 'out') {
      return NapiliOutput.getPrintWriter();
    } 

out is a special value for Bindings – it’s the value that’s used by the println() method.  So, by supplying our own value for it, we can redirect user println calls from going to System.out (and the console) and instead send the output to somewhere more useful and visible to the user. In this case, that redirection happens to an output tab in the UI.

    if (name == 'turtle') {
      return turtle;
    }

The turtle variable is used in the BaseScript file we covered last time.  It’s also present for the user to manipulate directly – which could be handy for advanced users who want to create two or more turtles.

    // treat all no-arg methods on Turtle as binding variables with side effects
    if (turtle.metaClass.respondsTo(turtle,name)) {
      return turtle.metaClass.invokeMethod(turtle, name)
    }
    return super.getVariable(name)
  }

The next method, setVariable, isn’t anything special – since all the code will stop working in a strange and mysterious way if the value of turtle is overridden, don’t allow that to happen.

  public void setVariable(String name, Object value) {
    if ("turtle".equals(name)) {
      NapiliOutput.println('Unable to set "turtle" to value' + value)
      return;
    }
    super.setVariable(name, value);
  }
}

And that’s it.  I’ve now gone over all the DSL magic in the Groovy Turtle Graphics program.  Hopefully you found this relatively clear – if not, don’t hesitate to ask questions.  

Advertisements

Written by jamesgdriscoll

November 3, 2012 at 9:20 AM

Posted in DSL, Groovy