[WIP] Importing shared data tables

This commit is contained in:
Yoshi Askharoun
2025-01-29 14:23:12 -06:00
parent c34aae8212
commit 0904702679
7 changed files with 148 additions and 72 deletions
+1 -1
View File
@@ -3,9 +3,9 @@
"UIXC": {
"commandName": "Project",
"commandLineArgs": "decompile C:\\Users\\jjask\\Documents\\Dump\\Zune\\ZuneShellResources -A ZuneShell.dll -A UIXControls.dll -A ZuneDBApi.dll -o C:\\Users\\jjask\\Documents\\Dump\\Zune\\ZuneShellResources_uixa -t C:\\Users\\jjask\\Documents\\Dump\\Zune\\ZuneShellResources_uixa\\_DATATABLE.uixa",
//"commandLineArgs": "decompile C:\\Users\\jjask\\Documents\\Dump\\Zune\\ZuneShellResources\\_DATATABLE.UIB -A ZuneShell.dll -A UIXControls.dll -A ZuneDBApi.dll -o C:\\Users\\jjask\\Documents\\Dump\\Zune\\ZuneShellResources_uixa",
//"commandLineArgs": "compile C:\\Users\\jjask\\Documents\\Dump\\Zune\\ZuneShellResources\\CreatePassport.uixa -A ZuneShell.dll -A UIXControls.dll -A ZuneDBApi.dll -o C:\\Users\\jjask\\Documents\\Dump\\Zune",
//"commandLineArgs": "compile C:\\Users\\jjask\\Documents\\Dump\\Zune\\_DATATABLE.uixa -A ZuneShell.dll -A UIXControls.dll -A ZuneDBApi.dll -o C:\\Users\\jjask\\Documents\\Dump\\Zune",
//"commandLineArgs": "decompile C:\\Users\\jjask\\Documents\\Dump\\Zune\\ZuneShellResources\\_DATATABLE.UIB -A ZuneShell.dll -A UIXControls.dll -A ZuneDBApi.dll -o C:\\Users\\jjask\\Documents\\Dump\\Zune\\ZuneShellResources_uixa",
//"commandLineArgs": "compile \"D:\\Documents\\REProj\\Zune\\UIXA\\ZuneShell.dll!_DataTable.uixa\" -A ZuneShell.dll -A UIXControls.dll -A ZuneDBApi.dll -o D:\\Documents\\REProj\\Zune\\UIXA",
//"commandLineArgs": "compile \"D:\\Documents\\REProj\\Zune\\UIXA\\ZuneShellResources.dll!_DataTable.uixa\" -A ZuneShell.dll -A UIXControls.dll -A ZuneDBApi.dll -o D:\\Documents\\REProj\\Zune\\UIXA",
+62 -36
View File
@@ -16,7 +16,8 @@ internal class AsmMarkupLoader
private readonly AsmMarkupLoadResult _loadResult;
private LoadPass _currentValidationPass;
private bool _usingSharedBinaryDataTable;
private SourceMarkupImportTables _importTables;
private AsmMarkupLoadResult _binaryDataTableLoadResult;
private MarkupBinaryDataTable _binaryDataTable;
private ObjectSection _objectSection;
private readonly Dictionary<string, LoadResult> _importedNamespaces = new();
@@ -70,16 +71,6 @@ internal class AsmMarkupLoader
var type = result.FindType(typeName);
//if (type is null)
//{
// foreach (var tryResult in _importedNamespaces.Values)
// {
// type = tryResult.FindType(typeName);
// if (type is not null)
// break;
// }
//}
if (type is null)
{
ErrorManager.ReportError(qualifiedName.Line, qualifiedName.Column,
@@ -105,11 +96,11 @@ internal class AsmMarkupLoader
return;
_currentValidationPass = currentPass;
if (_currentValidationPass == LoadPass.DeclareTypes)
{
if (_asmSource == null)
return;
if (_asmSource == null)
return;
if (Program is null && !HasErrors)
{
var parseResult = Lexer.Program.TryParse(_asmSource);
if (parseResult.WasSuccessful)
{
@@ -123,15 +114,48 @@ internal class AsmMarkupLoader
return;
}
if (_loadResult.BinaryDataTable != null)
{
_importTables = _loadResult.BinaryDataTable.SourceMarkupImportTables;
_usingSharedBinaryDataTable = true;
_usingSharedBinaryDataTable = Program.DataTableDirective is not null;
if (_usingSharedBinaryDataTable)
{
// Import the shared data table
var dataTableUri = Program.DataTableDirective.Uri;
var dataTableLoadResult = MarkupSystem.ResolveLoadResult(dataTableUri, _loadResult.IslandReferences);
if (dataTableLoadResult is null)
{
ReportError($"Unable to load '{dataTableUri}' (shared data table)", Program.DataTableDirective);
return;
}
if (dataTableLoadResult is not AsmMarkupLoadResult)
{
ReportError($"Shared data table at '{dataTableUri}' was not UIXA", Program.DataTableDirective);
return;
}
_binaryDataTableLoadResult = (AsmMarkupLoadResult)dataTableLoadResult;
if (_binaryDataTableLoadResult != null)
{
_binaryDataTableLoadResult.Load(_currentValidationPass);
_binaryDataTable = _binaryDataTableLoadResult.BinaryDataTable;
_binaryDataTable.SharedDependenciesTableWithBinaryDataTable ??= [_binaryDataTableLoadResult];
_loadResult.SetDependenciesTable(_binaryDataTable.SharedDependenciesTableWithBinaryDataTable);
}
else
MarkHasErrors();
}
else
{
_importTables = new SourceMarkupImportTables();
_binaryDataTable = new MarkupBinaryDataTable(_loadResult.Uri);
_binaryDataTable.SetConstantsTable(new MarkupConstantsTable());
_binaryDataTable.SetSourceMarkupImportTables(new SourceMarkupImportTables());
}
_loadResult.SetBinaryDataTable(_binaryDataTable);
}
if (_currentValidationPass == LoadPass.DeclareTypes)
{
foreach (var nsImport in Program.Directives.OfType<NamespaceImport>())
{
@@ -256,9 +280,9 @@ internal class AsmMarkupLoader
_loadResult.MarkLoadFailed();
MarkupImportTables importTables = null;
if (_importTables != null)
if (_binaryDataTable.SourceMarkupImportTables != null)
{
importTables = _importTables.PrepareImportTables();
importTables = _binaryDataTable.SourceMarkupImportTables.PrepareImportTables();
_loadResult.SetImportTables(importTables);
}
@@ -323,10 +347,10 @@ internal class AsmMarkupLoader
var contentBuffer = binaryEncodedConstant.Content;
ByteCodeWriter binaryConstantWrtier = new();
binaryConstantWrtier.Write(contentBuffer, (uint)contentBuffer.Length);
ByteCodeWriter binaryConstantWriter = new();
binaryConstantWriter.Write(contentBuffer, (uint)contentBuffer.Length);
var binaryConstantReader = binaryConstantWrtier.CreateReader();
var binaryConstantReader = binaryConstantWriter.CreateReader();
constantValue = constantTypeSchema.DecodeBinary(binaryConstantReader);
persistData = constantValue;
@@ -395,9 +419,9 @@ internal class AsmMarkupLoader
{
LoadResult[] loadResultArray = LoadResult.EmptyList;
int length = 0;
if (_importTables != null)
if (_binaryDataTable.SourceMarkupImportTables != null)
{
foreach (LoadResult importedLoadResult in _importTables.ImportedLoadResults)
foreach (LoadResult importedLoadResult in _binaryDataTable.SourceMarkupImportTables.ImportedLoadResults)
{
if (importedLoadResult != _loadResult)
++length;
@@ -407,7 +431,7 @@ internal class AsmMarkupLoader
{
loadResultArray = new LoadResult[length];
int index = 0;
foreach (LoadResult importedLoadResult in _importTables.ImportedLoadResults)
foreach (LoadResult importedLoadResult in _binaryDataTable.SourceMarkupImportTables.ImportedLoadResults)
{
if (importedLoadResult != _loadResult)
{
@@ -472,12 +496,14 @@ internal class AsmMarkupLoader
{
if (loadResult == MarkupSystem.UIXGlobal)
return;
for (int index = 0; index < _importTables.ImportedLoadResults.Count; ++index)
for (int index = 0; index < _binaryDataTable.SourceMarkupImportTables.ImportedLoadResults.Count; ++index)
{
if ((LoadResult)_importTables.ImportedLoadResults[index] == loadResult)
if ((LoadResult)_binaryDataTable.SourceMarkupImportTables.ImportedLoadResults[index] == loadResult)
return;
}
_importTables.ImportedLoadResults.Add(loadResult);
_binaryDataTable.SourceMarkupImportTables.ImportedLoadResults.Add(loadResult);
}
public int TrackImportedType(TypeSchema type)
@@ -485,14 +511,14 @@ internal class AsmMarkupLoader
if (type is null) return -1;
TrackImportedLoadResult(type.Owner);
return TrackImportedSchema(_importTables.ImportedTypes, type);
return TrackImportedSchema(_binaryDataTable.SourceMarkupImportTables.ImportedTypes, type);
}
public int TrackImportedConstructor(ConstructorSchema constructor)
{
if (constructor is null) return -1;
int num = TrackImportedSchema(_importTables.ImportedConstructors, constructor);
int num = TrackImportedSchema(_binaryDataTable.SourceMarkupImportTables.ImportedConstructors, constructor);
TrackImportedType(constructor.Owner);
foreach (TypeSchema parameterType in constructor.ParameterTypes)
TrackImportedType(parameterType);
@@ -503,7 +529,7 @@ internal class AsmMarkupLoader
{
if (property is null) return -1;
int num = TrackImportedSchema(_importTables.ImportedProperties, property);
int num = TrackImportedSchema(_binaryDataTable.SourceMarkupImportTables.ImportedProperties, property);
TrackImportedType(property.Owner);
return num;
}
@@ -512,7 +538,7 @@ internal class AsmMarkupLoader
{
if (method is null) return -1;
int num = TrackImportedSchema(_importTables.ImportedMethods, method);
int num = TrackImportedSchema(_binaryDataTable.SourceMarkupImportTables.ImportedMethods, method);
TrackImportedType(method.Owner);
foreach (TypeSchema parameterType in method.ParameterTypes)
TrackImportedType(parameterType);
@@ -523,7 +549,7 @@ internal class AsmMarkupLoader
{
if (evt is null) return -1;
int num = TrackImportedSchema(_importTables.ImportedEvents, evt);
int num = TrackImportedSchema(_binaryDataTable.SourceMarkupImportTables.ImportedEvents, evt);
TrackImportedType(evt.Owner);
return num;
}
+20 -11
View File
@@ -3,6 +3,7 @@ using Microsoft.Iris.Asm.Models;
using Microsoft.Iris.Markup;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Runtime.InteropServices;
@@ -24,9 +25,8 @@ public class Disassembler
{
_loadResult = loadResult;
_dataTableLoadResult = dataTableLoadResult is not null
? dataTableLoadResult
: loadResult.BinaryDataTable?.SharedDependenciesTableWithBinaryDataTable?.FirstOrDefault() as MarkupLoadResult;
_dataTableLoadResult = dataTableLoadResult
?? loadResult.BinaryDataTable?.SharedDependenciesTableWithBinaryDataTable?.FirstOrDefault() as MarkupLoadResult;
_importedUris = new()
{
@@ -57,7 +57,7 @@ public class Disassembler
if (_loadResult.Status == LoadResultStatus.Error)
throw new Exception($"Failed to load '{_loadResult.ErrorContextUri}'");
if (_dataTableLoadResult is not null)
if (UseSharedDataTable)
{
_dataTableLoadResult.FullLoad();
if (_dataTableLoadResult.Status == LoadResultStatus.Error)
@@ -75,7 +75,7 @@ public class Disassembler
foreach (var segment in segments)
body.AddRange(segment);
if (_dataTableLoadResult is not null)
if (UseSharedDataTable)
body.Add(new SharedDataTableDirective(_dataTableLoadResult.Uri));
_program = new(body);
@@ -86,6 +86,9 @@ public class Disassembler
public string Write() => Disassemble().ToString();
[MemberNotNullWhen(true, nameof(_dataTableLoadResult))]
private bool UseSharedDataTable => _dataTableLoadResult is not null;
private IEnumerable<ExportDirective> GetExports()
{
foreach (var typeSchema in _loadResult.ExportTable)
@@ -148,6 +151,9 @@ public class Disassembler
private IEnumerable<IImportDirective> EnumerateImports()
{
if (UseSharedDataTable)
yield break;
// Ues _importedUris to keep track of what has already been imported.
// Skip self and default UIX namespace.
@@ -323,7 +329,7 @@ public class Disassembler
private IEnumerable<ConstantDirective> GetConstants()
{
if (_dataTableLoadResult is not null)
if (UseSharedDataTable)
{
// Constants have already been disassembled from the shared binary table
var asmConstants = _dataTableLoadResult is AsmMarkupLoadResult asmDataTableLoadResult
@@ -333,9 +339,9 @@ public class Disassembler
foreach (var info in EnumerateConstantInfo(_dataTableLoadResult))
{
var constantName = asmConstants?[info.Index]?.Name
?? $"sharedConst{info.Index:D}";
?? info.GenerateDefaultName();
_constantsTable.Add(info.Index, constantName);
_constantsTable[info.Index] = constantName;
}
yield break;
@@ -344,7 +350,7 @@ public class Disassembler
{
foreach (var info in EnumerateConstantInfo(_loadResult))
{
var constantName = $"const{info.Index:D}";
var constantName = info.GenerateDefaultName();
_constantsTable[info.Index] = constantName;
yield return EncodeConstant(info.Value, constantName, info.Type);
}
@@ -397,7 +403,7 @@ public class Disassembler
{
var qualifiedTypeName = GetQualifiedName(typeSchema);
// ILayout has a number of derived classes with special named instacnes,
// ILayout has a number of derived classes with special named instances,
// but aren't implemented as canonical instances.
if (constantValue is Layout.ILayout constantLayout && Layout.PredefinedLayouts.TryConvertToString(constantLayout, out var constantLayoutString))
{
@@ -456,5 +462,8 @@ public class Disassembler
throw new NotSupportedException($"Unable to encode constant value '{constantValue}' of type '{qualifiedTypeName}'");
}
private record RawConstantInfo(int Index, TypeSchema Type, object Value);
private record RawConstantInfo(int Index, TypeSchema Type, object Value)
{
public string GenerateDefaultName() => $"const{Index:D}";
}
}
+4
View File
@@ -9,6 +9,9 @@ public static class Extensions
{
public static void FullLoad(this LoadResult result)
{
if (result.Status is LoadResultStatus.Success)
return;
result.Load(LoadPass.DeclareTypes);
result.Load(LoadPass.PopulatePublicModel);
result.Load(LoadPass.Full);
@@ -73,6 +76,7 @@ public static class Extensions
'\t' => @"\t",
'\'' => @"\'",
'"' => "\"",
'\\' => @"\\",
_ => null
};
+42 -5
View File
@@ -3,6 +3,7 @@ using Sprache;
using System;
using System.Globalization;
using System.Linq;
using System.Text;
namespace Microsoft.Iris.Asm;
@@ -86,13 +87,49 @@ partial class Lexer
if (!encodingMarkerResult.WasSuccessful)
{
// Support defining constants from string literals
var stringLiteralResult = ExpressionInBraces(StringLiteral)(input);
input = stringLiteralResult.Remainder;
if (!stringLiteralResult.WasSuccessful)
return stringLiteralResult.ForType<IDirective>();
// Skip the opening brace
input = input.Advance();
if (input.Current != '"')
return Result.Failure<IDirective>(input, "Invalid constant", ["Expected a string literal."]);
input = input.Advance();
StringBuilder literalBuilder = new();
char c;
while (true)
{
c = input.Current;
if (c == '\\')
{
// https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/lexical-structure#unicode-character-escape-sequences
input = input.Advance();
c = input.Current switch
{
'0' => '\0',
'b' => '\b',
'n' => '\n',
'r' => '\r',
't' => '\t',
_ => input.Current
};
}
input = input.Advance();
if (c == '"')
break;
literalBuilder.Append(c);
}
if (input.Current != ')')
return Result.Failure<IDirective>(input, "Invalid constant", ["Missing closed brace."]);
input = input.Advance();
persistMode = Markup.MarkupConstantPersistMode.FromString;
content = stringLiteralResult.Value[1..^1].Unescape();
content = literalBuilder.ToString();
}
else
{
-6
View File
@@ -130,10 +130,4 @@ public static partial class Lexer
return Result.Success(qualifiedName, input);
}
private static Parser<string> ExpressionInBraces(Parser<string> parser, char open = '(', char close = ')') =>
from openBrace in Parse.Char(open).Token()
from expression in parser.Optional()
from closeBrace in Parse.Char(close).Token()
select expression.GetOrElse(string.Empty).Trim();
}
+19 -13
View File
@@ -27,23 +27,29 @@ public record Program
public Program(IEnumerable<IBodyItem> body)
{
Body = body.Cached();
Directives = body.OfType<IDirective>().Cached();
DataTableDirective = Directives.OfType<SharedDataTableDirective>().SingleOrDefault();
Imports = Directives.OfType<IImportDirective>().Cached();
Exports = Directives.OfType<ExportDirective>().Cached();
Code = body.OfType<ICodeItem>().Cached();
}
public IEnumerable<IBodyItem> Body { get; }
public IEnumerable<IBodyItem> Body { get; private set; }
public IEnumerable<IDirective> Directives { get; }
public SharedDataTableDirective DataTableDirective { get; }
public IEnumerable<IImportDirective> Imports { get; }
public IEnumerable<ExportDirective> Exports { get; }
public IEnumerable<IDirective> Directives => Body.OfType<IDirective>();
public IEnumerable<ICodeItem> Code { get; }
public SharedDataTableDirective DataTableDirective => Body.OfType<SharedDataTableDirective>().SingleOrDefault();
public IEnumerable<IImportDirective> Imports => Directives.OfType<IImportDirective>();
public IEnumerable<ExportDirective> Exports => Directives.OfType<ExportDirective>();
public IEnumerable<ICodeItem> Code => Body.OfType<ICodeItem>();
public void ImportSharedDataTable(Program dataTable)
{
List<IBodyItem> newBody = Exports.ToList<IBodyItem>();
newBody.AddRange(dataTable.Directives.Where(d => d is not ExportDirective));
newBody.AddRange(Code);
Body = newBody.Cached();
}
public override string ToString()
{