CATS DSL - DeepL和訳 -

本記事は以下をDeepLによって和訳したものです。
※多少私の編集が入る可能性はあります

https://github.com/symbol/symbol/blob/dev/catbuffer/parser/docs/cats_dsl.md

# CATS DSL

CATSは3つの主要な宣言で構成されている： `using`、`enum`、`struct` である。
スキーマは空白が重要である。

## import

CATS ファイルは `import` ステートメントを使用することで、他のファイルをインクルードすることができる。
例えば、"other.cats "というファイルをインポートする場合：
```cpp
import "other.cats"
```

インポートされたファイル名はすべて、parserに渡されたインクルードパスからの相対パスとなる。
CLIツールを使用すると、`--include`コマンドライン引数で指定することができる。

## using

エイリアス文は、一意のPODタイプに名前を付けるために使用できる。
CATS は、2 種類の組み込みをサポートしています：

- 整数型：符号なし（"uint"）と符号あり（"int"）、サイズは { 1, 2, 4, 8 } です。
例えば、8 バイトの符号なし整数で表現される `Height` 型を定義する場合、次のようになります：
```cpp
using Height = uint64
```

- 固定バッファタイプ：任意の長さの符号なしバイトバッファ。
例えば、32 バイトの符号なしバッファで表現される `PublicKey` 型を定義する：
```cpp
using PublicKey = binary_fixed(32)
```

重要なことは、各エイリアスはユニークな型として扱われ、互換性を持って使用することはできないということです。
例えば、`Weight`は`Height`が期待される場合には使用できず、その逆も同様である。
```cpp
using Height = uint64
using Weight = uint64
```

## enum

列挙文は、可能な値の集合を定義するために使用できる。
各列挙は整数のバックタイプを指定します。

例えば、`TransportMode`列挙型を定義するには、2バイトの符号なし整数を指定します：
```cpp
enum TransportMode : uint16
```

列挙を構成する値は、インデントされた行の列挙宣言の後に続く。
例えば、`TransportMode` 列挙に `ROAD` (値 0x0001)、`SEA` (0x0002)、`SKY` (0x0004) という 3 つの値を追加します：
```cpp
enum TransportMode : uint32
	ROAD = 0x0001
	SEA = 0x0002
	SKY = 0x0004
```

### attributes

ヒントは、属性を使用して列挙に添付することができます。

列挙は以下の属性をサポートしています：
1. `is_bitwise`: 列挙がフラグを表し、ビット演算をサポートすることを示す。

例えば、`TransportMode` 列挙に `is_bitwise` 属性を設定するには、次のようにする：
```cpp
@is_bitwise
enum TransportMode : uint32
	ROAD = 0x0001
	SEA = 0x0002
	SKY = 0x0004
```

## struct

Structureステートメントは、構造化されたバイナリー・ペイロードを定義するために使用される。構造定義は包括的である。
他のフォーマットとは異なり、CATSパーサーは余計なデータやパディングを追加することはありません。

構造体は、以下の修飾子のいずれかを持つことができる：
1. None： ジェネレータは、最終出力に型を含めることが推奨される。
2. abstract: ジェネレータは、最終出力に型を含め、対応するファクトリを生成することを推奨します。
3. inline: ジェネレータは最終出力から構造を破棄することを推奨します。

例えば、 `abstract` 修飾子を持つ `Vehicle` 構造体を定義する場合、次のようになります：
```cpp
abstract struct Vehicle
```

構造体を構成するフィールドは、インデントされた行の構造体宣言に従う。
例えば、8バイトの符号なし `weight` 型フィールドを `Vehicle` 構造体に追加するには、次のようにします：
```cpp
abstract struct Vehicle
	weight = uint32
```

`make_const`は、構造体レイアウトに現れない定数フィールドを定義するために使用することができる。
例えば、2 バイトの符号なし定数 `TRANSPORT_MODE` を `ROAD` という値で定義する：
```cpp
struct Car
	TRANSPORT_MODE = make_const(TransportMode, ROAD)
```

`make_reserved`を使用すると、予約フィールドを定義することができます。予約フィールドはレイアウトに表示され、デフォルト値を指定します。
例えば、1バイトの符号なし定数 `wheel_count` を値4で定義する：

```cpp
inline struct Car
	wheel_count = make_reserved(uint8, 4)
```

`sizeof`は、他のフィールドのサイズで埋められるフィールドを定義するために使うことができる。
例えば、2 バイトの符号なし `car_size` を定義し、そのフィールドに `car` フィールドのサイズを代入する：

```cpp
inline struct SingleCarGarage
	car_size = sizeof(uint16, car)

	car = Car
```

### conditionals

フィールドは他のフィールドの値を条件とすることができる。
これは、いくつかの言語に存在するunionの概念を近似したものです。
CATS は以下の演算子をサポートしている：
1. `equals`：参照フィールドの値が条件値と正確に一致する場合、条件フィールドが含まれる。
2. `not equals`: 参照フィールドの値が条件値と一致しない場合、条件フィールドが含まれる。
3. `has`: 参照フィールドの値にすべての条件フラグが設定されている場合、条件フィールドが含まれる。
4. `not has`: 参照フィールドの値にすべての条件フラグが設定されていない場合、条件フィールドが含まれる。

例えば、`transport_mode` が `SEA` と等しい場合にのみ `buoyancy` が存在することを示す：

```cpp
abstract struct Vehicle
	transport_mode = TransportMode

	buoyancy = uint32 if SEA equals transport_mode
```

### arrays

動的なサイズの配列がサポートされている。
各配列には関連付けられたサイズがあり、定数、プロパティ参照、または特別な `__FILL__` キーワードを指定することができる。

例えば、 `vehicles` フィールドを持つ `Garage` を定義する場合、 `vehicles_count` `Vehicle` 構造体で構成される：
```cpp
struct Garage
	vehicles_count = uint32

	vehicles = array(Vehicle, vehicles_count)
```

特別なキーワード `__FILL__` は、配列が構造体の最後まで拡張されることを示す。
__FILL__`を使用するには、 `@size` 属性で指定したバイト単位のサイズを含むフィールドを含む構造体を指定しなければならない。
例えば、 `Vehicle` 構造体で構成される `vehicles` 配列が、バイトサイズ `garage_byte_size` の `Garage` 構造体の最後まで拡張されていることを示す：

```cpp
@size(garage_byte_size)
struct Garage
	garage_byte_size = uint32

	vehicles = array(Vehicle, __FILL__)
```

:warning: 配列の要素タイプ（例では `Vehicle` を使用）は、固定サイズの構造体か、`@size` 属性が付加された可変サイズの構造体でなければならない。

### inlines
構造体は `inline` キーワードを使って別の構造体の中にインライン化することができる。
例えば、2つのフィールドを持つ `Car` 構造体の先頭に `Vehicle` をインライン化するには、次のようにします：

```cpp
struct Car
	inline Vehicle

	max_clearance = Height
	has_left_steering_wheel = uint8
```

インラインは出現したところから展開されるので、`Car`フィールドの順番は次のようになる
{weight, max_clearance, has_left_steering_wheel}.

つまり以下と同等です:

```cpp
struct Car
	weight = uint32

	max_clearance = Height
	has_left_steering_wheel = uint8
```

さらに、名前付きインラインは、参照される構造体のフィールドに接頭辞をつけてインライン化する。
例えば、以下の `SizePrefixedString` は `friendly_name` として `Vehicle` にインライン化される：

```cpp
inline struct SizePrefixedString
	size = uint32
	__value__ = array(int8, size)

abstract struct Vehicle
	weight = uint32

	friendly_name = inline SizePrefixedString

	year = uint16
```

この拡張は同等となる：
```cpp
abstract struct Vehicle
	weight = uint32

	friendly_name_size = uint32
	friendly_name = array(int8, friendly_name_size)

	year = uint16
```

インライン構造内の `__value__` は特別なフィールド名で、包含構造 (`Vehicle`) で使用されている名前 (`friendly_name`) に置き換えられます。

インライン化された構造体の他のすべてのフィールドは、包含構造体 (`Vehicle`) で使用されている名前 (`friendly_name`) とアンダースコアで名前が付加されます。

つまり、 `__value__` は `friendly_name` となり、 `size` は `friendly_name ` + `_` + `size` また

### attributes

ヒントは、属性を使用して構造体に添付することができます。

構造体は以下の属性をサポートする：
1. `is_aligned`：すべての構造体フィールドがアラインされた境界に配置されていることを示す。
2. `is_size_implicit`: 構造体が `sizeof(x)` ステートメントで参照される可能性があり、サイズ計算をサポートしなければならないことを示す。
3. `size(x)`: `x` フィールドに（可変サイズの）構造体のフルサイズが格納されていることを示す。
4. `initializes(x, Y)`: `x` フィールドを定数 `Y` で初期化することを示す。
5. `discriminator(x [, y]+)`: (`x`, ...`y`) プロパティがファクトリーを生成する際に識別器として使用されることを示す（抽象構造体に対してのみ意味を持つ）。
6. `comparer(x [!a] [, y [!b]])`: (`x`, ...`y`) プロパティをカスタムソートに使用することを示します。オプションの (`a`, ...` b`) トランスフォームを指定することができ、プロパティ比較の前に適用することができます。

例えば、`transport_mode` フィールドと `TRANSPORT_MODE` 定数をリンクさせる場合、次のようになります：

```cpp
@initializes(transport_mode, TRANSPORT_MODE)
abstract struct Vehicle
	transport_mode = TransportMode

struct Car
	TRANSPORT_MODE = make_const(TransportMode, ROAD)

	inline Vehicle
```

`TRANSPORT_MODE`はどの派生構造でも定義できることに注意。

配列フィールドは以下の属性をサポートする：
1. `is_byte_constrained`: サイズ値が要素数ではなくバイト値として解釈されることを示す。
2. `alignment(x [, [not] pad_last])`: 要素が `x` アラインの境界から始まるようにパディングされることを示す。
3. `sort_key(x)`: 配列内の要素を `x` プロパティでソートすることを示す。

```cpp
struct Garage
	@sort_key(weight)
	vehicles = array(Vehicle, __FILL__)
```

整数フィールドは以下の属性をサポートしている：
1. `sizeref(x [, y])`: フィールドが `x` プロパティのサイズを `y` で調整したサイズで初期化されることを示す。

例えば、`vehicle_size` に自分自身と車両フィールドのサイズを自動入力する場合である：

```cpp
struct Garage
	@sizeref(vehicle, 2)
	vehicle_size = uint16

	vehicle = Vehicle
```

## comments

`#`で始まる行はすべてコメントとして扱われる。
コメント行が宣言や副宣言の直上にある場合、それは文書として扱われ、パーサーによって保存されます。
そうでない場合は破棄されます。

例えば、以下の「コメント1」は破棄され、「コメント2 コメント3」はHeightのドキュメントとして抽出されます。

```python
# comment 1

# comment 2
# comment 3
using Height = uint64
```