namespace Compiler; public sealed class TypeResolver(string fileName) { private readonly Dictionary structTypes = []; public List GetAllStructs() => structTypes.Values.ToList(); public NubTypeStruct? GetNamedStruct(string name) => structTypes.GetValueOrDefault(name); public static TypeResolver Create(string fileName, Ast ast, out List diagnostics) { diagnostics = []; var resolver = new TypeResolver(fileName); foreach (var structDef in ast.Structs) { if (resolver.structTypes.ContainsKey(structDef.Name.Ident)) { diagnostics.Add(Diagnostic.Error($"Duplicate struct: {structDef.Name.Ident}").At(fileName, structDef.Name).Build()); continue; } resolver.structTypes.Add(structDef.Name.Ident, new NubTypeStruct()); } foreach (var structDef in ast.Structs) { var structType = resolver.structTypes[structDef.Name.Ident]; try { structType.ResolveFields(structDef.Fields.Select(f => new NubTypeStruct.Field(f.Name.Ident, resolver.Resolve(f.Type))).ToList()); } catch (CompileException e) { diagnostics.Add(e.Diagnostic); } } return resolver; } public NubType Resolve(NodeType node) { return node switch { NodeTypeBool type => new NubTypeBool(), NodeTypeCustom type => ResolveStruct(type), NodeTypeFunc type => new NubTypeFunc(type.Parameters.Select(Resolve).ToList(), Resolve(type.ReturnType)), NodeTypePointer type => new NubTypePointer(Resolve(type.To)), NodeTypeSInt type => new NubTypeSInt(type.Width), NodeTypeUInt type => new NubTypeUInt(type.Width), NodeTypeString type => new NubTypeString(), NodeTypeVoid type => new NubTypeVoid(), _ => throw new ArgumentOutOfRangeException(nameof(node)) }; } private NubTypeStruct ResolveStruct(NodeTypeCustom type) { var structType = structTypes.GetValueOrDefault(type.Name.Ident); if (structType == null) throw new CompileException(Diagnostic.Error($"Unknown custom type: {type}").At(fileName, type).Build()); return structType; } }