This commit is contained in:
nub31
2025-10-31 14:42:58 +01:00
parent 031b118a24
commit 7c7624b1bc
17 changed files with 453 additions and 605 deletions

View File

@@ -1,6 +1,7 @@
using NubLang.Ast; using NubLang.Ast;
using NubLang.Diagnostics; using NubLang.Diagnostics;
using NubLang.Generation; using NubLang.Generation;
using NubLang.Modules;
using NubLang.Syntax; using NubLang.Syntax;
var diagnostics = new List<Diagnostic>(); var diagnostics = new List<Diagnostic>();
@@ -19,13 +20,24 @@ foreach (var file in args)
syntaxTrees.Add(syntaxTree); 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<List<TopLevelNode>>(); var compilationUnits = new List<List<TopLevelNode>>();
for (var i = 0; i < args.Length; i++) for (var i = 0; i < args.Length; i++)
{ {
var typeChecker = new TypeChecker(syntaxTrees[i], modules); var typeChecker = new TypeChecker();
var compilationUnit = typeChecker.Check(); var compilationUnit = typeChecker.Check(syntaxTrees[i], moduleRepository);
compilationUnits.Add(compilationUnit); compilationUnits.Add(compilationUnit);
diagnostics.AddRange(typeChecker.Diagnostics); diagnostics.AddRange(typeChecker.Diagnostics);

View File

@@ -55,7 +55,7 @@ internal class DefinitionHandler(WorkspaceManager workspaceManager) : Definition
return null; return null;
} }
case FuncIdentifierNode funcIdentifierNode: case ModuleFuncIdentifierNode funcIdentifierNode:
{ {
// var prototype = compilationUnit // var prototype = compilationUnit
// .ImportedFunctions // .ImportedFunctions

View File

@@ -8,59 +8,59 @@ public class WorkspaceManager(DiagnosticsPublisher diagnosticsPublisher)
{ {
private readonly Dictionary<string, SyntaxTree> _syntaxTrees = new(); private readonly Dictionary<string, SyntaxTree> _syntaxTrees = new();
private readonly Dictionary<string, List<TopLevelNode>> _compilationUnits = new(); private readonly Dictionary<string, List<TopLevelNode>> _compilationUnits = new();
private readonly Dictionary<string, TypedModule> _modules = new(); // private readonly Dictionary<string, TypedModule> _modules = new();
public void Init(string rootPath) public void Init(string rootPath)
{ {
var files = Directory.GetFiles(rootPath, "*.nub", SearchOption.AllDirectories); // var files = Directory.GetFiles(rootPath, "*.nub", SearchOption.AllDirectories);
foreach (var path in files) // foreach (var path in files)
{ // {
var text = File.ReadAllText(path); // var text = File.ReadAllText(path);
var tokenizer = new Tokenizer(path, text); // var tokenizer = new Tokenizer(path, text);
//
tokenizer.Tokenize(); // tokenizer.Tokenize();
diagnosticsPublisher.Publish(path, tokenizer.Diagnostics); // diagnosticsPublisher.Publish(path, tokenizer.Diagnostics);
//
var parser = new Parser(); // var parser = new Parser();
var parseResult = parser.Parse(tokenizer.Tokens); // var parseResult = parser.Parse(tokenizer.Tokens);
diagnosticsPublisher.Publish(path, parser.Diagnostics); // diagnosticsPublisher.Publish(path, parser.Diagnostics);
//
_syntaxTrees[path] = parseResult; // _syntaxTrees[path] = parseResult;
} // }
//
foreach (var (fsPath, syntaxTree) in _syntaxTrees) // foreach (var (fsPath, syntaxTree) in _syntaxTrees)
{ // {
var modules = Module.Collect(_syntaxTrees.Select(x => x.Value).ToList()); // var modules = Module.Collect(_syntaxTrees.Select(x => x.Value).ToList());
//
var typeChecker = new TypeChecker(syntaxTree, modules); // var typeChecker = new TypeChecker(syntaxTree, modules);
var result = typeChecker.Check(); // var result = typeChecker.Check();
diagnosticsPublisher.Publish(fsPath, typeChecker.Diagnostics); // diagnosticsPublisher.Publish(fsPath, typeChecker.Diagnostics);
//
_compilationUnits[fsPath] = result; // _compilationUnits[fsPath] = result;
} // }
} }
public void UpdateFile(DocumentUri path) public void UpdateFile(DocumentUri path)
{ {
var fsPath = path.GetFileSystemPath(); // var fsPath = path.GetFileSystemPath();
//
var text = File.ReadAllText(fsPath); // var text = File.ReadAllText(fsPath);
var tokenizer = new Tokenizer(fsPath, text); // var tokenizer = new Tokenizer(fsPath, text);
tokenizer.Tokenize(); // tokenizer.Tokenize();
diagnosticsPublisher.Publish(path, tokenizer.Diagnostics); // diagnosticsPublisher.Publish(path, tokenizer.Diagnostics);
//
var parser = new Parser(); // var parser = new Parser();
var syntaxTree = parser.Parse(tokenizer.Tokens); // var syntaxTree = parser.Parse(tokenizer.Tokens);
diagnosticsPublisher.Publish(path, parser.Diagnostics); // diagnosticsPublisher.Publish(path, parser.Diagnostics);
_syntaxTrees[fsPath] = syntaxTree; // _syntaxTrees[fsPath] = syntaxTree;
//
var modules = Module.Collect(_syntaxTrees.Select(x => x.Value).ToList()); // var modules = Module.Collect(_syntaxTrees.Select(x => x.Value).ToList());
//
var typeChecker = new TypeChecker(syntaxTree, modules); // var typeChecker = new TypeChecker(syntaxTree, modules);
var result = typeChecker.Check(); // var result = typeChecker.Check();
diagnosticsPublisher.Publish(fsPath, typeChecker.Diagnostics); // diagnosticsPublisher.Publish(fsPath, typeChecker.Diagnostics);
//
_compilationUnits[fsPath] = result; // _compilationUnits[fsPath] = result;
} }
public void RemoveFile(DocumentUri path) public void RemoveFile(DocumentUri path)

View File

@@ -1,12 +0,0 @@
using NubLang.Syntax;
namespace NubLang.Ast;
// public sealed class CompilationUnit(IdentifierToken module, List<FuncNode> functions, List<StructNode> structTypes, Dictionary<IdentifierToken, List<NubStructType>> importedStructTypes, Dictionary<IdentifierToken, List<FuncPrototypeNode>> importedFunctions)
// {
// public IdentifierToken Module { get; } = module;
// public List<FuncNode> Functions { get; } = functions;
// public List<StructNode> Structs { get; } = structTypes;
// public Dictionary<IdentifierToken, List<NubStructType>> ImportedStructTypes { get; } = importedStructTypes;
// public Dictionary<IdentifierToken, List<FuncPrototypeNode>> ImportedFunctions { get; } = importedFunctions;
// }

View File

@@ -1,4 +1,5 @@
using NubLang.Syntax; using NubLang.Syntax;
using NubLang.Types;
namespace NubLang.Ast; namespace NubLang.Ast;
@@ -31,16 +32,6 @@ public abstract class Node(List<Token> tokens)
public abstract class TopLevelNode(List<Token> tokens) : Node(tokens); public abstract class TopLevelNode(List<Token> tokens) : Node(tokens);
public class ImportNode(List<Token> tokens, IdentifierToken nameToken) : TopLevelNode(tokens)
{
public IdentifierToken NameToken { get; } = nameToken;
public override IEnumerable<Node> Children()
{
return [];
}
}
public class ModuleNode(List<Token> tokens, IdentifierToken nameToken) : TopLevelNode(tokens) public class ModuleNode(List<Token> tokens, IdentifierToken nameToken) : TopLevelNode(tokens)
{ {
public IdentifierToken NameToken { get; } = nameToken; public IdentifierToken NameToken { get; } = nameToken;
@@ -490,7 +481,18 @@ public class VariableIdentifierNode(List<Token> tokens, NubType type, Identifier
} }
} }
public class FuncIdentifierNode(List<Token> tokens, NubType type, IdentifierToken moduleToken, IdentifierToken nameToken, StringLiteralToken? externSymbolToken) : RValue(tokens, type) public class LocalFuncIdentifierNode(List<Token> tokens, NubType type, IdentifierToken nameToken, StringLiteralToken? externSymbolToken) : RValue(tokens, type)
{
public IdentifierToken NameToken { get; } = nameToken;
public StringLiteralToken? ExternSymbolToken { get; } = externSymbolToken;
public override IEnumerable<Node> Children()
{
return [];
}
}
public class ModuleFuncIdentifierNode(List<Token> tokens, NubType type, IdentifierToken moduleToken, IdentifierToken nameToken, StringLiteralToken? externSymbolToken) : RValue(tokens, type)
{ {
public IdentifierToken ModuleToken { get; } = moduleToken; public IdentifierToken ModuleToken { get; } = moduleToken;
public IdentifierToken NameToken { get; } = nameToken; public IdentifierToken NameToken { get; } = nameToken;
@@ -612,17 +614,4 @@ public class ConstArrayInitializerNode(List<Token> tokens, NubType type, List<Ex
} }
} }
public abstract class IntermediateExpression(List<Token> tokens) : ExpressionNode(tokens, new NubVoidType());
public class EnumReferenceIntermediateNode(List<Token> tokens, IdentifierToken moduleToken, IdentifierToken nameToken) : IntermediateExpression(tokens)
{
public IdentifierToken ModuleToken { get; } = moduleToken;
public IdentifierToken NameToken { get; } = nameToken;
public override IEnumerable<Node> Children()
{
return [];
}
}
#endregion #endregion

View File

@@ -1,32 +1,28 @@
using System.Diagnostics; using System.Diagnostics;
using NubLang.Diagnostics; using NubLang.Diagnostics;
using NubLang.Modules;
using NubLang.Syntax; using NubLang.Syntax;
using NubLang.Types;
namespace NubLang.Ast; namespace NubLang.Ast;
public sealed class TypeChecker public sealed class TypeChecker
{ {
private readonly SyntaxTree _syntaxTree; private SyntaxTree _syntaxTree = null!;
private readonly Dictionary<string, Module> _modules; private ModuleRepository _repository = null!;
private readonly Stack<Scope> _scopes = []; private Stack<Scope> _scopes = [];
private readonly TypeResolver _typeResolver; private Scope CurrentScope => _scopes.Peek();
private Scope Scope => _scopes.Peek(); public List<Diagnostic> Diagnostics { get; set; } = [];
public List<Diagnostic> Diagnostics { get; } = []; public List<TopLevelNode> Check(SyntaxTree syntaxTree, ModuleRepository repository)
public TypeChecker(SyntaxTree syntaxTree, Dictionary<string, Module> modules)
{ {
_syntaxTree = syntaxTree; _syntaxTree = syntaxTree;
_modules = modules; _repository = repository;
_typeResolver = new TypeResolver(_modules); Diagnostics = [];
} _scopes = [];
public List<TopLevelNode> Check()
{
_scopes.Clear();
var moduleDeclarations = _syntaxTree.TopLevelSyntaxNodes.OfType<ModuleSyntax>().ToList(); var moduleDeclarations = _syntaxTree.TopLevelSyntaxNodes.OfType<ModuleSyntax>().ToList();
if (moduleDeclarations.Count == 0) 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()); Diagnostics.Add(Diagnostic.Error("Multiple module declarations").WithHelp("Remove extra module declarations").Build());
} }
var moduleName = moduleDeclarations[0].NameToken; var module = _repository.Get(moduleDeclarations[0].NameToken);
var importDeclarations = _syntaxTree.TopLevelSyntaxNodes.OfType<ImportSyntax>().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 topLevelNodes = new List<TopLevelNode>(); var topLevelNodes = new List<TopLevelNode>();
using (BeginRootScope(moduleName)) using (BeginRootScope(module))
{ {
foreach (var topLevelSyntaxNode in _syntaxTree.TopLevelSyntaxNodes) foreach (var topLevelSyntaxNode in _syntaxTree.TopLevelSyntaxNodes)
{ {
@@ -98,9 +54,6 @@ public sealed class TypeChecker
case StructSyntax structSyntax: case StructSyntax structSyntax:
topLevelNodes.Add(CheckStructDefinition(structSyntax)); topLevelNodes.Add(CheckStructDefinition(structSyntax));
break; break;
case ImportSyntax importSyntax:
topLevelNodes.Add(new ImportNode(importSyntax.Tokens, importSyntax.NameToken));
break;
case ModuleSyntax moduleSyntax: case ModuleSyntax moduleSyntax:
topLevelNodes.Add(new ModuleNode(moduleSyntax.Tokens, moduleSyntax.NameToken)); topLevelNodes.Add(new ModuleNode(moduleSyntax.Tokens, moduleSyntax.NameToken));
break; break;
@@ -113,58 +66,15 @@ public sealed class TypeChecker
return topLevelNodes; return topLevelNodes;
} }
private (IdentifierToken Name, Module Module) GetCurrentModule()
{
var currentModule = _syntaxTree.TopLevelSyntaxNodes.OfType<ModuleSyntax>().First().NameToken;
return (currentModule, _modules[currentModule.Value]);
}
private List<(IdentifierToken Name, Module Module)> GetImportedModules()
{
var currentModule = _syntaxTree.TopLevelSyntaxNodes.OfType<ModuleSyntax>().First().NameToken;
return _syntaxTree.TopLevelSyntaxNodes
.OfType<ImportSyntax>()
.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<ModuleSyntax>().First().NameToken;
if (module == currentModule.Value)
{
return _modules[currentModule.Value];
}
var import = _syntaxTree.TopLevelSyntaxNodes.OfType<ImportSyntax>().FirstOrDefault(x => x.NameToken.Value == module);
if (import != null)
{
return _modules[import.NameToken.Value];
}
return null;
}
private ScopeDisposer BeginScope() private ScopeDisposer BeginScope()
{ {
_scopes.Push(Scope.SubScope()); _scopes.Push(CurrentScope.SubScope());
return new ScopeDisposer(this); 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); return new ScopeDisposer(this);
} }
@@ -186,10 +96,10 @@ public sealed class TypeChecker
{ {
var prototype = CheckFuncPrototype(node.Prototype); var prototype = CheckFuncPrototype(node.Prototype);
Scope.SetReturnType(prototype.ReturnType); CurrentScope.SetReturnType(prototype.ReturnType);
foreach (var parameter in prototype.Parameters) 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); var body = node.Body == null ? null : CheckBlock(node.Body);
@@ -203,7 +113,7 @@ public sealed class TypeChecker
foreach (var field in structSyntax.Fields) foreach (var field in structSyntax.Fields)
{ {
var fieldType = _typeResolver.ResolveType(field.Type, Scope.Module.Value); var fieldType = ResolveType(field.Type);
ExpressionNode? value = null; ExpressionNode? value = null;
if (field.Value != null) if (field.Value != null)
{ {
@@ -220,8 +130,7 @@ public sealed class TypeChecker
fields.Add(new StructFieldNode(field.Tokens, field.NameToken, fieldType, value)); fields.Add(new StructFieldNode(field.Tokens, field.NameToken, fieldType, value));
} }
var currentModule = GetCurrentModule(); 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());
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());
return new StructNode(structSyntax.Tokens, structSyntax.NameToken, type, structSyntax.Packed, fields); return new StructNode(structSyntax.Tokens, structSyntax.NameToken, type, structSyntax.Packed, fields);
} }
@@ -261,7 +170,7 @@ public sealed class TypeChecker
if (statement.Value != null) if (statement.Value != null)
{ {
var expectedReturnType = Scope.GetReturnType(); var expectedReturnType = CurrentScope.GetReturnType();
value = CheckExpression(statement.Value, expectedReturnType); value = CheckExpression(statement.Value, expectedReturnType);
} }
@@ -286,7 +195,7 @@ public sealed class TypeChecker
if (statement.ExplicitType != null) if (statement.ExplicitType != null)
{ {
type = _typeResolver.ResolveType(statement.ExplicitType, Scope.Module.Value); type = ResolveType(statement.ExplicitType);
} }
if (statement.Assignment != null) if (statement.Assignment != null)
@@ -314,7 +223,7 @@ public sealed class TypeChecker
.Build()); .Build());
} }
Scope.DeclareVariable(new Variable(statement.NameToken, type)); CurrentScope.DeclareVariable(new Variable(statement.NameToken, type));
return new VariableDeclarationNode(statement.Tokens, statement.NameToken, assignmentNode, type); return new VariableDeclarationNode(statement.Tokens, statement.NameToken, assignmentNode, type);
} }
@@ -337,10 +246,10 @@ public sealed class TypeChecker
{ {
using (BeginScope()) using (BeginScope())
{ {
Scope.DeclareVariable(new Variable(forSyntax.ElementNameToken, sliceType.ElementType)); CurrentScope.DeclareVariable(new Variable(forSyntax.ElementNameToken, sliceType.ElementType));
if (forSyntax.IndexNameToken != null) 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); var body = CheckBlock(forSyntax.Body);
@@ -351,10 +260,10 @@ public sealed class TypeChecker
{ {
using (BeginScope()) using (BeginScope())
{ {
Scope.DeclareVariable(new Variable(forSyntax.ElementNameToken, constArrayType.ElementType)); CurrentScope.DeclareVariable(new Variable(forSyntax.ElementNameToken, constArrayType.ElementType));
if (forSyntax.IndexNameToken != null) 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); var body = CheckBlock(forSyntax.Body);
@@ -376,10 +285,10 @@ public sealed class TypeChecker
var parameters = new List<FuncParameterNode>(); var parameters = new List<FuncParameterNode>();
foreach (var parameter in statement.Parameters) 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) private ExpressionNode CheckExpression(ExpressionSyntax node, NubType? expectedType = null)
@@ -401,7 +310,7 @@ public sealed class TypeChecker
FloatLiteralSyntax expression => CheckFloatLiteral(expression, expectedType), FloatLiteralSyntax expression => CheckFloatLiteral(expression, expectedType),
MemberAccessSyntax expression => CheckMemberAccess(expression, expectedType), MemberAccessSyntax expression => CheckMemberAccess(expression, expectedType),
StructInitializerSyntax expression => CheckStructInitializer(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), CastSyntax expression => CheckCast(expression, expectedType),
_ => throw new ArgumentOutOfRangeException(nameof(node)) _ => throw new ArgumentOutOfRangeException(nameof(node))
}; };
@@ -856,26 +765,16 @@ public sealed class TypeChecker
private ExpressionNode CheckLocalIdentifier(LocalIdentifierSyntax expression, NubType? _) private ExpressionNode CheckLocalIdentifier(LocalIdentifierSyntax expression, NubType? _)
{ {
// note(nub31): Local identifiers can be variables or a symbol in a module // 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) if (scopeIdent != null)
{ {
return new VariableIdentifierNode(expression.Tokens, scopeIdent.Type, expression.NameToken); return new VariableIdentifierNode(expression.Tokens, scopeIdent.Type, expression.NameToken);
} }
var module = GetImportedModule(Scope.Module.Value)!; if (CurrentScope.Module.TryResolveFunc(expression.NameToken, out var function, out var _))
var function = module.Functions(true).FirstOrDefault(x => x.NameToken.Value == expression.NameToken.Value);
if (function != null)
{ {
var parameters = function.Prototype.Parameters.Select(x => _typeResolver.ResolveType(x.Type, Scope.Module.Value)).ToList(); var type = new NubFuncType(function.Parameters.Select(x => x.Type).ToList(), function.ReturnType);
var type = new NubFuncType(parameters, _typeResolver.ResolveType(function.Prototype.ReturnType, Scope.Module.Value)); return new LocalFuncIdentifierNode(expression.Tokens, type, expression.NameToken, function.ExternSymbolToken);
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);
} }
throw new CompileException(Diagnostic throw new CompileException(Diagnostic
@@ -886,31 +785,13 @@ public sealed class TypeChecker
private ExpressionNode CheckModuleIdentifier(ModuleIdentifierSyntax expression, NubType? _) private ExpressionNode CheckModuleIdentifier(ModuleIdentifierSyntax expression, NubType? _)
{ {
var module = GetImportedModule(expression.ModuleToken.Value); var module = _repository.Get(expression.ModuleToken);
if (module == null) using (BeginRootScope(module))
{ {
throw new CompileException(Diagnostic if (module.TryResolveFunc(expression.NameToken, out var function, out var _))
.Error($"Module {expression.ModuleToken.Value} not found")
.WithHelp($"import \"{expression.ModuleToken.Value}\"")
.At(expression.ModuleToken)
.Build());
}
var function = module.Functions(false).FirstOrDefault(x => x.NameToken.Value == expression.NameToken.Value);
if (function != null)
{ {
using (BeginRootScope(expression.ModuleToken)) 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);
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 throw new CompileException(Diagnostic
@@ -918,6 +799,7 @@ public sealed class TypeChecker
.At(expression) .At(expression)
.Build()); .Build());
} }
}
private ExpressionNode CheckStringLiteral(StringLiteralSyntax expression, NubType? expectedType) private ExpressionNode CheckStringLiteral(StringLiteralSyntax expression, NubType? expectedType)
{ {
@@ -980,55 +862,6 @@ public sealed class TypeChecker
{ {
var target = CheckExpression(expression.Target); 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) switch (target.Type)
{ {
case NubStructType structType: 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) private StructInitializerNode CheckStructInitializer(StructInitializerSyntax expression, NubType? expectedType)
{ {
NubStructType? structType = null; NubStructType? structType = null;
if (expression.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) if (checkedType is not NubStructType checkedStructType)
{ {
throw new UnreachableException("Parser fucked up"); throw new UnreachableException("Parser fucked up");
@@ -1200,15 +989,55 @@ public sealed class TypeChecker
_ => throw new ArgumentOutOfRangeException(nameof(statement)) _ => throw new ArgumentOutOfRangeException(nameof(statement))
}; };
} }
private NubType ResolveType(TypeSyntax type)
{
return type switch
{
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}")
};
} }
public record Variable(IdentifierToken Name, NubType Type); private NubType ResolveCustomType(CustomTypeSyntax customType)
{
var module = customType.ModuleToken != null ? _repository.Get(customType.ModuleToken) : CurrentScope.Module;
public class Scope(IdentifierToken module, Scope? parent = null) var structType = module.StructTypes.FirstOrDefault(x => x.Name == customType.NameToken.Value);
if (structType != null)
{
return structType;
}
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());
}
private record Variable(IdentifierToken Name, NubType Type);
private class Scope(ModuleRepository.Module module, Scope? parent = null)
{ {
private NubType? _returnType; private NubType? _returnType;
private readonly List<Variable> _variables = []; private readonly List<Variable> _variables = [];
public IdentifierToken Module { get; } = module; public ModuleRepository.Module Module { get; } = module;
public void DeclareVariable(Variable variable) public void DeclareVariable(Variable variable)
{ {
@@ -1241,3 +1070,4 @@ public class Scope(IdentifierToken module, Scope? parent = null)
return new Scope(Module, this); return new Scope(Module, this);
} }
} }
}

View File

@@ -1,96 +0,0 @@
using NubLang.Diagnostics;
using NubLang.Syntax;
namespace NubLang.Ast;
public class TypeResolver
{
private readonly Dictionary<string, Module> _modules;
private readonly Dictionary<(string Module, string Name), NubType> _typeCache = new();
private readonly HashSet<(string Module, string Name)> _resolvingTypes = [];
public TypeResolver(Dictionary<string, Module> 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;
}
}

View File

@@ -1,5 +1,6 @@
using System.Text; using System.Text;
using NubLang.Ast; using NubLang.Ast;
using NubLang.Types;
namespace NubLang.Generation; namespace NubLang.Generation;
@@ -334,7 +335,7 @@ public class LlvmGenerator
Float32LiteralNode float32LiteralNode => EmitFloat32Literal(writer, float32LiteralNode), Float32LiteralNode float32LiteralNode => EmitFloat32Literal(writer, float32LiteralNode),
Float64LiteralNode float64LiteralNode => EmitFloat64Literal(writer, float64LiteralNode), Float64LiteralNode float64LiteralNode => EmitFloat64Literal(writer, float64LiteralNode),
FuncCallNode funcCallNode => EmitFuncCall(writer, funcCallNode), FuncCallNode funcCallNode => EmitFuncCall(writer, funcCallNode),
FuncIdentifierNode funcIdentifierNode => EmitFuncIdentifier(writer, funcIdentifierNode), ModuleFuncIdentifierNode funcIdentifierNode => EmitFuncIdentifier(writer, funcIdentifierNode),
I16LiteralNode i16LiteralNode => EmitI16Literal(writer, i16LiteralNode), I16LiteralNode i16LiteralNode => EmitI16Literal(writer, i16LiteralNode),
I32LiteralNode i32LiteralNode => EmitI32Literal(writer, i32LiteralNode), I32LiteralNode i32LiteralNode => EmitI32Literal(writer, i32LiteralNode),
I64LiteralNode i64LiteralNode => EmitI64Literal(writer, i64LiteralNode), I64LiteralNode i64LiteralNode => EmitI64Literal(writer, i64LiteralNode),
@@ -768,10 +769,10 @@ public class LlvmGenerator
return new Tmp(result, funcCallNode.Type, false); 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); var name = FuncName(moduleFuncIdentifierNode.ModuleToken.Value, moduleFuncIdentifierNode.NameToken.Value, moduleFuncIdentifierNode.ExternSymbolToken?.Value);
return new Tmp($"@{name}", funcIdentifierNode.Type, false); return new Tmp($"@{name}", moduleFuncIdentifierNode.Type, false);
} }
private Tmp EmitI16Literal(IndentedTextWriter writer, I16LiteralNode i16LiteralNode) private Tmp EmitI16Literal(IndentedTextWriter writer, I16LiteralNode i16LiteralNode)

View File

@@ -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<SyntaxTree> 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<ModuleSyntax>().FirstOrDefault();
if (module == null)
{
throw new CompileException(Diagnostic.Error("Module declaration missing").WithHelp("module \"main\"").Build());
}
foreach (var structSyntax in syntaxTree.TopLevelSyntaxNodes.OfType<StructSyntax>())
{
// 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<EnumSyntax>())
{
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<ModuleSyntax>().FirstOrDefault();
if (module == null)
{
throw new CompileException(Diagnostic.Error("Module declaration missing").WithHelp("module \"main\"").Build());
}
foreach (var structSyntax in syntaxTree.TopLevelSyntaxNodes.OfType<StructSyntax>())
{
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<string, Module>();
foreach (var syntaxTree in syntaxTrees)
{
var moduleDecl = syntaxTree.TopLevelSyntaxNodes.OfType<ModuleSyntax>().FirstOrDefault();
if (moduleDecl == null)
{
throw new CompileException(Diagnostic.Error("Module declaration missing").WithHelp("module \"main\"").Build());
}
var functionPrototypes = new List<FuncPrototypeNode>();
foreach (var funcSyntax in syntaxTree.TopLevelSyntaxNodes.OfType<FuncSyntax>())
{
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<string, Module> modules)
{
_modules = modules;
}
private readonly Dictionary<string, Module> _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<FuncPrototypeNode> FunctionPrototypes { get; init; } = [];
public required List<NubStructType> StructTypes { get; init; } = [];
public required Dictionary<string, NubIntType> 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;
}
}
}

View File

@@ -1,60 +0,0 @@
namespace NubLang.Syntax;
public sealed class Module
{
public static Dictionary<string, Module> Collect(List<SyntaxTree> syntaxTrees)
{
var modules = new Dictionary<string, Module>();
foreach (var syntaxTree in syntaxTrees)
{
var moduleDeclaration = syntaxTree.TopLevelSyntaxNodes.OfType<ModuleSyntax>().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<TopLevelSyntaxNode> _definitions = [];
public List<StructSyntax> Structs(bool includePrivate)
{
return _definitions
.OfType<StructSyntax>()
.Where(x => x.Exported || includePrivate)
.ToList();
}
public List<FuncSyntax> Functions(bool includePrivate)
{
return _definitions
.OfType<FuncSyntax>()
.Where(x => x.Exported || includePrivate)
.ToList();
}
public List<EnumSyntax> Enums(bool includePrivate)
{
return _definitions
.OfType<EnumSyntax>()
.Where(x => x.Exported || includePrivate)
.ToList();
}
public List<string> Imports()
{
return _definitions
.OfType<ImportSyntax>()
.Select(x => x.NameToken.Value)
.Distinct()
.ToList();
}
}

View File

@@ -42,7 +42,6 @@ public sealed class Parser
TopLevelSyntaxNode definition = keyword.Symbol switch TopLevelSyntaxNode definition = keyword.Symbol switch
{ {
Symbol.Module => ParseModule(startIndex), Symbol.Module => ParseModule(startIndex),
Symbol.Import => ParseImport(startIndex),
Symbol.Func => ParseFunc(startIndex, exported, null), Symbol.Func => ParseFunc(startIndex, exported, null),
Symbol.Struct => ParseStruct(startIndex, exported, packed), Symbol.Struct => ParseStruct(startIndex, exported, packed),
Symbol.Enum => ParseEnum(startIndex, exported), Symbol.Enum => ParseEnum(startIndex, exported),
@@ -73,12 +72,6 @@ public sealed class Parser
return new SyntaxTree(topLevelSyntaxNodes); return new SyntaxTree(topLevelSyntaxNodes);
} }
private ImportSyntax ParseImport(int startIndex)
{
var name = ExpectIdentifier();
return new ImportSyntax(GetTokens(startIndex), name);
}
private ModuleSyntax ParseModule(int startIndex) private ModuleSyntax ParseModule(int startIndex)
{ {
var name = ExpectIdentifier(); var name = ExpectIdentifier();

View File

@@ -8,8 +8,6 @@ public record TopLevelSyntaxNode(List<Token> Tokens) : SyntaxNode(Tokens);
public record ModuleSyntax(List<Token> Tokens, IdentifierToken NameToken) : TopLevelSyntaxNode(Tokens); public record ModuleSyntax(List<Token> Tokens, IdentifierToken NameToken) : TopLevelSyntaxNode(Tokens);
public record ImportSyntax(List<Token> Tokens, IdentifierToken NameToken) : TopLevelSyntaxNode(Tokens);
public abstract record DefinitionSyntax(List<Token> Tokens, IdentifierToken NameToken, bool Exported) : TopLevelSyntaxNode(Tokens); public abstract record DefinitionSyntax(List<Token> Tokens, IdentifierToken NameToken, bool Exported) : TopLevelSyntaxNode(Tokens);
public record FuncParameterSyntax(List<Token> Tokens, IdentifierToken NameToken, TypeSyntax Type) : SyntaxNode(Tokens); public record FuncParameterSyntax(List<Token> Tokens, IdentifierToken NameToken, TypeSyntax Type) : SyntaxNode(Tokens);

View File

@@ -16,15 +16,11 @@ public record IntLiteralToken(SourceSpan Span, string Value, int Base) : Token(S
{ {
private string GetNumericValue() private string GetNumericValue()
{ {
// Strip base prefixes: 0b, 0o, 0x
return Base switch return Base switch
{ {
2 when Value.StartsWith("0b", StringComparison.OrdinalIgnoreCase) 2 when Value.StartsWith("0b", StringComparison.OrdinalIgnoreCase) => Value[2..],
=> Value.Substring(2), 8 when Value.StartsWith("0o", StringComparison.OrdinalIgnoreCase) => Value[2..],
8 when Value.StartsWith("0o", StringComparison.OrdinalIgnoreCase) 16 when Value.StartsWith("0x", StringComparison.OrdinalIgnoreCase) => Value[2..],
=> Value.Substring(2),
16 when Value.StartsWith("0x", StringComparison.OrdinalIgnoreCase)
=> Value.Substring(2),
_ => Value _ => Value
}; };
} }
@@ -95,7 +91,6 @@ public enum Symbol
Func, Func,
Struct, Struct,
Enum, Enum,
Import,
Module, Module,
// Modifier // Modifier
@@ -159,7 +154,6 @@ public record SymbolToken(SourceSpan Span, Symbol Symbol) : Token(Span)
Symbol.Extern => "extern", Symbol.Extern => "extern",
Symbol.Module => "module", Symbol.Module => "module",
Symbol.Export => "export", Symbol.Export => "export",
Symbol.Import => "import",
Symbol.Defer => "defer", Symbol.Defer => "defer",
Symbol.Enum => "enum", Symbol.Enum => "enum",
Symbol.Equal => "==", Symbol.Equal => "==",

View File

@@ -262,7 +262,6 @@ public sealed class Tokenizer
"packed" => Symbol.Packed, "packed" => Symbol.Packed,
"module" => Symbol.Module, "module" => Symbol.Module,
"export" => Symbol.Export, "export" => Symbol.Export,
"import" => Symbol.Import,
_ => Symbol.None _ => Symbol.None
}, },
5 => span switch 5 => span switch

View File

@@ -1,52 +0,0 @@
using NubLang.Ast;
namespace NubLang.Syntax;
public sealed class TypedModule
{
public static TypedModule FromModule(string name, Module module, Dictionary<string, Module> modules)
{
var typeResolver = new TypeResolver(modules);
var functionPrototypes = new List<FuncPrototypeNode>();
foreach (var funcSyntax in module.Functions(true))
{
var parameters = new List<FuncParameterNode>();
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<NubStructType>();
foreach (var structSyntax in module.Structs(true))
{
var fields = new List<NubStructFieldType>();
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<FuncPrototypeNode> functionPrototypes, List<NubStructType> structTypes, List<string> imports)
{
FunctionPrototypes = functionPrototypes;
StructTypes = structTypes;
Imports = imports;
}
public List<FuncPrototypeNode> FunctionPrototypes { get; }
public List<NubStructType> StructTypes { get; }
public List<string> Imports { get; }
}

View File

@@ -1,7 +1,7 @@
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Text; using System.Text;
namespace NubLang.Ast; namespace NubLang.Types;
public abstract class NubType : IEquatable<NubType> public abstract class NubType : IEquatable<NubType>
{ {

View File

@@ -2,6 +2,12 @@ module main
extern "puts" func puts(text: ^i8) extern "puts" func puts(text: ^i8)
struct Test
{
field: u32
}
extern "main" func main(argc: i64, argv: [?]^i8) extern "main" func main(argc: i64, argv: [?]^i8)
{ {
let x: Test = {}
} }