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>()) foreach (var typeImport in Program.Imports.OfType<TypeImport>())
{ {
var typeSchema = ResolveTypeFromQualifiedName(typeImport.QualifiedName); var typeSchema = ResolveTypeFromQualifiedName(typeImport.QualifiedName);
_importTables.ImportedTypes.Add(typeSchema); TrackImportedType(typeSchema);
} }
foreach (var nsImport in Program.Imports.OfType<NamespaceImport>()) foreach (var nsImport in Program.Imports.OfType<NamespaceImport>())
@@ -215,7 +215,7 @@ internal class AsmMarkupLoader
foreach (var constant in Program.Body.OfType<ConstantDirective>()) foreach (var constant in Program.Body.OfType<ConstantDirective>())
{ {
object constantValue; object constantValue, persistData = null;
var constantTypeSchema = ResolveTypeFromQualifiedName(constant.TypeName); var constantTypeSchema = ResolveTypeFromQualifiedName(constant.TypeName);
if (constant is EncodedConstantDirective encodedConstant) 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); ReportError($"Failed to create an instance of '{constant.TypeName}' from '{encodedConstant.Content}'", constant);
continue; continue;
} }
persistData = encodedConstant.Content;
} }
else else
{ {
@@ -249,11 +251,18 @@ internal class AsmMarkupLoader
} }
} }
var mode = constantTypeSchema.SupportsBinaryEncoding MarkupConstantPersistMode mode;
? MarkupConstantPersistMode.Binary if (constantTypeSchema.SupportsBinaryEncoding)
: MarkupConstantPersistMode.FromString; {
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); _constants.Add(constant.Name, constantIndex);
} }
@@ -308,8 +317,30 @@ internal class AsmMarkupLoader
private LoadResult[] PrepareDependenciesTable() private LoadResult[] PrepareDependenciesTable()
{ {
// TODO LoadResult[] loadResultArray = LoadResult.EmptyList;
return []; 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() private MarkupDataMapping[] PrepareDataMappingTable()
+34
View File
@@ -131,6 +131,40 @@ public class Disassembler
yield return new TypeImport(new(namespacePrefix, typeImport.Name)); 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() public IEnumerable<ConstantDirective> GetConstants()
+67
View File
@@ -58,6 +58,73 @@ partial class Lexer
import = new TypeImport(typeNameResult.Value); import = new TypeImport(typeNameResult.Value);
break; 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: default:
return Result.Failure<IImportDirective>(input, $"Unknown import type '{importTypeResult.Value}'", ["Expected 'ns', 'type'"]); 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 public record NamespaceImport : ImportDirective
{ {
@@ -25,3 +28,54 @@ public record TypeImport : ImportDirective
public override string ToString() => $"{base.ToString()} {QualifiedName}"; 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 Text
.import-type Color .import-type Color
.import-type Font .import-type Font
.import-mbrs UI{Locals, Content}
.import-mbrs Text{Color, Content, Font}
.constant const0 = Color(255, 255, 0, 0) .constant const0 = Color(255, 255, 0, 0)
.constant const1 = String(Howdy from Microsoft.Iris!) .constant const1 = String(Howdy from Microsoft.Iris!)
@@ -35,8 +37,6 @@ public class Assembly(ITestOutputHelper output)
.constant const3 = Color(255, 0, 0, 255) .constant const3 = Color(255, 0, 0, 255)
.constant const4 = Font(JetBrains Mono) .constant const4 = Font(JetBrains Mono)
.constant const5 = String(This is some blue text) .constant const5 = String(This is some blue text)
.constant xmlTest = <FlowLayout Orientation="Vertical" Spacing="50,0" />
.section object .section object
Default_cont: Default_cont:
@@ -69,7 +69,7 @@ Alt_locl:
output.WriteLine(ast.ToString()); output.WriteLine(ast.ToString());
Assert.NotNull(ast); Assert.NotNull(ast);
Assert.Equal(19, ast.Directives.Count()); Assert.Equal(20, ast.Directives.Count());
Assert.Equal(24, ast.Code.Count()); Assert.Equal(24, ast.Code.Count());
} }