Your SlideShare is downloading. ×
  • Like
Turtle Graphics in Groovy
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Now you can save presentations on your phone or tablet

Available for both IPhone and Android

Text the download link to your phone

Standard text messaging rates apply

Turtle Graphics in Groovy

  • 417 views
Published

Using DSL techniques to recreate the children's learning tool

Using DSL techniques to recreate the children's learning tool

Published in Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
    Be the first to like this
No Downloads

Views

Total Views
417
On SlideShare
0
From Embeds
0
Number of Embeds
2

Actions

Shares
Downloads
3
Comments
0
Likes
0

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. <Insert Picture Here> Turtle Graphics in Groovy Jim Driscoll
  • 2. 2 My Background • ADFm – Part of Oracle's ADF Framework – Provides data binding and database access – Provides ways to customize data views via Groovy – Groovy uses have basic DSL customizations • Wanted to Learn JavaFX (after last year's GR8 Conf) • Have 5 year old daughter • Napili – named after the Maui bay
  • 3. 3 Logo • An early programming language (1960's) • Popular in the 80's as a teaching tool – Which is how I first heard about it • A dialect of Lisp (but much more approachable) • Currently (per Wikipedia) 197 different dialects • Most famous for it's use of Turtle Graphics
  • 4. 4 Turtle Graphics • Vector based graphics using a relative cursor – The “Turtle” – Represented in early work as a triangle • Turtles have three attributes – A location – An orientation – A “pen” (which has on/off state, color, width, etc)
  • 5. 5 Turtle Commands • home • left / right (takes int arg, degrees) • forward / back (takes int arg, #pixels) • penup / pendown • pencolor (takes Color arg) • show / hide • speed (takes int arg)
  • 6. 6 Language Style • Commands without parens – left 90, home, hide, etc • Chained Commands – left 90 forward 100 hide (as one line) • Use with an explicit turtle, or with an implicit turtle • Use Groovy language constructs – Define variables – Define methods – Closures
  • 7. 7 Language Decisions – DSL vs GPL • DSL (Domain Specific Language) – A limited language, designed to be useful for a specific task – HTML, SQL, stuff you can build with Groovy Builders • GPL (General Purpose Language) – A general language, designed to be useful for any task – Java, Groovy, Assembler, etc • I went the GPLish route, full Groovy + DSL extensions – But there's not necessarily a one right answer
  • 8. 8 Demo
  • 9. 9 First, Create a Framework • Created a Turtle class, with supporting classes – Methods like #home(), #hide(), #forward(int), etc. • Allows drawing on a canvas via a turtle • Used JavaFX, including animations – This isn't a JavaFX talk... • Once that's all working, add the control language
  • 10. 10 Executing Programs In Memory • Object GroovyShell#evaluate(String) – Can be slow (10ms) • Cacheing Scripts – Script GroovyShell#parse(String) ← slow part (10ms) – Object Script#run() ← fast part (<1ms) GroovyShell shell = new GroovyShell(); Script script = shell.parse("println 'hello world'"); script.run();
  • 11. 11 Bindings – the Nouns • A Binding is a way to pass values in/out of a script – Used as unqualified variables (“println name”) – Declared varaibles (def) go into a separate space • Groovy provides a default Binding – But you can provide one of your own • Use it to provide – Constant values – Default values – Error checked values test = 1 println test def test = 0 println test binding.test
  • 12. 12 Bindings in Napili • Little used – But could be used much more • Just two variables, turtle and out • out – Special variable to redirect println output • turtle – Used for direct calls on the turtle • turtle.penup(), turtle.forward(100) will now work
  • 13. 13 Initialize Bindings in Napili static class BasicBinding extends Binding { Turtle turtle public BasicBinding() { super(); turtle = new Turtle() }
  • 14. 14 Getting Binding Values public Object getVariable(String name) { if (name == 'out') { return NapiliOutput.getPrintWriter(); } if (name == 'turtle') { return turtle; } return super.getVariable(name) }
  • 15. 15 Setting Binding Values 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); }
  • 16. 16 Using the Binding GroovyShell shell = new GroovyShell(config) Script script = shell.parse(scriptStr) script.setBinding(new BasicBinding()) script.run()
  • 17. 17 Adding Imports • Can add imports and static imports to scripts • Allows easy usage of existing classes • Added via CompilerConfiguration – An optional parameter to GroovyShell • Static imports can let you define variables – import static java.lang.Math.PI lets “println PI” work
  • 18. 18 Adding Imports in Napili CompilerConfiguration config = new CompilerConfiguration() ImportCustomizer ic = new ImportCustomizer(); ic.addImports('javafx.scene.paint.Color') config.addCompilationCustomizers(ic) GroovyShell shell = new GroovyShell(config) • Adds an automatic import for JavaFX's Color so... • turtle.pencolor(Color.Purple) now works • If we instead do a static import, we could just say Purple – ImportCustomizer#addStarImports(String)
  • 19. 19 ScriptBaseClass – the Verbs • Dynamically assign a new base class • Allows you to declare top level functions • Inserted as part of the CompilerConfiguration • Has access to Binding variables – Can be used for implicit parameter passing
  • 20. 20 ScriptBaseClass – example abstract class BaseScript extends Script { def forward(int i) { turtle.forward(i) } def right(int i) { turtle.right(i) } }
  • 21. 21 InvokeMethod • Allows you to dynamically route method calls – Lets you use a context object – GroovyInterceptable interface • Just add a #invokeMethod(String,args) function def invokeMethod(String name, args) { println name } def test() {println “hey”} hello() test()
  • 22. 22 MethodMissing • Allows you to specify new behavior if a method isn't found • Just add a #methodMissing(String,args) function • Combined with a ScriptBaseClass...
  • 23. 23 ScriptBaseClass in Napili abstract class TurtleDelegateBaseScript extends Script { // if we can't find the method, look for it on the turtle binding object def methodMissing(String name, args) { binding.turtle."$name"(* args) } } • Abstract class • Effectively reroutes all calls through Turtle
  • 24. 24 ScriptBaseClass in Napili CompilerConfiguration config = new CompilerConfiguration() config.setScriptBaseClass("fullpath.TurtleDelegateBaseScript") GroovyShell shell = new GroovyShell(config) • Now, “forward(100)” works • Because of optional parens, “forward 100” works too • But “home()” is required, “home” won't work...
  • 25. 25 No arg Methods • But what about “home” or “penup”? • They're seen as Binding variables • So, use the Binding to execute them: public Object getVariable(String name) { ... // 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) }
  • 26. 26 No arg Methods as Properties • Use #propertyMissing(String) on Turtle • Allows turtle.hide instead of turtle.hide() def propertyMissing(String name) { // treat all no-arg methods as properties if (this.metaClass.respondsTo(this, name)) { return this.metaClass.invokeMethod(this, name) } throw new MissingPropertyException("No property on Turtle named '$name'") }
  • 27. 27 Timeout protection • What about while (true) {}? • groovy.transform.TimedInterrupt CompilerConfiguration config = new CompilerConfiguration() config.setScriptBaseClass("org.netdance.napili.language.TurtleDelegateBaseScript") ImportCustomizer ic = new ImportCustomizer(); ic.addImports('javafx.scene.paint.Color') def ti = new ASTTransformationCustomizer([value: Napili.TIMEOUT],TimedInterrupt) config.addCompilationCustomizers(ic, ti) GroovyShell shell = new GroovyShell(config)
  • 28. 28 Recap • Create a Turtle object • Make it available to scripts via the Binding • Use ScriptBaseClass to route all method calls through it • ImportCustomizer to allow using JavaFX Color • TimedInterrupt to stop runaway processes
  • 29. 29 Method Chaining • You may have noticed.... – forward 100 back 100 hide • It's harder than it looks – first second third fourth == first(second).third(fourth) – first second third fourth fifth == first(second).third(fourth).fifth – GroovyConsole is great for understanding the parse rules • No arg methods break that flow – forward 100 hide home ← doesn't work
  • 30. 30 Removing Language Features • SecureASTCustomizer – Static Analysis – def s = Shell; s.exit(0) – (See my talk this afternoon for more on security) • Can be used to remove language features
  • 31. 31 Removing Increment Operator (++) def config = new CompilerConfiguration(); def customizer = new SecureASTCustomizer(); def tokens = [] tokens.add(Types.PLUS_PLUS); customizer.setTokensBlacklist(tokens); config.addCompilationCustomizers(customizer); def shell = new GroovyShell(config);
  • 32. 32 Removing For Loops def config = new CompilerConfiguration(); def customizer = new SecureASTCustomizer(); def statements = [] statements.add(ForStatement.class); customizer.setStatementsBlacklist(statements); config.addCompilationCustomizers(customizer); def shell = new GroovyShell(config);
  • 33. 33 Q&A
  • 34. 34 Resources • Napili Code – https://github.com/netdance/Napili • My Blog – https://jamesgdriscoll.wordpress.com/ • Books – Groovy in Action, 2nd ed (still in early access, but worth getting) – Groovy for Domain Specific Languages – DSLs in Action (multiple language examples)
  • 35. 35 The preceding is intended to outline our general product direction. It is intended for information purposes only, and may not be incorporated into any contract. It is not a commitment to deliver any material, code, or functionality, and should not be relied upon in making purchasing decisions. The development, release, and timing of any features or functionality described for Oracle’s products remains at the sole discretion of Oracle.
  • 36. 36