From f2493d8e4494620d4f5aca4776e823d2db962d53 Mon Sep 17 00:00:00 2001 From: John Doe Date: Sun, 29 Jun 2025 09:35:37 -0700 Subject: [PATCH 01/11] Alist unit testing --- .../Tests/List/alist/AListProcInteractions.dm | 20 +++++++++++++++++++ .../DMProject/Tests/List/alist/AListSetGet.dm | 7 +++++++ .../Tests/List/alist/AListValidKeys.dm | 14 +++++++++++++ .../Tests/List/alist/AListValidValues.dm | 14 +++++++++++++ 4 files changed, 55 insertions(+) create mode 100644 Content.Tests/DMProject/Tests/List/alist/AListProcInteractions.dm create mode 100644 Content.Tests/DMProject/Tests/List/alist/AListSetGet.dm create mode 100644 Content.Tests/DMProject/Tests/List/alist/AListValidKeys.dm create mode 100644 Content.Tests/DMProject/Tests/List/alist/AListValidValues.dm diff --git a/Content.Tests/DMProject/Tests/List/alist/AListProcInteractions.dm b/Content.Tests/DMProject/Tests/List/alist/AListProcInteractions.dm new file mode 100644 index 0000000000..e1eadbd80f --- /dev/null +++ b/Content.Tests/DMProject/Tests/List/alist/AListProcInteractions.dm @@ -0,0 +1,20 @@ +/proc/RunTest() + var/alist/AL = alist("a" = 1, "b" = 2, "c" = -4) + values_cut_over(AL, 0) + ASSERT(AL["a"] == null) + ASSERT(AL["c"] == -4) + ASSERT(length(AL) == 1) + + AL = alist("a" = 1, "b" = 2, "c" = -4) + values_cut_under(AL, 0) + ASSERT(AL["a"] == 1) + ASSERT(AL["c"] == null) + ASSERT(length(AL) == 2) + + AL = alist("a" = 1, "b" = 2, "c" = -4) + var/alist/AL2 = alist("c" = 5, "d" = 6, "e" = 2) + ASSERT(values_dot(AL, AL2) == -20) + + AL = alist("a" = 1, "b" = 2, "c" = -4) + ASSERT(values_product(AL) == -8) + ASSERT(values_sum(AL) == -1) \ No newline at end of file diff --git a/Content.Tests/DMProject/Tests/List/alist/AListSetGet.dm b/Content.Tests/DMProject/Tests/List/alist/AListSetGet.dm new file mode 100644 index 0000000000..4cf093a066 --- /dev/null +++ b/Content.Tests/DMProject/Tests/List/alist/AListSetGet.dm @@ -0,0 +1,7 @@ +/proc/RunTest() + var/alist/A1 = alist("1" = 1) + ASSERT(A1["1"] == 1) + A1["1"] = 1.5 + A1["2"] = 2 + ASSERT(A1["1"] == 1.5) + ASSERT(A1["2"] == 2) \ No newline at end of file diff --git a/Content.Tests/DMProject/Tests/List/alist/AListValidKeys.dm b/Content.Tests/DMProject/Tests/List/alist/AListValidKeys.dm new file mode 100644 index 0000000000..789dc509be --- /dev/null +++ b/Content.Tests/DMProject/Tests/List/alist/AListValidKeys.dm @@ -0,0 +1,14 @@ +/proc/RunTest() + var/alist/AL = alist() + var/datum/D = new() + var/list/L = new() + AL[D] = 1 + AL["A"] = 2 + AL[5] = 3 + AL[L] = 4 + AL[null] = 5 + ASSERT(AL[D] == 1) + ASSERT(AL["A"] == 2) + ASSERT(AL[5] == 3) + ASSERT(AL[L] == 4) + ASSERT(AL[null] == 5) \ No newline at end of file diff --git a/Content.Tests/DMProject/Tests/List/alist/AListValidValues.dm b/Content.Tests/DMProject/Tests/List/alist/AListValidValues.dm new file mode 100644 index 0000000000..845757216a --- /dev/null +++ b/Content.Tests/DMProject/Tests/List/alist/AListValidValues.dm @@ -0,0 +1,14 @@ +/proc/RunTest() + var/alist/AL = alist() + var/datum/D = new() + var/list/L = new() + AL[1] = D + AL[2] = L + AL[3] = 3 + AL[4] = "4" + AL[5] = null + ASSERT(AL[1] == D) + ASSERT(AL[2] == L) + ASSERT(AL[3] == 3) + ASSERT(AL[4] == "4") + ASSERT(AL[5] == null) \ No newline at end of file From 4b35f5cca076956674599d871fb5c2e81ebe35c3 Mon Sep 17 00:00:00 2001 From: John Doe Date: Sun, 29 Jun 2025 12:09:37 -0700 Subject: [PATCH 02/11] WIP --- .../Tests/List/alist/AListProcInteractions.dm | 5 ++- .../Objects/Types/DreamAssocList.cs | 36 ++++++++++++++++++- OpenDreamRuntime/Objects/Types/DreamList.cs | 4 +++ OpenDreamRuntime/Objects/Types/IDreamList.cs | 5 +++ .../Procs/Native/DreamProcNativeRoot.cs | 12 +++---- 5 files changed, 54 insertions(+), 8 deletions(-) diff --git a/Content.Tests/DMProject/Tests/List/alist/AListProcInteractions.dm b/Content.Tests/DMProject/Tests/List/alist/AListProcInteractions.dm index e1eadbd80f..ddcab7e1ca 100644 --- a/Content.Tests/DMProject/Tests/List/alist/AListProcInteractions.dm +++ b/Content.Tests/DMProject/Tests/List/alist/AListProcInteractions.dm @@ -17,4 +17,7 @@ AL = alist("a" = 1, "b" = 2, "c" = -4) ASSERT(values_product(AL) == -8) - ASSERT(values_sum(AL) == -1) \ No newline at end of file + ASSERT(values_sum(AL) == -1) + + AL.Cut() + ASSERT(length(AL) == 0) \ No newline at end of file diff --git a/OpenDreamRuntime/Objects/Types/DreamAssocList.cs b/OpenDreamRuntime/Objects/Types/DreamAssocList.cs index b8d970fbc0..55ee700908 100644 --- a/OpenDreamRuntime/Objects/Types/DreamAssocList.cs +++ b/OpenDreamRuntime/Objects/Types/DreamAssocList.cs @@ -1,3 +1,6 @@ +using System.Linq; +using OpenDreamRuntime.Procs; + namespace OpenDreamRuntime.Objects.Types; // TODO: An arglist given to New() can be used to initialize an alist with values @@ -12,7 +15,8 @@ public void SetValue(DreamValue key, DreamValue value, bool allowGrowth = false) public DreamValue GetValue(DreamValue key) { if (!_values.TryGetValue(key, out var value)) - throw new Exception($"No value with the key {key}"); + return DreamValue.Null; + //throw new Exception($"No value with the key {key}"); return value; } @@ -21,7 +25,37 @@ public bool ContainsKey(DreamValue key) { return _values.ContainsKey(key); } + public override DreamValue OperatorIndex(DreamValue index, DMProcState state) { + return GetValue(index); + } + public IEnumerable EnumerateValues() { return _values.Keys; // The keys, counter-intuitively } + + public int GetLength() { + return _values.Count; + } + + public void Cut(int start = 1, int end = 0) { + if (start != 1) { + throw new Exception($"DoCut() was called with non-default start value of {start}."); + } + if (end != 0) { + throw new Exception($"DoCut() was called with non-default end value of {end}."); + } + _values.Clear(); + } + + public List GetValues() { + return _values.Keys.ToList(); + } + + public Dictionary GetAssociativeValues() { + return _values; + } + + public void RemoveValue(DreamValue value) { + _values.Remove(value); + } } diff --git a/OpenDreamRuntime/Objects/Types/DreamList.cs b/OpenDreamRuntime/Objects/Types/DreamList.cs index 9eff66d1d9..daeec9cb30 100644 --- a/OpenDreamRuntime/Objects/Types/DreamList.cs +++ b/OpenDreamRuntime/Objects/Types/DreamList.cs @@ -224,6 +224,10 @@ public virtual void Cut(int start = 1, int end = 0) { UpdateTracyContentsMemory(); } + public void DoCut(int start = 1, int end = 0) { + Cut(start, end); + } + public void Insert(int index, DreamValue value) { _values.Insert(index - 1, value); UpdateTracyContentsMemory(); diff --git a/OpenDreamRuntime/Objects/Types/IDreamList.cs b/OpenDreamRuntime/Objects/Types/IDreamList.cs index e801409ef9..a5a57f54cb 100644 --- a/OpenDreamRuntime/Objects/Types/IDreamList.cs +++ b/OpenDreamRuntime/Objects/Types/IDreamList.cs @@ -7,4 +7,9 @@ public interface IDreamList { public DreamValue GetValue(DreamValue key); public bool ContainsKey(DreamValue key); public IEnumerable EnumerateValues(); + public int GetLength(); + public void Cut(int start = 1, int end = 0); + public List GetValues(); + public Dictionary GetAssociativeValues(); + public void RemoveValue(DreamValue value); } diff --git a/OpenDreamRuntime/Procs/Native/DreamProcNativeRoot.cs b/OpenDreamRuntime/Procs/Native/DreamProcNativeRoot.cs index 1937ffc712..52537b6675 100644 --- a/OpenDreamRuntime/Procs/Native/DreamProcNativeRoot.cs +++ b/OpenDreamRuntime/Procs/Native/DreamProcNativeRoot.cs @@ -3231,10 +3231,10 @@ public static DreamValue NativeProc_values_cut_over(NativeProc.Bundle bundle, Dr if (bundle.Arguments.Length < 2 || bundle.Arguments.Length > 3) throw new Exception($"expected 2-3 arguments (found {bundle.Arguments.Length})"); DreamValue argList = bundle.GetArgument(0, "Alist"); - DreamValue argMin = bundle.GetArgument(1, "Max"); + DreamValue argMax = bundle.GetArgument(1, "Max"); DreamValue argInclusive = bundle.GetArgument(2, "inclusive"); - return values_cut_helper(argList, argMin, argInclusive, false); + return values_cut_helper(argList, argMax, argInclusive, false); } [DreamProc("values_cut_under")] @@ -3258,7 +3258,7 @@ private static DreamValue values_cut_helper(DreamValue argList, DreamValue argMi var cutCount = 0; // number of values cut from the list var min = argMin.UnsafeGetValueAsFloat(); - if (argList.TryGetValueAsDreamList(out var list)) { + if (argList.TryGetValueAsIDreamList(out var list)) { if (!list.IsAssociative) { cutCount = list.GetLength(); list.Cut(); @@ -3312,7 +3312,7 @@ public static DreamValue NativeProc_values_dot(NativeProc.Bundle bundle, DreamOb float sum = 0; // Default return is 0 for invalid args - if (argA.TryGetValueAsDreamList(out var listA) && listA.IsAssociative && argB.TryGetValueAsDreamList(out var listB) && listB.IsAssociative) { + if (argA.TryGetValueAsIDreamList(out var listA) && listA.IsAssociative && argB.TryGetValueAsIDreamList(out var listB) && listB.IsAssociative) { var aValues = listA.GetAssociativeValues(); var bValues = listB.GetAssociativeValues(); @@ -3339,7 +3339,7 @@ public static DreamValue NativeProc_values_product(NativeProc.Bundle bundle, Dre float product = 1; // Default return is 1 for invalid args - if (arg.TryGetValueAsDreamList(out var list) && list.IsAssociative) { + if (arg.TryGetValueAsIDreamList(out var list) && list.IsAssociative) { var assocValues = list.GetAssociativeValues(); foreach (var (_,value) in assocValues) { if(value.TryGetValueAsFloat(out var valFloat)) product *= valFloat; @@ -3358,7 +3358,7 @@ public static DreamValue NativeProc_values_sum(NativeProc.Bundle bundle, DreamOb float sum = 0; // Default return is 0 for invalid args - if (arg.TryGetValueAsDreamList(out var list) && list.IsAssociative) { + if (arg.TryGetValueAsIDreamList(out var list) && list.IsAssociative) { var assocValues = list.GetAssociativeValues(); foreach (var (_,value) in assocValues) { if(value.TryGetValueAsFloat(out var valFloat)) sum += valFloat; From 125dd14b7a1c0b2033cc1e911462d699d8574918 Mon Sep 17 00:00:00 2001 From: John Doe Date: Sun, 29 Jun 2025 20:59:06 -0700 Subject: [PATCH 03/11] more work --- .../Tests/List/alist/AListProcInteractions.dm | 2 ++ OpenDreamRuntime/Objects/DreamObjectTree.cs | 2 ++ OpenDreamRuntime/Objects/Types/DreamAssocList.cs | 5 ++--- OpenDreamRuntime/Procs/Native/DreamProcNative.cs | 11 +++++++++++ OpenDreamRuntime/Procs/Native/DreamProcNativeList.cs | 2 +- OpenDreamRuntime/Procs/Native/DreamProcNativeRoot.cs | 2 +- 6 files changed, 19 insertions(+), 5 deletions(-) diff --git a/Content.Tests/DMProject/Tests/List/alist/AListProcInteractions.dm b/Content.Tests/DMProject/Tests/List/alist/AListProcInteractions.dm index ddcab7e1ca..f91d9043d3 100644 --- a/Content.Tests/DMProject/Tests/List/alist/AListProcInteractions.dm +++ b/Content.Tests/DMProject/Tests/List/alist/AListProcInteractions.dm @@ -19,5 +19,7 @@ ASSERT(values_product(AL) == -8) ASSERT(values_sum(AL) == -1) + //var/list/L = list() + //L.Cut() AL.Cut() ASSERT(length(AL) == 0) \ No newline at end of file diff --git a/OpenDreamRuntime/Objects/DreamObjectTree.cs b/OpenDreamRuntime/Objects/DreamObjectTree.cs index 0602701e7f..adcd2361ad 100644 --- a/OpenDreamRuntime/Objects/DreamObjectTree.cs +++ b/OpenDreamRuntime/Objects/DreamObjectTree.cs @@ -149,6 +149,8 @@ public DreamObject CreateObject(TreeEntry type) { using (Profiler.BeginZone($"new {type}")) { if (type == List) return CreateList(); + if (type == AssocList) + return CreateAssocList(); if (type == Savefile) return new DreamObjectSavefile(Savefile.ObjectDefinition); if (type.ObjectDefinition.IsSubtypeOf(DatabaseQuery)) diff --git a/OpenDreamRuntime/Objects/Types/DreamAssocList.cs b/OpenDreamRuntime/Objects/Types/DreamAssocList.cs index 55ee700908..b57de060ec 100644 --- a/OpenDreamRuntime/Objects/Types/DreamAssocList.cs +++ b/OpenDreamRuntime/Objects/Types/DreamAssocList.cs @@ -16,7 +16,6 @@ public void SetValue(DreamValue key, DreamValue value, bool allowGrowth = false) public DreamValue GetValue(DreamValue key) { if (!_values.TryGetValue(key, out var value)) return DreamValue.Null; - //throw new Exception($"No value with the key {key}"); return value; } @@ -39,10 +38,10 @@ public int GetLength() { public void Cut(int start = 1, int end = 0) { if (start != 1) { - throw new Exception($"DoCut() was called with non-default start value of {start}."); + throw new Exception($"Cut() was called with non-default start value of {start}."); } if (end != 0) { - throw new Exception($"DoCut() was called with non-default end value of {end}."); + throw new Exception($"Cut() was called with non-default end value of {end}."); } _values.Clear(); } diff --git a/OpenDreamRuntime/Procs/Native/DreamProcNative.cs b/OpenDreamRuntime/Procs/Native/DreamProcNative.cs index a8b2a1131a..24a8337470 100644 --- a/OpenDreamRuntime/Procs/Native/DreamProcNative.cs +++ b/OpenDreamRuntime/Procs/Native/DreamProcNative.cs @@ -138,6 +138,17 @@ public static void SetupNativeProcs(DreamObjectTree objectTree) { objectTree.SetNativeProc(objectTree.List, DreamProcNativeList.NativeProc_Splice); objectTree.SetNativeProc(objectTree.List, DreamProcNativeList.NativeProc_Swap); + //objectTree.SetNativeProc(objectTree.List, DreamProcNativeList.NativeProc_Add); + //objectTree.SetNativeProc(objectTree.List, DreamProcNativeList.NativeProc_Copy); + objectTree.SetNativeProc(objectTree.AssocList, DreamProcNativeList.NativeProc_Cut); + /*objectTree.SetNativeProc(objectTree.List, DreamProcNativeList.NativeProc_Find); + objectTree.SetNativeProc(objectTree.List, DreamProcNativeList.NativeProc_Insert); + objectTree.SetNativeProc(objectTree.List, DreamProcNativeList.NativeProc_Join); + objectTree.SetNativeProc(objectTree.List, DreamProcNativeList.NativeProc_Remove); + objectTree.SetNativeProc(objectTree.List, DreamProcNativeList.NativeProc_RemoveAll); + objectTree.SetNativeProc(objectTree.List, DreamProcNativeList.NativeProc_Splice); + objectTree.SetNativeProc(objectTree.List, DreamProcNativeList.NativeProc_Swap);*/ + objectTree.SetNativeProc(objectTree.Matrix, DreamProcNativeMatrix.NativeProc_Add); objectTree.SetNativeProc(objectTree.Matrix, DreamProcNativeMatrix.NativeProc_Invert); objectTree.SetNativeProc(objectTree.Matrix, DreamProcNativeMatrix.NativeProc_Multiply); diff --git a/OpenDreamRuntime/Procs/Native/DreamProcNativeList.cs b/OpenDreamRuntime/Procs/Native/DreamProcNativeList.cs index 48152e7dd2..319a88fd95 100644 --- a/OpenDreamRuntime/Procs/Native/DreamProcNativeList.cs +++ b/OpenDreamRuntime/Procs/Native/DreamProcNativeList.cs @@ -41,7 +41,7 @@ public static DreamValue NativeProc_Copy(NativeProc.Bundle bundle, DreamObject? public static DreamValue NativeProc_Cut(NativeProc.Bundle bundle, DreamObject? src, DreamObject? usr) { int start = bundle.GetArgument(0, "Start").MustGetValueAsInteger(); //1-indexed int end = bundle.GetArgument(1, "End").MustGetValueAsInteger(); //1-indexed - DreamList list = (DreamList)src!; + IDreamList list = (IDreamList)src!; list.Cut(start, end); return DreamValue.Null; diff --git a/OpenDreamRuntime/Procs/Native/DreamProcNativeRoot.cs b/OpenDreamRuntime/Procs/Native/DreamProcNativeRoot.cs index 52537b6675..ae69e1382d 100644 --- a/OpenDreamRuntime/Procs/Native/DreamProcNativeRoot.cs +++ b/OpenDreamRuntime/Procs/Native/DreamProcNativeRoot.cs @@ -1603,7 +1603,7 @@ public static DreamValue NativeProc_json_encode(NativeProc.Bundle bundle, DreamO public static DreamValue _length(DreamValue value, bool countBytes) { if (value.TryGetValueAsString(out var str)) { return new DreamValue(countBytes ? str.Length : str.EnumerateRunes().Count()); - } else if (value.TryGetValueAsDreamList(out var list)) { + } else if (value.TryGetValueAsIDreamList(out var list)) { return new DreamValue(list.GetLength()); } else if (value.Type is DreamValueType.Float or DreamValueType.DreamObject or DreamValueType.DreamType) { return new DreamValue(0); From 415545a92b8f5137867611d761bc5c345889b37b Mon Sep 17 00:00:00 2001 From: John Doe Date: Tue, 23 Sep 2025 13:33:28 -0600 Subject: [PATCH 04/11] alist stuff done --- .../DMProject/Tests/List/alist/AListAdd.dm | 9 +++ .../DMProject/Tests/List/alist/AListCopy.dm | 8 +++ .../DMProject/Tests/List/alist/AListCut.dm | 5 ++ .../DMProject/Tests/List/alist/AListFind.dm | 5 ++ .../DMProject/Tests/List/alist/AListInsert.dm | 5 ++ .../DMProject/Tests/List/alist/AListJoin.dm | 6 ++ .../Tests/List/alist/AListProcInteractions.dm | 11 +--- .../DMProject/Tests/List/alist/AListRemove.dm | 12 ++++ .../Tests/List/alist/AListRemoveAll.dm | 12 ++++ .../DMProject/Tests/List/alist/AListSplice.dm | 5 ++ .../DMProject/Tests/List/alist/AListSwap.dm | 5 ++ .../Objects/Types/DreamAssocList.cs | 55 +++++++++++++++++++ OpenDreamRuntime/Objects/Types/DreamList.cs | 12 ++-- .../Objects/Types/DreamObjectImage.cs | 4 +- OpenDreamRuntime/Objects/Types/IDreamList.cs | 6 ++ .../Procs/Native/DreamProcNative.cs | 18 +++--- .../Procs/Native/DreamProcNativeList.cs | 33 +++++++---- 17 files changed, 174 insertions(+), 37 deletions(-) create mode 100644 Content.Tests/DMProject/Tests/List/alist/AListAdd.dm create mode 100644 Content.Tests/DMProject/Tests/List/alist/AListCopy.dm create mode 100644 Content.Tests/DMProject/Tests/List/alist/AListCut.dm create mode 100644 Content.Tests/DMProject/Tests/List/alist/AListFind.dm create mode 100644 Content.Tests/DMProject/Tests/List/alist/AListInsert.dm create mode 100644 Content.Tests/DMProject/Tests/List/alist/AListJoin.dm create mode 100644 Content.Tests/DMProject/Tests/List/alist/AListRemove.dm create mode 100644 Content.Tests/DMProject/Tests/List/alist/AListRemoveAll.dm create mode 100644 Content.Tests/DMProject/Tests/List/alist/AListSplice.dm create mode 100644 Content.Tests/DMProject/Tests/List/alist/AListSwap.dm diff --git a/Content.Tests/DMProject/Tests/List/alist/AListAdd.dm b/Content.Tests/DMProject/Tests/List/alist/AListAdd.dm new file mode 100644 index 0000000000..deca59ec9c --- /dev/null +++ b/Content.Tests/DMProject/Tests/List/alist/AListAdd.dm @@ -0,0 +1,9 @@ +/proc/RunTest() + var/alist/AL = alist("a" = 1, "b" = 2, "c" = -4) + AL.Add("c", "d") + ASSERT(AL["c"] == -4) + ASSERT(AL["d"] == null) + + AL.Add(list("c", "d")) + ASSERT(AL["c"] == -4) + ASSERT(AL["d"] == null) \ No newline at end of file diff --git a/Content.Tests/DMProject/Tests/List/alist/AListCopy.dm b/Content.Tests/DMProject/Tests/List/alist/AListCopy.dm new file mode 100644 index 0000000000..1b9fc45721 --- /dev/null +++ b/Content.Tests/DMProject/Tests/List/alist/AListCopy.dm @@ -0,0 +1,8 @@ +/proc/RunTest() + var/alist/AL = alist("a" = 1, "b" = 2, "c" = -4) + var/alist/AL2 + AL2 = AL.Copy(1, 2) + ASSERT(AL["a"] == 1) + ASSERT(AL2["a"] == 1) + ASSERT(AL2["b"] == 2) + ASSERT(!("c" in AL2)) diff --git a/Content.Tests/DMProject/Tests/List/alist/AListCut.dm b/Content.Tests/DMProject/Tests/List/alist/AListCut.dm new file mode 100644 index 0000000000..af511610b9 --- /dev/null +++ b/Content.Tests/DMProject/Tests/List/alist/AListCut.dm @@ -0,0 +1,5 @@ +/proc/RunTest() + var/alist/AL = alist("a" = 1, "b" = 2, "c" = -4) + AL.Cut() + ASSERT(length(AL) == 0) + ASSERT(!("a" in AL)) \ No newline at end of file diff --git a/Content.Tests/DMProject/Tests/List/alist/AListFind.dm b/Content.Tests/DMProject/Tests/List/alist/AListFind.dm new file mode 100644 index 0000000000..c654924bf1 --- /dev/null +++ b/Content.Tests/DMProject/Tests/List/alist/AListFind.dm @@ -0,0 +1,5 @@ +/proc/RunTest() + var/alist/AL = alist("a" = 1, "b" = 2, "c" = -4) + ASSERT(AL.Find("a")) + ASSERT(AL.Find("a", 2, 3)) + ASSERT(!AL.Find("d")) \ No newline at end of file diff --git a/Content.Tests/DMProject/Tests/List/alist/AListInsert.dm b/Content.Tests/DMProject/Tests/List/alist/AListInsert.dm new file mode 100644 index 0000000000..4f2e7a6f02 --- /dev/null +++ b/Content.Tests/DMProject/Tests/List/alist/AListInsert.dm @@ -0,0 +1,5 @@ +// RUNTIME ERROR + +/proc/RunTest() + var/alist/AL = alist("a" = 1, "b" = -2, "c" = 5.05) + AL.Insert(2, "d", "e") \ No newline at end of file diff --git a/Content.Tests/DMProject/Tests/List/alist/AListJoin.dm b/Content.Tests/DMProject/Tests/List/alist/AListJoin.dm new file mode 100644 index 0000000000..cf59ccc173 --- /dev/null +++ b/Content.Tests/DMProject/Tests/List/alist/AListJoin.dm @@ -0,0 +1,6 @@ +/proc/RunTest() + var/alist/AL = alist("a" = 1, "b" = 2, "c" = -4) + var/string_output = AL.Join(",") + ASSERT(string_output == "a,b,c") + string_output = AL.Join("", 2) + ASSERT(string_output == "bc") \ No newline at end of file diff --git a/Content.Tests/DMProject/Tests/List/alist/AListProcInteractions.dm b/Content.Tests/DMProject/Tests/List/alist/AListProcInteractions.dm index f91d9043d3..559ca992de 100644 --- a/Content.Tests/DMProject/Tests/List/alist/AListProcInteractions.dm +++ b/Content.Tests/DMProject/Tests/List/alist/AListProcInteractions.dm @@ -15,11 +15,6 @@ var/alist/AL2 = alist("c" = 5, "d" = 6, "e" = 2) ASSERT(values_dot(AL, AL2) == -20) - AL = alist("a" = 1, "b" = 2, "c" = -4) - ASSERT(values_product(AL) == -8) - ASSERT(values_sum(AL) == -1) - - //var/list/L = list() - //L.Cut() - AL.Cut() - ASSERT(length(AL) == 0) \ No newline at end of file + AL = alist("a" = 1, "b" = 2, "c" = -5) + ASSERT(values_product(AL) == -10) + ASSERT(values_sum(AL) == -2) \ No newline at end of file diff --git a/Content.Tests/DMProject/Tests/List/alist/AListRemove.dm b/Content.Tests/DMProject/Tests/List/alist/AListRemove.dm new file mode 100644 index 0000000000..7e746f9eac --- /dev/null +++ b/Content.Tests/DMProject/Tests/List/alist/AListRemove.dm @@ -0,0 +1,12 @@ +/proc/RunTest() + var/alist/AL = alist("a" = 1, "b" = 2, "c" = -4) + ASSERT(AL.Remove("a", "b")) + ASSERT(!("a" in AL)) + ASSERT(!("b" in AL)) + ASSERT("c" in AL) + + AL = alist("a" = 1, "b" = 2, "c" = -4) + ASSERT(AL.Remove(list("a", "b"))) + ASSERT(!("a" in AL)) + ASSERT(!("b" in AL)) + ASSERT("c" in AL) \ No newline at end of file diff --git a/Content.Tests/DMProject/Tests/List/alist/AListRemoveAll.dm b/Content.Tests/DMProject/Tests/List/alist/AListRemoveAll.dm new file mode 100644 index 0000000000..7e746f9eac --- /dev/null +++ b/Content.Tests/DMProject/Tests/List/alist/AListRemoveAll.dm @@ -0,0 +1,12 @@ +/proc/RunTest() + var/alist/AL = alist("a" = 1, "b" = 2, "c" = -4) + ASSERT(AL.Remove("a", "b")) + ASSERT(!("a" in AL)) + ASSERT(!("b" in AL)) + ASSERT("c" in AL) + + AL = alist("a" = 1, "b" = 2, "c" = -4) + ASSERT(AL.Remove(list("a", "b"))) + ASSERT(!("a" in AL)) + ASSERT(!("b" in AL)) + ASSERT("c" in AL) \ No newline at end of file diff --git a/Content.Tests/DMProject/Tests/List/alist/AListSplice.dm b/Content.Tests/DMProject/Tests/List/alist/AListSplice.dm new file mode 100644 index 0000000000..73902156bb --- /dev/null +++ b/Content.Tests/DMProject/Tests/List/alist/AListSplice.dm @@ -0,0 +1,5 @@ +// RUNTIME ERROR + +/proc/RunTest() + var/alist/AL = alist("a" = 1, "b" = -2, "c" = 5.05) + AL.Splice(1, 1, "d") \ No newline at end of file diff --git a/Content.Tests/DMProject/Tests/List/alist/AListSwap.dm b/Content.Tests/DMProject/Tests/List/alist/AListSwap.dm new file mode 100644 index 0000000000..3268078b44 --- /dev/null +++ b/Content.Tests/DMProject/Tests/List/alist/AListSwap.dm @@ -0,0 +1,5 @@ +// RUNTIME ERROR + +/proc/RunTest() + var/alist/AL = alist("a" = 1, "b" = -2, "c" = 5.05) + AL.Swap(1, 1) \ No newline at end of file diff --git a/OpenDreamRuntime/Objects/Types/DreamAssocList.cs b/OpenDreamRuntime/Objects/Types/DreamAssocList.cs index be1a9c98eb..59db2fe4cb 100644 --- a/OpenDreamRuntime/Objects/Types/DreamAssocList.cs +++ b/OpenDreamRuntime/Objects/Types/DreamAssocList.cs @@ -9,6 +9,12 @@ public sealed class DreamAssocList(DreamObjectDefinition aListDef, int size) : D private readonly Dictionary _values = new(size); + public DreamAssocList(DreamObjectDefinition listDef, Dictionary? values) : this(listDef, values?.Count ?? 0) { + if (values != null) { + _values = values; + } + } + public void SetValue(DreamValue key, DreamValue value, bool allowGrowth = false) { _values[key] = value; } @@ -72,4 +78,53 @@ public DreamValue[] CopyToArray() { public Dictionary CopyAssocValues() { return new(_values); } + + public void AddValue(DreamValue value) { + //if (GetValue(value) != DreamValue.Null) { + if(ContainsValue(value)) { + return; // calling Add("c") on alist("c" = 5) does not change anything + } + _values[value] = DreamValue.Null; + } + + public IDreamList CreateCopy(int start = 1, int end = 0) { + if (start == 0) ++start; //start being 0 and start being 1 are equivalent + + var values = GetValues(); + if (end > values.Count + 1 || start > values.Count + 1) throw new Exception("list index out of bounds"); + if (end == 0) end = values.Count + 1; + if (end <= start) + return new DreamAssocList(ObjectDefinition, 0); + + Dictionary copyValues = new Dictionary(_values); + + return new DreamAssocList(ObjectDefinition, copyValues); + } + + public int FindValue(DreamValue value, int start = 1, int end = 0) { + // Unlike list.Find(), alist.Find() doesn't pay attention to start and end, and returns a boolean 0/1 instead of the position of the found object + if(ContainsValue(value)) { + return 1; + } + return 0; + } + + public void Insert(int index, DreamValue value) { + throw new Exception("insert not allowed for this list"); + } + + public void Swap(int index1, int index2) { + throw new Exception("swap not allowed for this list"); + } + + public bool ContainsValue(DreamValue value) { + var keys = GetValues(); + for (int i = 0; i < keys.Count; i++) { + if (keys[i].Equals(value)) + return true; + } + + return false; + } + } diff --git a/OpenDreamRuntime/Objects/Types/DreamList.cs b/OpenDreamRuntime/Objects/Types/DreamList.cs index 1a1dde99bd..eae630023d 100644 --- a/OpenDreamRuntime/Objects/Types/DreamList.cs +++ b/OpenDreamRuntime/Objects/Types/DreamList.cs @@ -104,14 +104,14 @@ protected override void HandleDeletion(bool possiblyThreaded) { base.HandleDeletion(possiblyThreaded); } - public DreamList CreateCopy(int start = 1, int end = 0) { + public IDreamList CreateCopy(int start = 1, int end = 0) { if (start == 0) ++start; //start being 0 and start being 1 are equivalent var values = GetValues(); if (end > values.Count + 1 || start > values.Count + 1) throw new Exception("list index out of bounds"); if (end == 0) end = values.Count + 1; if (end <= start) - return new(ObjectDefinition, 0); + return new DreamList(ObjectDefinition, 0); List copyValues = values.GetRange(start - 1, end - start); @@ -124,7 +124,7 @@ public DreamList CreateCopy(int start = 1, int end = 0) { } } - return new(ObjectDefinition, copyValues, associativeValues); + return new DreamList(ObjectDefinition, copyValues, associativeValues); } /// @@ -337,7 +337,7 @@ public override void OperatorIndexAssign(DreamValue index, DMProcState state, Dr } public override DreamValue OperatorAdd(DreamValue b, DMProcState state) { - DreamList listCopy = CreateCopy(); + DreamList listCopy = (DreamList)CreateCopy()!; if (b.TryGetValueAsDreamList(out var bList)) { foreach (DreamValue value in bList.EnumerateValues()) { @@ -355,7 +355,7 @@ public override DreamValue OperatorAdd(DreamValue b, DMProcState state) { } public override DreamValue OperatorSubtract(DreamValue b, DMProcState state) { - DreamList listCopy = CreateCopy(); + DreamList listCopy = (DreamList)CreateCopy()!; if (b.TryGetValueAsDreamList(out var bList)) { foreach (DreamValue value in bList.EnumerateValues()) { @@ -374,7 +374,7 @@ public override DreamValue OperatorOr(DreamValue b, DMProcState state) { if (b.TryGetValueAsDreamList(out var bList)) { // List | List list = Union(bList); } else { // List | x - list = CreateCopy(); + list = (DreamList)CreateCopy()!; list.AddValue(b); } diff --git a/OpenDreamRuntime/Objects/Types/DreamObjectImage.cs b/OpenDreamRuntime/Objects/Types/DreamObjectImage.cs index fa88353320..aa08641fdf 100644 --- a/OpenDreamRuntime/Objects/Types/DreamObjectImage.cs +++ b/OpenDreamRuntime/Objects/Types/DreamObjectImage.cs @@ -132,7 +132,7 @@ protected override void SetVar(string varName, DreamValue value) { // Otherwise it attempts to create an appearance and creates a new (normal) list with that appearance if (ObjectDefinition.IsSubtypeOf(ObjectTree.MutableAppearance)) { if (valueList != null) { - _overlays = valueList.CreateCopy(); + _overlays = (DreamList)valueList.CreateCopy(); } else { var overlay = DreamOverlaysList.CreateOverlayAppearance(AtomManager, value, AtomManager.MustGetAppearance(this).Icon); if (overlay == null) @@ -165,7 +165,7 @@ protected override void SetVar(string varName, DreamValue value) { // See the comment in the overlays setter for info on this if (ObjectDefinition.IsSubtypeOf(ObjectTree.MutableAppearance)) { if (valueList != null) { - _underlays = valueList.CreateCopy(); + _underlays = (DreamList)valueList.CreateCopy(); } else { var underlay = DreamOverlaysList.CreateOverlayAppearance(AtomManager, value, AtomManager.MustGetAppearance(this).Icon); if (underlay == null) diff --git a/OpenDreamRuntime/Objects/Types/IDreamList.cs b/OpenDreamRuntime/Objects/Types/IDreamList.cs index 9be86b9ea4..731ff826b4 100644 --- a/OpenDreamRuntime/Objects/Types/IDreamList.cs +++ b/OpenDreamRuntime/Objects/Types/IDreamList.cs @@ -15,6 +15,12 @@ public interface IDreamList { public Dictionary GetAssociativeValues(); public void RemoveValue(DreamValue value); public IEnumerable> EnumerateAssocValues(); + public void AddValue(DreamValue value); + public IDreamList CreateCopy(int start = 1, int end = 0); + public int FindValue(DreamValue value, int start = 1, int end = 0); + public void Insert(int index, DreamValue value); + public bool ContainsValue(DreamValue value); + public void Swap(int index1, int index2); public DreamValue[] CopyToArray() { return EnumerateValues().ToArray(); diff --git a/OpenDreamRuntime/Procs/Native/DreamProcNative.cs b/OpenDreamRuntime/Procs/Native/DreamProcNative.cs index 24a8337470..a536defe55 100644 --- a/OpenDreamRuntime/Procs/Native/DreamProcNative.cs +++ b/OpenDreamRuntime/Procs/Native/DreamProcNative.cs @@ -138,16 +138,16 @@ public static void SetupNativeProcs(DreamObjectTree objectTree) { objectTree.SetNativeProc(objectTree.List, DreamProcNativeList.NativeProc_Splice); objectTree.SetNativeProc(objectTree.List, DreamProcNativeList.NativeProc_Swap); - //objectTree.SetNativeProc(objectTree.List, DreamProcNativeList.NativeProc_Add); - //objectTree.SetNativeProc(objectTree.List, DreamProcNativeList.NativeProc_Copy); + objectTree.SetNativeProc(objectTree.AssocList, DreamProcNativeList.NativeProc_Add); + objectTree.SetNativeProc(objectTree.AssocList, DreamProcNativeList.NativeProc_Copy); objectTree.SetNativeProc(objectTree.AssocList, DreamProcNativeList.NativeProc_Cut); - /*objectTree.SetNativeProc(objectTree.List, DreamProcNativeList.NativeProc_Find); - objectTree.SetNativeProc(objectTree.List, DreamProcNativeList.NativeProc_Insert); - objectTree.SetNativeProc(objectTree.List, DreamProcNativeList.NativeProc_Join); - objectTree.SetNativeProc(objectTree.List, DreamProcNativeList.NativeProc_Remove); - objectTree.SetNativeProc(objectTree.List, DreamProcNativeList.NativeProc_RemoveAll); - objectTree.SetNativeProc(objectTree.List, DreamProcNativeList.NativeProc_Splice); - objectTree.SetNativeProc(objectTree.List, DreamProcNativeList.NativeProc_Swap);*/ + objectTree.SetNativeProc(objectTree.AssocList, DreamProcNativeList.NativeProc_Find); + objectTree.SetNativeProc(objectTree.AssocList, DreamProcNativeList.NativeProc_Insert); + objectTree.SetNativeProc(objectTree.AssocList, DreamProcNativeList.NativeProc_Join); + objectTree.SetNativeProc(objectTree.AssocList, DreamProcNativeList.NativeProc_Remove); + objectTree.SetNativeProc(objectTree.AssocList, DreamProcNativeList.NativeProc_RemoveAll); + objectTree.SetNativeProc(objectTree.AssocList, DreamProcNativeList.NativeProc_Splice); + objectTree.SetNativeProc(objectTree.AssocList, DreamProcNativeList.NativeProc_Swap); objectTree.SetNativeProc(objectTree.Matrix, DreamProcNativeMatrix.NativeProc_Add); objectTree.SetNativeProc(objectTree.Matrix, DreamProcNativeMatrix.NativeProc_Invert); diff --git a/OpenDreamRuntime/Procs/Native/DreamProcNativeList.cs b/OpenDreamRuntime/Procs/Native/DreamProcNativeList.cs index 912b0c0306..35b18a7714 100644 --- a/OpenDreamRuntime/Procs/Native/DreamProcNativeList.cs +++ b/OpenDreamRuntime/Procs/Native/DreamProcNativeList.cs @@ -8,7 +8,7 @@ internal static class DreamProcNativeList { [DreamProc("Add")] [DreamProcParameter("Item1")] public static DreamValue NativeProc_Add(NativeProc.Bundle bundle, DreamObject? src, DreamObject? usr) { - DreamList list = (DreamList)src!; + IDreamList list = (IDreamList)src!; foreach (var argument in bundle.Arguments) { if (argument.TryGetValueAsDreamList(out var argumentList)) { @@ -29,10 +29,16 @@ public static DreamValue NativeProc_Add(NativeProc.Bundle bundle, DreamObject? s public static DreamValue NativeProc_Copy(NativeProc.Bundle bundle, DreamObject? src, DreamObject? usr) { int start = bundle.GetArgument(0, "Start").MustGetValueAsInteger(); //1-indexed int end = bundle.GetArgument(1, "End").MustGetValueAsInteger(); //1-indexed - DreamList list = (DreamList)src!; - DreamList listCopy = list.CreateCopy(start, end); - - return new DreamValue(listCopy); + IDreamList list = (IDreamList)src!; + if (list is DreamList) { + DreamList listCopy = (DreamList)list.CreateCopy(start, end)!; + return new DreamValue(listCopy); + } else if (list is DreamAssocList) { + DreamAssocList listCopy = (DreamAssocList)list.CreateCopy(start, end)!; + return new DreamValue(listCopy); + } else { + throw new Exception("Unhandled IDreamList child in NativeProc_Copy."); + } } [DreamProc("Cut")] @@ -56,7 +62,7 @@ public static DreamValue NativeProc_Find(NativeProc.Bundle bundle, DreamObject? if (!bundle.GetArgument(1, "Start").TryGetValueAsInteger(out var start)) //1-indexed start = 1; // 1 if non-number bundle.GetArgument(2, "End").TryGetValueAsInteger(out var end); //1-indexed, 0 if non-number - DreamList list = (DreamList)src!; + IDreamList list = (IDreamList)src!; return new(list.FindValue(element, start, end)); } @@ -91,7 +97,7 @@ public static DreamValue NativeProc_Insert(NativeProc.Bundle bundle, DreamObject [DreamProcParameter("Start", Type = DreamValueTypeFlag.Float, DefaultValue = 1)] [DreamProcParameter("End", Type = DreamValueTypeFlag.Float, DefaultValue = 0)] public static DreamValue NativeProc_Join(NativeProc.Bundle bundle, DreamObject? src, DreamObject? usr) { - DreamList list = (DreamList)src!; + IDreamList list = (IDreamList)src!; List values = list.GetValues(); bundle.GetArgument(0, "Glue").TryGetValueAsString(out var glue); @@ -122,14 +128,14 @@ public static DreamValue NativeProc_Join(NativeProc.Bundle bundle, DreamObject? [DreamProc("Remove")] [DreamProcParameter("Item1")] public static DreamValue NativeProc_Remove(NativeProc.Bundle bundle, DreamObject? src, DreamObject? usr) { - DreamList list = (DreamList)src!; + IDreamList list = (IDreamList)src!; return new DreamValue(ListRemove(list, bundle.Arguments) > 0 ? 1 : 0); } [DreamProc("RemoveAll")] [DreamProcParameter("Item1")] public static DreamValue NativeProc_RemoveAll(NativeProc.Bundle bundle, DreamObject? src, DreamObject? usr) { - DreamList list = (DreamList)src!; + IDreamList list = (IDreamList)src!; var totalRemoved = 0; int removed; do { @@ -140,7 +146,7 @@ public static DreamValue NativeProc_RemoveAll(NativeProc.Bundle bundle, DreamObj return new DreamValue(totalRemoved); } - private static int ListRemove(DreamList list, ReadOnlySpan args) { + private static int ListRemove(IDreamList list, ReadOnlySpan args) { var itemRemoved = 0; foreach (var argument in args) { if (argument.TryGetValueAsDreamList(out var argumentList)) { @@ -170,7 +176,10 @@ private static int ListRemove(DreamList list, ReadOnlySpan args) { public static DreamValue NativeProc_Splice(NativeProc.Bundle bundle, DreamObject? src, DreamObject? usr) { int startIndex = bundle.GetArgument(0, "Start").MustGetValueAsInteger(); //1-indexed int end = bundle.GetArgument(1, "End").MustGetValueAsInteger(); //1-indexed - DreamList list = (DreamList)src!; + IDreamList list = (IDreamList)src!; + if (list is DreamAssocList) { + throw new Exception("special list may not be spliced"); + } list.Cut(startIndex, end); @@ -197,7 +206,7 @@ public static DreamValue NativeProc_Splice(NativeProc.Bundle bundle, DreamObject [DreamProcParameter("Index1", Type = DreamValueTypeFlag.Float)] [DreamProcParameter("Index2", Type = DreamValueTypeFlag.Float)] public static DreamValue NativeProc_Swap(NativeProc.Bundle bundle, DreamObject? src, DreamObject? usr) { - DreamList list = (DreamList)src!; + IDreamList list = (IDreamList)src!; int index1 = bundle.GetArgument(0, "Index1").MustGetValueAsInteger(); int index2 = bundle.GetArgument(1, "Index2").MustGetValueAsInteger(); From 0dcb77901fe1b97a4a423cfcbd73efa81717601c Mon Sep 17 00:00:00 2001 From: John Doe Date: Wed, 24 Sep 2025 12:49:05 -0600 Subject: [PATCH 05/11] fix tests --- Content.Tests/DMProject/Tests/List/alist/AListBadCopy.dm | 6 ++++++ Content.Tests/DMProject/Tests/List/alist/AListCopy.dm | 4 ++-- OpenDreamRuntime/Procs/DMOpcodeHandlers.cs | 2 +- OpenDreamRuntime/Procs/Native/DreamProcNativeList.cs | 3 +++ 4 files changed, 12 insertions(+), 3 deletions(-) create mode 100644 Content.Tests/DMProject/Tests/List/alist/AListBadCopy.dm diff --git a/Content.Tests/DMProject/Tests/List/alist/AListBadCopy.dm b/Content.Tests/DMProject/Tests/List/alist/AListBadCopy.dm new file mode 100644 index 0000000000..1a36005af6 --- /dev/null +++ b/Content.Tests/DMProject/Tests/List/alist/AListBadCopy.dm @@ -0,0 +1,6 @@ +// RUNTIME ERROR + +/proc/RunTest() + var/alist/AL = alist("a" = 1, "b" = 2, "c" = -4) + var/alist/AL2 + AL2 = AL.Copy(1, 2) diff --git a/Content.Tests/DMProject/Tests/List/alist/AListCopy.dm b/Content.Tests/DMProject/Tests/List/alist/AListCopy.dm index 1b9fc45721..b003301b0a 100644 --- a/Content.Tests/DMProject/Tests/List/alist/AListCopy.dm +++ b/Content.Tests/DMProject/Tests/List/alist/AListCopy.dm @@ -1,8 +1,8 @@ /proc/RunTest() var/alist/AL = alist("a" = 1, "b" = 2, "c" = -4) var/alist/AL2 - AL2 = AL.Copy(1, 2) + AL2 = AL.Copy() ASSERT(AL["a"] == 1) ASSERT(AL2["a"] == 1) ASSERT(AL2["b"] == 2) - ASSERT(!("c" in AL2)) + ASSERT("c" in AL2) diff --git a/OpenDreamRuntime/Procs/DMOpcodeHandlers.cs b/OpenDreamRuntime/Procs/DMOpcodeHandlers.cs index 85e652d479..51f8143b0f 100644 --- a/OpenDreamRuntime/Procs/DMOpcodeHandlers.cs +++ b/OpenDreamRuntime/Procs/DMOpcodeHandlers.cs @@ -679,7 +679,7 @@ public static ProcStatus IsInList(DMProcState state) { DreamValue value = state.Pop(); if (listValue.TryGetValueAsDreamObject(out var listObject) && listObject != null) { - DreamList? list = listObject as DreamList; + IDreamList? list = listObject as IDreamList; if (list == null) { if (listObject is DreamObjectAtom or DreamObjectWorld) { diff --git a/OpenDreamRuntime/Procs/Native/DreamProcNativeList.cs b/OpenDreamRuntime/Procs/Native/DreamProcNativeList.cs index 35b18a7714..79a2e7113e 100644 --- a/OpenDreamRuntime/Procs/Native/DreamProcNativeList.cs +++ b/OpenDreamRuntime/Procs/Native/DreamProcNativeList.cs @@ -34,6 +34,9 @@ public static DreamValue NativeProc_Copy(NativeProc.Bundle bundle, DreamObject? DreamList listCopy = (DreamList)list.CreateCopy(start, end)!; return new DreamValue(listCopy); } else if (list is DreamAssocList) { + if (start != 1 || end != 0) { + throw new Exception("list index out of bounds"); + } DreamAssocList listCopy = (DreamAssocList)list.CreateCopy(start, end)!; return new DreamValue(listCopy); } else { From 10bad05a26c756427eeef7bdee0eb245efa1f43f Mon Sep 17 00:00:00 2001 From: John Doe Date: Wed, 24 Sep 2025 12:53:27 -0600 Subject: [PATCH 06/11] compounded test --- .../DMProject/Tests/List/alist/AListCompoundedLists.dm | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 Content.Tests/DMProject/Tests/List/alist/AListCompoundedLists.dm diff --git a/Content.Tests/DMProject/Tests/List/alist/AListCompoundedLists.dm b/Content.Tests/DMProject/Tests/List/alist/AListCompoundedLists.dm new file mode 100644 index 0000000000..91eca52596 --- /dev/null +++ b/Content.Tests/DMProject/Tests/List/alist/AListCompoundedLists.dm @@ -0,0 +1,7 @@ +/proc/RunTest() + var/alist/AL = alist("left"=alist("one"=1,"two"=2),"right"=1) + ASSERT(istype(AL["left"], /alist)) + ASSERT(AL["left"]["one"] == 1) + ASSERT(AL["left"]["two"] == 2) + ASSERT(AL["right"] == 1) + ASSERT(!("two" in AL)) From 55af62cc97f82a699dfff4bf5b98d2cb7f5a99e6 Mon Sep 17 00:00:00 2001 From: John Doe Date: Wed, 24 Sep 2025 13:28:49 -0600 Subject: [PATCH 07/11] fix some stuff considered "bad" --- OpenDreamRuntime/Objects/Types/DreamList.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/OpenDreamRuntime/Objects/Types/DreamList.cs b/OpenDreamRuntime/Objects/Types/DreamList.cs index eae630023d..67f6aebb1b 100644 --- a/OpenDreamRuntime/Objects/Types/DreamList.cs +++ b/OpenDreamRuntime/Objects/Types/DreamList.cs @@ -337,7 +337,7 @@ public override void OperatorIndexAssign(DreamValue index, DMProcState state, Dr } public override DreamValue OperatorAdd(DreamValue b, DMProcState state) { - DreamList listCopy = (DreamList)CreateCopy()!; + DreamList listCopy = (DreamList)CreateCopy(); if (b.TryGetValueAsDreamList(out var bList)) { foreach (DreamValue value in bList.EnumerateValues()) { @@ -355,7 +355,7 @@ public override DreamValue OperatorAdd(DreamValue b, DMProcState state) { } public override DreamValue OperatorSubtract(DreamValue b, DMProcState state) { - DreamList listCopy = (DreamList)CreateCopy()!; + DreamList listCopy = (DreamList)CreateCopy(); if (b.TryGetValueAsDreamList(out var bList)) { foreach (DreamValue value in bList.EnumerateValues()) { @@ -374,7 +374,7 @@ public override DreamValue OperatorOr(DreamValue b, DMProcState state) { if (b.TryGetValueAsDreamList(out var bList)) { // List | List list = Union(bList); } else { // List | x - list = (DreamList)CreateCopy()!; + list = (DreamList)CreateCopy(); list.AddValue(b); } From 50137cdd868f549f9703f10ee66e8b6e84d7ad81 Mon Sep 17 00:00:00 2001 From: John Doe Date: Wed, 24 Sep 2025 13:28:55 -0600 Subject: [PATCH 08/11] whoops --- OpenDreamRuntime/Procs/Native/DreamProcNativeList.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenDreamRuntime/Procs/Native/DreamProcNativeList.cs b/OpenDreamRuntime/Procs/Native/DreamProcNativeList.cs index 79a2e7113e..2b1df4cc4c 100644 --- a/OpenDreamRuntime/Procs/Native/DreamProcNativeList.cs +++ b/OpenDreamRuntime/Procs/Native/DreamProcNativeList.cs @@ -31,7 +31,7 @@ public static DreamValue NativeProc_Copy(NativeProc.Bundle bundle, DreamObject? int end = bundle.GetArgument(1, "End").MustGetValueAsInteger(); //1-indexed IDreamList list = (IDreamList)src!; if (list is DreamList) { - DreamList listCopy = (DreamList)list.CreateCopy(start, end)!; + DreamList listCopy = (DreamList)list.CreateCopy(start, end); return new DreamValue(listCopy); } else if (list is DreamAssocList) { if (start != 1 || end != 0) { From 7a758fc80e97822ce29b2dc69a62cea378fa1042 Mon Sep 17 00:00:00 2001 From: John Doe Date: Tue, 7 Oct 2025 08:53:29 -0700 Subject: [PATCH 09/11] lint fixes --- .../Objects/Types/DreamAssocList.cs | 12 ++++-- OpenDreamRuntime/Objects/Types/IDreamList.cs | 38 +++++++++---------- .../Procs/Native/DreamProcNativeList.cs | 3 +- 3 files changed, 30 insertions(+), 23 deletions(-) diff --git a/OpenDreamRuntime/Objects/Types/DreamAssocList.cs b/OpenDreamRuntime/Objects/Types/DreamAssocList.cs index 59db2fe4cb..ef8a302204 100644 --- a/OpenDreamRuntime/Objects/Types/DreamAssocList.cs +++ b/OpenDreamRuntime/Objects/Types/DreamAssocList.cs @@ -46,10 +46,13 @@ public void Cut(int start = 1, int end = 0) { if (start != 1) { throw new Exception($"Cut() was called with non-default start value of {start}."); } + if (end != 0) { throw new Exception($"Cut() was called with non-default end value of {end}."); } + _values.Clear(); + } public List GetValues() { @@ -84,6 +87,7 @@ public void AddValue(DreamValue value) { if(ContainsValue(value)) { return; // calling Add("c") on alist("c" = 5) does not change anything } + _values[value] = DreamValue.Null; } @@ -96,7 +100,7 @@ public IDreamList CreateCopy(int start = 1, int end = 0) { if (end <= start) return new DreamAssocList(ObjectDefinition, 0); - Dictionary copyValues = new Dictionary(_values); + Dictionary copyValues = new(_values); return new DreamAssocList(ObjectDefinition, copyValues); } @@ -106,6 +110,7 @@ public int FindValue(DreamValue value, int start = 1, int end = 0) { if(ContainsValue(value)) { return 1; } + return 0; } @@ -119,9 +124,10 @@ public void Swap(int index1, int index2) { public bool ContainsValue(DreamValue value) { var keys = GetValues(); - for (int i = 0; i < keys.Count; i++) { - if (keys[i].Equals(value)) + foreach (var key in keys) { + if (key.Equals(value)) { return true; + } } return false; diff --git a/OpenDreamRuntime/Objects/Types/IDreamList.cs b/OpenDreamRuntime/Objects/Types/IDreamList.cs index 731ff826b4..c8f53b3e8c 100644 --- a/OpenDreamRuntime/Objects/Types/IDreamList.cs +++ b/OpenDreamRuntime/Objects/Types/IDreamList.cs @@ -3,30 +3,30 @@ namespace OpenDreamRuntime.Objects.Types; public interface IDreamList { - public bool IsAssociative { get; } + bool IsAssociative { get; } - public void SetValue(DreamValue key, DreamValue value, bool allowGrowth = false); - public DreamValue GetValue(DreamValue key); - public bool ContainsKey(DreamValue key); - public IEnumerable EnumerateValues(); - public int GetLength(); - public void Cut(int start = 1, int end = 0); - public List GetValues(); - public Dictionary GetAssociativeValues(); - public void RemoveValue(DreamValue value); - public IEnumerable> EnumerateAssocValues(); - public void AddValue(DreamValue value); - public IDreamList CreateCopy(int start = 1, int end = 0); - public int FindValue(DreamValue value, int start = 1, int end = 0); - public void Insert(int index, DreamValue value); - public bool ContainsValue(DreamValue value); - public void Swap(int index1, int index2); + void SetValue(DreamValue key, DreamValue value, bool allowGrowth = false); + DreamValue GetValue(DreamValue key); + bool ContainsKey(DreamValue key); + IEnumerable EnumerateValues(); + int GetLength(); + void Cut(int start = 1, int end = 0); + List GetValues(); + Dictionary GetAssociativeValues(); + void RemoveValue(DreamValue value); + IEnumerable> EnumerateAssocValues(); + void AddValue(DreamValue value); + IDreamList CreateCopy(int start = 1, int end = 0); + int FindValue(DreamValue value, int start = 1, int end = 0); + void Insert(int index, DreamValue value); + bool ContainsValue(DreamValue value); + void Swap(int index1, int index2); - public DreamValue[] CopyToArray() { + DreamValue[] CopyToArray() { return EnumerateValues().ToArray(); } - public Dictionary CopyAssocValues() { + Dictionary CopyAssocValues() { return new(EnumerateAssocValues()); } } diff --git a/OpenDreamRuntime/Procs/Native/DreamProcNativeList.cs b/OpenDreamRuntime/Procs/Native/DreamProcNativeList.cs index 2b1df4cc4c..5e4d9b1ce9 100644 --- a/OpenDreamRuntime/Procs/Native/DreamProcNativeList.cs +++ b/OpenDreamRuntime/Procs/Native/DreamProcNativeList.cs @@ -37,7 +37,8 @@ public static DreamValue NativeProc_Copy(NativeProc.Bundle bundle, DreamObject? if (start != 1 || end != 0) { throw new Exception("list index out of bounds"); } - DreamAssocList listCopy = (DreamAssocList)list.CreateCopy(start, end)!; + + DreamAssocList listCopy = (DreamAssocList)list.CreateCopy(start, end); return new DreamValue(listCopy); } else { throw new Exception("Unhandled IDreamList child in NativeProc_Copy."); From cb2e90b11f1c9534746c476e83e88b4b6ae2e00f Mon Sep 17 00:00:00 2001 From: John Doe Date: Tue, 7 Oct 2025 09:16:57 -0700 Subject: [PATCH 10/11] fix 2 --- OpenDreamRuntime/Objects/Types/DreamAssocList.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/OpenDreamRuntime/Objects/Types/DreamAssocList.cs b/OpenDreamRuntime/Objects/Types/DreamAssocList.cs index ef8a302204..a2816e75a9 100644 --- a/OpenDreamRuntime/Objects/Types/DreamAssocList.cs +++ b/OpenDreamRuntime/Objects/Types/DreamAssocList.cs @@ -52,7 +52,6 @@ public void Cut(int start = 1, int end = 0) { } _values.Clear(); - } public List GetValues() { From a30e1e2eb2161ebc47cd757de38008e3a911b236 Mon Sep 17 00:00:00 2001 From: John Doe Date: Tue, 7 Oct 2025 14:16:18 -0700 Subject: [PATCH 11/11] req. changes --- Content.Tests/DMProject/Tests/List/alist/AListRemove.dm | 6 ------ .../DMProject/Tests/List/alist/AListRemoveAll.dm | 8 +------- OpenDreamRuntime/Objects/Types/DreamAssocList.cs | 2 -- OpenDreamRuntime/Objects/Types/DreamList.cs | 4 ---- 4 files changed, 1 insertion(+), 19 deletions(-) diff --git a/Content.Tests/DMProject/Tests/List/alist/AListRemove.dm b/Content.Tests/DMProject/Tests/List/alist/AListRemove.dm index 7e746f9eac..eeb8b5fe72 100644 --- a/Content.Tests/DMProject/Tests/List/alist/AListRemove.dm +++ b/Content.Tests/DMProject/Tests/List/alist/AListRemove.dm @@ -4,9 +4,3 @@ ASSERT(!("a" in AL)) ASSERT(!("b" in AL)) ASSERT("c" in AL) - - AL = alist("a" = 1, "b" = 2, "c" = -4) - ASSERT(AL.Remove(list("a", "b"))) - ASSERT(!("a" in AL)) - ASSERT(!("b" in AL)) - ASSERT("c" in AL) \ No newline at end of file diff --git a/Content.Tests/DMProject/Tests/List/alist/AListRemoveAll.dm b/Content.Tests/DMProject/Tests/List/alist/AListRemoveAll.dm index 7e746f9eac..3c57093942 100644 --- a/Content.Tests/DMProject/Tests/List/alist/AListRemoveAll.dm +++ b/Content.Tests/DMProject/Tests/List/alist/AListRemoveAll.dm @@ -1,12 +1,6 @@ /proc/RunTest() var/alist/AL = alist("a" = 1, "b" = 2, "c" = -4) - ASSERT(AL.Remove("a", "b")) + ASSERT(AL.RemoveAll("a", "b")) ASSERT(!("a" in AL)) ASSERT(!("b" in AL)) ASSERT("c" in AL) - - AL = alist("a" = 1, "b" = 2, "c" = -4) - ASSERT(AL.Remove(list("a", "b"))) - ASSERT(!("a" in AL)) - ASSERT(!("b" in AL)) - ASSERT("c" in AL) \ No newline at end of file diff --git a/OpenDreamRuntime/Objects/Types/DreamAssocList.cs b/OpenDreamRuntime/Objects/Types/DreamAssocList.cs index a2816e75a9..b15bdc8ffa 100644 --- a/OpenDreamRuntime/Objects/Types/DreamAssocList.cs +++ b/OpenDreamRuntime/Objects/Types/DreamAssocList.cs @@ -3,7 +3,6 @@ namespace OpenDreamRuntime.Objects.Types; -// TODO: An arglist given to New() can be used to initialize an alist with values public sealed class DreamAssocList(DreamObjectDefinition aListDef, int size) : DreamObject(aListDef), IDreamList { public bool IsAssociative => true; @@ -82,7 +81,6 @@ public Dictionary CopyAssocValues() { } public void AddValue(DreamValue value) { - //if (GetValue(value) != DreamValue.Null) { if(ContainsValue(value)) { return; // calling Add("c") on alist("c" = 5) does not change anything } diff --git a/OpenDreamRuntime/Objects/Types/DreamList.cs b/OpenDreamRuntime/Objects/Types/DreamList.cs index 67f6aebb1b..ed8426b190 100644 --- a/OpenDreamRuntime/Objects/Types/DreamList.cs +++ b/OpenDreamRuntime/Objects/Types/DreamList.cs @@ -242,10 +242,6 @@ public virtual void Cut(int start = 1, int end = 0) { UpdateTracyContentsMemory(); } - public void DoCut(int start = 1, int end = 0) { - Cut(start, end); - } - public void Insert(int index, DreamValue value) { _values.Insert(index - 1, value); UpdateTracyContentsMemory();