11//! layoutcode(对齐 layout/layout.go):检查 AST 并把结果布局写到 /lib/ 下的结构化 KV。
22//!
33//! 存储约定:
4- //! /lib/<pkg>·<name>/[0,0] 布局后签名 (kind=rwfunc)
5- //! /lib/<pkg>·<name>/<param> 命名参数→slot 指针(langtype=char , ref=1)
4+ //! /lib/<pkg>·<name>/[0,0] 布局后签名锚点 (kind=rwfunc,body=计数头 [nr,nw,dyn] )
5+ //! /lib/<pkg>·<name>/<param> 命名参数→slot 指针(langtype=该参类型 , ref=1, body=坐标 )
66//! /lib/<pkg>·<name>/[i,j] 编译后指令(kind=rwir),i 从 1 开始
77//! /lib/<pkg>·<name>/‥labels/<l> label → irseq
8- //! /lib/<pkg>·<name>.src 源码副本
8+ //! /lib/<pkg>·<name>.src 源码副本(仅 write_func 保留写入,dump 不再依赖)
99//!
1010//! WriteBody: DFS-number insts (incl. ScopeStmt), emit [i,j], rewrite goto/br labels to irseq.
11+ //! dump: 反向——严格读 /lib/<pkg> 子树重建 AST(签名读命名参数 Ptr、体读线性槽+‥labels),
12+ //! 不读 .src、不依赖签名行 [0,x] 静态槽。
1113
1214use std:: collections:: HashMap ;
1315
14- use super :: ast:: { Expr , Func , Instruction , RwirDecl , Stmt , StructDecl } ;
16+ use super :: ast:: { self , Expr , Func , FuncSig , Instruction , Param , RwirDecl , ScopeStmt , Stmt , StructDecl } ;
1517use super :: ffi:: Kv ;
1618use super :: { builtin, ffi, keytree, kvkind, lower, parser} ;
1719
@@ -173,15 +175,16 @@ pub fn dump(kv: &mut Kv, lib: &str) -> String {
173175 // prefix 本身就是函数目录:直接重建该函数(pkg/name 从路径反推)。
174176 let base = prefix. trim_start_matches ( "/lib/" ) ;
175177 let ( fpkg, name) = func_identity ( "" , base) ;
176- let src = kvkind:: value_string ( & kv. get_one ( & format ! ( "{prefix}.src" ) ) ) ;
178+ let dir = format ! ( "{prefix}/" ) ;
179+ let text = reconstruct ( kv, & dir, & name) ;
177180 let mut slots = Vec :: new ( ) ;
178- collect_slots ( kv, & format ! ( "{prefix}/" ) , & mut slots) ;
181+ collect_slots ( kv, & dir , & mut slots) ;
179182 funcs. push ( DumpFunc {
180183 pkg : fpkg,
181184 name,
182- src ,
185+ text ,
183186 slots,
184- dir : format ! ( "{prefix}/" ) ,
187+ dir,
185188 } ) ;
186189 } else {
187190 // 虚拟 pkg:func dir 以 prefix 为前缀(`/lib/foo` 匹配 `/lib/foo·*` 与 `/lib/foo/*`)。
@@ -210,11 +213,11 @@ pub fn dump(kv: &mut Kv, lib: &str) -> String {
210213 out
211214}
212215
213- /// 一个可运行函数:源码(.src) + 原始槽位注释。
216+ /// 一个可运行函数:从 /lib 子树重建的源码 + 原始槽位注释。
214217struct DumpFunc {
215218 pkg : String ,
216219 name : String ,
217- src : String ,
220+ text : String ,
218221 slots : Vec < String > ,
219222 dir : String ,
220223}
@@ -262,13 +265,13 @@ fn collect_funcs(
262265 let mem_sub = format ! ( "{prefix}{base}·" ) ;
263266 if is_func_dir ( kv, & dir_sub) {
264267 let ( fpkg, name) = func_identity ( pkg, & base) ;
265- let src = kvkind :: value_string ( & kv . get_one ( & format ! ( "{prefix}{base}.src" ) ) ) ;
268+ let text = reconstruct ( kv , & dir_sub , & name ) ;
266269 let mut slots = Vec :: new ( ) ;
267270 collect_slots ( kv, & dir_sub, & mut slots) ;
268271 funcs. push ( DumpFunc {
269272 pkg : fpkg,
270273 name,
271- src ,
274+ text ,
272275 slots,
273276 dir : dir_sub,
274277 } ) ;
@@ -342,7 +345,7 @@ fn emit_node(out: &mut String, node: &DumpNode, indent: &str) {
342345}
343346
344347fn emit_func ( out : & mut String , f : & DumpFunc , indent : & str ) {
345- for line in f. src . lines ( ) {
348+ for line in f. text . lines ( ) {
346349 out. push_str ( indent) ;
347350 out. push_str ( line) ;
348351 out. push ( '\n' ) ;
@@ -360,6 +363,251 @@ fn emit_func(out: &mut String, f: &DumpFunc, indent: &str) {
360363 out. push ( '\n' ) ;
361364}
362365
366+ // ── dump 重建:严格从 /lib 子树反出可运行 kvlang(不读 .src)─────────────
367+ //
368+ // 数据来源(对齐 write_func / spec「指令布局格式」):
369+ // 签名 ← [0,0] 计数头(nr,nw,dyn) + 命名参数 Ptr 键(langtype=类型、body=[0,±k] 定位读/写与序)
370+ // 函数体 ← 线性指令槽 [n,0]=opcode、[n,-j]=读参、[n,j]=写参(n 连续、scope 已拍平)
371+ // 控制流 ← ‥labels/<label>=irseq;goto/br 的整数读参即 irseq,映射回 label 名并按 irseq 切块
372+ // 重建成 AST(Func) 后复用其 Display/full_text,箭头一律规范化为 `->`(源箭头风格不落盘)。
373+
374+ /// 单个函数目录 → 可运行 kvlang 文本(签名 + 体)。
375+ fn reconstruct ( kv : & mut Kv , dir : & str , name : & str ) -> String {
376+ let ( nr, nw, dynamic) = kvkind:: counts ( & kv. get_one ( & format ! ( "{dir}[0,0]" ) ) ) ;
377+ let sig = reconstruct_sig ( kv, dir, name, nr, nw, dynamic) ;
378+ let labels = read_labels ( kv, dir) ;
379+ let insts = read_insts ( kv, dir) ;
380+ let body = build_body ( & insts, & labels) ;
381+ Func {
382+ comments : Vec :: new ( ) ,
383+ sig,
384+ body,
385+ pkg : String :: new ( ) ,
386+ }
387+ . full_text ( )
388+ }
389+
390+ /// 从命名参数 Ptr 键重建签名:类型取 Ptr langtype,读/写与序取 body 坐标 [0,±k]。
391+ fn reconstruct_sig ( kv : & mut Kv , dir : & str , name : & str , nr : i32 , nw : i32 , dynamic : bool ) -> FuncSig {
392+ let blank = || Param {
393+ name : String :: new ( ) ,
394+ ty : String :: new ( ) ,
395+ } ;
396+ let mut params: Vec < Param > = ( 0 ..nr) . map ( |_| blank ( ) ) . collect ( ) ;
397+ let mut returns: Vec < Param > = ( 0 ..nw) . map ( |_| blank ( ) ) . collect ( ) ;
398+ for c in kv. list ( dir, false , true ) {
399+ if c. starts_with ( '[' ) || c. ends_with ( '/' ) || c. starts_with ( keytree:: RUNTIME_MEMBER_SEP ) {
400+ continue ; // 指令槽 / labels 目录 / 运行时保留字段
401+ }
402+ let data = kv. get_one ( & format ! ( "{dir}{c}" ) ) ;
403+ if !kvkind:: is_ptr ( & data) {
404+ continue ;
405+ }
406+ let ty = kvkind:: langtype ( & data) ;
407+ let ( is_read, k) = match parse_slot_coord ( & kvkind:: ptr_target ( & data) ) {
408+ Some ( v) => v,
409+ None => continue ,
410+ } ;
411+ let slot = Param {
412+ name : c. clone ( ) ,
413+ ty,
414+ } ;
415+ let dst = if is_read { & mut params } else { & mut returns } ;
416+ if k >= 1 && ( k as usize ) <= dst. len ( ) {
417+ dst[ k as usize - 1 ] = slot;
418+ }
419+ }
420+ if dynamic {
421+ if let Some ( p) = params. last_mut ( ) {
422+ if !p. ty . is_empty ( ) {
423+ p. ty . push_str ( "..." ) ;
424+ }
425+ }
426+ }
427+ FuncSig {
428+ name : name. to_string ( ) ,
429+ params,
430+ returns,
431+ }
432+ }
433+
434+ /// 解析槽坐标 `[0,-1]`/`[0,1]` → (是否读参, |k|)。
435+ fn parse_slot_coord ( s : & str ) -> Option < ( bool , i32 ) > {
436+ let inner = s. strip_prefix ( '[' ) ?. strip_suffix ( ']' ) ?;
437+ let col = inner. split ( ',' ) . nth ( 1 ) ?. trim ( ) ;
438+ let n: i32 = col. parse ( ) . ok ( ) ?;
439+ Some ( ( n < 0 , n. abs ( ) ) )
440+ }
441+
442+ /// ‥labels/ 子树 → (irseq, label),按 irseq 升序(体切块用)。
443+ fn read_labels ( kv : & mut Kv , dir : & str ) -> Vec < ( i32 , String ) > {
444+ let ldir = format ! ( "{dir}{}{}/" , keytree:: RUNTIME_MEMBER_SEP , keytree:: SEG_LABELS ) ;
445+ let mut out: Vec < ( i32 , String ) > = kv
446+ . list ( & ldir, false , true )
447+ . into_iter ( )
448+ . filter ( |c| !c. ends_with ( '/' ) )
449+ . filter_map ( |c| {
450+ let irseq: i32 = kvkind:: plain ( & kv. get_one ( & format ! ( "{ldir}{c}" ) ) ) . parse ( ) . ok ( ) ?;
451+ Some ( ( irseq, c) )
452+ } )
453+ . collect ( ) ;
454+ out. sort_by_key ( |( irseq, _) | * irseq) ;
455+ out
456+ }
457+
458+ /// 一条重建指令:opcode + 读操作数 + 写目标名。
459+ struct RawInst {
460+ opcode : String ,
461+ reads : Vec < Operand > ,
462+ writes : Vec < String > ,
463+ }
464+
465+ /// 操作数:引用(变量/opcode/路径)、字符串字面量、其它字面量(数值/bool)。
466+ enum Operand {
467+ Ref ( String ) ,
468+ Str ( String ) ,
469+ Lit ( String ) ,
470+ }
471+
472+ /// 线性读回 [n,*](n 从 1 连续到首个空 opcode 前)。
473+ fn read_insts ( kv : & mut Kv , dir : & str ) -> Vec < RawInst > {
474+ let mut out = Vec :: new ( ) ;
475+ let mut n = 1 ;
476+ loop {
477+ let op = kv. get_one ( & format ! ( "{dir}[{n},0]" ) ) ;
478+ if op. is_empty ( ) {
479+ break ;
480+ }
481+ let opcode = kvkind:: rwir_sig ( & op) ;
482+ let mut reads = Vec :: new ( ) ;
483+ let mut j = 1 ;
484+ loop {
485+ let d = kv. get_one ( & format ! ( "{dir}[{n},-{j}]" ) ) ;
486+ if d. is_empty ( ) {
487+ break ;
488+ }
489+ reads. push ( decode_operand ( & d) ) ;
490+ j += 1 ;
491+ }
492+ let mut writes = Vec :: new ( ) ;
493+ let mut j = 1 ;
494+ loop {
495+ let d = kv. get_one ( & format ! ( "{dir}[{n},{j}]" ) ) ;
496+ if d. is_empty ( ) {
497+ break ;
498+ }
499+ writes. push ( kvkind:: rwir_sig ( & d) ) ;
500+ j += 1 ;
501+ }
502+ out. push ( RawInst {
503+ opcode,
504+ reads,
505+ writes,
506+ } ) ;
507+ n += 1 ;
508+ }
509+ out
510+ }
511+
512+ /// 槽值 → Operand:rwir 族为引用/opcode 名,char 为字符串字面量,其余为明文字面量。
513+ fn decode_operand ( data : & [ u8 ] ) -> Operand {
514+ let k = kvkind:: kind ( data) ;
515+ if matches ! ( k. as_str( ) , "rwir" | "rwir|rwfunc" | "rwfunc" | "def rwir" ) {
516+ Operand :: Ref ( kvkind:: rwir_sig ( data) )
517+ } else if kvkind:: is_char_kind ( & k) {
518+ Operand :: Str ( kvkind:: plain ( data) )
519+ } else {
520+ Operand :: Lit ( kvkind:: plain ( data) )
521+ }
522+ }
523+
524+ fn operand_expr ( o : & Operand ) -> Expr {
525+ match o {
526+ Operand :: Ref ( s) | Operand :: Lit ( s) => ast:: leaf ( s) ,
527+ Operand :: Str ( s) => ast:: str_lit ( s) ,
528+ }
529+ }
530+
531+ /// goto/br 的整数读参 → label 名(查不到则原样保留数字)。
532+ fn label_leaf ( o : & Operand , by_irseq : & HashMap < i32 , String > ) -> Expr {
533+ if let Operand :: Lit ( s) = o {
534+ if let Ok ( n) = s. parse :: < i32 > ( ) {
535+ if let Some ( l) = by_irseq. get ( & n) {
536+ return ast:: leaf ( l) ;
537+ }
538+ }
539+ }
540+ operand_expr ( o)
541+ }
542+
543+ /// 线性指令 + labels → 语句序列:首 label 前为前导语句,各 label 段成 ScopeStmt。
544+ fn build_body ( insts : & [ RawInst ] , labels : & [ ( i32 , String ) ] ) -> Vec < Stmt > {
545+ let by_irseq: HashMap < i32 , String > = labels. iter ( ) . map ( |( i, l) | ( * i, l. clone ( ) ) ) . collect ( ) ;
546+ let total = insts. len ( ) as i32 ;
547+ let first = labels. first ( ) . map ( |( i, _) | * i) . unwrap_or ( total + 1 ) ;
548+ let inst_stmt = |i : i32 | Stmt :: Instruction ( build_inst ( & insts[ i as usize - 1 ] , & by_irseq) ) ;
549+ let mut body: Vec < Stmt > = ( 1 ..first) . map ( inst_stmt) . collect ( ) ;
550+ for ( bi, ( start, label) ) in labels. iter ( ) . enumerate ( ) {
551+ let end = labels. get ( bi + 1 ) . map ( |( i, _) | * i) . unwrap_or ( total + 1 ) ;
552+ body. push ( Stmt :: Scope ( ScopeStmt {
553+ comments : Vec :: new ( ) ,
554+ label : label. clone ( ) ,
555+ body : ( * start..end) . map ( inst_stmt) . collect ( ) ,
556+ } ) ) ;
557+ }
558+ body
559+ }
560+
561+ /// (opcode, reads, writes) → Instruction(箭头规范化为 `->`;复用 Display 还原算子/糖)。
562+ fn build_inst ( inst : & RawInst , by_irseq : & HashMap < i32 , String > ) -> Instruction {
563+ let expr = match inst. opcode . as_str ( ) {
564+ "" => None ,
565+ "return" => Some ( ast:: leaf ( "return" ) ) ,
566+ "=" => inst. reads . first ( ) . map ( operand_expr) ,
567+ "goto" => Some ( ast:: call (
568+ "goto" ,
569+ inst. reads
570+ . iter ( )
571+ . map ( |o| label_leaf ( o, by_irseq) )
572+ . collect ( ) ,
573+ ) ) ,
574+ "br" => {
575+ let mut args = Vec :: with_capacity ( inst. reads . len ( ) ) ;
576+ for ( i, o) in inst. reads . iter ( ) . enumerate ( ) {
577+ args. push ( if i == 0 {
578+ operand_expr ( o)
579+ } else {
580+ label_leaf ( o, by_irseq)
581+ } ) ;
582+ }
583+ Some ( ast:: call ( "br" , args) )
584+ }
585+ op => Some ( ast:: call ( op, inst. reads . iter ( ) . map ( operand_expr) . collect ( ) ) ) ,
586+ } ;
587+ // array·fill 首参即写目标 langtype(Display 隐去不回显),回填 write_types 恢复类型标注。
588+ // 且须用前置 `=` 式(arrow_left=true):parser 仅在前置标注式把写类型喂给 array·fill 首参,
589+ // 后置箭头式 `[5...] -> b:TYPE` 会丢弃该类型(parser 不对称),故这里强制前置式以保幂等。
590+ let is_fill = inst. opcode == "array·fill" && !inst. writes . is_empty ( ) ;
591+ let write_types = if is_fill {
592+ let ty = match inst. reads . first ( ) {
593+ Some ( Operand :: Str ( s) ) | Some ( Operand :: Ref ( s) ) | Some ( Operand :: Lit ( s) ) => s. clone ( ) ,
594+ None => String :: new ( ) ,
595+ } ;
596+ let mut v = vec ! [ String :: new( ) ; inst. writes. len( ) ] ;
597+ v[ 0 ] = ty;
598+ v
599+ } else {
600+ Vec :: new ( )
601+ } ;
602+ Instruction {
603+ comments : Vec :: new ( ) ,
604+ expr,
605+ writes : inst. writes . clone ( ) ,
606+ write_types,
607+ arrow_left : is_fill,
608+ }
609+ }
610+
363611/// 写函数到 /lib/:签名(rwfunc)、源码、参数 Ptr、指令体。
364612pub fn write_func ( kv : & mut Kv , pkg : & str , fn_ : & mut Func ) {
365613 let mut type_map = lower:: infer_types ( fn_) ;
0 commit comments