Skip to content

Commit da48fc4

Browse files
🧩 Refactor(Workflow): 抽取ControlFlowArms共享值对象-KISS优化阶段L5
新增 ControlFlowArms 值对象(Contract 层),集中控制流 arm 的访问逻辑: Arms/TrueBlockName/FalseBlockName/LoopbackTarget/SetArm。消除 CFGStatement 与 FlowControlStatement 两处约 80 行逐字/近字重复,并修复一个隐藏的 null-vs-string.Empty 不一致(TrueBlockName/FalseBlockName 便利访问器在两层 返回不同类型的"空")。 ControlFlowArms 统一空值约定为 string.Empty(经 SetArm 归一化),避免 null 泄漏进 SourceCode 拼接。 # KitX Workflow KISS 深度重构 L5 阶段:抽取共享值对象(子模块部分) # Date: 2026-06-19 # Author: StarInk
1 parent 829afd3 commit da48fc4

1 file changed

Lines changed: 73 additions & 0 deletions

File tree

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
using System.Collections.Generic;
2+
3+
namespace KitX.Core.Contract.Workflow;
4+
5+
/// <summary>
6+
/// Shared control-flow arms model embedded by both <c>CFGStatement</c> (CFG layer) and
7+
/// <c>FlowControlStatement</c> (BlockScript layer). Eliminates the ~80 lines of
8+
/// character-identical <c>Arms</c>/<c>TrueBlockName</c>/<c>FalseBlockName</c>/
9+
/// <c>LoopbackTarget</c>/<c>SetArm</c> duplication that had drifted between the two layers
10+
/// (including a hidden null-vs-string.Empty inconsistency in the convenience accessors).
11+
///
12+
/// <para>Both layers expose this via their own delegating properties (<c>Arms</c>,
13+
/// <c>TrueBlockName</c>, <c>FalseBlockName</c>, <c>LoopbackTarget</c>) so existing call
14+
/// sites (<c>stmt.Arms</c>, <c>flow.TrueBlockName</c>, ...) are unchanged.</para>
15+
///
16+
/// <list type="bullet">
17+
/// <item>Branch: [<c>"True"</c>, <c>"False"</c>]</item>
18+
/// <item>Loop: [<c>"LoopBody"</c>, <c>"LoopEnd"</c>]</item>
19+
/// <item>ToLoopCond: [<c>"Exec"</c> with <see cref="BranchArm.IsLoopback"/>=true]</item>
20+
/// <item>Switch: [<c>"Default"</c>, <c>"0"</c>, <c>"1"</c>, ... , <c>"N-1"</c>]</item>
21+
/// </list>
22+
/// </summary>
23+
public class ControlFlowArms
24+
{
25+
/// <summary>
26+
/// Outgoing arms of this control-flow statement. Generalised model replacing the former
27+
/// fixed <c>TrueBlockName</c>/<c>FalseBlockName</c>/<c>ToLoopCondReturnTo</c> triple.
28+
/// See <see cref="BranchArm"/> for the per-arm layout of each control-flow kind.
29+
/// </summary>
30+
public List<BranchArm> Arms { get; set; } = [];
31+
32+
/// <summary>Convenience accessor: the true-branch / loop-body target (Arms[0]).</summary>
33+
public string? TrueBlockName
34+
{
35+
get => Arms.Count > 0 ? Arms[0].TargetBlockName : null;
36+
set => SetArm(0, "True", value);
37+
}
38+
39+
/// <summary>Convenience accessor: the false-branch / loop-exit target (Arms[1]).</summary>
40+
public string? FalseBlockName
41+
{
42+
get => Arms.Count > 1 ? Arms[1].TargetBlockName : null;
43+
set => SetArm(1, "False", value);
44+
}
45+
46+
/// <summary>
47+
/// The ToLoopCond loopback target — the loop condition block this statement returns to.
48+
/// Unified into <see cref="Arms"/>[0] (PinName="Exec", IsLoopback=true) so ToLoopCond is
49+
/// treated uniformly with Branch/Loop/Switch: all control-flow targets live in Arms.
50+
/// The former standalone <c>ToLoopCondReturnTo</c> field was a patch over an Arms[0]
51+
/// collision that no longer exists; Loop statements no longer carry this metadata at all
52+
/// (it was dead — never read for control flow, only copied and debug-printed).
53+
/// </summary>
54+
public string? LoopbackTarget
55+
{
56+
get => Arms.Count > 0 ? Arms[0].TargetBlockName : null;
57+
set => SetArm(0, "Exec", value, isLoopback: true);
58+
}
59+
60+
/// <summary>
61+
/// Sets the arm at <paramref name="index"/>, growing <see cref="Arms"/> with blank arms
62+
/// as needed. Normalises a null <paramref name="value"/> to <c>string.Empty</c> so the
63+
/// convenience accessors never surface null into SourceCode concatenation.
64+
/// </summary>
65+
public void SetArm(int index, string pinName, string? value, bool isLoopback = false)
66+
{
67+
while (Arms.Count <= index)
68+
Arms.Add(new BranchArm());
69+
Arms[index].PinName = pinName;
70+
Arms[index].TargetBlockName = value ?? string.Empty;
71+
Arms[index].IsLoopback = isLoopback;
72+
}
73+
}

0 commit comments

Comments
 (0)