Skip to content

Commit dd4e1bc

Browse files
committed
Cherry-picking DynamoDS#9578 into 2.0.3
1 parent 9e12eed commit dd4e1bc

File tree

5 files changed

+177
-34
lines changed

5 files changed

+177
-34
lines changed

src/Engine/ProtoCore/Lang/CallSite.cs

Lines changed: 44 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -809,22 +809,44 @@ private FunctionEndPoint GetLooseCompliantFEP(
809809
return compliantTarget;
810810
}
811811

812+
813+
/// <summary>
814+
/// This helper function checks if the current replication option is
815+
/// similar to the previous option but of a higher rank.
816+
/// Checks if the first entry is same in both the options and the current options count is more.
817+
/// </summary>
818+
/// <returns>Returns true or false based on the condition described above.
819+
/// </returns>
820+
private Boolean IsSimilarOptionButOfHigherRank(List<ReplicationInstruction> oldOption, List<ReplicationInstruction> newOption)
821+
{
822+
if (oldOption.Count > 0 && newOption.Count > 0 && oldOption.Count < newOption.Count)
823+
{
824+
if (oldOption[0].Equals(newOption[0]))
825+
return true;
826+
}
827+
return false;
828+
}
829+
812830
private void ComputeFeps(
813831
Context context,
814832
List<StackValue> arguments,
815833
FunctionGroup funcGroup,
816834
List<ReplicationInstruction> instructions,
817835
StackFrame stackFrame,
818836
RuntimeCore runtimeCore,
819-
out List<FunctionEndPoint> resolvesFeps,
837+
out List<FunctionEndPoint> resolvedFeps,
820838
out List<ReplicationInstruction> replicationInstructions)
821839
{
840+
replicationInstructions = null;
841+
resolvedFeps = null;
842+
var matchFound = false;
843+
822844
#region Case 1: Replication guide with exact match
823845
{
824846
FunctionEndPoint fep = GetCompleteMatchFunctionEndPoint(context, arguments, funcGroup, instructions, stackFrame, runtimeCore);
825847
if (fep != null)
826848
{
827-
resolvesFeps = new List<FunctionEndPoint>() { fep };
849+
resolvedFeps = new List<FunctionEndPoint>() { fep };
828850
replicationInstructions = instructions;
829851
return;
830852
}
@@ -842,13 +864,17 @@ private void ComputeFeps(
842864
HashSet<FunctionEndPoint> lookups;
843865
if (funcGroup.CanGetExactMatchStatics(context, reducedParams, stackFrame, runtimeCore, out lookups))
844866
{
845-
//Otherwise we have a cluster of FEPs that can be used to dispatch the array
846-
resolvesFeps = new List<FunctionEndPoint>(lookups);
847-
replicationInstructions = replicationOption;
848-
return;
867+
if (replicationInstructions == null || IsSimilarOptionButOfHigherRank(replicationInstructions, replicationOption))
868+
{
869+
//Otherwise we have a cluster of FEPs that can be used to dispatch the array
870+
resolvedFeps = new List<FunctionEndPoint>(lookups);
871+
replicationInstructions = replicationOption;
872+
matchFound = true;
873+
}
849874
}
850875
}
851-
876+
if (matchFound)
877+
return;
852878
}
853879
#endregion
854880

@@ -857,7 +883,7 @@ private void ComputeFeps(
857883
FunctionEndPoint compliantTarget = GetCompliantFEP(context, arguments, funcGroup, instructions, stackFrame, runtimeCore);
858884
if (compliantTarget != null)
859885
{
860-
resolvesFeps = new List<FunctionEndPoint>() { compliantTarget };
886+
resolvedFeps = new List<FunctionEndPoint>() { compliantTarget };
861887
replicationInstructions = instructions;
862888
return;
863889
}
@@ -873,11 +899,13 @@ private void ComputeFeps(
873899
FunctionEndPoint compliantTarget = GetCompliantFEP(context, arguments, funcGroup, replicationOption, stackFrame, runtimeCore);
874900
if (compliantTarget != null)
875901
{
876-
resolvesFeps = new List<FunctionEndPoint>() { compliantTarget };
902+
resolvedFeps = new List<FunctionEndPoint>() { compliantTarget };
877903
replicationInstructions = replicationOption;
878-
return;
904+
matchFound = true;
879905
}
880906
}
907+
if (matchFound)
908+
return;
881909
}
882910
}
883911

@@ -893,7 +921,7 @@ private void ComputeFeps(
893921
FunctionEndPoint compliantTarget = GetCompliantFEP(context, arguments, funcGroup, replicationOption, stackFrame, runtimeCore, true);
894922
if (compliantTarget != null)
895923
{
896-
resolvesFeps = new List<FunctionEndPoint>() { compliantTarget };
924+
resolvedFeps = new List<FunctionEndPoint>() { compliantTarget };
897925
replicationInstructions = replicationOption;
898926
return;
899927
}
@@ -908,15 +936,17 @@ private void ComputeFeps(
908936
FunctionEndPoint compliantTarget = GetLooseCompliantFEP(context, arguments, funcGroup, replicationOption, stackFrame, runtimeCore);
909937
if (compliantTarget != null)
910938
{
911-
resolvesFeps = new List<FunctionEndPoint>() { compliantTarget };
939+
resolvedFeps = new List<FunctionEndPoint>() { compliantTarget };
912940
replicationInstructions = replicationOption;
913-
return;
941+
matchFound = true;
914942
}
915943
}
944+
if (matchFound)
945+
return;
916946
}
917947
#endregion
918948

919-
resolvesFeps = new List<FunctionEndPoint>();
949+
resolvedFeps = new List<FunctionEndPoint>();
920950
replicationInstructions = instructions;
921951
}
922952

src/Engine/ProtoCore/Lang/Replication/ReplicationInstruction.cs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
using System.Collections.Generic;
2-
using System.Text;
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
34

45
namespace ProtoCore.Lang.Replication
56
{
@@ -44,5 +45,26 @@ public override string ToString()
4445
}
4546

4647
}
48+
49+
public Boolean Equals(ReplicationInstruction oldOption) {
50+
51+
if (this.Zipped == oldOption.Zipped && this.ZipAlgorithm == oldOption.ZipAlgorithm)
52+
{
53+
if (this.ZipIndecies == null && oldOption.ZipIndecies == null)
54+
return true;
55+
56+
if (this.ZipIndecies != null && oldOption.ZipIndecies != null)
57+
{
58+
// Fastest way to compare all elements of 2 lists.
59+
// Excluding one list from another list and checking if the leftover lists is empty or not.
60+
// https://stackoverflow.com/questions/12795882/quickest-way-to-compare-two-list
61+
var currentExcludesOldList = this.ZipIndecies.Except(oldOption.ZipIndecies).ToList();
62+
var oldExcludescurrentList = oldOption.ZipIndecies.Except(this.ZipIndecies).ToList();
63+
64+
return !currentExcludesOldList.Any() && !oldExcludescurrentList.Any();
65+
}
66+
}
67+
return false;
68+
}
4769
}
4870
}

test/Engine/ProtoTest/Associative/BuiltinMethodsTest.cs

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
using System;
22
using NUnit.Framework;
33
using ProtoCore.DSASM.Mirror;
4-
using ProtoTest.TD;
54
using ProtoTestFx.TD;
65
namespace ProtoTest.Associative
76
{
@@ -1069,6 +1068,51 @@ public void TestTryGetValuesFromDictionary08()
10691068
thisTest.Verify("r", null);
10701069
}
10711070

1071+
[Test]
1072+
public void TestTryGetValuesFromDictionary09()
1073+
{
1074+
string code = @"
1075+
a = { ""in"" : 42, ""out"" : 24 };
1076+
b = { ""in"" : 24, ""out"" : 42 };
1077+
c = [[a],[[b]]];
1078+
r1 = Dictionary.ValueAtKey(c, ""in"");
1079+
r2 = Dictionary.ValueAtKey(c, ""out"");
1080+
";
1081+
var mirror = thisTest.RunScriptSource(code);
1082+
thisTest.Verify("r1", new object[] { new object[] { 42 } , new object[] { new object[] { 24 } } });
1083+
thisTest.Verify("r2", new object[] { new object[] { 24 } , new object[] { new object[] { 42 } } });
1084+
}
1085+
1086+
[Test]
1087+
public void TestTryGetValuesFromDictionary10()
1088+
{
1089+
string code = @"
1090+
a = { ""in"" : 42, ""out"" : 24 };
1091+
b = { ""in"" : 24, ""out"" : 42 };
1092+
c = [[[a]],b];
1093+
r1 = Dictionary.ValueAtKey(c, ""in"");
1094+
r2 = Dictionary.ValueAtKey(c, ""out"");
1095+
";
1096+
var mirror = thisTest.RunScriptSource(code);
1097+
thisTest.Verify("r1", new object[] { new object[] { new object[] { 42 } }, 24 });
1098+
thisTest.Verify("r2", new object[] { new object[] { new object[] { 24 } }, 42 });
1099+
}
1100+
1101+
[Test, Category("Failure")]
1102+
public void TestTryGetValuesFromDictionary11()
1103+
{
1104+
string code = @"
1105+
a = [ ""in"" , 42, ""out"" , 24 ];
1106+
b = { ""in"" : 24, ""out"" : 42 };
1107+
c = [a,[b]];
1108+
r1 = Dictionary.ValueAtKey(c, ""in"");
1109+
r2 = Dictionary.ValueAtKey(c, ""out"");
1110+
";
1111+
var mirror = thisTest.RunScriptSource(code);
1112+
thisTest.Verify("r1", new object[] { new object[] { null, null, null, null }, new object[] { 24 } });
1113+
thisTest.Verify("r2", new object[] { new object[] { null, null, null, null }, new object[] { 42 } });
1114+
}
1115+
10721116
[Test]
10731117
public void TestGetKeysFromNonArray()
10741118
{

test/Engine/ProtoTest/Associative/MethodResolution.cs

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -396,21 +396,5 @@ def qux2()
396396
thisTest.Verify("z1", 22);
397397
thisTest.Verify("z2", 22);
398398
}
399-
400-
[Test]
401-
public void TestEmptyNestedListsForMethodResolution()
402-
{
403-
string code = @"import(""FFITarget.dll"");
404-
pt = DummyPoint2D.ByCoordinates(0,0);
405-
l = [[],[pt]];
406-
px1 = DummyPoint2D.X(l);
407-
pt = DummyPoint2D.ByCoordinates(0,0);
408-
l2 = [[pt],[]];
409-
px2 = DummyPoint2D.X(l2);
410-
";
411-
var mirror = thisTest.RunScriptSource(code);
412-
thisTest.Verify("px1", new object[] { new object[] { }, new object[] { 0 } });
413-
thisTest.Verify("px2", new object[] { new object[] { 0 }, new object[] { } });
414-
}
415399
}
416400
}

test/Engine/ProtoTest/TD/Associative/Replication.cs

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4926,7 +4926,70 @@ public void TestReplicationInInlineConditional()
49264926
thisTest.RunScriptSource(code);
49274927
thisTest.Verify("r", new object[] { 2, 5, 7 });
49284928
}
4929-
}
49304929

4930+
// This tests the case 2 block in the computeFeps method(CallSite.cs line:943)
4931+
[Test]
4932+
public void TestReplicationWithEmptyListInNestedLists()
4933+
{
4934+
string code = @"import(""FFITarget.dll"");
4935+
pt = DummyPoint2D.ByCoordinates(0,0);
4936+
l = [[],[pt]];
4937+
px1 = DummyPoint2D.X(l);
4938+
pt = DummyPoint2D.ByCoordinates(0,0);
4939+
l2 = [[pt],[]];
4940+
px2 = DummyPoint2D.X(l2);
4941+
";
4942+
var mirror = thisTest.RunScriptSource(code);
4943+
thisTest.Verify("px1", new object[] { new object[] { }, new object[] { 0 } });
4944+
thisTest.Verify("px2", new object[] { new object[] { 0 }, new object[] { } });
4945+
}
4946+
4947+
// This tests the case 4 block in the computeFeps method(CallSite.cs line:943)
4948+
[Test]
4949+
public void TestReplicationWithNullElementInNestedLists()
4950+
{
4951+
string code = @"import(""FFITarget.dll"");
4952+
pt = DummyPoint2D.ByCoordinates(0,0);
4953+
l = [null,[pt]];
4954+
px1 = DummyPoint2D.X(l);
4955+
pt = DummyPoint2D.ByCoordinates(0,0);
4956+
l2 = [[pt],null];
4957+
px2 = DummyPoint2D.X(l2);
4958+
";
4959+
4960+
var mirror = thisTest.RunScriptSource(code);
4961+
thisTest.Verify("px1", new object[] { null, new object[] { 0 } });
4962+
thisTest.Verify("px2", new object[] { new object[] { 0 }, null });
4963+
}
4964+
4965+
// This tests the case:6 block in the computeFeps method(CallSite.cs line:943)
4966+
// input example for case 6: l4 and l5 lists.
4967+
[Test]
4968+
public void TestReplicationWithArraysOfDifferentRanks()
4969+
{
4970+
string code = @"import(""FFITarget.dll"");
4971+
t1 = [1, [2]];
4972+
t2 = t1 + 5;
4973+
pt = DummyPoint2D.ByCoordinates(0,0);
4974+
l1 = [[[pt]],[pt]];
4975+
px1 = DummyPoint2D.X(l1);
4976+
l2 = [[pt],[[pt]]];
4977+
px2 = DummyPoint2D.X(l2);
4978+
l3 = [[null],[[pt]]];
4979+
px3 = DummyPoint2D.X(l3);
4980+
l4 = [3.3,[pt],[[pt]]];
4981+
px4 = DummyPoint2D.X(l4);
4982+
l5 = [""test"",[[pt]],[pt]];
4983+
px5 = DummyPoint2D.X(l5);
4984+
";
4985+
var mirror = thisTest.RunScriptSource(code);
4986+
thisTest.Verify("t2", new object[] { 6, new object[] { 7 } });
4987+
thisTest.Verify("px1", new object[] { new object[] { new object[] { 0 } }, new object[] { 0 } });
4988+
thisTest.Verify("px2", new object[] { new object[] { 0 }, new object[] { new object[] { 0 } } });
4989+
thisTest.Verify("px3", new object[] { new object[] { null }, new object[] { new object[] { 0 } } });
4990+
thisTest.Verify("px4", new object[] { null, new object[] { 0 }, new object[] { new object[] { 0 } } });
4991+
thisTest.Verify("px5", new object[] { null, new object[] { new object[] { 0 } }, new object[] { 0 } });
4992+
}
4993+
}
49314994
}
49324995

0 commit comments

Comments
 (0)