diff --git a/Library/BlocklyNet.csproj b/Library/BlocklyNet.csproj index 1f57561..d89d815 100644 --- a/Library/BlocklyNet.csproj +++ b/Library/BlocklyNet.csproj @@ -1,4 +1,4 @@ - + net8.0 @@ -12,7 +12,7 @@ - + diff --git a/Library/Core/Model/Workspace.cs b/Library/Core/Model/Workspace.cs index 64dc8fe..60fd0fc 100644 --- a/Library/Core/Model/Workspace.cs +++ b/Library/Core/Model/Workspace.cs @@ -1,4 +1,6 @@ using BlocklyNet.Core.Blocks.Text; +using BlocklyNet.Extensions; +using BlocklyNet.Scripting.Engine; namespace BlocklyNet.Core.Model; @@ -47,5 +49,45 @@ public class Workspace : IFragment return returnValue; } + + private void InspectBlockChain(Block? block) + { + for (; block != null; block = block.Next) + { + System.Diagnostics.Debug.WriteLine(block.Type); + + if (block is ExecutionGroup group) + { + System.Diagnostics.Debug.WriteLine(group.Fields["NAME"]); + + InspectBlockChain(group.Values.Get("RESULT")?.Block); + } + + foreach (var statement in block.Statements) + InspectBlockChain(statement.Block); + } + } + + /// + /// Get the hierarchy of groups based on a static analysis of + /// the script. + /// + /// The group information tree. + public async Task GetGroupTreeAsync() + { + /* Use a dummy site. */ + var context = new Context((IScriptSite)null!); + + /* Find all functions and generate the block list. */ + foreach (var block in Blocks.OfType()) + await block.EvaluateAsync(context); + + /* Inspect all blocks. */ + foreach (var block in Blocks) + if (block is not ProceduresDef) + InspectBlockChain(block); + + return 0; + } } diff --git a/Library/Core/Parser.cs b/Library/Core/Parser.cs index bc55a2b..8e2f553 100644 --- a/Library/Core/Parser.cs +++ b/Library/Core/Parser.cs @@ -27,8 +27,10 @@ private class ParsedScript(Workspace workspace) : IParsedScript { private readonly Workspace _workspace = workspace; + /// public Task RunAsync(IScriptSite engine) => _workspace.EvaluateAsync(new Context(engine)); + /// public async Task EvaluateAsync(Dictionary presets, IScriptSite site) { var ctx = new Context(site); @@ -54,6 +56,9 @@ private class ParsedScript(Workspace workspace) : IParsedScript /* No result at all. */ return null; } + + /// + public Task GetGroupTreeAsync() => _workspace.GetGroupTreeAsync(); } public IParsedScript Parse(string scriptAsText) diff --git a/Library/Extensions/ExecutionGroup.cs b/Library/Extensions/ExecutionGroup.cs index 5a79a82..8503989 100644 --- a/Library/Extensions/ExecutionGroup.cs +++ b/Library/Extensions/ExecutionGroup.cs @@ -16,15 +16,14 @@ namespace BlocklyNet.Extensions; { ""type"": ""input_dummy"" }, - { - ""type"": ""field_label_serializable"", + { + ""type"": ""field_input"", ""name"": ""NAME"", - ""text"": ""Name of the group"" + ""text"": ""Name of the Group"" }, { - ""type"": ""input_value"", - ""name"": ""NAME"", - ""check"": ""String"" + ""type"": ""input_dummy"", + ""name"": ""NAME"" }, { ""type"": ""field_label_serializable"", @@ -43,18 +42,7 @@ namespace BlocklyNet.Extensions; ""tooltip"": ""Execute something as a group."", ""helpUrl"": """" }", - @"{ - ""inputs"": { - ""NAME"": { - ""shadow"": { - ""type"": ""text"", - ""fields"": { - ""TEXT"": """" - } - } - } - } - }" + "" )] public class ExecutionGroup : Block { @@ -62,7 +50,7 @@ public class ExecutionGroup : Block public override async Task EvaluateAsync(Context context) { /* Register the group. */ - var name = await Values.EvaluateAsync("NAME", context, false); + var name = Fields["NAME"]; if (context.Engine.BeginGroup(Id, name)) { diff --git a/Library/Scripting/Parsing/IParsedScript.cs b/Library/Scripting/Parsing/IParsedScript.cs index f9ffa44..0c363ec 100644 --- a/Library/Scripting/Parsing/IParsedScript.cs +++ b/Library/Scripting/Parsing/IParsedScript.cs @@ -1,3 +1,4 @@ +using BlocklyNet.Core.Model; using BlocklyNet.Scripting.Engine; namespace BlocklyNet.Scripting.Parsing; @@ -21,4 +22,9 @@ public interface IParsedScript /// /// Task RunAsync(IScriptSite engine); + + /// + /// + /// + Task GetGroupTreeAsync(); } diff --git a/Tests/CoreEx/GroupExecutionTests.cs b/Tests/CoreEx/GroupExecutionTests.cs index bcec05a..741f79d 100644 --- a/Tests/CoreEx/GroupExecutionTests.cs +++ b/Tests/CoreEx/GroupExecutionTests.cs @@ -15,10 +15,12 @@ public async Task Can_Run_Simple_Groups_Async() var block = new ExecutionGroup { Id = "A", + Fields = { new() { Name = "NAME", Value = "A1" } }, Values = { new() { Name = "RESULT", Block = new AnyValueBlock(new GroupResult { Result = "1", Type = GroupResultType.Succeeded }) } }, Next = new ExecutionGroup { Id = "B", + Fields = { new() { Name = "NAME", Value = "B2" } }, Values = { new() { Name = "RESULT", Block = new AnyValueBlock(new GroupResult { Result = "2", Type = GroupResultType.Failed }) } } } }; @@ -27,8 +29,8 @@ public async Task Can_Run_Simple_Groups_Async() await block.EvaluateAsync(new Context(Site.Object)); - Site.Verify(s => s.BeginGroup("A", null), Times.Once); - Site.Verify(s => s.BeginGroup("B", null), Times.Once); + Site.Verify(s => s.BeginGroup("A", "A1"), Times.Once); + Site.Verify(s => s.BeginGroup("B", "B2"), Times.Once); Site.Verify(s => s.EndGroup(It.IsAny()), Times.Exactly(2)); Site.Verify(s => s.SingleStepAsync(It.IsAny()), Times.Exactly(2)); Site.VerifyGet(s => s.Cancellation, Times.Exactly(6)); diff --git a/Tests/Engine/GroupAnalyserTests.cs b/Tests/Engine/GroupAnalyserTests.cs new file mode 100644 index 0000000..d76e902 --- /dev/null +++ b/Tests/Engine/GroupAnalyserTests.cs @@ -0,0 +1,193 @@ +using BlocklyNet.Core.Model; +using NUnit.Framework; + +namespace BlocklyNetTests.Engine; + +[TestFixture] +public class GroupAnalyserTests : TestEnvironment +{ + private const string Script1 = @" + + + Start it all + Result + + + Type + Result + + + Succeeded + + + + + 1 + + + + + + + Functions + Result + + + + + + + + End it all + Result + + + Type + Result + + + Succeeded + + + + + 3 + + + + + + + + + + + func2 + Describe this function... + + + Inner Func + Result + + + Type + Result + + + Succeeded + + + + + 2.2.1 + + + + + + + + + Type + Result + + + Succeeded + + + + + 2.2 + + + + + + + func1 + Describe this function... + + + Outer Func Start + Result + + + Type + Result + + + Succeeded + + + + + 2.1 + + + + + + + Call Inner + Result + + + + + + + + Outer Func End + Result + + + Type + Result + + + Succeeded + + + + + 2.3 + + + + + + + + + + + + + Type + Result + + + Succeeded + + + + + 2 + + + + + + + "; + + [Test] + public async Task Can_Retrieve_Group_Structure_With_Functions_Async() + { + var script = Engine.Parser.Parse(Script1); + + var tree = await script.GetGroupTreeAsync(); + + Assert.That(tree, Is.EqualTo(0)); + } +} \ No newline at end of file diff --git a/Tests/Engine/GroupingTests.cs b/Tests/Engine/GroupingTests.cs index 4f3db8e..5dfbc2b 100644 --- a/Tests/Engine/GroupingTests.cs +++ b/Tests/Engine/GroupingTests.cs @@ -14,6 +14,7 @@ public class GroupingTests : TestEnvironment private const string Script1 = @" + Outer @@ -30,6 +31,7 @@ public class GroupingTests : TestEnvironment + Inner @@ -73,11 +75,6 @@ public class GroupingTests : TestEnvironment Name of the group Result - - - One - - Type @@ -98,11 +95,6 @@ public class GroupingTests : TestEnvironment Name of the group Result - - - Two - - Type @@ -123,11 +115,6 @@ public class GroupingTests : TestEnvironment Name of the group Result - - - Three - - Type @@ -215,7 +202,7 @@ public async Task Can_Retrieve_Hash_Of_Script_Async() await done.Task; /* Validate hash. */ - Assert.That(hash.Single(), Is.EqualTo("E4-B0-3E-B6-CF-2E-10-C5-33-C5-C4-E7-DF-CA-2A-8D-84-3D-E7-AE-BC-5D-98-E5-A3-9E-FC-F4-C1-97-3B-B5")); + Assert.That(hash.Single(), Is.EqualTo("EB-EC-09-A4-23-68-07-03-59-59-08-25-83-D3-3A-1A-7B-E0-5F-8E-2B-2E-B7-FA-8A-84-FB-BA-19-28-D7-06")); /* Validate status. */ Assert.That(status, Is.Not.Null);