Module system
This commit is contained in:
@@ -3,11 +3,11 @@ using NubLang.TypeChecking.Node;
|
||||
|
||||
namespace NubLang.TypeChecking;
|
||||
|
||||
public class ModuleSignature
|
||||
public class Module
|
||||
{
|
||||
public static IReadOnlyDictionary<string, ModuleSignature> CollectFromSyntaxTrees(IReadOnlyList<SyntaxTree> syntaxTrees)
|
||||
public static IReadOnlyDictionary<string, Module> CollectFromSyntaxTrees(IReadOnlyList<SyntaxTree> syntaxTrees)
|
||||
{
|
||||
var modules = new Dictionary<string, ModuleSignature>();
|
||||
var modules = new Dictionary<string, Module>();
|
||||
|
||||
foreach (var syntaxTree in syntaxTrees)
|
||||
{
|
||||
@@ -15,7 +15,7 @@ public class ModuleSignature
|
||||
|
||||
if (!modules.TryGetValue(moduleName, out var module))
|
||||
{
|
||||
module = new ModuleSignature();
|
||||
module = new Module();
|
||||
modules[moduleName] = module;
|
||||
}
|
||||
|
||||
@@ -25,11 +25,11 @@ public class ModuleSignature
|
||||
{
|
||||
case FuncSyntax funcDef:
|
||||
{
|
||||
var parameters = funcDef.Signature.Parameters.Select(p => TypeResolver.ResolveType(p.Type, modules)).ToList();
|
||||
var returnType = TypeResolver.ResolveType(funcDef.Signature.ReturnType, modules);
|
||||
var parameters = funcDef.Signature.Parameters.Select(p => ResolveType(p.Type)).ToList();
|
||||
var returnType = ResolveType(funcDef.Signature.ReturnType);
|
||||
|
||||
var type = new FuncTypeNode(parameters, returnType, funcDef.ExternSymbol);
|
||||
module._functions.Add(funcDef.Name, new ModuleMember<FuncTypeNode>(type, def.Exported));
|
||||
var type = new FuncTypeNode(parameters, returnType);
|
||||
module._functions.Add(new ModuleFuncType(def.Exported, funcDef.Name, funcDef.ExternSymbol, type));
|
||||
break;
|
||||
}
|
||||
case InterfaceSyntax interfaceDef:
|
||||
@@ -38,13 +38,13 @@ public class ModuleSignature
|
||||
for (var i = 0; i < interfaceDef.Functions.Count; i++)
|
||||
{
|
||||
var function = interfaceDef.Functions[i];
|
||||
var parameters = function.Signature.Parameters.Select(p => TypeResolver.ResolveType(p.Type, modules)).ToList();
|
||||
var returnType = TypeResolver.ResolveType(function.Signature.ReturnType, modules);
|
||||
var parameters = function.Signature.Parameters.Select(p => ResolveType(p.Type)).ToList();
|
||||
var returnType = ResolveType(function.Signature.ReturnType);
|
||||
functions.Add(new InterfaceTypeFunc(function.Name, new FuncTypeNode(parameters, returnType), i));
|
||||
}
|
||||
|
||||
var type = new InterfaceTypeNode(moduleName, interfaceDef.Name, functions);
|
||||
module._interfaces.Add(new ModuleMember<InterfaceTypeNode>(type, def.Exported));
|
||||
module._interfaces.Add(new ModuleInterfaceType(def.Exported, type));
|
||||
break;
|
||||
}
|
||||
case StructSyntax structDef:
|
||||
@@ -52,14 +52,14 @@ public class ModuleSignature
|
||||
var fields = new List<StructTypeField>();
|
||||
foreach (var field in structDef.Fields)
|
||||
{
|
||||
fields.Add(new StructTypeField(field.Name, TypeResolver.ResolveType(field.Type, modules), field.Index, field.Value.HasValue));
|
||||
fields.Add(new StructTypeField(field.Name, ResolveType(field.Type), field.Index, field.Value.HasValue));
|
||||
}
|
||||
|
||||
var functions = new List<StructTypeFunc>();
|
||||
foreach (var function in structDef.Functions)
|
||||
{
|
||||
var parameters = function.Signature.Parameters.Select(p => TypeResolver.ResolveType(p.Type, modules)).ToList();
|
||||
var returnType = TypeResolver.ResolveType(function.Signature.ReturnType, modules);
|
||||
var parameters = function.Signature.Parameters.Select(p => ResolveType(p.Type)).ToList();
|
||||
var returnType = ResolveType(function.Signature.ReturnType);
|
||||
functions.Add(new StructTypeFunc(function.Name, new FuncTypeNode(parameters, returnType)));
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ public class ModuleSignature
|
||||
throw new Exception("Interface implementation is not a custom type");
|
||||
}
|
||||
|
||||
var resolvedType = TypeResolver.ResolveCustomType(customType.Module, customType.Name, modules);
|
||||
var resolvedType = ResolveType(customType);
|
||||
if (resolvedType is not InterfaceTypeNode interfaceType)
|
||||
{
|
||||
throw new Exception("Interface implementation is not a interface");
|
||||
@@ -81,7 +81,7 @@ public class ModuleSignature
|
||||
}
|
||||
|
||||
var type = new StructTypeNode(moduleName, structDef.Name, fields, functions, interfaceImplementations);
|
||||
module._structs.Add(new ModuleMember<StructTypeNode>(type, def.Exported));
|
||||
module._structs.Add(new ModuleStructType(def.Exported, type));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -93,29 +93,97 @@ public class ModuleSignature
|
||||
}
|
||||
|
||||
return modules;
|
||||
}
|
||||
|
||||
private class ModuleMember<T>
|
||||
{
|
||||
public ModuleMember(T value, bool exported)
|
||||
TypeNode ResolveType(TypeSyntax type)
|
||||
{
|
||||
Value = value;
|
||||
Exported = exported;
|
||||
return type switch
|
||||
{
|
||||
BoolTypeSyntax => new BoolTypeNode(),
|
||||
CStringTypeSyntax => new CStringTypeNode(),
|
||||
IntTypeSyntax i => new IntTypeNode(i.Signed, i.Width),
|
||||
CustomTypeSyntax c => ResolveCustomType(c.Module, c.Name),
|
||||
FloatTypeSyntax f => new FloatTypeNode(f.Width),
|
||||
FuncTypeSyntax func => new FuncTypeNode(func.Parameters.Select(ResolveType).ToList(), ResolveType(func.ReturnType)),
|
||||
ArrayTypeSyntax arr => new ArrayTypeNode(ResolveType(arr.BaseType)),
|
||||
PointerTypeSyntax ptr => new PointerTypeNode(ResolveType(ptr.BaseType)),
|
||||
StringTypeSyntax => new StringTypeNode(),
|
||||
VoidTypeSyntax => new VoidTypeNode(),
|
||||
_ => throw new NotSupportedException($"Unknown type syntax: {type}")
|
||||
};
|
||||
}
|
||||
|
||||
public T Value { get; set; }
|
||||
public bool Exported { get; set; }
|
||||
TypeNode ResolveCustomType(string moduleName, string typeName)
|
||||
{
|
||||
if (!modules.TryGetValue(moduleName, out var module))
|
||||
{
|
||||
throw new Exception("Module not found: " + moduleName);
|
||||
}
|
||||
|
||||
var structType = module.AllStructTypes.FirstOrDefault(x => x.StructType.Name == typeName);
|
||||
if (structType != null)
|
||||
{
|
||||
return structType.StructType;
|
||||
}
|
||||
|
||||
var interfaceType = module.AllInterfaceTypes.FirstOrDefault(x => x.InterfaceType.Name == typeName);
|
||||
if (interfaceType != null)
|
||||
{
|
||||
return interfaceType.InterfaceType;
|
||||
}
|
||||
|
||||
throw new Exception($"Type {typeName} not found in module {moduleName}");
|
||||
}
|
||||
}
|
||||
|
||||
private readonly List<ModuleMember<StructTypeNode>> _structs = [];
|
||||
private readonly List<ModuleMember<InterfaceTypeNode>> _interfaces = [];
|
||||
private readonly Dictionary<string, ModuleMember<FuncTypeNode>> _functions = [];
|
||||
private readonly List<ModuleStructType> _structs = [];
|
||||
private readonly List<ModuleInterfaceType> _interfaces = [];
|
||||
private readonly List<ModuleFuncType> _functions = [];
|
||||
|
||||
public IReadOnlyList<StructTypeNode> ExportedStructTypes => _structs.Where(x => x.Exported).Select(x => x.Value).ToList();
|
||||
public IReadOnlyList<InterfaceTypeNode> ExportedInterfaceTypes => _interfaces.Where(x => x.Exported).Select(x => x.Value).ToList();
|
||||
public IReadOnlyDictionary<string, FuncTypeNode> ExportedFunctions => _functions.Where(x => x.Value.Exported).ToDictionary(x => x.Key, x => x.Value.Value);
|
||||
public IReadOnlyList<ModuleStructType> ExportedStructTypes => _structs.Where(x => x.Exported).ToList();
|
||||
public IReadOnlyList<ModuleInterfaceType> ExportedInterfaceTypes => _interfaces.Where(x => x.Exported).ToList();
|
||||
public IReadOnlyList<ModuleFuncType> ExportedFunctions => _functions.Where(x => x.Exported).ToList();
|
||||
|
||||
public IReadOnlyList<StructTypeNode> AllStructTypes => _structs.Select(x => x.Value).ToList();
|
||||
public IReadOnlyList<InterfaceTypeNode> AllInterfaceTypes => _interfaces.Select(x => x.Value).ToList();
|
||||
public IReadOnlyDictionary<string, FuncTypeNode> AllFunctions => _functions.ToDictionary(x => x.Key, x => x.Value.Value);
|
||||
public IReadOnlyList<ModuleStructType> AllStructTypes => _structs;
|
||||
public IReadOnlyList<ModuleInterfaceType> AllInterfaceTypes => _interfaces;
|
||||
public IReadOnlyList<ModuleFuncType> AllFunctions => _functions;
|
||||
}
|
||||
|
||||
public class ModuleStructType
|
||||
{
|
||||
public ModuleStructType(bool exported, StructTypeNode structType)
|
||||
{
|
||||
Exported = exported;
|
||||
StructType = structType;
|
||||
}
|
||||
|
||||
public bool Exported { get; }
|
||||
public StructTypeNode StructType { get; }
|
||||
}
|
||||
|
||||
public class ModuleInterfaceType
|
||||
{
|
||||
public ModuleInterfaceType(bool exported, InterfaceTypeNode interfaceType)
|
||||
{
|
||||
Exported = exported;
|
||||
InterfaceType = interfaceType;
|
||||
}
|
||||
|
||||
public bool Exported { get; }
|
||||
public InterfaceTypeNode InterfaceType { get; }
|
||||
}
|
||||
|
||||
public class ModuleFuncType
|
||||
{
|
||||
public ModuleFuncType(bool exported, string name, string? externSymbol, FuncTypeNode funcType)
|
||||
{
|
||||
Exported = exported;
|
||||
Name = name;
|
||||
ExternSymbol = externSymbol;
|
||||
FuncType = funcType;
|
||||
}
|
||||
|
||||
public bool Exported { get; }
|
||||
public string Name { get; }
|
||||
public string? ExternSymbol { get; }
|
||||
public FuncTypeNode FuncType { get; }
|
||||
}
|
||||
@@ -110,9 +110,8 @@ public class BoolTypeNode : SimpleTypeNode
|
||||
public override int GetHashCode() => HashCode.Combine(typeof(BoolTypeNode));
|
||||
}
|
||||
|
||||
public class FuncTypeNode(IReadOnlyList<TypeNode> parameters, TypeNode returnType, string? externSymbol = null) : SimpleTypeNode
|
||||
public class FuncTypeNode(IReadOnlyList<TypeNode> parameters, TypeNode returnType) : SimpleTypeNode
|
||||
{
|
||||
public string? ExternSymbol { get; } = externSymbol;
|
||||
public IReadOnlyList<TypeNode> Parameters { get; } = parameters;
|
||||
public TypeNode ReturnType { get; } = returnType;
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace NubLang.TypeChecking;
|
||||
public sealed class TypeChecker
|
||||
{
|
||||
private readonly SyntaxTree _syntaxTree;
|
||||
private readonly IReadOnlyDictionary<string, ModuleSignature> _moduleSignatures;
|
||||
private readonly IReadOnlyDictionary<string, Module> _importedModules;
|
||||
|
||||
private readonly Stack<Scope> _scopes = [];
|
||||
private readonly Stack<TypeNode> _funcReturnTypes = [];
|
||||
@@ -16,10 +16,10 @@ public sealed class TypeChecker
|
||||
|
||||
private Scope Scope => _scopes.Peek();
|
||||
|
||||
public TypeChecker(SyntaxTree syntaxTree, IReadOnlyDictionary<string, ModuleSignature> moduleSignatures)
|
||||
public TypeChecker(SyntaxTree syntaxTree, IReadOnlyDictionary<string, Module> moduleSignatures)
|
||||
{
|
||||
_syntaxTree = syntaxTree;
|
||||
_moduleSignatures = moduleSignatures.Where(x => syntaxTree.Metadata.Imports.Contains(x.Key) || _syntaxTree.Metadata.ModuleName == x.Key).ToDictionary();
|
||||
_importedModules = moduleSignatures.Where(x => syntaxTree.Metadata.Imports.Contains(x.Key) || _syntaxTree.Metadata.ModuleName == x.Key).ToDictionary();
|
||||
}
|
||||
|
||||
public IReadOnlyList<Diagnostic> GetDiagnostics() => _diagnostics;
|
||||
@@ -346,18 +346,43 @@ public sealed class TypeChecker
|
||||
}
|
||||
|
||||
// Second, look in the current module for a function matching the identifier
|
||||
var module = _moduleSignatures[_syntaxTree.Metadata.ModuleName];
|
||||
if (module.AllFunctions.TryGetValue(expression.Name, out var function))
|
||||
var module = _importedModules[_syntaxTree.Metadata.ModuleName];
|
||||
var function = module.AllFunctions.FirstOrDefault(x => x.Name == expression.Name);
|
||||
|
||||
if (function != null)
|
||||
{
|
||||
return new FuncIdentifierNode(function, _syntaxTree.Metadata.ModuleName, expression.Name);
|
||||
return new FuncIdentifierNode(function.FuncType, _syntaxTree.Metadata.ModuleName, expression.Name);
|
||||
}
|
||||
|
||||
throw new TypeCheckerException(Diagnostic.Error($"Identifier {expression.Name} not found").At(expression).Build());
|
||||
throw new TypeCheckerException(Diagnostic.Error($"Symbol {expression.Name} not found").At(expression).Build());
|
||||
}
|
||||
|
||||
private ExpressionNode CheckModuleIdentifier(ModuleIdentifierSyntax expression)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
if (!_importedModules.TryGetValue(expression.Module, out var module))
|
||||
{
|
||||
throw new TypeCheckerException(Diagnostic.Error($"Module {expression.Module} not found").WithHelp($"import \"{expression.Module}\"").At(expression).Build());
|
||||
}
|
||||
|
||||
// First, look for the exported function in the specified module (or all functions if current module)
|
||||
if (expression.Module == _syntaxTree.Metadata.ModuleName)
|
||||
{
|
||||
var function = module.AllFunctions.FirstOrDefault(x => x.Name == expression.Name);
|
||||
if (function != null)
|
||||
{
|
||||
return new FuncIdentifierNode(function.FuncType, expression.Module, expression.Name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var function = module.ExportedFunctions.FirstOrDefault(x => x.Name == expression.Name);
|
||||
if (function != null)
|
||||
{
|
||||
return new FuncIdentifierNode(function.FuncType, expression.Module, expression.Name);
|
||||
}
|
||||
}
|
||||
|
||||
throw new TypeCheckerException(Diagnostic.Error($"No exported symbol {expression.Name} not found in module {expression.Module}").At(expression).Build());
|
||||
}
|
||||
|
||||
private LiteralNode CheckLiteral(LiteralSyntax expression, TypeNode? expectedType)
|
||||
@@ -406,9 +431,61 @@ public sealed class TypeChecker
|
||||
return new BlockNode(statements);
|
||||
}
|
||||
|
||||
private TypeNode ResolveType(TypeSyntax fieldType)
|
||||
private TypeNode ResolveType(TypeSyntax type)
|
||||
{
|
||||
return TypeResolver.ResolveType(fieldType, _moduleSignatures);
|
||||
return type switch
|
||||
{
|
||||
BoolTypeSyntax => new BoolTypeNode(),
|
||||
CStringTypeSyntax => new CStringTypeNode(),
|
||||
IntTypeSyntax i => new IntTypeNode(i.Signed, i.Width),
|
||||
CustomTypeSyntax c => ResolveCustomType(c),
|
||||
FloatTypeSyntax f => new FloatTypeNode(f.Width),
|
||||
FuncTypeSyntax func => new FuncTypeNode(func.Parameters.Select(ResolveType).ToList(), ResolveType(func.ReturnType)),
|
||||
ArrayTypeSyntax arr => new ArrayTypeNode(ResolveType(arr.BaseType)),
|
||||
PointerTypeSyntax ptr => new PointerTypeNode(ResolveType(ptr.BaseType)),
|
||||
StringTypeSyntax => new StringTypeNode(),
|
||||
VoidTypeSyntax => new VoidTypeNode(),
|
||||
_ => throw new NotSupportedException($"Unknown type syntax: {type}")
|
||||
};
|
||||
}
|
||||
|
||||
private TypeNode ResolveCustomType(CustomTypeSyntax customType)
|
||||
{
|
||||
if (!_importedModules.TryGetValue(customType.Module, out var module))
|
||||
{
|
||||
throw new Exception("Module not found: " + customType.Module);
|
||||
}
|
||||
|
||||
if (customType.Module == _syntaxTree.Metadata.ModuleName)
|
||||
{
|
||||
var structType = module.AllStructTypes.FirstOrDefault(x => x.StructType.Name == customType.Name);
|
||||
if (structType != null)
|
||||
{
|
||||
return structType.StructType;
|
||||
}
|
||||
|
||||
var interfaceType = module.AllInterfaceTypes.FirstOrDefault(x => x.InterfaceType.Name == customType.Name);
|
||||
if (interfaceType != null)
|
||||
{
|
||||
return interfaceType.InterfaceType;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var structType = module.ExportedStructTypes.FirstOrDefault(x => x.StructType.Name == customType.Name);
|
||||
if (structType != null)
|
||||
{
|
||||
return structType.StructType;
|
||||
}
|
||||
|
||||
var interfaceType = module.ExportedInterfaceTypes.FirstOrDefault(x => x.InterfaceType.Name == customType.Name);
|
||||
if (interfaceType != null)
|
||||
{
|
||||
return interfaceType.InterfaceType;
|
||||
}
|
||||
}
|
||||
|
||||
throw new TypeCheckerException(Diagnostic.Error($"Type {customType.Name} not found in module {customType.Module}").At(customType).Build());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user