From 387ac341379e9ab8a4e0e008a3957c220f92b861 Mon Sep 17 00:00:00 2001 From: nub31 Date: Fri, 12 Sep 2025 16:58:09 +0200 Subject: [PATCH] ... --- compiler/NubLang.CLI/Program.cs | 30 ++- .../NubLang/Generation/QBE/QBEGenerator.cs | 34 ++-- compiler/NubLang/Modules/Module.cs | 48 +++++ compiler/NubLang/Modules/ModuleRepository.cs | 66 ++++++ compiler/NubLang/Parsing/Parser.cs | 4 +- .../Parsing/Syntax/DefinitionSyntax.cs | 2 +- compiler/NubLang/TypeChecking/Module.cs | 189 ------------------ .../TypeChecking/Node/DefinitionNode.cs | 2 +- .../TypeChecking/Node/ExpressionNode.cs | 2 +- .../NubLang/TypeChecking/Node/TypeNode.cs | 3 +- compiler/NubLang/TypeChecking/TypeChecker.cs | 103 +++++----- example/src/test.nub | 7 + 12 files changed, 212 insertions(+), 278 deletions(-) create mode 100644 compiler/NubLang/Modules/Module.cs create mode 100644 compiler/NubLang/Modules/ModuleRepository.cs delete mode 100644 compiler/NubLang/TypeChecking/Module.cs create mode 100644 example/src/test.nub diff --git a/compiler/NubLang.CLI/Program.cs b/compiler/NubLang.CLI/Program.cs index e458b77..a1c81ec 100644 --- a/compiler/NubLang.CLI/Program.cs +++ b/compiler/NubLang.CLI/Program.cs @@ -1,7 +1,9 @@ -using NubLang.CLI; +using System.Collections.Immutable; +using NubLang.CLI; using NubLang.Code; using NubLang.Diagnostics; using NubLang.Generation.QBE; +using NubLang.Modules; using NubLang.Parsing; using NubLang.Parsing.Syntax; using NubLang.Tokenization; @@ -60,16 +62,30 @@ foreach (var file in options.Files) syntaxTrees.Add(syntaxTree); } -var moduleSignatures = Module.CollectFromSyntaxTrees(syntaxTrees); +var moduleRepository = new ModuleRepository(syntaxTrees); var definitions = new List(); +var referencedStructTypes = new HashSet(); +var referencedInterfaceTypes = new HashSet(); + foreach (var syntaxTree in syntaxTrees) { - var typeChecker = new TypeChecker(syntaxTree, moduleSignatures); - var checkedDefinitions = typeChecker.Check(); - diagnostics.AddRange(typeChecker.GetDiagnostics()); - definitions.AddRange(checkedDefinitions); + var typeChecker = new TypeChecker(syntaxTree, moduleRepository); + typeChecker.Check(); + + definitions.AddRange(typeChecker.Definitions); + diagnostics.AddRange(typeChecker.Diagnostics); + + foreach (var structType in typeChecker.ReferencedStructTypes) + { + referencedStructTypes.Add(structType); + } + + foreach (var interfaceType in typeChecker.ReferencedInterfaceTypes) + { + referencedInterfaceTypes.Add(interfaceType); + } } foreach (var diagnostic in diagnostics) @@ -84,7 +100,7 @@ if (diagnostics.Any(diagnostic => diagnostic.Severity == DiagnosticSeverity.Erro Directory.CreateDirectory(".build"); -var generator = new QBEGenerator(definitions, moduleSignatures); +var generator = new QBEGenerator(definitions, referencedStructTypes.ToImmutableHashSet(), referencedInterfaceTypes.ToImmutableHashSet()); var ssa = generator.Emit(); var ssaFilePath = Path.Combine(".build", "out.ssa"); File.WriteAllText(ssaFilePath, ssa); diff --git a/compiler/NubLang/Generation/QBE/QBEGenerator.cs b/compiler/NubLang/Generation/QBE/QBEGenerator.cs index 4b6264e..2da2dd6 100644 --- a/compiler/NubLang/Generation/QBE/QBEGenerator.cs +++ b/compiler/NubLang/Generation/QBE/QBEGenerator.cs @@ -1,8 +1,8 @@ -using System.Diagnostics; +using System.Collections.Immutable; +using System.Diagnostics; using System.Globalization; using System.Text; using NubLang.Tokenization; -using NubLang.TypeChecking; using NubLang.TypeChecking.Node; namespace NubLang.Generation.QBE; @@ -11,7 +11,8 @@ public class QBEGenerator { private readonly QBEWriter _writer; private readonly IReadOnlyList _definitions; - private readonly IReadOnlyDictionary _moduleSignatures; + private readonly ImmutableHashSet _structTypes; + private readonly ImmutableHashSet _interfaceTypes; private readonly List _cStringLiterals = []; private readonly List _stringLiterals = []; @@ -23,10 +24,11 @@ public class QBEGenerator private int _stringLiteralIndex; private bool _codeIsReachable = true; - public QBEGenerator(IReadOnlyList definitions, IReadOnlyDictionary moduleSignatures) + public QBEGenerator(IReadOnlyList definitions, ImmutableHashSet structTypes, ImmutableHashSet interfaceTypes) { _definitions = definitions; - _moduleSignatures = moduleSignatures; + _structTypes = structTypes; + _interfaceTypes = interfaceTypes; _writer = new QBEWriter(); } @@ -42,13 +44,10 @@ public class QBEGenerator _stringLiteralIndex = 0; _codeIsReachable = true; - foreach (var (module, signature) in _moduleSignatures) + foreach (var structType in _structTypes) { - foreach (var structType in signature.ExportedStructTypes) - { - EmitStructType(module, structType.StructType); - _writer.NewLine(); - } + EmitStructType(structType); + _writer.NewLine(); } foreach (var structDef in _definitions.OfType()) @@ -386,7 +385,7 @@ public class QBEGenerator _writer.Write(FuncQBETypeName(funcDef.Signature.ReturnType) + ' '); } - _writer.Write(FuncName(funcDef.Module, funcDef.Name)); + _writer.Write(FuncName(funcDef.Module, funcDef.Name, funcDef.ExternSymbol)); _writer.Write("("); foreach (var parameter in funcDef.Signature.Parameters) @@ -453,9 +452,9 @@ public class QBEGenerator } } - private void EmitStructType(string module, StructTypeNode structType) + private void EmitStructType(StructTypeNode structType) { - _writer.WriteLine($"type {StructTypeName(module, structType.Name)} = {{ "); + _writer.WriteLine($"type {StructTypeName(structType.Module, structType.Name)} = {{ "); foreach (var field in structType.Fields) { @@ -658,7 +657,7 @@ public class QBEGenerator private string EmitFuncIdentifier(FuncIdentifierNode funcIdent) { - return FuncName(funcIdent.Module, funcIdent.Name); + return FuncName(funcIdent.Module, funcIdent.Name, funcIdent.ExternSymbol); } private string EmitVariableIdentifier(VariableIdentifierNode variableIdent) @@ -1391,10 +1390,9 @@ public class QBEGenerator return $"$string{++_stringLiteralIndex}"; } - private string FuncName(string module, string name) + private string FuncName(string module, string name, string? externSymbol) { - var function = _moduleSignatures[module].AllFunctions.First(x => x.Name == name); - var symbol = function.ExternSymbol ?? $"{module}.{name}"; + var symbol = externSymbol ?? $"{module}.{name}"; return "$" + symbol; } diff --git a/compiler/NubLang/Modules/Module.cs b/compiler/NubLang/Modules/Module.cs new file mode 100644 index 0000000..e2d1df4 --- /dev/null +++ b/compiler/NubLang/Modules/Module.cs @@ -0,0 +1,48 @@ +using NubLang.Parsing.Syntax; + +namespace NubLang.Modules; + +public class Module +{ + private readonly List _structs = []; + private readonly List _interfaces = []; + private readonly List _functions = []; + + public void RegisterStruct(bool exported, string name, IReadOnlyList fields) + { + _structs.Add(new ModuleStructType(exported, name, fields)); + } + + public void RegisterInterface(bool exported, string name) + { + _interfaces.Add(new ModuleInterfaceType(exported, name)); + } + + public void RegisterFunction(bool exported, string name, string? externSymbol, FuncTypeSyntax type) + { + _functions.Add(new ModuleFuncType(exported, name, externSymbol, type)); + } + + public IReadOnlyList StructTypes(bool includePrivate) + { + return _structs.Where(x => x.Exported || includePrivate).ToList(); + } + + public IReadOnlyList InterfaceTypes(bool includePrivate) + { + return _interfaces.Where(x => x.Exported || includePrivate).ToList(); + } + + public IReadOnlyList Functions(bool includePrivate) + { + return _functions.Where(x => x.Exported || includePrivate).ToList(); + } +} + +public record ModuleStructTypeField(string Name, TypeSyntax Type, bool HasDefaultValue); + +public record ModuleStructType(bool Exported, string Name, IReadOnlyList Fields); + +public record ModuleInterfaceType(bool Exported, string Name); + +public record ModuleFuncType(bool Exported, string Name, string? ExternSymbol, FuncTypeSyntax FuncType); \ No newline at end of file diff --git a/compiler/NubLang/Modules/ModuleRepository.cs b/compiler/NubLang/Modules/ModuleRepository.cs new file mode 100644 index 0000000..53065d9 --- /dev/null +++ b/compiler/NubLang/Modules/ModuleRepository.cs @@ -0,0 +1,66 @@ +using NubLang.Parsing.Syntax; + +namespace NubLang.Modules; + +public class ModuleRepository +{ + private readonly Dictionary _modules = new(); + + public ModuleRepository(IReadOnlyList syntaxTrees) + { + foreach (var syntaxTree in syntaxTrees) + { + var moduleName = syntaxTree.Metadata.ModuleName; + var module = GetOrCreate(moduleName); + ProcessSyntaxTree(module, syntaxTree); + } + } + + private static void ProcessSyntaxTree(Module module, SyntaxTree syntaxTree) + { + foreach (var definition in syntaxTree.Definitions) + { + switch (definition) + { + case FuncSyntax funcDef: + { + var parameters = funcDef.Signature.Parameters.Select(x => x.Type).ToList(); + var type = new FuncTypeSyntax([], parameters, funcDef.Signature.ReturnType); + module.RegisterFunction(funcDef.Exported, funcDef.Name, funcDef.ExternSymbol, type); + break; + } + case StructSyntax structDef: + { + var fields = structDef.Fields.Select(x => new ModuleStructTypeField(x.Name, x.Type, x.Value.HasValue)).ToList(); + module.RegisterStruct(structDef.Exported, structDef.Name, fields); + break; + } + case InterfaceSyntax interfaceDef: + { + module.RegisterInterface(interfaceDef.Exported, interfaceDef.Name); + break; + } + default: + { + throw new ArgumentOutOfRangeException(nameof(definition)); + } + } + } + } + + public IReadOnlyDictionary Modules() + { + return _modules; + } + + private Module GetOrCreate(string name) + { + if (!_modules.TryGetValue(name, out var module)) + { + module = new Module(); + _modules[name] = module; + } + + return module; + } +} \ No newline at end of file diff --git a/compiler/NubLang/Parsing/Parser.cs b/compiler/NubLang/Parsing/Parser.cs index a381540..97cfefd 100644 --- a/compiler/NubLang/Parsing/Parser.cs +++ b/compiler/NubLang/Parsing/Parser.cs @@ -183,8 +183,6 @@ public sealed class Parser List fields = []; List funcs = []; - var fieldIndex = 0; - while (!TryExpectSymbol(Symbol.CloseBrace)) { var memberStartIndex = _tokenIndex; @@ -210,7 +208,7 @@ public sealed class Parser fieldValue = ParseExpression(); } - fields.Add(new StructFieldSyntax(GetTokens(memberStartIndex), fieldIndex++, fieldName, fieldType, fieldValue)); + fields.Add(new StructFieldSyntax(GetTokens(memberStartIndex), fieldName, fieldType, fieldValue)); } } diff --git a/compiler/NubLang/Parsing/Syntax/DefinitionSyntax.cs b/compiler/NubLang/Parsing/Syntax/DefinitionSyntax.cs index 2c220ac..7a20805 100644 --- a/compiler/NubLang/Parsing/Syntax/DefinitionSyntax.cs +++ b/compiler/NubLang/Parsing/Syntax/DefinitionSyntax.cs @@ -10,7 +10,7 @@ public record FuncSignatureSyntax(IEnumerable Tokens, IReadOnlyList Tokens, string Name, bool Exported, string? ExternSymbol, FuncSignatureSyntax Signature, BlockSyntax? Body) : DefinitionSyntax(Tokens, Name, Exported); -public record StructFieldSyntax(IEnumerable Tokens, int Index, string Name, TypeSyntax Type, Optional Value) : SyntaxNode(Tokens); +public record StructFieldSyntax(IEnumerable Tokens, string Name, TypeSyntax Type, Optional Value) : SyntaxNode(Tokens); public record StructFuncSyntax(IEnumerable Tokens, string Name, FuncSignatureSyntax Signature, BlockSyntax Body) : SyntaxNode(Tokens); diff --git a/compiler/NubLang/TypeChecking/Module.cs b/compiler/NubLang/TypeChecking/Module.cs deleted file mode 100644 index c5cb328..0000000 --- a/compiler/NubLang/TypeChecking/Module.cs +++ /dev/null @@ -1,189 +0,0 @@ -using NubLang.Parsing.Syntax; -using NubLang.TypeChecking.Node; - -namespace NubLang.TypeChecking; - -public class Module -{ - public static IReadOnlyDictionary CollectFromSyntaxTrees(IReadOnlyList syntaxTrees) - { - var modules = new Dictionary(); - - foreach (var syntaxTree in syntaxTrees) - { - var moduleName = syntaxTree.Metadata.ModuleName; - - if (!modules.TryGetValue(moduleName, out var module)) - { - module = new Module(); - modules[moduleName] = module; - } - - foreach (var def in syntaxTree.Definitions) - { - switch (def) - { - case FuncSyntax funcDef: - { - var parameters = funcDef.Signature.Parameters.Select(p => ResolveType(p.Type)).ToList(); - var returnType = ResolveType(funcDef.Signature.ReturnType); - - var type = new FuncTypeNode(parameters, returnType); - module._functions.Add(new ModuleFuncType(def.Exported, funcDef.Name, funcDef.ExternSymbol, type)); - break; - } - case InterfaceSyntax interfaceDef: - { - var functions = new List(); - for (var i = 0; i < interfaceDef.Functions.Count; i++) - { - var function = interfaceDef.Functions[i]; - 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 ModuleInterfaceType(def.Exported, type)); - break; - } - case StructSyntax structDef: - { - var fields = new List(); - foreach (var field in structDef.Fields) - { - fields.Add(new StructTypeField(field.Name, ResolveType(field.Type), field.Index, field.Value.HasValue)); - } - - var functions = new List(); - foreach (var function in structDef.Functions) - { - 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))); - } - - var interfaceImplementations = new List(); - foreach (var interfaceImplementation in structDef.InterfaceImplementations) - { - if (interfaceImplementation is not CustomTypeSyntax customType) - { - throw new Exception("Interface implementation is not a custom type"); - } - - var resolvedType = ResolveType(customType); - if (resolvedType is not InterfaceTypeNode interfaceType) - { - throw new Exception("Interface implementation is not a interface"); - } - - interfaceImplementations.Add(interfaceType); - } - - var type = new StructTypeNode(moduleName, structDef.Name, fields, functions, interfaceImplementations); - module._structs.Add(new ModuleStructType(def.Exported, type)); - break; - } - default: - { - throw new ArgumentOutOfRangeException(nameof(def)); - } - } - } - } - - return modules; - - TypeNode ResolveType(TypeSyntax type) - { - 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}") - }; - } - - 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 _structs = []; - private readonly List _interfaces = []; - private readonly List _functions = []; - - public IReadOnlyList ExportedStructTypes => _structs.Where(x => x.Exported).ToList(); - public IReadOnlyList ExportedInterfaceTypes => _interfaces.Where(x => x.Exported).ToList(); - public IReadOnlyList ExportedFunctions => _functions.Where(x => x.Exported).ToList(); - - public IReadOnlyList AllStructTypes => _structs; - public IReadOnlyList AllInterfaceTypes => _interfaces; - public IReadOnlyList 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; } -} \ No newline at end of file diff --git a/compiler/NubLang/TypeChecking/Node/DefinitionNode.cs b/compiler/NubLang/TypeChecking/Node/DefinitionNode.cs index b61332e..21d1e77 100644 --- a/compiler/NubLang/TypeChecking/Node/DefinitionNode.cs +++ b/compiler/NubLang/TypeChecking/Node/DefinitionNode.cs @@ -8,7 +8,7 @@ public record FuncSignatureNode(IReadOnlyList Parameters, Typ public record FuncNode(string Module, string Name, string? ExternSymbol, FuncSignatureNode Signature, BlockNode? Body) : DefinitionNode(Module, Name); -public record StructFieldNode(int Index, string Name, TypeNode Type, Optional Value) : Node; +public record StructFieldNode(string Name, TypeNode Type, Optional Value) : Node; public record StructFuncNode(string Name, FuncSignatureNode Signature, BlockNode Body) : Node; diff --git a/compiler/NubLang/TypeChecking/Node/ExpressionNode.cs b/compiler/NubLang/TypeChecking/Node/ExpressionNode.cs index df480cd..07dc28b 100644 --- a/compiler/NubLang/TypeChecking/Node/ExpressionNode.cs +++ b/compiler/NubLang/TypeChecking/Node/ExpressionNode.cs @@ -49,7 +49,7 @@ public record VariableIdentifierNode(TypeNode Type, string Name) : LValueExpress public record FuncParameterIdentifierNode(TypeNode Type, string Name) : RValueExpressionNode(Type); -public record FuncIdentifierNode(TypeNode Type, string Module, string Name) : RValueExpressionNode(Type); +public record FuncIdentifierNode(TypeNode Type, string Module, string Name, string? ExternSymbol) : RValueExpressionNode(Type); public record ArrayInitializerNode(TypeNode Type, ExpressionNode Capacity, TypeNode ElementType) : RValueExpressionNode(Type); diff --git a/compiler/NubLang/TypeChecking/Node/TypeNode.cs b/compiler/NubLang/TypeChecking/Node/TypeNode.cs index 55d29aa..0e9135a 100644 --- a/compiler/NubLang/TypeChecking/Node/TypeNode.cs +++ b/compiler/NubLang/TypeChecking/Node/TypeNode.cs @@ -174,11 +174,10 @@ public class StringTypeNode : ComplexTypeNode public override int GetHashCode() => HashCode.Combine(typeof(StringTypeNode)); } -public class StructTypeField(string name, TypeNode type, int index, bool hasDefaultValue) +public class StructTypeField(string name, TypeNode type, bool hasDefaultValue) { public string Name { get; } = name; public TypeNode Type { get; } = type; - public int Index { get; } = index; public bool HasDefaultValue { get; } = hasDefaultValue; } diff --git a/compiler/NubLang/TypeChecking/TypeChecker.cs b/compiler/NubLang/TypeChecking/TypeChecker.cs index 9c8d059..4863fb4 100644 --- a/compiler/NubLang/TypeChecking/TypeChecker.cs +++ b/compiler/NubLang/TypeChecking/TypeChecker.cs @@ -1,5 +1,6 @@ using System.Diagnostics; using NubLang.Diagnostics; +using NubLang.Modules; using NubLang.Parsing.Syntax; using NubLang.Tokenization; using NubLang.TypeChecking.Node; @@ -9,42 +10,51 @@ namespace NubLang.TypeChecking; public sealed class TypeChecker { private readonly SyntaxTree _syntaxTree; - private readonly IReadOnlyDictionary _importedModules; + private readonly Dictionary _visibleModules; private readonly Stack _scopes = []; private readonly Stack _funcReturnTypes = []; private readonly List _diagnostics = []; + private readonly List _referencedStructTypes = []; + private readonly List _referencedInterfaceTypes = []; + private readonly List _definitions = []; private Scope Scope => _scopes.Peek(); - public TypeChecker(SyntaxTree syntaxTree, IReadOnlyDictionary moduleSignatures) + public TypeChecker(SyntaxTree syntaxTree, ModuleRepository moduleRepository) { _syntaxTree = syntaxTree; - _importedModules = moduleSignatures.Where(x => syntaxTree.Metadata.Imports.Contains(x.Key) || _syntaxTree.Metadata.ModuleName == x.Key).ToDictionary(); + _visibleModules = moduleRepository + .Modules() + .Where(x => syntaxTree.Metadata.Imports.Contains(x.Key) || _syntaxTree.Metadata.ModuleName == x.Key) + .ToDictionary(); } - public IReadOnlyList GetDiagnostics() => _diagnostics; + public IReadOnlyList Definitions => _definitions; + public IReadOnlyList Diagnostics => _diagnostics; + public IReadOnlyList ReferencedStructTypes => _referencedStructTypes; + public IReadOnlyList ReferencedInterfaceTypes => _referencedInterfaceTypes; - public IReadOnlyList Check() + public void Check() { - _diagnostics.Clear(); _scopes.Clear(); - - var definitions = new List(); + _funcReturnTypes.Clear(); + _diagnostics.Clear(); + _referencedStructTypes.Clear(); + _referencedInterfaceTypes.Clear(); + _definitions.Clear(); foreach (var definition in _syntaxTree.Definitions) { try { - definitions.Add(CheckDefinition(definition)); + _definitions.Add(CheckDefinition(definition)); } catch (TypeCheckerException e) { _diagnostics.Add(e.Diagnostic); } } - - return definitions; } private DefinitionNode CheckDefinition(DefinitionSyntax node) @@ -78,7 +88,7 @@ public sealed class TypeChecker value = CheckExpression(field.Value.Value); } - fields.Add(new StructFieldNode(field.Index, field.Name, ResolveType(field.Type), value)); + fields.Add(new StructFieldNode(field.Name, ResolveType(field.Type), value)); } var functions = new List(); @@ -351,12 +361,12 @@ public sealed class TypeChecker } // Second, look in the current module for a function matching the identifier - var module = _importedModules[_syntaxTree.Metadata.ModuleName]; - var function = module.AllFunctions.FirstOrDefault(x => x.Name == expression.Name); + var module = _visibleModules[_syntaxTree.Metadata.ModuleName]; + var function = module.Functions(true).FirstOrDefault(x => x.Name == expression.Name); if (function != null) { - return new FuncIdentifierNode(function.FuncType, _syntaxTree.Metadata.ModuleName, expression.Name); + return new FuncIdentifierNode(ResolveType(function.FuncType), _syntaxTree.Metadata.ModuleName, expression.Name, function.ExternSymbol); } throw new TypeCheckerException(Diagnostic.Error($"Symbol {expression.Name} not found").At(expression).Build()); @@ -364,27 +374,18 @@ public sealed class TypeChecker private ExpressionNode CheckModuleIdentifier(ModuleIdentifierSyntax expression) { - if (!_importedModules.TryGetValue(expression.Module, out var module)) + if (!_visibleModules.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 includePrivate = expression.Module == _syntaxTree.Metadata.ModuleName; + + // First, look for the exported function in the specified module + var function = module.Functions(includePrivate).FirstOrDefault(x => x.Name == expression.Name); + if (function != null) { - 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); - } + return new FuncIdentifierNode(ResolveType(function.FuncType), expression.Module, expression.Name, function.ExternSymbol); } throw new TypeCheckerException(Diagnostic.Error($"No exported symbol {expression.Name} not found in module {expression.Module}").At(expression).Build()); @@ -521,38 +522,28 @@ public sealed class TypeChecker private TypeNode ResolveCustomType(CustomTypeSyntax customType) { - if (!_importedModules.TryGetValue(customType.Module, out var module)) + 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()); } - if (customType.Module == _syntaxTree.Metadata.ModuleName) - { - var structType = module.AllStructTypes.FirstOrDefault(x => x.StructType.Name == customType.Name); - if (structType != null) - { - return structType.StructType; - } + var includePrivate = customType.Module == _syntaxTree.Metadata.ModuleName; - var interfaceType = module.AllInterfaceTypes.FirstOrDefault(x => x.InterfaceType.Name == customType.Name); - if (interfaceType != null) - { - return interfaceType.InterfaceType; - } + var structType = module.StructTypes(includePrivate).FirstOrDefault(x => x.Name == customType.Name); + if (structType != null) + { + 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; } - 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; - } + var interfaceType = module.InterfaceTypes(includePrivate).FirstOrDefault(x => x.Name == customType.Name); + if (interfaceType != null) + { + var result = new InterfaceTypeNode(customType.Module, interfaceType.Name, []); + _referencedInterfaceTypes.AddRange(result); + return result; } throw new TypeCheckerException(Diagnostic.Error($"Type {customType.Name} not found in module {customType.Module}").At(customType).Build()); diff --git a/example/src/test.nub b/example/src/test.nub new file mode 100644 index 0000000..ae15028 --- /dev/null +++ b/example/src/test.nub @@ -0,0 +1,7 @@ +module "test" +import "main" + +export struct Test2 +{ + test1: ^main::Test1 +} \ No newline at end of file