ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Carbon 语言元组与元组索引(Tuples and Tuple Indexing):p003646 提案全解析与实现验证

Carbon 语言元组与元组索引(Tuples and Tuple Indexing):p003646 提案全解析与实现验证 Carbon 语言元组与元组索引Tuples and Tuple Indexingp003646 提案全解析与实现验证【免费下载链接】carbon-langCarbon Languages main repository: documents, design, implementation, and related tools. (NOTE: Carbon Language is experimental; see README)项目地址: https://gitcode.com/GitHub_Trending/ca/carbon-lang导读本文深入剖析 Carbon 语言设计提案 p003646: Tuples and tuple indexing它正式确立了 Carbon 中元组类型的存在与基本语法规则并新增了通过数值索引提取元组元素的能力tuple.0、tuple.(expr)及指针形式的-0、-(expr)。读完本文你将掌握 Carbon 元组索引的两套完整语法、其背后的上下文相关词法规则、索引边界与拼写约束以及该设计在工具链源码与测试用例中的落地证据。提案背景为什么需要元组索引提案指出在 Carbon 之前的设计中访问元组元素的唯一途径是模式匹配pattern matching。虽然模式匹配能覆盖大多数场景但当只需要单个元素的值时它显得过于繁琐——因此需要一种更简洁的按数值索引访问方式。提案同时对比了主流语言的既有做法Python使用方括号tup[1]索引元组Cstd::pair用.first/.secondstd::tuple用std::getIRust 与 Swift使用.NN为十进制整数且禁止在N中使用数字分隔符与进制前缀Rust 因历史原因允许部分字面量后缀。提案还特别指出Carbon 现有文档中一直建议使用tuple[i]进行元组索引但该语法此前从未经过正式提案审批这正是本提案要补上的缺口。提案核心正式确立元组类型在语法与索引设计之前提案首先补上了元组类型的名分Carbon 中存在元组类型它们是具名位置元素unnamed positional elements的乘积类型product type。此前的多份提案虽已隐含支持元组但从未有一份提案正式声明其存在。此外提案将此前仅在 leads issues 中确定、但未形成提案的设计决策正式纳入设计Leads issue #2191单元素元组及其语法尽管聚焦于单元素元组但确立了所有元数的元组语法。Carbon 元组允许可选尾随逗号而单元素元组强制要求尾随逗号如(42,)Leads issue #710确立了元组的赋值、比较与隐式转换规则——这些操作均**逐元素elementwise进行其中关系比较按字典序lexicographically**执行。元组索引语法总览本提案的核心新增内容是元组索引支持以下两种语法语法形式说明.NN为整数字面量如tuple.0、pair.1.(expr)expr为整数类型的模板常量template constant如tuple.(1 1)对于指向元组的指针同样支持-N与-(expr)两种形式。该语法设计有两大意图提供 C 中.first、.second与std::getI用法的迁移语法——允许表达式而非仅字面量作为索引可支持std::getexpression类代码的迁移保持与结构体成员访问语法的一致性让元组元素索引看起来像成员访问。词法规则详解.后紧跟数字的词法特判多层元组索引会产生诸如tuple_of_tuples.1.2的写法。关键问题在于若按现有词法规则1.2会被识别为一个实数real literal那么tuple_of_tuples.1.2就会被切分为tuple_of_tuples.1.2三个 token而非两次元组索引。为此提案引入新规则当一个.或-token 后紧跟数字时将其词法解析为.或-token 后跟一个整数integer literal绝不会解析为实数。也就是说词法切分变得轻微上下文相关contextual紧跟在.或-之后的 token 词法规则与其他任何上下文中的词法规则不同。提案同时给出了一种等价但非上下文相关的表述方式将.integer以及-integer视为一个单一词素lexeme但产出两个 token。这种表述对工具链实现更友好——例如语法高亮器可以直接把.i当作一种独立的 token 类型而无须实现上下文相关的词法。提案在 Rationale 中强调这一规则仅需查看数字字面量之前的单个字符即可决定它是元组索引还是通用数字字面量完全契合 低上下文敏感性原则。索引即名称十进制整数作为元素名提案将元组的各个元素视为以其十进制整数作为名称.0、.1等。在简单成员访问simple member access中整数的拼写必须精确匹配元素名称否则即为错误// OK let a: i32 (1, 2, 3).0; // 错误元组元素名中没有名为 0x0 的元素 let b: i32 (1, 2, 3).0x0; // 错误元组元素名中没有名为 1_2 的元素 let c: i32 large_tuple.1_2;即进制前缀如0x与数字分隔符如_均不允许出现在简单成员访问的索引中。但同样的拼写可作为表达式操作数使用见下文// 均为合法.() 形式接受表达式 let x: i32 (1, 2).(0x0); let y: i32 large_tuple.(1_2);这一设计在 成员访问设计文档 中有更完整的表述元组类型的成员名是integer-literal而非 word每个位置元素的名称即对应十进制整数成员解析的结果是指向元组对应元素的实例成员// ✅ a 42。 let a: i32 (41, 42, 43).1; // ❌ 错误没有名为 0x1 的元组元素。 let b: i32 (1, 2, 3).0x1; // ❌ 错误没有名为 2 的元组元素。 let c: i32 (1, 2).2; var t: (i32, i32, i32) (1, 2, 3); let p: (i32, i32, i32)* t; // ✅ m 3。 let m: i32 p-2;优先级与结合性.N语法与后缀成员访问语法.name拥有相同的优先级并可在同一表达式中自由组合a.0.x.1合法.(expr)语法并非本提案新创继续维持与.name相同的优先级成员访问表达式从左到右结合。优先级上成员访问高于所有其他表达式形式如1 X.Y解析为1 (X.Y)而低于主表达式字面量、未限定名称、括号表达式。表达式操作数.()形式的语义在.(expr)语法中若第一个操作数是元组第二个操作数是任意整数类型的常量则结果是对应的元组元素其效果等同于以十进制整数字面量指定索引该规则内建于语言本身.()索引目前不可重载not currently overloadable——这与a[i]下标语法通过IndexWith/IndirectIndexWith接口重写为方法调用形成鲜明对比详见 下标设计文档。在复合成员访问中若第二个操作数为整数或整数字面量类型则要求第一个操作数为元组类型或扩展了元组类型否则成员解析失败第二个操作数必须是非负的模板常量且小于元组元素个数// ✅ d 43。 let d: i32 (41, 42, 43).(1 1); // ✅ e 2。 let template e: i32 (1, 2, 3).(0x1); // ❌ 错误不存在索引为 4 的元组元素。 let f: i32 (1, 2).(2 * 2); // ✅ n 3。 let n: i32 p-(e);边界检查若元组索引不在 0 到元素个数 − 1的闭区间内则索引无效。该约束在检查器测试中得到了严格验证详见下文实现验证小节。元组切片本提案明确不做当前骨架设计skeleton design曾建议使用tuple[a .. b]对元组进行切片例如tuple[0 .. 2]提取前两个元素。本提案不覆盖元组切片但指出未来可通过tuple.(0 .. 2)这类语法补充。同时提案提醒风险该语法可能引导出关于 Carbon 的错误理论——即tuple.__给出元素而tuple.(__)给出一个元组。切片提案若成行还应重新审视从末尾负向索引见备选方案的需求。设计动机与理由Rationale提案依据 项目目标 给出了设计理由目标/原则对应设计考量语言工具与生态词法规则实现相对简单语法高亮器等工具可将.i视为独立 token 类型而无须上下文相关词法软件与语言演进统一使用元组字段索引有助于支持随时间新增元组元素的代码演进易读、易懂、易写的代码元组访问比模式匹配更简洁将.1.2词法解析为四个 token 而非两个避免链式成员访问难以书写简单成员访问要求无分隔符的十进制整数使索引可视为元素名与现有 C 代码的互操作与迁移为.first、.second、std::getI提供迁移语法允许表达式索引以支持std::getexpression迁移低上下文敏感性原则仅查看数字字面量前一个字符即可决定词法解析方式备选方案讨论备选词法规则方案 A将.0、.1等整体作为单一 token。这会简化词法不再上下文相关但被否决原因有二与struct.fieldname的处理不一致且要么tuple . 0非法与结构体不一致要么需要为tuple.0单独建立语法产生式。方案 B只要前一个 token 是.就词法解析为整数无论是否紧跟。例如将((1, 2, 3), 4) . 0.1视为元组索引而非元组后跟.与实数。Swift 采用此做法。否决原因此处的0.1看起来像实数会造成读者困惑且会令上下文相关词法变为非局部规则。方案 C其他达到类似效果的手段如允许.后的实数再拆分为成员访问rustc的做法、或把实数切为整数 token .token 后缀 token再由解析器合并intellij-rust 的做法。提案指出这些方案并非完全等价如 Rust 中 proc macro 可观察差异且任何 token 合并/拆分都会导致 token 流与程序解释不匹配对工具链不友好——例如许多 Rust 语法高亮器无法正确高亮链式元组索引。十进制索引限制Carbon 与 Rust、Swift 一致将元组索引限制为十进制整数。该限制引入了.0x0与.(0x0)之间的不一致可轻易去掉但它允许将.0、.1等直接视为元组元素的名字类似结构体字段名且进制前缀或数字分隔符并无明确实用价值。方括号记法替代方案是tuple[0]与tuple[IndexConstant]。优点是与常量/表达式下标语法更一致缺点是与结构体成员访问不够一致。提案认为非常量索引的元组访问是罕见操作且.记法更能传达开发者意图x[n]记法主要面向**同质homogenous**索引如数组、容器通常允许运行时索引.记法用于**异质heterogenous**访问元组索引要求常量索引正如结构体成员访问要求常量名称——这体现了二者在求值阶段上的差异。此外.N记法未来可扩展为对结构体/类的成员索引[]记法难以支持后者。[]记法的优势是减少O.0、l.0、Z.0与0.0、1.0、2.0的视觉混淆但 Rust/Swift 实践中未见此问题且类似歧义如F(O, l, Z)与F(0, 1, 2)在无.0后缀时同样存在。从元组末尾负向索引Python 风格的tuple.-1或tuple.(-1)表示最后一个元素被否决这种记法容易混淆且存在尴尬的边缘情况——**差一错误off-by-one**或访问超出起始一个的元素时有时会被接受并静默执行错误操作。提案明确若未来引入元组切片应重新评估此问题切片常需要从末尾取元素并可考虑不同记法如tuple.(.size - 1)。尾随逗号Carbon 元组允许可选尾随逗号单元素元组强制尾随逗号其备选方案已在 leads issue #2191 中讨论。实现验证源码与测试中的落地证据提案设计已在当前仓库的工具链中实现并测试。最直接的证据是检查器check阶段的文件测试 toolchain/check/testdata/tuple/element_access.carbon其中覆盖了提案定义的几乎全部行为基础访问b.0提取单元素元组(i32,)的第 0 个元素非常量索引表达式a.({.index 1}.index)、a.(0 as i32)均可作为表达式索引使用边界错误TupleIndexOutOfBounds——对(i32,)使用b.1、对(i32, i32)使用a.2、对空元组F().0、以及a.(-10)负索引均报错非常量索引报错a.(b)b为运行时变量报TupleIndexNotConstant并伴随对编译期专属函数的非常量调用错误非整数索引报错a.(2.6)报ConversionFailure提示Core.FloatLiteral无法隐式转换为Core.IntLiteral非元组类型报错对array(i32, 2)使用.0报TupleIndexOnANonTupleType明确只有元组才能这样索引。元组类型本身的基础语义空元组、嵌套元组、单元素/双元素元组及其复制由 toolchain/check/testdata/tuple/basics.carbon 验证其中嵌套元组(((), ()), ())的 SemIR 转储清晰地展示了tuple_access ... element0/element1的嵌套链式访问结构。从源码结构看元组元素索引在语义层由SemIR::TupleAccess指令表示其元素序号使用 toolchain/sem_ir/field.h 中定义的ElementIndex类型基于IndexBase并在 toolchain/sem_ir/inst_categories.h 中被列入表达式指令类别——这印证了提案中元组索引是内建于语言、不可重载的成员访问这一语义定位与通过接口重写实现的a[i]下标见 docs/design/expressions/indexing.md走的是完全不同的代码路径。如果你希望本地运行这些测试验证行为可执行仓库为只读仅限测试运行bazel test //toolchain/testing:file_test \ --test_arg--file_teststoolchain/check/testdata/tuple/element_access.carbon小结提案 p003646 为 Carbon 语言补上了两块拼图一是以正式提案的形式确立了元组类型及其基本语义乘积类型、逐元素赋值/比较/隐式转换、单元素元组强制尾随逗号二是新增了.N与.(expr)以及指针的-形式两套元组索引语法并配套定义了上下文相关的词法规则、十进制元素命名约束、与成员访问一致的优先级以及严格的边界检查。它明确拒绝了方括号记法、负向索引与切片语法留待未来提案并通过 Rationale 将每项选择锚定到项目目标与低上下文敏感性原则。这些设计决策不仅停留在文档层面更已在检查器测试与 SemIR 指令层面完整落地可供语言实现者与工具链开发者直接参照。【免费下载链接】carbon-langCarbon Languages main repository: documents, design, implementation, and related tools. (NOTE: Carbon Language is experimental; see README)项目地址: https://gitcode.com/GitHub_Trending/ca/carbon-lang创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表