Skip to content

Commit

Permalink
Documentation updates.
Browse files Browse the repository at this point in the history
- Fixed outdated description of `FlatMap` syntax (#584).
- Docuement @-bindings (#583).
- Documented `deserialize_from_array` attribute.
- Add link to Go API documentation to the tutorial.
  • Loading branch information
ryzhyk committed Apr 1, 2020
1 parent 4263e2d commit c4374d3
Show file tree
Hide file tree
Showing 5 changed files with 154 additions and 19 deletions.
24 changes: 6 additions & 18 deletions doc/language_reference/language_reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,9 +144,9 @@ union_type ::= (constructor "|")* constructor
type_alias ::= type_name (* type name declared using typedef*)
["<" type_spec [("," type_spec)*] ">"] (* type arguments *)
constructor ::= cons_name (* constructor without fields *)
| cons_name "{" [field ("," field)*] "}"
field ::= field_name ":" simple_type_spec
constructor ::= [attributes] cons_name (* constructor without fields *)
| [attributes] cons_name "{" [field ("," field)*] "}"
field ::= [attributes] field_name ":" simple_type_spec
```

### Constraints on types
Expand Down Expand Up @@ -590,8 +590,8 @@ rhs_clause ::= atom (* 1.atom *)
| "not" atom (* 2.negated atom *)
| expr (* 3.condition *)
| expr "=" expr (* 4.assignment *)
| "FlatMap" "(" var_name "=" expr ")" (* 5.flat map *)
| "var " var_name = "Aggregate" "(" (* 6.aggregation *)
| "var" var_name "=" "FlatMap" "(" expr ")" (* 5.flat map *)
| "var" var_name = "Aggregate" "(" (* 6.aggregation *)
"(" [var_name ("," var_name)*] ")" ","
func_name "(" expr ")" ")"
```
Expand Down Expand Up @@ -653,7 +653,7 @@ variable, e.g.:
Logical_Switch_Port_ips(lsp, mac, ip) :-
Logical_Switch_Port_addresses(lsp, addrs),
(mac, ips) = extract_mac(addrs),
FlatMap(ip = extract_ips(ips))
var ip = FlatMap(extract_ips(ips))
```

Here, `extract_ips` must return a *set* of IP addresses:
Expand Down Expand Up @@ -781,15 +781,3 @@ blockStatement ::= "{" statement ( ";" statement )* "}"
emptyStatement ::= "skip"
```

# Supported meta-attributes

Only one attribute is supported at the moment, namely the `size` attribute,
applicable to `extern type` declarations. It specifies the size of the
corresponding Rust data type in bytes and serves as a hint to compiler
to optimize data structures layout.

```
#[size=4]
extern type IObj<'A>
```
117 changes: 116 additions & 1 deletion doc/tutorial/tutorial.md
Original file line number Diff line number Diff line change
Expand Up @@ -783,6 +783,30 @@ SanitizedHTTPEndpoint(endpoint) :-
not Blacklisted(endpoint).
```
#### `@`-bindings
When performing pattern matching inside rules, it is often helpful to
simultaneously refer to a struct and its individual fields by name. This can be
achieved using `@`-bindings:
```
typedef Book = Book {
author: string,
title: string
}

input relation Library(book: Book)
input relation Author(name: string, born: u32)

output relation BookByAuthor(book: Book, author: Author)

BookByAuthor(b, author) :-
// Variable `b` will be bound to the entire `Book` struct;
// `author_name` will be bound to `b.author`.
Library(.book = b@Book{.author = author_name}),
author in Author(.name = author_name).
```
#### Container types, FlatMap, and for-loops
DDlog supports three built-in container data types: `Vec`, `Set`, and `Map`. These
Expand Down Expand Up @@ -827,7 +851,7 @@ result that is the union of all the resulting sets:
```
HostIP(host, addr) :- HostAddress(host, addrs),
FlatMap(addr=split_ip_list(addrs)).
var addr = FlatMap(split_ip_list(addrs)).
```
You can read this rule as follows:
Expand Down Expand Up @@ -1642,6 +1666,90 @@ purpose. They do not affect the performance of the DDlog program and cannot be
used as an optimization technique (DDlog does use indexes for performance, but
these indexes are constructed automatically and are not visible to the user).
## Meta-attributes
Meta-attributes are annotations that can be attached to various DDlog program
declarations (types, constructors, fields, etc.). They affect compilation
process and program's external behavior in ways that are outside of the language
semantics. We describe currently supported meta-attributes in the following
sections.
### Size attribute: `#[size=N]`
This attribute is applicable to `extern type` declarations. It specifies the
size of the corresponding Rust data type in bytes and serves as a hint to compiler
to optimize data structures layout:
```
#[size=4]
extern type IObj<'A>
```
### `#[deserialize_from_array=func()]`
This attribute is used in conjunction with `json.dl` library (and potentially
other serialization libraries). When working with JSON, it is common to have
to deserialize an array of entities that encodes a map, with each entity containing
a unique key. Deserializing directly to a map rather than a vector (which would
be the default representation) can be beneficial for performance if
frequent map lookups are required.
The `deserialize_from_array` attribute can be associated with a field of a struct
of type `Map<'K,'V>`. The annotation takes a function name as its value. The function,
whose signature must be: `function f(V): K` is used to project each
value `V` to key `K`:
```
// We will be deserializing a JSON array of these structures.
typedef StructWithKey = StructWithKey {
key: u64,
payload: string
}

// Key function.
function key_structWithKey(x: StructWithKey): u64 = {
x.key
}

// This struct's serialized representaion is an array of
// `StructWithKey`; however it is deserialized into a map rather than
// vector.
typedef StructWithMap = StructWithMap {
#[deserialize_from_array=key_structWithKey()]
f: Map<u64, StructWithKey>
}

Example JSON representation of `StructWithMap`
{"f": [{"key": 100, "payload": "foo"}]}
```
### `#[rust="..."]`
This attribute is applicable to type definitions, constructors, and individual
fields of a constructor. Its value is copied directly to the generated Rust
type definition. It is particularly useful in controling
serialization/deserialization behavior of the type. DDlog generates
`serde::Serialize` and `serde::Deserialize` implementations for all types in
the program. Meta-attributes defined in the `serde` Rust crate can be used to
control the behavior of these traits. For example, the following declaration:
```
#[rust="serde(tag = \"@type\")"]
typedef TaggedEnum = #[rust="serde(rename = \"t.V1\")"]
TVariant1 { b: bool }
| #[rust="serde(rename = \"t.V2\")"]
TVariant2 { u: u32 }
```
creates a type whose JSON representation is:
```
{"@type": "t.V1", "b": true}
```
Other useful serde attributes are `default` and `flatten`. See [serde
documentation](https://serde.rs/attributes.html) for details.
## Input/output to DDlog
DDlog offers several ways to feed data to a program:
Expand All @@ -1656,6 +1764,8 @@ DDlog offers several ways to feed data to a program:
1. From a Java program.
1. From a Go program.
In the following sections, we expand on each method.
### Specifying ground facts statically in the program source code
Expand Down Expand Up @@ -1707,6 +1817,11 @@ If you plan to use the library from a Java program, make sure to use
See [Java API documentation](../java_api.md) for a detailed description of
the Java API.
1. **Go**
See [Go API documentation](../../go/README.md) for a detailed description of the
Go API.
1. The text-based interface is implemented by an
auto-generated executable `./playpen_ddlog/target/release/playpen_cli`. This interface is
primarily meant for testing and debugging purposes, as it does not offer the same performance and
Expand Down
10 changes: 10 additions & 0 deletions test/datalog_tests/tutorial.dat
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,16 @@ dump HostIP;
echo HostIPVSep:;
dump HostIPVSep;

start;
insert Library(Book{"Ernest Hemingway", "For Whom the Bell Tolls"}),
insert Library(Book{"Dav Pilkey", "For Whom the Ball Rolls"}),
insert Author("Ernest Hemingway", 1899),
insert Author("Dav Pilkey", 1966),
commit;

echo BookByAuthor;
dump BookByAuthor;

start;
insert EvensAndOdds([0,1,2,3,4,5]),
insert EvensAndOdds([1,3,5,7]),
Expand Down
19 changes: 19 additions & 0 deletions test/datalog_tests/tutorial.dl
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,25 @@ SanitizedEndpoint(endpoint) :-
var endpoint = addr_port(ip, proto, preferred_port),
not Blacklisted(endpoint).

/*
* Example: @-bindings.
*/
typedef Book = Book {
author: string,
title: string
}

input relation Library(book: Book)
input relation Author(name: string, born: u32)

output relation BookByAuthor(book: Book, author: Author)

BookByAuthor(b, author) :-
// Variable `b` will be bound to the entire `Book` struct;
// `author_name` will be bound to `b.author`.
Library(.book = b@Book{.author = author_name}),
author in Author(.name = author_name).

/*
* Example: recursion
* (see path.dl)
Expand Down
3 changes: 3 additions & 0 deletions test/datalog_tests/tutorial.dump.expected
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ HostIPVSep:
HostIPVSep{.host = 1, .addrs = "10.10.10.101\n10.10.10.102\n"}
HostIPVSep{.host = 2, .addrs = "192.168.0.1\n"}
HostIPVSep{.host = 3, .addrs = "192.168.0.3\n192.168.0.4\n192.168.0.5\n192.168.0.6\n"}
BookByAuthor
BookByAuthor{.book = Book{.author = "Dav Pilkey", .title = "For Whom the Ball Rolls"}, .author = Author{.name = "Dav Pilkey", .born = 1966}}
BookByAuthor{.book = Book{.author = "Ernest Hemingway", .title = "For Whom the Bell Tolls"}, .author = Author{.name = "Ernest Hemingway", .born = 1899}}
Evens:
Evens{.evens_and_odds = [0, 1, 2, 3, 4, 5], .evens = [0, 2, 4]}
Evens{.evens_and_odds = [1, 3, 5, 7], .evens = []}
Expand Down

0 comments on commit c4374d3

Please sign in to comment.