SpectraRust/REFACTORING_GUIDE.md
2026-03-21 09:12:18 +08:00

9.3 KiB
Raw Blame History

TLUSTY Rust 重构规范

1. 选定下一个重构目标

优先处理依赖少无io的函数

注意DATA 语句硬编码的数据表已经由scripts/extract_fortran_data.py生成到src/data.rs中

不要管复杂不复杂和有无common依赖 按python3 scripts/analyze_fortran.py --priority | head -10 的顺序来

分离出来的原始fortran函数在/home/fmq/program/tlusty/tl208-s54/rust/tlusty/extracted文件夹下

优先级排序

核心原则: 优先处理"传递未实现依赖=0"的函数,它们不依赖其他未完成的函数。

按以下顺序选择待重构函数:

  1. 无未实现依赖 (传递未实现=0)

    • 可立即开始,无需等待其他函数
    • 包括纯函数和只有 COMMON 依赖的函数
  2. 少量未实现依赖 (传递未实现=1~3)

    • 需要先完成少数依赖函数
    • --tree 查看具体依赖链
  3. 多未实现依赖 (传递未实现>3)

    • 依赖链较长,最后处理
    • 或考虑整体重构策略
  4. 有 I/O 依赖的函数

    • 最后处理,可能需要设计新的 I/O 抽象层

查询命令

CSV 列结构: fortran_file,unit_name,unit_type,is_pure,common_deps,call_deps,has_io,rust_module,status

依赖树分析

# 输出重构优先级列表(按未实现依赖排序,推荐!)
python3 scripts/analyze_fortran.py --priority

# 输出指定单元的依赖树
python3 scripts/analyze_fortran.py --tree UNIT_NAME

# 输出完整传递依赖的 CSV
python3 scripts/analyze_fortran.py --full > fortran_analysis_full.csv

优先级列表说明:

重构优先级列表 (按未实现依赖排序)
====================================================================================================
单元名                     未实现      传递未实现   深度     直接调用     传递调用   IO
----------------------------------------------------------------------------------------------------
C                         0          0    0        0        0    ○
ALIFR3                    0          0    0        0        0    ○
  • 未实现: 直接依赖中未完成的函数数
  • 传递未实现: 所有递归依赖中未完成的函数数(关键指标!)
  • 排序: 传递未实现少 → 深度低 → 依赖少
  • 只显示未完成pending的函数
  • IO 列: ○ = 无IO, ✓ = 有IO

依赖树输出示例:

依赖树: ALISK1 ○
============================================================
直接依赖: 4, 传递依赖: 27, 未实现: 20
未实现依赖: ALIFRK, OPACF1, OPADD, ROSSTD, ...
------------------------------------------------------------
○ ALISK1 (4未实现)
├── ○ OPACF1 (6未实现)
│   ├── ○ OPADD (5未实现)
│   │   ├── ○ cia_h2h2 (1未实现)
│   │   │   └── if [未找到/未实现]
│   │   └── ✓ locate
│   └── ...
└── ○ ALIFRK
  • ✓ = 已完成, ○ = 待处理
  • (N未实现) = 该节点有 N 个直接依赖未完成
  • 顶部汇总:传递未实现依赖数及列表
  • 子节点按未实现依赖数排序(多的在前)

按纯度筛选

无io的纯函数已经全部实现重构

按 I/O 筛选

# 有 I/O 的未完成函数 (最后处理)
awk -F, '$7=="True" && $9=="pending"' fortran_analysis.csv

# 无 I/O 的未完成函数 (优先处理)
awk -F, '$7=="False" && $9=="pending"' fortran_analysis.csv

# 无 I/O 且无调用依赖的未完成函数
awk -F, '$6=="" && $7=="False" && $9=="pending"' fortran_analysis.csv

按 COMMON 依赖筛选

# 只依赖 BASICS 的未完成函数
awk -F, '$5=="BASICS" && $9=="pending"' fortran_analysis.csv

# 依赖 BASICS 和 ATOMIC但无其他依赖
awk -F, '$5 ~ /^BASICS\|ATOMIC$/ && $9=="pending"' fortran_analysis.csv

# 不依赖 MODELQ 的未完成函数 (MODELQ 最复杂)
awk -F, '$5 !~ /MODELQ/ && $9=="pending"' fortran_analysis.csv

# 列出所有不同的 COMMON 依赖组合
awk -F, '{print $5}' fortran_analysis.csv | sort | uniq -c | sort -rn

按状态筛选

# 所有已完成函数
awk -F, '$9=="done"' fortran_analysis.csv

# 所有进行中函数
awk -F, '$9=="in_progress"' fortran_analysis.csv

# 统计各状态数量
awk -F, '{print $9}' fortran_analysis.csv | sort | uniq -c

组合筛选

# 最佳候选:无 I/O + 无调用依赖 + 纯函数或简单 COMMON
awk -F, '$6=="" && $7=="False" && $9=="pending"' fortran_analysis.csv

# 次优候选:无 I/O + 有调用依赖但依赖已完成
awk -F, '$6!="" && $7=="False" && $9=="pending"' fortran_analysis.csv

# 查看特定函数的依赖信息
awk -F, '$2=="TARGET"' fortran_analysis.csv

按代码大小排序

# 按行数排序(选小的先做)
cd tlusty/extracted
wc -l *.f | sort -n | head -30

# 查看小文件 + 纯函数
for f in $(ls *.f); do
  lines=$(wc -l < "$f")
  name=$(basename "$f" .f)
  if grep -q "True.*pending" ../../fortran_analysis.csv && [ $lines -lt 100 ]; then
    echo "$lines $name"
  fi
done | sort -n

快速查看

# 查看重构进度摘要
echo "已完成: $(awk -F, '$9=="done"' fortran_analysis.csv | wc -l)"
echo "待处理: $(awk -F, '$9=="pending"' fortran_analysis.csv | wc -l)"
echo "纯函数待处理: $(awk -F, '$4=="True" && $9=="pending"' fortran_analysis.csv | wc -l)"
echo "无IO待处理: $(awk -F, '$7=="False" && $9=="pending"' fortran_analysis.csv | wc -l)"

2. 重构流程

Step 1: 分析 Fortran 源码

# 查看源码
cat tlusty/extracted/TARGET.f

检查:

  • INCLUDE 文件列表
  • COMMON 块
  • 调用的其他函数
  • 是否有 I/O

Step 2: 创建 Rust 模块

# 创建文件
touch src/math/TARGET.rs

Step 3: 实现函数

遵循命名规范:

  • Fortran FUNCTION → Rust pub fn
  • Fortran SUBROUTINE → Rust pub fn (返回值用参数或元组)
  • COMMON 块 → 结构体参数

Step 4: 添加到 mod.rs

// src/math/mod.rs
mod target;
pub use target::target;

Step 5: 编写测试

#[cfg(test)]
mod tests {
    use super::*;
    use approx::assert_relative_eq;

    #[test]
    fn test_target_basic() {
        // 基本测试
    }
}

Step 6: 运行测试

# 单个模块测试 (不要 cargo test 全量!)
cargo test target

Step 7: 更新追踪表

# 如果是一对一映射,脚本自动识别
python3 scripts/analyze_fortran.py > fortran_analysis.csv
python3 scripts/generate_tracking.py > FORTRAN_TRACKING.md

# 如果是一对多映射,先更新 SPECIAL_MAPPINGS

3. SPECIAL_MAPPINGS 维护

何时需要更新

当一个 Rust 文件实现多个 Fortran 函数时,需要添加映射。

位置

scripts/analyze_fortran.py 第 72 行

格式

SPECIAL_MAPPINGS = {
    # Rust 文件名 -> [Fortran 函数名列表]
    'gfree': ['gfree0', 'gfreed', 'gfree1'],
    'interpolate': ['yint', 'lagran'],
    'sgmer': ['sgmer0', 'sgmer1', 'sgmerd'],
    'ctdata': ['hction', 'hctrecom'],
    'cross': ['cross', 'crossd'],
    'expint': ['eint', 'expinx'],
    'erfcx': ['erfcx', 'erfcin'],
    # 新增映射...
}

添加新映射后执行

python3 scripts/analyze_fortran.py > fortran_analysis.csv
python3 scripts/generate_tracking.py > FORTRAN_TRACKING.md

4. 状态更新流程

手动更新状态

如需手动标记状态,编辑 fortran_analysis.csv

# status 列: done, pending, in_progress, skip
filename.f,UNIT,SUBROUTINE,False,"...",...,False,src/math/xxx.rs,done

然后重新生成 Markdown

python3 scripts/generate_tracking.py > FORTRAN_TRACKING.md

5. 代码规范

文件头注释

//! 模块简要说明。
//!
//! 重构自 TLUSTY `filename.f`

函数注释

/// 函数功能说明。
///
/// # 参数
///
/// * `x` - 参数说明
///
/// # 返回值
///
/// 返回值说明
///
/// # 示例
///
/// ```
/// use tlusty_rust::math::func;
/// assert!((func(1.0) - 2.0).abs() < 1e-10);
/// ```
pub fn func(x: f64) -> f64 { ... }

精度要求

函数类型 容差
简单数学运算 1e-10
多项式近似 1e-7
f32 数组 1e-24

常见陷阱

问题 解决方案
Fortran 1-indexed arr(i)arr[i-1]
-LOG(X) -ln(X) 不是 ln(-X)
powi 类型歧义 用显式乘法 (a)*(a)
矩阵列优先 A(j,i)a[(i-1)*N + (j-1)]

6. 快速命令参考

# 查看重构进度
cat FORTRAN_TRACKING.md | head -20

# 进度统计
echo "已完成: $(awk -F, '$9=="done"' fortran_analysis.csv | wc -l)"
echo "待处理: $(awk -F, '$9=="pending"' fortran_analysis.csv | wc -l)"

# 推荐方式:查看优先级列表(按未实现依赖排序)
python3 scripts/analyze_fortran.py --priority | head -30

# 查看函数依赖树(含未实现依赖数)
python3 scripts/analyze_fortran.py --tree FUNCTION_NAME

# 找最佳候选无IO + 无调用依赖
awk -F, '$6=="" && $7=="False" && $9=="pending"' fortran_analysis.csv | head -5

# 找纯函数
grep "True.*pending" fortran_analysis.csv | head -5

# 找无IO的函数
awk -F, '$7=="False" && $9=="pending"' fortran_analysis.csv | head -5

# 测试单个模块
cargo test module_name

# 更新追踪表
python3 scripts/analyze_fortran.py > fortran_analysis.csv && \
python3 scripts/generate_tracking.py > FORTRAN_TRACKING.md

# 编译检查
cargo build 2>&1 | grep error