ARTICLE DETAIL

资讯详情

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

Carbon 语言 while 循环语法提案全解析:从设计决策到编译器落地

Carbon 语言 while 循环语法提案全解析:从设计决策到编译器落地 Carbon 语言 while 循环语法提案全解析从设计决策到编译器落地【免费下载链接】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-langwhile循环是 Carbon 语言基础控制流的关键组成。本文以 Carbon 官方提案 proposals/p000340-while-loops.md 为主体完整解析其背景调研、语法语义决策、C 基线取舍逻辑并结合仓库中解析器parse与语义检查check的真实源码与测试用例展示该提案如何从设计文档一步步落地为可运行的编译器实现。读完本文你将掌握 Carbonwhile/continue/break的完整语法规则、设计动机以及它们在toolchain中的具体实现路径。提案背景为何需要正式定义while在 Carbon 语言的早期阶段语言概述文档 中已经提及while但其语法细节仍处于暂定状态。控制流是一门口语言的核心能力而while又是其中最基本的构件——它在众多语言中形态相近即便细节各有差异。提案认为尽早将其正式化、固定下来比继续维持模糊的暂定状态更有利于语言演进。这正是 p000340 提案存在的直接动因。背景调研主流语言中while的形态对比提案在动手设计之前系统梳理了 C 系及主流现代语言中while循环的既有形态为后续以 C 为基线的决策提供了横向参照。C 系Java 与 TypeScriptC 提供经典的while与do/while两种形态Java 和 TypeScript 基本照搬了这一语法while (x) { DoSomething(); } do { DoSomethingElse(); } while (y);Python无do/while但有while/elsePython 不提供do/while但其while上的else子句——在条件从未为真时执行的代码——引起了提案的关注while x: DoSomething() while True: DoSomethingElse() if not y: break while z: print(z is true) else: print(z was never true)Swift用repeat替代doSwift 的关键词差异在于使用repeat而不是do其余结构相同while x { DoSomething() } repeat { DoSomethingElse() } while yRust只有基础while借助loop实现先执行后判断Rust 仅提供基础while循环do/while式的至少执行一次行为通过无条件loop加条件break组合实现while x { DoSomething(); } loop { DoSomethingElse(); if (!y) { break; } }Go没有while一切皆forGo 语言中不存在while关键字只提供for循环但for可以省略子句写法上几乎等价于whilefor x { DoSomething() } for { DoSomethingElse(); if !y { break; } }这一横向对比为提案定下了基调Carbon 将回归最经典的 C 形态而不是引入repeat、loop或while/else等变体。核心提案采用与 C/C 一致的三种语句提案明确主张 Carbon 应采用与 C 和 C 一致的while循环语法具体包含三种语句while声明一个循环并承载循环条件continue直接进入下一次循环迭代从循环条件重新开始break立即跳出循环不再测试循环条件。三者组合即可覆盖绝大多数循环场景且对 C 开发者零学习成本。语法细节与执行语义while语句语法形式为while (boolean expression) {statements}while会在每轮循环之前求值循环条件仅当条件为真时继续执行循环体条件求值为假时循环立即结束。例如 docs/design/control_flow/loops.md 中的示例依次打印0、1、2后打印Done!var x: Int 0; while (x 3) { Print(x); x; } Print(Done!);与if/else提案Carbon PR #285保持一致while后的大括号可选但必须成对若省略大括号则循环体只能包含一条语句若使用大括号则必须以{ ... }形式成对出现。continue与breakcontinue直接跳到下一次循环迭代跳过循环体中后续的所有语句。下一次迭代行为与正常迭代一致——从重新测试循环条件开始。break立即退出循环不再测试条件。二者的行为与 C/C 完全一致。设计文档 loops.md 给出了break的典型场景处理步骤列表遇到手动步骤即中止for (step: Step in steps) { if (step.IsManual()) { Print(Reached manual step!); break; } step.Process(); }continue的典型场景则是跳过空行继续处理文件见 loops.mdvar f: File OpenFile(path); while (!f.EOF()) { var line: strbuf f.ReadLine(); if (line.IsEmpty()) { continue; } Print(line); }可执行语义形式Executable semantics form提案给出了形式化的语法定义YACC 文法将上述三条语句精确落地%token WHILE %token CONTINUE %token BREAK statement: WHILE ( expression ) statement | CONTINUE ; | BREAK ; | /* preexisting statements elided */ ;其中特别强调continue和break只能在循环上下文中使用。文法层面虽然允许它们出现在任意 statement 位置但语义检查阶段必须拦截循环外使用的情况——这一点在仓库的语义检查实现中得到了严格验证下文详述。源码实现印证从文法到编译器提案最终被采纳并进入语言正式设计见 docs/design/control_flow/loops.md。其在toolchain中的落地路径清晰可循分为解析parse与语义检查check两个阶段。解析器语法树节点的定义与状态机在 toolchain/parse/node_kind.def 中while/break/continue被声明为完整的语句节点族CARBON_PARSE_NODE_KIND_STATEMENT(BreakStatementStart) CARBON_PARSE_NODE_KIND_STATEMENT(BreakStatement) CARBON_PARSE_NODE_KIND_STATEMENT(ContinueStatementStart) CARBON_PARSE_NODE_KIND_STATEMENT(ContinueStatement) CARBON_PARSE_NODE_KIND_STATEMENT(WhileConditionStart) CARBON_PARSE_NODE_KIND_STATEMENT(WhileCondition) CARBON_PARSE_NODE_KIND_STATEMENT(WhileStatement)解析状态机在 toolchain/parse/state.def 中定义StatementWhile→StatementWhileConditionFinish→StatementWhileBlockFinish条件部分复用ParenConditionAs(If|While|Match)的括号条件解析state.def体现了while与if条件语法的一致性设计。解析器的测试用例位于 toolchain/parse/testdata/while/覆盖了正常解析basic.carbon 验证while 条件 代码块 内部break/continue的完整解析树缺失大括号fail_unbraced.carbon 触发expected braced code block [ExpectedCodeBlock]错误——注意这里的大括号虽可选但省略后仅允许单条语句且测试注释中标注了TODO: This should have an error缺少分号fail_no_semi.carbon 验证break/continue必须以;结尾ExpectedStatementSemi缺少条件fail_missing_cond.carbon 验证while后必须紧跟(ExpectedParenAfter。语义检查CFG 块结构与循环限定语义检查的核心实现在 toolchain/check/handle_loop_statement.cpp它把while编译为经典的三块 CFG控制流图结构StartLoopHeader无条件跳转到循环头块preheader确保循环始终有前置块BranchAndStartLoopBody将条件表达式转换为boolConvertToBoolValue然后按真/假分别分支到循环体块与循环出口块同时把break目标出口块与continue目标循环头块压入break_continue_stack并记录清理作用域深度以正确处理临时对象的析构FinishLoopBody在循环体末尾添加回边back-edge跳回循环头完成闭环。break与continue的语义检查位于同一文件L276-L291 与 L301-L316如果break_continue_stack为空说明当前不在任何循环内将分别报出BreakOutsideLoopbreakcan only be used in a loop与ContinueOutsideLoopcontinuecan only be used in a loop诊断错误——这正是提案中continue/break仅限循环上下文规则的落地实现。语义测试SEM IR 可视化验证语义检查测试 toolchain/check/testdata/while/while.carbon 通过//dump-sem-ir输出 SEM IR直观展示了上述三块结构!while.cond: ... if %.loc12_16.2 br !while.body else br !while.done !while.body: ... br !while.cond !while.done: ...其中break_continue.carbon子测试还验证了嵌套循环中continue/break分别绑定到最近的循环continue跳回!while.cond.loc14/loc17break跳到对应的!while.donefail_bad_condition.carbon则验证了条件类型必须是bool{}无法隐式转换为bool时报ConversionFailurefail_bad_break_continue.carbon验证循环外使用break/continue的诊断信息。取舍与说明CaveatsC 基线原则这套语法以 C 为基线其依据是 Carbon 项目目标中的迁移子目标——为有经验的 C 开发者提供熟悉感与平缓的学习曲线。提案明确表示凡是对 C 语法的偏离只有当备选方案明显更优时才值得采纳而本提案的首要目标是避免无谓争论、产出一份平凡的提案。对于可能引发争议的备选方案应由倡导者在单独提案中另行探讨。do/while暂缓do/while因社区对是否纳入 Carbon存在分歧而明确排除在本提案之外。这样做的目的是将无争议的while部分独立评审避免被do/while的争论拖累。换言之do/while不是被否决而是留待单独提案。目标依据为什么这样设计符合 Carbon 定位提案从 Carbon 项目目标中援引了两条核心依据详见 docs/project/goals.md目标 3代码易于阅读、理解与编写——while循环本身易读且极具实用性目标 7与现有 C 代码的互操作与迁移——语法贴近 C 将显著降低开发者的迁移门槛。这两条目标正是以 C 语法为基线决策的顶层依据。备选方案讨论if/else提案PR #285中讨论过的两个备选方案同样适用于while去掉括号或强制要求大括号或两者兼有。本提案的结论与之保持一致以避免语法体系内部出现分歧。非 C 语法明确排除但保留扩展空间提案明确列出了一些 C 中不存在的非 C 特性均不建议在此时引入while上的else子句如 Python条件从未为真时执行具有while(true)行为的loop语句如 Rust带标签的break/continue如 Java、TypeScript。这些特性未来可能追加但它们不属于 C 基线范畴且提案评估认为采用当前提议的语法不会显著妨碍未来再引入这些特性。设计文档 loops.md 也继续引用了这些备选条目供后续决策参考。while中初始化变量留待表达式语义演进本提案不提供在while条件中初始化变量的能力。对比之下C 允许在条件中声明变量while (optionalT next get_next()) { ... }另外C 的 Selection statements with initializerP0305R1 可以引申出对应的while (init; cond)语法猜想。但提案认为Carbon 更可能走另一条路线——允许在表达式中声明变量。若如此下面这段代码合法不是因为while使用了允许变量声明的condition语义而是因为它使用expression语义、var属于expression的一部分while (var optionalT next get_next()) { ... }这条路线还能覆盖 C 难以处理的更复杂场景例如while ((var status_code c bar()) ! SUCCESS) { ... }这略偏离了 C 基线只提供 C 功能的子集。但提案的判断是若后续expression语义最终不包含var届时再补充相关功能即可暂时省略condition功能可以避免将来与expression路线冲突时不得不回头调和而且它对while循环的核心功能并不关键。小结Carbon 的while循环以最小分歧、贴近 C为设计哲学三种语句、一对括号、可选成对大括号语义完全对齐 C/C。从 proposals/p000340-while-loops.md 的提案文本到 docs/design/control_flow/loops.md 的正式设计再到toolchain/parse与toolchain/check中的解析器状态机、CFG 块生成与循环限定诊断以及覆盖正常/错误场景的完整测试数据这条从设计到实现的链路清晰完整。对于想深入阅读源码的读者建议从 handle_loop_statement.cpp 与 while 解析测试目录 入手对照本文所述的三块 CFG 结构与各类诊断信息逐一验证。【免费下载链接】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),仅供参考
返回列表