doc/ag-reference.md
# AG Reference
AG is the language to write an input to Silverchain (i.e. to write the rules of fluent APIs). The following lines are AG code that defines the rules of a fluent builder of `java.time.LocalDateTime`:
```java
org.example.DateTimeBuilder {
java.time.LocalDateTime year(int y) month(int m) day(int d);
}
```
AG code consists of one or more named blocks (`<NAME> { }`). The name of a block is the name of the _entrypoint class_ of a fluent API. Specifically, `org.example.DateTimeBuilder { … }` indicates that the fluent builder allows its users to start writing a method chain by instantiating `org.example.DateTimeBuilder`:
```java
import org.example.DateTimeBuilder;
new DateTimeBuilder().year(2021). … ;
```
The lines inside a block describe the rules on method chains. Each rule consists of
- the type of an object that is returned by the last method in a chain,
- a regular expression whose atomic element (or _alphabet_) is a method declaration,
and a semicolon. In the example AG code, the second line indicates that
- the API allows its users to chain `year(int)`, `month(int)`, and `day(int)` in this order, and
- the expression `year(…).month(…).day(…)` returns an instance of `java.time.LocalDateTime`.
## More on chain rules
### Types and methods in rule
One can write any valid Java type/method in a chain rule. One can write `void`, `int[]`, `String[][]`, etc., not only simple class/interface names; One can use `...` in method parameters; One can add `throws` to the method.
### Repeat operators
Common repeat operators such as `?` are supported. The example below indicates that the invocations of `month(int)` and `day(int)` are optional.
```java
org.example.DateTimeBuilder {
java.time.LocalDateTime year(int y) month(int m)? day(int d)?;
}
```
The following lists all the operators allowed in AG code:
| operator | semantics |
| :----------- | :------------------------------------------------------- |
| `foo()?` | zero or one invocation of `foo()` |
| `foo()*` | zero or more invocations of `foo()` |
| `foo()+` | one or more invocations of `foo()` |
| `foo()[n]` | `n` invocations of `foo()` |
| `foo()[n,]` | `n` or more invocations of `foo()` |
| `foo()[n,m]` | at least `n` but no more than `m` invocations of `foo()` |
### Unordered rules
Some API would provide a group of methods that can be invoked in any order, but each of them only once. Silverchain supports a special operator `{}`:
```java
import java.time.LocalDateTime;
import org.example.DateTimeBuilder;
DateTimeBuilder {
// Invoke year, month, day in any order,
// but each of them only once
LocalDateTime { year(int y), month(int m), day(int d) };
}
```
The above example means that the API allows all of the below:
- `year(2021).month(11).day(6)`
- `year(2021).day(6).month(11)`
- `month(11).year(2021).day(6)`
- `month(11).day(6).year(2021)`
- `day(6).year(2021).month(11)`
- `day(6).month(11).year(2021)`.
However, the API does not allow
- `year(2021).month(11).day(6).day(6)` (Invoking `day` twice)
- `month(11).day(6)` (Missing `year`)
## Sugars to simplify AG code
### Importing types
By importing a type like in Java, one can refer to that type by its simple name:
```java
import java.time.LocalDateTime;
org.example.DateTimeBuilder {
LocalDateTime // = java.time.LocalDateTime
year(int y) month(int m) day(int d);
}
```
One can use an import statement to use a simple name for classes to be generated by Silverchain:
```java
import org.example.DateTimeBuilder;
DateTimeBuilder { // = org.example.DateTimeBuilder
java.time.LocalDateTime year(int y) month(int m) day(int d);
}
```
### Fragments
The repetition in rules can be removed by defining a fragment:
```java
import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import java.time.ZoneId;
import org.example.DateTimeBuilder;
// Fragment definition ($FRAGMENT_NAME = …);
$YMD = year(int y) month(int m) day(int d);
DateTimeBuilder {
// $YMD is expanded into `year(int y) month(int m) day(int d)`
LocalDateTime $YMD local();
ZonedDateTime $YMD timezone(ZoneId z);
}
```
## Type parameters
There are three kinds of type parameters:
1. Ones listed in a type declaration
1. **Ones listed before `;` or without `;`**. These type parameters are shared in a chain expression and are included in the generated type declaration. For example, if you give an input like `Foo<T> { … }`, Silverchain generates `Foo<T>`.
2. **Ones listed after `;`**. These type parameters are shared in a chain expression but are **not** included in the generated type declaration. For example, If you give an input like `Foo<;T> { … }`, Silverchain generates `Foo` (without the type parameter `T`). The examples [mapbuilder.ag](https://github.com/tomokinakamaru/silverchain/blob/master/src/test/resources/mapbuilder.ag) and [listutil.ag](https://github.com/tomokinakamaru/silverchain/blob/fix/issue39/src/test/resources/listutil.ag) are their usecases.
2. **Ones listed in a method declaration**. These type parameters are **not** shared in a chain. They are only used in that method.
## Comments
One can write comments in AG code. Everything after `//` in a line is treated as a comment. `/* */` to write a block comment.
To add comments to generated files, use the `--javadoc` option (See [here](./javadoc.md)).