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

Remove last uses of DreamPath outside of the compiler #1528

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading