Skip to content

Commit

Permalink
Remove last uses of DreamPath outside of the compiler (#1528)
Browse files Browse the repository at this point in the history
* Remove last uses of `DreamPath` outside of the compiler

* Fix error

* Fix indentation
  • Loading branch information
wixoaGit authored Dec 18, 2023
1 parent ac0410a commit bbadf69
Show file tree
Hide file tree
Showing 24 changed files with 514 additions and 518 deletions.
2 changes: 1 addition & 1 deletion DMCompiler/Compiler/DM/DMASTHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public void HashFile(DMASTFile node) {
}

public DMASTProcDefinition GetProcByPath(string path) {
var h = Hash(new DMASTProcDefinition(Location.Unknown, new OpenDreamShared.Dream.DreamPath(path), new DMASTDefinitionParameter[0], null));
var h = Hash(new DMASTProcDefinition(Location.Unknown, new DreamPath(path), new DMASTDefinitionParameter[0], null));
return nodes[h][0] as DMASTProcDefinition;
}
public void HashDefine(DMASTNode node) {
Expand Down
11 changes: 3 additions & 8 deletions DMCompiler/Compiler/DM/DMPath.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@

using System.Collections.Generic;
using OpenDreamShared.Dream;
using System.Collections.Generic;

namespace DMCompiler.Compiler.DM
{

public abstract class VarDeclInfo
{
namespace DMCompiler.Compiler.DM {
public abstract class VarDeclInfo {
public DreamPath? TypePath;
public string VarName;

Expand Down
1 change: 0 additions & 1 deletion DMCompiler/Compiler/DMM/DMMParser.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System;
using OpenDreamShared.Compiler;
using OpenDreamShared.Dream;
using OpenDreamShared.Json;
using DMCompiler.DM;
using System.Collections.Generic;
Expand Down
1 change: 0 additions & 1 deletion DMCompiler/DM/DMExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using DMCompiler.DM.Visitors;
using OpenDreamShared.Compiler;
using DMCompiler.Compiler.DM;
using OpenDreamShared.Dream;
using System.Diagnostics.CodeAnalysis;
using DMCompiler.Bytecode;

Expand Down
1 change: 0 additions & 1 deletion DMCompiler/DM/Expressions/Binary.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System.Diagnostics.CodeAnalysis;
using DMCompiler.Bytecode;
using OpenDreamShared.Compiler;
using OpenDreamShared.Dream;

namespace DMCompiler.DM.Expressions {
abstract class BinaryOp : DMExpression {
Expand Down
1 change: 0 additions & 1 deletion DMCompiler/DM/Expressions/Constant.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using OpenDreamShared.Compiler;
using OpenDreamShared.Dream;
using OpenDreamShared.Json;
using System;
using System.Collections.Generic;
Expand Down
1 change: 0 additions & 1 deletion DMCompiler/DM/Expressions/LValue.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System.Diagnostics.CodeAnalysis;
using DMCompiler.Bytecode;
using OpenDreamShared.Compiler;
using OpenDreamShared.Dream;

namespace DMCompiler.DM.Expressions {
abstract class LValue : DMExpression {
Expand Down
245 changes: 245 additions & 0 deletions DMCompiler/DreamPath.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,245 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json.Serialization;

namespace DMCompiler;

// TODO: This is fairly ugly structure and should probably be removed/redone with something much nicer.
// It's heavily embedded into a lot of corners of the compiler though.
public struct DreamPath {
public static readonly DreamPath Root = new DreamPath("/");
public static readonly DreamPath Exception = new DreamPath("/exception");
public static readonly DreamPath List = new DreamPath("/list");
public static readonly DreamPath Regex = new DreamPath("/regex");
public static readonly DreamPath Savefile = new DreamPath("/savefile");
public static readonly DreamPath Sound = new DreamPath("/sound");
public static readonly DreamPath Image = new DreamPath("/image");
public static readonly DreamPath Icon = new DreamPath("/icon");
public static readonly DreamPath MutableAppearance = new DreamPath("/mutable_appearance");
public static readonly DreamPath World = new DreamPath("/world");
public static readonly DreamPath Client = new DreamPath("/client");
public static readonly DreamPath Datum = new DreamPath("/datum");
public static readonly DreamPath Matrix = new DreamPath("/matrix");
public static readonly DreamPath Atom = new DreamPath("/atom");
public static readonly DreamPath Area = new DreamPath("/area");
public static readonly DreamPath Turf = new DreamPath("/turf");
public static readonly DreamPath Movable = new DreamPath("/atom/movable");
public static readonly DreamPath Obj = new DreamPath("/obj");
public static readonly DreamPath Mob = new DreamPath("/mob");
public static readonly DreamPath Filter = new DreamPath("/dm_filter");

public enum PathType {
Absolute,
Relative,

//TODO: These really shouldn't be here
DownwardSearch,
UpwardSearch
}

[JsonIgnore]
public string? LastElement {
get => Elements.Length > 0 ? Elements.Last() : null;
}

[JsonIgnore]
public string[] Elements {
get => _elements;
set {
_elements = value;
_pathString = null;
}
}

public string PathString {
get {
if (_pathString != null) return _pathString;

_pathString = Type switch {
PathType.Absolute => "/",
PathType.DownwardSearch => ":",
PathType.UpwardSearch => ".",
_ => string.Empty
};

// Elements is usually small enough for this to be faster than StringBuilder
_pathString += string.Join("/", Elements);

return _pathString;
}
set => SetFromString(value);
}

public PathType Type;

private string[] _elements;
private string? _pathString;

public DreamPath(string path) {
Type = PathType.Absolute;
_elements = Array.Empty<string>(); // Set in SetFromString()
_pathString = null;

SetFromString(path);
}

public DreamPath(PathType type, string[] elements) {
Type = type;
_elements = elements;
_pathString = null;

Normalize(true);
}

public void SetFromString(string rawPath) {
char pathTypeChar = rawPath[0];
string[] tempElements = rawPath.Split('/', StringSplitOptions.RemoveEmptyEntries);
bool skipFirstChar = false;

switch (pathTypeChar) {
case '/':
Type = PathType.Absolute;
// No need to skip the first char, as it will end up as an empty entry in tempElements
break;
case ':':
Type = PathType.DownwardSearch;
skipFirstChar = true;
break;
case '.':
Type = PathType.UpwardSearch;
skipFirstChar = true;
break;
default:
Type = PathType.Relative;
break;
}

if (skipFirstChar) {
// Skip the '/', ':' or '.' if needed
tempElements[0] = tempElements[0][1..];
}

Elements = tempElements;
Normalize(false);
}

/// <summary>
/// Checks if the DreamPath is a descendant of another. NOTE: For type inheritance, use IsSubtypeOf()
/// </summary>
/// <param name="path">Path to compare to.</param>
public bool IsDescendantOf(DreamPath path) {
if (path.Elements.Length > Elements.Length) return false;

for (int i = 0; i < path.Elements.Length; i++) {
if (Elements[i] != path.Elements[i]) return false;
}

return true;
}

public DreamPath AddToPath(string path) {
string rawPath = PathString;

if (!rawPath.EndsWith('/') && !path.StartsWith('/')) {
path = '/' + path;
}

return new DreamPath(rawPath + path);
}

public int FindElement(string element) {
return Array.IndexOf(Elements, element);
}

public string[] GetElements(int elementStart, int elementEnd = -1) {
if (elementEnd < 0) elementEnd = Elements.Length + elementEnd + 1;

string[] elements = new string[elementEnd - elementStart];
Array.Copy(Elements, elementStart, elements, 0, elements.Length);

return elements;
}

public DreamPath FromElements(int elementStart, int elementEnd = -1) {
string[] elements = GetElements(elementStart, elementEnd);
string rawPath = String.Empty;

if (elements.Length >= 1) {
rawPath = elements.Aggregate((string first, string second) => {
return first + "/" + second;
});
}

rawPath = "/" + rawPath;
return new DreamPath(rawPath);
}

public DreamPath RemoveElement(int elementIndex) {
if (elementIndex < 0) elementIndex += Elements.Length;

List<string> elements = new List<string>();
elements.AddRange(GetElements(0, elementIndex));
elements.AddRange(GetElements(Math.Min(elementIndex + 1, Elements.Length), -1));
return new DreamPath(Type, elements.ToArray());
}

public DreamPath Combine(DreamPath path) {
switch (path.Type) {
case PathType.Relative: return new DreamPath(PathString + "/" + path.PathString);
case PathType.Absolute: return path;
default: return new DreamPath(PathString + path.PathString);
}
}

public override string ToString() {
return PathString;
}

public override bool Equals(object? obj) => obj is DreamPath other && Equals(other);

public bool Equals(DreamPath other) {
if (other.Elements.Length != Elements.Length) return false;

for (int i = 0; i < Elements.Length; i++) {
if (Elements[i] != other.Elements[i]) return false;
}

return true;
}

public override int GetHashCode() {
int hashCode = 0;
for (int i = 0; i < Elements.Length; i++) {
hashCode += Elements[i].GetHashCode();
}

return hashCode;
}

public static bool operator ==(DreamPath lhs, DreamPath rhs) => lhs.Equals(rhs);

public static bool operator !=(DreamPath lhs, DreamPath rhs) => !(lhs == rhs);

private void Normalize(bool canHaveEmptyEntries) {
if (canHaveEmptyEntries && _elements.Contains("")) {
// Slow path :(
_elements = _elements.Where(el => !string.IsNullOrEmpty(el)).ToArray();
}

var writeIdx = Array.IndexOf(_elements, "..");
if (writeIdx == -1) return;

for (var i = writeIdx; i < _elements.Length; i++) {
var elem = _elements[i];
if (elem == "..") {
writeIdx -= 1;
} else {
_elements[writeIdx] = elem;
writeIdx += 1;
}
}

Elements = _elements[..writeIdx];
}
}
35 changes: 17 additions & 18 deletions DMDisassembler/DMType.cs
Original file line number Diff line number Diff line change
@@ -1,27 +1,26 @@
using OpenDreamShared.Dream;
using OpenDreamShared.Json;
using OpenDreamShared.Json;
using System.Collections.Generic;

namespace DMDisassembler {
class DMType {
public DreamPath Path;
public DreamTypeJson Json;
public DMProc InitProc;
public Dictionary<string, DMProc> Procs;
namespace DMDisassembler;

public DMType(DreamTypeJson json) {
Json = json;
Path = new DreamPath(Json.Path);
internal class DMType {
public string Path;
public DreamTypeJson Json;
public DMProc InitProc;
public Dictionary<string, DMProc> Procs;

InitProc = Json.InitProc.HasValue ? Program.Procs[Json.InitProc.Value] : null;
public DMType(DreamTypeJson json) {
Json = json;
Path = Json.Path;

Procs = new(json.Procs?.Count ?? 0);
if (Json.Procs != null) {
foreach (List<int> procIds in Json.Procs) {
DMProc proc = Program.Procs[procIds[^1]];
InitProc = Json.InitProc.HasValue ? Program.Procs[Json.InitProc.Value] : null;

Procs.Add(proc.Name, proc);
}
Procs = new(json.Procs?.Count ?? 0);
if (Json.Procs != null) {
foreach (List<int> procIds in Json.Procs) {
DMProc proc = Program.Procs[procIds[^1]];

Procs.Add(proc.Name, proc);
}
}
}
Expand Down
Loading

0 comments on commit bbadf69

Please sign in to comment.