Type instancing

This commit is contained in:
nub31
2026-02-09 21:32:37 +01:00
parent 00a172b922
commit d409bb4d92
3 changed files with 137 additions and 128 deletions

View File

@@ -1,157 +1,165 @@
namespace Compiler;
public abstract class NubType : IEquatable<NubType>
public abstract class NubType
{
public abstract override string ToString();
public abstract bool Equals(NubType? other);
public override bool Equals(object? obj)
{
if (obj is NubType otherNubType)
{
return Equals(otherNubType);
}
return false;
}
public abstract override int GetHashCode();
public static bool operator ==(NubType? left, NubType? right) => Equals(left, right);
public static bool operator !=(NubType? left, NubType? right) => !Equals(left, right);
}
public sealed class NubTypeVoid : NubType
{
public override string ToString() => "void";
public static readonly NubTypeVoid Instance = new();
public override bool Equals(NubType? other) => other is NubTypeVoid;
public override int GetHashCode() => HashCode.Combine(typeof(NubTypeVoid));
private NubTypeVoid()
{
}
public override string ToString() => "void";
}
public sealed class NubTypeUInt(int width) : NubType
public sealed class NubTypeUInt : NubType
{
public readonly int Width = width;
private static readonly Dictionary<int, NubTypeUInt> Cache = new();
public static NubTypeUInt Get(int width)
{
if (!Cache.TryGetValue(width, out var type))
Cache[width] = type = new NubTypeUInt(width);
return type;
}
public int Width { get; }
private NubTypeUInt(int width)
{
Width = width;
}
public override string ToString() => $"u{Width}";
public override bool Equals(NubType? other) => other is NubTypeUInt otherUInt && Width == otherUInt.Width;
public override int GetHashCode() => HashCode.Combine(typeof(NubTypeUInt), Width);
}
public sealed class NubTypeSInt(int width) : NubType
public sealed class NubTypeSInt : NubType
{
public readonly int Width = width;
private static readonly Dictionary<int, NubTypeSInt> Cache = new();
public static NubTypeSInt Get(int width)
{
if (!Cache.TryGetValue(width, out var type))
Cache[width] = type = new NubTypeSInt(width);
return type;
}
public int Width { get; }
private NubTypeSInt(int width)
{
Width = width;
}
public override string ToString() => $"i{Width}";
public override bool Equals(NubType? other) => other is NubTypeSInt otherUInt && Width == otherUInt.Width;
public override int GetHashCode() => HashCode.Combine(typeof(NubTypeSInt), Width);
}
public sealed class NubTypeBool : NubType
{
public override string ToString() => "bool";
public static readonly NubTypeBool Instance = new();
public override bool Equals(NubType? other) => other is NubTypeBool;
public override int GetHashCode() => HashCode.Combine(typeof(NubTypeBool));
private NubTypeBool()
{
}
public override string ToString() => "bool";
}
public sealed class NubTypeString : NubType
{
public override string ToString() => "string";
public static readonly NubTypeString Instance = new();
public override bool Equals(NubType? other) => other is NubTypeString;
public override int GetHashCode() => HashCode.Combine(typeof(NubTypeString));
private NubTypeString()
{
}
public override string ToString() => "string";
}
public sealed class NubTypeStruct : NubType
{
private List<Field>? _resolvedFields;
public List<Field> Fields => _resolvedFields ?? throw new InvalidOperationException();
public string Name { get; }
public string Module { get; }
public void ResolveFields(List<Field> fields)
private IReadOnlyList<Field>? _resolvedFields;
public IReadOnlyList<Field> Fields => _resolvedFields ?? throw new InvalidOperationException();
public NubTypeStruct(string module, string name)
{
Module = module;
Name = name;
}
public void ResolveFields(IReadOnlyList<Field> fields)
{
if (_resolvedFields != null)
throw new InvalidOperationException($"{ToString()} already resolved");
throw new InvalidOperationException($"{Name} already resolved");
_resolvedFields = fields;
}
public override string ToString()
{
if (_resolvedFields == null)
return "struct <unresolved>";
return $"struct {{ {string.Join(' ', Fields.Select(f => $"{f.Name}: {f.Type}"))} }}";
}
public override bool Equals(NubType? other)
{
if (other is not NubTypeStruct structType)
return false;
if (Fields.Count != structType.Fields.Count)
return false;
for (var i = 0; i < Fields.Count; i++)
{
if (Fields[i].Name != structType.Fields[i].Name)
return false;
if (Fields[i].Type != structType.Fields[i].Type)
return false;
}
return true;
}
public override int GetHashCode()
{
var hash = new HashCode();
hash.Add(typeof(NubTypeStruct));
foreach (var field in Fields)
{
hash.Add(field.Name);
hash.Add(field.Type);
}
return hash.ToHashCode();
}
public override string ToString() => _resolvedFields == null ? $"struct {Module}::{Name} <unresolved>" : $"struct {Module}::{Name} {{ {string.Join(' ', Fields.Select(f => $"{f.Name}: {f.Type}"))} }}";
public sealed class Field(string name, NubType type)
{
public readonly string Name = name;
public readonly NubType Type = type;
public string Name { get; } = name;
public NubType Type { get; } = type;
}
}
public sealed class NubTypePointer(NubType to) : NubType
public sealed class NubTypePointer : NubType
{
public readonly NubType To = to;
public override string ToString() => $"^{To}";
private static readonly Dictionary<NubType, NubTypePointer> Cache = new();
public override bool Equals(NubType? other) => other is NubTypePointer pointer && To == pointer.To;
public override int GetHashCode() => HashCode.Combine(typeof(NubTypePointer));
public static NubTypePointer Get(NubType to)
{
if (!Cache.TryGetValue(to, out var ptr))
Cache[to] = ptr = new NubTypePointer(to);
return ptr;
}
public NubType To { get; }
private NubTypePointer(NubType to)
{
To = to;
}
public override string ToString() => $"^{To}";
}
public sealed class NubTypeFunc(List<NubType> parameters, NubType returnType) : NubType
public sealed class NubTypeFunc : NubType
{
public readonly List<NubType> Parameters = parameters;
public readonly NubType ReturnType = returnType;
private static readonly Dictionary<Signature, NubTypeFunc> Cache = new();
public static NubTypeFunc Get(List<NubType> parameters, NubType returnType)
{
var sig = new Signature(parameters, returnType);
if (!Cache.TryGetValue(sig, out var func))
Cache[sig] = func = new NubTypeFunc(parameters, returnType);
return func;
}
public IReadOnlyList<NubType> Parameters { get; }
public NubType ReturnType { get; }
private NubTypeFunc(List<NubType> parameters, NubType returnType)
{
Parameters = parameters;
ReturnType = returnType;
}
public override string ToString() => $"func({string.Join(' ', Parameters)}): {ReturnType}";
public override bool Equals(NubType? other) => other is NubTypeFunc func && ReturnType.Equals(func.ReturnType) && Parameters.SequenceEqual(func.Parameters);
public override int GetHashCode()
{
var hash = new HashCode();
hash.Add(typeof(NubTypeFunc));
hash.Add(ReturnType);
foreach (var param in Parameters)
hash.Add(param);
return hash.ToHashCode();
}
private readonly record struct Signature(IReadOnlyList<NubType> Parameters, NubType ReturnType);
}