...
This commit is contained in:
@@ -1,8 +1,8 @@
|
|||||||
CC = clang
|
CC = gcc
|
||||||
NUBC = ../src/compiler/NubLang.CLI/bin/Debug/net9.0/nubc
|
NUBC = ../src/compiler/NubLang.CLI/bin/Debug/net9.0/nubc
|
||||||
|
|
||||||
.build/out: .build/out.a
|
.build/out: .build/out.a
|
||||||
$(CC) -g -o .build/out .build/out.a
|
$(CC) -ffreestanding -g -o .build/out .build/out.a
|
||||||
|
|
||||||
.build/out.a: $(NUBC) src/main.nub
|
.build/out.a: $(NUBC) src/main.nub
|
||||||
$(NUBC) src/main.nub
|
$(NUBC) src/main.nub
|
||||||
|
|||||||
@@ -13,4 +13,11 @@
|
|||||||
<ProjectReference Include="..\NubLang\NubLang.csproj" />
|
<ProjectReference Include="..\NubLang\NubLang.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Remove="assets\runtime.o" />
|
||||||
|
<EmbeddedResource Include="assets\runtime.o" />
|
||||||
|
<None Remove="assets\x64.o" />
|
||||||
|
<EmbeddedResource Include="assets\x64.o" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using NubLang.CLI;
|
using System.Reflection;
|
||||||
|
using NubLang.CLI;
|
||||||
using NubLang.Code;
|
using NubLang.Code;
|
||||||
using NubLang.Diagnostics;
|
using NubLang.Diagnostics;
|
||||||
using NubLang.Generation.QBE;
|
using NubLang.Generation.QBE;
|
||||||
@@ -6,6 +7,7 @@ using NubLang.Parsing;
|
|||||||
using NubLang.Parsing.Syntax;
|
using NubLang.Parsing.Syntax;
|
||||||
using NubLang.Tokenization;
|
using NubLang.Tokenization;
|
||||||
using NubLang.TypeChecking;
|
using NubLang.TypeChecking;
|
||||||
|
using Module = NubLang.TypeChecking.Module;
|
||||||
|
|
||||||
var options = new Options();
|
var options = new Options();
|
||||||
|
|
||||||
@@ -120,6 +122,38 @@ for (var i = 0; i < typedModules.Count; i++)
|
|||||||
objectFiles.Add(objFilePath);
|
objectFiles.Add(objFilePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var resources = Assembly.GetExecutingAssembly().GetManifestResourceNames();
|
||||||
|
|
||||||
|
string[] runtimeObjects = ["runtime.o", "x64.o"];
|
||||||
|
|
||||||
|
foreach (var runtimeObject in runtimeObjects)
|
||||||
|
{
|
||||||
|
var runtime = resources.First(r => r.EndsWith(runtimeObject));
|
||||||
|
|
||||||
|
await using var reader = Assembly
|
||||||
|
.GetExecutingAssembly()
|
||||||
|
.GetManifestResourceStream(runtime);
|
||||||
|
|
||||||
|
if (reader == null)
|
||||||
|
{
|
||||||
|
Console.Error.WriteLine($"Cannot open read stream to '{runtimeObject}'");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
var runtimePath = Path.Combine(".build", "runtime", runtimeObject);
|
||||||
|
var runtimeDir = Path.GetDirectoryName(runtimePath);
|
||||||
|
if (!string.IsNullOrEmpty(runtimeDir))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(runtimeDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
await using var writer = new FileStream(runtimePath, FileMode.Create);
|
||||||
|
|
||||||
|
reader.CopyTo(writer);
|
||||||
|
|
||||||
|
objectFiles.Add(runtimePath);
|
||||||
|
}
|
||||||
|
|
||||||
var outPath = options.OutputPath ?? Path.Combine(".build", "out.a");
|
var outPath = options.OutputPath ?? Path.Combine(".build", "out.a");
|
||||||
var outDir = Path.GetDirectoryName(outPath);
|
var outDir = Path.GetDirectoryName(outPath);
|
||||||
if (!string.IsNullOrEmpty(outDir))
|
if (!string.IsNullOrEmpty(outDir))
|
||||||
|
|||||||
BIN
src/compiler/NubLang.CLI/assets/runtime.o
Normal file
BIN
src/compiler/NubLang.CLI/assets/runtime.o
Normal file
Binary file not shown.
BIN
src/compiler/NubLang.CLI/assets/x64.o
Normal file
BIN
src/compiler/NubLang.CLI/assets/x64.o
Normal file
Binary file not shown.
@@ -11,7 +11,7 @@ public class QBEGenerator
|
|||||||
{
|
{
|
||||||
private readonly QBEWriter _writer;
|
private readonly QBEWriter _writer;
|
||||||
private readonly TypedModule _module;
|
private readonly TypedModule _module;
|
||||||
private readonly IReadOnlyList<ModuleSignature> _moduleSignatures;
|
private readonly IReadOnlyDictionary<string, ModuleSignature> _moduleSignatures;
|
||||||
|
|
||||||
private readonly List<CStringLiteral> _cStringLiterals = [];
|
private readonly List<CStringLiteral> _cStringLiterals = [];
|
||||||
private readonly List<StringLiteral> _stringLiterals = [];
|
private readonly List<StringLiteral> _stringLiterals = [];
|
||||||
@@ -23,7 +23,7 @@ public class QBEGenerator
|
|||||||
private int _stringLiteralIndex;
|
private int _stringLiteralIndex;
|
||||||
private bool _codeIsReachable = true;
|
private bool _codeIsReachable = true;
|
||||||
|
|
||||||
public QBEGenerator(TypedModule module, IReadOnlyList<ModuleSignature> moduleSignatures)
|
public QBEGenerator(TypedModule module, IReadOnlyDictionary<string, ModuleSignature> moduleSignatures)
|
||||||
{
|
{
|
||||||
_module = module;
|
_module = module;
|
||||||
_moduleSignatures = moduleSignatures;
|
_moduleSignatures = moduleSignatures;
|
||||||
@@ -42,11 +42,11 @@ public class QBEGenerator
|
|||||||
_stringLiteralIndex = 0;
|
_stringLiteralIndex = 0;
|
||||||
_codeIsReachable = true;
|
_codeIsReachable = true;
|
||||||
|
|
||||||
foreach (var moduleSignature in _moduleSignatures)
|
foreach (var (module, signature) in _moduleSignatures)
|
||||||
{
|
{
|
||||||
foreach (var structType in moduleSignature.Symbols.Values.OfType<StructTypeNode>())
|
foreach (var structType in signature.StructTypes)
|
||||||
{
|
{
|
||||||
EmitStructType(moduleSignature.Name, structType);
|
EmitStructType(module, structType);
|
||||||
_writer.NewLine();
|
_writer.NewLine();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -384,7 +384,7 @@ public class QBEGenerator
|
|||||||
_writer.Write(FuncQBETypeName(funcDef.Signature.ReturnType) + ' ');
|
_writer.Write(FuncQBETypeName(funcDef.Signature.ReturnType) + ' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
_writer.Write(LocalFuncName(_module.Name, funcDef));
|
_writer.Write(LocalFuncName(_module.Name, funcDef.Name));
|
||||||
|
|
||||||
_writer.Write("(");
|
_writer.Write("(");
|
||||||
foreach (var parameter in funcDef.Signature.Parameters)
|
foreach (var parameter in funcDef.Signature.Parameters)
|
||||||
@@ -408,15 +408,17 @@ public class QBEGenerator
|
|||||||
|
|
||||||
private void EmitStructDefinition(StructNode structDef)
|
private void EmitStructDefinition(StructNode structDef)
|
||||||
{
|
{
|
||||||
_writer.WriteLine($"export function {StructCtorName(_module.Name, structDef.Name)}() {{");
|
var type = TypeResolver.ResolveStructType(_module.Name, structDef.Name, _moduleSignatures);
|
||||||
_writer.WriteLine("@start");
|
|
||||||
_writer.Indented($"%struct =l alloc8 {SizeOf(structDef.)}");
|
|
||||||
_writer.Indented("ret %struct");
|
|
||||||
_writer.WriteLine("}");
|
|
||||||
|
|
||||||
for (var i = 0; i < structDef.Functions.Count; i++)
|
// _writer.WriteLine($"export function {StructCtorName(_module.Name, structDef.Name)}() {{");
|
||||||
|
// _writer.WriteLine("@start");
|
||||||
|
// _writer.Indented($"%struct =l alloc8 {SizeOf(type)}");
|
||||||
|
// // todo(nub31): Finish constructor
|
||||||
|
// _writer.Indented("ret %struct");
|
||||||
|
// _writer.WriteLine("}");
|
||||||
|
|
||||||
|
foreach (var function in structDef.Functions)
|
||||||
{
|
{
|
||||||
var function = structDef.Functions[i];
|
|
||||||
_labelIndex = 0;
|
_labelIndex = 0;
|
||||||
_tmpIndex = 0;
|
_tmpIndex = 0;
|
||||||
|
|
||||||
@@ -457,7 +459,7 @@ public class QBEGenerator
|
|||||||
|
|
||||||
foreach (var field in structType.Fields)
|
foreach (var field in structType.Fields)
|
||||||
{
|
{
|
||||||
_writer.Indented($"{StructDefQBEType(field)},");
|
_writer.Indented($"{StructDefQBEType(field.Type)},");
|
||||||
}
|
}
|
||||||
|
|
||||||
_writer.WriteLine("}");
|
_writer.WriteLine("}");
|
||||||
@@ -479,9 +481,9 @@ public class QBEGenerator
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (complexType is StructTypeNode structType)
|
if (complexType is StructTypeNode childStructType)
|
||||||
{
|
{
|
||||||
return StructTypeName(structType.Module, structType.Name);
|
return StructTypeName(childStructType.Module, childStructType.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
return "l";
|
return "l";
|
||||||
@@ -642,7 +644,9 @@ public class QBEGenerator
|
|||||||
ConvertToInterfaceNode convertToInterface => EmitConvertToInterface(convertToInterface),
|
ConvertToInterfaceNode convertToInterface => EmitConvertToInterface(convertToInterface),
|
||||||
ConvertIntNode convertInt => EmitConvertInt(convertInt),
|
ConvertIntNode convertInt => EmitConvertInt(convertInt),
|
||||||
ConvertFloatNode convertFloat => EmitConvertFloat(convertFloat),
|
ConvertFloatNode convertFloat => EmitConvertFloat(convertFloat),
|
||||||
VariableIdentifierNode identifier => EmitIdentifier(identifier),
|
VariableIdentifierNode identifier => EmitVariableIdentifier(identifier),
|
||||||
|
FuncIdentifierNode funcIdentifier => EmitFuncIdentifier(funcIdentifier),
|
||||||
|
FuncParameterIdentifierNode funcParameterIdentifier => EmitParameterFuncIdentifier(funcParameterIdentifier),
|
||||||
LiteralNode literal => EmitLiteral(literal),
|
LiteralNode literal => EmitLiteral(literal),
|
||||||
UnaryExpressionNode unaryExpression => EmitUnaryExpression(unaryExpression),
|
UnaryExpressionNode unaryExpression => EmitUnaryExpression(unaryExpression),
|
||||||
StructFieldAccessNode structFieldAccess => EmitStructFieldAccess(structFieldAccess),
|
StructFieldAccessNode structFieldAccess => EmitStructFieldAccess(structFieldAccess),
|
||||||
@@ -652,9 +656,24 @@ public class QBEGenerator
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private string EmitIdentifier(VariableIdentifierNode variableIdentifier)
|
private string EmitFuncIdentifier(FuncIdentifierNode localFuncIdent)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
// todo(nub31): Support for extern funcs
|
||||||
|
return LocalFuncName(localFuncIdent.Module, localFuncIdent.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string EmitVariableIdentifier(VariableIdentifierNode variableIdent)
|
||||||
|
{
|
||||||
|
var address = EmitAddressOfVariableIdent(variableIdent);
|
||||||
|
|
||||||
|
return variableIdent.Type.IsSimpleType(out _, out _)
|
||||||
|
? EmitLoad(variableIdent.Type, address)
|
||||||
|
: address;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string EmitParameterFuncIdentifier(FuncParameterIdentifierNode funcParameterIdent)
|
||||||
|
{
|
||||||
|
return "%" + funcParameterIdent.Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string EmitArrayIndexAccess(ArrayIndexAccessNode arrayIndexAccess)
|
private string EmitArrayIndexAccess(ArrayIndexAccessNode arrayIndexAccess)
|
||||||
@@ -710,43 +729,43 @@ public class QBEGenerator
|
|||||||
{
|
{
|
||||||
return addressOf switch
|
return addressOf switch
|
||||||
{
|
{
|
||||||
// ArrayIndexAccessNode arrayIndexAccess => EmitAddressOfArrayIndexAccess(arrayIndexAccess),
|
ArrayIndexAccessNode arrayIndexAccess => EmitAddressOfArrayIndexAccess(arrayIndexAccess),
|
||||||
// StructFieldAccessNode structFieldAccess => EmitAddressOfStructFieldAccess(structFieldAccess),
|
StructFieldAccessNode structFieldAccess => EmitAddressOfStructFieldAccess(structFieldAccess),
|
||||||
// VariableIdentNode variableIdent => EmitAddressOfVariableIdent(variableIdent),
|
VariableIdentifierNode variableIdent => EmitAddressOfVariableIdent(variableIdent),
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(addressOf))
|
_ => throw new ArgumentOutOfRangeException(nameof(addressOf))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// private string EmitAddressOfArrayIndexAccess(ArrayIndexAccessNode arrayIndexAccess)
|
private string EmitAddressOfArrayIndexAccess(ArrayIndexAccessNode arrayIndexAccess)
|
||||||
// {
|
{
|
||||||
// var array = EmitExpression(arrayIndexAccess.Target);
|
var array = EmitExpression(arrayIndexAccess.Target);
|
||||||
// var index = EmitExpression(arrayIndexAccess.Index);
|
var index = EmitExpression(arrayIndexAccess.Index);
|
||||||
//
|
|
||||||
// var elementType = ((ArrayTypeNode)arrayIndexAccess.Target.Type).ElementType;
|
var elementType = ((ArrayTypeNode)arrayIndexAccess.Target.Type).ElementType;
|
||||||
//
|
|
||||||
// var offset = TmpName();
|
var offset = TmpName();
|
||||||
// _writer.Indented($"{offset} =l mul {index}, {SizeOf(elementType)}");
|
_writer.Indented($"{offset} =l mul {index}, {SizeOf(elementType)}");
|
||||||
// _writer.Indented($"{offset} =l add {offset}, 8");
|
_writer.Indented($"{offset} =l add {offset}, 8");
|
||||||
// _writer.Indented($"{offset} =l add {array}, {offset}");
|
_writer.Indented($"{offset} =l add {array}, {offset}");
|
||||||
// return offset;
|
return offset;
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// private string EmitAddressOfStructFieldAccess(StructFieldAccessNode structFieldAccess)
|
private string EmitAddressOfStructFieldAccess(StructFieldAccessNode structFieldAccess)
|
||||||
// {
|
{
|
||||||
// var target = EmitExpression(structFieldAccess.Target);
|
var target = EmitExpression(structFieldAccess.Target);
|
||||||
//
|
|
||||||
// var structDef = _definitionTable.LookupStruct(structFieldAccess.StructType.Name);
|
var structType = TypeResolver.ResolveStructType(structFieldAccess.StructType.Module, structFieldAccess.StructType.Name, _moduleSignatures);
|
||||||
// var offset = OffsetOf(structDef, structFieldAccess.Field);
|
var offset = OffsetOf(structType, structFieldAccess.Field);
|
||||||
//
|
|
||||||
// var address = TmpName();
|
var address = TmpName();
|
||||||
// _writer.Indented($"{address} =l add {target}, {offset}");
|
_writer.Indented($"{address} =l add {target}, {offset}");
|
||||||
// return address;
|
return address;
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// private string EmitAddressOfVariableIdent(VariableIdentNode variableIdent)
|
private string EmitAddressOfVariableIdent(VariableIdentifierNode variableIdent)
|
||||||
// {
|
{
|
||||||
// return "%" + variableIdent.Name;
|
return "%" + variableIdent.Name;
|
||||||
// }
|
}
|
||||||
|
|
||||||
private string EmitBinaryExpression(BinaryExpressionNode binaryExpression)
|
private string EmitBinaryExpression(BinaryExpressionNode binaryExpression)
|
||||||
{
|
{
|
||||||
@@ -1006,21 +1025,11 @@ public class QBEGenerator
|
|||||||
var size = SizeOf(structInitializer.StructType);
|
var size = SizeOf(structInitializer.StructType);
|
||||||
_writer.Indented($"{destination} =l alloc8 {size}");
|
_writer.Indented($"{destination} =l alloc8 {size}");
|
||||||
|
|
||||||
foreach (var field in structInitializer.StructType.Fields)
|
foreach (var (field, value) in structInitializer.Initializers)
|
||||||
{
|
{
|
||||||
if (!structInitializer.Initializers.TryGetValue(field.Name, out var valueExpression))
|
|
||||||
{
|
|
||||||
valueExpression = field.Value.Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (valueExpression == null)
|
|
||||||
{
|
|
||||||
throw new UnreachableException("Value of field in uninitialized. This should have been caught in the type checker");
|
|
||||||
}
|
|
||||||
|
|
||||||
var offset = TmpName();
|
var offset = TmpName();
|
||||||
_writer.Indented($"{offset} =l add {destination}, {OffsetOf(structDef, field.Name)}");
|
_writer.Indented($"{offset} =l add {destination}, {OffsetOf(structInitializer.StructType, field)}");
|
||||||
EmitCopyInto(valueExpression, offset);
|
EmitCopyInto(value, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
return destination;
|
return destination;
|
||||||
@@ -1086,8 +1095,7 @@ public class QBEGenerator
|
|||||||
|
|
||||||
private string EmitStructFuncCall(StructFuncCallNode structFuncCall)
|
private string EmitStructFuncCall(StructFuncCallNode structFuncCall)
|
||||||
{
|
{
|
||||||
var structDef = _definitionTable.LookupStruct(structFuncCall.StructType.Name);
|
var func = StructFuncName(structFuncCall.StructType.Module, structFuncCall.StructType.Name, structFuncCall.Name);
|
||||||
var func = StructFuncName(structDef.Name, structFuncCall.Name);
|
|
||||||
|
|
||||||
var thisParameter = EmitExpression(structFuncCall.StructExpression);
|
var thisParameter = EmitExpression(structFuncCall.StructExpression);
|
||||||
|
|
||||||
@@ -1116,8 +1124,7 @@ public class QBEGenerator
|
|||||||
{
|
{
|
||||||
var target = EmitExpression(interfaceFuncCall.InterfaceExpression);
|
var target = EmitExpression(interfaceFuncCall.InterfaceExpression);
|
||||||
|
|
||||||
var interfaceDef = _definitionTable.LookupInterface(interfaceFuncCall.InterfaceType.Name);
|
var functionIndex = interfaceFuncCall.InterfaceType.Functions.ToList().FindIndex(x => x.Name == interfaceFuncCall.Name);
|
||||||
var functionIndex = interfaceDef.Functions.ToList().FindIndex(x => x.Name == interfaceFuncCall.Name);
|
|
||||||
var offset = functionIndex * 8;
|
var offset = functionIndex * 8;
|
||||||
|
|
||||||
var vtable = TmpName();
|
var vtable = TmpName();
|
||||||
@@ -1173,7 +1180,7 @@ public class QBEGenerator
|
|||||||
_writer.Indented($"{destination} =l alloc8 {SizeOf(convertToInterface.InterfaceType)}");
|
_writer.Indented($"{destination} =l alloc8 {SizeOf(convertToInterface.InterfaceType)}");
|
||||||
|
|
||||||
var interfaceVtablePointer = TmpName();
|
var interfaceVtablePointer = TmpName();
|
||||||
_writer.Indented($"{interfaceVtablePointer} =l add {StructVtableName(convertToInterface.StructType.Name)}, {vtableOffset}");
|
_writer.Indented($"{interfaceVtablePointer} =l add {StructVtableName(convertToInterface.StructType.Module, convertToInterface.StructType.Name)}, {vtableOffset}");
|
||||||
_writer.Indented($"storel {interfaceVtablePointer}, {destination}");
|
_writer.Indented($"storel {interfaceVtablePointer}, {destination}");
|
||||||
|
|
||||||
var objectPointer = TmpName();
|
var objectPointer = TmpName();
|
||||||
@@ -1287,11 +1294,13 @@ public class QBEGenerator
|
|||||||
{
|
{
|
||||||
var offset = 0;
|
var offset = 0;
|
||||||
|
|
||||||
|
var fields = new List<TypeNode>(structType.Fields.Count);
|
||||||
|
|
||||||
foreach (var field in structType.Fields)
|
foreach (var field in structType.Fields)
|
||||||
{
|
{
|
||||||
var fieldAlignment = AlignmentOf(field);
|
var fieldAlignment = AlignmentOf(field.Type);
|
||||||
offset = AlignTo(offset, fieldAlignment);
|
offset = AlignTo(offset, fieldAlignment);
|
||||||
offset += SizeOf(field);
|
offset += SizeOf(field.Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
var structAlignment = CalculateStructAlignment(structType);
|
var structAlignment = CalculateStructAlignment(structType);
|
||||||
@@ -1331,7 +1340,7 @@ public class QBEGenerator
|
|||||||
|
|
||||||
foreach (var field in structType.Fields)
|
foreach (var field in structType.Fields)
|
||||||
{
|
{
|
||||||
var fieldAlignment = AlignmentOf(field);
|
var fieldAlignment = AlignmentOf(field.Type);
|
||||||
maxAlignment = Math.Max(maxAlignment, fieldAlignment);
|
maxAlignment = Math.Max(maxAlignment, fieldAlignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1343,7 +1352,7 @@ public class QBEGenerator
|
|||||||
return (offset + alignment - 1) & ~(alignment - 1);
|
return (offset + alignment - 1) & ~(alignment - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int OffsetOf(StructNode structDef, string member)
|
private static int OffsetOf(StructTypeNode structDef, string member)
|
||||||
{
|
{
|
||||||
var offset = 0;
|
var offset = 0;
|
||||||
|
|
||||||
@@ -1385,9 +1394,9 @@ public class QBEGenerator
|
|||||||
return $"$string{++_stringLiteralIndex}";
|
return $"$string{++_stringLiteralIndex}";
|
||||||
}
|
}
|
||||||
|
|
||||||
private string LocalFuncName(string module, LocalFuncNode funcDef)
|
private string LocalFuncName(string module, string name)
|
||||||
{
|
{
|
||||||
return $"${module}.{funcDef.Name}";
|
return $"${module}.{name}";
|
||||||
}
|
}
|
||||||
|
|
||||||
private string ExternFuncName(ExternFuncNode funcDef)
|
private string ExternFuncName(ExternFuncNode funcDef)
|
||||||
|
|||||||
@@ -107,12 +107,13 @@ public class ModuleSignature
|
|||||||
}
|
}
|
||||||
case InterfaceSyntax interfaceDef:
|
case InterfaceSyntax interfaceDef:
|
||||||
{
|
{
|
||||||
var functions = new Dictionary<string, FuncTypeNode>();
|
var functions = new List<InterfaceTypeFunc>();
|
||||||
foreach (var function in interfaceDef.Functions)
|
for (var i = 0; i < interfaceDef.Functions.Count; i++)
|
||||||
{
|
{
|
||||||
|
var function = interfaceDef.Functions[i];
|
||||||
var parameters = function.Signature.Parameters.Select(p => TypeResolver.ResolveType(p.Type, modules)).ToList();
|
var parameters = function.Signature.Parameters.Select(p => TypeResolver.ResolveType(p.Type, modules)).ToList();
|
||||||
var returnType = TypeResolver.ResolveType(function.Signature.ReturnType, modules);
|
var returnType = TypeResolver.ResolveType(function.Signature.ReturnType, modules);
|
||||||
functions.Add(function.Name, new FuncTypeNode(parameters, returnType));
|
functions.Add(new InterfaceTypeFunc(function.Name, new FuncTypeNode(parameters, returnType), i));
|
||||||
}
|
}
|
||||||
|
|
||||||
var type = new InterfaceTypeNode(moduleName, interfaceDef.Name, functions);
|
var type = new InterfaceTypeNode(moduleName, interfaceDef.Name, functions);
|
||||||
@@ -121,14 +122,18 @@ public class ModuleSignature
|
|||||||
}
|
}
|
||||||
case StructSyntax structDef:
|
case StructSyntax structDef:
|
||||||
{
|
{
|
||||||
var fields = structDef.Fields.Select(x => new StructTypeField(x.Name, TypeResolver.ResolveType(x.Type, modules), x.Value.HasValue)).ToList();
|
var fields = new List<StructTypeField>();
|
||||||
|
foreach (var field in structDef.Fields)
|
||||||
|
{
|
||||||
|
fields.Add(new StructTypeField(field.Name, TypeResolver.ResolveType(field.Type, modules), field.Index, field.Value.HasValue));
|
||||||
|
}
|
||||||
|
|
||||||
var functions = new Dictionary<string, FuncTypeNode>();
|
var functions = new List<StructTypeFunc>();
|
||||||
foreach (var function in structDef.Functions)
|
foreach (var function in structDef.Functions)
|
||||||
{
|
{
|
||||||
var parameters = function.Signature.Parameters.Select(p => TypeResolver.ResolveType(p.Type, modules)).ToList();
|
var parameters = function.Signature.Parameters.Select(p => TypeResolver.ResolveType(p.Type, modules)).ToList();
|
||||||
var returnType = TypeResolver.ResolveType(function.Signature.ReturnType, modules);
|
var returnType = TypeResolver.ResolveType(function.Signature.ReturnType, modules);
|
||||||
functions.Add(function.Name, new FuncTypeNode(parameters, returnType));
|
functions.Add(new StructTypeFunc(function.Name, new FuncTypeNode(parameters, returnType)));
|
||||||
}
|
}
|
||||||
|
|
||||||
var interfaceImplementations = new List<InterfaceTypeNode>();
|
var interfaceImplementations = new List<InterfaceTypeNode>();
|
||||||
|
|||||||
@@ -174,19 +174,26 @@ public class StringTypeNode : ComplexTypeNode
|
|||||||
public override int GetHashCode() => HashCode.Combine(typeof(StringTypeNode));
|
public override int GetHashCode() => HashCode.Combine(typeof(StringTypeNode));
|
||||||
}
|
}
|
||||||
|
|
||||||
public class StructTypeField(string name, TypeNode type, bool hasDefaultValue)
|
public class StructTypeField(string name, TypeNode type, int index, bool hasDefaultValue)
|
||||||
{
|
{
|
||||||
public string Name { get; } = name;
|
public string Name { get; } = name;
|
||||||
public TypeNode Type { get; } = type;
|
public TypeNode Type { get; } = type;
|
||||||
|
public int Index { get; } = index;
|
||||||
public bool HasDefaultValue { get; } = hasDefaultValue;
|
public bool HasDefaultValue { get; } = hasDefaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class StructTypeNode(string module, string name, IReadOnlyList<StructTypeField> fields, IReadOnlyDictionary<string, FuncTypeNode> functions, IReadOnlyList<InterfaceTypeNode> interfaceImplementations) : ComplexTypeNode
|
public class StructTypeFunc(string name, FuncTypeNode type)
|
||||||
|
{
|
||||||
|
public string Name { get; } = name;
|
||||||
|
public FuncTypeNode Type { get; } = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class StructTypeNode(string module, string name, IReadOnlyList<StructTypeField> fields, IReadOnlyList<StructTypeFunc> functions, IReadOnlyList<InterfaceTypeNode> interfaceImplementations) : ComplexTypeNode
|
||||||
{
|
{
|
||||||
public string Module { get; } = module;
|
public string Module { get; } = module;
|
||||||
public string Name { get; } = name;
|
public string Name { get; } = name;
|
||||||
public IReadOnlyList<StructTypeField> Fields { get; set; } = fields;
|
public IReadOnlyList<StructTypeField> Fields { get; set; } = fields;
|
||||||
public IReadOnlyDictionary<string, FuncTypeNode> Functions { get; set; } = functions;
|
public IReadOnlyList<StructTypeFunc> Functions { get; set; } = functions;
|
||||||
public IReadOnlyList<InterfaceTypeNode> InterfaceImplementations { get; set; } = interfaceImplementations;
|
public IReadOnlyList<InterfaceTypeNode> InterfaceImplementations { get; set; } = interfaceImplementations;
|
||||||
|
|
||||||
public override string ToString() => Name;
|
public override string ToString() => Name;
|
||||||
@@ -194,11 +201,18 @@ public class StructTypeNode(string module, string name, IReadOnlyList<StructType
|
|||||||
public override int GetHashCode() => HashCode.Combine(typeof(StructTypeNode), Name);
|
public override int GetHashCode() => HashCode.Combine(typeof(StructTypeNode), Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class InterfaceTypeNode(string module, string name, IReadOnlyDictionary<string, FuncTypeNode> functions) : ComplexTypeNode
|
public class InterfaceTypeFunc(string name, FuncTypeNode type, int index)
|
||||||
|
{
|
||||||
|
public string Name { get; } = name;
|
||||||
|
public FuncTypeNode Type { get; } = type;
|
||||||
|
public int Index { get; } = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class InterfaceTypeNode(string module, string name, IReadOnlyList<InterfaceTypeFunc> functions) : ComplexTypeNode
|
||||||
{
|
{
|
||||||
public string Module { get; } = module;
|
public string Module { get; } = module;
|
||||||
public string Name { get; } = name;
|
public string Name { get; } = name;
|
||||||
public IReadOnlyDictionary<string, FuncTypeNode> Functions { get; set; } = functions;
|
public IReadOnlyList<InterfaceTypeFunc> Functions { get; set; } = functions;
|
||||||
|
|
||||||
public override string ToString() => Name;
|
public override string ToString() => Name;
|
||||||
public override bool Equals(TypeNode? other) => other is InterfaceTypeNode interfaceType && Name == interfaceType.Name && Module == interfaceType.Module;
|
public override bool Equals(TypeNode? other) => other is InterfaceTypeNode interfaceType && Name == interfaceType.Name && Module == interfaceType.Module;
|
||||||
|
|||||||
@@ -43,6 +43,38 @@ public static class TypeResolver
|
|||||||
return interfaceType;
|
return interfaceType;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Exception("Type not found: " + typeName);
|
throw new Exception($"Type {typeName} not found in module {moduleName}");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static StructTypeNode ResolveStructType(string moduleName, string structName, IReadOnlyDictionary<string, ModuleSignature> modules)
|
||||||
|
{
|
||||||
|
if (!modules.TryGetValue(moduleName, out var module))
|
||||||
|
{
|
||||||
|
throw new Exception("Module not found: " + moduleName);
|
||||||
|
}
|
||||||
|
|
||||||
|
var structType = module.StructTypes.FirstOrDefault(x => x.Name == structName);
|
||||||
|
if (structType != null)
|
||||||
|
{
|
||||||
|
return structType;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Exception($"Struct type {structName} not found in module {moduleName}");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static InterfaceTypeNode ResolveInterfaceType(string moduleName, string structName, IReadOnlyDictionary<string, ModuleSignature> modules)
|
||||||
|
{
|
||||||
|
if (!modules.TryGetValue(moduleName, out var module))
|
||||||
|
{
|
||||||
|
throw new Exception("Module not found: " + moduleName);
|
||||||
|
}
|
||||||
|
|
||||||
|
var structType = module.InterfaceTypes.FirstOrDefault(x => x.Name == structName);
|
||||||
|
if (structType != null)
|
||||||
|
{
|
||||||
|
return structType;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Exception($"Interface type {structName} not found in module {moduleName}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user