RFC-0050:FIDL 語法翻新

RFC-0050:FIDL 語法更新
狀態已接受
領域
  • FIDL
說明

我們會建立語法選擇的指導原則,並根據這些原則進行幾項語法變更。

作者
提交日期 (年-月-日)2020-02-26
審查日期 (年-月-日)2019-06-04

摘要

我們會建立語法選擇的指導原則,並提供一些語法 遵循這些原則的

變更

  • 類型放在第二位,例如:在方法參數名稱前面 資料表宣告的成員名稱,後面加上各自的類型
  • 將類型變更為將版面配置和限制條件分開,藉此放置版面配置 「:」分隔符左側的相關類型資訊 右側的限制條件資訊,例如:array<T, 5>vector<T>:5 更清楚地表示陣列的大小為版面配置 但對向量而言是極限
  • 介紹匿名版面配置。舉例來說,table { f1 uint8; f2 uint16; } 可直接在方法參數清單中使用。
  • 如要宣告頂層類型,請使用匿名版面配置,並搭配使用 有關 type Name = Layout; 表單的類型簡介宣告說明。
  • 最後,如果是通訊協定 P,請將 Prequest<P> 重新命名client_end:Pserver_end:P。請注意,通訊協定是 用戶端或伺服器端的限制,而非上一個位置。 ,這些錯誤會錯誤地指出與版面配置有關的問題

與其他 RFC 的關係

此 RFC 後來經過以下修訂:

提振精神

入門範例

代數資料類型

該語法用途廣泛,可以代表代數資料類型 (ADT) 可以 就可以輕鬆處理,不需要多發糖例如:

/// Describes simple algebraic expressions.
type Expression = flexible union {
    1: value int64;
    2: bin_op struct {
        op flexible enum {
            ADD = 1;
            MUL = 2;
            DIV = 3;
        };
        left_exp Expression;
        right_exp Expression;
    };
    3: un_op struct {
        op flexible enum {
            NEG = 1;
        };
        exp Expression;
    };
};

根據模式,我們選擇使用 structunionunion 提供的優惠 因此不需要 (且偏好) 使用 固定式變數。如果需要變更變化版本,可以改為新增變化版本 並改用這個新的變化版本。(在其他 企業必須提升穩定性,例如二進位或一元運算子的清單 彈性列舉)。

支援 ADT 描述資料類型時,需要用比人體工學語法還要多。 例如,其中一個預期的主要功能是易於建構的 破壞性 (例如透過模式比對或訪客模式)。

這個 RFC 並未推出 FIDL 的新功能,以及 遞迴型別會導致今日無法編譯範例。我們預計新增 支援一般化遞迴類型,而這個擴充功能將成為 未來的 RFC

以無法修改的訊息與可變訊息輕鬆結合

舉例來說,如要定義「可延伸結構」其中包含兩種 struct 元素 (精簡、內嵌、快速編碼/解碼),而且 已延長:

type Something = struct {
    ...

    /// Provide extension point, initially empty.
    extension table {};
};

舉例來說,fuchsia.test.breakpoints 程式庫需要定義 可延伸活動 (配音為 Invocation)。這些事件都有相同的價值,例如 以及每個事件變化版本的特定酬載現在規律 並簡明扼要,如下所示:

type Invocation = table {
    1: target_moniker string:MAX_MONIKER_LENGTH;
    2: handler Handler;
    3: payload InvocationPayload;
};

type InvocationPayload = union {
    1: start_instance struct{};
    2: routing table {
        1: protocol RoutingProtocol;
        2: capability_id string:MAX_CAPABILITY_ID_LENGTH;
        3: source CapabilitySource;
    };
};

可擴充的方法引數

舉例來說,可擴充的方法引數如下:

protocol Peripheral {
    StartAdvertising(table {
        1: data AdvertisingData;
        2: scan_response AdvertisingData;
        3: mode_hint AdvertisingModeHint;
        4: connectable bool;
        5: handle server_end:AdvertisingHandle;
    }) -> () error PeripheralError;
};

使用 table 做為引數並非「最佳做法」。視情況而定 但也有一些問題,例如有 N 可能 ] 欄位,因此收件者可能十分複雜。

指導原則

FIDL 主要在定義應用程式二進位檔 介面 (ABI) 第二,與應用程式設計介面 (API) 疑慮有關。這個 產生的語法可能會超過一個較複雜的語法,或者 與其他程式設計語言相比舉例來說, 聯集的 unit 變體會表示為空白結構體,如下所示 在上述 InvocationPayload 範例中。我們可以選擇運用語法 但這樣會違反 ABI 的疑慮 正面朝中央

將版面配置與限制區隔

語法對齊

    layout:constraint

如果是類型,也就是任何會控製版面配置的行為,都位於冒號之前 控制項限制位於冒號後方。版面配置說明位元組 對比他們如何理解這項限制會限制 此為驗證步驟 編碼/解碼

這個語法可以簡化 ABI 對變更的影響 而且尤其會導致兩個簡略規則:

  1. 如果兩種型別使用不同的版面配置,就無法進行柔和轉換 反之亦然1,亦即變更 左右打斷 ABI
  2. 限制可能不斷演變,只要編寫者的限制比 而且保持內容相容,也就是說,有必要改變適當的內容 保留 ABI

以下是遵循這項原則的範例變更:

  • array<T>:N 會變成 array<T, N>
  • handle<K> 會變成 handle:K
  • vector<T>? 會變成 vector<T>:optional
  • Struct? 會變成 box<Struct>
  • Table? 會變成 Table:optional
  • Union? 會變成 Union:optional

相關異動有參考本 RFC 的設計一節。

請先格式化二進位線

雖然許多格式可以代表 FIDL 訊息,但 FIDL 傳輸格式 (又稱「FIDL 二進位線路格式」) 是偏好治療的方法,且 都會排序為優先

這表示語法選擇是為了讓 ABI 保持一致的語法 一致性應考慮 ABI 採用二進位線格式 (而非 例如 JSON)。

舉例來說,名稱對於類型ABI:名稱確實 規律地遵循通訊協定和方法雖然名稱對於可能的 JSON 而言至關重要 編寫語法時,我們選擇過度輪換為二元 ABI 格式 也不會為了使用文字表示法而改變語法 這會導致無法理解 ABI 規則

較少功能

Wright 的「表單和函式應為一」 因此我們致力在外觀相似的情況下呈現類似涵義 反之亦然例如所有內部使用的可延伸資料 信封:一律以 ordinal: 表示。

layout {
    ordinal: name type;
};

我們盡可能擁有最基本的功能與規則,並設法結合各項功能, 用途實務上,在考慮採用新功能時 嘗試調整或整體化其他現有功能,而非導入新的 接著介紹網際網路通訊層 包括兩項主要的安全防護功能比方說,雖然特殊語法可以用於擴充式 方法引數 (以及傳回) RFC-0044:可擴充方法引數 但我們偏好使用 table 和這類項目的正常語法。

可能就表示我們甚至需要匿名的 struct 版面配置 方法,而不是最新的語法糖 大部分程式設計語言都藉出引數。但競爭設計 因此考量到圖書館作者,整體作者會保持一致 enum 版面配置宣告,比起明確選擇 包裝的型別,因為具有合理的預設值,可為列舉提供更高的一致性 分散在 FIDL 程式庫之間這反而會提供切換列舉的遷移路徑 例如:程式庫應定義一般用途 ErrorStatus 列舉,之後可再以另一個「better」取代一般用途 ErrorStatusV2

設計

類型

類型應遵循一般形式:

Name<Param1, Param2, ...>:<Constraint1, Constraint2, ...>

空白類型參數化必須省略 <>,即 uint32 (而非 uint32<>)。

沒有限制條件的類型必須同時省略 : 分隔符和 <>,即 uint32 (非 uint32:<>,或 uint32:)。

設有單一限制的類型可能會省略 <>,即 vector<uint32>:5。 和 vector<uint32>:<5> 兩者皆可使用,且兩者相等。

內建

系統支援下列原始類型

  • 布林值 bool
  • 帶正負號整數 int8int16int32int64
  • 非帶號整數 uint8uint16uint32uint64
  • IEEE 754 浮點值 float32float64

固定大小的重複值

array<T, N>

可視為含有 T 類型的 N 元素的 struct

變數大小的重複值

vector<T>
vector<T>:N

意即可以省略 N 大小。

變數大小的 UTF-8 字串

string
string:N

意即可以省略 N 大小。

對核心物件 (即控制代碼) 的參照

handle
handle:S

其中,子類型 S 是以下其中一種:btibufferchanneldebuglogeventeventpairexceptionfifoguestinterruptiommujobpagerpcidevicepmtportprocessprofileresourcesocketsuspendtokenthreadtimervcpuvmarvmo

使用 RFC-0028: Handle Rights 規定的權利處理代碼:

handle:<S, R>

權利 R 可以是權利值或權利表達。

通訊協定物件 (即目標用途的管道控點) 的參照

client_end:P
server_end:P

例如 client_end:fuchsia.media.AudioCoreserver_end:fuchsia.ui.scenic.Session

具體來說,只參照通訊協定並不合法:通訊協定 宣告不會導入型別,只有這種型別可以想成 用戶端或伺服器終止事件這在「傳輸」領域中 一般化章節。

版面配置

除了內建版面配置外,我們也提供五種版面配置, 以引入新的型別:

  • enum
  • bits
  • struct
  • table
  • union

有限版面配置

enumbits 版面配置的表示方式類似:

layout : WrappedType {
    MEMBER = expression;
    ...;
};

其中 : WrappedType 是選用項目 [^2],省略時則預設為 uint32

enum 範例:

enum {
    OTHER = 1;
    AUDIO = 2;
    VIDEO = 3;
    ...
};

bits 範例:

bits : uint64 {
    TOTAL_BYTES = 0x1;
    USED_BYTES  = 0x2;
    TOTAL_NODES = 0x4;
    ...
};

可彈性調整的版面配置

tableunion 版面配置的表示方式類似:

layout {
    ordinal: member_name type;
    ...;
};

在這裡,ordinal: 可以視為語法糖來描述 envelope<type>

就資料表而言,成員通常稱為欄位。聯集會成員: 這通常稱為子類此外,還可以保留以下成員:

layout {
    ordinal: reserved;
    ...
};

Rigid 版面配置

唯一彈性版面配置 struct 的表示方式接近彈性 版面配置,而沒有彈性標記法:

layout {
    member_name type;
    ...;
};

對於結構體,成員通常稱為欄位。

屬性

版面配置前面可能會顯示該版面配置的屬性:

[MaxBytes = "64"] struct {
    x uint32;
    y uint32;
};

這樣就能明確地將屬性附加至 版面配置以及該成員的類型:

table {
    [OnMember = "origin"]
    1: origin [OnLayout] struct {
        x uint32;
        y uint32;
    };
};

新類型開始使用版面配置時,有兩個 新導入類型的屬性可能的刊登位置:

  • 新類型為:[Attr] type MyStruct = struct { ... }
  • 在版面配置中:type MyStruct = [Attr] struct { ... }

fidlc 會考慮這些對等屬性,如果屬性是其他屬性,則會引發錯誤 兩者皆是如此

無論使用哪個刊登位置來指定屬性 概念上是附加至版面配置本身,而不是將型別串連起來 。實際應用的範例之一是,在任何 IR 偏好設定建議是將類型的每種屬性降至版面配置 而不是將版面配置中的屬性提升至類型範圍。

命名情境和版面配置方式

版面配置本身不會包含名稱,因為所有版面配置都是「匿名」的。 而是會特別使用版面配置,來設定版面配置的名稱 翻譯成目標語言

例如,版面配置最常見的用途是導入新的頂層 類型:

library fuchsia.mem;

type Buffer = struct {
    vmo handle:vmo;
    size uint64;
};

這裡,結構體版面配置用於「新類型」在頂層宣告中 資源庫。

匿名原則的用法範例已經在簡介中 表示可延伸方法引數:

library fuchsia.bluetooth.le;

protocol Peripheral {
    StartAdvertising(table {
        1: data AdvertisingData;
        2: scan_response AdvertisingData;
        3: mode_hint AdvertisingModeHint;
        4: connectable bool;
        5: handle server_end:AdvertisingHandle;
    }) -> () error PeripheralError;
};

在此處,表格版面配置會在 StartAdvertising 要求中使用 方法擷取到 Peripheral 通訊協定宣告中。

我們會參照名稱清單 (從最明確到最明確) 指出使用版面配置做為「命名背景」。在兩個例子中 上方,我們有 fuchsia.mem/Buffer 和 有兩個名稱:fuchsia.bluetooth.le/Peripheral, StartAdvertising, request 定義。

在 JSON IR 中,版面配置宣告會包含其命名情境,例如 上述名稱的階層清單。

為背景資訊命名

在程式庫 some.library 中,type Name = 宣告會導入 some.library/Name 的命名情境

Method 要求中的用途 (在回應中) Protocol 導入了 some.library/Protocol, Method, request/response 的命名情境

版面配置中的用途會將欄位名稱 (或變化版本名稱) 新增至命名 相關資訊例如:

type Outer = struct {
    inner struct {
        ...
    };
};

第一個外部結構體版面配置的命名情境為 some.library/Outer,而 第二個內部結構體版面配置的命名情境為 some.library/Outer, inner

產生的簡化名稱

許多目標語言能以階層方式表示命名方式。在 C++ 中: 舉例來說,您可以在封閉類型內定義類型。不過,有些目標 語言沒有此功能,因此我們必須考慮 產生的錯誤。

例如命名背景資訊 some.library/Protocol, Method, request。這可能是壓平成 some.library/MethodRequestOfProtocool 英寸的 開始如果其他定義確實存在使用命名情境 some.library/MethodRequestOfProtocool,則 Go 繫結會發生 Conundrum:必須重新命名兩個宣告的其中一個。最差,不應該 只有一項宣告 (無名稱衝突) 進化為使用 宣告 (具有名稱衝突),Go 繫結就必須與 以避免發生來源破壞性變更。

根據我們的經驗,這些決策最能採用核心 FIDL 而不是委派工具鍊至 FIDL 繫結。我們會 因此請運算並保證採用穩定的扁平化名稱。

在 JSON IR 中,命名背景資訊會包含產生的扁平名稱, 編譯器保證在全域範圍內是唯一的,也就是說,前端編譯器 負責產生整併名稱及驗證經過簡化的名稱 不得與其他宣告衝突 (例如其他扁平名稱或頂層) 宣告)。

以先前範例來說,如果程式庫作者新增了宣告 type MethodRequestOfProtocool = ...,該宣告與產生的扁平名稱衝突 否則編譯就會失敗

使用繫結為結構定義命名

繫結可分成大約兩種類別:

  1. 可表示目標語言的命名情境範圍,例如: C++ 語言的繫結;
  2. 無法指出命名情境,也無法改回使用 系統產生的扁平合併名稱,例如Go 語言的繫結

這改善了目前的情況,因為至少 且可在前端提供編譯器。今天,我們 還需要在遊戲後期 (後端) 產生一些名稱 有害或容易出錯的方法

例如,請思考以下定義:

type BinOp = union {
    add struct {
        left uint32;
        right uint32;
    };
};

在 C++ 繫結中,我們最後可能:

class BinOp {
    class Add {
        ...
    };
};

變化版本 add 的存取子如下:

BinOp.add();

但不會與類別定義衝突

在 Go 中,使用扁平化名稱:

type BinOp struct { ... };
type BinOpAdd struct { ... };

如果程式庫作者之後決定導入頂層宣告 前端編譯器會擷取名為 BinOpAdd 的檔案,並回報為 發生錯誤。圖書館作者全權掌控 以及是否在忽略後 這項新宣告的來源相容性。同樣地,這個 是與目前這種來源相容性的現況相較的改善項目 發現故障情形,發生時間會比做出決策那遙遠。

型別和新型別

RFC-0052:類型別名和新類型中,我們不斷改進類型別名和 請使用新的類型宣告

別名會宣告為:

alias NewName = AliasedType;

亦即與 RFC-0052 中建議的語法相同。

新類型會宣告為:

type NewType = WrappedType;

亦即,不論包裝類型是其他型別還是新型別的語法都一樣 現有的類型 (換行) 或部分版面配置 (新的頂層類型)。與 RFC-0052 中最初提議的語法

選用性

某些類型原本就能選用:vectorsstringsenvelopes 以及使用這些結構的版面配置,例如 table,也就是 信封) 和 union,這是標記加上信封。因此 這些類型屬於選用或非限制條件,且可發展為 (將限制為空值、透過放寬限制),或從頭轉出 ( 來縮減限制)。

另一方面,int8struct 版面配置等類型通常不是硬性規定。 也可以是選用為了使用選用性, 間接參照,例如透過結構體中的間接參照。身為 結果,有別於本質上可選擇的型別,沒有進化路徑

為了區分這兩種情況,並遵循保留 ABI 會「左側」疑慮和可發展的疑慮包含:

可以自由選擇 非自然選用
string:optional box<struct>
vector:optional
union:optional

命名時,我們建議使用「選用」、「必要」、「存在」和「不存在」等字詞。 (應避免「可為空值」、「不可為空值」或「空值欄位」)。配合這項原則 命名偏好設定,請選擇 box<T> 而非 pointer<T>box 是 選用的預設結構。例如,新語法中的 box<struct> 是 相當於舊版語法中的 struct?,而 box<struct>:optional 是 且可能會觸發編譯器或 Linter 的警告。這是 用途更符合預期:使用者一般會使用 Box 結構體 而不是增加間接性

常數

常數的宣告方式為:

const NAME type = expression;

限制排序

根據版面配置和限制將類型參數化時, 這些引數是固定型別的。這個 RFC 定義了以下項目 限制順序 (目前沒有任何類型含有多個版面配置引數):

  • 帳號代碼:子類型、權利、選用。
  • 通訊協定 client/server_end:通訊協定、選用性。
  • 向量:大小、選用。
  • 聯集:選填。

原則上,選擇性性一律存在,對於控點, 子類型。

舉例來說,假設此結構體已定義所有可能的限制 成員:

type Foo = struct {
  h1 zx.handle,
  h2 zx.handle:optional,
  h3 zx.handle:VMO,
  h4 zx.handle:<VMO,optional>,
  h5 zx.handle:<VMO,zx.READ>,
  h6 zx.handle:<VMO,zx.READ,optional>,
  p1 client_end:MyProtocol,
  p2 client_end:<MyProtocol,optional>,
  r1 server_end:P,
  r2 server_end:<MyProtocol,optional>,
  s1 MyStruct,
  s2 box<MyStruct>,
  u1 MyUnion,
  u2 MyUnion:optional,
  v1 vector<bool>,
  v2 vector<bool>:optional,
  v3 vector<bool>:16,
  v4 vector<bool>:<16,optional>,
};

未來方向

除了變更現有功能所使用的語法之外, 並設定預期每天都能呈現出的光線 不久的將來本研究將重點放在預設展現性和語法性 轉譯時 (非精確語意,則需要不同的 RFC)。適用對象 舉例來說,雖然我們描述的是傳輸一般化功能,但我們不會討論 複雜的設計問題 (例如設定的涵蓋範圍、JSON 的表示法等) IR)。

這部分也應視為大方向判讀,而非未來 規格。隨著新功能推出,相應的語法 以及這些功能的精確運作

內容比對名稱解析

例如:

const A_OR_B MyBits = MyBits.A | MyBits.B;

簡化為:

const A_OR_B MyBits = A | B;

例如:

zx.handle:<zx.VMO, zx.rights.READ_ONLY>

簡化為:

zx.handle:<VMO, READ_ONLY>

限制

聲明網站限制

type CircleCoordinates = struct {
    x int32;
    y int32;
}:x^2 + y^2 < 100;

使用網站限制

type Small = struct {
    content fuchsia.mem.Buffer:vmo.size < 1024;
};

獨立限制

constraint Circular : Coordinates {
    x^2 + y^2 < 100
};

信封限制

表格和可延伸聯集的語法隱藏了信封的使用:

  • table 是一種 vector<envelope<...>>
  • union 是一種 struct { tag uint64; variant envelope<...>; }

目前,位於 tableunion 宣告中的 ordinal: 如下 只有信封存在的地方,思考這個語法會很有幫助 「糖」帶上信封的簡介基本上,我們可以 如下:

脫糖資料表和彈性聯集
table ExampleTable {
    1: name string;
    2: size uint32;
};
table ExampleTable {
    @1 name envelope;
    @2 size envelope;
};
union ExampleUnion {
    1: name string;
    2: size uint32;
};
union ExampleUnion {
    @1 name envelope;
    @2 size envelope;
};

如果我們想限制 envelope (例如對元素 require) 會將此限制放在序數 ordinal:C 上,例如:

脫糖資料表和彈性聯集
table ExampleTable {
    1:C1 name string:C2;
    2:C size uint32;
};
table ExampleTable {
    @1 name envelope:C1;
    @2 size envelope:C;
};
union ExampleUnion {
    1:C1 name string:C2;
    2:C size uint32;
};
union ExampleUnion {
    @1 name envelope:C1;
    @2 size envelope:C;
};

屬性

FIDL 的類型系統已經是設有限制概念的系統。我們 vector<uint8>:8:表示向量最多有 8 個元素,或 string:optional 放寬選用性限制,並將字串設為選用。

不同的需求正逐漸迎向更具體的限制, 清楚呈現這些限制的整合及處理方式。

例如 fuchsia.mem/Buffer 指出「此大小不得大於 VMO 的實體大小」。公司 請繼續介紹 RFC-0028:帳號代碼 即限制控點。或是規定必須使用表格欄位,也就是限制 在其他選擇的信封上是否存在

目前無法描述值的執行階段屬性。 方法。雖然 string 值具有大小,但不能 為它命名雖然handle擁有相關聯的權利,但 也可以為這些項目命名

為了正確解決與限制類型相關的表達能力問題,我們 必須先橋接值的執行階段層面,並選用 FIDL 含有這些值。我們計劃推出 **屬性 **, 視為附加在值上的虛擬欄位資源沒有影響 線型結構,純粹是語言層級架構,會以 繫結的 JSON IR 能為執行階段提供意義。屬性已存在 唯一的用途每項資源 這兩個元件的已知繫結一般, 繫結。

延續上方範例,string 值可能含有 uint32 size ,帳號代碼可能包含 zx.rights rights 屬性。

例如:

layout name {
    properties {
        size uint32;
    };
};

傳輸一般化

宣告新的傳輸方式至少需要定義新名稱,且須指定 限制傳輸支援的訊息 (例如「no handle」、「no」和「no」) 資料表」),以及通訊協定的限制 (例如 「射後不理的方法」、「無事件」)。

備受喜愛的語法類似於以無類型 FIDL 文字表示的設定:

transport ipc = {
    methods: {
        fire_and_forget: true,
        request_response: true,
    },
    allowed_resources: [handle],
};

然後使用以下形式:

protocol SomeProtocol over zx.ipc {
    ...
};

處理一般化

目前控制代碼是純粹的 Fuchsia 概念,兩者直接連結 對應至 Zircon 核心,可對應至 zx_handle_t (或其他語言的同等功能) 而這些物件的種類只是由核心公開的物件,例如 portvmofifo

考慮其他情況 (例如處理程序通訊) 時 其中一個理想的擴充點 是可以直接在 FIDL 中定義控制點 而不是語言定義的一部分

例如,定義 Zircon 控點:

library zx;

resource handle : uint32 {
    properties {
        subtype handle_subtype;
        rights rights;
    };
};

type handle_subtype = enum {
    PROCESS = 1;
    THREAD = 2;
    VMO = 3;
    CHANNEL = 4;
};

type rights = bits {
    READ = ...;
    WRIE = ...;
};

這麼做會允許 handlehandle:VMO (或其他程式庫) zx.handle:zx.handle.VMO)。

實驗版 而且將用於在 Zircon 和 FIDL (在這項變更之前,Zircon 的 API 是在 FIDL 中說明,但 FIDL) 部分為 Zircon 的 API 定義)。

執行策略

暫時性的「版本宣告」將新增至全部 .fidl 個檔案的頂端 供 fidlc 使用,偵測 .fidl 檔案是位於先前或新的 語法。

這個權杖緊接在程式庫陳述式的前面:

// Copyright notice...

deprecated_syntax;

library fidl.test;
...

建議使用明確標記,以簡化 fidlc 中 偵測語法並提高可讀性挑戰範例 偵測語法是指導致 編譯錯誤這類情境需要累積經驗來區分 結果可能會出乎意料的結果

此外,這個權杖是新增至採用先前語法的所有檔案,而非新增到 新語法 (例如 new_syntax;") 才能社交 即將進行的遷移作業 - 讀取 FIDL 檔案的讀取者會知道語法為 可能改變,並透過其他管道 (例如 說明文件、郵寄清單)。

即將新增新的 fidlconv 主機工具,可擷取舊版中的 FIDL 檔案 格式,並將檔案轉換為名為 .fidl_new 的新格式檔案。 各節所述者。雖然這項工具與 fidlc 不同 就需要利用編譯器的內部表示法 這項轉換是否正確。舉例來說,您需要將 Foo 類型轉換為 僅限通訊協定時使用 client_end:Foo - 用於判斷案件 fidlconv 會先使用 fidlc 編譯 FIDL 程式庫。

FIDL 前端編譯器 fidlc 及隨附工具,例如 會擴充 formatter 和 linter,以便支援任何符合 標記。

利用這項新增功能,建構管道將進行擴充,如下所示:

視覺化:建構管道策略

具體說明如下:

  • fidlconv 工具會將舊語法中的 FIDL 檔案轉換為新語法 語法。
  • fidlc 編譯器會編譯舊語法來輸出 .json
  • 另外,fidlc 編譯器會編譯新的 .json IR, 語法。
  • fidlfmt 格式設定工具會為產生的新程式庫檔案設定格式 .fidl_new

測試和驗證:

  • 系統會比較兩個 JSON IR,並驗證其相符 (時距除外) 資訊)。
  • 新資料庫檔案格式的命名慣例會通過驗證 檢查 fidlc 編譯器的輸出內容和 fidlfmt 的輸出內容 格式轉換為新的語法

在這個實作過程中,FIDL 團隊也會移動程式設計表。 做為獨立二進位檔 (與其他後端相同), 刪除 C 繫結後端,藉此產生上次使用時間,以及刪除 C 繫結後端。 請前往 fuchsia.git 樹狀結構存放區進行檢查。

人體工學

此 RFC 著重於人體工學。

我們願意讓熟悉的開發人員在短期內失去生產力 使用經過修改的語法 深信未來將有更多的開發人員使用 FIDL 這麼做會很有幫助

說明文件和範例

這需要變更:

回溯相容性

這項變更無法回溯相容。詳情請參閱 轉換計畫。

成效

這項異動不會影響效能。

安全性

這項異動不會對安全性造成影響。

測試

請參閱轉換計畫的導入部分,並確認轉換計畫 確保資料正確性

缺點、替代方案與不明

使用冒號分隔名稱與類型

由於我們把型別設為第二種,因此也可考慮使用 與類型理論、Rust、Kotlin、機器學習語言中執行的一般 : 分隔符 (SML、Haskell、OCaml)、Scala、Nim、Python、TypeScript 等:

    field: int32 rather than the proposed field int32

此提案會拒絕這個做法。

最基本使用 : 分隔符,將版面配置與限制分開。這項服務 也用於表示「包裝類型」,enumbits 宣告。 最後用於表示 tableunion 宣告中的信封。 進一步超載 : 分隔符,特別是在近似的文法鄰近區域 因此會造成混淆 (例如資料表成員 1: name: string:128;)。

省略分號

我們討論過如何省略終止宣告的分號 (意就好) 成員、常數或其他項目)。

本提案選擇不探討這個簡化過程。

移除分號幾乎不會影響 FIDL 作者的語法差異。是 也是一項重大的變革 我們之後也想探究這部分 修改十分容易 (例如 Go's 的做法移除半形分號)。

然而,出現分號來終止成員,宣告則能使成員宣告 更容易保證明確的文法規則 限制 (使用現場和宣告網站)舉例來說 網站版面配置限制 (C),例如:我們為 struct Example { ... }:C; 限制在 : 分隔符和 ; 結束字元之間。

統合列舉和聯集

從型別理論的角度而言,列舉代表單位型別的總和 聯集代表任何型別的總和。所以您可能會想前往 將這兩個概念合而為一。這是程式設計的方法 支援 ADT 的語言,例如 ML 或 Rust。

不過,從版面配置的角度來看,只有單位類型的總和 ( 列舉) 能以比可延伸模組高效率的方式表示 組合 (聯集)。這兩者都提供可擴充的功能 只有聯合會可提高成員的擴充性,從單位型別 (例如 struct {}) 到任何型別。使用這種擴充性會產生內置信封的價值。

我們選擇了務實的方法,可以兼顧兩者的複雜程度 而且可享受特殊大小寫列舉的效能優勢。

參考資料

使用語法

針對可擴充的方法引數

類型別名和已命名類型

Footnote2

比起明確選擇 包裝的型別,具有合理的預設值,可為列舉提供更高的一致性 分散在 FIDL 程式庫之間這個術語是指提供切換列舉的遷移路徑 例如:程式庫應定義一般用途 ErrorStatus 列舉,之後可再以另一個「better」取代一般用途 ErrorStatusV2


  1. 或者至少,如果沒有充分瞭解配線格式和注意事項,例如: https://fxrev.dev/360015