From bace846a2a1eb234061667d106f2ac51849b9f0f Mon Sep 17 00:00:00 2001 From: nub31 Date: Fri, 12 Sep 2025 17:06:45 +0200 Subject: [PATCH] ... --- .../NubLang/TypeChecking/Node/TypeNode.cs | 16 ++--- compiler/NubLang/TypeChecking/TypeChecker.cs | 68 ++++++++++++++----- 2 files changed, 59 insertions(+), 25 deletions(-) diff --git a/compiler/NubLang/TypeChecking/Node/TypeNode.cs b/compiler/NubLang/TypeChecking/Node/TypeNode.cs index 0e9135a..92bba75 100644 --- a/compiler/NubLang/TypeChecking/Node/TypeNode.cs +++ b/compiler/NubLang/TypeChecking/Node/TypeNode.cs @@ -110,9 +110,9 @@ public class BoolTypeNode : SimpleTypeNode public override int GetHashCode() => HashCode.Combine(typeof(BoolTypeNode)); } -public class FuncTypeNode(IReadOnlyList parameters, TypeNode returnType) : SimpleTypeNode +public class FuncTypeNode(List parameters, TypeNode returnType) : SimpleTypeNode { - public IReadOnlyList Parameters { get; } = parameters; + public List Parameters { get; } = parameters; public TypeNode ReturnType { get; } = returnType; public override StorageSize StorageSize => StorageSize.U64; @@ -187,13 +187,13 @@ public class StructTypeFunc(string name, FuncTypeNode type) public FuncTypeNode Type { get; } = type; } -public class StructTypeNode(string module, string name, IReadOnlyList fields, IReadOnlyList functions, IReadOnlyList interfaceImplementations) : ComplexTypeNode +public class StructTypeNode(string module, string name, List fields, List functions, List interfaceImplementations) : ComplexTypeNode { public string Module { get; } = module; public string Name { get; } = name; - public IReadOnlyList Fields { get; set; } = fields; - public IReadOnlyList Functions { get; set; } = functions; - public IReadOnlyList InterfaceImplementations { get; set; } = interfaceImplementations; + public List Fields { get; set; } = fields; + public List Functions { get; set; } = functions; + public List InterfaceImplementations { get; set; } = interfaceImplementations; public override string ToString() => Name; public override bool Equals(TypeNode? other) => other is StructTypeNode structType && Name == structType.Name && Module == structType.Module; @@ -207,11 +207,11 @@ public class InterfaceTypeFunc(string name, FuncTypeNode type, int index) public int Index { get; } = index; } -public class InterfaceTypeNode(string module, string name, IReadOnlyList functions) : ComplexTypeNode +public class InterfaceTypeNode(string module, string name, List functions) : ComplexTypeNode { public string Module { get; } = module; public string Name { get; } = name; - public IReadOnlyList Functions { get; set; } = functions; + public List Functions { get; set; } = functions; public override string ToString() => Name; public override bool Equals(TypeNode? other) => other is InterfaceTypeNode interfaceType && Name == interfaceType.Name && Module == interfaceType.Module; diff --git a/compiler/NubLang/TypeChecking/TypeChecker.cs b/compiler/NubLang/TypeChecking/TypeChecker.cs index 4863fb4..9ff860f 100644 --- a/compiler/NubLang/TypeChecking/TypeChecker.cs +++ b/compiler/NubLang/TypeChecking/TypeChecker.cs @@ -520,33 +520,67 @@ public sealed class TypeChecker }; } + private readonly Dictionary<(string Module, string Name), TypeNode> _typeCache = new(); + private readonly HashSet<(string Module, string Name)> _resolvingTypes = []; + private TypeNode ResolveCustomType(CustomTypeSyntax customType) { - if (!_visibleModules.TryGetValue(customType.Module, out var module)) + var key = (customType.Module, customType.Name); + + if (_typeCache.TryGetValue(key, out var cachedType)) { - throw new TypeCheckerException(Diagnostic.Error($"Module {customType.Module} not found").WithHelp($"import \"{customType.Module}\"").At(customType).Build()); + return cachedType; } - var includePrivate = customType.Module == _syntaxTree.Metadata.ModuleName; - - var structType = module.StructTypes(includePrivate).FirstOrDefault(x => x.Name == customType.Name); - if (structType != null) + if (!_resolvingTypes.Add(key)) { - var fields = structType.Fields.Select(x => new StructTypeField(x.Name, ResolveType(x.Type), x.HasDefaultValue)).ToList(); - var result = new StructTypeNode(customType.Module, structType.Name, fields, [], []); - _referencedStructTypes.Add(result); - return result; + var placeholder = new StructTypeNode(customType.Module, customType.Name, new List(), [], []); + _typeCache[key] = placeholder; + return placeholder; } - var interfaceType = module.InterfaceTypes(includePrivate).FirstOrDefault(x => x.Name == customType.Name); - if (interfaceType != null) + try { - var result = new InterfaceTypeNode(customType.Module, interfaceType.Name, []); - _referencedInterfaceTypes.AddRange(result); - return result; - } + if (!_visibleModules.TryGetValue(customType.Module, out var module)) + { + throw new TypeCheckerException(Diagnostic.Error($"Module {customType.Module} not found").WithHelp($"import \"{customType.Module}\"").At(customType).Build()); + } - throw new TypeCheckerException(Diagnostic.Error($"Type {customType.Name} not found in module {customType.Module}").At(customType).Build()); + var includePrivate = customType.Module == _syntaxTree.Metadata.ModuleName; + + var structType = module.StructTypes(includePrivate).FirstOrDefault(x => x.Name == customType.Name); + if (structType != null) + { + var result = new StructTypeNode(customType.Module, structType.Name, [], [], []); + _typeCache[key] = result; + + var fields = structType.Fields.Select(x => new StructTypeField(x.Name, ResolveType(x.Type), x.HasDefaultValue)).ToList(); + result.Fields.AddRange(fields); + + // todo(nub31): Functions and interface implementations + + _referencedStructTypes.Add(result); + return result; + } + + var interfaceType = module.InterfaceTypes(includePrivate).FirstOrDefault(x => x.Name == customType.Name); + if (interfaceType != null) + { + var result = new InterfaceTypeNode(customType.Module, interfaceType.Name, []); + _typeCache[key] = result; + + // todo(nub31): Put func resolution code here + + _referencedInterfaceTypes.AddRange(result); + return result; + } + + throw new TypeCheckerException(Diagnostic.Error($"Type {customType.Name} not found in module {customType.Module}").At(customType).Build()); + } + finally + { + _resolvingTypes.Remove(key); + } } }