Add section directives

This commit is contained in:
Yoshi Askharoun
2024-02-05 09:23:46 -06:00
parent 804bca823b
commit 5a0473e499
8 changed files with 192 additions and 27 deletions
+93 -14
View File
@@ -1,12 +1,12 @@
using Microsoft.Iris.Asm.Models;
using Microsoft.Iris.Data;
using Microsoft.Iris.Library;
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;
@@ -15,15 +15,18 @@ 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<string, LoadResult> _importedNamespaces = new();
private readonly Dictionary<string, LoadResult> _importedNamespaces = new();
private readonly HashSet<string> _referencedNamespaces = new();
protected AsmMarkupLoader(AsmMarkupLoadResult loadResult) => _loadResult = loadResult;
public bool HasErrors { get; protected set; }
internal static unsafe AsmMarkupLoader Load(AsmMarkupLoadResult loadResult, Resource resource)
{
AsmMarkupLoader owner = new(loadResult);
@@ -50,9 +53,10 @@ internal class AsmMarkupLoader
public void MarkHasErrors()
{
if (_hasErrors)
if (HasErrors)
return;
_hasErrors = true;
HasErrors = true;
_loadResult.MarkLoadFailed();
}
@@ -128,17 +132,87 @@ internal class AsmMarkupLoader
//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);
// }
//}
if (_currentValidationPass == LoadPass.Full)
{
foreach (var nsImport in _program.Imports.OfType<NamespaceImport>())
{
if (!_referencedNamespaces.Contains(nsImport.Name))
ErrorManager.ReportWarning(nsImport.Line, nsImport.Column, $"Unreferenced namespace '{nsImport.Name}'");
}
}
}
//CompleteValidationPass();
if (_currentValidationPass == LoadPass.DeclareTypes)
{
//_loadResult.SetExportTable(PrepareExportTable());
//_loadResult.SetAliasTable(PrepareAliasTable());
}
else if (_currentValidationPass == LoadPass.PopulatePublicModel)
{
if (_program == null)
return;
//foreach (ValidateClass validateClass in _parseResult.ClassList)
// validateClass.TypeExport?.BuildProperties();
}
else
{
if (_currentValidationPass != LoadPass.Full)
return;
if (HasErrors)
_loadResult.MarkLoadFailed();
MarkupImportTables importTables = null;
if (_importTables != null)
{
importTables = _importTables.PrepareImportTables();
_loadResult.SetImportTables(importTables);
}
MarkupLineNumberTable lineNumberTable = new MarkupLineNumberTable();
MarkupConstantsTable constantsTable = _loadResult.BinaryDataTable == null
? new MarkupConstantsTable()
: _loadResult.BinaryDataTable.ConstantsTable;
_loadResult.SetDataMappingsTable(PrepareDataMappingTable());
_loadResult.ValidationComplete();
ByteCodeReader reader = null;
if (!HasErrors)
EncodeOBJECTSection();
// reader = new MarkupEncoder(importTables, constantsTable, lineNumberTable).EncodeOBJECTSection(_parseResult, _loadResult.Uri, null);
if (!_usingSharedBinaryDataTable)
{
constantsTable.PrepareForRuntimeUse();
_loadResult.SetConstantsTable(constantsTable);
}
lineNumberTable.PrepareForRuntimeUse();
_loadResult.SetLineNumberTable(lineNumberTable);
if (reader != null)
_loadResult.SetObjectSection(reader);
_loadResult.SetDependenciesTable(PrepareDependenciesTable());
if (!MarkupSystem.TrackAdditionalMetadata)
_program = null;
//foreach (DisposableObject validateObject in _validateObjects)
// validateObject.Dispose(this);
}
}
private LoadResult[] PrepareDependenciesTable()
{
throw new NotImplementedException();
}
private MarkupDataMapping[] PrepareDataMappingTable()
{
throw new NotImplementedException();
}
public void ReportError(string error, int line, int column)
@@ -146,4 +220,9 @@ internal class AsmMarkupLoader
MarkHasErrors();
ErrorManager.ReportError(line, column, error);
}
private void EncodeOBJECTSection()
{
var instructions = _program.Body.OfType<Instruction>();
}
}
+2 -2
View File
@@ -39,7 +39,7 @@ public class Disassembler
if (scheme == "assembly")
{
// Assume the URI represents a C# namespace
name = uri.Split('.', '/', '\\')[^1];
name = uri.Split('.', '/', '\\', '!')[^1];
// Remove the extra assembly info
uri = uri.Split(',')[0];
@@ -48,7 +48,7 @@ public class Disassembler
{
// Assume the URI represents a file,
// skip the extension
name = uri.Split('.', '/', '\\')[^2];
name = uri.Split('.', '/', '\\', '!')[^2];
}
}
+14 -2
View File
@@ -13,9 +13,22 @@ partial class Lexer
var line = input.Line;
var column = input.Column;
var directiveResult = ParseDirective(input);
if (directiveResult.WasSuccessful)
{
input = directiveResult.Remainder;
var directive = directiveResult.Value;
if (directive is not IBodyItem directiveBodyItem)
return Result.Failure<IBodyItem>(input, "Invalid code", [$"The {directive.Identifier} directive cannot be placed in the body of a program"]);
directive.Line = line;
directive.Column = column;
return Result.Success(directiveBodyItem, input);
}
var identifierResult = Parse.Letter.AtLeastOnce().Text().Invoke(input);
if (!identifierResult.WasSuccessful)
return Result.Failure<Instruction>(input, "Invalid code", []);
return Result.Failure<IBodyItem>(input, "Invalid code", []);
input = identifierResult.Remainder;
var identifier = identifierResult.Value;
@@ -54,5 +67,4 @@ partial class Lexer
return Result.Success(bodyItem, input);
}
}
+52
View File
@@ -0,0 +1,52 @@
using Microsoft.Iris.Asm.Models;
using Sprache;
namespace Microsoft.Iris.Asm;
partial class Lexer
{
private static IResult<IDirective> ParseDirective(IInput input)
{
input = ConsumeWhitespace(input);
var line = input.Line;
var column = input.Column;
var directiveBeginResult = Parse.String(".")(input);
input = directiveBeginResult.Remainder;
if (!directiveBeginResult.WasSuccessful)
return Result.Failure<IDirective>(input, "Invalid directive", ["Expected '.', followed by an identifier"]);
var directiveIdResult = Parse.Letter.AtLeastOnce().Text()(input);
input = directiveIdResult.Remainder;
if (!directiveIdResult.WasSuccessful)
return Result.Failure<IDirective>(input, "Invalid directive", ["Expected an identifier"]);
IDirective directive;
switch (directiveIdResult.Value.ToUpperInvariant())
{
case "IMPORT":
return ParseImportAsDirective(input);
case "SECTION":
if (StatementEnd(input).WasSuccessful)
return Result.Failure<IImport>(input, "Invalid section directive", ["Expected a section name"]);
var sectionNameResult = Parse.Letter.AtLeastOnce().Token().Text()(input);
input = sectionNameResult.Remainder;
if (!sectionNameResult.WasSuccessful)
return Result.Failure<IImport>(input, "Invalid section name", ["Expected a section name containing only letters"]);
directive = new SectionDirective(sectionNameResult.Value)
{
Line = line,
Column = column,
};
break;
default:
return Result.Failure<IImport>(input, $"Unknown import type '{directiveIdResult.Value}'", ["Expected 'import' or 'section'"]);
}
return Result.Success(directive, input);
}
}
+10 -1
View File
@@ -9,11 +9,20 @@ partial class Lexer
{
input = ConsumeWhitespace(input);
var importDirectiveResult = Parse.String(".import-")(input);
var importDirectiveResult = Parse.String(".import")(input);
input = importDirectiveResult.Remainder;
if (!importDirectiveResult.WasSuccessful)
return Result.Failure<IImport>(input, "Invalid import directive", ["Expected '.import'"]);
return ParseImportAsDirective(input);
}
private static IResult<IImport> ParseImportAsDirective(IInput input)
{
if (input.Current != '-' || input.AtEnd)
return Result.Failure<IImport>(input, "Invalid import type", ["An import type must be specified"]);
input = input.Advance();
var importTypeResult = Parse.Letter.AtLeastOnce().Text()(input);
input = importTypeResult.Remainder;
if (!importTypeResult.WasSuccessful)
+2 -5
View File
@@ -12,13 +12,10 @@ public static partial class Lexer
public static readonly Parser<string> StatementEnd = Parse.Char(';').Return(";").Or(Parse.LineTerminator);
public static readonly Parser<string> SectionDirective =
from _ in Parse.String(".section").Token()
from sectionId in Parse.Letter.AtLeastOnce().Text()
select sectionId;
public static readonly Parser<IImport> Import = ParseImport;
public static readonly Parser<IDirective> Directive = ParseDirective;
public static readonly Parser<IBodyItem> BodyItem = ParseBodyItem;
public static readonly Parser<Program> Program =
+13
View File
@@ -0,0 +1,13 @@
namespace Microsoft.Iris.Asm.Models;
public record SectionDirective : Directive, IBodyItem
{
public SectionDirective(string name) : base("section")
{
Name = name;
}
public string Name { get; init; }
public override string ToString() => $"{base.ToString()} {Name}";
}
+4 -1
View File
@@ -18,6 +18,9 @@ public class Assembly(ITestOutputHelper output)
.import-ns Me as me
.import-ns assembly://UIX/Microsoft.Iris as iris
.section data
.section object
main:
COBJ 2
PSHC 0
@@ -34,7 +37,7 @@ main:
Assert.NotNull(ast);
Assert.Equal(2, ast.Imports.Count());
Assert.Equal(9, ast.Body.Count());
Assert.Equal(9 + 2, ast.Body.Count());
}
[Fact]