Add member imports to lexer, assembler, and disassembler

This commit is contained in:
Yoshi Askharoun
2024-02-16 20:37:47 -06:00
parent 6bc1880f2c
commit 772a0bf60b
5 changed files with 198 additions and 12 deletions
+39 -8
View File
@@ -161,7 +161,7 @@ internal class AsmMarkupLoader
foreach (var typeImport in Program.Imports.OfType<TypeImport>())
{
var typeSchema = ResolveTypeFromQualifiedName(typeImport.QualifiedName);
_importTables.ImportedTypes.Add(typeSchema);
TrackImportedType(typeSchema);
}
foreach (var nsImport in Program.Imports.OfType<NamespaceImport>())
@@ -215,7 +215,7 @@ internal class AsmMarkupLoader
foreach (var constant in Program.Body.OfType<ConstantDirective>())
{
object constantValue;
object constantValue, persistData = null;
var constantTypeSchema = ResolveTypeFromQualifiedName(constant.TypeName);
if (constant is EncodedConstantDirective encodedConstant)
@@ -226,6 +226,8 @@ internal class AsmMarkupLoader
ReportError($"Failed to create an instance of '{constant.TypeName}' from '{encodedConstant.Content}'", constant);
continue;
}
persistData = encodedConstant.Content;
}
else
{
@@ -249,11 +251,18 @@ internal class AsmMarkupLoader
}
}
var mode = constantTypeSchema.SupportsBinaryEncoding
? MarkupConstantPersistMode.Binary
: MarkupConstantPersistMode.FromString;
MarkupConstantPersistMode mode;
if (constantTypeSchema.SupportsBinaryEncoding)
{
mode = MarkupConstantPersistMode.Binary;
persistData = constantValue;
}
else
{
mode = MarkupConstantPersistMode.FromString;
}
var constantIndex = (ushort)constantsTable.Add(constantTypeSchema, constantValue, mode);
var constantIndex = (ushort)constantsTable.Add(constantTypeSchema, constantValue, mode, persistData);
_constants.Add(constant.Name, constantIndex);
}
@@ -308,8 +317,30 @@ internal class AsmMarkupLoader
private LoadResult[] PrepareDependenciesTable()
{
// TODO
return [];
LoadResult[] loadResultArray = LoadResult.EmptyList;
int length = 0;
if (_importTables != null)
{
foreach (LoadResult importedLoadResult in _importTables.ImportedLoadResults)
{
if (importedLoadResult != _loadResult)
++length;
}
}
if (length != 0)
{
loadResultArray = new LoadResult[length];
int index = 0;
foreach (LoadResult importedLoadResult in _importTables.ImportedLoadResults)
{
if (importedLoadResult != _loadResult)
{
loadResultArray[index] = importedLoadResult;
++index;
}
}
}
return loadResultArray;
}
private MarkupDataMapping[] PrepareDataMappingTable()
+34
View File
@@ -131,6 +131,40 @@ public class Disassembler
yield return new TypeImport(new(namespacePrefix, typeImport.Name));
};
foreach (var constructorImport in _loadResult.ImportTables.ConstructorImports)
{
var typeName = GetQualifiedName(constructorImport.Owner);
var parameterTypeNames = constructorImport.ParameterTypes.Select(GetQualifiedName);
yield return new ConstructorImport(typeName, parameterTypeNames);
}
foreach (var methodImport in _loadResult.ImportTables.MethodImports)
{
var typeName = GetQualifiedName(methodImport.Owner);
var parameterTypeNames = methodImport.ParameterTypes.Select(GetQualifiedName);
yield return new MethodImport(typeName, methodImport.Name, parameterTypeNames);
}
Dictionary<QualifiedTypeName, List<string>> namedMemberImports = new();
void GroupMemberImport(TypeSchema owner, string memberName)
{
var typeName = GetQualifiedName(owner);
if (!namedMemberImports.TryGetValue(typeName, out var currentTypeImports))
currentTypeImports = namedMemberImports[typeName] = new();
currentTypeImports.Add(memberName);
}
foreach (var propertyImport in _loadResult.ImportTables.PropertyImports)
GroupMemberImport(propertyImport.Owner, propertyImport.Name);
foreach (var eventImport in _loadResult.ImportTables.EventImports)
GroupMemberImport(eventImport.Owner, eventImport.Name);
foreach (var groupedImport in namedMemberImports)
yield return new NamedMemberImport(groupedImport.Key, groupedImport.Value);
}
public IEnumerable<ConstantDirective> GetConstants()
+67
View File
@@ -58,6 +58,73 @@ partial class Lexer
import = new TypeImport(typeNameResult.Value);
break;
case "MBRS":
input = ConsumeWhitespace(input);
var memberTypeNameResult = ParseQualifiedTypeName(input);
input = memberTypeNameResult.Remainder;
if (!memberTypeNameResult.WasSuccessful)
return Result.Failure<IImportDirective>(input, "Invalid member import", ["Expected qualified type name"]);
input = Parse.Char('{')(input).Remainder;
var memberNamesResult = Parse.Ref(() => Identifier).DelimitedBy(Parse.Char(',').Token())(input);
input = memberNamesResult.Remainder;
if (!memberNamesResult.WasSuccessful)
return Result.Failure<IImportDirective>(input, "Invalid member import", ["Expected list of members to import"]);
input = Parse.Char('}')(input).Remainder;
import = new NamedMemberImport(memberTypeNameResult.Value, memberNamesResult.Value);
break;
case "CTOR":
input = ConsumeWhitespace(input);
var ctorMemberTypeNameResult = ParseQualifiedTypeName(input);
input = ctorMemberTypeNameResult.Remainder;
if (!ctorMemberTypeNameResult.WasSuccessful)
return Result.Failure<IImportDirective>(input, "Invalid constructor import", ["Expected qualified type name"]);
input = Parse.Char('(')(input).Remainder;
var ctorParameterTypesResult = Parse.Ref(() => QualifiedTypeName).DelimitedBy(Parse.Char(',').Token())(input);
input = ctorParameterTypesResult.Remainder;
if (!ctorParameterTypesResult.WasSuccessful)
return Result.Failure<IImportDirective>(input, "Invalid constructor import", ["Expected constructor parameter types"]);
input = Parse.Char(')')(input).Remainder;
import = new ConstructorImport(ctorMemberTypeNameResult.Value, ctorParameterTypesResult.Value);
break;
case "MTHD":
input = ConsumeWhitespace(input);
var mthdMemberTypeNameResult = ParseQualifiedTypeName(input);
input = mthdMemberTypeNameResult.Remainder;
if (!mthdMemberTypeNameResult.WasSuccessful)
return Result.Failure<IImportDirective>(input, "Invalid method import", ["Expected qualified type name"]);
input = Parse.Char('.')(input).Remainder;
var mthdNameResult = Identifier(input);
input = mthdNameResult.Remainder;
if (!mthdNameResult.WasSuccessful)
return Result.Failure<IImportDirective>(input, "Invalid method import", ["Expected method name"]);
input = Parse.Char('(')(input).Remainder;
var mthdParameterTypesResult = Parse.Ref(() => QualifiedTypeName).DelimitedBy(Parse.Char(',').Token())(input);
input = mthdParameterTypesResult.Remainder;
if (!mthdParameterTypesResult.WasSuccessful)
return Result.Failure<IImportDirective>(input, "Invalid constructor import", ["Expected constructor parameter types"]);
input = Parse.Char(')')(input).Remainder;
import = new MethodImport(mthdMemberTypeNameResult.Value, mthdNameResult.Value, mthdParameterTypesResult.Value);
break;
default:
return Result.Failure<IImportDirective>(input, $"Unknown import type '{importTypeResult.Value}'", ["Expected 'ns', 'type'"]);
}
+55 -1
View File
@@ -1,4 +1,7 @@
namespace Microsoft.Iris.Asm.Models;
using System.Collections.Generic;
using System.Linq;
namespace Microsoft.Iris.Asm.Models;
public record NamespaceImport : ImportDirective
{
@@ -25,3 +28,54 @@ public record TypeImport : ImportDirective
public override string ToString() => $"{base.ToString()} {QualifiedName}";
}
/// <summary>
/// Imports many members that can be specified by solely their name.
/// </summary>
public record NamedMemberImport : ImportDirective
{
public NamedMemberImport(QualifiedTypeName qualifiedName, IEnumerable<string> memberNames) : base("mbrs")
{
QualifiedName = qualifiedName;
MemberNames = memberNames.ToList();
}
public QualifiedTypeName QualifiedName { get; init; }
public List<string> MemberNames { get; init; }
public override string ToString() => $"{base.ToString()} {QualifiedName}{{{string.Join(", ", MemberNames)}}}";
}
public record ConstructorImport : ImportDirective
{
public ConstructorImport(QualifiedTypeName qualifiedName, IEnumerable<QualifiedTypeName> parameterTypes) : base("ctor")
{
QualifiedName = qualifiedName;
ParameterTypes = parameterTypes.ToList();
}
public QualifiedTypeName QualifiedName { get; init; }
public IEnumerable<QualifiedTypeName> ParameterTypes { get; init; }
public override string ToString() => $"{base.ToString()} {QualifiedName}.({string.Join(", ", ParameterTypes)})";
}
public record MethodImport : ImportDirective
{
public MethodImport(QualifiedTypeName qualifiedName, string methodName, IEnumerable<QualifiedTypeName> parameterTypes) : base("mthd")
{
QualifiedName = qualifiedName;
MethodName = methodName;
ParameterTypes = parameterTypes.ToList();
}
public QualifiedTypeName QualifiedName { get; init; }
public string MethodName { get; init; }
public IEnumerable<QualifiedTypeName> ParameterTypes { get; init; }
public override string ToString() => $"{base.ToString()} {QualifiedName}.{MethodName}({string.Join(", ", ParameterTypes)})";
}
+3 -3
View File
@@ -28,6 +28,8 @@ public class Assembly(ITestOutputHelper output)
.import-type Text
.import-type Color
.import-type Font
.import-mbrs UI{Locals, Content}
.import-mbrs Text{Color, Content, Font}
.constant const0 = Color(255, 255, 0, 0)
.constant const1 = String(Howdy from Microsoft.Iris!)
@@ -35,8 +37,6 @@ public class Assembly(ITestOutputHelper output)
.constant const3 = Color(255, 0, 0, 255)
.constant const4 = Font(JetBrains Mono)
.constant const5 = String(This is some blue text)
.constant xmlTest = <FlowLayout Orientation="Vertical" Spacing="50,0" />
.section object
Default_cont:
@@ -69,7 +69,7 @@ Alt_locl:
output.WriteLine(ast.ToString());
Assert.NotNull(ast);
Assert.Equal(19, ast.Directives.Count());
Assert.Equal(20, ast.Directives.Count());
Assert.Equal(24, ast.Code.Count());
}