From 7c7624b1bc3e2ee8566af2b15078aa73f23c601a Mon Sep 17 00:00:00 2001 From: nub31 Date: Fri, 31 Oct 2025 14:42:58 +0100 Subject: [PATCH] ... --- compiler/NubLang.CLI/Program.cs | 18 +- compiler/NubLang.LSP/DefinitionHandler.cs | 2 +- compiler/NubLang.LSP/WorkspaceManager.cs | 92 ++--- compiler/NubLang/Ast/CompilationUnit.cs | 12 - compiler/NubLang/Ast/Node.cs | 37 +- compiler/NubLang/Ast/TypeChecker.cs | 404 ++++++------------- compiler/NubLang/Ast/TypeResolver.cs | 96 ----- compiler/NubLang/Generation/LlvmGenerator.cs | 9 +- compiler/NubLang/Modules/ModuleRepository.cs | 246 +++++++++++ compiler/NubLang/Syntax/Module.cs | 60 --- compiler/NubLang/Syntax/Parser.cs | 7 - compiler/NubLang/Syntax/Syntax.cs | 2 - compiler/NubLang/Syntax/Token.cs | 12 +- compiler/NubLang/Syntax/Tokenizer.cs | 1 - compiler/NubLang/Syntax/TypedModule.cs | 52 --- compiler/NubLang/{Ast => Types}/NubType.cs | 2 +- examples/playgroud/main.nub | 6 + 17 files changed, 453 insertions(+), 605 deletions(-) delete mode 100644 compiler/NubLang/Ast/CompilationUnit.cs delete mode 100644 compiler/NubLang/Ast/TypeResolver.cs create mode 100644 compiler/NubLang/Modules/ModuleRepository.cs delete mode 100644 compiler/NubLang/Syntax/Module.cs delete mode 100644 compiler/NubLang/Syntax/TypedModule.cs rename compiler/NubLang/{Ast => Types}/NubType.cs (99%) diff --git a/compiler/NubLang.CLI/Program.cs b/compiler/NubLang.CLI/Program.cs index e72a9f9..ac5cd6b 100644 --- a/compiler/NubLang.CLI/Program.cs +++ b/compiler/NubLang.CLI/Program.cs @@ -1,6 +1,7 @@ using NubLang.Ast; using NubLang.Diagnostics; using NubLang.Generation; +using NubLang.Modules; using NubLang.Syntax; var diagnostics = new List(); @@ -19,13 +20,24 @@ foreach (var file in args) syntaxTrees.Add(syntaxTree); } -var modules = Module.Collect(syntaxTrees); +ModuleRepository moduleRepository; + +try +{ + moduleRepository = ModuleRepository.Create(syntaxTrees); +} +catch (CompileException e) +{ + Console.Error.WriteLine(e.Diagnostic.FormatANSI()); + return 1; +} + var compilationUnits = new List>(); for (var i = 0; i < args.Length; i++) { - var typeChecker = new TypeChecker(syntaxTrees[i], modules); - var compilationUnit = typeChecker.Check(); + var typeChecker = new TypeChecker(); + var compilationUnit = typeChecker.Check(syntaxTrees[i], moduleRepository); compilationUnits.Add(compilationUnit); diagnostics.AddRange(typeChecker.Diagnostics); diff --git a/compiler/NubLang.LSP/DefinitionHandler.cs b/compiler/NubLang.LSP/DefinitionHandler.cs index a86779b..22b4c70 100644 --- a/compiler/NubLang.LSP/DefinitionHandler.cs +++ b/compiler/NubLang.LSP/DefinitionHandler.cs @@ -55,7 +55,7 @@ internal class DefinitionHandler(WorkspaceManager workspaceManager) : Definition return null; } - case FuncIdentifierNode funcIdentifierNode: + case ModuleFuncIdentifierNode funcIdentifierNode: { // var prototype = compilationUnit // .ImportedFunctions diff --git a/compiler/NubLang.LSP/WorkspaceManager.cs b/compiler/NubLang.LSP/WorkspaceManager.cs index 2d81221..3dcc1ce 100644 --- a/compiler/NubLang.LSP/WorkspaceManager.cs +++ b/compiler/NubLang.LSP/WorkspaceManager.cs @@ -8,59 +8,59 @@ public class WorkspaceManager(DiagnosticsPublisher diagnosticsPublisher) { private readonly Dictionary _syntaxTrees = new(); private readonly Dictionary> _compilationUnits = new(); - private readonly Dictionary _modules = new(); + // private readonly Dictionary _modules = new(); public void Init(string rootPath) { - var files = Directory.GetFiles(rootPath, "*.nub", SearchOption.AllDirectories); - foreach (var path in files) - { - var text = File.ReadAllText(path); - var tokenizer = new Tokenizer(path, text); - - tokenizer.Tokenize(); - diagnosticsPublisher.Publish(path, tokenizer.Diagnostics); - - var parser = new Parser(); - var parseResult = parser.Parse(tokenizer.Tokens); - diagnosticsPublisher.Publish(path, parser.Diagnostics); - - _syntaxTrees[path] = parseResult; - } - - foreach (var (fsPath, syntaxTree) in _syntaxTrees) - { - var modules = Module.Collect(_syntaxTrees.Select(x => x.Value).ToList()); - - var typeChecker = new TypeChecker(syntaxTree, modules); - var result = typeChecker.Check(); - diagnosticsPublisher.Publish(fsPath, typeChecker.Diagnostics); - - _compilationUnits[fsPath] = result; - } + // var files = Directory.GetFiles(rootPath, "*.nub", SearchOption.AllDirectories); + // foreach (var path in files) + // { + // var text = File.ReadAllText(path); + // var tokenizer = new Tokenizer(path, text); + // + // tokenizer.Tokenize(); + // diagnosticsPublisher.Publish(path, tokenizer.Diagnostics); + // + // var parser = new Parser(); + // var parseResult = parser.Parse(tokenizer.Tokens); + // diagnosticsPublisher.Publish(path, parser.Diagnostics); + // + // _syntaxTrees[path] = parseResult; + // } + // + // foreach (var (fsPath, syntaxTree) in _syntaxTrees) + // { + // var modules = Module.Collect(_syntaxTrees.Select(x => x.Value).ToList()); + // + // var typeChecker = new TypeChecker(syntaxTree, modules); + // var result = typeChecker.Check(); + // diagnosticsPublisher.Publish(fsPath, typeChecker.Diagnostics); + // + // _compilationUnits[fsPath] = result; + // } } public void UpdateFile(DocumentUri path) { - var fsPath = path.GetFileSystemPath(); - - var text = File.ReadAllText(fsPath); - var tokenizer = new Tokenizer(fsPath, text); - tokenizer.Tokenize(); - diagnosticsPublisher.Publish(path, tokenizer.Diagnostics); - - var parser = new Parser(); - var syntaxTree = parser.Parse(tokenizer.Tokens); - diagnosticsPublisher.Publish(path, parser.Diagnostics); - _syntaxTrees[fsPath] = syntaxTree; - - var modules = Module.Collect(_syntaxTrees.Select(x => x.Value).ToList()); - - var typeChecker = new TypeChecker(syntaxTree, modules); - var result = typeChecker.Check(); - diagnosticsPublisher.Publish(fsPath, typeChecker.Diagnostics); - - _compilationUnits[fsPath] = result; + // var fsPath = path.GetFileSystemPath(); + // + // var text = File.ReadAllText(fsPath); + // var tokenizer = new Tokenizer(fsPath, text); + // tokenizer.Tokenize(); + // diagnosticsPublisher.Publish(path, tokenizer.Diagnostics); + // + // var parser = new Parser(); + // var syntaxTree = parser.Parse(tokenizer.Tokens); + // diagnosticsPublisher.Publish(path, parser.Diagnostics); + // _syntaxTrees[fsPath] = syntaxTree; + // + // var modules = Module.Collect(_syntaxTrees.Select(x => x.Value).ToList()); + // + // var typeChecker = new TypeChecker(syntaxTree, modules); + // var result = typeChecker.Check(); + // diagnosticsPublisher.Publish(fsPath, typeChecker.Diagnostics); + // + // _compilationUnits[fsPath] = result; } public void RemoveFile(DocumentUri path) diff --git a/compiler/NubLang/Ast/CompilationUnit.cs b/compiler/NubLang/Ast/CompilationUnit.cs deleted file mode 100644 index 4cf2489..0000000 --- a/compiler/NubLang/Ast/CompilationUnit.cs +++ /dev/null @@ -1,12 +0,0 @@ -using NubLang.Syntax; - -namespace NubLang.Ast; - -// public sealed class CompilationUnit(IdentifierToken module, List functions, List structTypes, Dictionary> importedStructTypes, Dictionary> importedFunctions) -// { -// public IdentifierToken Module { get; } = module; -// public List Functions { get; } = functions; -// public List Structs { get; } = structTypes; -// public Dictionary> ImportedStructTypes { get; } = importedStructTypes; -// public Dictionary> ImportedFunctions { get; } = importedFunctions; -// } \ No newline at end of file diff --git a/compiler/NubLang/Ast/Node.cs b/compiler/NubLang/Ast/Node.cs index 14aad22..cb6974e 100644 --- a/compiler/NubLang/Ast/Node.cs +++ b/compiler/NubLang/Ast/Node.cs @@ -1,4 +1,5 @@ using NubLang.Syntax; +using NubLang.Types; namespace NubLang.Ast; @@ -31,16 +32,6 @@ public abstract class Node(List tokens) public abstract class TopLevelNode(List tokens) : Node(tokens); -public class ImportNode(List tokens, IdentifierToken nameToken) : TopLevelNode(tokens) -{ - public IdentifierToken NameToken { get; } = nameToken; - - public override IEnumerable Children() - { - return []; - } -} - public class ModuleNode(List tokens, IdentifierToken nameToken) : TopLevelNode(tokens) { public IdentifierToken NameToken { get; } = nameToken; @@ -490,7 +481,18 @@ public class VariableIdentifierNode(List tokens, NubType type, Identifier } } -public class FuncIdentifierNode(List tokens, NubType type, IdentifierToken moduleToken, IdentifierToken nameToken, StringLiteralToken? externSymbolToken) : RValue(tokens, type) +public class LocalFuncIdentifierNode(List tokens, NubType type, IdentifierToken nameToken, StringLiteralToken? externSymbolToken) : RValue(tokens, type) +{ + public IdentifierToken NameToken { get; } = nameToken; + public StringLiteralToken? ExternSymbolToken { get; } = externSymbolToken; + + public override IEnumerable Children() + { + return []; + } +} + +public class ModuleFuncIdentifierNode(List tokens, NubType type, IdentifierToken moduleToken, IdentifierToken nameToken, StringLiteralToken? externSymbolToken) : RValue(tokens, type) { public IdentifierToken ModuleToken { get; } = moduleToken; public IdentifierToken NameToken { get; } = nameToken; @@ -612,17 +614,4 @@ public class ConstArrayInitializerNode(List tokens, NubType type, List tokens) : ExpressionNode(tokens, new NubVoidType()); - -public class EnumReferenceIntermediateNode(List tokens, IdentifierToken moduleToken, IdentifierToken nameToken) : IntermediateExpression(tokens) -{ - public IdentifierToken ModuleToken { get; } = moduleToken; - public IdentifierToken NameToken { get; } = nameToken; - - public override IEnumerable Children() - { - return []; - } -} - #endregion \ No newline at end of file diff --git a/compiler/NubLang/Ast/TypeChecker.cs b/compiler/NubLang/Ast/TypeChecker.cs index 4dfb156..628a6d5 100644 --- a/compiler/NubLang/Ast/TypeChecker.cs +++ b/compiler/NubLang/Ast/TypeChecker.cs @@ -1,32 +1,28 @@ using System.Diagnostics; using NubLang.Diagnostics; +using NubLang.Modules; using NubLang.Syntax; +using NubLang.Types; namespace NubLang.Ast; public sealed class TypeChecker { - private readonly SyntaxTree _syntaxTree; - private readonly Dictionary _modules; + private SyntaxTree _syntaxTree = null!; + private ModuleRepository _repository = null!; - private readonly Stack _scopes = []; + private Stack _scopes = []; - private readonly TypeResolver _typeResolver; + private Scope CurrentScope => _scopes.Peek(); - private Scope Scope => _scopes.Peek(); + public List Diagnostics { get; set; } = []; - public List Diagnostics { get; } = []; - - public TypeChecker(SyntaxTree syntaxTree, Dictionary modules) + public List Check(SyntaxTree syntaxTree, ModuleRepository repository) { _syntaxTree = syntaxTree; - _modules = modules; - _typeResolver = new TypeResolver(_modules); - } - - public List Check() - { - _scopes.Clear(); + _repository = repository; + Diagnostics = []; + _scopes = []; var moduleDeclarations = _syntaxTree.TopLevelSyntaxNodes.OfType().ToList(); if (moduleDeclarations.Count == 0) @@ -40,51 +36,11 @@ public sealed class TypeChecker Diagnostics.Add(Diagnostic.Error("Multiple module declarations").WithHelp("Remove extra module declarations").Build()); } - var moduleName = moduleDeclarations[0].NameToken; - - var importDeclarations = _syntaxTree.TopLevelSyntaxNodes.OfType().ToList(); - foreach (var importDeclaration in importDeclarations) - { - var name = importDeclaration.NameToken.Value; - - var last = importDeclarations.Last(x => x.NameToken.Value == name); - if (importDeclaration != last) - { - Diagnostics.Add(Diagnostic - .Warning($"Module \"{last.NameToken.Value}\" is imported twice") - .WithHelp($"Remove duplicate import \"{last.NameToken.Value}\"") - .At(last) - .Build()); - } - - var exists = _modules.ContainsKey(name); - if (!exists) - { - var suggestions = _modules.Keys - .Select(m => new { Name = m, Distance = Utils.LevenshteinDistance(name, m) }) - .OrderBy(x => x.Distance) - .Take(3) - .Where(x => x.Distance <= 3) - .Select(x => $"\"{x.Name}\"") - .ToArray(); - - var suggestionText = suggestions.Length != 0 - ? $"Did you mean {string.Join(", ", suggestions)}?" - : "Check that the module name is correct."; - - Diagnostics.Add(Diagnostic - .Error($"Module \"{name}\" does not exist") - .WithHelp(suggestionText) - .At(last) - .Build()); - - return []; - } - } + var module = _repository.Get(moduleDeclarations[0].NameToken); var topLevelNodes = new List(); - using (BeginRootScope(moduleName)) + using (BeginRootScope(module)) { foreach (var topLevelSyntaxNode in _syntaxTree.TopLevelSyntaxNodes) { @@ -98,9 +54,6 @@ public sealed class TypeChecker case StructSyntax structSyntax: topLevelNodes.Add(CheckStructDefinition(structSyntax)); break; - case ImportSyntax importSyntax: - topLevelNodes.Add(new ImportNode(importSyntax.Tokens, importSyntax.NameToken)); - break; case ModuleSyntax moduleSyntax: topLevelNodes.Add(new ModuleNode(moduleSyntax.Tokens, moduleSyntax.NameToken)); break; @@ -113,58 +66,15 @@ public sealed class TypeChecker return topLevelNodes; } - private (IdentifierToken Name, Module Module) GetCurrentModule() - { - var currentModule = _syntaxTree.TopLevelSyntaxNodes.OfType().First().NameToken; - return (currentModule, _modules[currentModule.Value]); - } - - private List<(IdentifierToken Name, Module Module)> GetImportedModules() - { - var currentModule = _syntaxTree.TopLevelSyntaxNodes.OfType().First().NameToken; - return _syntaxTree.TopLevelSyntaxNodes - .OfType() - .Select(x => (Name: x.NameToken, Module: _modules[x.NameToken.Value])) - .Concat([(Name: currentModule, Module: _modules[currentModule.Value])]) - .ToList(); - } - - private bool IsCurrentModule(IdentifierToken? module) - { - if (module == null) - { - return true; - } - - return module.Value == Scope.Module.Value; - } - - private Module? GetImportedModule(string module) - { - var currentModule = _syntaxTree.TopLevelSyntaxNodes.OfType().First().NameToken; - if (module == currentModule.Value) - { - return _modules[currentModule.Value]; - } - - var import = _syntaxTree.TopLevelSyntaxNodes.OfType().FirstOrDefault(x => x.NameToken.Value == module); - if (import != null) - { - return _modules[import.NameToken.Value]; - } - - return null; - } - private ScopeDisposer BeginScope() { - _scopes.Push(Scope.SubScope()); + _scopes.Push(CurrentScope.SubScope()); return new ScopeDisposer(this); } - private ScopeDisposer BeginRootScope(IdentifierToken moduleName) + private ScopeDisposer BeginRootScope(ModuleRepository.Module module) { - _scopes.Push(new Scope(moduleName)); + _scopes.Push(new Scope(module)); return new ScopeDisposer(this); } @@ -186,10 +96,10 @@ public sealed class TypeChecker { var prototype = CheckFuncPrototype(node.Prototype); - Scope.SetReturnType(prototype.ReturnType); + CurrentScope.SetReturnType(prototype.ReturnType); foreach (var parameter in prototype.Parameters) { - Scope.DeclareVariable(new Variable(parameter.NameToken, parameter.Type)); + CurrentScope.DeclareVariable(new Variable(parameter.NameToken, parameter.Type)); } var body = node.Body == null ? null : CheckBlock(node.Body); @@ -203,7 +113,7 @@ public sealed class TypeChecker foreach (var field in structSyntax.Fields) { - var fieldType = _typeResolver.ResolveType(field.Type, Scope.Module.Value); + var fieldType = ResolveType(field.Type); ExpressionNode? value = null; if (field.Value != null) { @@ -220,8 +130,7 @@ public sealed class TypeChecker fields.Add(new StructFieldNode(field.Tokens, field.NameToken, fieldType, value)); } - var currentModule = GetCurrentModule(); - var type = new NubStructType(currentModule.Name.Value, structSyntax.NameToken.Value, structSyntax.Packed, fields.Select(x => new NubStructFieldType(x.NameToken.Value, x.Type, x.Value != null)).ToList()); + var type = new NubStructType(CurrentScope.Module.Name, structSyntax.NameToken.Value, structSyntax.Packed, fields.Select(x => new NubStructFieldType(x.NameToken.Value, x.Type, x.Value != null)).ToList()); return new StructNode(structSyntax.Tokens, structSyntax.NameToken, type, structSyntax.Packed, fields); } @@ -261,7 +170,7 @@ public sealed class TypeChecker if (statement.Value != null) { - var expectedReturnType = Scope.GetReturnType(); + var expectedReturnType = CurrentScope.GetReturnType(); value = CheckExpression(statement.Value, expectedReturnType); } @@ -286,7 +195,7 @@ public sealed class TypeChecker if (statement.ExplicitType != null) { - type = _typeResolver.ResolveType(statement.ExplicitType, Scope.Module.Value); + type = ResolveType(statement.ExplicitType); } if (statement.Assignment != null) @@ -314,7 +223,7 @@ public sealed class TypeChecker .Build()); } - Scope.DeclareVariable(new Variable(statement.NameToken, type)); + CurrentScope.DeclareVariable(new Variable(statement.NameToken, type)); return new VariableDeclarationNode(statement.Tokens, statement.NameToken, assignmentNode, type); } @@ -337,10 +246,10 @@ public sealed class TypeChecker { using (BeginScope()) { - Scope.DeclareVariable(new Variable(forSyntax.ElementNameToken, sliceType.ElementType)); + CurrentScope.DeclareVariable(new Variable(forSyntax.ElementNameToken, sliceType.ElementType)); if (forSyntax.IndexNameToken != null) { - Scope.DeclareVariable(new Variable(forSyntax.IndexNameToken, new NubIntType(false, 64))); + CurrentScope.DeclareVariable(new Variable(forSyntax.IndexNameToken, new NubIntType(false, 64))); } var body = CheckBlock(forSyntax.Body); @@ -351,10 +260,10 @@ public sealed class TypeChecker { using (BeginScope()) { - Scope.DeclareVariable(new Variable(forSyntax.ElementNameToken, constArrayType.ElementType)); + CurrentScope.DeclareVariable(new Variable(forSyntax.ElementNameToken, constArrayType.ElementType)); if (forSyntax.IndexNameToken != null) { - Scope.DeclareVariable(new Variable(forSyntax.IndexNameToken, new NubIntType(false, 64))); + CurrentScope.DeclareVariable(new Variable(forSyntax.IndexNameToken, new NubIntType(false, 64))); } var body = CheckBlock(forSyntax.Body); @@ -376,10 +285,10 @@ public sealed class TypeChecker var parameters = new List(); foreach (var parameter in statement.Parameters) { - parameters.Add(new FuncParameterNode(parameter.Tokens, parameter.NameToken, _typeResolver.ResolveType(parameter.Type, Scope.Module.Value))); + parameters.Add(new FuncParameterNode(parameter.Tokens, parameter.NameToken, ResolveType(parameter.Type))); } - return new FuncPrototypeNode(statement.Tokens, statement.NameToken, statement.ExternSymbolToken, parameters, _typeResolver.ResolveType(statement.ReturnType, Scope.Module.Value)); + return new FuncPrototypeNode(statement.Tokens, statement.NameToken, statement.ExternSymbolToken, parameters, ResolveType(statement.ReturnType)); } private ExpressionNode CheckExpression(ExpressionSyntax node, NubType? expectedType = null) @@ -401,7 +310,7 @@ public sealed class TypeChecker FloatLiteralSyntax expression => CheckFloatLiteral(expression, expectedType), MemberAccessSyntax expression => CheckMemberAccess(expression, expectedType), StructInitializerSyntax expression => CheckStructInitializer(expression, expectedType), - SizeSyntax expression => new SizeNode(node.Tokens, _typeResolver.ResolveType(expression.Type, Scope.Module.Value)), + SizeSyntax expression => new SizeNode(node.Tokens, ResolveType(expression.Type)), CastSyntax expression => CheckCast(expression, expectedType), _ => throw new ArgumentOutOfRangeException(nameof(node)) }; @@ -856,26 +765,16 @@ public sealed class TypeChecker private ExpressionNode CheckLocalIdentifier(LocalIdentifierSyntax expression, NubType? _) { // note(nub31): Local identifiers can be variables or a symbol in a module - var scopeIdent = Scope.LookupVariable(expression.NameToken); + var scopeIdent = CurrentScope.LookupVariable(expression.NameToken); if (scopeIdent != null) { return new VariableIdentifierNode(expression.Tokens, scopeIdent.Type, expression.NameToken); } - var module = GetImportedModule(Scope.Module.Value)!; - - var function = module.Functions(true).FirstOrDefault(x => x.NameToken.Value == expression.NameToken.Value); - if (function != null) + if (CurrentScope.Module.TryResolveFunc(expression.NameToken, out var function, out var _)) { - var parameters = function.Prototype.Parameters.Select(x => _typeResolver.ResolveType(x.Type, Scope.Module.Value)).ToList(); - var type = new NubFuncType(parameters, _typeResolver.ResolveType(function.Prototype.ReturnType, Scope.Module.Value)); - return new FuncIdentifierNode(expression.Tokens, type, Scope.Module, expression.NameToken, function.Prototype.ExternSymbolToken); - } - - var enumDef = module.Enums(true).FirstOrDefault(x => x.NameToken.Value == expression.NameToken.Value); - if (enumDef != null) - { - return new EnumReferenceIntermediateNode(expression.Tokens, Scope.Module, expression.NameToken); + var type = new NubFuncType(function.Parameters.Select(x => x.Type).ToList(), function.ReturnType); + return new LocalFuncIdentifierNode(expression.Tokens, type, expression.NameToken, function.ExternSymbolToken); } throw new CompileException(Diagnostic @@ -886,37 +785,20 @@ public sealed class TypeChecker private ExpressionNode CheckModuleIdentifier(ModuleIdentifierSyntax expression, NubType? _) { - var module = GetImportedModule(expression.ModuleToken.Value); - if (module == null) + var module = _repository.Get(expression.ModuleToken); + using (BeginRootScope(module)) { + if (module.TryResolveFunc(expression.NameToken, out var function, out var _)) + { + var type = new NubFuncType(function.Parameters.Select(x => x.Type).ToList(), function.ReturnType); + return new ModuleFuncIdentifierNode(expression.Tokens, type, expression.ModuleToken, expression.NameToken, function.ExternSymbolToken); + } + throw new CompileException(Diagnostic - .Error($"Module {expression.ModuleToken.Value} not found") - .WithHelp($"import \"{expression.ModuleToken.Value}\"") - .At(expression.ModuleToken) + .Error($"Module {expression.ModuleToken.Value} does not export a member named {expression.NameToken.Value}") + .At(expression) .Build()); } - - var function = module.Functions(false).FirstOrDefault(x => x.NameToken.Value == expression.NameToken.Value); - if (function != null) - { - using (BeginRootScope(expression.ModuleToken)) - { - var parameters = function.Prototype.Parameters.Select(x => _typeResolver.ResolveType(x.Type, Scope.Module.Value)).ToList(); - var type = new NubFuncType(parameters, _typeResolver.ResolveType(function.Prototype.ReturnType, Scope.Module.Value)); - return new FuncIdentifierNode(expression.Tokens, type, expression.ModuleToken, expression.NameToken, function.Prototype.ExternSymbolToken); - } - } - - var enumDef = module.Enums(false).FirstOrDefault(x => x.NameToken.Value == expression.NameToken.Value); - if (enumDef != null) - { - return new EnumReferenceIntermediateNode(expression.Tokens, expression.ModuleToken, expression.NameToken); - } - - throw new CompileException(Diagnostic - .Error($"Module {expression.ModuleToken.Value} does not export a member named {expression.NameToken.Value}") - .At(expression) - .Build()); } private ExpressionNode CheckStringLiteral(StringLiteralSyntax expression, NubType? expectedType) @@ -980,55 +862,6 @@ public sealed class TypeChecker { var target = CheckExpression(expression.Target); - if (target is EnumReferenceIntermediateNode enumReferenceIntermediate) - { - var enumDef = GetImportedModules() - .First(x => x.Name.Value == enumReferenceIntermediate.ModuleToken.Value) - .Module - .Enums(IsCurrentModule(enumReferenceIntermediate.ModuleToken)) - .First(x => x.NameToken.Value == enumReferenceIntermediate.NameToken.Value); - - var field = enumDef.Fields.FirstOrDefault(x => x.NameToken.Value == expression.MemberToken.Value); - if (field == null) - { - throw new CompileException(Diagnostic - .Error($"Enum {Scope.Module.Value}::{enumReferenceIntermediate.NameToken.Value} does not have a field named {expression.MemberToken.Value}") - .At(enumDef) - .Build()); - } - - var enumType = enumDef.Type != null ? _typeResolver.ResolveType(enumDef.Type, Scope.Module.Value) : new NubIntType(false, 64); - if (enumType is not NubIntType enumIntType) - { - throw new CompileException(Diagnostic.Error("Enum type must be an int type").At(enumDef.Type).Build()); - } - - if (enumIntType.Signed) - { - var fieldValue = CalculateSignedEnumFieldValue(enumDef, field); - return enumIntType.Width switch - { - 8 => new I8LiteralNode(expression.Tokens, (sbyte)fieldValue), - 16 => new I16LiteralNode(expression.Tokens, (short)fieldValue), - 32 => new I32LiteralNode(expression.Tokens, (int)fieldValue), - 64 => new I64LiteralNode(expression.Tokens, fieldValue), - _ => throw new ArgumentOutOfRangeException() - }; - } - else - { - var fieldValue = CalculateUnsignedEnumFieldValue(enumDef, field); - return enumIntType.Width switch - { - 8 => new U8LiteralNode(expression.Tokens, (byte)fieldValue), - 16 => new U16LiteralNode(expression.Tokens, (ushort)fieldValue), - 32 => new U32LiteralNode(expression.Tokens, (uint)fieldValue), - 64 => new U64LiteralNode(expression.Tokens, fieldValue), - _ => throw new ArgumentOutOfRangeException() - }; - } - } - switch (target.Type) { case NubStructType structType: @@ -1054,57 +887,13 @@ public sealed class TypeChecker } } - private static long CalculateSignedEnumFieldValue(EnumSyntax enumDef, EnumFieldSyntax field) - { - long currentValue = 0; - - foreach (var f in enumDef.Fields) - { - if (f.ValueToken != null) - { - currentValue = f.ValueToken.AsI64; - } - - if (f == field) - { - return currentValue; - } - - currentValue++; - } - - throw new UnreachableException(); - } - - private static ulong CalculateUnsignedEnumFieldValue(EnumSyntax enumDef, EnumFieldSyntax field) - { - ulong currentValue = 0; - - foreach (var f in enumDef.Fields) - { - if (f.ValueToken != null) - { - currentValue = f.ValueToken.AsU64; - } - - if (f == field) - { - return currentValue; - } - - currentValue++; - } - - throw new UnreachableException(); - } - private StructInitializerNode CheckStructInitializer(StructInitializerSyntax expression, NubType? expectedType) { NubStructType? structType = null; if (expression.StructType != null) { - var checkedType = _typeResolver.ResolveType(expression.StructType, Scope.Module.Value); + var checkedType = ResolveType(expression.StructType); if (checkedType is not NubStructType checkedStructType) { throw new UnreachableException("Parser fucked up"); @@ -1200,44 +989,85 @@ public sealed class TypeChecker _ => throw new ArgumentOutOfRangeException(nameof(statement)) }; } -} -public record Variable(IdentifierToken Name, NubType Type); - -public class Scope(IdentifierToken module, Scope? parent = null) -{ - private NubType? _returnType; - private readonly List _variables = []; - public IdentifierToken Module { get; } = module; - - public void DeclareVariable(Variable variable) + private NubType ResolveType(TypeSyntax type) { - _variables.Add(variable); - } - - public void SetReturnType(NubType returnType) - { - _returnType = returnType; - } - - public NubType? GetReturnType() - { - return _returnType ?? parent?.GetReturnType(); - } - - public Variable? LookupVariable(IdentifierToken name) - { - var variable = _variables.FirstOrDefault(x => x.Name.Value == name.Value); - if (variable != null) + return type switch { - return variable; + ArrayTypeSyntax arr => new NubArrayType(ResolveType(arr.BaseType)), + BoolTypeSyntax => new NubBoolType(), + IntTypeSyntax i => new NubIntType(i.Signed, i.Width), + FloatTypeSyntax f => new NubFloatType(f.Width), + FuncTypeSyntax func => new NubFuncType(func.Parameters.Select(ResolveType).ToList(), ResolveType(func.ReturnType)), + SliceTypeSyntax slice => new NubSliceType(ResolveType(slice.BaseType)), + ConstArrayTypeSyntax arr => new NubConstArrayType(ResolveType(arr.BaseType), arr.Size), + PointerTypeSyntax ptr => new NubPointerType(ResolveType(ptr.BaseType)), + StringTypeSyntax => new NubStringType(), + CustomTypeSyntax c => ResolveCustomType(c), + VoidTypeSyntax => new NubVoidType(), + _ => throw new NotSupportedException($"Unknown type syntax: {type}") + }; + } + + private NubType ResolveCustomType(CustomTypeSyntax customType) + { + var module = customType.ModuleToken != null ? _repository.Get(customType.ModuleToken) : CurrentScope.Module; + + var structType = module.StructTypes.FirstOrDefault(x => x.Name == customType.NameToken.Value); + if (structType != null) + { + return structType; } - return parent?.LookupVariable(name); + var enumType = module.EnumTypes.GetValueOrDefault(customType.NameToken.Value); + if (enumType != null) + { + return enumType; + } + + throw new CompileException(Diagnostic + .Error($"Type {customType.NameToken.Value} not found in module {module.Name}") + .At(customType) + .Build()); } - public Scope SubScope() + private record Variable(IdentifierToken Name, NubType Type); + + private class Scope(ModuleRepository.Module module, Scope? parent = null) { - return new Scope(Module, this); + private NubType? _returnType; + private readonly List _variables = []; + public ModuleRepository.Module Module { get; } = module; + + public void DeclareVariable(Variable variable) + { + _variables.Add(variable); + } + + public void SetReturnType(NubType returnType) + { + _returnType = returnType; + } + + public NubType? GetReturnType() + { + return _returnType ?? parent?.GetReturnType(); + } + + public Variable? LookupVariable(IdentifierToken name) + { + var variable = _variables.FirstOrDefault(x => x.Name.Value == name.Value); + if (variable != null) + { + return variable; + } + + return parent?.LookupVariable(name); + } + + public Scope SubScope() + { + return new Scope(Module, this); + } } } \ No newline at end of file diff --git a/compiler/NubLang/Ast/TypeResolver.cs b/compiler/NubLang/Ast/TypeResolver.cs deleted file mode 100644 index 1734341..0000000 --- a/compiler/NubLang/Ast/TypeResolver.cs +++ /dev/null @@ -1,96 +0,0 @@ -using NubLang.Diagnostics; -using NubLang.Syntax; - -namespace NubLang.Ast; - -public class TypeResolver -{ - private readonly Dictionary _modules; - private readonly Dictionary<(string Module, string Name), NubType> _typeCache = new(); - private readonly HashSet<(string Module, string Name)> _resolvingTypes = []; - - public TypeResolver(Dictionary modules) - { - _modules = modules; - } - - public NubType ResolveType(TypeSyntax type, string currentModule) - { - return type switch - { - ArrayTypeSyntax arr => new NubArrayType(ResolveType(arr.BaseType, currentModule)), - BoolTypeSyntax => new NubBoolType(), - IntTypeSyntax i => new NubIntType(i.Signed, i.Width), - FloatTypeSyntax f => new NubFloatType(f.Width), - FuncTypeSyntax func => new NubFuncType(func.Parameters.Select(x => ResolveType(x, currentModule)).ToList(), ResolveType(func.ReturnType, currentModule)), - SliceTypeSyntax slice => new NubSliceType(ResolveType(slice.BaseType, currentModule)), - ConstArrayTypeSyntax arr => new NubConstArrayType(ResolveType(arr.BaseType, currentModule), arr.Size), - PointerTypeSyntax ptr => new NubPointerType(ResolveType(ptr.BaseType, currentModule)), - StringTypeSyntax => new NubStringType(), - CustomTypeSyntax c => ResolveCustomType(c, currentModule), - VoidTypeSyntax => new NubVoidType(), - _ => throw new NotSupportedException($"Unknown type syntax: {type}") - }; - } - - private NubType ResolveCustomType(CustomTypeSyntax customType, string currentModule) - { - var module = _modules[customType.ModuleToken?.Value ?? currentModule]; - - var enumDef = module.Enums(true).FirstOrDefault(x => x.NameToken.Value == customType.NameToken.Value); - if (enumDef != null) - { - return enumDef.Type != null ? ResolveType(enumDef.Type, currentModule) : new NubIntType(false, 64); - } - - var structDef = module.Structs(true).FirstOrDefault(x => x.NameToken.Value == customType.NameToken.Value); - if (structDef != null) - { - var key = (customType.ModuleToken?.Value ?? currentModule, customType.NameToken.Value); - - if (_typeCache.TryGetValue(key, out var cachedType)) - { - return cachedType; - } - - if (!_resolvingTypes.Add(key)) - { - var placeholder = new NubStructType(customType.ModuleToken?.Value ?? currentModule, customType.NameToken.Value, structDef.Packed, []); - _typeCache[key] = placeholder; - return placeholder; - } - - try - { - var result = new NubStructType(customType.ModuleToken?.Value ?? currentModule, structDef.NameToken.Value, structDef.Packed, []); - _typeCache[key] = result; - - var fields = structDef.Fields - .Select(x => new NubStructFieldType(x.NameToken.Value, ResolveType(x.Type, currentModule), x.Value != null)) - .ToList(); - - result.Fields.AddRange(fields); - return result; - } - finally - { - _resolvingTypes.Remove(key); - } - } - - throw new TypeResolverException(Diagnostic - .Error($"Type {customType.NameToken.Value} not found in module {customType.ModuleToken?.Value ?? currentModule}") - .At(customType) - .Build()); - } -} - -public class TypeResolverException : Exception -{ - public Diagnostic Diagnostic { get; } - - public TypeResolverException(Diagnostic diagnostic) : base(diagnostic.Message) - { - Diagnostic = diagnostic; - } -} \ No newline at end of file diff --git a/compiler/NubLang/Generation/LlvmGenerator.cs b/compiler/NubLang/Generation/LlvmGenerator.cs index 3e91f66..0ab7fa4 100644 --- a/compiler/NubLang/Generation/LlvmGenerator.cs +++ b/compiler/NubLang/Generation/LlvmGenerator.cs @@ -1,5 +1,6 @@ using System.Text; using NubLang.Ast; +using NubLang.Types; namespace NubLang.Generation; @@ -334,7 +335,7 @@ public class LlvmGenerator Float32LiteralNode float32LiteralNode => EmitFloat32Literal(writer, float32LiteralNode), Float64LiteralNode float64LiteralNode => EmitFloat64Literal(writer, float64LiteralNode), FuncCallNode funcCallNode => EmitFuncCall(writer, funcCallNode), - FuncIdentifierNode funcIdentifierNode => EmitFuncIdentifier(writer, funcIdentifierNode), + ModuleFuncIdentifierNode funcIdentifierNode => EmitFuncIdentifier(writer, funcIdentifierNode), I16LiteralNode i16LiteralNode => EmitI16Literal(writer, i16LiteralNode), I32LiteralNode i32LiteralNode => EmitI32Literal(writer, i32LiteralNode), I64LiteralNode i64LiteralNode => EmitI64Literal(writer, i64LiteralNode), @@ -768,10 +769,10 @@ public class LlvmGenerator return new Tmp(result, funcCallNode.Type, false); } - private Tmp EmitFuncIdentifier(IndentedTextWriter writer, FuncIdentifierNode funcIdentifierNode) + private Tmp EmitFuncIdentifier(IndentedTextWriter writer, ModuleFuncIdentifierNode moduleFuncIdentifierNode) { - var name = FuncName(funcIdentifierNode.ModuleToken.Value, funcIdentifierNode.NameToken.Value, funcIdentifierNode.ExternSymbolToken?.Value); - return new Tmp($"@{name}", funcIdentifierNode.Type, false); + var name = FuncName(moduleFuncIdentifierNode.ModuleToken.Value, moduleFuncIdentifierNode.NameToken.Value, moduleFuncIdentifierNode.ExternSymbolToken?.Value); + return new Tmp($"@{name}", moduleFuncIdentifierNode.Type, false); } private Tmp EmitI16Literal(IndentedTextWriter writer, I16LiteralNode i16LiteralNode) diff --git a/compiler/NubLang/Modules/ModuleRepository.cs b/compiler/NubLang/Modules/ModuleRepository.cs new file mode 100644 index 0000000..a7c7203 --- /dev/null +++ b/compiler/NubLang/Modules/ModuleRepository.cs @@ -0,0 +1,246 @@ +using System.Diagnostics.CodeAnalysis; +using NubLang.Ast; +using NubLang.Diagnostics; +using NubLang.Syntax; +using NubLang.Types; + +namespace NubLang.Modules; + +public sealed class ModuleRepository +{ + public static ModuleRepository Create(List syntaxTrees) + { + var structTypes = new Dictionary<(string module, string name), NubStructType>(); + var enumTypes = new Dictionary<(string module, string name), NubIntType>(); + + foreach (var syntaxTree in syntaxTrees) + { + var module = syntaxTree.TopLevelSyntaxNodes.OfType().FirstOrDefault(); + if (module == null) + { + throw new CompileException(Diagnostic.Error("Module declaration missing").WithHelp("module \"main\"").Build()); + } + + foreach (var structSyntax in syntaxTree.TopLevelSyntaxNodes.OfType()) + { + // note(nub31): Since not all struct types are registered yet, we cannot register field types as they might reference unregistered structs + var key = (module.NameToken.Value, structSyntax.NameToken.Value); + structTypes.Add(key, new NubStructType(module.NameToken.Value, structSyntax.NameToken.Value, structSyntax.Packed, [])); + } + + foreach (var enumSyntax in syntaxTree.TopLevelSyntaxNodes.OfType()) + { + NubIntType? underlyingType = null; + if (enumSyntax.Type != null) + { + if (enumSyntax.Type is not IntTypeSyntax intType) + { + throw new CompileException(Diagnostic.Error("Underlying type of enum must be an integer type").At(enumSyntax.Type).Build()); + } + + underlyingType = new NubIntType(intType.Signed, intType.Width); + } + + underlyingType ??= new NubIntType(false, 64); + + var key = (module.NameToken.Value, enumSyntax.NameToken.Value); + enumTypes.Add(key, underlyingType); + } + } + + // note(nub31): Since all struct types are now registered, we can safely resolve the field types + foreach (var syntaxTree in syntaxTrees) + { + var module = syntaxTree.TopLevelSyntaxNodes.OfType().FirstOrDefault(); + if (module == null) + { + throw new CompileException(Diagnostic.Error("Module declaration missing").WithHelp("module \"main\"").Build()); + } + + foreach (var structSyntax in syntaxTree.TopLevelSyntaxNodes.OfType()) + { + var key = (module.NameToken.Value, structSyntax.NameToken.Value); + + structTypes[key].Fields = structSyntax.Fields + .Select(x => new NubStructFieldType(x.NameToken.Value, ResolveType(x.Type, module.NameToken.Value), x.Value != null)) + .ToList(); + } + } + + var modules = new Dictionary(); + + foreach (var syntaxTree in syntaxTrees) + { + var moduleDecl = syntaxTree.TopLevelSyntaxNodes.OfType().FirstOrDefault(); + if (moduleDecl == null) + { + throw new CompileException(Diagnostic.Error("Module declaration missing").WithHelp("module \"main\"").Build()); + } + + var functionPrototypes = new List(); + + foreach (var funcSyntax in syntaxTree.TopLevelSyntaxNodes.OfType()) + { + var returnType = ResolveType(funcSyntax.Prototype.ReturnType, moduleDecl.NameToken.Value); + var parameters = funcSyntax.Prototype.Parameters.Select(x => new FuncParameterNode(x.Tokens, x.NameToken, ResolveType(x.Type, moduleDecl.NameToken.Value))).ToList(); + functionPrototypes.Add(new FuncPrototypeNode(funcSyntax.Prototype.Tokens, funcSyntax.Prototype.NameToken, funcSyntax.Prototype.ExternSymbolToken, parameters, returnType)); + } + + var module = new Module + { + Name = moduleDecl.NameToken.Value, + StructTypes = structTypes.Where(x => x.Key.module == moduleDecl.NameToken.Value).Select(x => x.Value).ToList(), + EnumTypes = enumTypes + .Where(x => x.Key.module == moduleDecl.NameToken.Value) + .ToDictionary(x => x.Key.name, x => x.Value), + FunctionPrototypes = functionPrototypes + }; + + modules.Add(moduleDecl.NameToken.Value, module); + } + + return new ModuleRepository(modules); + + NubType ResolveType(TypeSyntax type, string currentModule) + { + return type switch + { + ArrayTypeSyntax arr => new NubArrayType(ResolveType(arr.BaseType, currentModule)), + BoolTypeSyntax => new NubBoolType(), + IntTypeSyntax i => new NubIntType(i.Signed, i.Width), + FloatTypeSyntax f => new NubFloatType(f.Width), + FuncTypeSyntax func => new NubFuncType(func.Parameters.Select(x => ResolveType(x, currentModule)).ToList(), ResolveType(func.ReturnType, currentModule)), + SliceTypeSyntax slice => new NubSliceType(ResolveType(slice.BaseType, currentModule)), + ConstArrayTypeSyntax arr => new NubConstArrayType(ResolveType(arr.BaseType, currentModule), arr.Size), + PointerTypeSyntax ptr => new NubPointerType(ResolveType(ptr.BaseType, currentModule)), + StringTypeSyntax => new NubStringType(), + CustomTypeSyntax c => ResolveCustomType(c, currentModule), + VoidTypeSyntax => new NubVoidType(), + _ => throw new NotSupportedException($"Unknown type syntax: {type}") + }; + } + + NubType ResolveCustomType(CustomTypeSyntax customType, string currentModule) + { + var customTypeKey = (customType.ModuleToken?.Value ?? currentModule, customType.NameToken.Value); + + var resolvedStructType = structTypes.GetValueOrDefault(customTypeKey); + if (resolvedStructType != null) + { + return resolvedStructType; + } + + var resolvedEnumType = enumTypes.GetValueOrDefault(customTypeKey); + if (resolvedEnumType != null) + { + return resolvedEnumType; + } + + throw new CompileException(Diagnostic + .Error($"Type {customType.NameToken.Value} not found in module {customType.ModuleToken?.Value ?? currentModule}") + .At(customType) + .Build()); + } + } + + private ModuleRepository(Dictionary modules) + { + _modules = modules; + } + + private readonly Dictionary _modules; + + public Module Get(IdentifierToken ident) + { + var module = _modules.GetValueOrDefault(ident.Value); + if (module == null) + { + throw new CompileException(Diagnostic.Error($"Module {ident.Value} was not found").At(ident).Build()); + } + + return module; + } + + public sealed class Module + { + public required string Name { get; init; } + public required List FunctionPrototypes { get; init; } = []; + public required List StructTypes { get; init; } = []; + public required Dictionary EnumTypes { get; init; } = []; + + public bool TryResolveFunc(IdentifierToken name, [NotNullWhen(true)] out FuncPrototypeNode? value, [NotNullWhen(false)] out Diagnostic? diagnostic) + { + value = FunctionPrototypes.FirstOrDefault(x => x.NameToken.Value == name.Value); + + if (value == null) + { + value = null; + diagnostic = Diagnostic.Error($"Func {name.Value} not found in module {Name}").At(name).Build(); + return false; + } + + diagnostic = null; + return true; + } + + public FuncPrototypeNode ResolveFunc(IdentifierToken name) + { + if (!TryResolveFunc(name, out var value, out var diagnostic)) + { + throw new CompileException(diagnostic); + } + + return value; + } + + public bool TryResolveStruct(IdentifierToken name, [NotNullWhen(true)] out NubStructType? value, [NotNullWhen(false)] out Diagnostic? diagnostic) + { + value = StructTypes.FirstOrDefault(x => x.Name == name.Value); + + if (value == null) + { + value = null; + diagnostic = Diagnostic.Error($"Struct {name.Value} not found in module {Name}").At(name).Build(); + return false; + } + + diagnostic = null; + return true; + } + + public NubStructType ResolveStruct(IdentifierToken name) + { + if (!TryResolveStruct(name, out var value, out var diagnostic)) + { + throw new CompileException(diagnostic); + } + + return value; + } + + public bool TryResolveEnum(IdentifierToken name, [NotNullWhen(true)] out NubIntType? value, [NotNullWhen(false)] out Diagnostic? diagnostic) + { + value = EnumTypes.GetValueOrDefault(name.Value); + + if (value == null) + { + value = null; + diagnostic = Diagnostic.Error($"Enum {name.Value} not found in module {Name}").At(name).Build(); + return false; + } + + diagnostic = null; + return true; + } + + public NubIntType ResolveEnum(IdentifierToken name) + { + if (!TryResolveEnum(name, out var value, out var diagnostic)) + { + throw new CompileException(diagnostic); + } + + return value; + } + } +} \ No newline at end of file diff --git a/compiler/NubLang/Syntax/Module.cs b/compiler/NubLang/Syntax/Module.cs deleted file mode 100644 index c635fb9..0000000 --- a/compiler/NubLang/Syntax/Module.cs +++ /dev/null @@ -1,60 +0,0 @@ -namespace NubLang.Syntax; - -public sealed class Module -{ - public static Dictionary Collect(List syntaxTrees) - { - var modules = new Dictionary(); - foreach (var syntaxTree in syntaxTrees) - { - var moduleDeclaration = syntaxTree.TopLevelSyntaxNodes.OfType().FirstOrDefault(); - if (moduleDeclaration != null) - { - if (!modules.TryGetValue(moduleDeclaration.NameToken.Value, out var module)) - { - module = new Module(); - modules.Add(moduleDeclaration.NameToken.Value, module); - } - - module._definitions.AddRange(syntaxTree.TopLevelSyntaxNodes); - } - } - - return modules; - } - - private readonly List _definitions = []; - - public List Structs(bool includePrivate) - { - return _definitions - .OfType() - .Where(x => x.Exported || includePrivate) - .ToList(); - } - - public List Functions(bool includePrivate) - { - return _definitions - .OfType() - .Where(x => x.Exported || includePrivate) - .ToList(); - } - - public List Enums(bool includePrivate) - { - return _definitions - .OfType() - .Where(x => x.Exported || includePrivate) - .ToList(); - } - - public List Imports() - { - return _definitions - .OfType() - .Select(x => x.NameToken.Value) - .Distinct() - .ToList(); - } -} \ No newline at end of file diff --git a/compiler/NubLang/Syntax/Parser.cs b/compiler/NubLang/Syntax/Parser.cs index bf3d7bf..c6f7c78 100644 --- a/compiler/NubLang/Syntax/Parser.cs +++ b/compiler/NubLang/Syntax/Parser.cs @@ -42,7 +42,6 @@ public sealed class Parser TopLevelSyntaxNode definition = keyword.Symbol switch { Symbol.Module => ParseModule(startIndex), - Symbol.Import => ParseImport(startIndex), Symbol.Func => ParseFunc(startIndex, exported, null), Symbol.Struct => ParseStruct(startIndex, exported, packed), Symbol.Enum => ParseEnum(startIndex, exported), @@ -73,12 +72,6 @@ public sealed class Parser return new SyntaxTree(topLevelSyntaxNodes); } - private ImportSyntax ParseImport(int startIndex) - { - var name = ExpectIdentifier(); - return new ImportSyntax(GetTokens(startIndex), name); - } - private ModuleSyntax ParseModule(int startIndex) { var name = ExpectIdentifier(); diff --git a/compiler/NubLang/Syntax/Syntax.cs b/compiler/NubLang/Syntax/Syntax.cs index 4c1f233..0c70250 100644 --- a/compiler/NubLang/Syntax/Syntax.cs +++ b/compiler/NubLang/Syntax/Syntax.cs @@ -8,8 +8,6 @@ public record TopLevelSyntaxNode(List Tokens) : SyntaxNode(Tokens); public record ModuleSyntax(List Tokens, IdentifierToken NameToken) : TopLevelSyntaxNode(Tokens); -public record ImportSyntax(List Tokens, IdentifierToken NameToken) : TopLevelSyntaxNode(Tokens); - public abstract record DefinitionSyntax(List Tokens, IdentifierToken NameToken, bool Exported) : TopLevelSyntaxNode(Tokens); public record FuncParameterSyntax(List Tokens, IdentifierToken NameToken, TypeSyntax Type) : SyntaxNode(Tokens); diff --git a/compiler/NubLang/Syntax/Token.cs b/compiler/NubLang/Syntax/Token.cs index 0d7e641..3be0c77 100644 --- a/compiler/NubLang/Syntax/Token.cs +++ b/compiler/NubLang/Syntax/Token.cs @@ -16,15 +16,11 @@ public record IntLiteralToken(SourceSpan Span, string Value, int Base) : Token(S { private string GetNumericValue() { - // Strip base prefixes: 0b, 0o, 0x return Base switch { - 2 when Value.StartsWith("0b", StringComparison.OrdinalIgnoreCase) - => Value.Substring(2), - 8 when Value.StartsWith("0o", StringComparison.OrdinalIgnoreCase) - => Value.Substring(2), - 16 when Value.StartsWith("0x", StringComparison.OrdinalIgnoreCase) - => Value.Substring(2), + 2 when Value.StartsWith("0b", StringComparison.OrdinalIgnoreCase) => Value[2..], + 8 when Value.StartsWith("0o", StringComparison.OrdinalIgnoreCase) => Value[2..], + 16 when Value.StartsWith("0x", StringComparison.OrdinalIgnoreCase) => Value[2..], _ => Value }; } @@ -95,7 +91,6 @@ public enum Symbol Func, Struct, Enum, - Import, Module, // Modifier @@ -159,7 +154,6 @@ public record SymbolToken(SourceSpan Span, Symbol Symbol) : Token(Span) Symbol.Extern => "extern", Symbol.Module => "module", Symbol.Export => "export", - Symbol.Import => "import", Symbol.Defer => "defer", Symbol.Enum => "enum", Symbol.Equal => "==", diff --git a/compiler/NubLang/Syntax/Tokenizer.cs b/compiler/NubLang/Syntax/Tokenizer.cs index 983bf93..1ca8129 100644 --- a/compiler/NubLang/Syntax/Tokenizer.cs +++ b/compiler/NubLang/Syntax/Tokenizer.cs @@ -262,7 +262,6 @@ public sealed class Tokenizer "packed" => Symbol.Packed, "module" => Symbol.Module, "export" => Symbol.Export, - "import" => Symbol.Import, _ => Symbol.None }, 5 => span switch diff --git a/compiler/NubLang/Syntax/TypedModule.cs b/compiler/NubLang/Syntax/TypedModule.cs deleted file mode 100644 index 55d7337..0000000 --- a/compiler/NubLang/Syntax/TypedModule.cs +++ /dev/null @@ -1,52 +0,0 @@ -using NubLang.Ast; - -namespace NubLang.Syntax; - -public sealed class TypedModule -{ - public static TypedModule FromModule(string name, Module module, Dictionary modules) - { - var typeResolver = new TypeResolver(modules); - - var functionPrototypes = new List(); - - foreach (var funcSyntax in module.Functions(true)) - { - var parameters = new List(); - foreach (var parameter in funcSyntax.Prototype.Parameters) - { - parameters.Add(new FuncParameterNode(parameter.Tokens, parameter.NameToken, typeResolver.ResolveType(parameter.Type, name))); - } - - var returnType = typeResolver.ResolveType(funcSyntax.Prototype.ReturnType, name); - - functionPrototypes.Add(new FuncPrototypeNode(funcSyntax.Tokens, funcSyntax.Prototype.NameToken, funcSyntax.Prototype.ExternSymbolToken, parameters, returnType)); - } - - var structTypes = new List(); - - foreach (var structSyntax in module.Structs(true)) - { - var fields = new List(); - foreach (var field in structSyntax.Fields) - { - fields.Add(new NubStructFieldType(field.NameToken.Value, typeResolver.ResolveType(field.Type, name), field.Value != null)); - } - - structTypes.Add(new NubStructType(name, structSyntax.NameToken.Value, structSyntax.Packed, fields)); - } - - return new TypedModule(functionPrototypes, structTypes, module.Imports()); - } - - public TypedModule(List functionPrototypes, List structTypes, List imports) - { - FunctionPrototypes = functionPrototypes; - StructTypes = structTypes; - Imports = imports; - } - - public List FunctionPrototypes { get; } - public List StructTypes { get; } - public List Imports { get; } -} \ No newline at end of file diff --git a/compiler/NubLang/Ast/NubType.cs b/compiler/NubLang/Types/NubType.cs similarity index 99% rename from compiler/NubLang/Ast/NubType.cs rename to compiler/NubLang/Types/NubType.cs index ba3ac93..de99b2e 100644 --- a/compiler/NubLang/Ast/NubType.cs +++ b/compiler/NubLang/Types/NubType.cs @@ -1,7 +1,7 @@ using System.Security.Cryptography; using System.Text; -namespace NubLang.Ast; +namespace NubLang.Types; public abstract class NubType : IEquatable { diff --git a/examples/playgroud/main.nub b/examples/playgroud/main.nub index 9b3deb9..eac807c 100644 --- a/examples/playgroud/main.nub +++ b/examples/playgroud/main.nub @@ -2,6 +2,12 @@ module main extern "puts" func puts(text: ^i8) +struct Test +{ + field: u32 +} + extern "main" func main(argc: i64, argv: [?]^i8) { + let x: Test = {} } \ No newline at end of file