103 lines
3.5 KiB
Markdown
103 lines
3.5 KiB
Markdown
# PDL Compiler Specification
|
|
|
|
Given one or more PDL files representing a protocol, the compiler shall generate
|
|
a Go package named "protocol", which shall contain types for message and type
|
|
definitions, as well as encoding and decoding methods.
|
|
|
|
## Static Section
|
|
|
|
The compiler shall write a static section alongside the generated code. It
|
|
shall contain this text:
|
|
|
|
```go
|
|
// Table is a KTV table with an undefined schema.
|
|
type Table map[uint16] any
|
|
|
|
// Message is any message that can be sent along this protocol.
|
|
type Message interface {
|
|
codec.Encodable
|
|
codec.Decodable
|
|
|
|
// Method returns the method code of the message.
|
|
Method() uint16
|
|
}
|
|
```
|
|
|
|
## Preamble
|
|
|
|
At the start of each file but after the package name, the compiler shall emit
|
|
this text:
|
|
|
|
```go
|
|
/* # Do not edit this package by hand!
|
|
*
|
|
* This file was automatically generated by the Holanet PDL compiler. The
|
|
* source file is located at <path>
|
|
* Please edit that file instead, and re-compile it to this location.
|
|
*
|
|
* HOPP, TAPE, METADAPT, PDL/0 (c) 2025 holanet.xyz
|
|
*/
|
|
```
|
|
|
|
Where `<path>` is the path of the protocol definition file relative to the
|
|
generated file.
|
|
|
|
## Message Definitions
|
|
|
|
For each defined message, the compiler shall generate a Go type named
|
|
`MessageName`, where `Name` is the name of the message as written in its
|
|
definition. The message shall be encodable, and shall have `Encode` and `Decode`
|
|
methods as described below.
|
|
|
|
All messages shall satisfy a `Message` interface, which is defined in the
|
|
static section.
|
|
|
|
## Type Definitions
|
|
|
|
For each defined type, the compiler shall generate a Go type with the same name
|
|
as written in its definition. The Go type shall be encodable, and shall have
|
|
`Encode` and `Decode` methods as described below.
|
|
|
|
## Encoding and Decoding Methods
|
|
|
|
Each encodable type shall be given an `Encode` method and a `Decode` method,
|
|
which will take in a `codec.Encoder` and a `codec.Decoder` respectively. Both
|
|
return an `(int, error)` pair describing the amount of bytes written and an
|
|
error if the write stopped early. `Encode` will encode the data within the
|
|
message to the given encoder, and `Decode` will decode data from the given
|
|
decoder and place it in the type's value. The methods shall not retain or close
|
|
any encoders or decoders they are given. Both methods shall have pointer
|
|
receivers. In effect, these methods will satisfy `codec.Encodable` and
|
|
`codec.Decodable`.
|
|
|
|
## Connection
|
|
|
|
The compiler shall generate a `Conn` struct which embeds a `hopp.Conn`, which
|
|
is the real "porcelain" of the generated code. It shall provide methods to
|
|
create and accept transactions. Each transaction shall be a struct which embeds
|
|
a `hopp.Trans`, and shall have methods for sending and receiving messages.
|
|
|
|
### Sending
|
|
|
|
To send a message along a transaction, the program shall:
|
|
|
|
1. Obtain the method code from the message
|
|
3. Obtain a writer from the connection using the method code
|
|
4. Wrap the writer in a `codec.Encoder`
|
|
5. Use the encoder to encode the message
|
|
6. Close the writer
|
|
|
|
### Receiving
|
|
|
|
To receiving a message from a transaction, the program shall:
|
|
|
|
1. Obtain a method code and reader from the connection
|
|
2. Wrap the reader in a `codec.Decoder`
|
|
3. Switch on the method code, and decode the correct message using the decoder
|
|
4. Return the message to the caller as a value
|
|
|
|
The recieve function must return the message as a value instead of a pointer in
|
|
order to avoid making an allocation. Because of this, the return value must be
|
|
`any` instead of `Message`. The caller must then use a type switch to figure out
|
|
what message was sent.
|