This commit is contained in:
nub31
2025-09-11 21:50:49 +02:00
parent 7903cfa254
commit 2af3782e32
11 changed files with 80 additions and 178 deletions

View File

@@ -3,66 +3,6 @@ using NubLang.TypeChecking.Node;
namespace NubLang.TypeChecking;
public class Module
{
public static IReadOnlyList<Module> CollectFromSyntaxTrees(IReadOnlyList<SyntaxTree> syntaxTrees)
{
var modules = new Dictionary<string, Module>();
foreach (var syntaxTree in syntaxTrees)
{
var name = syntaxTree.Metadata.ModuleName;
if (name == null)
{
continue;
}
if (!modules.TryGetValue(name, out var module))
{
module = new Module(name, syntaxTree.Metadata.Imports);
modules[name] = module;
}
foreach (var definition in syntaxTree.Definitions)
{
module.AddDefinition(definition);
}
}
return modules.Values.ToList();
}
private readonly List<DefinitionSyntax> _definitions = [];
public Module(string name, IReadOnlyList<string> imports)
{
Name = name;
Imports = imports;
}
public string Name { get; }
public IReadOnlyList<string> Imports { get; }
public IReadOnlyList<DefinitionSyntax> Definitions => _definitions;
private void AddDefinition(DefinitionSyntax syntax)
{
_definitions.Add(syntax);
}
}
public class TypedModule
{
public TypedModule(string name, IReadOnlyList<DefinitionNode> definitions)
{
Name = name;
Definitions = definitions;
}
public string Name { get; }
public IReadOnlyList<DefinitionNode> Definitions { get; }
}
public class ModuleSignature
{
public static IReadOnlyDictionary<string, ModuleSignature> CollectFromSyntaxTrees(IReadOnlyList<SyntaxTree> syntaxTrees)
@@ -72,10 +12,6 @@ public class ModuleSignature
foreach (var syntaxTree in syntaxTrees)
{
var moduleName = syntaxTree.Metadata.ModuleName;
if (moduleName == null)
{
continue;
}
if (!modules.TryGetValue(moduleName, out var module))
{
@@ -85,7 +21,7 @@ public class ModuleSignature
foreach (var def in syntaxTree.Definitions)
{
if (!def.Exported) continue;
// if (!def.Exported) continue;
switch (def)
{

View File

@@ -1,19 +1,19 @@
namespace NubLang.TypeChecking.Node;
public abstract record DefinitionNode : Node;
public abstract record DefinitionNode(string Module, string Name) : Node;
public record FuncParameterNode(string Name, TypeNode Type) : Node;
public record FuncSignatureNode(IReadOnlyList<FuncParameterNode> Parameters, TypeNode ReturnType) : Node;
public record FuncNode(string Name, FuncSignatureNode Signature, BlockNode? Body) : DefinitionNode;
public record FuncNode(string Module, string Name, FuncSignatureNode Signature, BlockNode? Body) : DefinitionNode(Module, Name);
public record StructFieldNode(int Index, string Name, TypeNode Type, Optional<ExpressionNode> Value) : Node;
public record StructFuncNode(string Name, FuncSignatureNode Signature, BlockNode Body) : Node;
public record StructNode(string Name, IReadOnlyList<StructFieldNode> Fields, IReadOnlyList<StructFuncNode> Functions, IReadOnlyList<InterfaceTypeNode> InterfaceImplementations) : DefinitionNode;
public record StructNode(string Module, string Name, IReadOnlyList<StructFieldNode> Fields, IReadOnlyList<StructFuncNode> Functions, IReadOnlyList<InterfaceTypeNode> InterfaceImplementations) : DefinitionNode(Module, Name);
public record InterfaceFuncNode(string Name, FuncSignatureNode Signature) : Node;
public record InterfaceNode(string Name, IReadOnlyList<InterfaceFuncNode> Functions) : DefinitionNode;
public record InterfaceNode(string Module, string Name, IReadOnlyList<InterfaceFuncNode> Functions) : DefinitionNode(Module, Name);

View File

@@ -2,4 +2,6 @@
public abstract record Node;
public record BlockNode(IReadOnlyList<StatementNode> Statements) : Node;
public record BlockNode(IReadOnlyList<StatementNode> Statements) : Node;
public record TypedSyntaxTree(IReadOnlyList<DefinitionNode> Definitions);

View File

@@ -7,7 +7,7 @@ namespace NubLang.TypeChecking;
public sealed class TypeChecker
{
private readonly Module _currentModule;
private readonly SyntaxTree _syntaxTree;
private readonly IReadOnlyDictionary<string, ModuleSignature> _moduleSignatures;
private readonly Stack<Scope> _scopes = [];
@@ -16,22 +16,22 @@ public sealed class TypeChecker
private Scope Scope => _scopes.Peek();
public TypeChecker(Module currentModule, IReadOnlyDictionary<string, ModuleSignature> moduleSignatures)
public TypeChecker(SyntaxTree syntaxTree, IReadOnlyDictionary<string, ModuleSignature> moduleSignatures)
{
_currentModule = currentModule;
_moduleSignatures = moduleSignatures.Where(x => currentModule.Imports.Contains(x.Key) || _currentModule.Name == x.Key).ToDictionary();
_syntaxTree = syntaxTree;
_moduleSignatures = moduleSignatures.Where(x => syntaxTree.Metadata.Imports.Contains(x.Key) || _syntaxTree.Metadata.ModuleName == x.Key).ToDictionary();
}
public IReadOnlyList<Diagnostic> GetDiagnostics() => _diagnostics;
public TypedModule CheckModule()
public IReadOnlyList<DefinitionNode> Check()
{
_diagnostics.Clear();
_scopes.Clear();
var definitions = new List<DefinitionNode>();
foreach (var definition in _currentModule.Definitions)
foreach (var definition in _syntaxTree.Definitions)
{
try
{
@@ -43,7 +43,7 @@ public sealed class TypeChecker
}
}
return new TypedModule(_currentModule.Name, definitions);
return definitions;
}
private DefinitionNode CheckDefinition(DefinitionSyntax node)
@@ -105,7 +105,7 @@ public sealed class TypeChecker
interfaceImplementations.Add(interfaceType);
}
return new StructNode(node.Name, fields, functions, interfaceImplementations);
return new StructNode(_syntaxTree.Metadata.ModuleName, node.Name, fields, functions, interfaceImplementations);
}
private FuncNode CheckFuncDefinition(FuncSyntax node)
@@ -124,7 +124,7 @@ public sealed class TypeChecker
_funcReturnTypes.Pop();
}
return new FuncNode(node.Name, CheckFuncSignature(node.Signature), body);
return new FuncNode(_syntaxTree.Metadata.ModuleName, node.Name, CheckFuncSignature(node.Signature), body);
}
private StatementNode CheckStatement(StatementSyntax node)
@@ -223,7 +223,8 @@ public sealed class TypeChecker
DereferenceSyntax expression => CheckDereference(expression),
DotFuncCallSyntax expression => CheckDotFuncCall(expression),
FuncCallSyntax expression => CheckFuncCall(expression),
IdentifierSyntax expression => CheckIdentifier(expression),
LocalIdentifierSyntax expression => CheckLocalIdentifier(expression),
ModuleIdentifierSyntax expression => CheckModuleIdentifier(expression),
LiteralSyntax expression => CheckLiteral(expression, expectedType),
StructFieldAccessSyntax expression => CheckStructFieldAccess(expression),
StructInitializerSyntax expression => CheckStructInitializer(expression, expectedType),
@@ -321,44 +322,44 @@ public sealed class TypeChecker
throw new NotImplementedException();
}
private ExpressionNode CheckIdentifier(IdentifierSyntax expression)
private ExpressionNode CheckLocalIdentifier(LocalIdentifierSyntax expression)
{
// If the identifier does not have a module specified, first check if a local variable or function parameter with that identifier exists
if (!expression.Module.TryGetValue(out var moduleName))
// First, look in the current scope for a matching identifier
var scopeIdent = Scope.Lookup(expression.Name);
if (scopeIdent != null)
{
var scopeIdent = Scope.Lookup(expression.Name);
if (scopeIdent != null)
switch (scopeIdent.Kind)
{
switch (scopeIdent.Kind)
case IdentifierKind.Variable:
{
case IdentifierKind.Variable:
{
return new VariableIdentifierNode(scopeIdent.Type, expression.Name);
}
case IdentifierKind.FunctionParameter:
{
return new FuncParameterIdentifierNode(scopeIdent.Type, expression.Name);
}
default:
{
throw new ArgumentOutOfRangeException();
}
return new VariableIdentifierNode(scopeIdent.Type, expression.Name);
}
case IdentifierKind.FunctionParameter:
{
return new FuncParameterIdentifierNode(scopeIdent.Type, expression.Name);
}
default:
{
throw new ArgumentOutOfRangeException();
}
}
}
moduleName ??= _currentModule.Name;
if (_moduleSignatures.TryGetValue(moduleName, out var module))
// Second, look in the current module for a function matching the identifier
var module = _moduleSignatures[_syntaxTree.Metadata.ModuleName];
if (module.Functions.TryGetValue(expression.Name, out var function))
{
if (module.Functions.TryGetValue(expression.Name, out var function))
{
return new FuncIdentifierNode(function, moduleName, expression.Name);
}
return new FuncIdentifierNode(function, _syntaxTree.Metadata.ModuleName, expression.Name);
}
throw new TypeCheckerException(Diagnostic.Error($"Identifier {expression.Name} not found").At(expression).Build());
}
private ExpressionNode CheckModuleIdentifier(ModuleIdentifierSyntax expression)
{
throw new NotImplementedException();
}
private LiteralNode CheckLiteral(LiteralSyntax expression, TypeNode? expectedType)
{
// todo(nub31): Check if the types can actually be represented as another one. For example, an int should be passed when a string is expected