Skip to content

Commit

Permalink
Implement /tmp and /const var decorators on object vars for `issa…
Browse files Browse the repository at this point in the history
…ved()` (#1443)

* fun

* oops, missed those

* redundant test

* remove useless test

* Update OpenDreamShared/Json/DreamObjectJson.cs

Co-authored-by: wixoa <wixoag@gmail.com>

* move to default

* const/type

* no readonly

* oops

* missed a couple

* logic better

* readability, something bugged

* fixed

---------

Co-authored-by: amy <amylizzle@users.noreply.github.com>
Co-authored-by: wixoa <wixoag@gmail.com>
  • Loading branch information
3 people authored Sep 28, 2023
1 parent 16f26ce commit 3ef630f
Show file tree
Hide file tree
Showing 14 changed files with 70 additions and 36 deletions.
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 @@ -367,6 +367,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);
}
}

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) {
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

0 comments on commit 3ef630f

Please sign in to comment.