From c65fbeba132e13f88abeddb6571b1fe879b20b52 Mon Sep 17 00:00:00 2001 From: nub31 Date: Tue, 10 Feb 2026 23:03:27 +0100 Subject: [PATCH] ... --- compiler/Diagnostic.cs | 140 +++++++++++++++++++++------------------- compiler/Generator.cs | 12 +++- compiler/ModuleGraph.cs | 23 ++++--- compiler/NubType.cs | 134 +++++++++++++++++++++----------------- compiler/Parser.cs | 76 ++++++++++++---------- compiler/Program.cs | 2 +- compiler/Tokenizer.cs | 24 ++++--- compiler/TypeChecker.cs | 54 ++++++++++------ 8 files changed, 266 insertions(+), 199 deletions(-) diff --git a/compiler/Diagnostic.cs b/compiler/Diagnostic.cs index 016615e..1d4b46e 100644 --- a/compiler/Diagnostic.cs +++ b/compiler/Diagnostic.cs @@ -1,88 +1,96 @@ namespace Compiler; -public sealed class Diagnostic(DiagnosticSeverity severity, string message, string? help, FileInfo? file) +public class Diagnostic { - public static DiagnosticBuilder Info(string message) => new DiagnosticBuilder(DiagnosticSeverity.Info, message); - public static DiagnosticBuilder Warning(string message) => new DiagnosticBuilder(DiagnosticSeverity.Warning, message); - public static DiagnosticBuilder Error(string message) => new DiagnosticBuilder(DiagnosticSeverity.Error, message); + public static Builder Info(string message) => new Builder(DiagnosticSeverity.Info, message); + public static Builder Warning(string message) => new Builder(DiagnosticSeverity.Warning, message); + public static Builder Error(string message) => new Builder(DiagnosticSeverity.Error, message); - public DiagnosticSeverity Severity { get; } = severity; - public string Message { get; } = message; - public string? Help { get; } = help; - public FileInfo? File { get; } = file; -} - -public sealed class DiagnosticBuilder(DiagnosticSeverity severity, string message) -{ - private FileInfo? file; - private string? help; - - public DiagnosticBuilder At(string fileName, int line, int column, int length) + private Diagnostic(DiagnosticSeverity severity, string message, string? help, FileInfo? file) { - file = new FileInfo(fileName, line, column, length); - return this; + Severity = severity; + Message = message; + Help = help; + File = file; } - public DiagnosticBuilder At(string fileName, Token? token) + public class FileInfo(string file, int line, int column, int length) { - if (token != null) + public string File { get; } = file; + public int Line { get; } = line; + public int Column { get; } = column; + public int Length { get; } = length; + } + + public DiagnosticSeverity Severity { get; } + public string Message { get; } + public string? Help { get; } + public FileInfo? File { get; } + + public enum DiagnosticSeverity + { + Info, + Warning, + Error, + } + + public class Builder(DiagnosticSeverity severity, string message) + { + private FileInfo? file; + private string? help; + + public Builder At(string fileName, int line, int column, int length) { - At(fileName, token.Line, token.Column, token.Length); + file = new FileInfo(fileName, line, column, length); + return this; } - return this; - } - - public DiagnosticBuilder At(string fileName, Node? node) - { - if (node != null && node.Tokens.Count != 0) + public Builder At(string fileName, Token? token) { - // todo(nub31): Calculate length based on last token - At(fileName, node.Tokens[0]); + if (token != null) + { + At(fileName, token.Line, token.Column, token.Length); + } + + return this; } - return this; - } - - public DiagnosticBuilder At(string fileName, TypedNode? node) - { - if (node != null && node.Tokens.Count != 0) + public Builder At(string fileName, Node? node) { - // todo(nub31): Calculate length based on last token - At(fileName, node.Tokens[0]); + if (node != null && node.Tokens.Count != 0) + { + // todo(nub31): Calculate length based on last token + At(fileName, node.Tokens[0]); + } + + return this; } - return this; - } + public Builder At(string fileName, TypedNode? node) + { + if (node != null && node.Tokens.Count != 0) + { + // todo(nub31): Calculate length based on last token + At(fileName, node.Tokens[0]); + } - public DiagnosticBuilder WithHelp(string helpMessage) - { - help = helpMessage; - return this; - } + return this; + } - public Diagnostic Build() - { - return new Diagnostic(severity, message, help, file); + public Builder WithHelp(string helpMessage) + { + help = helpMessage; + return this; + } + + public Diagnostic Build() + { + return new Diagnostic(severity, message, help, file); + } } } -public sealed class FileInfo(string file, int line, int column, int length) -{ - public string File { get; } = file; - public int Line { get; } = line; - public int Column { get; } = column; - public int Length { get; } = length; -} - -public enum DiagnosticSeverity -{ - Info, - Warning, - Error, -} - -public sealed class CompileException(Diagnostic diagnostic) : Exception +public class CompileException(Diagnostic diagnostic) : Exception { public Diagnostic Diagnostic { get; } = diagnostic; } @@ -93,9 +101,9 @@ public static class DiagnosticFormatter { var (label, color) = diagnostic.Severity switch { - DiagnosticSeverity.Info => ("info", Ansi.Cyan), - DiagnosticSeverity.Warning => ("warning", Ansi.Yellow), - DiagnosticSeverity.Error => ("error", Ansi.Red), + Diagnostic.DiagnosticSeverity.Info => ("info", Ansi.Cyan), + Diagnostic.DiagnosticSeverity.Warning => ("warning", Ansi.Yellow), + Diagnostic.DiagnosticSeverity.Error => ("error", Ansi.Red), _ => ("unknown", Ansi.Reset), }; diff --git a/compiler/Generator.cs b/compiler/Generator.cs index 3572588..14b266b 100644 --- a/compiler/Generator.cs +++ b/compiler/Generator.cs @@ -2,13 +2,23 @@ namespace Compiler; -public sealed class Generator(List functions, ModuleGraph moduleGraph, bool compileLib) +public class Generator { public static string Emit(List functions, ModuleGraph moduleGraph, bool compileLib) { return new Generator(functions, moduleGraph, compileLib).Emit(); } + private Generator(List functions, ModuleGraph moduleGraph, bool compileLib) + { + this.functions = functions; + this.moduleGraph = moduleGraph; + this.compileLib = compileLib; + } + + private readonly List functions; + private readonly ModuleGraph moduleGraph; + private readonly bool compileLib; private readonly IndentedTextWriter writer = new(); private readonly Dictionary structTypeNames = new(); diff --git a/compiler/ModuleGraph.cs b/compiler/ModuleGraph.cs index 655b9c7..a6d6987 100644 --- a/compiler/ModuleGraph.cs +++ b/compiler/ModuleGraph.cs @@ -3,9 +3,16 @@ using System.Diagnostics.CodeAnalysis; namespace Compiler; -public class ModuleGraph(Dictionary modules) +public class ModuleGraph { - public static Builder Create() => new(); + public static Builder CreateBuilder() => new(); + + private ModuleGraph(Dictionary modules) + { + this.modules = modules; + } + + private readonly Dictionary modules; public List GetModules() { @@ -23,7 +30,7 @@ public class ModuleGraph(Dictionary modules) return new Manifest(1, GetModules().Select(x => x.CreateManifestModule()).ToList()); } - public sealed class Module(string name) + public class Module(string name) { public string Name { get; } = name; private readonly Dictionary customTypes = new(); @@ -108,7 +115,7 @@ public class ModuleGraph(Dictionary modules) public ManifestCustomTypeInfo CreateManifestCustomTypeInfo() { - return new ManifestCustomTypeInfo(TypeMangler.Encode(Type), Exported); + return new ManifestCustomTypeInfo(TypeEncoder.Encode(Type), Exported); } } @@ -120,7 +127,7 @@ public class ModuleGraph(Dictionary modules) public ManifestIdentifierInfo CreateManifestIdentifierInfo() { - return new ManifestIdentifierInfo(TypeMangler.Encode(Type), Exported); + return new ManifestIdentifierInfo(TypeEncoder.Encode(Type), Exported); } } } @@ -159,13 +166,13 @@ public class ModuleGraph(Dictionary modules) foreach (var customType in manifestModule.CustomTypes) { - var decoded = TypeMangler.Decode(customType.Value.EncodedType); + var decoded = TypeDecoder.Decode(customType.Value.EncodedType); module.AddCustomType(customType.Key, new Module.CustomTypeInfo(decoded, customType.Value.Exported, Module.Source.Lib)); } foreach (var identifier in manifestModule.Identifiers) { - var decoded = TypeMangler.Decode(identifier.Value.EncodedType); + var decoded = TypeDecoder.Decode(identifier.Value.EncodedType); module.AddIdentifier(identifier.Key, new Module.IdentifierInfo(decoded, identifier.Value.Exported, Module.Source.Lib)); } } @@ -234,7 +241,7 @@ public class ModuleGraph(Dictionary modules) } } - if (diagnostics.Any(x => x.Severity == DiagnosticSeverity.Error)) + if (diagnostics.Any(x => x.Severity == Diagnostic.DiagnosticSeverity.Error)) return null; return new ModuleGraph(modules); diff --git a/compiler/NubType.cs b/compiler/NubType.cs index 7a0e871..c758090 100644 --- a/compiler/NubType.cs +++ b/compiler/NubType.cs @@ -1,4 +1,3 @@ -using System.Net; using System.Text; namespace Compiler; @@ -8,7 +7,7 @@ public abstract class NubType public abstract override string ToString(); } -public sealed class NubTypeVoid : NubType +public class NubTypeVoid : NubType { public static readonly NubTypeVoid Instance = new(); @@ -19,7 +18,7 @@ public sealed class NubTypeVoid : NubType public override string ToString() => "void"; } -public sealed class NubTypeUInt : NubType +public class NubTypeUInt : NubType { private static readonly Dictionary Cache = new(); @@ -41,7 +40,7 @@ public sealed class NubTypeUInt : NubType public override string ToString() => $"u{Width}"; } -public sealed class NubTypeSInt : NubType +public class NubTypeSInt : NubType { private static readonly Dictionary Cache = new(); @@ -63,7 +62,7 @@ public sealed class NubTypeSInt : NubType public override string ToString() => $"i{Width}"; } -public sealed class NubTypeBool : NubType +public class NubTypeBool : NubType { public static readonly NubTypeBool Instance = new(); @@ -74,7 +73,7 @@ public sealed class NubTypeBool : NubType public override string ToString() => "bool"; } -public sealed class NubTypeString : NubType +public class NubTypeString : NubType { public static readonly NubTypeString Instance = new(); @@ -85,7 +84,7 @@ public sealed class NubTypeString : NubType public override string ToString() => "string"; } -public sealed class NubTypeStruct : NubType +public class NubTypeStruct : NubType { public string Name { get; } public string Module { get; } @@ -112,14 +111,14 @@ public sealed class NubTypeStruct : NubType public override string ToString() => _resolvedFields == null ? $"struct {Module}::{Name} " : $"struct {Module}::{Name} {{ {string.Join(' ', Fields.Select(f => $"{f.Name}: {f.Type}"))} }}"; - public sealed class Field(string name, NubType type) + public class Field(string name, NubType type) { public string Name { get; } = name; public NubType Type { get; } = type; } } -public sealed class NubTypePointer : NubType +public class NubTypePointer : NubType { private static readonly Dictionary Cache = new(); @@ -141,7 +140,7 @@ public sealed class NubTypePointer : NubType public override string ToString() => $"^{To}"; } -public sealed class NubTypeFunc : NubType +public class NubTypeFunc : NubType { private static readonly Dictionary Cache = new(); @@ -171,7 +170,7 @@ public sealed class NubTypeFunc : NubType private readonly record struct Signature(IReadOnlyList Parameters, NubType ReturnType); } -static class TypeMangler +static class TypeEncoder { public static string Encode(NubType type) { @@ -241,63 +240,78 @@ static class TypeMangler throw new NotSupportedException(type.GetType().Name); } } +} +class TypeDecoder +{ public static NubType Decode(string encoded) { - int pos = 0; - return Parse(encoded, ref pos); + return new TypeDecoder(encoded).Decode(); } - private static NubType Parse(string s, ref int pos) + private TypeDecoder(string encoded) { - if (pos >= s.Length) + this.encoded = encoded; + } + + private readonly string encoded; + private int pos; + + private NubType Decode() + { + return Parse(); + } + + private NubType Parse() + { + if (pos >= encoded.Length) throw new InvalidOperationException("Unexpected end of string"); - char c = s[pos++]; + char c = encoded[pos++]; return c switch { 'V' => NubTypeVoid.Instance, 'B' => NubTypeBool.Instance, 'S' => NubTypeString.Instance, - 'U' => ParseUInt(s, ref pos), - 'I' => ParseSInt(s, ref pos), - 'P' => ParsePointer(s, ref pos), - 'T' => ParseStruct(s, ref pos), - 'F' => ParseFunc(s, ref pos), + 'U' => ParseUInt(), + 'I' => ParseSInt(), + 'P' => ParsePointer(), + 'T' => ParseStruct(), + 'F' => ParseFunc(), _ => throw new NotSupportedException($"Unknown type code '{c}' at position {pos - 1}") }; } - private static NubTypeUInt ParseUInt(string s, ref int pos) + private NubTypeUInt ParseUInt() { - ExpectChar(s, ref pos, '('); - int width = ReadNumber(s, ref pos); - ExpectChar(s, ref pos, ')'); + ExpectChar('('); + int width = ReadNumber(); + ExpectChar(')'); return NubTypeUInt.Get(width); } - private static NubTypeSInt ParseSInt(string s, ref int pos) + private NubTypeSInt ParseSInt() { - ExpectChar(s, ref pos, '('); - int width = ReadNumber(s, ref pos); - ExpectChar(s, ref pos, ')'); + ExpectChar('('); + int width = ReadNumber(); + ExpectChar(')'); return NubTypeSInt.Get(width); } - private static NubTypePointer ParsePointer(string s, ref int pos) + private NubTypePointer ParsePointer() { - ExpectChar(s, ref pos, '('); - var to = Parse(s, ref pos); - ExpectChar(s, ref pos, ')'); + ExpectChar('('); + var to = Parse(); + ExpectChar(')'); return NubTypePointer.Get(to); } - private static NubTypeStruct ParseStruct(string s, ref int pos) + private NubTypeStruct ParseStruct() { - ExpectChar(s, ref pos, '('); + ExpectChar('('); int start = pos; - while (pos < s.Length && s[pos] != ',' && s[pos] != '{') pos++; - var fullName = s[start..pos]; + while (pos < encoded.Length && encoded[pos] != ',' && encoded[pos] != '{') pos++; + var fullName = encoded[start..pos]; var parts = fullName.Split("::"); if (parts.Length != 2) throw new InvalidOperationException($"Invalid struct name: {fullName}"); @@ -305,64 +319,64 @@ static class TypeMangler string module = parts[0], name = parts[1]; bool packed = false; - if (s[pos] == ',') + if (encoded[pos] == ',') { pos += 1; - packed = s[pos += 1] == '1'; + packed = encoded[pos += 1] == '1'; } var st = new NubTypeStruct(module, name, packed); - ExpectChar(s, ref pos, '{'); + ExpectChar('{'); var fields = new List(); - while (s[pos] != '}') + while (encoded[pos] != '}') { int nameStart = pos; - while (s[pos] != ':') pos += 1; - string fieldName = s[nameStart..pos]; + while (encoded[pos] != ':') pos += 1; + string fieldName = encoded[nameStart..pos]; pos += 1; - var fieldType = Parse(s, ref pos); + var fieldType = Parse(); fields.Add(new NubTypeStruct.Field(fieldName, fieldType)); - if (s[pos] == ',') pos += 1; + if (encoded[pos] == ',') pos += 1; } - ExpectChar(s, ref pos, '}'); - ExpectChar(s, ref pos, ')'); + ExpectChar('}'); + ExpectChar(')'); st.ResolveFields(fields); return st; } - private static NubTypeFunc ParseFunc(string s, ref int pos) + private NubTypeFunc ParseFunc() { - ExpectChar(s, ref pos, '('); + ExpectChar('('); var parameters = new List(); while (true) { - if (s[pos] == ')') + if (encoded[pos] == ')') { pos++; break; } - var param = Parse(s, ref pos); + var param = Parse(); parameters.Add(param); - if (s[pos] == ',') + if (encoded[pos] == ',') { pos += 1; } - else if (s[pos] == ')') + else if (encoded[pos] == ')') { pos += 1; break; } else { - throw new InvalidOperationException($"Unexpected char '{s[pos]}' in function type at {pos}"); + throw new InvalidOperationException($"Unexpected char '{encoded[pos]}' in function type at {pos}"); } } @@ -375,20 +389,20 @@ static class TypeMangler return NubTypeFunc.Get(paramTypes, returnType); } - private static void ExpectChar(string s, ref int pos, char expected) + private void ExpectChar(char expected) { - if (pos >= s.Length || s[pos] != expected) + if (pos >= encoded.Length || encoded[pos] != expected) throw new InvalidOperationException($"Expected '{expected}' at position {pos}"); pos += 1; } - private static int ReadNumber(string s, ref int pos) + private int ReadNumber() { int start = pos; - while (pos < s.Length && char.IsDigit(s[pos])) pos += 1; + while (pos < encoded.Length && char.IsDigit(encoded[pos])) pos += 1; if (start == pos) throw new InvalidOperationException($"Expected number at position {start}"); - return int.Parse(s[start..pos]); + return int.Parse(encoded[start..pos]); } } @@ -414,7 +428,7 @@ static class SymbolNameGen { public static string Exported(string module, string function, NubType type) { - var canonical = TypeMangler.Encode(type); + var canonical = TypeEncoder.Encode(type); var hash = Hashing.Fnv1a64(canonical); return $"nub_{Sanitize(module)}_{Sanitize(function)}_{hash:x16}"; diff --git a/compiler/Parser.cs b/compiler/Parser.cs index 2f32b1a..6608d81 100644 --- a/compiler/Parser.cs +++ b/compiler/Parser.cs @@ -2,13 +2,21 @@ namespace Compiler; -public sealed class Parser(string fileName, List tokens) +public class Parser { public static Ast? Parse(string fileName, List tokens, out List diagnostics) { return new Parser(fileName, tokens).Parse(out diagnostics); } + private Parser(string fileName, List tokens) + { + this.fileName = fileName; + this.tokens = tokens; + } + + private readonly string fileName; + private readonly List tokens; private int index; private Ast? Parse(out List diagnostics) @@ -33,7 +41,7 @@ public sealed class Parser(string fileName, List tokens) diagnostics.Add(e.Diagnostic); } - if (moduleName == null || diagnostics.Any(x => x.Severity == DiagnosticSeverity.Error)) + if (moduleName == null || diagnostics.Any(x => x.Severity == Diagnostic.DiagnosticSeverity.Error)) return null; return new Ast(fileName, moduleName, definitions); @@ -594,7 +602,7 @@ public sealed class Parser(string fileName, List tokens) } } -public sealed class Ast(string fileName, TokenIdent moduleName, List definitions) +public class Ast(string fileName, TokenIdent moduleName, List definitions) { public string FileName { get; } = fileName; public TokenIdent ModuleName { get; } = moduleName; @@ -608,7 +616,7 @@ public abstract class Node(List tokens) public abstract class NodeDefinition(List tokens) : Node(tokens); -public sealed class NodeDefinitionFunc(List tokens, bool exported, TokenIdent name, List parameters, NodeStatement body, NodeType returnType) : NodeDefinition(tokens) +public class NodeDefinitionFunc(List tokens, bool exported, TokenIdent name, List parameters, NodeStatement body, NodeType returnType) : NodeDefinition(tokens) { public bool Exported { get; } = exported; public TokenIdent Name { get; } = name; @@ -616,28 +624,28 @@ public sealed class NodeDefinitionFunc(List tokens, bool exported, TokenI public NodeStatement Body { get; } = body; public NodeType ReturnType { get; } = returnType; - public sealed class Param(List tokens, TokenIdent name, NodeType type) : Node(tokens) + public class Param(List tokens, TokenIdent name, NodeType type) : Node(tokens) { public TokenIdent Name { get; } = name; public NodeType Type { get; } = type; } } -public sealed class NodeDefinitionStruct(List tokens, bool exported, bool packed, TokenIdent name, List fields) : NodeDefinition(tokens) +public class NodeDefinitionStruct(List tokens, bool exported, bool packed, TokenIdent name, List fields) : NodeDefinition(tokens) { public bool Exported { get; } = exported; public bool Packed { get; } = packed; public TokenIdent Name { get; } = name; public List Fields { get; } = fields; - public sealed class Field(List tokens, TokenIdent name, NodeType type) : Node(tokens) + public class Field(List tokens, TokenIdent name, NodeType type) : Node(tokens) { public TokenIdent Name { get; } = name; public NodeType Type { get; } = type; } } -public sealed class NodeDefinitionGlobalVariable(List tokens, bool exported, TokenIdent name, NodeType type) : NodeDefinition(tokens) +public class NodeDefinitionGlobalVariable(List tokens, bool exported, TokenIdent name, NodeType type) : NodeDefinition(tokens) { public bool Exported { get; } = exported; public TokenIdent Name { get; } = name; @@ -646,42 +654,42 @@ public sealed class NodeDefinitionGlobalVariable(List tokens, bool export public abstract class NodeStatement(List tokens) : Node(tokens); -public sealed class NodeStatementBlock(List tokens, List statements) : NodeStatement(tokens) +public class NodeStatementBlock(List tokens, List statements) : NodeStatement(tokens) { public List Statements { get; } = statements; } -public sealed class NodeStatementExpression(List tokens, NodeExpression expression) : NodeStatement(tokens) +public class NodeStatementExpression(List tokens, NodeExpression expression) : NodeStatement(tokens) { public NodeExpression Expression { get; } = expression; } -public sealed class NodeStatementReturn(List tokens, NodeExpression value) : NodeStatement(tokens) +public class NodeStatementReturn(List tokens, NodeExpression value) : NodeStatement(tokens) { public NodeExpression Value { get; } = value; } -public sealed class NodeStatementVariableDeclaration(List tokens, TokenIdent name, NodeType type, NodeExpression value) : NodeStatement(tokens) +public class NodeStatementVariableDeclaration(List tokens, TokenIdent name, NodeType type, NodeExpression value) : NodeStatement(tokens) { public TokenIdent Name { get; } = name; public NodeType Type { get; } = type; public NodeExpression Value { get; } = value; } -public sealed class NodeStatementAssignment(List tokens, NodeExpression target, NodeExpression value) : NodeStatement(tokens) +public class NodeStatementAssignment(List tokens, NodeExpression target, NodeExpression value) : NodeStatement(tokens) { public NodeExpression Target { get; } = target; public NodeExpression Value { get; } = value; } -public sealed class NodeStatementIf(List tokens, NodeExpression condition, NodeStatement thenBlock, NodeStatement? elseBlock) : NodeStatement(tokens) +public class NodeStatementIf(List tokens, NodeExpression condition, NodeStatement thenBlock, NodeStatement? elseBlock) : NodeStatement(tokens) { public NodeExpression Condition { get; } = condition; public NodeStatement ThenBlock { get; } = thenBlock; public NodeStatement? ElseBlock { get; } = elseBlock; } -public sealed class NodeStatementWhile(List tokens, NodeExpression condition, NodeStatement block) : NodeStatement(tokens) +public class NodeStatementWhile(List tokens, NodeExpression condition, NodeStatement block) : NodeStatement(tokens) { public NodeExpression Condition { get; } = condition; public NodeStatement Block { get; } = block; @@ -689,58 +697,58 @@ public sealed class NodeStatementWhile(List tokens, NodeExpression condit public abstract class NodeExpression(List tokens) : Node(tokens); -public sealed class NodeExpressionIntLiteral(List tokens, TokenIntLiteral value) : NodeExpression(tokens) +public class NodeExpressionIntLiteral(List tokens, TokenIntLiteral value) : NodeExpression(tokens) { public TokenIntLiteral Value { get; } = value; } -public sealed class NodeExpressionStringLiteral(List tokens, TokenStringLiteral value) : NodeExpression(tokens) +public class NodeExpressionStringLiteral(List tokens, TokenStringLiteral value) : NodeExpression(tokens) { public TokenStringLiteral Value { get; } = value; } -public sealed class NodeExpressionBoolLiteral(List tokens, TokenBoolLiteral value) : NodeExpression(tokens) +public class NodeExpressionBoolLiteral(List tokens, TokenBoolLiteral value) : NodeExpression(tokens) { public TokenBoolLiteral Value { get; } = value; } -public sealed class NodeExpressionStructLiteral(List tokens, TokenIdent module, TokenIdent name, List initializers) : NodeExpression(tokens) +public class NodeExpressionStructLiteral(List tokens, TokenIdent module, TokenIdent name, List initializers) : NodeExpression(tokens) { public TokenIdent Module { get; } = module; public TokenIdent Name { get; } = name; public List Initializers { get; } = initializers; - public sealed class Initializer(List tokens, TokenIdent name, NodeExpression value) : Node(tokens) + public class Initializer(List tokens, TokenIdent name, NodeExpression value) : Node(tokens) { public TokenIdent Name { get; } = name; public NodeExpression Value { get; } = value; } } -public sealed class NodeExpressionMemberAccess(List tokens, NodeExpression target, TokenIdent name) : NodeExpression(tokens) +public class NodeExpressionMemberAccess(List tokens, NodeExpression target, TokenIdent name) : NodeExpression(tokens) { public NodeExpression Target { get; } = target; public TokenIdent Name { get; } = name; } -public sealed class NodeExpressionFuncCall(List tokens, NodeExpression target, List parameters) : NodeExpression(tokens) +public class NodeExpressionFuncCall(List tokens, NodeExpression target, List parameters) : NodeExpression(tokens) { public NodeExpression Target { get; } = target; public List Parameters { get; } = parameters; } -public sealed class NodeExpressionLocalIdent(List tokens, TokenIdent value) : NodeExpression(tokens) +public class NodeExpressionLocalIdent(List tokens, TokenIdent value) : NodeExpression(tokens) { public TokenIdent Value { get; } = value; } -public sealed class NodeExpressionModuleIdent(List tokens, TokenIdent module, TokenIdent value) : NodeExpression(tokens) +public class NodeExpressionModuleIdent(List tokens, TokenIdent module, TokenIdent value) : NodeExpression(tokens) { public TokenIdent Module { get; } = module; public TokenIdent Value { get; } = value; } -public sealed class NodeExpressionBinary(List tokens, NodeExpression left, NodeExpressionBinary.Op operation, NodeExpression right) : NodeExpression(tokens) +public class NodeExpressionBinary(List tokens, NodeExpression left, NodeExpressionBinary.Op operation, NodeExpression right) : NodeExpression(tokens) { public NodeExpression Left { get; } = left; public Op Operation { get; } = operation; @@ -773,7 +781,7 @@ public sealed class NodeExpressionBinary(List tokens, NodeExpression left } } -public sealed class NodeExpressionUnary(List tokens, NodeExpression target, NodeExpressionUnary.Op op) : NodeExpression(tokens) +public class NodeExpressionUnary(List tokens, NodeExpression target, NodeExpressionUnary.Op op) : NodeExpression(tokens) { public NodeExpression Target { get; } = target; public Op Operation { get; } = op; @@ -787,34 +795,34 @@ public sealed class NodeExpressionUnary(List tokens, NodeExpression targe public abstract class NodeType(List tokens) : Node(tokens); -public sealed class NodeTypeVoid(List tokens) : NodeType(tokens); +public class NodeTypeVoid(List tokens) : NodeType(tokens); -public sealed class NodeTypeUInt(List tokens, int width) : NodeType(tokens) +public class NodeTypeUInt(List tokens, int width) : NodeType(tokens) { public int Width { get; } = width; } -public sealed class NodeTypeSInt(List tokens, int width) : NodeType(tokens) +public class NodeTypeSInt(List tokens, int width) : NodeType(tokens) { public int Width { get; } = width; } -public sealed class NodeTypeBool(List tokens) : NodeType(tokens); +public class NodeTypeBool(List tokens) : NodeType(tokens); -public sealed class NodeTypeString(List tokens) : NodeType(tokens); +public class NodeTypeString(List tokens) : NodeType(tokens); -public sealed class NodeTypeCustom(List tokens, TokenIdent module, TokenIdent name) : NodeType(tokens) +public class NodeTypeCustom(List tokens, TokenIdent module, TokenIdent name) : NodeType(tokens) { public TokenIdent Module { get; } = module; public TokenIdent Name { get; } = name; } -public sealed class NodeTypePointer(List tokens, NodeType to) : NodeType(tokens) +public class NodeTypePointer(List tokens, NodeType to) : NodeType(tokens) { public NodeType To { get; } = to; } -public sealed class NodeTypeFunc(List tokens, List parameters, NodeType returnType) : NodeType(tokens) +public class NodeTypeFunc(List tokens, List parameters, NodeType returnType) : NodeType(tokens) { public List Parameters { get; } = parameters; public NodeType ReturnType { get; } = returnType; diff --git a/compiler/Program.cs b/compiler/Program.cs index 82fbb3e..1eb5912 100644 --- a/compiler/Program.cs +++ b/compiler/Program.cs @@ -60,7 +60,7 @@ for (int i = 0; i < args.Length; i++) } } -var moduleGraphBuilder = ModuleGraph.Create(); +var moduleGraphBuilder = ModuleGraph.CreateBuilder(); var asts = new List(); var archivePaths = new List(); diff --git a/compiler/Tokenizer.cs b/compiler/Tokenizer.cs index db0f9c0..9762822 100644 --- a/compiler/Tokenizer.cs +++ b/compiler/Tokenizer.cs @@ -3,13 +3,21 @@ using System.Text; namespace Compiler; -public sealed class Tokenizer(string fileName, string contents) +public class Tokenizer { public static List? Tokenize(string fileName, string contents, out List diagnostics) { return new Tokenizer(fileName, contents).Tokenize(out diagnostics); } + private Tokenizer(string fileName, string contents) + { + this.fileName = fileName; + this.contents = contents; + } + + private readonly string fileName; + private readonly string contents; private int index; private int line = 1; private int column = 1; @@ -53,7 +61,7 @@ public sealed class Tokenizer(string fileName, string contents) } } - if (diagnostics.Any(x => x.Severity == DiagnosticSeverity.Error)) + if (diagnostics.Any(x => x.Severity == Diagnostic.DiagnosticSeverity.Error)) return null; return tokens; @@ -459,22 +467,22 @@ public abstract class Token(int line, int column, int length) public int Length { get; } = length; } -public sealed class TokenIdent(int line, int column, int length, string ident) : Token(line, column, length) +public class TokenIdent(int line, int column, int length, string ident) : Token(line, column, length) { public string Ident { get; } = ident; } -public sealed class TokenIntLiteral(int line, int column, int length, BigInteger value) : Token(line, column, length) +public class TokenIntLiteral(int line, int column, int length, BigInteger value) : Token(line, column, length) { public BigInteger Value { get; } = value; } -public sealed class TokenStringLiteral(int line, int column, int length, string value) : Token(line, column, length) +public class TokenStringLiteral(int line, int column, int length, string value) : Token(line, column, length) { public string Value { get; } = value; } -public sealed class TokenBoolLiteral(int line, int column, int length, bool value) : Token(line, column, length) +public class TokenBoolLiteral(int line, int column, int length, bool value) : Token(line, column, length) { public bool Value { get; } = value; } @@ -516,7 +524,7 @@ public enum Symbol PipePipe, } -public sealed class TokenSymbol(int line, int column, int length, Symbol symbol) : Token(line, column, length) +public class TokenSymbol(int line, int column, int length, Symbol symbol) : Token(line, column, length) { public Symbol Symbol { get; } = symbol; } @@ -535,7 +543,7 @@ public enum Keyword Export, } -public sealed class TokenKeyword(int line, int column, int length, Keyword keyword) : Token(line, column, length) +public class TokenKeyword(int line, int column, int length, Keyword keyword) : Token(line, column, length) { public Keyword Keyword { get; } = keyword; } diff --git a/compiler/TypeChecker.cs b/compiler/TypeChecker.cs index a89d96b..e8b9daa 100644 --- a/compiler/TypeChecker.cs +++ b/compiler/TypeChecker.cs @@ -1,12 +1,24 @@ namespace Compiler; -public sealed class TypeChecker(string fileName, string moduleName, NodeDefinitionFunc function, ModuleGraph moduleGraph) +public class TypeChecker { public static TypedNodeDefinitionFunc? CheckFunction(string fileName, string moduleName, NodeDefinitionFunc function, ModuleGraph moduleGraph, out List diagnostics) { return new TypeChecker(fileName, moduleName, function, moduleGraph).CheckFunction(out diagnostics); } + private TypeChecker(string fileName, string moduleName, NodeDefinitionFunc function, ModuleGraph moduleGraph) + { + this.fileName = fileName; + this.moduleName = moduleName; + this.function = function; + this.moduleGraph = moduleGraph; + } + + private readonly string fileName; + private readonly string moduleName; + private readonly NodeDefinitionFunc function; + private readonly ModuleGraph moduleGraph; private readonly Scope scope = new(null); private TypedNodeDefinitionFunc? CheckFunction(out List diagnostics) @@ -422,7 +434,7 @@ public abstract class TypedNodeDefinition(List tokens, string module) : T public string Module { get; } = module; } -public sealed class TypedNodeDefinitionFunc(List tokens, string module, TokenIdent name, List parameters, TypedNodeStatement body, NubType returnType) : TypedNodeDefinition(tokens, module) +public class TypedNodeDefinitionFunc(List tokens, string module, TokenIdent name, List parameters, TypedNodeStatement body, NubType returnType) : TypedNodeDefinition(tokens, module) { public TokenIdent Name { get; } = name; public List Parameters { get; } = parameters; @@ -439,7 +451,7 @@ public sealed class TypedNodeDefinitionFunc(List tokens, string module, T return SymbolNameGen.Exported(Module, Name.Ident, GetNubType()); } - public sealed class Param(List tokens, TokenIdent name, NubType type) : TypedNode(tokens) + public class Param(List tokens, TokenIdent name, NubType type) : TypedNode(tokens) { public TokenIdent Name { get; } = name; public NubType Type { get; } = type; @@ -448,43 +460,43 @@ public sealed class TypedNodeDefinitionFunc(List tokens, string module, T public abstract class TypedNodeStatement(List tokens) : TypedNode(tokens); -public sealed class TypedNodeStatementBlock(List tokens, List statements) : TypedNodeStatement(tokens) +public class TypedNodeStatementBlock(List tokens, List statements) : TypedNodeStatement(tokens) { public List Statements { get; } = statements; } -public sealed class TypedNodeStatementFuncCall(List tokens, TypedNodeExpression target, List parameters) : TypedNodeStatement(tokens) +public class TypedNodeStatementFuncCall(List tokens, TypedNodeExpression target, List parameters) : TypedNodeStatement(tokens) { public TypedNodeExpression Target { get; } = target; public List Parameters { get; } = parameters; } -public sealed class TypedNodeStatementReturn(List tokens, TypedNodeExpression value) : TypedNodeStatement(tokens) +public class TypedNodeStatementReturn(List tokens, TypedNodeExpression value) : TypedNodeStatement(tokens) { public TypedNodeExpression Value { get; } = value; } -public sealed class TypedNodeStatementVariableDeclaration(List tokens, TokenIdent name, NubType type, TypedNodeExpression value) : TypedNodeStatement(tokens) +public class TypedNodeStatementVariableDeclaration(List tokens, TokenIdent name, NubType type, TypedNodeExpression value) : TypedNodeStatement(tokens) { public TokenIdent Name { get; } = name; public NubType Type { get; } = type; public TypedNodeExpression Value { get; } = value; } -public sealed class TypedNodeStatementAssignment(List tokens, TypedNodeExpression target, TypedNodeExpression value) : TypedNodeStatement(tokens) +public class TypedNodeStatementAssignment(List tokens, TypedNodeExpression target, TypedNodeExpression value) : TypedNodeStatement(tokens) { public TypedNodeExpression Target { get; } = target; public TypedNodeExpression Value { get; } = value; } -public sealed class TypedNodeStatementIf(List tokens, TypedNodeExpression condition, TypedNodeStatement thenBlock, TypedNodeStatement? elseBlock) : TypedNodeStatement(tokens) +public class TypedNodeStatementIf(List tokens, TypedNodeExpression condition, TypedNodeStatement thenBlock, TypedNodeStatement? elseBlock) : TypedNodeStatement(tokens) { public TypedNodeExpression Condition { get; } = condition; public TypedNodeStatement ThenBlock { get; } = thenBlock; public TypedNodeStatement? ElseBlock { get; } = elseBlock; } -public sealed class TypedNodeStatementWhile(List tokens, TypedNodeExpression condition, TypedNodeStatement block) : TypedNodeStatement(tokens) +public class TypedNodeStatementWhile(List tokens, TypedNodeExpression condition, TypedNodeStatement block) : TypedNodeStatement(tokens) { public TypedNodeExpression Condition { get; } = condition; public TypedNodeStatement Block { get; } = block; @@ -495,56 +507,56 @@ public abstract class TypedNodeExpression(List tokens, NubType type) : Ty public NubType Type { get; } = type; } -public sealed class TypedNodeExpressionIntLiteral(List tokens, NubType type, TokenIntLiteral value) : TypedNodeExpression(tokens, type) +public class TypedNodeExpressionIntLiteral(List tokens, NubType type, TokenIntLiteral value) : TypedNodeExpression(tokens, type) { public TokenIntLiteral Value { get; } = value; } -public sealed class TypedNodeExpressionStringLiteral(List tokens, NubType type, TokenStringLiteral value) : TypedNodeExpression(tokens, type) +public class TypedNodeExpressionStringLiteral(List tokens, NubType type, TokenStringLiteral value) : TypedNodeExpression(tokens, type) { public TokenStringLiteral Value { get; } = value; } -public sealed class TypedNodeExpressionBoolLiteral(List tokens, NubType type, TokenBoolLiteral value) : TypedNodeExpression(tokens, type) +public class TypedNodeExpressionBoolLiteral(List tokens, NubType type, TokenBoolLiteral value) : TypedNodeExpression(tokens, type) { public TokenBoolLiteral Value { get; } = value; } -public sealed class TypedNodeExpressionStructLiteral(List tokens, NubType type, List initializers) : TypedNodeExpression(tokens, type) +public class TypedNodeExpressionStructLiteral(List tokens, NubType type, List initializers) : TypedNodeExpression(tokens, type) { public List Initializers { get; } = initializers; - public sealed class Initializer(List tokens, TokenIdent name, TypedNodeExpression value) : Node(tokens) + public class Initializer(List tokens, TokenIdent name, TypedNodeExpression value) : Node(tokens) { public TokenIdent Name { get; } = name; public TypedNodeExpression Value { get; } = value; } } -public sealed class TypedNodeExpressionMemberAccess(List tokens, NubType type, TypedNodeExpression target, TokenIdent name) : TypedNodeExpression(tokens, type) +public class TypedNodeExpressionMemberAccess(List tokens, NubType type, TypedNodeExpression target, TokenIdent name) : TypedNodeExpression(tokens, type) { public TypedNodeExpression Target { get; } = target; public TokenIdent Name { get; } = name; } -public sealed class TypedNodeExpressionFuncCall(List tokens, NubType type, TypedNodeExpression target, List parameters) : TypedNodeExpression(tokens, type) +public class TypedNodeExpressionFuncCall(List tokens, NubType type, TypedNodeExpression target, List parameters) : TypedNodeExpression(tokens, type) { public TypedNodeExpression Target { get; } = target; public List Parameters { get; } = parameters; } -public sealed class TypedNodeExpressionLocalIdent(List tokens, NubType type, TokenIdent value) : TypedNodeExpression(tokens, type) +public class TypedNodeExpressionLocalIdent(List tokens, NubType type, TokenIdent value) : TypedNodeExpression(tokens, type) { public TokenIdent Value { get; } = value; } -public sealed class TypedNodeExpressionModuleIdent(List tokens, NubType type, TokenIdent module, TokenIdent value) : TypedNodeExpression(tokens, type) +public class TypedNodeExpressionModuleIdent(List tokens, NubType type, TokenIdent module, TokenIdent value) : TypedNodeExpression(tokens, type) { public TokenIdent Module { get; } = module; public TokenIdent Value { get; } = value; } -public sealed class TypedNodeExpressionBinary(List tokens, NubType type, TypedNodeExpression left, TypedNodeExpressionBinary.Op operation, TypedNodeExpression right) : TypedNodeExpression(tokens, type) +public class TypedNodeExpressionBinary(List tokens, NubType type, TypedNodeExpression left, TypedNodeExpressionBinary.Op operation, TypedNodeExpression right) : TypedNodeExpression(tokens, type) { public TypedNodeExpression Left { get; } = left; public Op Operation { get; } = operation; @@ -577,7 +589,7 @@ public sealed class TypedNodeExpressionBinary(List tokens, NubType type, } } -public sealed class TypedNodeExpressionUnary(List tokens, NubType type, TypedNodeExpression target, TypedNodeExpressionUnary.Op op) : TypedNodeExpression(tokens, type) +public class TypedNodeExpressionUnary(List tokens, NubType type, TypedNodeExpression target, TypedNodeExpressionUnary.Op op) : TypedNodeExpression(tokens, type) { public TypedNodeExpression Target { get; } = target; public Op Operation { get; } = op;