@@ -275,15 +275,15 @@ public static void Main(string[] args)
275275 if ( ShouldRunTest ( "X" ) )
276276 {
277277 Console . WriteLine ( "\n ┌──────────────────────────────────────────────────────────┐" ) ;
278- Console . WriteLine ( "│ Test X: Pipeline (\\ - ) parse + flatten + compile + exec │" ) ;
278+ Console . WriteLine ( "│ Test X: Pipeline (> ) parse + flatten + compile + exec │" ) ;
279279 Console . WriteLine ( "└──────────────────────────────────────────────────────────┘\n " ) ;
280280 RunPipelineExecutionTest ( parser , converter ) ;
281281 }
282282
283283 if ( ShouldRunTest ( "Y" ) )
284284 {
285285 Console . WriteLine ( "\n ┌──────────────────────────────────────────────────────────┐" ) ;
286- Console . WriteLine ( "│ Test Y: Pipeline (\\ - ) round-trip fidelity │" ) ;
286+ Console . WriteLine ( "│ Test Y: Pipeline (> ) round-trip fidelity │" ) ;
287287 Console . WriteLine ( "└──────────────────────────────────────────────────────────┘\n " ) ;
288288 RunPipelineRoundTripTest ( parser , converter , reverseConverter ) ;
289289 }
@@ -301,10 +301,12 @@ private static void RunDiagnosticsTest(
301301 {
302302 bool allPassed = true ;
303303
304- // U1: a valid script produces NO diagnostics.
304+ // U1: a valid, nesting-free script produces NO diagnostics.
305+ // (GetSequentialScript is used because the deprecated nested form now emits
306+ // BS_DEPRECATED_NESTING warnings, which is correct behaviour, not a clean script.)
305307 try
306308 {
307- converter . Convert ( GetRawNestedScript ( ) , helpers ) ;
309+ converter . Convert ( GetSequentialScript ( ) , helpers ) ;
308310 var diag = converter . LastDiagnostics ;
309311 bool clean = diag == null || ( ! diag . HasErrors && ! diag . HasWarnings ) ;
310312 Console . WriteLine ( $ " [U1] Clean script diagnostics: { ( clean ? "none (expected)" : diag ! . Format ( ) ) } ") ;
@@ -734,7 +736,10 @@ private static string GetPreExpandedScript() => @"#ConstBlock
734736Print(""示例工作流结束"");" ;
735737
736738 // ──────────────────────────────────────────────
737- // Test B: Raw nested format (BS2CFGConverter must expand)
739+ // Test B: Raw nested format — exercises the BS2CFGConverter nested-call expander. Nested
740+ // calls are deprecated (BS_DEPRECATED_NESTING warning) but still supported; this test guards
741+ // the expander until nesting is fully removed in a future commit (pending a CFG2CS variable-
742+ // ordering fix that the pre-expanded form needs to compile cleanly through round-trip).
738743 // ──────────────────────────────────────────────
739744 private static string GetRawNestedScript ( ) => @"#ConstBlock
740745int guessNum = 5;
@@ -1072,54 +1077,72 @@ private static string GetNoConstScript() => @"#MainBlock
10721077Print(""Done"");" ;
10731078
10741079 // ──────────────────────────────────────────────
1075- // Test H: Break inside Loop
1080+ // Test H: Break inside Loop (pre-expanded PubVar form, no nested calls)
10761081 // ──────────────────────────────────────────────
10771082 private static string GetBreakScript ( ) => @"#ConstBlock
10781083int maxIter = 10;
10791084int target = 3;
10801085
1086+ #PubVarBlock
1087+ bool vaaa0001;
1088+ int vaaa0002;
1089+
10811090#MainBlock
10821091Set(""i"", 0);
1083- NextBlock = Loop(HelperFuncCompare(""BLE"", Get(""i""), maxIter), ""LoopBody"", ""AfterLoop"");
1092+ vaaa0002 = Get(""i"");
1093+ vaaa0001 = HelperFuncCompare(""BLE"", vaaa0002, maxIter);
1094+ NextBlock = Loop(vaaa0001, ""LoopBody"", ""AfterLoop"");
10841095
10851096#Block LoopBody
1086- NextBlock = Branch(
1087- HelperFuncCompare(""BEQ"", Get(""i""), target),
1088- ""BreakBlock"",
1089- ""ContinueBlock""
1090- );
1097+ vaaa0002 = Get(""i"");
1098+ vaaa0001 = HelperFuncCompare(""BEQ"", vaaa0002, target);
1099+ NextBlock = Branch(vaaa0001, ""BreakBlock"", ""ContinueBlock"");
10911100
10921101#Block BreakBlock
10931102Break();
10941103
10951104#Block ContinueBlock
1096- Set(""i"", HelperFuncAdd(Get(""i""), 1));
1105+ vaaa0002 = Get(""i"");
1106+ vaaa0002 = HelperFuncAdd(vaaa0002, 1);
1107+ Set(""i"", vaaa0002);
10971108NextBlock = ToLoopCond(""MainBlock"");
10981109
10991110#Block AfterLoop
11001111Print(""Loop finished with break"");" ;
11011112
11021113 // ──────────────────────────────────────────────
1103- // Test I: Nested Loop
1114+ // Test I: Nested Loop (pre-expanded PubVar form, no nested calls)
11041115 // ──────────────────────────────────────────────
11051116 private static string GetNestedLoopScript ( ) => @"#ConstBlock
11061117int outerMax = 2;
11071118int innerMax = 3;
11081119
1120+ #PubVarBlock
1121+ bool vaaa0001;
1122+ int vaaa0002;
1123+
11091124#MainBlock
11101125Set(""outer"", 0);
1111- NextBlock = Loop(HelperFuncCompare(""BLT"", Get(""outer""), outerMax), ""OuterBody"", ""Done"");
1126+ vaaa0002 = Get(""outer"");
1127+ vaaa0001 = HelperFuncCompare(""BLT"", vaaa0002, outerMax);
1128+ NextBlock = Loop(vaaa0001, ""OuterBody"", ""Done"");
11121129
11131130#Block OuterBody
11141131Set(""inner"", 0);
1115- NextBlock = Loop(HelperFuncCompare(""BLT"", Get(""inner""), innerMax), ""InnerBody"", ""OuterEnd"");
1132+ vaaa0002 = Get(""inner"");
1133+ vaaa0001 = HelperFuncCompare(""BLT"", vaaa0002, innerMax);
1134+ NextBlock = Loop(vaaa0001, ""InnerBody"", ""OuterEnd"");
11161135
11171136#Block InnerBody
1118- Set(""inner"", HelperFuncAdd(Get(""inner""), 1));
1137+ vaaa0002 = Get(""inner"");
1138+ vaaa0002 = HelperFuncAdd(vaaa0002, 1);
1139+ Set(""inner"", vaaa0002);
11191140NextBlock = ToLoopCond(""OuterBody"");
11201141
11211142#Block OuterEnd
1122- Set(""outer"", HelperFuncAdd(Get(""outer""), 1));
1143+ vaaa0002 = Get(""outer"");
1144+ vaaa0002 = HelperFuncAdd(vaaa0002, 1);
1145+ Set(""outer"", vaaa0002);
11231146NextBlock = ToLoopCond(""MainBlock"");
11241147
11251148#Block Done
@@ -2009,33 +2032,31 @@ private static void RunQualifiedPluginCallTest(IBlockScriptParser parser)
20092032 }
20102033 }
20112034
2012- // Test T: Nested PluginCall inside Set — does the BS→CFG expander flatten it
2013- // into a temp PubVar + standalone PluginCall, the way it does for Helper functions
2014- // (Test B/C exercise HelperFuncAdd(Get(...), 1))? If yes, the generated C# should
2015- // compile cleanly. If no, the nested PluginCall is emitted verbatim and fails with
2016- // CS0103 'PluginCall does not exist' — a real converter gap worth fixing.
2035+ // Test T: PluginCall assigned to a PubVar — does the BS→CFG converter lower a value-producing
2036+ // PluginCall (builtin or dotted) into a temp PubVar + the call, so the generated C# compiles
2037+ // cleanly? The expanded form is the nesting-free successor to the former nested Set.
20172038 private static void RunNestedPluginCallTest ( IBlockScriptParser parser )
20182039 {
2019- Console . WriteLine ( "[Test T] Nested PluginCall as Set argument — expander coverage check" ) ;
2040+ Console . WriteLine ( "[Test T] PluginCall assigned to PubVar — expander coverage check" ) ;
20202041
2021- // Form 1: builtin PluginCall(plugin, method, args) nested in Set .
2042+ // Form 1: builtin PluginCall(plugin, method, args) assigned to a PubVar .
20222043 var sourceBuiltin = @"
20232044#PubVarBlock
20242045dynamic result;
20252046
20262047#MainBlock
2027- Set("" result"", PluginCall(""TestPlugin"", ""Echo"", ""hello"") );
2028- Print(Get("" result"") );
2048+ result = PluginCall(""TestPlugin"", ""Echo"", ""hello"");
2049+ Print(result);
20292050" ;
20302051
2031- // Form 2: dotted Plugin.Method(args) nested in Set .
2052+ // Form 2: dotted Plugin.Method(args) assigned to a PubVar .
20322053 var sourceDotted = @"
20332054#PubVarBlock
20342055dynamic result;
20352056
20362057#MainBlock
2037- Set("" result"", TestPlugin.Echo(""hello"") );
2038- Print(Get("" result"") );
2058+ result = TestPlugin.Echo(""hello"");
2059+ Print(result);
20392060" ;
20402061
20412062 int fails = 0 ;
@@ -2202,14 +2223,14 @@ private static void RunStringConcatRoundTripTest(
22022223 }
22032224
22042225 // ──────────────────────────────────────────────
2205- // Test X: Pipeline (\- ) parse + flatten + compile + execute.
2226+ // Test X: Pipeline (> ) parse + flatten + compile + execute.
22062227 // Exercises linear chains, diamond (multi-source) dependency, and the _ placeholder.
22072228 // ──────────────────────────────────────────────
22082229 private static void RunPipelineExecutionTest (
22092230 IBlockScriptParser parser ,
22102231 BlockScriptToBlueprintConverter converter )
22112232 {
2212- Console . WriteLine ( "[Test X] Pipeline (\\ - ): parse, flatten, compile, execute" ) ;
2233+ Console . WriteLine ( "[Test X] Pipeline (> ): parse, flatten, compile, execute" ) ;
22132234 int fails = 0 ;
22142235
22152236 // X1: linear chain — Get → StringConcat → Print. Verifies single-source pipeline compiles
@@ -2222,7 +2243,7 @@ private static void RunPipelineExecutionTest(
22222243dynamic greeting;
22232244
22242245#MainBlock
2225- Get(""name"") \- StringConcat(""Hello, "", _) \- Print;
2246+ Get(""name"") > StringConcat(""Hello, "", _) > Print;
22262247" ;
22272248
22282249 // X2: diamond dependency — two sources (Get + literal) feed StringConcat positionally.
@@ -2232,7 +2253,7 @@ private static void RunPipelineExecutionTest(
22322253string b = ""World"";
22332254
22342255#MainBlock
2235- Get(""a""), Get(""b"") \- StringConcat \- Print;
2256+ Get(""a""), Get(""b"") > StringConcat > Print;
22362257" ;
22372258
22382259 foreach ( var ( label , src , expectedInOutput ) in new [ ]
@@ -2291,27 +2312,27 @@ private static void RunPipelineExecutionTest(
22912312 }
22922313
22932314 // ──────────────────────────────────────────────
2294- // Test Y: Pipeline (\- ) round-trip.
2315+ // Test Y: Pipeline (> ) round-trip.
22952316 // BS → BP → BS. The pipeline flattens across the blueprint boundary (BlueprintNode does not
22962317 // carry CFG PipelineId provenance), so the round-tripped BS is the equivalent flat PubVar
22972318 // form — which must still parse and compile, and execute to the same output. Preserving the
2298- // literal \- syntax through the blueprint is a future enhancement (storing pipeline grouping
2319+ // literal > syntax through the blueprint is a future enhancement (storing pipeline grouping
22992320 // on blueprint nodes); for now the contract is semantic equivalence + re-compilability.
23002321 // ──────────────────────────────────────────────
23012322 private static void RunPipelineRoundTripTest (
23022323 IBlockScriptParser parser ,
23032324 BlockScriptToBlueprintConverter converter ,
23042325 IBlueprintToBlockScriptConverter reverseConverter )
23052326 {
2306- Console . WriteLine ( "[Test Y] Pipeline (\\ - ): BS↔BP round-trip (semantic equivalence)" ) ;
2327+ Console . WriteLine ( "[Test Y] Pipeline (> ): BS↔BP round-trip (semantic equivalence)" ) ;
23072328 int fails = 0 ;
23082329
23092330 var src = @"
23102331#ConstBlock
23112332string name = ""World"";
23122333
23132334#MainBlock
2314- Get(""name"") \- StringConcat(""Hi "", _) \- Print;
2335+ Get(""name"") > StringConcat(""Hi "", _) > Print;
23152336" ;
23162337
23172338 try
0 commit comments