message-size-increase #3
102
design/pdl-compiler.md
Normal file
102
design/pdl-compiler.md
Normal file
@ -0,0 +1,102 @@
|
||||
# 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.
|
@ -108,80 +108,3 @@ Below is an EBNF description of the language.
|
||||
<message> -> <method> <ident> <type>
|
||||
<typedef> -> <ident> <type>
|
||||
```
|
||||
|
||||
## Go Code Generation
|
||||
|
||||
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. Any
|
||||
|
Loading…
Reference in New Issue
Block a user