RFC-0050:FIDL 语法修订

RFC-0050:FIDL 语法改进
状态已接受
领域
  • FIDL
说明

我们制定了语法选择指导原则,并遵照这些原则对语法进行了一些更改。

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

摘要

我们为语法选择确立指导原则, 更改。

变更

  • types 置于第二个位置,例如放在方法参数名称前面 在表声明中,成员名称会放在其各自的类型之前 相应类型;
  • 将类型更改为将布局与约束条件分开,以放置布局 : 分隔符左侧的 右侧的约束条件信息,如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 引入新功能, 递归类型会导致示例目前无法编译。我们计划将 支持通用递归类型,并且此扩展将是 提供建议

更轻松地将不可演变的消息与可演变的消息相结合

例如,表示“可扩展结构体”它具有两个结构体元素 (紧凑、内联、快速编码/解码), 扩展:

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 的 2N 个可能性 字段,可能会给收件人带来很大的复杂性。

指导原则

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 Binary Wire Format”)是优先处理规则; 。

这意味着语法选择旨在确保语法与 ABI 保持一致 一致性时应考虑二进制传输格式下的 ABI(而不是 其他格式,如 JSON)。

例如,就类型而言,名称并不重要ABI - 名称可以 对协议和方法至关重要虽然名称对于可能存在的 JSON 文件很重要 在生成语法时,我们选择过度旋转为二进制 ABI 格式 因此,如果 会妨碍对 ABI 规则的理解。

最少功能

赖特的“形式与功能应为一种” 让我们努力寻找外观相似的构件,以使它们具有相似的含义, 反之亦然。例如,所有可扩展数据 信封,始终显示 ordinal:

layout {
    ordinal: name type;
};

我们会尽量减少特性和规则,并力求将特性和规则组合起来, 实现用例。在实践中,在考虑新功能时,我们首先应该 尝试调整或泛化其他现有特征,而不是引入新的特征 功能。例如,虽然特殊语法可以设计为可扩展 方法参数(和返回),如 RFC-0044:可扩展方法参数 我们更倾向于使用 table 和这些语法的常规语法。

有人可能会认为,我们甚至应该要求使用匿名 struct 布局 而不是当前语法糖 参数。然而,一个竞争性设计 我们的考量是帮助图书馆作者总体上实现一致性: enum 布局声明,我们更喜欢语法糖,而不是显式选择 封装类型,因为具有合理的默认值可以为枚举提供更高的一致性 不同 FIDL 库的版本。这进而又提供了切换枚举的迁移路径 例如,库应该定义通用 ErrorStatus 吗 枚举,之后可能会替换为其他“更好”的通用 ErrorStatusV2

设计

类型

类型遵循以下常规形式:

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

空类型参数化必须省略 <>,即 uint32(而不是 uint32<>)。

没有任何约束条件的类型必须同时省略 : 分隔符和 <>,即 uint32(不是 uint32:<>,也不是 uint32:)。

具有单个约束条件的类型可以省略 <>,即 vector<uint32>:5vector<uint32>:<5> 都是允许使用的,并且是等效的。

内置

支持以下基元类型

  • 布尔值 bool
  • 有符号整数 int8int16int32int64
  • 无符号整数 uint8uint16uint32uint64
  • IEEE 754 浮点 float32float64

固定大小的重复值

array<T, N>

可以将其视为 struct,其中包含类型为 TN 元素。

可变大小的重复值

vector<T>
vector<T>:N

即,可以省略大小 N

可变大小的 UTF-8 字符串

string
string:N

即,可以省略大小 N

对内核对象(即句柄)的引用

handle
handle:S

其中子类型 Sbtibufferchanneldebuglogevent eventpairexceptionfifoguestinterruptiommujobpager pcidevicepmtportprocessprofileresourcesocket suspendtokenthreadtimervcpuvmarvmo

处理 RFC-0028:处理权限中引入的权限:

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;
    ...
};

刚性布局

唯一一种刚性布局 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 中, 将类型节中的属性降低到布局 而不是将布局中的属性提升到 stanza 类型。

命名上下文和使用布局

布局本身没有名称,所有布局都是“匿名”的。 相反,它是布局的一种具体用法,它决定了它将会具有的名称 目标语言。

例如,布局最常见的用途是引入一个新的顶层 类型:

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/Bufferfuchsia.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 绑定将面临 难题:必须重命名两个声明中的一个。最糟糕的是,应该建一个图书馆 会发展为包含两个声明(没有名称冲突)的库, 声明(存在名称冲突),那么 Go 绑定必须与 避免对源代码进行破坏性更改

我们的经验表明,这些决定最好交由核心 FIDL 处理 编译器,而不是将工具链委托给 FIDL 绑定。我们将 因此会计算并保证一个稳定的扁平化名称。

在 JSON IR 中,命名上下文将包含生成的扁平化名称, 编译器保证在全局范围内是唯一的,即前端编译器 负责生成拼合名称,并验证 不与其他声明(无论是其他展平名称,还是顶级域名, 声明)。

拿前面的例子来说,如果库作者添加声明 type MethodRequestOfProtocool = ...,而该声明与生成的扁平化名称 另一个声明,编译将失败。

通过绑定使用命名上下文

绑定可大致分为两类:

  1. 能够使用目标语言表示命名上下文范围,例如 C++ 语言绑定;
  2. 无法表示命名上下文,并回退到使用 生成的扁平化 nuse 扁平化名称,例如用于 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 是标记加信封。因此,无论 这些类型是可选的,或者不是限制,并且可以演化为 (通过放宽约束条件变为可为 null),或者从(成为 所需方式)。

另一方面,int8struct 布局等类型本身并不是 而且是选填的为了提供可选性, 一个间接引用,例如在结构体用例中通过间接引用。作为 与固有可选的类型不同,进化路径是不可或缺的

为了区分这两种情况,并遵循始终 ABI 问题“左侧”以及日益增长的担忧具有:

自然可选 并非必然选择
string:optional box<struct>
vector:optional
union:optional

在命名时,我们倾向于使用“可选”“必需”“存在”“不存在”这些术语。 (我们应避免使用“可为 null”“不可为 null”和“null 字段”。)与此一致 命名偏好设置,我们选择 box<T>,而不是 pointer<T>box是 默认情况下,这是一个可选结构,也就是说,新语法中的 box<struct> 是 相当于旧语法中的 struct?,且 box<struct>:optional 是 是多余的,并且可能会触发编译器或 linter 的警告。这是为了 更符合我们预期的用例:用户通常会对结构体进行封装, 而不是添加间接方法。

常量

常量声明为:

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
};

对信封的约束条件

表和可扩展联合的语法隐藏了信封的使用:

  • tablevector<envelope<...>>,以及
  • unionstruct { 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 表示向量最多包含 8 个元素 放宽可选性约束,允许字符串是可选的。

各种需求都在推动着更具表现力的限制, 对如何统一和处理这些约束条件有主见的观点。

例如 fuchsia.mem/Buffer “此大小不得大于 VMO 的物理大小。”工作为 持续推出 RFC-0028:处理权限, 即约束手柄。或者认为需要表字段,即限制 其他可选的信封上的内容

目前无法描述这些值的运行时属性或 被操纵的实体虽然 string 值有大小,但大小并不相同 为其命名handle虽然具有与之关联的权利,但它不是 为其命名

为了正确解决与受限类型相关的表现力问题, 必须先使用有限视图(即 FIDL 具有这些值。我们计划引入 **属性 **, 可以看作是附加到值的虚拟字段。房源不会影响 传输格式,它们纯粹属于语言级别的结构, 绑定的 JSON IR,为它们提供运行时含义。存在的 目的是表达对它们的限制每个媒体资源 绑定需要知道绑定关系,其方式与内置函数类似, 绑定。

继续上面的示例,string 值可能包含 uint32 size 属性,句柄可以具有 zx.rights rights 属性。

例如:

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

传输泛化

声明新的传输至少需要定义一个新名称,指定 对传输所支持消息的限制(例如“无句柄”“否” 表”),以及指定协议的约束条件(例如, “即发即弃”方法“无事件”)。

设想的语法类似于非类型化 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(在此次变更之前,FIDL 中介绍了 Zircon 的 API, 有一部分是根据 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 编译器将通过编译新的 IR 来单独输出 .json IR 语法。
  • fidlfmt 格式化程序将设置生成的新库文件的格式 .fidl_new

对于测试和验证:

  • 将对两个 JSON IR 进行比较,并验证其是否匹配(span 除外) 信息)。
  • 将验证新库文件格式的幂等性, 检查 fidlc 编译器的输出和 fidlfmt 新语法的格式设置工具。

在实施过程中,FIDL 团队还将移动编码表 作为一个独立的二进制文件(与其他后端一样),并将 通过生成最后一次使用来过时并删除 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 移除分号的方法)。

不过,如果用分号终止成员,声明会导致 更容易保证语法规则清晰易懂,尤其是在探索 (use-site 和声明-site)。例如,使用声明 网站布局约束条件 (C),例如 struct Example { ... }:C;: 分隔符和 ; 终结符之间的约束条件。

统一枚举和联合

从类型理论的角度来看,枚举表示单元类型的总和, 而并集表示任何类型的总和。因此,他们很想尝试 将这两个概念整合为一个概念。这就是编程工具采用的方法。 支持 ADT 的语言 ML 或 Rust。

不过,从布局的角度来看,只有单位类型(即 可以比可扩展的 副本(并集)。虽然这两种方式都能提供可扩展性, 成员,只有工会才提供从单位类型(例如 struct {})转换为任何类型的可扩展性。这种可扩展性是以内联信封为代价的。

我们选择了一种实用的方法,在这两种方法之间 结构,同时具有特殊大小写枚举的性能优势。

参考文档

在语法上

针对可扩展方法参数

关于类型别名和命名类型

Footnote2

尽管与明确选择语言模型相比,更倾向于语法简洁似乎似乎有点奇怪, 封装类型,具有合理的默认值可以为枚举提供更高的一致性 不同 FIDL 库的版本。这方面提供了切换枚举的迁移路径 例如,库应该定义通用 ErrorStatus 吗 枚举,之后可能会替换为其他“更好”的通用 ErrorStatusV2


  1. 或者至少,在没有充分了解电线格式和注意方式的情况下, https://fxrev.dev/360015