From f5dcc0206f44b0904ee841dd653f2845ef34ec49 Mon Sep 17 00:00:00 2001 From: Yoshi Askharoun Date: Fri, 2 Feb 2024 23:26:55 -0600 Subject: [PATCH] Begin markup assembler --- libs/UIX.Asm/AsmMarkupLoadResult.cs | 95 +++++++++++++++++++ libs/UIX.Asm/AsmMarkupLoader.cs | 139 ++++++++++++++++++++++++++++ libs/UIX.Asm/Assembler.cs | 9 ++ 3 files changed, 243 insertions(+) create mode 100644 libs/UIX.Asm/AsmMarkupLoadResult.cs create mode 100644 libs/UIX.Asm/AsmMarkupLoader.cs create mode 100644 libs/UIX.Asm/Assembler.cs diff --git a/libs/UIX.Asm/AsmMarkupLoadResult.cs b/libs/UIX.Asm/AsmMarkupLoadResult.cs new file mode 100644 index 0000000..92adbda --- /dev/null +++ b/libs/UIX.Asm/AsmMarkupLoadResult.cs @@ -0,0 +1,95 @@ +using Microsoft.Iris.Data; +using Microsoft.Iris.Markup; +using Microsoft.Iris.Session; +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; +using System.Text; + +namespace Microsoft.Iris.Asm; + +[Serializable] +internal class AsmMarkupLoadResult : MarkupLoadResult +{ + private MarkupConstantsTable _constantsTable; + private MarkupImportTables _importTables; + private Resource _resource; + private AsmMarkupLoader _loader; + private bool _doneWithLoader; + + public AsmMarkupLoadResult(Resource resource, string uri) + : base(uri) + { + _resource = resource; + if (uri != resource.Uri) + _uriUnderlying = resource.Uri; + _loader = AsmMarkupLoader.Load(this, resource); + } + + public AsmMarkupLoadResult(string uri) + : base(uri) + { + } + + protected AsmMarkupLoadResult(SerializationInfo info, StreamingContext context) : base(info, context) + { + _constantsTable = info.GetValue(nameof(ConstantsTable)); + _importTables = info.GetValue(nameof(ImportTables)); + } + + public override bool IsSource => true; + + internal AsmMarkupLoader Loader => _loader; + + public override MarkupConstantsTable ConstantsTable => _constantsTable; + + public override MarkupImportTables ImportTables => _importTables; + + public override void Load(LoadPass currentPass) + { + if (_doneWithLoader) + return; + ErrorManager.EnterContext(ErrorContextUri); + _loader.Validate(currentPass); + ErrorManager.ExitContext(); + if (currentPass != LoadPass.Done) + return; + if (!MarkupSystem.TrackAdditionalMetadata) + _loader = null; + _doneWithLoader = true; + } + + public void ValidateType(MarkupTypeSchema typeSchema, LoadPass currentPass) + { + var loadData = typeSchema.LoadData; + if (loadData == null) + return; + ErrorManager.EnterContext(ErrorContextUri); + // TODO: loadData.Validate(currentPass); + ErrorManager.ExitContext(); + } + + public void ValidationComplete() + { + if (_resource != null) + { + _resource.Free(); + _resource = null; + } + if (Status == LoadResultStatus.Loading) + SetStatus(LoadResultStatus.Success); + foreach (MarkupTypeSchema markupTypeSchema in ExportTable) + markupTypeSchema.Seal(); + } + + public void SetConstantsTable(MarkupConstantsTable constantsTable) => _constantsTable = constantsTable; + + public void SetImportTables(MarkupImportTables importTables) => _importTables = importTables; + + public override void GetObjectData(SerializationInfo info, StreamingContext context) + { + base.GetObjectData(info, context); + + info.AddValue(nameof(_resource), _resource); + } +} diff --git a/libs/UIX.Asm/AsmMarkupLoader.cs b/libs/UIX.Asm/AsmMarkupLoader.cs new file mode 100644 index 0000000..a65e0a1 --- /dev/null +++ b/libs/UIX.Asm/AsmMarkupLoader.cs @@ -0,0 +1,139 @@ +using Microsoft.Iris.Asm.Models; +using Microsoft.Iris.Data; +using Microsoft.Iris.Markup; +using Microsoft.Iris.Session; +using Sprache; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; + +namespace Microsoft.Iris.Asm; + +internal class AsmMarkupLoader +{ + private string _asmSource; + private Program _program; + private bool _hasErrors; + private LoadPass _currentValidationPass; + private readonly AsmMarkupLoadResult _loadResult; + private bool _usingSharedBinaryDataTable; + private SourceMarkupImportTables _importTables; + private Dictionary _importedNamespaces = new(); + + protected AsmMarkupLoader(AsmMarkupLoadResult loadResult) => _loadResult = loadResult; + + internal static AsmMarkupLoader Load(AsmMarkupLoadResult loadResult, Resource resource) + { + AsmMarkupLoader owner = new(loadResult); + + if (resource.Status != ResourceStatus.Available) + throw new InvalidOperationException("Resource must be available for reading"); + + var data = new byte[resource.Length]; + Marshal.Copy(resource.Buffer, data, 0, (int)resource.Length); + owner._asmSource = Encoding.UTF8.GetString(data); + + var parseResult = Lexer.Program.TryParse(owner._asmSource); + if (parseResult.WasSuccessful) + owner._program = parseResult.Value; + else + owner.MarkHasErrors(); + return owner; + } + + public void MarkHasErrors() + { + if (_hasErrors) + return; + _hasErrors = true; + _loadResult.MarkLoadFailed(); + } + + public void Validate(LoadPass currentPass) + { + if (_currentValidationPass >= currentPass) + return; + _currentValidationPass = currentPass; + + if (_currentValidationPass == LoadPass.DeclareTypes) + { + if (_asmSource == null) + return; + + var parseResult = Lexer.Program.TryParse(_asmSource); + if (parseResult.WasSuccessful) + _program = parseResult.Value; + else + foreach (var errors in parseResult.Expectations) + ReportError(errors, -1, -1); + + if (_loadResult.BinaryDataTable != null) + { + _importTables = _loadResult.BinaryDataTable.SourceMarkupImportTables; + _usingSharedBinaryDataTable = true; + } + else + { + _importTables = new SourceMarkupImportTables(); + } + + foreach (var nsImport in _program.Imports.OfType()) + { + LoadResult loadResult; + if (nsImport.Uri == "Me") + loadResult = _loadResult; + else + loadResult = MarkupSystem.ResolveLoadResult(nsImport.Uri, _loadResult.IslandReferences); + + if (loadResult == null || loadResult is ErrorLoadResult) + ReportError($"Unable to load '{nsImport.Uri}' (xmlns prefix '{nsImport.Name}')", -1, -1); + else if (loadResult.Status == LoadResultStatus.Error) + MarkHasErrors(); + if (MarkupSystem.CompileMode) + loadResult.SetCompilerReferenceName(nsImport.Uri); + + if (loadResult != null) + { + _importedNamespaces[nsImport.Name] = loadResult; + //TrackImportedLoadResult(loadResult); + } + } + } + foreach (LoadResult loadResult in _importedNamespaces.Values) + { + if (loadResult != _loadResult && loadResult != MarkupSystem.UIXGlobal) + { + loadResult.Load(_currentValidationPass); + if (loadResult.Status == LoadResultStatus.Error) + MarkHasErrors(); + } + } + if (_program != null && currentPass != LoadPass.Done) + { + foreach (ValidateClass validateClass in _program.ClassList) + validateClass.Validate(_currentValidationPass); + foreach (ValidateDataMapping dataMapping in _program.DataMappingList) + dataMapping.Validate(_currentValidationPass); + foreach (ValidateAlias alias in _program.AliasList) + alias.Validate(_currentValidationPass); + if (_currentValidationPass == LoadPass.Full) + { + for (ValidateNamespace validateNamespace = _program.XmlnsList; validateNamespace != null; validateNamespace = validateNamespace.Next) + { + if (!_referencedNamespaces.ContainsKey(validateNamespace.Prefix)) + ErrorManager.ReportWarning(validateNamespace.Line, validateNamespace.Column, "Unreferenced namespace {0}", validateNamespace.Prefix); + } + } + } + + CompleteValidationPass(); + } + + public void ReportError(string error, int line, int column) + { + MarkHasErrors(); + ErrorManager.ReportError(line, column, error); + } +} \ No newline at end of file diff --git a/libs/UIX.Asm/Assembler.cs b/libs/UIX.Asm/Assembler.cs new file mode 100644 index 0000000..bbc5e67 --- /dev/null +++ b/libs/UIX.Asm/Assembler.cs @@ -0,0 +1,9 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Microsoft.Iris.Asm; + +public class Assembler +{ +}