This commit is contained in:
nub31
2025-09-12 17:06:45 +02:00
parent ef1720195d
commit bace846a2a
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 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 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<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 Name { get; } = name;
public IReadOnlyList<StructTypeField> Fields { get; set; } = fields;
public IReadOnlyList<StructTypeFunc> Functions { get; set; } = functions;
public IReadOnlyList<InterfaceTypeNode> InterfaceImplementations { get; set; } = interfaceImplementations;
public List<StructTypeField> Fields { get; set; } = fields;
public List<StructTypeFunc> Functions { get; set; } = functions;
public List<InterfaceTypeNode> 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<InterfaceTypeFunc> functions) : ComplexTypeNode
public class InterfaceTypeNode(string module, string name, List<InterfaceTypeFunc> functions) : ComplexTypeNode
{
public string Module { get; } = module;
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 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)
{
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<StructTypeField>(), [], []);
_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);
}
}
}