Skip to content

Commit

Permalink
Find stray nodes in compilation units
Browse files Browse the repository at this point in the history
  • Loading branch information
RA-Kooi committed Oct 11, 2022
1 parent 79b4980 commit 58db5d9
Showing 1 changed file with 115 additions and 0 deletions.
115 changes: 115 additions & 0 deletions DwarfOne2C/Parsing/CompilationUnit.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Linq;

namespace DwarfOne2C
{
Expand Down Expand Up @@ -45,6 +46,8 @@ public CompilationUnit(

AddNodeChildren(allTags, IDToIndex, root);

FindStrays(allTags, IDToIndex);

ApplyFixes();
}

Expand Down Expand Up @@ -182,5 +185,117 @@ void FixFunclet(Node parent, int depth)
}
}
}

void FindStrays(List<Tag> allTags, Dictionary<int, int> IDToIndex)
{
Dictionary<int, int> refCounts = new();

int end = root.tag.sibling == Tag.NoSibling
? allTags.Count
: IDToIndex[root.tag.sibling];

for(int i = IDToIndex[root.tag.ID]; i < end; ++i)
{
Tag current = allTags[i];

if(current.tagType == TagType.End)
continue;

int value = 0;

refCounts.TryGetValue(current.sibling, out value);
refCounts[current.sibling] = value + 1;
}

refCounts.Where(kvp => kvp.Value <= 1)
.Select(kvp => kvp.Key)
.All(
key =>
{
refCounts.Remove(key);
return true;
});

Node FindParent(Node parent, int tagID)
{
Node result = parent.children.Find(n => n.tag.ID == tagID);

if(result != null)
return parent;

foreach(Node child in parent.children)
{
result = FindParent(child, tagID);

if(result != null)
return result;
}

return null;
}

foreach(KeyValuePair<int, int> tagRefCount in refCounts)
{
int refIdx = IDToIndex[tagRefCount.Key];
Tag referenced = allTags[refIdx];

int CUIdx = IDToIndex[root.tag.ID];

List<Tag> searchRange = allTags.GetRange(CUIdx, refIdx - CUIdx);
List<Tag> referencingTags = searchRange
.Where(tag => tag.sibling == tagRefCount.Key)
.ToList();

System.Diagnostics.Debug.Assert(referencingTags.Count == 2);

// Look for the referencing ID, as the current key can be an end tag.
Node parent = FindParent(root, referencingTags[0].ID);

int leftIdx = parent.children
.FindIndex(n => n.tag.ID == referencingTags[0].ID);

Node left = parent.children[leftIdx];

Tag stray = referencingTags[1];

while(true)
{
Tag result = null;

// Faster backward search...
for(int i = IDToIndex[stray.ID]; i > CUIdx; --i)
{
Tag current = allTags[i];

if(current.sibling == stray.ID)
{
result = current;
break;
}
}

if(result == null)
break;

stray = result;
}

left.tag.sibling = stray.ID;

List<Node> newChildren = new();

while(stray.ID != tagRefCount.Key)
{
Node right = new(stray);
AddNodeChildren(allTags, IDToIndex, right);

newChildren.Add(right);

stray = allTags[IDToIndex[stray.sibling]];
}

parent.children.InsertRange(leftIdx + 1, newChildren);
}
}
}
}

0 comments on commit 58db5d9

Please sign in to comment.