RFC-0040:标识符唯一性 | |
---|---|
状态 | 已接受 |
领域 |
|
说明 | FIDL 规范和前端编译器目前基于简单的字符串比较将两个标识符视为不同。它提出了一种将绑定生成器进行的转换考虑在内的新算法。 |
作者 | |
提交日期(年-月-日) | 2019-04-08 |
审核日期(年-月-日) | 2019-05-14 |
“SnowFlake 与 SNOW_FLAKE”
摘要
FIDL 规范和前端编译器目前考虑 不同。 该算法提出了一种将转换过程考虑在内的新算法, 绑定生成器创建的机制。
设计初衷
语言绑定生成器转换标识符,以符合目标 将多个 FIDL 标识符映射到单个 目标语言标识符。 这可能会导致意外冲突, 定位语言。
设计
此方案提议对不存在的 FIDL 标识符施加限制。 违反。 它不会更改 FIDL 语言、IR(目前为 1)、绑定、样式 指南或评分准则。
实际上,标识符由一系列组合在一起的单词组成。
联接字词的常用方法是 CamelCase
,其中过渡
表示字词边界;snake_case
,其中 1 或
许多下划线 (_
) 用于分隔字词。
应将标识符转换为规范形式,以便进行比较。这将
为 lower_snake_case
形式,并保留原始单词中的单词分离
表单。字词被破坏 (1) 有下划线,(2) 从
以及 (3) 从大写转换为大写之前
。
在 FIDL 中,标识符必须以原始形式使用。
因此,如果某个类型名为 FooBar
,尝试以 foo_bar
的形式引用它将会出错。
可通过一个简单的算法执行此转换, 使用 Python2:
def canonical(identifier):
last = '_'
out = ''
for i, c in enumerate(identifier):
is_next_lower = i + 1 < len(identifier) and identifier[i+1].islower()
if c == '_':
if last != '_':
out += '_'
elif (((last.islower() or last.isdigit()) and c.isupper())
or (last != '_' and c.isupper() and is_next_lower)):
out += '_' + c.lower()
else:
out += c.lower()
last = c
return out
以下是一些示例,以及各种目标语言可能的翻译:
FIDL 标识符 | 规范形式 | C++ | Rust | Go | Dart |
---|---|---|---|---|---|
Foobar | Foobar | Foobar | Foobar | 美食酒吧 | foobar_ |
foo_bar | foo_bar | foo_bar | foo_bar | FooBar | fooBar_ |
foo__bar | foo_bar | foo_bar | foo_bar | FooBar | fooBar_ |
FooBar | foo_bar | foo_bar | foo_bar | FooBar | fooBar_ |
fooBar | foo_bar | foo_bar | foo_bar | FooBar | fooBar_ |
FOOBar | foo_bar | foo_bar | foo_bar | FooBar | fooBar_ |
实施策略
前端编译器将进行更新,以检查每个新标识符的 规范形式不与任何其他标识符的规范形式冲突。
下一版 FIDL IR 应围绕规范名称进行整理 但原始名称将作为 字段。 如果我们能避免在生成的绑定中使用未经修改的名称 原始名称可从 IR 中删除。
工效学设计
该规范编制了对实践中存在的 FIDL 语言的限制。
文档和示例
我们将更新 FIDL 语言文档以描述此限制条件。 随后我们会进行扩展,以包含 设计部分。
由于该方案只是对现有实践、示例和 教程不会受到影响。
向后兼容性
任何可能与此更改发生冲突的现有 FIDL 库都会违反我们的 样式指南,不适用于许多语言绑定。 这不会更改用于计算序数的标识符的形式。
性能
这对前端编译器的开销可以忽略不计。
安全
无影响。
测试
我们会对规范化算法进行大量测试
fidlc
中的实现。
此外,还会执行 fidlc
测试,以确保在
同时确保原始名称与原始名称
来引用声明。
缺点、替代方案和未知问题
一种选择是不执行任何操作。
通常,我们会将这些问题捕获为非 C++ 生成的绑定中的构建失败。
随着 Rust 在 fuchsia.git
中的使用越来越频繁,冲突滑动的可能性会降低
直到其他花瓣都变小
这类问题已经相当罕见了。
规范化算法很简单,但也存在一种会失败的情况
— UPPER_SNAKE_CASE 标识符中的混合字母数字单词可能是
损坏。
例如 H264_ENCODER
→ h264_encoder
,但 A2DP_PROFILE
→
a2_dp_profile
。
这是因为该算法将数字视为小写字母。
我们必须中断数字到字母的转换,因为 H264Encoder
应该
规范化为 h264_encoder
。
不含小写字母的标识符可以采用特殊大小写 - 仅
会破坏下划线,但这会增加算法的复杂性,
可能是心智模型。
规范形式可以表示为字词列表,而不是 lower_camel_case 字符串。 它们是等效的,实际上以字符串形式管理它们更简单。
我们可以使用标识符规范形式。 这会使此更改成为一项破坏性更改,没有明显的好处。 如果未来的某天有颠覆性日子 请考虑此更改。
初次拒绝,然后再次审核
在 2019 年 4 月 18 日首次审核时,此 FTP 被拒,存在以下 理由。
- 在解决这类问题方面,存在两种相反的观点。
- 构建目标语言的模型尽可能保持
(即使它不同于
建议样式
这就是这个 FTP 所采用的方法
- 优点:对于在 Fuchsia 以外的最终使用 FIDL 时保持灵活性, 从编程语言的角度来看,这种做法更为纯粹。
- 缺点:范围规则比较复杂,不会强制执行样式, (例如通过执行 lint 请求)。 可能会导致合作伙伴构建的 API 不符合 Fuchsia 要求 风格指南(因为它们不需要运行,也不需要遵循 lint 检查)。
- 直接在语言中强制实施样式限制,这样就消除了
一类的问题。
- 优点:强制执行样式,告知开发者应该如何设计,或 无法编译。
- 缺点:在语言定义中吸纳出风格选择,山势较高 适合使用 FIDL 的初级开发者攀爬。
- → 我们拒绝了该提案,而是倾向于采用 直接在语言中强制执行样式
- → 接下来,我们会提供实现这一目标的正式建议,并澄清
其所有方面(例如,
uint8
应为Uint8
,vector<T>
应为Vector<T>
?)
基于以下观察结果,我们决定推翻这一决定:
内核 API 现在称为 FIDL。这促使我们重新打开了 标识符唯一性问题,我们实质上推翻了 既允许 C 语言型语言,和“FIDL-style”才能共存这是 Fill linter 今天会进行检查。
我们看到过其他用例推动 FIDL 进行泛化,并且 以及本地样式规则,以便更好地支持这些领域。
标识符冲突仍然是一个问题,根据模型估算目标语言 限制是 FIDL 工具链中明显存在的一个差距。
先验技术和参考资料
在 proto3 中,系统会应用类似的规则来生成 lowerCamelCase
名称
。