diff --git a/src/Engine/ProtoAssociative/CodeGen_SSA.cs b/src/Engine/ProtoAssociative/CodeGen_SSA.cs index 745092a71ad..2958837dfc1 100644 --- a/src/Engine/ProtoAssociative/CodeGen_SSA.cs +++ b/src/Engine/ProtoAssociative/CodeGen_SSA.cs @@ -1,4 +1,4 @@ -using ProtoCore.AST.AssociativeAST; +using ProtoCore.AST.AssociativeAST; using ProtoCore.DSASM; using ProtoCore.Utils; using System.Collections.Generic; @@ -275,7 +275,11 @@ private List BuildSSA(List astList, ProtoCore. BinaryExpressionNode bnode = (node as BinaryExpressionNode); int generatedUID = ProtoCore.DSASM.Constants.kInvalidIndex; - if (context.applySSATransform && core.Options.GenerateSSA) + // Skip SSA for input ASTs that are first assigned null such as this: + // a = null; (update "a") => a = ; + // SSA would break up the null AST into two assignments, which then breaks update: + // a = null; (SSA) => temp = null; a = temp; + if (context.applySSATransform && core.Options.GenerateSSA && !bnode.IsInputExpression) { int ssaID = ProtoCore.DSASM.Constants.kInvalidIndex; string name = ProtoCore.Utils.CoreUtils.GenerateIdentListNameString(bnode.LeftNode); @@ -382,53 +386,6 @@ private List BuildSSA(List astList, ProtoCore. return astList; } - private void DfsSSAIeentList(AssociativeNode node, ref Stack ssaStack, ref List astlist) - { - if (node is IdentifierListNode) - { - IdentifierListNode listNode = node as IdentifierListNode; - - bool isSingleDot = !(listNode.LeftNode is IdentifierListNode) && !(listNode.RightNode is IdentifierListNode); - if (isSingleDot) - { - BinaryExpressionNode bnode = BuildSSAIdentListAssignmentNode(listNode); - astlist.Add(bnode); - ssaStack.Push(bnode); - } - else - { - DfsSSAIeentList(listNode.LeftNode, ref ssaStack, ref astlist); - - IdentifierListNode newListNode = node as IdentifierListNode; - newListNode.Optr = Operator.dot; - - AssociativeNode leftnode = ssaStack.Pop(); - Validity.Assert(leftnode is BinaryExpressionNode); - - newListNode.LeftNode = (leftnode as BinaryExpressionNode).LeftNode; - newListNode.RightNode = listNode.RightNode; - - BinaryExpressionNode bnode = BuildSSAIdentListAssignmentNode(newListNode); - astlist.Add(bnode); - ssaStack.Push(bnode); - - } - } - else if (node is FunctionCallNode) - { - FunctionCallNode fcNode = node as FunctionCallNode; - for (int idx = 0; idx < fcNode.FormalArguments.Count; idx++) - { - AssociativeNode arg = fcNode.FormalArguments[idx]; - - Stack ssaStack1 = new Stack(); - DFSEmitSSA_AST(arg, ssaStack1, ref astlist); - AssociativeNode argNode = ssaStack.Pop(); - fcNode.FormalArguments[idx] = argNode is BinaryExpressionNode ? (argNode as BinaryExpressionNode).LeftNode : argNode; - } - } - } - private void DFSEmitSSA_AST(AssociativeNode node, Stack ssaStack, ref List astlist) { Validity.Assert(null != astlist && null != ssaStack); @@ -488,7 +445,8 @@ private void DFSEmitSSA_AST(AssociativeNode node, Stack ssaStac var bnode = AstFactory.BuildAssignment(leftNode, rightNode); bnode.isSSAAssignment = isSSAAssignment; - bnode.IsInputExpression = astBNode.IsInputExpression; + // TODO: SSA is not called for ASTs that are input expressions. Revisit this if there are any issues. + // bnode.IsInputExpression = astBNode.IsInputExpression; astlist.Add(bnode); ssaStack.Push(bnode); diff --git a/src/Engine/ProtoCore/DSASM/InstructionSet.cs b/src/Engine/ProtoCore/DSASM/InstructionSet.cs index 07d285218c4..31068a45323 100644 --- a/src/Engine/ProtoCore/DSASM/InstructionSet.cs +++ b/src/Engine/ProtoCore/DSASM/InstructionSet.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using ProtoCore.Exceptions; @@ -10,6 +10,7 @@ namespace ProtoCore.DSASM public enum Registers { RX, + // Register used to temporarily store primitive values for graph update cycles. LX, } diff --git a/src/Libraries/CoreNodeModels/Enum.cs b/src/Libraries/CoreNodeModels/Enum.cs index a6c1639c352..a2c9860da3c 100644 --- a/src/Libraries/CoreNodeModels/Enum.cs +++ b/src/Libraries/CoreNodeModels/Enum.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; diff --git a/test/DynamoCoreWpfTests/NodeExecutionUITest.cs b/test/DynamoCoreWpfTests/NodeExecutionUITest.cs index 73bb94e40ca..8662c69d72e 100644 --- a/test/DynamoCoreWpfTests/NodeExecutionUITest.cs +++ b/test/DynamoCoreWpfTests/NodeExecutionUITest.cs @@ -328,5 +328,58 @@ public void TestSelectionNodeUpdate2() AssertPreviewValue(tsn.GUID.ToString(), 0); } + + [Test] + public void TestDropdownNodeUpdate() + { + var model = GetModel(); + var tdd = new TestDropdown + { + SelectedIndex = 0 + }; + + var command = new DynamoModel.CreateNodeCommand(tdd, 0, 0, true, false); + model.ExecuteCommand(command); + + AssertPreviewValue(tdd.GUID.ToString(), "one"); + + tdd.SelectedIndex = 1; + tdd.OnNodeModified(); + + AssertPreviewValue(tdd.GUID.ToString(), "two"); + + tdd.SelectedIndex = 2; + tdd.OnNodeModified(); + + AssertPreviewValue(tdd.GUID.ToString(), "three"); + + } + + [Test] + public void TestDropdownNodeUpdate1() + { + var model = GetModel(); + var tdd = new TestDropdown(); + + var command = new DynamoModel.CreateNodeCommand(tdd, 0, 0, true, false); + model.ExecuteCommand(command); + + AssertPreviewValue(tdd.GUID.ToString(), null); + + tdd.SelectedIndex = 0; + tdd.OnNodeModified(); + + AssertPreviewValue(tdd.GUID.ToString(), "one"); + + tdd.SelectedIndex = 1; + tdd.OnNodeModified(); + + AssertPreviewValue(tdd.GUID.ToString(), "two"); + + tdd.SelectedIndex = 2; + tdd.OnNodeModified(); + + AssertPreviewValue(tdd.GUID.ToString(), "three"); + } } } diff --git a/test/TestUINodes/TestUINodes.cs b/test/TestUINodes/TestUINodes.cs index cd3e3581545..004c2ff971a 100644 --- a/test/TestUINodes/TestUINodes.cs +++ b/test/TestUINodes/TestUINodes.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections; using System.Collections.Generic; using System.IO; @@ -140,4 +140,54 @@ protected override int GetModelObjectFromIdentifer(string id) return id.Length; } } + + [NodeName("Test Dropdown Node")] + [NodeCategory("TestUINodes")] + [NodeDescription("test dropdown node")] + [OutPortTypes("string")] + [IsDesignScriptCompatible] + [IsVisibleInDynamoLibrary(false)] + public class TestDropdown : DSDropDownBase + { + public TestDropdown() : base("TestDropdown") { } + + + public override IEnumerable BuildOutputAst(List inputAstNodes) + { + AssociativeNode node; + if (SelectedIndex < 0 || SelectedIndex >= Items.Count) + { + node = AstFactory.BuildNullNode(); + return new[] { AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), node) }; + } + else + { + // get the selected items name + var stringNode = AstFactory.BuildStringNode((string)Items[SelectedIndex].Name); + + // assign the selected name to an actual enumeration value + var assign = AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), stringNode); + + // return the enumeration value + return new List { assign }; + } + } + + protected override SelectionState PopulateItemsCore(string currentSelection) + { + Items.Clear(); + + var symbols = new[] { "one", "two", "three" }; + + + foreach (var symbol in symbols) + { + + Items.Add(new DynamoDropDownItem(symbol, symbol)); + } + + return SelectionState.Restore; + } + + } }