From e5ed05ef63321120ecc668d0be5f7d0f431a1a19 Mon Sep 17 00:00:00 2001 From: amy Date: Fri, 1 Sep 2023 18:34:26 +0100 Subject: [PATCH 01/13] fun --- Content.Tests/DMProject/Tests/Const/Const7.dm | 8 ++++++++ .../Special Procs/issaved/issaved_vars_index.dm | 11 +++++------ .../{Broken Tests => Tests}/Stdlib/issaved.dm | 1 - DMCompiler/DM/DMObject.cs | 10 ++++++++++ DMCompiler/DM/DMObjectTree.cs | 2 +- DMCompiler/DM/DMVariable.cs | 6 ++++-- DMCompiler/DM/Visitors/DMObjectBuilder.cs | 6 +++++- OpenDreamRuntime/Objects/DreamObject.cs | 5 ++++- OpenDreamRuntime/Objects/DreamObjectDefinition.cs | 6 ++++++ OpenDreamRuntime/Objects/DreamObjectTree.cs | 12 ++++++++++++ OpenDreamShared/Json/DreamObjectJson.cs | 2 ++ 11 files changed, 57 insertions(+), 12 deletions(-) create mode 100644 Content.Tests/DMProject/Tests/Const/Const7.dm rename Content.Tests/DMProject/{Broken Tests => Tests}/Stdlib/issaved.dm (70%) diff --git a/Content.Tests/DMProject/Tests/Const/Const7.dm b/Content.Tests/DMProject/Tests/Const/Const7.dm new file mode 100644 index 0000000000..669cdfc6b2 --- /dev/null +++ b/Content.Tests/DMProject/Tests/Const/Const7.dm @@ -0,0 +1,8 @@ +// RUNTIME ERROR +/obj/test + var/const/A = 1 + +/proc/RunTest() + var/obj/test/T = new() + T.vars["A"] = 2 //ideally should runtime + ASSERT(T.A == 2) //ideally should fail diff --git a/Content.Tests/DMProject/Tests/Special Procs/issaved/issaved_vars_index.dm b/Content.Tests/DMProject/Tests/Special Procs/issaved/issaved_vars_index.dm index 293fcc7d2b..d0a7e41b0f 100644 --- a/Content.Tests/DMProject/Tests/Special Procs/issaved/issaved_vars_index.dm +++ b/Content.Tests/DMProject/Tests/Special Procs/issaved/issaved_vars_index.dm @@ -1,23 +1,22 @@ -// !issaved(B) commented out because of TODO in DMOpcodeHandlers.IsSaved /obj/o var/A - //var/tmp/B + var/tmp/B /obj/o/proc/IsSavedSrcVars() ASSERT(issaved(A)) - //ASSERT(!issaved(B)) + ASSERT(!issaved(B)) ASSERT(issaved(vars["A"])) - //ASSERT(!issaved(vars["B"])) + ASSERT(!issaved(vars["B"])) /proc/RunTest() var/obj/o/test = new ASSERT(issaved(test.A)) - //ASSERT(!issaved(test.B)) + ASSERT(!issaved(test.B)) // Note that this doesn't work on most lists and will instead return false ASSERT(issaved(test.vars["A"])) - //ASSERT(!issaved(test.vars["B"])) + ASSERT(!issaved(test.vars["B"])) /* var/expected = prob(50) diff --git a/Content.Tests/DMProject/Broken Tests/Stdlib/issaved.dm b/Content.Tests/DMProject/Tests/Stdlib/issaved.dm similarity index 70% rename from Content.Tests/DMProject/Broken Tests/Stdlib/issaved.dm rename to Content.Tests/DMProject/Tests/Stdlib/issaved.dm index 073b9306dc..569727c8b6 100644 --- a/Content.Tests/DMProject/Broken Tests/Stdlib/issaved.dm +++ b/Content.Tests/DMProject/Tests/Stdlib/issaved.dm @@ -14,4 +14,3 @@ /proc/RunTest() var/obj/o = new o.log_vars() - ASSERT(FALSE) // To ensure this test fails until it's been revisited (in case we add CI to check broken tests) diff --git a/DMCompiler/DM/DMObject.cs b/DMCompiler/DM/DMObject.cs index 1c488a92b4..de02e80c06 100644 --- a/DMCompiler/DM/DMObject.cs +++ b/DMCompiler/DM/DMObject.cs @@ -21,6 +21,8 @@ internal sealed class DMObject { public Dictionary VariableOverrides = new(); public Dictionary GlobalVariables = new(); /// A list of var and verb initializations implicitly done before the user's New() is called. + public HashSet ConstVariables = new(); + public HashSet TmpVariables = new(); public List InitializationProcExpressions = new(); public int? InitializationProc; @@ -169,6 +171,14 @@ public DreamTypeJson CreateJsonRepresentation() { typeJson.GlobalVariables = GlobalVariables; } + if (ConstVariables.Count > 0) { + typeJson.ConstVariables = ConstVariables; + } + + if (TmpVariables.Count > 0) { + typeJson.TmpVariables = TmpVariables; + } + if (InitializationProc != null) { typeJson.InitProc = InitializationProc; } diff --git a/DMCompiler/DM/DMObjectTree.cs b/DMCompiler/DM/DMObjectTree.cs index 4c86ed53b4..ec2355b1ac 100644 --- a/DMCompiler/DM/DMObjectTree.cs +++ b/DMCompiler/DM/DMObjectTree.cs @@ -173,7 +173,7 @@ public static bool TryGetTypeId(DreamPath path, out int typeId) { public static int CreateGlobal(out DMVariable global, DreamPath? type, string name, bool isConst, DMValueType valType = DMValueType.Anything) { int id = Globals.Count; - global = new DMVariable(type, name, true, isConst, valType); + global = new DMVariable(type, name, true, isConst, false, valType); Globals.Add(global); return id; } diff --git a/DMCompiler/DM/DMVariable.cs b/DMCompiler/DM/DMVariable.cs index 86f63e91c9..6f2efaea20 100644 --- a/DMCompiler/DM/DMVariable.cs +++ b/DMCompiler/DM/DMVariable.cs @@ -10,14 +10,16 @@ sealed class DMVariable { /// NOTE: This DMVariable may be forced constant through opendream_compiletimereadonly. This only marks that the variable has the DM quality of /const/ness. /// public bool IsConst; + public bool IsTmp; public DMExpression Value; public DMValueType ValType; - public DMVariable(DreamPath? type, string name, bool isGlobal, bool isConst, DMValueType valType = DMValueType.Anything) { + public DMVariable(DreamPath? type, string name, bool isGlobal, bool isConst, bool isTmp, DMValueType valType = DMValueType.Anything) { Type = type; Name = name; IsGlobal = isGlobal; IsConst = isConst; + IsTmp = isTmp; Value = null; ValType = valType; } @@ -33,7 +35,7 @@ public DMVariable WriteToValue(Expressions.Constant value) { return this; } - DMVariable clone = new DMVariable(Type, Name, IsGlobal, IsConst, ValType); + DMVariable clone = new DMVariable(Type, Name, IsGlobal, IsConst, IsTmp, ValType); clone.Value = value; return clone; } diff --git a/DMCompiler/DM/Visitors/DMObjectBuilder.cs b/DMCompiler/DM/Visitors/DMObjectBuilder.cs index e5706e83b1..3a5c4545c8 100644 --- a/DMCompiler/DM/Visitors/DMObjectBuilder.cs +++ b/DMCompiler/DM/Visitors/DMObjectBuilder.cs @@ -227,8 +227,12 @@ private static void ProcessVarDefinition(DMObject? varObject, DMASTObjectVarDefi if (varDefinition.IsStatic) { variable = varObject.CreateGlobalVariable(varDefinition.Type, varDefinition.Name, varDefinition.IsConst, varDefinition.ValType); } else { - variable = new DMVariable(varDefinition.Type, varDefinition.Name, false, varDefinition.IsConst,varDefinition.ValType); + variable = new DMVariable(varDefinition.Type, varDefinition.Name, false, varDefinition.IsConst, varDefinition.IsTmp, varDefinition.ValType); varObject.Variables[variable.Name] = variable; + if(varDefinition.IsConst) + varObject.ConstVariables.Add(varDefinition.Name); + if(varDefinition.IsTmp) + varObject.TmpVariables.Add(varDefinition.Name); } } diff --git a/OpenDreamRuntime/Objects/DreamObject.cs b/OpenDreamRuntime/Objects/DreamObject.cs index 305ec32b0e..008e11bcaf 100644 --- a/OpenDreamRuntime/Objects/DreamObject.cs +++ b/OpenDreamRuntime/Objects/DreamObject.cs @@ -122,7 +122,8 @@ public virtual DreamValue Initial(string name) { public virtual bool IsSaved(string name) { //TODO: Add support for var/const/ and var/tmp/ once those are properly in - return ObjectDefinition.Variables.ContainsKey(name) && !ObjectDefinition.GlobalVariables.ContainsKey(name); + return ObjectDefinition.Variables.ContainsKey(name) && !ObjectDefinition.GlobalVariables.ContainsKey(name) + && !ObjectDefinition.ConstVariables.Contains(name) && !ObjectDefinition.TmpVariables.Contains(name); } public bool HasVariable(string name) { @@ -171,6 +172,8 @@ protected virtual bool TryGetVar(string varName, out DreamValue value) { } protected virtual void SetVar(string varName, DreamValue value) { + if(ObjectDefinition.ConstVariables.Contains(varName)) + throw new Exception($"Cannot set const var \"{varName}\""); switch (varName) { case "type": case "parent_type": diff --git a/OpenDreamRuntime/Objects/DreamObjectDefinition.cs b/OpenDreamRuntime/Objects/DreamObjectDefinition.cs index 6aad54c8c6..3965e745a5 100644 --- a/OpenDreamRuntime/Objects/DreamObjectDefinition.cs +++ b/OpenDreamRuntime/Objects/DreamObjectDefinition.cs @@ -48,6 +48,10 @@ public bool NoConstructors { public readonly Dictionary Variables = new(); // Maps /static variables from name to their index in the global variable table. public readonly Dictionary GlobalVariables = new(); + // Contains hashes of variables that are tagged /const. + public readonly HashSet ConstVariables = new(); + // Contains hashes of variables that are tagged /tmp. + public readonly HashSet TmpVariables = new(); public DreamObjectDefinition(DreamObjectDefinition copyFrom) { DreamManager = copyFrom.DreamManager; @@ -68,6 +72,8 @@ public DreamObjectDefinition(DreamObjectDefinition copyFrom) { Variables = new Dictionary(copyFrom.Variables); GlobalVariables = new Dictionary(copyFrom.GlobalVariables); + ConstVariables = new HashSet(copyFrom.ConstVariables); + TmpVariables = new HashSet(copyFrom.TmpVariables); Procs = new Dictionary(copyFrom.Procs); OverridingProcs = new Dictionary(copyFrom.OverridingProcs); if (copyFrom.Verbs != null) diff --git a/OpenDreamRuntime/Objects/DreamObjectTree.cs b/OpenDreamRuntime/Objects/DreamObjectTree.cs index dc00e5caa4..4749e4f1b2 100644 --- a/OpenDreamRuntime/Objects/DreamObjectTree.cs +++ b/OpenDreamRuntime/Objects/DreamObjectTree.cs @@ -364,6 +364,18 @@ private void LoadVariablesFromJson(DreamObjectDefinition objectDefinition, Dream objectDefinition.GlobalVariables.Add(jsonGlobalVariable.Key, jsonGlobalVariable.Value); } } + + if (jsonObject.ConstVariables != null) { + foreach (string jsonConstVariable in jsonObject.ConstVariables) { + objectDefinition.ConstVariables.Add(jsonConstVariable); + } + } + + if(jsonObject.TmpVariables != null) { + foreach (string jsonTmpVariable in jsonObject.TmpVariables) { + objectDefinition.TmpVariables.Add(jsonTmpVariable); + } + } } public DreamProc LoadProcJson(int id, DreamTypeJson[] types, ProcDefinitionJson procDefinition) { diff --git a/OpenDreamShared/Json/DreamObjectJson.cs b/OpenDreamShared/Json/DreamObjectJson.cs index b34dfb057a..16dde55417 100644 --- a/OpenDreamShared/Json/DreamObjectJson.cs +++ b/OpenDreamShared/Json/DreamObjectJson.cs @@ -20,6 +20,8 @@ public sealed class DreamTypeJson { public List Verbs { get; set; } public Dictionary Variables { get; set; } public Dictionary GlobalVariables { get; set; } + public HashSet ConstVariables { get; set; } + public HashSet TmpVariables { get; set; } } public sealed class GlobalListJson { From d45a5566a156304f37cc9147eaec3338498778fe Mon Sep 17 00:00:00 2001 From: amy Date: Fri, 1 Sep 2023 18:39:40 +0100 Subject: [PATCH 02/13] oops, missed those --- OpenDreamRuntime/Objects/DreamObject.cs | 1 - OpenDreamRuntime/Procs/DMOpcodeHandlers.cs | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/OpenDreamRuntime/Objects/DreamObject.cs b/OpenDreamRuntime/Objects/DreamObject.cs index 008e11bcaf..c4b3d08d9f 100644 --- a/OpenDreamRuntime/Objects/DreamObject.cs +++ b/OpenDreamRuntime/Objects/DreamObject.cs @@ -121,7 +121,6 @@ public virtual DreamValue Initial(string name) { } public virtual bool IsSaved(string name) { - //TODO: Add support for var/const/ and var/tmp/ once those are properly in return ObjectDefinition.Variables.ContainsKey(name) && !ObjectDefinition.GlobalVariables.ContainsKey(name) && !ObjectDefinition.ConstVariables.Contains(name) && !ObjectDefinition.TmpVariables.Contains(name); } diff --git a/OpenDreamRuntime/Procs/DMOpcodeHandlers.cs b/OpenDreamRuntime/Procs/DMOpcodeHandlers.cs index f9b8cab3ca..9732128dd2 100644 --- a/OpenDreamRuntime/Procs/DMOpcodeHandlers.cs +++ b/OpenDreamRuntime/Procs/DMOpcodeHandlers.cs @@ -2008,8 +2008,7 @@ public static ProcStatus IsSaved(DMProcState state) { throw new Exception($"Invalid owner for issaved() call {owner}"); } - //TODO: Add support for var/const/ and var/tmp/ once those are properly in - if (objectDefinition.GlobalVariables.ContainsKey(property)) { + if (objectDefinition.GlobalVariables.ContainsKey(property) || objectDefinition.ConstVariables.Contains(property) || objectDefinition.TmpVariables.Contains(property)) { state.Push(new DreamValue(0)); } else { state.Push(new DreamValue(1)); From c5b5d6571426548d91f7343a0424517319620407 Mon Sep 17 00:00:00 2001 From: amy Date: Fri, 1 Sep 2023 18:52:53 +0100 Subject: [PATCH 03/13] redundant test --- Content.Tests/DMProject/Tests/Const/Const7.dm | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 Content.Tests/DMProject/Tests/Const/Const7.dm diff --git a/Content.Tests/DMProject/Tests/Const/Const7.dm b/Content.Tests/DMProject/Tests/Const/Const7.dm deleted file mode 100644 index 669cdfc6b2..0000000000 --- a/Content.Tests/DMProject/Tests/Const/Const7.dm +++ /dev/null @@ -1,8 +0,0 @@ -// RUNTIME ERROR -/obj/test - var/const/A = 1 - -/proc/RunTest() - var/obj/test/T = new() - T.vars["A"] = 2 //ideally should runtime - ASSERT(T.A == 2) //ideally should fail From 2164069b66d6f47cb6cd44e2c1c84e40ffd7bc06 Mon Sep 17 00:00:00 2001 From: amy Date: Fri, 1 Sep 2023 19:04:57 +0100 Subject: [PATCH 04/13] remove useless test --- Content.Tests/DMProject/Tests/Stdlib/issaved.dm | 16 ---------------- 1 file changed, 16 deletions(-) delete mode 100644 Content.Tests/DMProject/Tests/Stdlib/issaved.dm diff --git a/Content.Tests/DMProject/Tests/Stdlib/issaved.dm b/Content.Tests/DMProject/Tests/Stdlib/issaved.dm deleted file mode 100644 index 569727c8b6..0000000000 --- a/Content.Tests/DMProject/Tests/Stdlib/issaved.dm +++ /dev/null @@ -1,16 +0,0 @@ - -// TODO: This test needs further cleanup/validation but I cba and we need more issaved() tests - -//# issue 684 - -/obj - var/V - var/const/C - - proc/log_vars() - for(var/vname in vars) - world.log << (issaved(vars[vname])) - -/proc/RunTest() - var/obj/o = new - o.log_vars() From ad0122e4e6fd2799ea732d9fd0b08c0ece012977 Mon Sep 17 00:00:00 2001 From: Amy <3855802+amylizzle@users.noreply.github.com> Date: Fri, 1 Sep 2023 19:26:25 +0100 Subject: [PATCH 05/13] Update OpenDreamShared/Json/DreamObjectJson.cs Co-authored-by: wixoa --- OpenDreamShared/Json/DreamObjectJson.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenDreamShared/Json/DreamObjectJson.cs b/OpenDreamShared/Json/DreamObjectJson.cs index 16dde55417..bc5421823f 100644 --- a/OpenDreamShared/Json/DreamObjectJson.cs +++ b/OpenDreamShared/Json/DreamObjectJson.cs @@ -20,8 +20,8 @@ public sealed class DreamTypeJson { public List Verbs { get; set; } public Dictionary Variables { get; set; } public Dictionary GlobalVariables { get; set; } - public HashSet ConstVariables { get; set; } - public HashSet TmpVariables { get; set; } + public HashSet? ConstVariables { get; set; } + public HashSet? TmpVariables { get; set; } } public sealed class GlobalListJson { From eadbb5ec4e08b48cc28b83df4b81b469c86a97da Mon Sep 17 00:00:00 2001 From: amy Date: Fri, 1 Sep 2023 19:29:02 +0100 Subject: [PATCH 06/13] move to default --- OpenDreamRuntime/Objects/DreamObject.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenDreamRuntime/Objects/DreamObject.cs b/OpenDreamRuntime/Objects/DreamObject.cs index c4b3d08d9f..64f98ab77a 100644 --- a/OpenDreamRuntime/Objects/DreamObject.cs +++ b/OpenDreamRuntime/Objects/DreamObject.cs @@ -171,8 +171,6 @@ protected virtual bool TryGetVar(string varName, out DreamValue value) { } protected virtual void SetVar(string varName, DreamValue value) { - if(ObjectDefinition.ConstVariables.Contains(varName)) - throw new Exception($"Cannot set const var \"{varName}\""); switch (varName) { case "type": case "parent_type": @@ -184,6 +182,8 @@ protected virtual void SetVar(string varName, DreamValue value) { Tag = newTag; break; default: + if(ObjectDefinition.ConstVariables.Contains(varName)) + throw new Exception($"Cannot set const var \"{varName}\" on {ObjectDefinition.Type}"); if (!ObjectDefinition.Variables.ContainsKey(varName)) throw new Exception($"Cannot set var \"{varName}\" on {ObjectDefinition.Type}"); From 70b523dcf8cba17b5841f79800a1365b5159fe54 Mon Sep 17 00:00:00 2001 From: amy Date: Fri, 1 Sep 2023 19:34:57 +0100 Subject: [PATCH 07/13] const/type --- DMCompiler/DMStandard/Types/Client.dm | 2 +- DMCompiler/DMStandard/Types/Datum.dm | 2 +- DMCompiler/DMStandard/Types/List.dm | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/DMCompiler/DMStandard/Types/Client.dm b/DMCompiler/DMStandard/Types/Client.dm index 4ec61aeeab..4f6f895580 100644 --- a/DMCompiler/DMStandard/Types/Client.dm +++ b/DMCompiler/DMStandard/Types/Client.dm @@ -9,7 +9,7 @@ var/default_verb_category = "Commands" var/tag - var/type = /client + var/const/type = /client var/mob/mob var/atom/eye diff --git a/DMCompiler/DMStandard/Types/Datum.dm b/DMCompiler/DMStandard/Types/Datum.dm index 66e47ef3ba..2237e6b34e 100644 --- a/DMCompiler/DMStandard/Types/Datum.dm +++ b/DMCompiler/DMStandard/Types/Datum.dm @@ -1,5 +1,5 @@ /datum - var/type + var/const/type var/parent_type var/list/vars diff --git a/DMCompiler/DMStandard/Types/List.dm b/DMCompiler/DMStandard/Types/List.dm index ca0faa0822..ce16246e56 100644 --- a/DMCompiler/DMStandard/Types/List.dm +++ b/DMCompiler/DMStandard/Types/List.dm @@ -1,6 +1,6 @@ /list var/len - var/type = /list + var/const/type = /list proc/New(Size) From 863a7bf8d32d30b77ce85d72f85902eb600edc73 Mon Sep 17 00:00:00 2001 From: amy Date: Fri, 1 Sep 2023 19:53:06 +0100 Subject: [PATCH 08/13] no readonly --- DMCompiler/DMStandard/Types/Datum.dm | 4 ++-- OpenDreamRuntime/Objects/DreamObject.cs | 2 +- OpenDreamRuntime/Objects/DreamObjectDefinition.cs | 4 ++-- OpenDreamRuntime/Objects/DreamObjectTree.cs | 13 ++----------- 4 files changed, 7 insertions(+), 16 deletions(-) diff --git a/DMCompiler/DMStandard/Types/Datum.dm b/DMCompiler/DMStandard/Types/Datum.dm index 2237e6b34e..ce2d1c7b01 100644 --- a/DMCompiler/DMStandard/Types/Datum.dm +++ b/DMCompiler/DMStandard/Types/Datum.dm @@ -1,8 +1,8 @@ /datum var/const/type - var/parent_type + var/tmp/parent_type - var/list/vars + var/const/list/vars var/tag diff --git a/OpenDreamRuntime/Objects/DreamObject.cs b/OpenDreamRuntime/Objects/DreamObject.cs index 64f98ab77a..855a0702d5 100644 --- a/OpenDreamRuntime/Objects/DreamObject.cs +++ b/OpenDreamRuntime/Objects/DreamObject.cs @@ -182,7 +182,7 @@ protected virtual void SetVar(string varName, DreamValue value) { Tag = newTag; break; default: - if(ObjectDefinition.ConstVariables.Contains(varName)) + if (ObjectDefinition is not null && ObjectDefinition.ConstVariables.Contains(varName)) throw new Exception($"Cannot set const var \"{varName}\" on {ObjectDefinition.Type}"); if (!ObjectDefinition.Variables.ContainsKey(varName)) throw new Exception($"Cannot set var \"{varName}\" on {ObjectDefinition.Type}"); diff --git a/OpenDreamRuntime/Objects/DreamObjectDefinition.cs b/OpenDreamRuntime/Objects/DreamObjectDefinition.cs index 3965e745a5..b52702b8b5 100644 --- a/OpenDreamRuntime/Objects/DreamObjectDefinition.cs +++ b/OpenDreamRuntime/Objects/DreamObjectDefinition.cs @@ -49,9 +49,9 @@ public bool NoConstructors { // Maps /static variables from name to their index in the global variable table. public readonly Dictionary GlobalVariables = new(); // Contains hashes of variables that are tagged /const. - public readonly HashSet ConstVariables = new(); + public HashSet? ConstVariables = null; // Contains hashes of variables that are tagged /tmp. - public readonly HashSet TmpVariables = new(); + public HashSet? TmpVariables = null; public DreamObjectDefinition(DreamObjectDefinition copyFrom) { DreamManager = copyFrom.DreamManager; diff --git a/OpenDreamRuntime/Objects/DreamObjectTree.cs b/OpenDreamRuntime/Objects/DreamObjectTree.cs index 4749e4f1b2..2fcf253ab3 100644 --- a/OpenDreamRuntime/Objects/DreamObjectTree.cs +++ b/OpenDreamRuntime/Objects/DreamObjectTree.cs @@ -365,17 +365,8 @@ private void LoadVariablesFromJson(DreamObjectDefinition objectDefinition, Dream } } - if (jsonObject.ConstVariables != null) { - foreach (string jsonConstVariable in jsonObject.ConstVariables) { - objectDefinition.ConstVariables.Add(jsonConstVariable); - } - } - - if(jsonObject.TmpVariables != null) { - foreach (string jsonTmpVariable in jsonObject.TmpVariables) { - objectDefinition.TmpVariables.Add(jsonTmpVariable); - } - } + objectDefinition.ConstVariables = jsonObject.ConstVariables; + objectDefinition.TmpVariables = jsonObject.TmpVariables; } public DreamProc LoadProcJson(int id, DreamTypeJson[] types, ProcDefinitionJson procDefinition) { From 668056806cd3af3c1b464f9b5fb6fec2f09b7346 Mon Sep 17 00:00:00 2001 From: amy Date: Fri, 1 Sep 2023 19:53:51 +0100 Subject: [PATCH 09/13] oops --- OpenDreamRuntime/Objects/DreamObject.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenDreamRuntime/Objects/DreamObject.cs b/OpenDreamRuntime/Objects/DreamObject.cs index 855a0702d5..dd25f7fcb5 100644 --- a/OpenDreamRuntime/Objects/DreamObject.cs +++ b/OpenDreamRuntime/Objects/DreamObject.cs @@ -182,7 +182,7 @@ protected virtual void SetVar(string varName, DreamValue value) { Tag = newTag; break; default: - if (ObjectDefinition is not null && ObjectDefinition.ConstVariables.Contains(varName)) + if (ObjectDefinition.ConstVariables is not null && ObjectDefinition.ConstVariables.Contains(varName)) throw new Exception($"Cannot set const var \"{varName}\" on {ObjectDefinition.Type}"); if (!ObjectDefinition.Variables.ContainsKey(varName)) throw new Exception($"Cannot set var \"{varName}\" on {ObjectDefinition.Type}"); From 906992934c9ad50ea243e66071a97427b6b9be75 Mon Sep 17 00:00:00 2001 From: amy Date: Fri, 1 Sep 2023 20:01:27 +0100 Subject: [PATCH 10/13] missed a couple --- OpenDreamRuntime/Objects/DreamObject.cs | 3 ++- OpenDreamRuntime/Objects/DreamObjectDefinition.cs | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/OpenDreamRuntime/Objects/DreamObject.cs b/OpenDreamRuntime/Objects/DreamObject.cs index dd25f7fcb5..bdb91c88cc 100644 --- a/OpenDreamRuntime/Objects/DreamObject.cs +++ b/OpenDreamRuntime/Objects/DreamObject.cs @@ -122,7 +122,8 @@ public virtual DreamValue Initial(string name) { public virtual bool IsSaved(string name) { return ObjectDefinition.Variables.ContainsKey(name) && !ObjectDefinition.GlobalVariables.ContainsKey(name) - && !ObjectDefinition.ConstVariables.Contains(name) && !ObjectDefinition.TmpVariables.Contains(name); + && (ObjectDefinition.ConstVariables is not null && !ObjectDefinition.ConstVariables.Contains(name)) + && (ObjectDefinition.TmpVariables is not null && !ObjectDefinition.TmpVariables.Contains(name)); } public bool HasVariable(string name) { diff --git a/OpenDreamRuntime/Objects/DreamObjectDefinition.cs b/OpenDreamRuntime/Objects/DreamObjectDefinition.cs index b52702b8b5..b09d93bcfa 100644 --- a/OpenDreamRuntime/Objects/DreamObjectDefinition.cs +++ b/OpenDreamRuntime/Objects/DreamObjectDefinition.cs @@ -72,8 +72,8 @@ public DreamObjectDefinition(DreamObjectDefinition copyFrom) { Variables = new Dictionary(copyFrom.Variables); GlobalVariables = new Dictionary(copyFrom.GlobalVariables); - ConstVariables = new HashSet(copyFrom.ConstVariables); - TmpVariables = new HashSet(copyFrom.TmpVariables); + ConstVariables = copyFrom.ConstVariables is not null ? new HashSet(copyFrom.ConstVariables) : null; + TmpVariables = copyFrom.TmpVariables is not null ? new HashSet(copyFrom.TmpVariables) : null; Procs = new Dictionary(copyFrom.Procs); OverridingProcs = new Dictionary(copyFrom.OverridingProcs); if (copyFrom.Verbs != null) From 7455de630d06417dc922499d79a4ae0f10ca281d Mon Sep 17 00:00:00 2001 From: amy Date: Fri, 1 Sep 2023 20:08:49 +0100 Subject: [PATCH 11/13] logic better --- OpenDreamRuntime/Objects/DreamObject.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenDreamRuntime/Objects/DreamObject.cs b/OpenDreamRuntime/Objects/DreamObject.cs index bdb91c88cc..40384c2d62 100644 --- a/OpenDreamRuntime/Objects/DreamObject.cs +++ b/OpenDreamRuntime/Objects/DreamObject.cs @@ -122,8 +122,8 @@ public virtual DreamValue Initial(string name) { public virtual bool IsSaved(string name) { return ObjectDefinition.Variables.ContainsKey(name) && !ObjectDefinition.GlobalVariables.ContainsKey(name) - && (ObjectDefinition.ConstVariables is not null && !ObjectDefinition.ConstVariables.Contains(name)) - && (ObjectDefinition.TmpVariables is not null && !ObjectDefinition.TmpVariables.Contains(name)); + && (ObjectDefinition.ConstVariables is null || !ObjectDefinition.ConstVariables.Contains(name)) + && (ObjectDefinition.TmpVariables is null || !ObjectDefinition.TmpVariables.Contains(name)); } public bool HasVariable(string name) { From 8e135c34577600341d86d66ed22632b38936ee07 Mon Sep 17 00:00:00 2001 From: amy Date: Fri, 1 Sep 2023 21:21:56 +0100 Subject: [PATCH 12/13] readability, something bugged --- DMCompiler/DM/Visitors/DMObjectBuilder.cs | 8 ++++++-- OpenDreamRuntime/Objects/DreamObject.cs | 7 ++++--- OpenDreamRuntime/Objects/DreamObjectDefinition.cs | 4 ++++ OpenDreamRuntime/Procs/DMOpcodeHandlers.cs | 4 +++- 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/DMCompiler/DM/Visitors/DMObjectBuilder.cs b/DMCompiler/DM/Visitors/DMObjectBuilder.cs index 3edd7bd01f..9d62e01b4d 100644 --- a/DMCompiler/DM/Visitors/DMObjectBuilder.cs +++ b/DMCompiler/DM/Visitors/DMObjectBuilder.cs @@ -276,10 +276,14 @@ private static void ProcessVarDefinition(DMObject? varObject, DMASTObjectVarDefi } else { variable = new DMVariable(varDefinition.Type, varDefinition.Name, false, varDefinition.IsConst, varDefinition.IsTmp, varDefinition.ValType); varObject.Variables[variable.Name] = variable; - if(varDefinition.IsConst) + if(varDefinition.IsConst){ + varObject.ConstVariables ??= new HashSet(); varObject.ConstVariables.Add(varDefinition.Name); - if(varDefinition.IsTmp) + } + if(varDefinition.IsTmp){ + varObject.TmpVariables ??= new HashSet(); varObject.TmpVariables.Add(varDefinition.Name); + } } } diff --git a/OpenDreamRuntime/Objects/DreamObject.cs b/OpenDreamRuntime/Objects/DreamObject.cs index 40384c2d62..7e9a6904fb 100644 --- a/OpenDreamRuntime/Objects/DreamObject.cs +++ b/OpenDreamRuntime/Objects/DreamObject.cs @@ -121,9 +121,10 @@ public virtual DreamValue Initial(string name) { } public virtual bool IsSaved(string name) { - return ObjectDefinition.Variables.ContainsKey(name) && !ObjectDefinition.GlobalVariables.ContainsKey(name) - && (ObjectDefinition.ConstVariables is null || !ObjectDefinition.ConstVariables.Contains(name)) - && (ObjectDefinition.TmpVariables is null || !ObjectDefinition.TmpVariables.Contains(name)); + return ObjectDefinition.Variables.ContainsKey(name) + && !ObjectDefinition.GlobalVariables.ContainsKey(name) + && !(ObjectDefinition.ConstVariables is not null && ObjectDefinition.ConstVariables.Contains(name)) + && !(ObjectDefinition.TmpVariables is not null && ObjectDefinition.TmpVariables.Contains(name)); } public bool HasVariable(string name) { diff --git a/OpenDreamRuntime/Objects/DreamObjectDefinition.cs b/OpenDreamRuntime/Objects/DreamObjectDefinition.cs index b09d93bcfa..92e24a8686 100644 --- a/OpenDreamRuntime/Objects/DreamObjectDefinition.cs +++ b/OpenDreamRuntime/Objects/DreamObjectDefinition.cs @@ -103,6 +103,10 @@ public DreamObjectDefinition(DreamManager dreamManager, DreamObjectTree objectTr Verbs = new List(Parent.Verbs); if (Parent != ObjectTree.Root.ObjectDefinition) // Don't include root-level globals GlobalVariables = new Dictionary(Parent.GlobalVariables); + if (Parent.ConstVariables != null) + ConstVariables = new HashSet(Parent.ConstVariables); + if (Parent.TmpVariables != null) + TmpVariables = new HashSet(Parent.TmpVariables); } } diff --git a/OpenDreamRuntime/Procs/DMOpcodeHandlers.cs b/OpenDreamRuntime/Procs/DMOpcodeHandlers.cs index 9732128dd2..182a046b7f 100644 --- a/OpenDreamRuntime/Procs/DMOpcodeHandlers.cs +++ b/OpenDreamRuntime/Procs/DMOpcodeHandlers.cs @@ -2008,7 +2008,9 @@ public static ProcStatus IsSaved(DMProcState state) { throw new Exception($"Invalid owner for issaved() call {owner}"); } - if (objectDefinition.GlobalVariables.ContainsKey(property) || objectDefinition.ConstVariables.Contains(property) || objectDefinition.TmpVariables.Contains(property)) { + if (objectDefinition.GlobalVariables.ContainsKey(property) + || (objectDefinition.ConstVariables is not null && objectDefinition.ConstVariables.Contains(property)) + || (objectDefinition.TmpVariables is not null && objectDefinition.TmpVariables.Contains(property))) { state.Push(new DreamValue(0)); } else { state.Push(new DreamValue(1)); From 7dbe7f1320d3592a19e5b96f351f3aeb7c808b17 Mon Sep 17 00:00:00 2001 From: amy Date: Fri, 1 Sep 2023 21:35:06 +0100 Subject: [PATCH 13/13] fixed --- .../Special Procs/issaved/issaved_vars_index.dm | 1 + OpenDreamRuntime/Objects/DreamObjectTree.cs | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Content.Tests/DMProject/Tests/Special Procs/issaved/issaved_vars_index.dm b/Content.Tests/DMProject/Tests/Special Procs/issaved/issaved_vars_index.dm index d0a7e41b0f..f77f95dc52 100644 --- a/Content.Tests/DMProject/Tests/Special Procs/issaved/issaved_vars_index.dm +++ b/Content.Tests/DMProject/Tests/Special Procs/issaved/issaved_vars_index.dm @@ -11,6 +11,7 @@ /proc/RunTest() var/obj/o/test = new + ASSERT(!issaved(test.type)) ASSERT(issaved(test.A)) ASSERT(!issaved(test.B)) diff --git a/OpenDreamRuntime/Objects/DreamObjectTree.cs b/OpenDreamRuntime/Objects/DreamObjectTree.cs index 2fcf253ab3..6a0462300b 100644 --- a/OpenDreamRuntime/Objects/DreamObjectTree.cs +++ b/OpenDreamRuntime/Objects/DreamObjectTree.cs @@ -365,8 +365,19 @@ private void LoadVariablesFromJson(DreamObjectDefinition objectDefinition, Dream } } - objectDefinition.ConstVariables = jsonObject.ConstVariables; - objectDefinition.TmpVariables = jsonObject.TmpVariables; + if (jsonObject.ConstVariables != null) { + objectDefinition.ConstVariables ??= new(); + foreach (string jsonConstVariable in jsonObject.ConstVariables) { + objectDefinition.ConstVariables.Add(jsonConstVariable); + } + } + + if(jsonObject.TmpVariables != null) { + objectDefinition.TmpVariables ??= new(); + foreach (string jsonTmpVariable in jsonObject.TmpVariables) { + objectDefinition.TmpVariables.Add(jsonTmpVariable); + } + } } public DreamProc LoadProcJson(int id, DreamTypeJson[] types, ProcDefinitionJson procDefinition) {