feat(interp): 字符串插值 ${...} 展开(lexer part-token + parser 链 + checker 就地改写;含对抗复核五条) - #126
Merged
Merged
Conversation
dslsdzc
force-pushed
the
feature/interp-expand
branch
from
September 18, 2026 01:12
afcf126 to
d84ac05
Compare
**背景**:`#124`(同链前一提交)修掉 lexer 插值分支**双推进**(`}` 后首字符静默丢 / 收尾引号被吞 ⇒ 串吞到行尾 ⇒ 顶层 `fn` P21 级联);本提交按裁定 (b) 实现**展开**,让 `${...}` 真正取值。 **实现(三段)** 1. **lexer**:含洞字面量**拆 part token**——段 = `T_STRING`、洞 = `T_INTERP`(lexeme = 洞内原文)。 扫描 = **花括号配平**(`${S{f=1}}`/`${S{f=1}.f}` 取到配对 `}`;旧「跳至首个 `}`」会截断), 洞内字符串字面量及其转义整体跳过;换行/EOF 终止(未闭合 ⇒ parser 报 P027)。 iv 位回填(**用加法不用按位或**——bootstrap 后端不支持 `|`/`&`,实测 `NotImplementedError: Binary op |`): +1 = 属本插值字面量 · +2 = 其后还有 part · 4 = 洞已闭合。 **无洞字面量与旧实现逐字相同**(单 T_STRING、同 line/col、iv=0)⇒ 非插值语料产物零足迹。 2. **parser**:`parse_interp_run` 把 part 串成 `seg + hole + seg …` 链(**只连同字面量的 part** ⇒ `"${x}" "y"` 仍是两个字面量、裸邻接字符串照旧报错);洞节点 = 新 kind `EXPR_INTERP_HOLE`(data = 洞文本)。 洞表达式在 **`parse_all` 末尾统一解析**(那时本文件 token 流已用毕 ⇒ 可安全重新 `tokenize`;洞内嵌套插值 产生的新洞节点由同一循环自然覆盖)。 3. **checker**:`EXPR_INTERP_HOLE` **就地改写**为带类型转换的表达式——扁平 AST 父节点只存索引 ⇒ **无需父指针**。转换表:`string` 恒等(字段副本)· `int → int_str(x)` · `bool → bool_str(x)`(**不经 int**, 遵「bool 不隐式转 int」裁定,返回 `"true"`/`"false"`)· **`char`/`dex`/其它 ⇒ P028 硬错**。 **两条实测更正(对签字 A–E 的落地修正,逐条有实测)** - **`bool` 不能合成 `if` 表达式**:`"v=" + if b { "true" } else { "false" }` **手写亦 rc=139**(预存缺陷) ⇒ 只能走**函数调用面** ⇒ `fmt.cr` 新增 `bool_str`(代价见下「载体」)。 - **`char` 本批不放开**:char 运行期值是**字符串**、类型是 `TI_CHAR` ⇒ `chr(char)` 把串指针当码点(实测输出空); 改恒等则踩 **`string + char` = rc=139**(预存,`ch := 'Z'; "c=" + ch` 独立复现,已登记 `#2026-09-18-13`)。 `dex` 两表示(bits/scaled)各需规则 ⇒ 不猜、硬错(文案指向显式转换)。 **换代**:`CIR_CACHE_VER 20 → 21`——含插值源修复前或崩、或(`}` 换行形态)编成**原文串常量**(静默空转), `.cir` 键 = 源路径::函数名 + AST 指纹(同源前后相同)⇒ 旧快照会把旧语义原样复活 ⇒ 必须换代(无害重建)。 **判据**(`tests/selfhost/test_string_interp.py` 重写,**全绿**;已挂 `selfhost-tests`) A 解析完整性 3 例(同行含 `}`/后续语句 ⇒ 无 P21 + rc)· **B 值 10 形态**(变量/表达式/bool/string 恒等/ 多段/相邻/嵌套调用/**洞内花括号配平**/`\${` 字面/实参位)· **C 错误面 4 例**(未闭合 / `${}` 空 ⇒ **P027**; 结构体 / dex ⇒ **P028**;每条 = check rc=1 + 码 + build rc=1 + **零产物**)· D bootstrap 面事实 (bootstrap lexer 仍「原文保留」⇒ **两前端分歧**,已登记)· E 回退守卫 4 条(lexer/parser/checker/bool_str 形状)。 **零足迹(非插值面)**:`tests/suite`+`tests/fixtures` 37 档 `check` rc / `build` rc / `.ccr` / ELF **逐字节 IDENTICAL**(对照 = 展开前二进制,两侧各自 clean-cache);`check src/compiler/main.cr` **rc=0**; CI `check` job 本地 **rc=0**。 ⚠ **canary/载体面(已上报取裁)**:`fmt.cr` 新增 `bool_str` ⇒ 凡 `import fmt` 的程序产物变大 (pa ELF 28822→28854 **+32B**、`.ccr` +725B,gt 同族)⇒ 按 §6「ELF canary 变 ⇒ 停下上报」已上报, 经维护者声明 + 同批**重锁**(旧值留痕)。 **同批附带**:LSP 镜像 `src/lsp/analysis.cr` span —— 删**逐字复制的双推进**(`:1046`「镜像 lexer 循环尾 _pos+1」) + 扫描改**配平**(段止于 `${`、洞按配平)+ 两处契约文字重定;`docs/pseudocode/compiler/lexer.md` 示例 9/16 同批重定; `TODO.md #2026-09-18-11` 补展开实现段 + 两条 ⚠;新增 `#2026-09-18-13`(`string + char` rc=139 预存)。 **自源即语料(当场踩到、已修)**:P027 诊断**文案里带 `${}`** ⇒ 自举编译器检查自身源码即报 P027 ⇒ `check src/compiler` 红。已把文案中的 `$` 转义(`\${`)⇒ 复验 rc=0。
dslsdzc
force-pushed
the
feature/interp-expand
branch
from
September 18, 2026 01:16
d84ac05 to
ba0c6be
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
批 8(静默面收口)插值展开:lexer 拆 part token + parser 串链 + checker 就地改写(裁定 (b) 同批落地)。
背景
#124(已合2dbe528b)修掉 lexer 插值分支双推进(}后首字符静默丢 / 收尾引号被吞 ⇒ 串吞到行尾 ⇒ 顶层fnP21 级联)。本 PR 按裁定 (b) 实现展开,并同批处理对抗复核五条 + 维护者四条裁定。
实现
T_STRING/ 洞T_INTERP,lexeme = 洞内原文)。洞扫描按复核要求显式跳过:嵌套字符串字面量(含转义)· char 字面量 · 行注释 · 块注释;跨行/EOF 终止。iv 回填用加法(+1/+2/4+% 4/>= 4判读)——bootstrap 后端不支持|/&(实测NotImplementedError: Binary op |,登记#2026-09-18-15)。parse_interp_run串成seg + hole …链(只连同字面量的 part;无洞字面量逐字同旧 ⇒ 非插值语料零足迹);洞表达式在parse_all末尾统一解析。EXPR_INTERP_HOLE就地改写(扁平 AST 父只存索引 ⇒ 无需父指针):string恒等 ·int → int_str·bool → bool_str· 其余 ⇒ P028;畸形插值 ⇒ P027。ir_gen对残留洞 ⇒ P029 响亮拒绝(绝不静默当空值);monomorph.cr::gen_clone_tree显式克隆分支(防未知 kind 静默丢子树)。对抗复核五条处置(详见
docs/superpowers/plans/2026-09-18-interp-expansion.md)CIR_CACHE_VER 21→22,依据改为身份闸 + 语义面变化(复核实证:func_fingerprint的 body walk 是 stub ⇒ 指纹不覆盖函数体;真正防线 =cir_cache.cr:549-551身份比对)⇒ 登记#2026-09-18-16。bool_str为新增 helper(不合成if:手写"v=" + if b {…}亦 rc=139 ⇒#2026-09-18-14);char洞 ⇒ P028(实测两条路都不通:chr(char)输出空 / 恒等踩string + charrc=139 ⇒#2026-09-18-13);泛型洞T⇒ P028 + 未覆盖面。${}空 · 泛型洞 · dex 两形态 · bool 值断言 · 未闭合两形态 ·\${口径;断言面 = 运行值;build 面零产物显式断言;既有nested_braces用例同批重锁(本批改了 lexer)。判据(本地全绿)
tests/selfhost/test_string_interp.py全 PASS(A 解析完整性 · B 值 13 形态(含扫描硬化三例)· C 错误面 7 例(P027×3 / P028×4)· D bootstrap 面事实 · E 回退守卫 4 条)。checkjob rc=0(含自源check src/compiler;自源即语料当场踩到并已修:P027 诊断文案里曾带${}⇒ 自举检查自身源码即红 ⇒ 已把$转义)。suitejob ALL PASS(35 档 build+run)。tests/suite+tests/fixtures37 档.ccr/ELF 逐字节 IDENTICAL(对照 = 展开前二进制,两侧各自 clean-cache)。fmt.cr新增bool_str⇒ 凡import fmt程序变大:pa ELF +32B、.ccr+520B),不是发射面泄漏(反面证据 = 非插值语料逐字节不变);值表头注含「内容面 ≠ 发射面」区分 + 两条旧值留痕(pre-fix(cir): 串域跨进程 id 修复——生成期 intern 日志 + 装载期按序重放(CIR_CACHE_VER 20→21;canary 待声明重锁) #123 与 fix(cir): 串域跨进程 id 修复——生成期 intern 日志 + 装载期按序重放(CIR_CACHE_VER 20→21;canary 待声明重锁) #123 重锁值)。J1–J66/6(TODO 条目-11…-16,与 develop 既有条目按号序并集)。CIR_CACHE_VER 21→22(含插值源修复前后 IR 不等价)。未覆盖面(显式登记,理由 = 实测)
char插值 ·dex插值(两形态)· 泛型洞T· bootstrap 面仍「原文保留」(两前端分歧)· 洞扫描对新词法形态的同步(残余风险)。