Skip to content

Commit

Permalink
doc: improve template documentation (#1068)
Browse files Browse the repository at this point in the history
  • Loading branch information
monperrus authored and surli committed Dec 22, 2016
1 parent d026cbc commit 7a55cd2
Show file tree
Hide file tree
Showing 4 changed files with 162 additions and 117 deletions.
30 changes: 0 additions & 30 deletions doc/template_can_be_templated.md

This file was deleted.

177 changes: 162 additions & 15 deletions doc/template_definition.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
---
title: Template definition
title: Transformation with Templates
tags: [template]
keywords: template, definition, code, java
last_updated: October 7, 2015
---

Spoon provides developers a way of writing code transformations:
code templates. Those templates are statically type-checked, in
Spoon provides developers a way of writing code transformations called
**code templates**. Those templates are statically type-checked, in
order to ensure statically that the generated code will be correct.
Our key idea behind Spoon templates is that they are regular Java code.
Hence, the type-checking is that of the Java compiler itself.

A Spoon template is a regular Java class that taken as input by the Spoon templating engine to perform a transformation.
This is summarized in Figure below. A Spoon template can be seen as a
higher-order program, which takes program elements as arguments, and returns a
transformed program. Like any function, a template can be used in different
contexts and give different results, depending on its parameters.

![Overview of Spoon's Templating System]({{ "/images/template-overview.svg" | prepend: site.baseurl }})

A Spoon template is a Java class that is type-checked by the Java compiler,
then taken as input by the Spoon templating engine to perform a transformation.
This is summarized in Figure above. A Spoon template can be seen as a
higher-order program, which takes program elements as arguments, and returns a
transformed program. Like any function, a template can be used in different
contexts and give different results, depending on its parameters.
Definition of templates
-----------------------

Class `CheckBoundTemplate` below defines a Spoon template.

```java
public class CheckBoundTemplate extends StatementTemplate {
Expand All @@ -31,7 +32,7 @@ public class CheckBoundTemplate extends StatementTemplate {
}
```

Class `CheckBoundTemplate` defines a Spoon template. This template specifies a
This template specifies a
statement (in method `statement`) that is a precondition to check that a list
is smaller than a certain size. This piece of code will be injected at the
beginning of all methods dealing with size-bounded lists. This template has
Expand All @@ -49,5 +50,151 @@ checked. Instead of being executed, the template source code is taken as input b
templating engine which is described above. Consequently, the template source is
well-typed, compiles, but the binary code of the template is thrown away.

There are three kinds of templates: block templates, statement templates and
expression templates. Their names denote the code grain they respectively address.
Template Instantiation
-------------

In order to be correctly substituted, the template parameters need
to be bound to actual values. This is done during template instantiation.

The code at the end of this page shows how to use the check-bound
of template, `CheckBoundTemplate`, presented in the previous section.
One first instantiates a template, then one sets the template parameters,
and finally, one calls the template engine. In last line, the bound check
is injected at the beginning of a method body.

Since the template is given the first method parameter which is in the
scope of the insertion location, the generated code is guaranteed to compile.
The Java compiler ensures that the template compiles with a given scope, the
developer is responsible for checking that the scope where she uses
template-generated code is consistent with the template scope.

```java
// creating a template instance
Template t = new CheckBoundTemplate();
t._col_ = createVariableAccess(method.getParameters().get(0));

// getting the final AST
CtStatement injectedCode = t.apply();

// adds the bound check at the beginning of a method
method.getBody().insertBegin(injectedCode);

```

Kinds of templating
-------------------

There are different kinds of templating.

#### Subclassing `StatementTemplate`
Using method `apply()` enables to get a new statement (see example `CheckBoundTemplate` above)

#### Subclassing `BlockTemplate`
Using method `apply()` enables to get a new block.

#### Subclassing `ExpressionTemplate`
Using method `apply()` enables to get a new expression. The core template method must be called `expression` and only contain a return with the expression to be templated.

#### Subclassing `ExtensionTemplate`
Using method `apply()` enables to get a new class where:

1) methods and field of the templates are injected in the target class

```java
public class ATemplate1 extends ExtensionTemplate {
int i;
void foo() {};
}

// inject `i` and `foo` in aCtClass
Substitution.insertAll(aCtClass, new ATemplate1());
```

2) parametrized superinterfaces are injected in the target class

```java
class ATemplate2 extends ExtensionTemplate implements Serializable, A, B {
// interface templates supports TypeReference
@Parameter
Class A;
}

Template t = new ATemplate2();
t.A = Comparable.class
Substitution.insertAll(aCtClass, t);
// aCtClass now implements Serializable and Serializable

```

3) method parameters

```java
class ATemplate3 extends ExtensionTemplate {
public void methodWithTemplatedParameters(Object params) {
// code
}

@Parameter
public List<CtParameter> params;
}

Template t = new ATemplate3();
t.params = ...
Substitution.insertAll(aCtClass, t);
// aCtClass contains methodmethodWithTemplatedParameters with specific parameters

```

Template parameters
------------------

#### AST elements
All meta-model elements can be used as template parameter. For instance, one can
template a try/catch block as shown in the class `TryCatchOutOfBoundTemplate`using a block as parameter.
This template type-checks, and can be used as input by the substitution
engine to wrap a method body into a try/catch block. The substitution engine
contains various methods that implement different substitution scenarios.


```java
public class TryCatchOutOfBoundTemplate extends BlockTemplate {
TemplateParameter<Void> _body_; // the body to surround

@Override
public void block() {
try {
_body_.S();
} catch (OutOfBoundException e) {
e.printStackTrace();
}
}
}
```

#### Literal template Parameters

For literals, Spoon provides developers with *literal template parameters*. When the parameter is known to
be a literal (primitive types, `String`, `Class` or a one-dimensional array of
these types), a template parameter, annotated with `@Parameter` enables one to have concise template code.

```java
// with literal template parameter
@Parameter
int val;
...
val = 5;
...
if (list.size()>val) {...}
```

Note that AST elements can also be given as parameter using `@Parameter` ([javadoc](http://spoon.gforge.inria.fr/mvnsites/spoon-core/apidocs/spoon/template/Parameter.html))
annotation.

```java
class ATemplate extends BlockTemplate {
@Parameter
CtExpression<String> exp;
...
if ("er".equals(val)) {...}
}
```
33 changes: 0 additions & 33 deletions doc/template_instantiation.md

This file was deleted.

39 changes: 0 additions & 39 deletions doc/template_parameter.md

This file was deleted.

0 comments on commit 7a55cd2

Please sign in to comment.