This commit is contained in:
nub31
2026-02-24 21:51:36 +01:00
parent 35867ffa28
commit 3ebaa67b6d
4 changed files with 242 additions and 78 deletions

View File

@@ -191,7 +191,7 @@ public class ModuleGraph
return node switch
{
NodeTypeBool => NubTypeBool.Instance,
NodeTypeCustom type => ResolveCustomType(type, currentModule),
NodeTypeNamed type => ResolveNamedType(type, currentModule),
NodeTypeFunc type => NubTypeFunc.Get(type.Parameters.Select(x => ResolveType(x, currentModule)).ToList(), ResolveType(type.ReturnType, currentModule)),
NodeTypePointer type => NubTypePointer.Get(ResolveType(type.To, currentModule)),
NodeTypeSInt type => NubTypeSInt.Get(type.Width),
@@ -202,25 +202,103 @@ public class ModuleGraph
};
}
NubType ResolveCustomType(NodeTypeCustom type, string currentModule)
NubType ResolveNamedType(NodeTypeNamed type, string currentModule)
{
var module = modules.GetValueOrDefault(type.Module.Ident);
if (module == null)
throw new CompileException(Diagnostic.Error($"Unknown module: {type.Module.Ident}").Build());
var includePrivate = currentModule == type.Module.Ident;
if (!module.TryResolveType(type.Name.Ident, includePrivate, out var customType))
throw new CompileException(Diagnostic.Error($"Unknown custom type: {type.Module.Ident}::{type.Name.Ident}").Build());
return customType switch
return type.Sections.Count switch
{
Module.TypeInfoStruct => NubTypeStruct.Get(type.Module.Ident, type.Name.Ident),
Module.TypeInfoEnum => NubTypeEnum.Get(type.Module.Ident, type.Name.Ident),
_ => throw new ArgumentOutOfRangeException(nameof(customType))
3 => ResolveThreePartType(type.Sections[0], type.Sections[1], type.Sections[2], currentModule),
2 => ResolveTwoPartType(type.Sections[0], type.Sections[1], currentModule),
1 => ResolveOnePartType(type.Sections[0], currentModule),
_ => throw BasicError("Invalid type name")
};
}
NubType ResolveThreePartType(TokenIdent first, TokenIdent second, TokenIdent third, string currentModule)
{
var module = ResolveModule(first);
if (!module.TryResolveType(second.Ident, currentModule == module.Name, out var typeInfo))
throw BasicError($"Named type '{module.Name}::{second.Ident}' not found");
if (typeInfo is not Module.TypeInfoEnum enumInfo)
throw BasicError($"'{module.Name}::{second.Ident}' is not an enum");
var variant = enumInfo.Variants.FirstOrDefault(v => v.Name == third.Ident);
if (variant == null)
throw BasicError($"Enum '{module.Name}::{second.Ident}' does not have a variant named '{third.Ident}'");
return NubTypeEnumVariant.Get(NubTypeEnum.Get(module.Name, second.Ident), third.Ident);
}
NubType ResolveTwoPartType(TokenIdent first, TokenIdent second, string currentModule)
{
if (TryResolveEnumVariant(currentModule, first.Ident, second.Ident, out var variant))
return variant;
var module = ResolveModule(first);
if (!module.TryResolveType(second.Ident, currentModule == module.Name, out var typeInfo))
throw BasicError($"Named type '{module.Name}::{second.Ident}' not found");
return typeInfo switch
{
Module.TypeInfoStruct => NubTypeStruct.Get(module.Name, second.Ident),
Module.TypeInfoEnum => NubTypeEnum.Get(module.Name, second.Ident),
_ => throw new ArgumentOutOfRangeException(nameof(typeInfo))
};
}
NubType ResolveOnePartType(TokenIdent name, string currentModule)
{
if (!modules.TryGetValue(currentModule, out var module))
throw BasicError($"Module '{currentModule}' not found");
if (!module.TryResolveType(name.Ident, true, out var typeInfo))
throw BasicError($"Named type '{module.Name}::{name.Ident}' not found");
return typeInfo switch
{
Module.TypeInfoStruct => NubTypeStruct.Get(module.Name, name.Ident),
Module.TypeInfoEnum => NubTypeEnum.Get(module.Name, name.Ident),
_ => throw new ArgumentOutOfRangeException(nameof(typeInfo))
};
}
Module ResolveModule(TokenIdent name)
{
if (!modules.TryGetValue(name.Ident, out var module))
throw BasicError($"Module '{name.Ident}' not found");
return module;
}
bool TryResolveEnumVariant(string moduleName, string enumName, string variantName, [NotNullWhen(true)] out NubType? result)
{
result = null;
if (!modules.TryGetValue(moduleName, out var module))
return false;
if (!module.TryResolveType(enumName, true, out var typeInfo))
return false;
if (typeInfo is not Module.TypeInfoEnum enumInfo)
return false;
var variant = enumInfo.Variants.FirstOrDefault(v => v.Name == variantName);
if (variant == null)
return false;
result = NubTypeEnumVariant.Get(
NubTypeEnum.Get(moduleName, enumName),
variantName);
return true;
}
Exception BasicError(string message)
{
return new CompileException(Diagnostic.Error(message).Build());
}
Module GetOrCreateModule(string name)
{
if (!modules.TryGetValue(name, out var module))