BUILDING DSL USING GROOVYGreach 2018
PUNEET BEHL
© 2018, Object Computing, Inc. (OCI). All rights reserved. No part of these notes may be reproduced, stored in a retrieval system,
or transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or otherwise, without the prior, written
objectcomputing.com
permission of Object Computing, Inc. (OCI)
About Me
About Me
Puneet Behl
Grails Team at OCI
Twitter: @puneetbhl
Email: [email protected]
Github: http://github.com/puneetbehl/
© 2018, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com
Team includes Grails co-founders & subject matter experts from around
the globe
25+ updates & releases to the framework in the past 9 months
Grails 3.3 GA released July 2017
© 2018, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com
WE ARE SOFTWARE ENGINEERS.
We deliver mission-critical software solutions that accelerate innovation within
your organization and stand up to the evolving demands of your business.
AREAS OF EXPERTISE
INDUSTRIAL IoT MACHINE LEARNING
We equip industrial environments We can modernize your legacy
with seamless connectivity and applications and enable scalable,
real-time analytics that reduce integrated AI capabilities tailored
operating costs and deliver on to your unique sets of data.
customer demands.
BLOCKCHAIN CONSULTING CLOUD SOLUTIONS
We are at the forefront of blockchain We combine software engineering
technology, and we have practical, expertise with cloud-native
real-world experience with its architecture to accelerate innovation
implementation. within your organization.
© 2018, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com
PARTIAL CLIENT LIST
90%
Repeat Clients
© 2018, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com
OUR COMMUNITY OF OPEN SOURCE PARTNERS
© 2018, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com
OUR GLOBAL FOOTPRINT
160+
Engineers
MS/PHDAdvanced
19
Security Clearance
Average Years
Engineering
Experience
14
Average Years
OCI Tenure
© 2018, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com
Agenda
1. Introduction to DSL 1. Writing your own DSL
2. Characteristics of DSL 2. Security
3. Pros & Cons
4. Why use Groovy
© 2018, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com
What is DSL?
A computer language specialized to solve a particular application domain
Not intended to be broadly applicable across domains
Syntax is focused on intended domain or problem
Small and simple
© 2018, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com
Examples
© 2018, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com
Characteristics of DSL
Highly Context Sensitive
Fluency
© 2018, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com
Characteristics of DSL - Highly Context Sensitive
List<String> employees = ["Puneet", "Ivan"]
employees.with {
add "Graeme"
add "Jeff"
}
© 2018, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com
Characteristics of DSL - Fluency
take 2.pills of chloroquinine after 6.hours
© 2018, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com
Pros & Cons of DSL
Pros
Cons
Domain Experts can help, modify,
validate and often develop DSL Learning cost
Self Documenting Cost of designing,
Enhance quality, productivity, implementing and
reliability, maintainability, portability maintaining DSL
and reusability
Safety, as long as language
Tools and IDE support
constructs are safe, any DSL content Attaining proper scope
can be considered safe.
© 2018, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com
Why use Groovy
© 2018, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com
Why use Groovy - Sample Java Code to Read File
package greachdemo.examples; static String readFile(String path) {
import java.io.BufferedReader; StringBuilder builder = new StringBuilder();
import java.io.FileNotFoundException; try {
import java.io.FileReader; BufferedReader reader = new BufferedReader(
import java.io.IOException; new FileReader(path)
public class FileDemo { );
public static void main(String[] args) { String aLine = null;
String content = readFile("settings.gradle"); try {
System.out.println(content); while ((aLine = reader.readLine()) != null) {
} builder.append(aLine + System.getProperty("line.separator"));
} }
} catch (IOException io) {
io.printStackTrace();
}
} catch (FileNotFoundException f) {
f.printStackTrace();
;
}
return builder.toString();
}
}
© 2018, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com
Why use Groovy - Groovy Code
package greachdemo.examples; static String readFile(String path) {
import java.io.BufferedReader; StringBuilder builder = new StringBuilder();
import java.io.FileNotFoundException; try {
import java.io.FileReader; BufferedReader reader = new BufferedReader(
import java.io.IOException; new FileReader(path)
public class FileDemo { );
public static void main(String[] args) { String aLine = null;
String content = readFile("settings.gradle"); try {
System.out.println(content); while ((aLine = reader.readLine()) != null) {
} builder.append(aLine + System.getProperty("line.separator"));
} }
} catch (IOException io) {
io.printStackTrace();
}
} catch (FileNotFoundException f) {
f.printStackTrace();
;
}
return builder.toString();
}
}
new File("./settings.gradle").text
© 2018, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com
Some Useful Groovy Features
No need to create a class, use scripts
Optional typing
Native Syntax Constructs
Parenthesis and semi-colons are optional
Named arguments
Closure for custom control structures
Command Chains
Operator Overloading
© 2018, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com
Command Chains
// equivalent to: take(2.pills).of(chloroquinine).after(6.hours)
take 2.pills of chloroquinine after 6.hours
© 2018, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com
Operator Overloading
http://docs.groovy-lang.org/docs/latest/html/documentation/core-domain-specific-languages.
html#_operator_overloading
© 2018, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com
Binding variables to the script
def binding = new Binding()
def shell = new GroovyShell(binding)
binding.setVariable('x',1)
binding.setVariable('y',3)
shell.evaluate 'z=2*x+y'
assert binding.getVariable('z') == 5
© 2018, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com
The Script class
abstract class MyBaseClass extends Script {
String name
public void greet() { println "Hello, $name!" }
}
def config = new CompilerConfiguration()
config.scriptBaseClass = 'MyBaseClass'
def shell = new GroovyShell(this.class.classLoader, config)
shell.evaluate """
setName 'Judith'
greet()
“""
“Or”
@BaseScript(MyBaseClass)
import groovy.transform.BaseScript
setName 'Judith'
greet()
© 2018, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com
Adding Properties to Numbers
Categories
ExpandoMetaClass
use(TimeCategory) { Number.metaClass.getDollars = {->
println 1.minute.from.now new Currency(delegate, Unit.dollars)
println 10.hours.ago }
def someDate = new Date() Number.metaClass.getINR = {->
println someDate - 3.months new Currency(delegate, Unit.INR)
} }
Number.metaClass.getEuros = {->
new Currency(delegate, Unit.euros)
}
© 2018, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com
Compilation Customizers
ImportCustomizer: add transpirent import
ASTTransformationCustomizer: inject AST transform
SecureASTCustomizer: restrictions
© 2018, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com
Compilation Customizers - ImportCustomizer
package greachdemo.researchwork
import org.codehaus.groovy.control.CompilerConfiguration
import org.codehaus.groovy.control.customizers.ImportCustomizer
def configuration = new CompilerConfiguration()
def imports = new ImportCustomizer()
imports.addStaticStars(Direction.name)
configuration.addCompilationCustomizers(imports)
new GroovyShell(new Binding([bike: new BiCycle()]), configuration).evaluate('''
bike.go forward
''')
© 2018, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com
Compilation Customizers - ASTTransformationCustomizer
allow/disallow creation of closures
allow/disallow imports
allow/disallow package definition
allow/disallow definition of methods
restrict the receivers of method calls
restrict the kind of AST expressions a user can use
restrict the tokens (grammar-wise) a user can use
restrict the types of the constants that can be used in code
© 2018, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com
Writing your own DSL
© 2018, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com
Writing your own DSL - The Problem
Let’s assume we are writing the DSL for
giving instructions to the Robot on
bicycle.
© 2018, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com
Assumptions
We will not be bothered about balancing problem in this presentation.
© 2018, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com
What do we want to achieve?
Build a computer language which is easy to understand by our engineers working
with the robot. For example:
go forward at 1.km/h
doStunt airborne
doStunt bunnyHop
doStunt rotateHandle
doStunt barSpin
ring bell
turn left
© 2018, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com
Let’s Code …
© 2018, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com
Let’s Code - Java Version
package greachdemo.demo01;
import greachdemo.researchwork.Direction;
public class Bike {
public static void main(String[] args) {
Bike bike = new Bike();
bike.go(Direction.forward);
}
Bike go(Direction direction) {
return this;
}
}
© 2018, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com
Let’s Code - Groovy Version
package greachdemo.demo01;
import greachdemo.researchwork.Direction
import static greachdemo.researchwork.Direction.forward
class Bike {
Bike go(Direction direction) {
return this
}
}
Bike bike = new Bike()
bike.go forward
© 2018, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com
Let’s Code - Groovy Version
package greachdemo.demo01;
import greachdemo.researchwork.Direction;
public class Bike {
public static void main(String[] args) {
Bike bike = new Bike();
bike.move(Direction.forward);
}
Bike move(Direction direction) {
return this;
}
}
© 2018, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com
References
https://www.designboom.com (Robot Image)
http://groovy-lang.org/documentation.html
© 2018, Object Computing, Inc. (OCI). All rights reserved. objectcomputing.com