This commit is contained in:
nub31
2025-09-12 17:06:45 +02:00
parent 387ac34137
commit fcccf0d51e
2 changed files with 59 additions and 25 deletions

View File

@@ -110,9 +110,9 @@ public class BoolTypeNode : SimpleTypeNode
public override int GetHashCode() => HashCode.Combine(typeof(BoolTypeNode)); public override int GetHashCode() => HashCode.Combine(typeof(BoolTypeNode));
} }
public class FuncTypeNode(IReadOnlyList<TypeNode> parameters, TypeNode returnType) : SimpleTypeNode public class FuncTypeNode(List<TypeNode> parameters, TypeNode returnType) : SimpleTypeNode
{ {
public IReadOnlyList<TypeNode> Parameters { get; } = parameters; public List<TypeNode> Parameters { get; } = parameters;
public TypeNode ReturnType { get; } = returnType; public TypeNode ReturnType { get; } = returnType;
public override StorageSize StorageSize => StorageSize.U64; public override StorageSize StorageSize => StorageSize.U64;
@@ -187,13 +187,13 @@ public class StructTypeFunc(string name, FuncTypeNode type)
public FuncTypeNode Type { get; } = type; public FuncTypeNode Type { get; } = type;
} }
public class StructTypeNode(string module, string name, IReadOnlyList<StructTypeField> fields, IReadOnlyList<StructTypeFunc> functions, IReadOnlyList<InterfaceTypeNode> interfaceImplementations) : ComplexTypeNode public class StructTypeNode(string module, string name, List<StructTypeField> fields, List<StructTypeFunc> functions, List<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 List<StructTypeField> Fields { get; set; } = fields;
public IReadOnlyList<StructTypeFunc> Functions { get; set; } = functions; public List<StructTypeFunc> Functions { get; set; } = functions;
public IReadOnlyList<InterfaceTypeNode> InterfaceImplementations { get; set; } = interfaceImplementations; public List<InterfaceTypeNode> InterfaceImplementations { get; set; } = interfaceImplementations;
public override string ToString() => Name; public override string ToString() => Name;
public override bool Equals(TypeNode? other) => other is StructTypeNode structType && Name == structType.Name && Module == structType.Module; 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 int Index { get; } = index;
} }
public class InterfaceTypeNode(string module, string name, IReadOnlyList<InterfaceTypeFunc> functions) : ComplexTypeNode public class InterfaceTypeNode(string module, string name, List<InterfaceTypeFunc> functions) : ComplexTypeNode
{ {
public string Module { get; } = module; public string Module { get; } = module;
public string Name { get; } = name; public string Name { get; } = name;
public IReadOnlyList<InterfaceTypeFunc> Functions { get; set; } = functions; public List<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;

View File

@@ -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) 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; if (!_resolvingTypes.Add(key))
var structType = module.StructTypes(includePrivate).FirstOrDefault(x => x.Name == customType.Name);
if (structType != null)
{ {
var fields = structType.Fields.Select(x => new StructTypeField(x.Name, ResolveType(x.Type), x.HasDefaultValue)).ToList(); var placeholder = new StructTypeNode(customType.Module, customType.Name, new List<StructTypeField>(), [], []);
var result = new StructTypeNode(customType.Module, structType.Name, fields, [], []); _typeCache[key] = placeholder;
_referencedStructTypes.Add(result); return placeholder;
return result;
} }
var interfaceType = module.InterfaceTypes(includePrivate).FirstOrDefault(x => x.Name == customType.Name); try
if (interfaceType != null)
{ {
var result = new InterfaceTypeNode(customType.Module, interfaceType.Name, []); if (!_visibleModules.TryGetValue(customType.Module, out var module))
_referencedInterfaceTypes.AddRange(result); {
return result; 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);
}
} }
} }