Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement /tmp and /const var decorators on object vars for issaved() #1443

Merged
17 changes: 0 additions & 17 deletions Content.Tests/DMProject/Broken Tests/Stdlib/issaved.dm

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
// !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.type))
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)
Expand Down
10 changes: 10 additions & 0 deletions DMCompiler/DM/DMObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ internal sealed class DMObject {
public Dictionary<string, DMVariable> VariableOverrides = new();
public Dictionary<string, int> GlobalVariables = new();
/// <summary>A list of var and verb initializations implicitly done before the user's New() is called.</summary>
public HashSet<string> ConstVariables = new();
public HashSet<string> TmpVariables = new();
public List<DMExpression> InitializationProcExpressions = new();
public int? InitializationProc;

Expand Down Expand Up @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion DMCompiler/DM/DMObjectTree.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
6 changes: 4 additions & 2 deletions DMCompiler/DM/DMVariable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
/// </remarks>
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;
}
Expand All @@ -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;
}
Expand Down
10 changes: 9 additions & 1 deletion DMCompiler/DM/Visitors/DMObjectBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -274,8 +274,16 @@ 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 ??= new HashSet<string>();
varObject.ConstVariables.Add(varDefinition.Name);
}
if(varDefinition.IsTmp){
varObject.TmpVariables ??= new HashSet<string>();
varObject.TmpVariables.Add(varDefinition.Name);
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion DMCompiler/DMStandard/Types/Client.dm
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
var/default_verb_category = "Commands"

var/tag
var/type = /client
var/const/type = /client

var/mob/mob
var/atom/eye
Expand Down
6 changes: 3 additions & 3 deletions DMCompiler/DMStandard/Types/Datum.dm
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/datum
var/type
var/parent_type
var/const/type
var/tmp/parent_type

var/list/vars
var/const/list/vars

var/tag

Expand Down
2 changes: 1 addition & 1 deletion DMCompiler/DMStandard/Types/List.dm
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/list
var/len
var/type = /list
var/const/type = /list

proc/New(Size)

Expand Down
8 changes: 6 additions & 2 deletions OpenDreamRuntime/Objects/DreamObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,10 @@ 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 is not null && ObjectDefinition.ConstVariables.Contains(name))
&& !(ObjectDefinition.TmpVariables is not null && ObjectDefinition.TmpVariables.Contains(name));
}

public bool HasVariable(string name) {
Expand Down Expand Up @@ -182,6 +184,8 @@ protected virtual void SetVar(string varName, DreamValue value) {
Tag = newTag;
break;
default:
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}");

Expand Down
10 changes: 10 additions & 0 deletions OpenDreamRuntime/Objects/DreamObjectDefinition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ public bool NoConstructors {
public readonly Dictionary<string, DreamValue> Variables = new();
// Maps /static variables from name to their index in the global variable table.
public readonly Dictionary<string, int> GlobalVariables = new();
// Contains hashes of variables that are tagged /const.
public HashSet<string>? ConstVariables = null;
// Contains hashes of variables that are tagged /tmp.
public HashSet<string>? TmpVariables = null;

public DreamObjectDefinition(DreamObjectDefinition copyFrom) {
DreamManager = copyFrom.DreamManager;
Expand All @@ -68,6 +72,8 @@ public DreamObjectDefinition(DreamObjectDefinition copyFrom) {

Variables = new Dictionary<string, DreamValue>(copyFrom.Variables);
GlobalVariables = new Dictionary<string, int>(copyFrom.GlobalVariables);
ConstVariables = copyFrom.ConstVariables is not null ? new HashSet<string>(copyFrom.ConstVariables) : null;
TmpVariables = copyFrom.TmpVariables is not null ? new HashSet<string>(copyFrom.TmpVariables) : null;
Procs = new Dictionary<string, int>(copyFrom.Procs);
OverridingProcs = new Dictionary<string, int>(copyFrom.OverridingProcs);
if (copyFrom.Verbs != null)
Expand Down Expand Up @@ -97,6 +103,10 @@ public DreamObjectDefinition(DreamManager dreamManager, DreamObjectTree objectTr
Verbs = new List<int>(Parent.Verbs);
if (Parent != ObjectTree.Root.ObjectDefinition) // Don't include root-level globals
GlobalVariables = new Dictionary<string, int>(Parent.GlobalVariables);
if (Parent.ConstVariables != null)
ConstVariables = new HashSet<string>(Parent.ConstVariables);
if (Parent.TmpVariables != null)
TmpVariables = new HashSet<string>(Parent.TmpVariables);
}
}

Expand Down
14 changes: 14 additions & 0 deletions OpenDreamRuntime/Objects/DreamObjectTree.cs
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,20 @@ private void LoadVariablesFromJson(DreamObjectDefinition objectDefinition, Dream
objectDefinition.GlobalVariables.Add(jsonGlobalVariable.Key, jsonGlobalVariable.Value);
}
}

if (jsonObject.ConstVariables != null) {
objectDefinition.ConstVariables ??= new();
foreach (string jsonConstVariable in jsonObject.ConstVariables) {
objectDefinition.ConstVariables.Add(jsonConstVariable);
}
amylizzle marked this conversation as resolved.
Show resolved Hide resolved
}

if(jsonObject.TmpVariables != null) {
objectDefinition.TmpVariables ??= new();
foreach (string jsonTmpVariable in jsonObject.TmpVariables) {
objectDefinition.TmpVariables.Add(jsonTmpVariable);
}
amylizzle marked this conversation as resolved.
Show resolved Hide resolved
}
}

public DreamProc LoadProcJson(int id, DreamTypeJson[] types, ProcDefinitionJson procDefinition) {
Expand Down
5 changes: 3 additions & 2 deletions OpenDreamRuntime/Procs/DMOpcodeHandlers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2017,8 +2017,9 @@ 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 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));
Expand Down
2 changes: 2 additions & 0 deletions OpenDreamShared/Json/DreamObjectJson.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ public sealed class DreamTypeJson {
public List<int> Verbs { get; set; }
public Dictionary<string, object> Variables { get; set; }
public Dictionary<string, int> GlobalVariables { get; set; }
public HashSet<string>? ConstVariables { get; set; }
public HashSet<string>? TmpVariables { get; set; }
}

public sealed class GlobalListJson {
Expand Down
Loading