diff --git a/example/.gitignore b/example/.gitignore
index 145bd1e..a8b1f05 100644
--- a/example/.gitignore
+++ b/example/.gitignore
@@ -1,2 +1,3 @@
.build
+out.a
out
\ No newline at end of file
diff --git a/example/makefile b/example/makefile
index 4932cb8..f63b491 100644
--- a/example/makefile
+++ b/example/makefile
@@ -1,18 +1,16 @@
-CC = gcc
-NUBC = ../src/compiler/NubLang.CLI/bin/Debug/net9.0/nubc
+NUBC = ../compiler/NubLang.CLI/bin/Debug/net9.0/nubc
-.build/out: .build/out.a
- $(CC) -ffreestanding -g -o .build/out .build/out.a
+out: out.a
+ gcc -nostartfiles -o out x86_64.s out.a
+ rm out.a
-.build/out.a: $(NUBC) src/main.nub
- $(NUBC) src/main.nub
+out.a: $(NUBC) main.nub
+ $(NUBC) main.nub
+.PHONY: $(NUBC)
$(NUBC):
- dotnet build ../src/compiler/NubLang.CLI/NubLang.CLI.csproj
-
-run: .build/out
- ./.build/out
+ dotnet build ../compiler/NubLang.CLI/NubLang.CLI.csproj
clean:
@rm -r .build 2>/dev/null || true
- @rm out 2>/dev/null || true
+ @rm out.a 2>/dev/null || true
diff --git a/example/src/main.nub b/example/src/main.nub
deleted file mode 100644
index 0372339..0000000
--- a/example/src/main.nub
+++ /dev/null
@@ -1,15 +0,0 @@
-module main
-
-extern func puts(text: cstring)
-
-struct Test
-{
-
-}
-
-func main(args: []cstring): i64
-{
- puts("test")
-
- return 0
-}
diff --git a/src/compiler/.gitignore b/src/compiler/.gitignore
deleted file mode 100644
index c6cc67a..0000000
--- a/src/compiler/.gitignore
+++ /dev/null
@@ -1,34 +0,0 @@
-# Common IntelliJ Platform excludes
-
-# User specific
-**/.idea/**/workspace.xml
-**/.idea/**/tasks.xml
-**/.idea/shelf/*
-**/.idea/dictionaries
-**/.idea/httpRequests/
-
-# Sensitive or high-churn files
-**/.idea/**/dataSources/
-**/.idea/**/dataSources.ids
-**/.idea/**/dataSources.xml
-**/.idea/**/dataSources.local.xml
-**/.idea/**/sqlDataSources.xml
-**/.idea/**/dynamic.xml
-
-# Rider
-# Rider auto-generates .iml files, and contentModel.xml
-**/.idea/**/*.iml
-**/.idea/**/contentModel.xml
-**/.idea/**/modules.xml
-
-*.suo
-*.user
-.vs/
-[Bb]in/
-[Oo]bj/
-_UpgradeReport_Files/
-[Pp]ackages/
-
-Thumbs.db
-Desktop.ini
-.DS_Store
\ No newline at end of file
diff --git a/src/compiler/.idea/.idea.Compiler/.idea/.gitignore b/src/compiler/.idea/.idea.Compiler/.idea/.gitignore
deleted file mode 100644
index cda1cf4..0000000
--- a/src/compiler/.idea/.idea.Compiler/.idea/.gitignore
+++ /dev/null
@@ -1,13 +0,0 @@
-# Default ignored files
-/shelf/
-/workspace.xml
-# Rider ignored files
-/modules.xml
-/projectSettingsUpdater.xml
-/contentModel.xml
-/.idea.Compiler.iml
-# Editor-based HTTP Client requests
-/httpRequests/
-# Datasource local storage ignored files
-/dataSources/
-/dataSources.local.xml
diff --git a/src/compiler/.idea/.idea.Compiler/.idea/.name b/src/compiler/.idea/.idea.Compiler/.idea/.name
deleted file mode 100644
index b92b7a3..0000000
--- a/src/compiler/.idea/.idea.Compiler/.idea/.name
+++ /dev/null
@@ -1 +0,0 @@
-Compiler
\ No newline at end of file
diff --git a/src/compiler/.idea/.idea.Compiler/.idea/encodings.xml b/src/compiler/.idea/.idea.Compiler/.idea/encodings.xml
deleted file mode 100644
index df87cf9..0000000
--- a/src/compiler/.idea/.idea.Compiler/.idea/encodings.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/src/compiler/.idea/.idea.Compiler/.idea/indexLayout.xml b/src/compiler/.idea/.idea.Compiler/.idea/indexLayout.xml
deleted file mode 100644
index 2135b43..0000000
--- a/src/compiler/.idea/.idea.Compiler/.idea/indexLayout.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
- Runtime
-
-
-
-
-
\ No newline at end of file
diff --git a/src/compiler/.idea/.idea.Compiler/.idea/vcs.xml b/src/compiler/.idea/.idea.Compiler/.idea/vcs.xml
deleted file mode 100644
index b2bdec2..0000000
--- a/src/compiler/.idea/.idea.Compiler/.idea/vcs.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/compiler/Compiler.sln b/src/compiler/Compiler.sln
deleted file mode 100644
index 292d374..0000000
--- a/src/compiler/Compiler.sln
+++ /dev/null
@@ -1,22 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NubLang", "NubLang\NubLang.csproj", "{5047E21F-590D-4CB3-AFF3-064316485009}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NubLang.CLI", "NubLang.CLI\NubLang.CLI.csproj", "{A22F17ED-FA17-45AB-92BA-CD02C28B3524}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {5047E21F-590D-4CB3-AFF3-064316485009}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {5047E21F-590D-4CB3-AFF3-064316485009}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {5047E21F-590D-4CB3-AFF3-064316485009}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {5047E21F-590D-4CB3-AFF3-064316485009}.Release|Any CPU.Build.0 = Release|Any CPU
- {A22F17ED-FA17-45AB-92BA-CD02C28B3524}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {A22F17ED-FA17-45AB-92BA-CD02C28B3524}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {A22F17ED-FA17-45AB-92BA-CD02C28B3524}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {A22F17ED-FA17-45AB-92BA-CD02C28B3524}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
-EndGlobal
diff --git a/src/compiler/NubLang.CLI/Archive.cs b/src/compiler/NubLang.CLI/Archive.cs
deleted file mode 100644
index 59919c5..0000000
--- a/src/compiler/NubLang.CLI/Archive.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-using System.Diagnostics;
-
-namespace NubLang.CLI;
-
-public static class Archive
-{
- public static async Task Invoke(string fileName, params IEnumerable objectFiles)
- {
- using var process = new Process();
- process.StartInfo = new ProcessStartInfo("ar", ["rcs", fileName, ..objectFiles])
- {
- UseShellExecute = false,
- RedirectStandardOutput = true,
- RedirectStandardError = true,
- CreateNoWindow = true
- };
-
- process.Start();
- await process.WaitForExitAsync();
-
- var errors = await process.StandardError.ReadToEndAsync();
- if (!string.IsNullOrWhiteSpace(errors))
- {
- await Console.Error.WriteLineAsync("ar error when archiving:\n" + errors);
- }
-
- return process.ExitCode == 0;
- }
-}
\ No newline at end of file
diff --git a/src/compiler/NubLang.CLI/GCC.cs b/src/compiler/NubLang.CLI/GCC.cs
deleted file mode 100644
index db54016..0000000
--- a/src/compiler/NubLang.CLI/GCC.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-using System.Diagnostics;
-
-namespace NubLang.CLI;
-
-public static class GCC
-{
- public static async Task Assemble(string asmPath, string outPath)
- {
- using var process = new Process();
- process.StartInfo = new ProcessStartInfo("gcc", ["-xassembler", "-g", "-c", "-o", outPath, asmPath])
- {
- UseShellExecute = false,
- RedirectStandardOutput = true,
- RedirectStandardError = true,
- CreateNoWindow = true
- };
-
- process.Start();
-
- await process.WaitForExitAsync();
-
- var errors = await process.StandardError.ReadToEndAsync();
- if (!string.IsNullOrWhiteSpace(errors))
- {
- await Console.Error.WriteLineAsync("gcc error when assembling:\n" + errors);
- }
-
- return process.ExitCode == 0;
- }
-}
\ No newline at end of file
diff --git a/src/compiler/NubLang.CLI/NubLang.CLI.csproj b/src/compiler/NubLang.CLI/NubLang.CLI.csproj
deleted file mode 100644
index 2f25112..0000000
--- a/src/compiler/NubLang.CLI/NubLang.CLI.csproj
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
- nubc
- Exe
- net9.0
- enable
- enable
- true
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/compiler/NubLang.CLI/Options.cs b/src/compiler/NubLang.CLI/Options.cs
deleted file mode 100644
index acef2bc..0000000
--- a/src/compiler/NubLang.CLI/Options.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-using NubLang.Code;
-
-namespace NubLang.CLI;
-
-public class Options
-{
- public string? OutputPath { get; set; }
- public List Files { get; } = [];
-}
\ No newline at end of file
diff --git a/src/compiler/NubLang.CLI/Program.cs b/src/compiler/NubLang.CLI/Program.cs
deleted file mode 100644
index 55dc9d0..0000000
--- a/src/compiler/NubLang.CLI/Program.cs
+++ /dev/null
@@ -1,170 +0,0 @@
-using System.Reflection;
-using NubLang.CLI;
-using NubLang.Code;
-using NubLang.Diagnostics;
-using NubLang.Generation.QBE;
-using NubLang.Parsing;
-using NubLang.Parsing.Syntax;
-using NubLang.Tokenization;
-using NubLang.TypeChecking;
-using Module = NubLang.TypeChecking.Module;
-
-var options = new Options();
-
-for (var i = 0; i < args.Length; i++)
-{
- var arg = args[i];
- switch (arg)
- {
- case "-o":
- {
- ++i;
- if (i >= args.Length)
- {
- return 1;
- }
-
- options.OutputPath = args[i];
- break;
- }
- default:
- {
- options.Files.Add(new SourceFile(arg));
- break;
- }
- }
-}
-
-foreach (var file in options.Files)
-{
- if (!File.Exists(file.Path))
- {
- Console.Error.WriteLine($"File '{file}' does not exist");
- return 1;
- }
-}
-
-var diagnostics = new List();
-
-var syntaxTrees = new List();
-foreach (var file in options.Files)
-{
- var tokenizer = new Tokenizer(file);
- var tokens = tokenizer.Tokenize().ToList();
- diagnostics.AddRange(tokenizer.GetDiagnostics());
-
- var parser = new Parser();
- var syntaxTree = parser.Parse(tokens);
-
- diagnostics.AddRange(parser.GetDiagnostics());
-
- syntaxTrees.Add(syntaxTree);
-}
-
-var moduleSignatures = ModuleSignature.CollectFromSyntaxTrees(syntaxTrees);
-var modules = Module.CollectFromSyntaxTrees(syntaxTrees);
-
-var typedModules = new List();
-
-foreach (var module in modules)
-{
- var typeChecker = new TypeChecker(module, moduleSignatures);
- var typedModule = typeChecker.CheckModule();
- diagnostics.AddRange(typeChecker.GetDiagnostics());
- typedModules.Add(typedModule);
-}
-
-foreach (var diagnostic in diagnostics)
-{
- Console.Error.WriteLine(diagnostic.FormatANSI());
-}
-
-if (diagnostics.Any(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error))
-{
- return 1;
-}
-
-var objectFiles = new List();
-
-for (var i = 0; i < typedModules.Count; i++)
-{
- var typedModule = typedModules[i];
- var outFileName = Path.Combine(".build", "code", Path.ChangeExtension(options.Files[i].Path, null));
-
- var outFileDir = Path.GetDirectoryName(outFileName);
- if (!string.IsNullOrEmpty(outFileDir))
- {
- Directory.CreateDirectory(outFileDir);
- }
-
- var generator = new QBEGenerator(typedModule, moduleSignatures);
- var ssa = generator.Emit();
-
- var ssaFilePath = Path.ChangeExtension(outFileName, "ssa");
- File.WriteAllText(ssaFilePath, ssa);
-
- var asmFilePath = Path.ChangeExtension(outFileName, "s");
- var qbeSuccess = await QBE.Invoke(ssaFilePath, asmFilePath);
-
- if (!qbeSuccess)
- {
- return 1;
- }
-
- var objFilePath = Path.ChangeExtension(outFileName, "o");
- var asmSuccess = await GCC.Assemble(asmFilePath, objFilePath);
-
- if (!asmSuccess)
- {
- return 1;
- }
-
- objectFiles.Add(objFilePath);
-}
-
-var resources = Assembly.GetExecutingAssembly().GetManifestResourceNames();
-
-string[] runtimeObjects = ["runtime.o", "x64.o"];
-
-foreach (var runtimeObject in runtimeObjects)
-{
- var runtime = resources.First(r => r.EndsWith(runtimeObject));
-
- await using var reader = Assembly
- .GetExecutingAssembly()
- .GetManifestResourceStream(runtime);
-
- if (reader == null)
- {
- Console.Error.WriteLine($"Cannot open read stream to '{runtimeObject}'");
- return 1;
- }
-
- var runtimePath = Path.Combine(".build", "runtime", runtimeObject);
- var runtimeDir = Path.GetDirectoryName(runtimePath);
- if (!string.IsNullOrEmpty(runtimeDir))
- {
- Directory.CreateDirectory(runtimeDir);
- }
-
- await using var writer = new FileStream(runtimePath, FileMode.Create);
-
- reader.CopyTo(writer);
-
- objectFiles.Add(runtimePath);
-}
-
-var outPath = options.OutputPath ?? Path.Combine(".build", "out.a");
-var outDir = Path.GetDirectoryName(outPath);
-if (!string.IsNullOrEmpty(outDir))
-{
- Directory.CreateDirectory(outDir);
-}
-
-var archiveResult = await Archive.Invoke(outPath, objectFiles);
-if (!archiveResult)
-{
- return 1;
-}
-
-return 0;
\ No newline at end of file
diff --git a/src/compiler/NubLang.CLI/QBE.cs b/src/compiler/NubLang.CLI/QBE.cs
deleted file mode 100644
index 52e37c5..0000000
--- a/src/compiler/NubLang.CLI/QBE.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-using System.Diagnostics;
-
-namespace NubLang.CLI;
-
-public static class QBE
-{
- public static async Task Invoke(string ssaPath, string outPath)
- {
- using var process = new Process();
- process.StartInfo = new ProcessStartInfo("qbe", ["-o", outPath, ssaPath])
- {
- UseShellExecute = false,
- RedirectStandardOutput = true,
- RedirectStandardError = true,
- CreateNoWindow = true
- };
-
- process.Start();
-
- await process.WaitForExitAsync();
-
- var errors = await process.StandardError.ReadToEndAsync();
- if (!string.IsNullOrWhiteSpace(errors))
- {
- await Console.Error.WriteLineAsync("qbe error:\n" + errors);
- }
-
- return process.ExitCode == 0;
- }
-}
\ No newline at end of file
diff --git a/src/compiler/NubLang.CLI/assets/runtime.o b/src/compiler/NubLang.CLI/assets/runtime.o
deleted file mode 100644
index 3024a90..0000000
Binary files a/src/compiler/NubLang.CLI/assets/runtime.o and /dev/null differ
diff --git a/src/compiler/NubLang.CLI/assets/x64.o b/src/compiler/NubLang.CLI/assets/x64.o
deleted file mode 100644
index 6724856..0000000
Binary files a/src/compiler/NubLang.CLI/assets/x64.o and /dev/null differ
diff --git a/src/compiler/NubLang/Code/SourceFile.cs b/src/compiler/NubLang/Code/SourceFile.cs
deleted file mode 100644
index 48370c4..0000000
--- a/src/compiler/NubLang/Code/SourceFile.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-namespace NubLang.Code;
-
-public class SourceFile
-{
- private string? _content;
-
- public SourceFile(string path)
- {
- Path = path ?? throw new ArgumentNullException(nameof(path));
- }
-
- public string Path { get; }
-
- public string GetText() => _content ??= File.ReadAllText(Path);
- public override string ToString() => Path;
-
- public override bool Equals(object? obj)
- {
- return obj is SourceFile other && other.Path == Path;
- }
-
- public override int GetHashCode()
- {
- return HashCode.Combine(typeof(SourceFile), Path);
- }
-
- public static bool operator ==(SourceFile? left, SourceFile? right) => Equals(left, right);
- public static bool operator !=(SourceFile? left, SourceFile? right) => !Equals(left, right);
-}
-
-public class SourceFileSpan
-{
- public SourceFileSpan(SourceFile sourceFile, SourceSpan span)
- {
- SourceFile = sourceFile;
- Span = span;
- }
-
- public SourceFile SourceFile { get; }
- public SourceSpan Span { get; }
-}
\ No newline at end of file
diff --git a/src/compiler/NubLang/Code/SourceLocation.cs b/src/compiler/NubLang/Code/SourceLocation.cs
deleted file mode 100644
index 38bf900..0000000
--- a/src/compiler/NubLang/Code/SourceLocation.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-namespace NubLang.Code;
-
-public readonly struct SourceLocation : IEquatable
-{
- public static SourceLocation Zero => new(0, 0);
-
- public SourceLocation(int line, int column)
- {
- Line = line;
- Column = column;
- }
-
- public int Line { get; }
- public int Column { get; }
-
- public override string ToString()
- {
- return $"{Line}:{Column}";
- }
-
- public override bool Equals(object? obj)
- {
- return obj is SourceLocation other && Equals(other);
- }
-
- public bool Equals(SourceLocation other)
- {
- return Line == other.Line && Column == other.Column;
- }
-
- public override int GetHashCode()
- {
- return HashCode.Combine(typeof(SourceLocation), Line, Column);
- }
-
- public static bool operator ==(SourceLocation left, SourceLocation right) => Equals(left, right);
- public static bool operator !=(SourceLocation left, SourceLocation right) => !Equals(left, right);
- public static bool operator <(SourceLocation left, SourceLocation right) => left.Line < right.Line || (left.Line == right.Line && left.Column < right.Column);
- public static bool operator >(SourceLocation left, SourceLocation right) => left.Line > right.Line || (left.Line == right.Line && left.Column > right.Column);
- public static bool operator <=(SourceLocation left, SourceLocation right) => left.Line <= right.Line || (left.Line == right.Line && left.Column <= right.Column);
- public static bool operator >=(SourceLocation left, SourceLocation right) => left.Line >= right.Line || (left.Line == right.Line && left.Column >= right.Column);
-}
\ No newline at end of file
diff --git a/src/compiler/NubLang/Code/SourceSpan.cs b/src/compiler/NubLang/Code/SourceSpan.cs
deleted file mode 100644
index 3e7a89b..0000000
--- a/src/compiler/NubLang/Code/SourceSpan.cs
+++ /dev/null
@@ -1,57 +0,0 @@
-namespace NubLang.Code;
-
-public readonly struct SourceSpan : IEquatable
-{
- public static SourceSpan Zero => new(SourceLocation.Zero, SourceLocation.Zero);
-
- public static SourceSpan Merge(params IEnumerable spans)
- {
- var spanArray = spans as SourceSpan[] ?? spans.ToArray();
-
- if (spanArray.Length == 0)
- {
- return Zero;
- }
-
- var minStart = spanArray.Min(s => s.Start);
- var maxEnd = spanArray.Max(s => s.End);
-
- return new SourceSpan(minStart, maxEnd);
- }
-
- public SourceSpan(SourceLocation start, SourceLocation end)
- {
- if (start > end)
- {
- throw new ArgumentException("Start location cannot be after end location");
- }
-
- Start = start;
- End = end;
- }
-
- public SourceLocation Start { get; }
- public SourceLocation End { get; }
-
- public override string ToString()
- {
- if (Start == End)
- {
- return $"{Start}";
- }
-
- if (Start.Line == End.Line)
- {
- return Start.Column == End.Column ? $"{Start}" : $"{Start.Line}:{Start.Column}-{End.Column}";
- }
-
- return $"{Start}-{End}";
- }
-
- public bool Equals(SourceSpan other) => Start == other.Start && End == other.End;
- public override bool Equals(object? obj) => obj is SourceSpan other && Equals(other);
- public override int GetHashCode() => HashCode.Combine(typeof(SourceSpan), Start, End);
-
- public static bool operator ==(SourceSpan left, SourceSpan right) => Equals(left, right);
- public static bool operator !=(SourceSpan left, SourceSpan right) => !Equals(left, right);
-}
\ No newline at end of file
diff --git a/src/compiler/NubLang/Diagnostics/ConsoleColors.cs b/src/compiler/NubLang/Diagnostics/ConsoleColors.cs
deleted file mode 100644
index 1a6f7a3..0000000
--- a/src/compiler/NubLang/Diagnostics/ConsoleColors.cs
+++ /dev/null
@@ -1,56 +0,0 @@
-namespace NubLang.Diagnostics;
-
-public static class ConsoleColors
-{
- public const string Reset = "\e[0m";
- public const string Bold = "\e[1m";
- public const string Faint = "\e[2m";
- public const string Italic = "\e[3m";
- public const string Underline = "\e[4m";
- public const string SlowBlink = "\e[5m";
- public const string RapidBlink = "\e[6m";
- public const string SwapBgAndFg = "\e[7m";
- public const string Conceal = "\e[8m";
- public const string CrossedOut = "\e[9m";
-
- public const string DefaultFont = "\e[10m";
- public const string AltFont1 = "\e[11m";
- public const string AltFont2 = "\e[12m";
- public const string AltFont3 = "\e[13m";
- public const string AltFont4 = "\e[14m";
- public const string AltFont5 = "\e[15m";
- public const string AltFont6 = "\e[16m";
- public const string AltFont7 = "\e[17m";
- public const string AltFont8 = "\e[18m";
- public const string AltFont9 = "\e[19m";
-
- public const string Black = "\e[30m";
- public const string Red = "\e[31m";
- public const string Green = "\e[32m";
- public const string Yellow = "\e[33m";
- public const string Blue = "\e[34m";
- public const string Magenta = "\e[35m";
- public const string Cyan = "\e[36m";
- public const string White = "\e[37m";
-
- public const string BrightBlack = "\e[90m";
- public const string BrightRed = "\e[91m";
- public const string BrightGreen = "\e[92m";
- public const string BrightYellow = "\e[93m";
- public const string BrightBlue = "\e[94m";
- public const string BrightMagenta = "\e[95m";
- public const string BrightCyan = "\e[96m";
- public const string BrightWhite = "\e[97m";
-
- private static bool IsColorSupported()
- {
- var term = Environment.GetEnvironmentVariable("TERM");
- var colorTerm = Environment.GetEnvironmentVariable("COLORTERM");
- return !string.IsNullOrEmpty(term) || !string.IsNullOrEmpty(colorTerm) || !Console.IsOutputRedirected;
- }
-
- public static string Colorize(string text, string color)
- {
- return IsColorSupported() ? $"{color}{text}{Reset}" : text;
- }
-}
\ No newline at end of file
diff --git a/src/compiler/NubLang/Diagnostics/Diagnostic.cs b/src/compiler/NubLang/Diagnostics/Diagnostic.cs
deleted file mode 100644
index b1fdd5f..0000000
--- a/src/compiler/NubLang/Diagnostics/Diagnostic.cs
+++ /dev/null
@@ -1,325 +0,0 @@
-using System.Text;
-using NubLang.Code;
-using NubLang.Parsing.Syntax;
-using NubLang.Tokenization;
-
-namespace NubLang.Diagnostics;
-
-public class Diagnostic
-{
- public class DiagnosticBuilder
- {
- private readonly DiagnosticSeverity _severity;
- private readonly string _message;
- private SourceFileSpan? _fileSpan;
- private string? _help;
-
- public DiagnosticBuilder(DiagnosticSeverity severity, string message)
- {
- _severity = severity;
- _message = message;
- }
-
- public DiagnosticBuilder At(SyntaxNode? node)
- {
- if (node != null)
- {
- var first = node.Tokens.FirstOrDefault();
- if (first?.FileSpan != null)
- {
- var span = SourceSpan.Merge(node.Tokens.Select(x => x.FileSpan?.Span ?? SourceSpan.Zero));
- At(new SourceFileSpan(first.FileSpan.SourceFile, span));
- }
- }
-
- return this;
- }
-
- public DiagnosticBuilder At(Token? token)
- {
- if (token != null)
- {
- At(token.FileSpan);
- }
-
- return this;
- }
-
- public DiagnosticBuilder At(SourceFileSpan? fileSpan)
- {
- if (fileSpan != null)
- {
- _fileSpan = fileSpan;
- }
-
- return this;
- }
-
- public DiagnosticBuilder WithHelp(string help)
- {
- _help = help;
- return this;
- }
-
- public Diagnostic Build() => new(_severity, _message, _help, _fileSpan);
- }
-
- public static DiagnosticBuilder Error(string message) => new(DiagnosticSeverity.Error, message);
- public static DiagnosticBuilder Warning(string message) => new(DiagnosticSeverity.Warning, message);
- public static DiagnosticBuilder Info(string message) => new(DiagnosticSeverity.Info, message);
-
- public DiagnosticSeverity Severity { get; }
- public string Message { get; }
- public string? Help { get; }
- public SourceFileSpan? FileSpan { get; }
-
- private Diagnostic(DiagnosticSeverity severity, string message, string? help, SourceFileSpan? fileSpan)
- {
- Severity = severity;
- Message = message;
- Help = help;
- FileSpan = fileSpan;
- }
-
- public string FormatANSI()
- {
- var sb = new StringBuilder();
-
- sb.Append(Severity switch
- {
- DiagnosticSeverity.Error => ConsoleColors.Colorize("error", ConsoleColors.Bold + ConsoleColors.Red),
- DiagnosticSeverity.Warning => ConsoleColors.Colorize("warning", ConsoleColors.Bold + ConsoleColors.Yellow),
- DiagnosticSeverity.Info => ConsoleColors.Colorize("info", ConsoleColors.Bold + ConsoleColors.Blue),
- _ => ConsoleColors.Colorize("unknown", ConsoleColors.Bold + ConsoleColors.White)
- });
-
- if (FileSpan != null)
- {
- sb.Append(ConsoleColors.Colorize($" at {FileSpan.SourceFile.Path}:{FileSpan.Span}", ConsoleColors.Faint));
- }
-
- sb.Append(": ");
- sb.Append(ConsoleColors.Colorize(Message, ConsoleColors.BrightWhite));
-
- if (FileSpan != null)
- {
- sb.AppendLine();
- var text = FileSpan.SourceFile.GetText();
-
- var lines = text.Split('\n');
-
- var startLine = FileSpan.Span.Start.Line;
- var endLine = FileSpan.Span.End.Line;
-
- const int CONTEXT_LINES = 3;
-
- var contextStartLine = Math.Max(1, startLine - CONTEXT_LINES);
- var contextEndLine = Math.Min(lines.Length, endLine + CONTEXT_LINES);
-
- var numberPadding = contextEndLine.ToString().Length;
- var codePadding = lines.Skip(contextStartLine - 1).Take(contextEndLine - contextStartLine).Max(x => x.Length);
-
- sb.Append('╭');
- sb.Append(new string('─', numberPadding + 2));
- sb.Append('┬');
- sb.Append(new string('─', codePadding + 2));
- sb.Append('╮');
- sb.AppendLine();
-
- var tokenizer = new Tokenizer(FileSpan.SourceFile);
- var tokens = tokenizer.Tokenize().ToList();
-
- for (var i = contextStartLine; i <= contextEndLine; i++)
- {
- var line = lines[i - 1];
-
- sb.Append("│ ");
- sb.Append(i.ToString().PadRight(numberPadding));
- sb.Append(" │ ");
- sb.Append(ApplySyntaxHighlighting(line.PadRight(codePadding), i, tokens));
- sb.Append(" │");
- sb.AppendLine();
-
- if (i >= startLine && i <= endLine)
- {
- var markerStartColumn = 1;
- var markerEndColumn = line.Length + 1;
-
- if (i == startLine)
- {
- markerStartColumn = FileSpan.Span.Start.Column;
- }
-
- if (i == endLine)
- {
- markerEndColumn = FileSpan.Span.End.Column;
- }
-
- var markerLength = markerEndColumn - markerStartColumn;
- var marker = new string('^', markerLength);
-
- var markerColor = Severity switch
- {
- DiagnosticSeverity.Info => ConsoleColors.Blue,
- DiagnosticSeverity.Warning => ConsoleColors.Yellow,
- DiagnosticSeverity.Error => ConsoleColors.Red,
- _ => ConsoleColors.White
- };
-
- sb.Append("│ ");
- sb.Append(new string(' ', numberPadding));
- sb.Append(" │ ");
- sb.Append(new string(' ', markerStartColumn - 1));
- sb.Append(ConsoleColors.Colorize(marker, markerColor));
- sb.Append(new string(' ', codePadding - markerEndColumn + 1));
- sb.Append(" │");
- sb.AppendLine();
- }
- }
-
- sb.Append('╰');
- sb.Append(new string('─', numberPadding + 2));
- sb.Append('┴');
- sb.Append(new string('─', codePadding + 2));
- sb.Append('╯');
- }
-
- if (Help != null)
- {
- sb.AppendLine();
- sb.Append(ConsoleColors.Colorize($"help: {Help}", ConsoleColors.Cyan));
- }
-
- return sb.ToString();
- }
-
- private static string ApplySyntaxHighlighting(string line, int lineNumber, List tokens)
- {
- var sb = new StringBuilder();
- var lineTokens = tokens
- .Where(t => t.FileSpan.Span.Start.Line == lineNumber)
- .OrderBy(t => t.FileSpan.Span.Start.Column)
- .ToList();
-
- if (lineTokens.Count == 0)
- {
- return line;
- }
-
- var currentColumn = 1;
-
- foreach (var token in lineTokens)
- {
- var tokenStart = token.FileSpan.Span.Start.Column;
- var tokenEnd = token.FileSpan.Span.End.Column;
-
- if (tokenStart > currentColumn)
- {
- var beforeToken = line.Substring(currentColumn - 1, tokenStart - currentColumn);
- sb.Append(beforeToken);
- }
-
- var tokenLength = tokenEnd - tokenStart;
- if (tokenStart - 1 + tokenLength <= line.Length)
- {
- var tokenText = line.Substring(tokenStart - 1, tokenLength);
-
- var coloredToken = ColorizeToken(token, tokenText);
- sb.Append(coloredToken);
- }
-
- currentColumn = tokenEnd;
- }
-
- if (currentColumn <= line.Length)
- {
- var remaining = line[(currentColumn - 1)..];
- sb.Append(remaining);
- }
-
- return sb.ToString();
- }
-
- private static string ColorizeToken(Token token, string tokenText)
- {
- switch (token)
- {
- case IdentifierToken:
- {
- return ConsoleColors.Colorize(tokenText, ConsoleColors.BrightWhite);
- }
- case LiteralToken literal:
- {
- if (literal.Kind == LiteralKind.String)
- {
- return ConsoleColors.Colorize(tokenText, ConsoleColors.Green);
- }
-
- return ConsoleColors.Colorize(tokenText, ConsoleColors.Magenta);
- }
- case SymbolToken symbolToken:
- {
- switch (symbolToken.Symbol)
- {
- case Symbol.Func:
- case Symbol.Return:
- case Symbol.If:
- case Symbol.Else:
- case Symbol.While:
- case Symbol.Break:
- case Symbol.Continue:
- case Symbol.Struct:
- case Symbol.Let:
- case Symbol.Calls:
- case Symbol.Interface:
- case Symbol.For:
- case Symbol.Extern:
- {
- return ConsoleColors.Colorize(tokenText, ConsoleColors.Bold + ConsoleColors.Blue);
- }
- case Symbol.Assign:
- case Symbol.Bang:
- case Symbol.Equal:
- case Symbol.NotEqual:
- case Symbol.LessThan:
- case Symbol.LessThanOrEqual:
- case Symbol.GreaterThan:
- case Symbol.GreaterThanOrEqual:
- case Symbol.Plus:
- case Symbol.Minus:
- case Symbol.Star:
- case Symbol.ForwardSlash:
- case Symbol.Caret:
- case Symbol.Ampersand:
- {
- return ConsoleColors.Colorize(tokenText, ConsoleColors.Yellow);
- }
- case Symbol.Colon:
- case Symbol.OpenParen:
- case Symbol.CloseParen:
- case Symbol.OpenBrace:
- case Symbol.CloseBrace:
- case Symbol.OpenBracket:
- case Symbol.CloseBracket:
- case Symbol.Comma:
- case Symbol.Period:
- case Symbol.Semi:
- {
- return ConsoleColors.Colorize(tokenText, ConsoleColors.BrightBlack);
- }
- }
-
- break;
- }
- }
-
- return tokenText;
- }
-}
-
-public enum DiagnosticSeverity
-{
- Info,
- Warning,
- Error
-}
\ No newline at end of file
diff --git a/src/compiler/NubLang/Generation/QBE/QBEGenerator.cs b/src/compiler/NubLang/Generation/QBE/QBEGenerator.cs
deleted file mode 100644
index 4f956e2..0000000
--- a/src/compiler/NubLang/Generation/QBE/QBEGenerator.cs
+++ /dev/null
@@ -1,1440 +0,0 @@
-using System.Diagnostics;
-using System.Globalization;
-using System.Text;
-using NubLang.Tokenization;
-using NubLang.TypeChecking;
-using NubLang.TypeChecking.Node;
-
-namespace NubLang.Generation.QBE;
-
-public class QBEGenerator
-{
- private readonly QBEWriter _writer;
- private readonly TypedModule _module;
- private readonly IReadOnlyDictionary _moduleSignatures;
-
- private readonly List _cStringLiterals = [];
- private readonly List _stringLiterals = [];
- private readonly Stack _breakLabels = [];
- private readonly Stack _continueLabels = [];
- private int _tmpIndex;
- private int _labelIndex;
- private int _cStringLiteralIndex;
- private int _stringLiteralIndex;
- private bool _codeIsReachable = true;
-
- public QBEGenerator(TypedModule module, IReadOnlyDictionary moduleSignatures)
- {
- _module = module;
- _moduleSignatures = moduleSignatures;
- _writer = new QBEWriter();
- }
-
- public string Emit()
- {
- _cStringLiterals.Clear();
- _stringLiterals.Clear();
- _breakLabels.Clear();
- _continueLabels.Clear();
- _tmpIndex = 0;
- _labelIndex = 0;
- _cStringLiteralIndex = 0;
- _stringLiteralIndex = 0;
- _codeIsReachable = true;
-
- foreach (var (module, signature) in _moduleSignatures)
- {
- foreach (var structType in signature.StructTypes)
- {
- EmitStructType(module, structType);
- _writer.NewLine();
- }
- }
-
- foreach (var structDef in _module.Definitions.OfType())
- {
- EmitStructDefinition(structDef);
- _writer.NewLine();
- }
-
- foreach (var funcDef in _module.Definitions.OfType())
- {
- EmitLocalFuncDefinition(funcDef);
- _writer.NewLine();
- }
-
- // foreach (var structDef in _module.Definitions.OfType().Where(x => x.InterfaceImplementations.Count > 0))
- // {
- // _writer.Write($"data {StructVtableName(_module.Name, structDef.Name)} = {{ ");
- //
- // foreach (var interfaceImplementation in structDef.InterfaceImplementations)
- // {
- // var interfaceDef = _definitionTable.LookupInterface(interfaceImplementation.Name);
- // foreach (var func in interfaceDef.Functions)
- // {
- // _writer.Write($"l {StructFuncName(_module.Name, structDef.Name, func.Name)}, ");
- // }
- // }
- //
- // _writer.WriteLine("}");
- // }
-
- foreach (var cStringLiteral in _cStringLiterals)
- {
- _writer.WriteLine($"data {cStringLiteral.Name} = {{ b \"{cStringLiteral.Value}\", b 0 }}");
- }
-
- foreach (var stringLiteral in _stringLiterals)
- {
- var bytes = Encoding.UTF8.GetBytes(stringLiteral.Value).Select(b => $"b {b}");
- _writer.WriteLine($"data {stringLiteral.Name} = {{ l {stringLiteral.Value.Length}, {string.Join(", ", bytes)} }}");
- }
-
- return _writer.ToString();
- }
-
- private static string QBEAssign(TypeNode type)
- {
- if (type.IsSimpleType(out var simpleType, out _))
- {
- return simpleType.StorageSize switch
- {
- StorageSize.I8 or StorageSize.U8 or StorageSize.I16 or StorageSize.U16 or StorageSize.I32 or StorageSize.U32 => "=w",
- StorageSize.I64 or StorageSize.U64 => "=l",
- StorageSize.F32 => "=s",
- StorageSize.F64 => "=d",
- _ => throw new ArgumentOutOfRangeException(nameof(simpleType.StorageSize))
- };
- }
-
- return "=l";
- }
-
- private void EmitStore(TypeNode type, string value, string destination)
- {
- string store;
-
- if (type.IsSimpleType(out var simpleType, out _))
- {
- store = simpleType.StorageSize switch
- {
- StorageSize.I8 or StorageSize.U8 => "storeb",
- StorageSize.I16 or StorageSize.U16 => "storeh",
- StorageSize.I32 or StorageSize.U32 => "storew",
- StorageSize.I64 or StorageSize.U64 => "storel",
- StorageSize.F32 => "stores",
- StorageSize.F64 => "stored",
- _ => throw new ArgumentOutOfRangeException(nameof(simpleType.StorageSize))
- };
- }
- else
- {
- store = "storel";
- }
-
- _writer.Indented($"{store} {value}, {destination}");
- }
-
- private string EmitLoad(TypeNode type, string from)
- {
- string load;
-
- if (type.IsSimpleType(out var simpleType, out _))
- {
- load = simpleType.StorageSize switch
- {
- StorageSize.I64 or StorageSize.U64 => "loadl",
- StorageSize.I32 or StorageSize.U32 => "loadw",
- StorageSize.I16 => "loadsh",
- StorageSize.I8 => "loadsb",
- StorageSize.U16 => "loaduh",
- StorageSize.U8 => "loadub",
- StorageSize.F64 => "loadd",
- StorageSize.F32 => "loads",
- _ => throw new ArgumentOutOfRangeException(nameof(simpleType.StorageSize))
- };
- }
- else
- {
- load = "loadl";
- }
-
- var into = TmpName();
-
- _writer.Indented($"{into} {QBEAssign(type)} {load} {from}");
-
- return into;
- }
-
- private void EmitMemset(string destination, int value, string length)
- {
- var count = TmpName();
- _writer.Indented($"{count} =l copy 0");
-
- var loopLabel = LabelName();
- _writer.WriteLine(loopLabel);
-
- var continueLabel = LabelName();
- var doneLabel = LabelName();
- var condition = TmpName();
- _writer.Indented($"{condition} =w cultl {count}, {length}");
- _writer.Indented($"jnz {condition}, {continueLabel}, {doneLabel}");
-
- _writer.WriteLine(continueLabel);
-
- var destinationAddress = TmpName();
- _writer.Indented($"{destinationAddress} =l add {destination}, {count}");
-
- _writer.Indented($"storeb {value}, {destinationAddress}");
-
- _writer.Indented($"{count} =l add {count}, 1");
- _writer.Indented($"jmp {loopLabel}");
-
- _writer.WriteLine(doneLabel);
- }
-
- private void EmitMemcpy(string source, string destination, string length)
- {
- var count = TmpName();
- _writer.Indented($"{count} =l copy 0");
-
- var loopLabel = LabelName();
- _writer.WriteLine(loopLabel);
-
- var continueLabel = LabelName();
- var doneLabel = LabelName();
- var condition = TmpName();
- _writer.Indented($"{condition} =w cultl {count}, {length}");
- _writer.Indented($"jnz {condition}, {continueLabel}, {doneLabel}");
-
- _writer.WriteLine(continueLabel);
-
- var sourceAddress = TmpName();
- _writer.Indented($"{sourceAddress} =l add {source}, {count}");
-
- var destinationAddress = TmpName();
- _writer.Indented($"{destinationAddress} =l add {destination}, {count}");
-
- var value = TmpName();
- _writer.Indented($"{value} =w loadub {sourceAddress}");
- _writer.Indented($"storeb {value}, {destinationAddress}");
-
- _writer.Indented($"{count} =l add {count}, 1");
- _writer.Indented($"jmp {loopLabel}");
-
- _writer.WriteLine(doneLabel);
- }
-
- private string EmitArraySizeInBytes(ArrayTypeNode type, string array)
- {
- var size = TmpName();
- _writer.Indented($"{size} =l loadl {array}");
- _writer.Indented($"{size} =l mul {size}, {SizeOf(type.ElementType)}");
- _writer.Indented($"{size} =l add {size}, 8");
- return size;
- }
-
- private string EmitCStringSizeInBytes(string cstring)
- {
- var count = TmpName();
- _writer.Indented($"{count} =l copy 0");
-
- var loopLabel = LabelName();
- _writer.WriteLine(loopLabel);
-
- var address = TmpName();
- _writer.Indented($"{address} =l add {cstring}, {count}");
-
- var value = TmpName();
- _writer.Indented($"{value} =w loadub {address}");
-
- var notZeroLabel = LabelName();
- var zeroLabel = LabelName();
- _writer.Indented($"jnz {value}, {notZeroLabel}, {zeroLabel}");
- _writer.WriteLine(notZeroLabel);
- _writer.Indented($"{count} =l add {count}, 1");
- _writer.Indented($"jmp {loopLabel}");
- _writer.WriteLine(zeroLabel);
-
- return count;
- }
-
- private string EmitStringSizeInBytes(string nubstring)
- {
- var size = TmpName();
- _writer.Indented($"{size} =l loadl {nubstring}");
- _writer.Indented($"{size} =l add {size}, 8");
- return size;
- }
-
- private void EmitCopyInto(ExpressionNode source, string destination)
- {
- // Simple types are passed in registers and can therefore just be stored
- if (source.Type.IsSimpleType(out var simpleType, out var complexType))
- {
- var value = EmitExpression(source);
- EmitStore(simpleType, value, destination);
- return;
- }
-
- // Structs and interfaces has known sizes at compile time
- if (complexType is StructTypeNode or InterfaceTypeNode)
- {
- var value = EmitExpression(source);
- _writer.Indented($"blit {value}, {destination}, {SizeOf(complexType)}");
- }
- // The rest of the complex types has unknown sizes
- else
- {
- var value = EmitExpression(source);
- var size = complexType switch
- {
- ArrayTypeNode arrayType => EmitArraySizeInBytes(arrayType, value),
- CStringTypeNode => EmitCStringSizeInBytes(value),
- StringTypeNode => EmitStringSizeInBytes(value),
- _ => throw new ArgumentOutOfRangeException(nameof(source.Type))
- };
-
- var buffer = TmpName();
- _writer.Indented($"{buffer} =l alloc8 {size}");
- EmitMemcpy(value, buffer, size);
- EmitStore(complexType, buffer, destination);
- }
- }
-
- private string EmitCopy(ExpressionNode source)
- {
- // Allowlist for types which are safe to not copy
- if (source is ArrayInitializerNode or StructInitializerNode or ConvertToInterfaceNode or LiteralNode)
- {
- return EmitExpression(source);
- }
-
- // Simple types are passed in registers and therefore always copied
- if (source.Type.IsSimpleType(out _, out var complexType))
- {
- return EmitExpression(source);
- }
-
- // For the rest, we figure out the size of the type and shallow copy them
- var value = EmitExpression(source);
- var destination = TmpName();
-
- // Structs and interfaces has known sizes at compile time
- if (complexType is StructTypeNode or InterfaceTypeNode)
- {
- var size = SizeOf(complexType);
- _writer.Indented($"{destination} =l alloc8 {size}");
- _writer.Indented($"blit {value}, {destination}, {size}");
- }
- // The rest of the complex types has unknown sizes
- else
- {
- var size = complexType switch
- {
- ArrayTypeNode arrayType => EmitArraySizeInBytes(arrayType, value),
- CStringTypeNode => EmitCStringSizeInBytes(value),
- StringTypeNode => EmitStringSizeInBytes(value),
- _ => throw new ArgumentOutOfRangeException(nameof(source.Type))
- };
-
- _writer.Indented($"{destination} =l alloc8 {size}");
- EmitMemcpy(value, destination, size);
- }
-
- return destination;
- }
-
- // Utility to create QBE type names for function parameters and return types
- private string FuncQBETypeName(TypeNode type)
- {
- if (type.IsSimpleType(out var simpleType, out var complexType))
- {
- return simpleType.StorageSize switch
- {
- StorageSize.I64 or StorageSize.U64 => "l",
- StorageSize.I32 or StorageSize.U32 => "w",
- StorageSize.I16 => "sh",
- StorageSize.I8 => "sb",
- StorageSize.U16 => "uh",
- StorageSize.U8 => "ub",
- StorageSize.F64 => "d",
- StorageSize.F32 => "s",
- _ => throw new ArgumentOutOfRangeException()
- };
- }
-
- if (complexType is StructTypeNode structType)
- {
- return StructTypeName(structType.Module, structType.Name);
- }
-
- return "l";
- }
-
- private void EmitLocalFuncDefinition(LocalFuncNode funcDef)
- {
- _labelIndex = 0;
- _tmpIndex = 0;
-
- _writer.Write("export function ");
-
- if (funcDef.Signature.ReturnType is not VoidTypeNode)
- {
- _writer.Write(FuncQBETypeName(funcDef.Signature.ReturnType) + ' ');
- }
-
- _writer.Write(LocalFuncName(_module.Name, funcDef.Name));
-
- _writer.Write("(");
- foreach (var parameter in funcDef.Signature.Parameters)
- {
- _writer.Write(FuncQBETypeName(parameter.Type) + $" %{parameter.Name}");
- }
-
- _writer.WriteLine(") {");
- _writer.WriteLine("@start");
-
- EmitBlock(funcDef.Body);
-
- // Implicit return for void functions if no explicit return has been set
- if (funcDef.Signature.ReturnType is VoidTypeNode && funcDef.Body.Statements.LastOrDefault() is not ReturnNode)
- {
- _writer.Indented("ret");
- }
-
- _writer.WriteLine("}");
- }
-
- private void EmitStructDefinition(StructNode structDef)
- {
- var type = TypeResolver.ResolveStructType(_module.Name, structDef.Name, _moduleSignatures);
-
- // _writer.WriteLine($"export function {StructCtorName(_module.Name, structDef.Name)}() {{");
- // _writer.WriteLine("@start");
- // _writer.Indented($"%struct =l alloc8 {SizeOf(type)}");
- // // todo(nub31): Finish constructor
- // _writer.Indented("ret %struct");
- // _writer.WriteLine("}");
-
- foreach (var function in structDef.Functions)
- {
- _labelIndex = 0;
- _tmpIndex = 0;
-
- _writer.NewLine();
- _writer.Write("export function ");
-
- if (function.Signature.ReturnType is not VoidTypeNode)
- {
- _writer.Write(FuncQBETypeName(function.Signature.ReturnType) + ' ');
- }
-
- _writer.Write(StructFuncName(_module.Name, structDef.Name, function.Name));
-
- _writer.Write("(l %this, ");
- foreach (var parameter in function.Signature.Parameters)
- {
- _writer.Write(FuncQBETypeName(parameter.Type) + $" %{parameter.Name}, ");
- }
-
- _writer.WriteLine(") {");
- _writer.WriteLine("@start");
-
- EmitBlock(function.Body);
-
- // Implicit return for void functions if no explicit return has been set
- if (function.Signature.ReturnType is VoidTypeNode && function.Body.Statements.LastOrDefault() is not ReturnNode)
- {
- _writer.Indented("ret");
- }
-
- _writer.WriteLine("}");
- }
- }
-
- private void EmitStructType(string module, StructTypeNode structType)
- {
- _writer.WriteLine($"type {StructTypeName(module, structType.Name)} = {{ ");
-
- foreach (var field in structType.Fields)
- {
- _writer.Indented($"{StructDefQBEType(field.Type)},");
- }
-
- _writer.WriteLine("}");
- return;
-
- string StructDefQBEType(TypeNode type)
- {
- if (type.IsSimpleType(out var simpleType, out var complexType))
- {
- return simpleType.StorageSize switch
- {
- StorageSize.I64 or StorageSize.U64 => "l",
- StorageSize.I32 or StorageSize.U32 => "w",
- StorageSize.I16 or StorageSize.U16 => "h",
- StorageSize.I8 or StorageSize.U8 => "b",
- StorageSize.F64 => "d",
- StorageSize.F32 => "s",
- _ => throw new ArgumentOutOfRangeException()
- };
- }
-
- if (complexType is StructTypeNode childStructType)
- {
- return StructTypeName(childStructType.Module, childStructType.Name);
- }
-
- return "l";
- }
- }
-
- private void EmitBlock(BlockNode block)
- {
- foreach (var statement in block.Statements)
- {
- if (_codeIsReachable)
- {
- EmitStatement(statement);
- }
- }
-
- _codeIsReachable = true;
- }
-
- private void EmitStatement(StatementNode statement)
- {
- // var tokens = statement.Tokens.ToArray();
- // if (tokens.Length != 0)
- // {
- // _writer.WriteLine($"dbgloc {tokens[0].FileSpan.Span.Start.Line}");
- // }
-
- switch (statement)
- {
- case AssignmentNode assignment:
- EmitAssignment(assignment);
- break;
- case BreakNode:
- EmitBreak();
- break;
- case ContinueNode:
- EmitContinue();
- break;
- case IfNode ifStatement:
- EmitIf(ifStatement);
- break;
- case ReturnNode @return:
- EmitReturn(@return);
- break;
- case StatementExpressionNode statementExpression:
- EmitExpression(statementExpression.Expression);
- break;
- case VariableDeclarationNode variableDeclaration:
- EmitVariableDeclaration(variableDeclaration);
- break;
- case WhileNode whileStatement:
- EmitWhile(whileStatement);
- break;
- default:
- throw new ArgumentOutOfRangeException(nameof(statement));
- }
- }
-
- private void EmitAssignment(AssignmentNode assignment)
- {
- EmitCopyInto(assignment.Value, EmitAddressOfLValue(assignment.Target));
- }
-
- private void EmitBreak()
- {
- _writer.Indented($"jmp {_breakLabels.Peek()}");
- _codeIsReachable = false;
- }
-
- private void EmitContinue()
- {
- _writer.Indented($"jmp {_continueLabels.Peek()}");
- _codeIsReachable = false;
- }
-
- private void EmitIf(IfNode ifStatement)
- {
- var trueLabel = LabelName();
- var falseLabel = LabelName();
- var endLabel = LabelName();
-
- var result = EmitExpression(ifStatement.Condition);
- _writer.Indented($"jnz {result}, {trueLabel}, {falseLabel}");
- _writer.WriteLine(trueLabel);
- EmitBlock(ifStatement.Body);
- _writer.Indented($"jmp {endLabel}");
- _writer.WriteLine(falseLabel);
- if (ifStatement.Else.HasValue)
- {
- ifStatement.Else.Value.Match(EmitIf, EmitBlock);
- }
-
- _writer.WriteLine(endLabel);
- }
-
- private void EmitReturn(ReturnNode @return)
- {
- if (@return.Value.HasValue)
- {
- var result = EmitExpression(@return.Value.Value);
- _writer.Indented($"ret {result}");
- }
- else
- {
- _writer.Indented("ret");
- }
- }
-
- private void EmitVariableDeclaration(VariableDeclarationNode variableDeclaration)
- {
- var name = $"%{variableDeclaration.Name}";
- _writer.Indented($"{name} =l alloc8 {SizeOf(variableDeclaration.Type)}");
-
- if (variableDeclaration.Assignment.HasValue)
- {
- EmitCopyInto(variableDeclaration.Assignment.Value, name);
- }
- }
-
- private void EmitWhile(WhileNode whileStatement)
- {
- var conditionLabel = LabelName();
- var iterationLabel = LabelName();
- var endLabel = LabelName();
-
- _breakLabels.Push(endLabel);
- _continueLabels.Push(conditionLabel);
-
- _writer.Indented($"jmp {conditionLabel}");
- _writer.WriteLine(iterationLabel);
- EmitBlock(whileStatement.Body);
- _writer.WriteLine(conditionLabel);
- var result = EmitExpression(whileStatement.Condition);
- _writer.Indented($"jnz {result}, {iterationLabel}, {endLabel}");
- _writer.WriteLine(endLabel);
-
- _continueLabels.Pop();
- _breakLabels.Pop();
- }
-
- private string EmitExpression(ExpressionNode expression)
- {
- // var tokens = expression.Tokens.ToArray();
- // if (tokens.Length != 0)
- // {
- // _writer.WriteLine($"dbgloc {tokens[0].FileSpan.Span.Start.Line}");
- // }
-
- return expression switch
- {
- ArrayInitializerNode arrayInitializer => EmitArrayInitializer(arrayInitializer),
- StructInitializerNode structInitializer => EmitStructInitializer(structInitializer),
- AddressOfNode addressOf => EmitAddressOf(addressOf),
- DereferenceNode dereference => EmitDereference(dereference),
- BinaryExpressionNode binary => EmitBinaryExpression(binary),
- FuncCallNode funcCall => EmitFuncCall(funcCall),
- InterfaceFuncCallNode interfaceFuncCall => EmitInterfaceFuncCall(interfaceFuncCall),
- ConvertToInterfaceNode convertToInterface => EmitConvertToInterface(convertToInterface),
- ConvertIntNode convertInt => EmitConvertInt(convertInt),
- ConvertFloatNode convertFloat => EmitConvertFloat(convertFloat),
- VariableIdentifierNode identifier => EmitVariableIdentifier(identifier),
- FuncIdentifierNode funcIdentifier => EmitFuncIdentifier(funcIdentifier),
- FuncParameterIdentifierNode funcParameterIdentifier => EmitParameterFuncIdentifier(funcParameterIdentifier),
- LiteralNode literal => EmitLiteral(literal),
- UnaryExpressionNode unaryExpression => EmitUnaryExpression(unaryExpression),
- StructFieldAccessNode structFieldAccess => EmitStructFieldAccess(structFieldAccess),
- StructFuncCallNode structFuncCall => EmitStructFuncCall(structFuncCall),
- ArrayIndexAccessNode arrayIndex => EmitArrayIndexAccess(arrayIndex),
- _ => throw new ArgumentOutOfRangeException(nameof(expression))
- };
- }
-
- private string EmitFuncIdentifier(FuncIdentifierNode localFuncIdent)
- {
- // todo(nub31): Support for extern funcs
- return LocalFuncName(localFuncIdent.Module, localFuncIdent.Name);
- }
-
- private string EmitVariableIdentifier(VariableIdentifierNode variableIdent)
- {
- var address = EmitAddressOfVariableIdent(variableIdent);
-
- return variableIdent.Type.IsSimpleType(out _, out _)
- ? EmitLoad(variableIdent.Type, address)
- : address;
- }
-
- private string EmitParameterFuncIdentifier(FuncParameterIdentifierNode funcParameterIdent)
- {
- return "%" + funcParameterIdent.Name;
- }
-
- private string EmitArrayIndexAccess(ArrayIndexAccessNode arrayIndexAccess)
- {
- // var address = EmitAddressOfArrayIndexAccess(arrayIndexAccess);
- // if (arrayIndexAccess.Type is StructTypeNode)
- // {
- // return address;
- // }
- //
- // return EmitLoad(arrayIndexAccess.Type, address);
- throw new NotImplementedException();
- }
-
- private string EmitArrayInitializer(ArrayInitializerNode arrayInitializer)
- {
- var capacity = EmitExpression(arrayInitializer.Capacity);
- var elementSize = SizeOf(arrayInitializer.ElementType);
-
- var capacityInBytes = TmpName();
- _writer.Indented($"{capacityInBytes} =l mul {capacity}, {elementSize}");
- var totalSize = TmpName();
- _writer.Indented($"{totalSize} =l add {capacityInBytes}, 8");
-
- var arrayPointer = TmpName();
- _writer.Indented($"{arrayPointer} =l alloc8 {totalSize}");
- _writer.Indented($"storel {capacity}, {arrayPointer}");
-
- var dataPointer = TmpName();
- _writer.Indented($"{dataPointer} =l add {arrayPointer}, 8");
- EmitMemset(dataPointer, 0, capacityInBytes);
-
- return arrayPointer;
- }
-
- private string EmitDereference(DereferenceNode dereference)
- {
- var address = EmitExpression(dereference.Expression);
- if (dereference.Type is StructTypeNode)
- {
- return address;
- }
-
- return EmitLoad(dereference.Type, address);
- }
-
- private string EmitAddressOf(AddressOfNode addressOf)
- {
- return EmitAddressOfLValue(addressOf.LValue);
- }
-
- private string EmitAddressOfLValue(LValueExpressionNode addressOf)
- {
- return addressOf switch
- {
- ArrayIndexAccessNode arrayIndexAccess => EmitAddressOfArrayIndexAccess(arrayIndexAccess),
- StructFieldAccessNode structFieldAccess => EmitAddressOfStructFieldAccess(structFieldAccess),
- VariableIdentifierNode variableIdent => EmitAddressOfVariableIdent(variableIdent),
- _ => throw new ArgumentOutOfRangeException(nameof(addressOf))
- };
- }
-
- private string EmitAddressOfArrayIndexAccess(ArrayIndexAccessNode arrayIndexAccess)
- {
- var array = EmitExpression(arrayIndexAccess.Target);
- var index = EmitExpression(arrayIndexAccess.Index);
-
- var elementType = ((ArrayTypeNode)arrayIndexAccess.Target.Type).ElementType;
-
- var offset = TmpName();
- _writer.Indented($"{offset} =l mul {index}, {SizeOf(elementType)}");
- _writer.Indented($"{offset} =l add {offset}, 8");
- _writer.Indented($"{offset} =l add {array}, {offset}");
- return offset;
- }
-
- private string EmitAddressOfStructFieldAccess(StructFieldAccessNode structFieldAccess)
- {
- var target = EmitExpression(structFieldAccess.Target);
-
- var structType = TypeResolver.ResolveStructType(structFieldAccess.StructType.Module, structFieldAccess.StructType.Name, _moduleSignatures);
- var offset = OffsetOf(structType, structFieldAccess.Field);
-
- var address = TmpName();
- _writer.Indented($"{address} =l add {target}, {offset}");
- return address;
- }
-
- private string EmitAddressOfVariableIdent(VariableIdentifierNode variableIdent)
- {
- return "%" + variableIdent.Name;
- }
-
- private string EmitBinaryExpression(BinaryExpressionNode binaryExpression)
- {
- var left = EmitExpression(binaryExpression.Left);
- var right = EmitExpression(binaryExpression.Right);
-
- var outputName = TmpName();
-
- var instruction = EmitBinaryInstructionForOperator(binaryExpression.Operator, binaryExpression.Left.Type);
-
- _writer.Indented($"{outputName} {QBEAssign(binaryExpression.Left.Type)} {instruction} {left}, {right}");
- return outputName;
- }
-
- private static string EmitBinaryInstructionForOperator(BinaryOperator op, TypeNode type)
- {
- return op switch
- {
- BinaryOperator.RightShift => type switch
- {
- IntTypeNode { Signed: true } => "sar",
- IntTypeNode { Signed: false } => "shr",
- _ => throw new NotSupportedException($"Right shift not supported for type '{type}'")
- },
- BinaryOperator.BitwiseAnd => "and",
- BinaryOperator.BitwiseOr => "or",
- BinaryOperator.BitwiseXor => "xor",
- BinaryOperator.LeftShift => "shl",
- BinaryOperator.Divide => type switch
- {
- IntTypeNode { Signed: true } => "div",
- IntTypeNode { Signed: false } => "udiv",
- FloatTypeNode => "div",
- _ => throw new NotSupportedException($"Division not supported for type '{type}'")
- },
- BinaryOperator.Modulo => type switch
- {
- IntTypeNode { Signed: true } => "rem",
- IntTypeNode { Signed: false } => "urem",
- _ => throw new NotSupportedException($"Modulo not supported for type '{type}'")
- },
- BinaryOperator.Plus => "add",
- BinaryOperator.Minus => "sub",
- BinaryOperator.Multiply => "mul",
- BinaryOperator.Equal => type switch
- {
- IntTypeNode intType => intType.Width switch
- {
- <= 32 => "ceqw",
- 64 => "ceql",
- _ => throw new ArgumentOutOfRangeException()
- },
- FloatTypeNode floatType => floatType.Width switch
- {
- 32 => "ceqs",
- 64 => "ceqd",
- _ => throw new ArgumentOutOfRangeException()
- },
- _ => throw new NotSupportedException($"Equality comparison not supported for type '{type}'")
- },
- BinaryOperator.NotEqual => type switch
- {
- IntTypeNode intType => intType.Width switch
- {
- <= 32 => "cnew",
- 64 => "cnel",
- _ => throw new ArgumentOutOfRangeException()
- },
- FloatTypeNode floatType => floatType.Width switch
- {
- 32 => "cnes",
- 64 => "cned",
- _ => throw new ArgumentOutOfRangeException()
- },
- _ => throw new NotSupportedException($"Inequality comparison not supported for type '{type}'")
- },
- BinaryOperator.LessThan => type switch
- {
- IntTypeNode { Signed: true } intType => intType.Width switch
- {
- <= 32 => "csltw",
- 64 => "csltl",
- _ => throw new ArgumentOutOfRangeException()
- },
- IntTypeNode { Signed: false } intType => intType.Width switch
- {
- <= 32 => "cultw",
- 64 => "cultl",
- _ => throw new ArgumentOutOfRangeException()
- },
- FloatTypeNode floatType => floatType.Width switch
- {
- 32 => "clts",
- 64 => "cltd",
- _ => throw new ArgumentOutOfRangeException()
- },
- _ => throw new NotSupportedException($"Less than comparison not supported for type '{type}'")
- },
- BinaryOperator.LessThanOrEqual => type switch
- {
- IntTypeNode { Signed: true } intType => intType.Width switch
- {
- <= 32 => "cslew",
- 64 => "cslel",
- _ => throw new ArgumentOutOfRangeException()
- },
- IntTypeNode { Signed: false } intType => intType.Width switch
- {
- <= 32 => "culew",
- 64 => "culel",
- _ => throw new ArgumentOutOfRangeException()
- },
- FloatTypeNode floatType => floatType.Width switch
- {
- 32 => "cles",
- 64 => "cled",
- _ => throw new ArgumentOutOfRangeException()
- },
- _ => throw new NotSupportedException($"Less than or equal comparison not supported for type '{type}'")
- },
- BinaryOperator.GreaterThan => type switch
- {
- IntTypeNode { Signed: true } intType => intType.Width switch
- {
- <= 32 => "csgtw",
- 64 => "csgtl",
- _ => throw new ArgumentOutOfRangeException()
- },
- IntTypeNode { Signed: false } intType => intType.Width switch
- {
- <= 32 => "cugtw",
- 64 => "cugtl",
- _ => throw new ArgumentOutOfRangeException()
- },
- FloatTypeNode floatType => floatType.Width switch
- {
- 32 => "cgts",
- 64 => "cgtd",
- _ => throw new ArgumentOutOfRangeException()
- },
- _ => throw new NotSupportedException($"Greater than comparison not supported for type '{type}'")
- },
- BinaryOperator.GreaterThanOrEqual => type switch
- {
- IntTypeNode { Signed: true } intType => intType.Width switch
- {
- <= 32 => "csgew",
- 64 => "csgel",
- _ => throw new ArgumentOutOfRangeException()
- },
- IntTypeNode { Signed: false } intType => intType.Width switch
- {
- <= 32 => "cugew",
- 64 => "cugel",
- _ => throw new ArgumentOutOfRangeException()
- },
- FloatTypeNode floatType => floatType.Width switch
- {
- 32 => "cges",
- 64 => "cged",
- _ => throw new ArgumentOutOfRangeException()
- },
- _ => throw new NotSupportedException($"Greater than or equal comparison not supported for type '{type}'")
- },
- // todo(nub31): Implement short circuiting
- BinaryOperator.LogicalAnd => "and",
- BinaryOperator.LogicalOr => "or",
- _ => throw new ArgumentOutOfRangeException(nameof(op))
- };
- }
-
- private string EmitLiteral(LiteralNode literal)
- {
- switch (literal.Kind)
- {
- case LiteralKind.Integer:
- {
- if (literal.Type is FloatTypeNode { Width: 32 })
- {
- var value = float.Parse(literal.Value, CultureInfo.InvariantCulture);
- var bits = BitConverter.SingleToInt32Bits(value);
- return bits.ToString();
- }
-
- if (literal.Type is FloatTypeNode { Width: 64 })
- {
- var value = double.Parse(literal.Value, CultureInfo.InvariantCulture);
- var bits = BitConverter.DoubleToInt64Bits(value);
- return bits.ToString();
- }
-
- if (literal.Type is IntTypeNode)
- {
- return literal.Value;
- }
-
- break;
- }
- case LiteralKind.Float:
- {
- if (literal.Type is IntTypeNode)
- {
- return literal.Value.Split(".").First();
- }
-
- if (literal.Type is FloatTypeNode { Width: 32 })
- {
- var value = float.Parse(literal.Value, CultureInfo.InvariantCulture);
- var bits = BitConverter.SingleToInt32Bits(value);
- return bits.ToString();
- }
-
- if (literal.Type is FloatTypeNode { Width: 64 })
- {
- var value = double.Parse(literal.Value, CultureInfo.InvariantCulture);
- var bits = BitConverter.DoubleToInt64Bits(value);
- return bits.ToString();
- }
-
- break;
- }
- case LiteralKind.String:
- {
- if (literal.Type is StringTypeNode)
- {
- var stringLiteral = new StringLiteral(literal.Value, StringName());
- _stringLiterals.Add(stringLiteral);
- return stringLiteral.Name;
- }
-
- if (literal.Type is CStringTypeNode)
- {
- var cStringLiteral = new CStringLiteral(literal.Value, CStringName());
- _cStringLiterals.Add(cStringLiteral);
- return cStringLiteral.Name;
- }
-
- break;
- }
- case LiteralKind.Bool:
- {
- if (literal.Type is BoolTypeNode)
- {
- return bool.Parse(literal.Value) ? "1" : "0";
- }
-
- break;
- }
- }
-
- throw new NotSupportedException($"Cannot create literal of kind '{literal.Kind}' for type {literal.Type}");
- }
-
- private string EmitStructInitializer(StructInitializerNode structInitializer)
- {
- var destination = TmpName();
- var size = SizeOf(structInitializer.StructType);
- _writer.Indented($"{destination} =l alloc8 {size}");
-
- foreach (var (field, value) in structInitializer.Initializers)
- {
- var offset = TmpName();
- _writer.Indented($"{offset} =l add {destination}, {OffsetOf(structInitializer.StructType, field)}");
- EmitCopyInto(value, offset);
- }
-
- return destination;
- }
-
- private string EmitUnaryExpression(UnaryExpressionNode unaryExpression)
- {
- var operand = EmitExpression(unaryExpression.Operand);
- var outputName = TmpName();
-
- switch (unaryExpression.Operator)
- {
- case UnaryOperator.Negate:
- {
- switch (unaryExpression.Operand.Type)
- {
- case IntTypeNode { Signed: true, Width: 64 }:
- _writer.Indented($"{outputName} =l neg {operand}");
- return outputName;
- case IntTypeNode { Signed: true, Width: 8 or 16 or 32 }:
- _writer.Indented($"{outputName} =w neg {operand}");
- return outputName;
- case FloatTypeNode { Width: 64 }:
- _writer.Indented($"{outputName} =d neg {operand}");
- return outputName;
- case FloatTypeNode { Width: 32 }:
- _writer.Indented($"{outputName} =s neg {operand}");
- return outputName;
- }
-
- break;
- }
- case UnaryOperator.Invert:
- {
- switch (unaryExpression.Operand.Type)
- {
- case BoolTypeNode:
- _writer.Indented($"{outputName} =w xor {operand}, 1");
- return outputName;
- }
-
- break;
- }
- default:
- {
- throw new ArgumentOutOfRangeException();
- }
- }
-
- throw new NotSupportedException($"Unary operator {unaryExpression.Operator} for type {unaryExpression.Operand.Type} not supported");
- }
-
- private string EmitStructFieldAccess(StructFieldAccessNode structFieldAccess)
- {
- var address = EmitAddressOfStructFieldAccess(structFieldAccess);
- if (structFieldAccess.Type is StructTypeNode)
- {
- return address;
- }
-
- return EmitLoad(structFieldAccess.Type, address);
- }
-
- private string EmitStructFuncCall(StructFuncCallNode structFuncCall)
- {
- var func = StructFuncName(structFuncCall.StructType.Module, structFuncCall.StructType.Name, structFuncCall.Name);
-
- var thisParameter = EmitExpression(structFuncCall.StructExpression);
-
- List parameterStrings = [$"l {thisParameter}"];
-
- foreach (var parameter in structFuncCall.Parameters)
- {
- var copy = EmitCopy(parameter);
- parameterStrings.Add($"{FuncQBETypeName(parameter.Type)} {copy}");
- }
-
- if (structFuncCall.Type is VoidTypeNode)
- {
- _writer.Indented($"call {func}({string.Join(", ", parameterStrings)})");
- return string.Empty;
- }
- else
- {
- var outputName = TmpName();
- _writer.Indented($"{outputName} {QBEAssign(structFuncCall.Type)} call {func}({string.Join(", ", parameterStrings)})");
- return outputName;
- }
- }
-
- private string EmitInterfaceFuncCall(InterfaceFuncCallNode interfaceFuncCall)
- {
- var target = EmitExpression(interfaceFuncCall.InterfaceExpression);
-
- var functionIndex = interfaceFuncCall.InterfaceType.Functions.ToList().FindIndex(x => x.Name == interfaceFuncCall.Name);
- var offset = functionIndex * 8;
-
- var vtable = TmpName();
- _writer.Indented($"{vtable} =l loadl {target}");
-
- var funcOffset = TmpName();
- _writer.Indented($"{funcOffset} =l add {vtable}, {offset}");
-
- var func = TmpName();
- _writer.Indented($"{func} =l loadl {funcOffset}");
-
- var data = TmpName();
- _writer.Indented($"{data} =l add {target}, 8");
- _writer.Indented($"{data} =l loadl {data}");
-
- List parameterStrings = [$"l {data}"];
-
- foreach (var parameter in interfaceFuncCall.Parameters)
- {
- var copy = EmitCopy(parameter);
- parameterStrings.Add($"{FuncQBETypeName(parameter.Type)} {copy}");
- }
-
- if (interfaceFuncCall.Type is VoidTypeNode)
- {
- _writer.Indented($"call {func}({string.Join(", ", parameterStrings)})");
- return string.Empty;
- }
- else
- {
- var outputName = TmpName();
- _writer.Indented($"{outputName} {QBEAssign(interfaceFuncCall.Type)} call {func}({string.Join(", ", parameterStrings)})");
- return outputName;
- }
- }
-
- private string EmitConvertToInterface(ConvertToInterfaceNode convertToInterface)
- {
- var implementation = EmitExpression(convertToInterface.Implementation);
-
- var vtableOffset = 0;
- foreach (var interfaceImplementation in convertToInterface.StructType.InterfaceImplementations)
- {
- if (interfaceImplementation == convertToInterface.InterfaceType)
- {
- break;
- }
-
- vtableOffset += interfaceImplementation.Functions.Count * 8;
- }
-
- var destination = TmpName();
- _writer.Indented($"{destination} =l alloc8 {SizeOf(convertToInterface.InterfaceType)}");
-
- var interfaceVtablePointer = TmpName();
- _writer.Indented($"{interfaceVtablePointer} =l add {StructVtableName(convertToInterface.StructType.Module, convertToInterface.StructType.Name)}, {vtableOffset}");
- _writer.Indented($"storel {interfaceVtablePointer}, {destination}");
-
- var objectPointer = TmpName();
- _writer.Indented($"{objectPointer} =l add {destination}, 8");
- _writer.Indented($"storel {implementation}, {objectPointer}");
-
- return destination;
- }
-
- private string EmitConvertInt(ConvertIntNode convertInt)
- {
- var value = EmitExpression(convertInt.Value);
-
- if (convertInt.ValueType.Width >= convertInt.TargetType.Width)
- {
- return value;
- }
-
- var method = convertInt.ValueType.Signed switch
- {
- true => convertInt.ValueType.Width switch
- {
- 8 => "extsb",
- 16 => "extsh",
- 32 => "extsw",
- _ => throw new ArgumentOutOfRangeException()
- },
- false => convertInt.ValueType.Width switch
- {
- 8 => "extub",
- 16 => "extuh",
- 32 => "extuw",
- _ => throw new ArgumentOutOfRangeException()
- }
- };
-
- var result = TmpName();
- _writer.Indented($"{result} {QBEAssign(convertInt.TargetType)} {method} {value}");
- return result;
- }
-
- private string EmitConvertFloat(ConvertFloatNode convertFloat)
- {
- var value = EmitExpression(convertFloat.Value);
-
- if (convertFloat.ValueType.Width == convertFloat.TargetType.Width)
- {
- return value;
- }
-
- var method = convertFloat.ValueType.Width switch
- {
- 32 => "exts",
- 64 => "truncd",
- _ => throw new ArgumentOutOfRangeException()
- };
-
- var result = TmpName();
- _writer.Indented($"{result} {QBEAssign(convertFloat.TargetType)} {method} {value}");
- return result;
- }
-
- private string EmitFuncCall(FuncCallNode funcCall)
- {
- var funcPointer = EmitExpression(funcCall.Expression);
-
- var parameterStrings = new List();
-
- foreach (var parameter in funcCall.Parameters)
- {
- var copy = EmitCopy(parameter);
- parameterStrings.Add($"{FuncQBETypeName(parameter.Type)} {copy}");
- }
-
- if (funcCall.Type is VoidTypeNode)
- {
- _writer.Indented($"call {funcPointer}({string.Join(", ", parameterStrings)})");
- return string.Empty;
- }
- else
- {
- var outputName = TmpName();
- _writer.Indented($"{outputName} {QBEAssign(funcCall.Type)} call {funcPointer}({string.Join(", ", parameterStrings)})");
- return outputName;
- }
- }
-
- private static int SizeOf(TypeNode type)
- {
- return type switch
- {
- SimpleTypeNode simple => simple.StorageSize switch
- {
- StorageSize.Void => 0,
- StorageSize.I8 or StorageSize.U8 => 1,
- StorageSize.I16 or StorageSize.U16 => 2,
- StorageSize.I32 or StorageSize.U32 or StorageSize.F32 => 4,
- StorageSize.I64 or StorageSize.U64 or StorageSize.F64 => 8,
- _ => throw new ArgumentOutOfRangeException(nameof(type), $"Unknown storage size: {simple.StorageSize}")
- },
- CStringTypeNode => 8,
- StringTypeNode => 8,
- ArrayTypeNode => 8,
- StructTypeNode structType => CalculateStructSize(structType),
- InterfaceTypeNode => 16,
- _ => throw new ArgumentOutOfRangeException(nameof(type), $"Unknown type: {type.GetType()}")
- };
- }
-
- private static int CalculateStructSize(StructTypeNode structType)
- {
- var offset = 0;
-
- var fields = new List(structType.Fields.Count);
-
- foreach (var field in structType.Fields)
- {
- var fieldAlignment = AlignmentOf(field.Type);
- offset = AlignTo(offset, fieldAlignment);
- offset += SizeOf(field.Type);
- }
-
- var structAlignment = CalculateStructAlignment(structType);
- return AlignTo(offset, structAlignment);
- }
-
- private static int AlignmentOf(TypeNode type)
- {
- return type switch
- {
- SimpleTypeNode simple => simple.StorageSize switch
- {
- StorageSize.Void => 1,
- StorageSize.I8 or StorageSize.U8 => 1,
- StorageSize.I16 or StorageSize.U16 => 2,
- StorageSize.I32 or StorageSize.U32 or StorageSize.F32 => 4,
- StorageSize.I64 or StorageSize.U64 or StorageSize.F64 => 8,
- _ => throw new ArgumentOutOfRangeException(nameof(type), $"Unknown storage size: {simple.StorageSize}")
- },
- CStringTypeNode => 8,
- StringTypeNode => 8,
- ArrayTypeNode => 8,
- StructTypeNode structType => CalculateStructAlignment(structType),
- InterfaceTypeNode => 8,
- _ => throw new ArgumentOutOfRangeException(nameof(type), $"Unknown type: {type.GetType()}")
- };
- }
-
- private static int CalculateStructAlignment(StructTypeNode structType)
- {
- var maxAlignment = 1;
-
- if (structType.InterfaceImplementations.Any())
- {
- maxAlignment = Math.Max(maxAlignment, 8);
- }
-
- foreach (var field in structType.Fields)
- {
- var fieldAlignment = AlignmentOf(field.Type);
- maxAlignment = Math.Max(maxAlignment, fieldAlignment);
- }
-
- return maxAlignment;
- }
-
- private static int AlignTo(int offset, int alignment)
- {
- return (offset + alignment - 1) & ~(alignment - 1);
- }
-
- private static int OffsetOf(StructTypeNode structDef, string member)
- {
- var offset = 0;
-
- foreach (var field in structDef.Fields)
- {
- if (field.Name == member)
- {
- return offset;
- }
-
- var fieldAlignment = AlignmentOf(field.Type);
-
- offset = AlignTo(offset, fieldAlignment);
- offset += SizeOf(field.Type);
- }
-
- throw new UnreachableException($"Member '{member}' not found in struct");
- }
-
- #region Naming utilities
-
- private string TmpName()
- {
- return $"%t{++_tmpIndex}";
- }
-
- private string LabelName()
- {
- return $"@l{++_labelIndex}";
- }
-
- private string CStringName()
- {
- return $"$cstring{++_cStringLiteralIndex}";
- }
-
- private string StringName()
- {
- return $"$string{++_stringLiteralIndex}";
- }
-
- private string LocalFuncName(string module, string name)
- {
- return $"${module}.{name}";
- }
-
- private string ExternFuncName(ExternFuncNode funcDef)
- {
- return $"${funcDef.CallName}";
- }
-
- private string StructTypeName(string module, string name)
- {
- return $":{module}.{name}";
- }
-
- private string StructFuncName(string module, string structName, string funcName)
- {
- return $"${module}.{structName}_func.{funcName}";
- }
-
- private string StructCtorName(string module, string structName)
- {
- return $"${module}.{structName}_ctor";
- }
-
- private string StructVtableName(string module, string structName)
- {
- return $"${module}.{structName}_vtable";
- }
-
- #endregion
-}
-
-public class StringLiteral(string value, string name)
-{
- public string Value { get; } = value;
- public string Name { get; } = name;
-}
-
-public class CStringLiteral(string value, string name)
-{
- public string Value { get; } = value;
- public string Name { get; } = name;
-}
\ No newline at end of file
diff --git a/src/compiler/NubLang/Generation/QBE/QBEWriter.cs b/src/compiler/NubLang/Generation/QBE/QBEWriter.cs
deleted file mode 100644
index 2ff8668..0000000
--- a/src/compiler/NubLang/Generation/QBE/QBEWriter.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-using System.Text;
-
-namespace NubLang.Generation.QBE;
-
-internal class QBEWriter
-{
- private readonly StringBuilder _builder = new();
-
- public void Indented(string value)
- {
- _builder.Append('\t');
- _builder.AppendLine(value);
- }
-
- public void Comment(string comment)
- {
- _builder.AppendLine("# " + comment);
- }
-
- public void WriteLine(string text)
- {
- _builder.AppendLine(text);
- }
-
- public void Write(string text)
- {
- _builder.Append(text);
- }
-
- public void NewLine()
- {
- _builder.AppendLine();
- }
-
- public override string ToString()
- {
- return _builder.ToString();
- }
-}
\ No newline at end of file
diff --git a/src/compiler/NubLang/NubLang.csproj b/src/compiler/NubLang/NubLang.csproj
deleted file mode 100644
index b682a68..0000000
--- a/src/compiler/NubLang/NubLang.csproj
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
- net9.0
- enable
- enable
- true
-
-
-
diff --git a/src/compiler/NubLang/Optional.cs b/src/compiler/NubLang/Optional.cs
deleted file mode 100644
index a467b5b..0000000
--- a/src/compiler/NubLang/Optional.cs
+++ /dev/null
@@ -1,82 +0,0 @@
-using System.Diagnostics.CodeAnalysis;
-
-namespace NubLang;
-
-public static class Optional
-{
- public static Optional Empty() => new();
-
- ///
- /// Alias for creating an Optional which allows for implicit types
- ///
- public static Optional OfNullable(TValue? value)
- {
- return value ?? Optional.Empty();
- }
-
- ///
- /// Converts a nullable type to an Optional
- ///
- public static Optional ToOptional(this TValue? value)
- {
- return OfNullable(value);
- }
-}
-
-public readonly struct Optional
-{
- public static Optional Empty() => new();
-
- public static Optional OfNullable(TValue? value)
- {
- return value ?? Empty();
- }
-
- public Optional()
- {
- Value = default;
- HasValue = false;
- }
-
- public Optional(TValue value)
- {
- Value = value;
- HasValue = true;
- }
-
- public TValue? Value { get; }
-
- [MemberNotNullWhen(true, nameof(Value))]
- public bool HasValue { get; }
-
-
- [MemberNotNullWhen(true, nameof(Value))]
- public bool TryGetValue([NotNullWhen(true)] out TValue? value)
- {
- if (HasValue)
- {
- value = Value;
- return true;
- }
-
- value = default;
- return false;
- }
-
- public TValue GetValue()
- {
- return Value ?? throw new InvalidOperationException("Value is not set");
- }
-
- public static implicit operator Optional(TValue value) => new(value);
-
- public TValue Or(TValue other)
- {
- if (HasValue)
- {
- return Value;
- }
-
- return other;
- }
-}
\ No newline at end of file
diff --git a/src/compiler/NubLang/Parsing/Parser.cs b/src/compiler/NubLang/Parsing/Parser.cs
deleted file mode 100644
index c6d84ff..0000000
--- a/src/compiler/NubLang/Parsing/Parser.cs
+++ /dev/null
@@ -1,856 +0,0 @@
-using System.Diagnostics.CodeAnalysis;
-using NubLang.Diagnostics;
-using NubLang.Parsing.Syntax;
-using NubLang.Tokenization;
-
-namespace NubLang.Parsing;
-
-public sealed class Parser
-{
- private readonly List _diagnostics = [];
- private IReadOnlyList _tokens = [];
- private int _tokenIndex;
- private string _moduleName = string.Empty;
-
- private Token? CurrentToken => _tokenIndex < _tokens.Count ? _tokens[_tokenIndex] : null;
- private bool HasToken => CurrentToken != null;
-
- public IReadOnlyList GetDiagnostics()
- {
- return _diagnostics;
- }
-
- public SyntaxTree Parse(IReadOnlyList tokens)
- {
- _diagnostics.Clear();
- _tokens = tokens;
- _tokenIndex = 0;
- _moduleName = string.Empty;
-
- var metadata = ParseMetadata();
- var definitions = ParseDefinitions();
-
- return new SyntaxTree(definitions, metadata);
- }
-
- private SyntaxTreeMetadata ParseMetadata()
- {
- var imports = new List();
-
- try
- {
- ExpectSymbol(Symbol.Module);
- _moduleName = ExpectIdentifier().Value;
-
- while (TryExpectSymbol(Symbol.Import))
- {
- imports.Add(ExpectIdentifier().Value);
- }
- }
- catch (ParseException e)
- {
- _diagnostics.Add(e.Diagnostic);
- while (HasToken)
- {
- if (CurrentToken is SymbolToken { Symbol: Symbol.Module or Symbol.Import })
- {
- break;
- }
-
- Next();
- }
- }
-
- return new SyntaxTreeMetadata(_moduleName, imports);
- }
-
- private List ParseDefinitions()
- {
- var definitions = new List();
-
- while (HasToken)
- {
- try
- {
- var startIndex = _tokenIndex;
- var keyword = ExpectSymbol();
- var definition = keyword.Symbol switch
- {
- Symbol.Extern => ParseExtern(startIndex),
- Symbol.Func => ParseFunc(startIndex),
- Symbol.Struct => ParseStruct(startIndex),
- Symbol.Interface => ParseInterface(startIndex),
- _ => throw new ParseException(Diagnostic
- .Error($"Expected 'extern', 'func', 'struct' or 'interface' but found '{keyword.Symbol}'")
- .WithHelp("Valid definition keywords are 'extern', 'func', 'struct' and 'interface'")
- .At(keyword)
- .Build())
- };
-
- definitions.Add(definition);
- }
- catch (ParseException e)
- {
- _diagnostics.Add(e.Diagnostic);
- while (HasToken)
- {
- if (CurrentToken is SymbolToken { Symbol: Symbol.Extern or Symbol.Func or Symbol.Struct or Symbol.Interface })
- {
- break;
- }
-
- Next();
- }
- }
- }
-
- return definitions;
- }
-
- private FuncSignatureSyntax ParseFuncSignature()
- {
- var startIndex = _tokenIndex;
- List parameters = [];
-
- ExpectSymbol(Symbol.OpenParen);
-
- while (!TryExpectSymbol(Symbol.CloseParen))
- {
- parameters.Add(ParseFuncParameter());
-
- if (!TryExpectSymbol(Symbol.Comma))
- {
- ExpectSymbol(Symbol.CloseParen);
- break;
- }
- }
-
- var returnType = TryExpectSymbol(Symbol.Colon) ? ParseType() : new VoidTypeSyntax([]);
-
- return new FuncSignatureSyntax(GetTokens(startIndex), parameters, returnType);
- }
-
- private FuncParameterSyntax ParseFuncParameter()
- {
- var startIndex = _tokenIndex;
- var name = ExpectIdentifier();
- ExpectSymbol(Symbol.Colon);
- var type = ParseType();
-
- return new FuncParameterSyntax(GetTokens(startIndex), name.Value, type);
- }
-
- private DefinitionSyntax ParseExtern(int startIndex)
- {
- var keyword = ExpectSymbol();
-
- return keyword.Symbol switch
- {
- Symbol.Func => ParseExternFunc(startIndex),
- _ => throw new ParseException(Diagnostic
- .Error($"Unexpected symbol {keyword.Symbol} after extern declaration")
- .At(keyword)
- .Build())
- };
- }
-
- private ExternFuncSyntax ParseExternFunc(int startIndex)
- {
- var name = ExpectIdentifier();
-
- var callName = name.Value;
-
- if (TryExpectSymbol(Symbol.Calls))
- {
- callName = ExpectIdentifier().Value;
- }
-
- var signature = ParseFuncSignature();
-
- return new ExternFuncSyntax(GetTokens(startIndex), name.Value, callName, signature);
- }
-
- private FuncSyntax ParseFunc(int startIndex)
- {
- var name = ExpectIdentifier();
- var signature = ParseFuncSignature();
- var body = ParseBlock();
-
- return new FuncSyntax(GetTokens(startIndex), name.Value, signature, body);
- }
-
- private DefinitionSyntax ParseStruct(int startIndex)
- {
- var name = ExpectIdentifier();
- var interfaceImplementations = new List();
-
- if (TryExpectSymbol(Symbol.Colon))
- {
- do
- {
- var interfaceType = ParseType();
- interfaceImplementations.Add(interfaceType);
- } while (TryExpectSymbol(Symbol.Comma));
- }
-
- ExpectSymbol(Symbol.OpenBrace);
-
- List fields = [];
- List funcs = [];
-
- var fieldIndex = 0;
-
- while (!TryExpectSymbol(Symbol.CloseBrace))
- {
- var memberStartIndex = _tokenIndex;
-
- if (TryExpectSymbol(Symbol.Func))
- {
- var funcName = ExpectIdentifier().Value;
- var funcSignature = ParseFuncSignature();
- var funcBody = ParseBlock();
-
- funcs.Add(new StructFuncSyntax(GetTokens(memberStartIndex), funcName, funcSignature, funcBody));
- }
- else
- {
- var fieldName = ExpectIdentifier().Value;
- ExpectSymbol(Symbol.Colon);
- var fieldType = ParseType();
-
- var fieldValue = Optional.Empty();
-
- if (TryExpectSymbol(Symbol.Assign))
- {
- fieldValue = ParseExpression();
- }
-
- fields.Add(new StructFieldSyntax(GetTokens(memberStartIndex), fieldIndex++, fieldName, fieldType, fieldValue));
- }
- }
-
- return new StructSyntax(GetTokens(startIndex), name.Value, fields, funcs, interfaceImplementations);
- }
-
- private InterfaceSyntax ParseInterface(int startIndex)
- {
- var name = ExpectIdentifier();
-
- ExpectSymbol(Symbol.OpenBrace);
-
- List functions = [];
-
- while (!TryExpectSymbol(Symbol.CloseBrace))
- {
- var funcStartIndex = _tokenIndex;
-
- ExpectSymbol(Symbol.Func);
-
- var funcName = ExpectIdentifier().Value;
- var signature = ParseFuncSignature();
-
- functions.Add(new InterfaceFuncSyntax(GetTokens(funcStartIndex), funcName, signature));
- }
-
- return new InterfaceSyntax(GetTokens(startIndex), name.Value, functions);
- }
-
- private StatementSyntax ParseStatement()
- {
- if (CurrentToken is SymbolToken symbol)
- {
- switch (symbol.Symbol)
- {
- case Symbol.Return:
- return ParseReturn();
- case Symbol.If:
- return ParseIf();
- case Symbol.While:
- return ParseWhile();
- case Symbol.Let:
- return ParseVariableDeclaration();
- case Symbol.Break:
- return ParseBreak();
- case Symbol.Continue:
- return ParseContinue();
- }
- }
-
- return ParseStatementExpression();
- }
-
- private StatementSyntax ParseStatementExpression()
- {
- var startIndex = _tokenIndex;
- var expr = ParseExpression();
-
- if (TryExpectSymbol(Symbol.Assign))
- {
- var value = ParseExpression();
- return new AssignmentSyntax(GetTokens(startIndex), expr, value);
- }
-
- return new StatementExpressionSyntax(GetTokens(startIndex), expr);
- }
-
- private VariableDeclarationSyntax ParseVariableDeclaration()
- {
- var startIndex = _tokenIndex;
- ExpectSymbol(Symbol.Let);
- var name = ExpectIdentifier().Value;
-
- var explicitType = Optional.Empty();
- if (TryExpectSymbol(Symbol.Colon))
- {
- explicitType = ParseType();
- }
-
- var assignment = Optional.Empty();
- if (TryExpectSymbol(Symbol.Assign))
- {
- assignment = ParseExpression();
- }
-
- return new VariableDeclarationSyntax(GetTokens(startIndex), name, explicitType, assignment);
- }
-
- private StatementSyntax ParseBreak()
- {
- var startIndex = _tokenIndex;
- ExpectSymbol(Symbol.Break);
- return new BreakSyntax(GetTokens(startIndex));
- }
-
- private StatementSyntax ParseContinue()
- {
- var startIndex = _tokenIndex;
- ExpectSymbol(Symbol.Continue);
- return new ContinueSyntax(GetTokens(startIndex));
- }
-
- private ReturnSyntax ParseReturn()
- {
- var startIndex = _tokenIndex;
- ExpectSymbol(Symbol.Return);
-
- var value = Optional.Empty();
-
- if (!TryExpectSymbol(Symbol.Semi))
- {
- value = ParseExpression();
- }
-
- return new ReturnSyntax(GetTokens(startIndex), value);
- }
-
- private IfSyntax ParseIf()
- {
- var startIndex = _tokenIndex;
- ExpectSymbol(Symbol.If);
- var condition = ParseExpression();
- var body = ParseBlock();
-
- var elseStatement = Optional>.Empty();
- if (TryExpectSymbol(Symbol.Else))
- {
- elseStatement = TryExpectSymbol(Symbol.If)
- ? (Variant)ParseIf()
- : (Variant)ParseBlock();
- }
-
- return new IfSyntax(GetTokens(startIndex), condition, body, elseStatement);
- }
-
- private WhileSyntax ParseWhile()
- {
- var startIndex = _tokenIndex;
- ExpectSymbol(Symbol.While);
- var condition = ParseExpression();
- var body = ParseBlock();
- return new WhileSyntax(GetTokens(startIndex), condition, body);
- }
-
- private ExpressionSyntax ParseExpression(int precedence = 0)
- {
- var startIndex = _tokenIndex;
- var left = ParsePrimaryExpression();
-
- while (CurrentToken is SymbolToken symbolToken && TryGetBinaryOperator(symbolToken.Symbol, out var op) && GetBinaryOperatorPrecedence(op.Value) >= precedence)
- {
- Next();
- var right = ParseExpression(GetBinaryOperatorPrecedence(op.Value) + 1);
- left = new BinaryExpressionSyntax(GetTokens(startIndex), left, op.Value, right);
- }
-
- return left;
- }
-
- private static int GetBinaryOperatorPrecedence(BinaryOperatorSyntax operatorSyntax)
- {
- return operatorSyntax switch
- {
- BinaryOperatorSyntax.Multiply => 10,
- BinaryOperatorSyntax.Divide => 10,
- BinaryOperatorSyntax.Modulo => 10,
-
- BinaryOperatorSyntax.Plus => 9,
- BinaryOperatorSyntax.Minus => 9,
-
- BinaryOperatorSyntax.LeftShift => 8,
- BinaryOperatorSyntax.RightShift => 8,
-
- BinaryOperatorSyntax.GreaterThan => 7,
- BinaryOperatorSyntax.GreaterThanOrEqual => 7,
- BinaryOperatorSyntax.LessThan => 7,
- BinaryOperatorSyntax.LessThanOrEqual => 7,
-
- BinaryOperatorSyntax.Equal => 7,
- BinaryOperatorSyntax.NotEqual => 7,
-
- BinaryOperatorSyntax.BitwiseAnd => 6,
- BinaryOperatorSyntax.BitwiseXor => 5,
- BinaryOperatorSyntax.BitwiseOr => 4,
-
- BinaryOperatorSyntax.LogicalAnd => 3,
- BinaryOperatorSyntax.LogicalOr => 2,
-
- _ => throw new ArgumentOutOfRangeException(nameof(operatorSyntax), operatorSyntax, null)
- };
- }
-
- private bool TryGetBinaryOperator(Symbol symbol, [NotNullWhen(true)] out BinaryOperatorSyntax? binaryExpressionOperator)
- {
- switch (symbol)
- {
- case Symbol.Equal:
- binaryExpressionOperator = BinaryOperatorSyntax.Equal;
- return true;
- case Symbol.NotEqual:
- binaryExpressionOperator = BinaryOperatorSyntax.NotEqual;
- return true;
- case Symbol.LessThan:
- binaryExpressionOperator = BinaryOperatorSyntax.LessThan;
- return true;
- case Symbol.LessThanOrEqual:
- binaryExpressionOperator = BinaryOperatorSyntax.LessThanOrEqual;
- return true;
- case Symbol.GreaterThan:
- binaryExpressionOperator = BinaryOperatorSyntax.GreaterThan;
- return true;
- case Symbol.GreaterThanOrEqual:
- binaryExpressionOperator = BinaryOperatorSyntax.GreaterThanOrEqual;
- return true;
- case Symbol.And:
- binaryExpressionOperator = BinaryOperatorSyntax.LogicalAnd;
- return true;
- case Symbol.Or:
- binaryExpressionOperator = BinaryOperatorSyntax.LogicalOr;
- return true;
- case Symbol.Plus:
- binaryExpressionOperator = BinaryOperatorSyntax.Plus;
- return true;
- case Symbol.Minus:
- binaryExpressionOperator = BinaryOperatorSyntax.Minus;
- return true;
- case Symbol.Star:
- binaryExpressionOperator = BinaryOperatorSyntax.Multiply;
- return true;
- case Symbol.ForwardSlash:
- binaryExpressionOperator = BinaryOperatorSyntax.Divide;
- return true;
- case Symbol.Percent:
- binaryExpressionOperator = BinaryOperatorSyntax.Modulo;
- return true;
- case Symbol.LeftShift:
- binaryExpressionOperator = BinaryOperatorSyntax.LeftShift;
- return true;
- case Symbol.RightShift:
- binaryExpressionOperator = BinaryOperatorSyntax.RightShift;
- return true;
- case Symbol.Ampersand:
- binaryExpressionOperator = BinaryOperatorSyntax.BitwiseAnd;
- return true;
- case Symbol.Pipe:
- binaryExpressionOperator = BinaryOperatorSyntax.BitwiseOr;
- return true;
- case Symbol.Caret:
- binaryExpressionOperator = BinaryOperatorSyntax.BitwiseXor;
- return true;
- default:
- binaryExpressionOperator = null;
- return false;
- }
- }
-
- private ExpressionSyntax ParsePrimaryExpression()
- {
- var startIndex = _tokenIndex;
- var token = ExpectToken();
- var expr = token switch
- {
- LiteralToken literal => new LiteralSyntax(GetTokens(startIndex), literal.Value, literal.Kind),
- IdentifierToken identifier => new IdentifierSyntax(GetTokens(startIndex), Optional.Empty(), identifier.Value),
- SymbolToken symbolToken => symbolToken.Symbol switch
- {
- Symbol.OpenParen => ParseParenthesizedExpression(),
- Symbol.Minus => new UnaryExpressionSyntax(GetTokens(startIndex), UnaryOperatorSyntax.Negate, ParsePrimaryExpression()),
- Symbol.Bang => new UnaryExpressionSyntax(GetTokens(startIndex), UnaryOperatorSyntax.Invert, ParsePrimaryExpression()),
- Symbol.OpenBracket => ParseArrayInitializer(startIndex),
- Symbol.OpenBrace => new StructInitializerSyntax(GetTokens(startIndex), Optional.Empty(), ParseStructInitializerBody()),
- Symbol.Struct => ParseStructInitializer(startIndex),
- _ => throw new ParseException(Diagnostic
- .Error($"Unexpected symbol '{symbolToken.Symbol}' in expression")
- .WithHelp("Expected '(', '-', '!', '[' or '{'")
- .At(symbolToken)
- .Build())
- },
- _ => throw new ParseException(Diagnostic
- .Error($"Unexpected token '{token.GetType().Name}' in expression")
- .WithHelp("Expected literal, identifier, or parenthesized expression")
- .At(token)
- .Build())
- };
-
- return ParsePostfixOperators(expr);
- }
-
- private ExpressionSyntax ParseParenthesizedExpression()
- {
- var expression = ParseExpression();
- ExpectSymbol(Symbol.CloseParen);
- return expression;
- }
-
- private ExpressionSyntax ParsePostfixOperators(ExpressionSyntax expr)
- {
- var startIndex = _tokenIndex;
- while (HasToken)
- {
- if (TryExpectSymbol(Symbol.Ampersand))
- {
- expr = new AddressOfSyntax(GetTokens(startIndex), expr);
- continue;
- }
-
- if (TryExpectSymbol(Symbol.Caret))
- {
- expr = new DereferenceSyntax(GetTokens(startIndex), expr);
- continue;
- }
-
- if (TryExpectSymbol(Symbol.Period))
- {
- var member = ExpectIdentifier().Value;
- if (TryExpectSymbol(Symbol.OpenParen))
- {
- var parameters = new List();
-
- while (!TryExpectSymbol(Symbol.CloseParen))
- {
- parameters.Add(ParseExpression());
- if (!TryExpectSymbol(Symbol.Comma))
- {
- ExpectSymbol(Symbol.CloseParen);
- break;
- }
- }
-
- expr = new DotFuncCallSyntax(GetTokens(startIndex), member, expr, parameters);
- continue;
- }
-
- expr = new StructFieldAccessSyntax(GetTokens(startIndex), expr, member);
- continue;
- }
-
- if (TryExpectSymbol(Symbol.OpenBracket))
- {
- var index = ParseExpression();
- ExpectSymbol(Symbol.CloseBracket);
- expr = new ArrayIndexAccessSyntax(GetTokens(startIndex), expr, index);
- continue;
- }
-
- if (TryExpectSymbol(Symbol.OpenParen))
- {
- var parameters = new List();
-
- while (!TryExpectSymbol(Symbol.CloseParen))
- {
- parameters.Add(ParseExpression());
- if (!TryExpectSymbol(Symbol.Comma))
- {
- ExpectSymbol(Symbol.CloseParen);
- break;
- }
- }
-
- expr = new FuncCallSyntax(GetTokens(startIndex), expr, parameters);
- continue;
- }
-
- break;
- }
-
- return expr;
- }
-
- private ArrayInitializerSyntax ParseArrayInitializer(int startIndex)
- {
- var capacity = ParseExpression();
- ExpectSymbol(Symbol.CloseBracket);
- var type = ParseType();
- return new ArrayInitializerSyntax(GetTokens(startIndex), capacity, type);
- }
-
- private StructInitializerSyntax ParseStructInitializer(int startIndex)
- {
- var type = Optional.Empty();
- if (!TryExpectSymbol(Symbol.OpenBrace))
- {
- type = ParseType();
- ExpectSymbol(Symbol.OpenBrace);
- }
-
- var initializers = ParseStructInitializerBody();
-
- return new StructInitializerSyntax(GetTokens(startIndex), type, initializers);
- }
-
- private Dictionary ParseStructInitializerBody()
- {
- Dictionary initializers = [];
- while (!TryExpectSymbol(Symbol.CloseBrace))
- {
- var name = ExpectIdentifier().Value;
- ExpectSymbol(Symbol.Assign);
- var value = ParseExpression();
- initializers.Add(name, value);
- }
-
- return initializers;
- }
-
- private BlockSyntax ParseBlock()
- {
- var startIndex = _tokenIndex;
- ExpectSymbol(Symbol.OpenBrace);
- List statements = [];
- while (!TryExpectSymbol(Symbol.CloseBrace))
- {
- try
- {
- statements.Add(ParseStatement());
- }
- catch (ParseException ex)
- {
- _diagnostics.Add(ex.Diagnostic);
- Next();
- }
- }
-
- return new BlockSyntax(GetTokens(startIndex), statements);
- }
-
- private TypeSyntax ParseType()
- {
- var startIndex = _tokenIndex;
- if (TryExpectIdentifier(out var name))
- {
- if (name.Value[0] == 'u' && int.TryParse(name.Value[1..], out var size))
- {
- if (size is not 8 and not 16 and not 32 and not 64)
- {
- throw new ParseException(Diagnostic
- .Error("Arbitrary uint size is not supported")
- .WithHelp("Use u8, u16, u32 or u64")
- .At(name)
- .Build());
- }
-
- return new IntTypeSyntax(GetTokens(startIndex), false, size);
- }
-
- if (name.Value[0] == 'i' && int.TryParse(name.Value[1..], out size))
- {
- if (size is not 8 and not 16 and not 32 and not 64)
- {
- throw new ParseException(Diagnostic
- .Error("Arbitrary int size is not supported")
- .WithHelp("Use i8, i16, i32 or i64")
- .At(name)
- .Build());
- }
-
- return new IntTypeSyntax(GetTokens(startIndex), true, size);
- }
-
- if (name.Value[0] == 'f' && int.TryParse(name.Value[1..], out size))
- {
- if (size is not 32 and not 64)
- {
- throw new ParseException(Diagnostic
- .Error("Arbitrary float size is not supported")
- .WithHelp("Use f32 or f64")
- .At(name)
- .Build());
- }
-
- return new FloatTypeSyntax(GetTokens(startIndex), size);
- }
-
- return name.Value switch
- {
- "void" => new VoidTypeSyntax(GetTokens(startIndex)),
- "string" => new StringTypeSyntax(GetTokens(startIndex)),
- "cstring" => new CStringTypeSyntax(GetTokens(startIndex)),
- "bool" => new BoolTypeSyntax(GetTokens(startIndex)),
- _ => new CustomTypeSyntax(GetTokens(startIndex), _moduleName, name.Value)
- };
- }
-
- if (TryExpectSymbol(Symbol.Caret))
- {
- var baseType = ParseType();
- return new PointerTypeSyntax(GetTokens(startIndex), baseType);
- }
-
- if (TryExpectSymbol(Symbol.Func))
- {
- ExpectSymbol(Symbol.OpenParen);
-
- List parameters = [];
- while (!TryExpectSymbol(Symbol.CloseParen))
- {
- parameters.Add(ParseType());
- if (!TryExpectSymbol(Symbol.Comma))
- {
- ExpectSymbol(Symbol.CloseParen);
- break;
- }
- }
-
- var returnType = TryExpectSymbol(Symbol.Colon)
- ? ParseType()
- : new VoidTypeSyntax([]);
-
- return new FuncTypeSyntax(GetTokens(startIndex), parameters, returnType);
- }
-
- if (TryExpectSymbol(Symbol.OpenBracket))
- {
- ExpectSymbol(Symbol.CloseBracket);
- var baseType = ParseType();
- return new ArrayTypeSyntax(GetTokens(startIndex), baseType);
- }
-
- throw new ParseException(Diagnostic
- .Error("Invalid type syntax")
- .WithHelp("Expected type name, '^' for pointer, or '[]' for array")
- .At(CurrentToken)
- .Build());
- }
-
- private Token ExpectToken()
- {
- if (!HasToken)
- {
- throw new ParseException(Diagnostic
- .Error("Unexpected end of file")
- .WithHelp("Expected more tokens to complete the syntax")
- .At(_tokens[^1])
- .Build());
- }
-
- var token = CurrentToken!;
- Next();
- return token;
- }
-
- private SymbolToken ExpectSymbol()
- {
- var token = ExpectToken();
- if (token is not SymbolToken symbol)
- {
- throw new ParseException(Diagnostic
- .Error($"Expected symbol, but found {token.GetType().Name}")
- .WithHelp("This position requires a symbol like '(', ')', '{', '}', etc.")
- .At(token)
- .Build());
- }
-
- return symbol;
- }
-
- private void ExpectSymbol(Symbol expectedSymbol)
- {
- var token = ExpectSymbol();
- if (token.Symbol != expectedSymbol)
- {
- throw new ParseException(Diagnostic
- .Error($"Expected '{expectedSymbol}', but found '{token.Symbol}'")
- .WithHelp($"Insert '{expectedSymbol}' here")
- .At(token)
- .Build());
- }
- }
-
- private bool TryExpectSymbol(Symbol symbol)
- {
- if (CurrentToken is SymbolToken symbolToken && symbolToken.Symbol == symbol)
- {
- Next();
- return true;
- }
-
- return false;
- }
-
- private bool TryExpectIdentifier([NotNullWhen(true)] out IdentifierToken? identifier)
- {
- if (CurrentToken is IdentifierToken identifierToken)
- {
- identifier = identifierToken;
- Next();
- return true;
- }
-
- identifier = null;
- return false;
- }
-
- private IdentifierToken ExpectIdentifier()
- {
- var token = ExpectToken();
- if (token is not IdentifierToken identifier)
- {
- throw new ParseException(Diagnostic
- .Error($"Expected identifier, but found {token.GetType().Name}")
- .WithHelp("Provide a valid identifier name here")
- .At(token)
- .Build());
- }
-
- return identifier;
- }
-
- private void Next()
- {
- _tokenIndex++;
- }
-
- private IEnumerable GetTokens(int tokenStartIndex)
- {
- return _tokens.Skip(tokenStartIndex).Take(_tokenIndex - tokenStartIndex);
- }
-}
-
-public class ParseException : Exception
-{
- public Diagnostic Diagnostic { get; }
-
- public ParseException(Diagnostic diagnostic) : base(diagnostic.Message)
- {
- Diagnostic = diagnostic;
- }
-}
\ No newline at end of file
diff --git a/src/compiler/NubLang/Parsing/Syntax/DefinitionSyntax.cs b/src/compiler/NubLang/Parsing/Syntax/DefinitionSyntax.cs
deleted file mode 100644
index 524a8ef..0000000
--- a/src/compiler/NubLang/Parsing/Syntax/DefinitionSyntax.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-using NubLang.Tokenization;
-
-namespace NubLang.Parsing.Syntax;
-
-// todo(nub31): Check export modifier instead of harcoding true
-public abstract record DefinitionSyntax(IEnumerable Tokens, string Name, bool Exported = true) : SyntaxNode(Tokens);
-
-public record FuncParameterSyntax(IEnumerable Tokens, string Name, TypeSyntax Type) : SyntaxNode(Tokens);
-
-public record FuncSignatureSyntax(IEnumerable Tokens, IReadOnlyList Parameters, TypeSyntax ReturnType) : SyntaxNode(Tokens);
-
-public record FuncSyntax(IEnumerable Tokens, string Name, FuncSignatureSyntax Signature, BlockSyntax Body) : DefinitionSyntax(Tokens, Name);
-
-public record ExternFuncSyntax(IEnumerable Tokens, string Name, string CallName, FuncSignatureSyntax Signature) : DefinitionSyntax(Tokens, Name);
-
-public record StructFieldSyntax(IEnumerable Tokens, int Index, string Name, TypeSyntax Type, Optional Value) : SyntaxNode(Tokens);
-
-public record StructFuncSyntax(IEnumerable Tokens, string Name, FuncSignatureSyntax Signature, BlockSyntax Body) : SyntaxNode(Tokens);
-
-public record StructSyntax(IEnumerable Tokens, string Name, IReadOnlyList Fields, IReadOnlyList Functions, IReadOnlyList InterfaceImplementations) : DefinitionSyntax(Tokens, Name);
-
-public record InterfaceFuncSyntax(IEnumerable Tokens, string Name, FuncSignatureSyntax Signature) : SyntaxNode(Tokens);
-
-public record InterfaceSyntax(IEnumerable Tokens, string Name, IReadOnlyList Functions) : DefinitionSyntax(Tokens, Name);
\ No newline at end of file
diff --git a/src/compiler/NubLang/Parsing/Syntax/ExpressionSyntax.cs b/src/compiler/NubLang/Parsing/Syntax/ExpressionSyntax.cs
deleted file mode 100644
index f5f4a30..0000000
--- a/src/compiler/NubLang/Parsing/Syntax/ExpressionSyntax.cs
+++ /dev/null
@@ -1,57 +0,0 @@
-using NubLang.Tokenization;
-
-namespace NubLang.Parsing.Syntax;
-
-public enum UnaryOperatorSyntax
-{
- Negate,
- Invert
-}
-
-public enum BinaryOperatorSyntax
-{
- Equal,
- NotEqual,
- GreaterThan,
- GreaterThanOrEqual,
- LessThan,
- LessThanOrEqual,
- LogicalAnd,
- LogicalOr,
- Plus,
- Minus,
- Multiply,
- Divide,
- Modulo,
- LeftShift,
- RightShift,
- BitwiseAnd,
- BitwiseXor,
- BitwiseOr,
-}
-
-public abstract record ExpressionSyntax(IEnumerable Tokens) : SyntaxNode(Tokens);
-
-public record BinaryExpressionSyntax(IEnumerable Tokens, ExpressionSyntax Left, BinaryOperatorSyntax Operator, ExpressionSyntax Right) : ExpressionSyntax(Tokens);
-
-public record UnaryExpressionSyntax(IEnumerable Tokens, UnaryOperatorSyntax Operator, ExpressionSyntax Operand) : ExpressionSyntax(Tokens);
-
-public record FuncCallSyntax(IEnumerable Tokens, ExpressionSyntax Expression, IReadOnlyList Parameters) : ExpressionSyntax(Tokens);
-
-public record DotFuncCallSyntax(IEnumerable Tokens, string Name, ExpressionSyntax ThisParameter, IReadOnlyList Parameters) : ExpressionSyntax(Tokens);
-
-public record IdentifierSyntax(IEnumerable Tokens, Optional Module, string Name) : ExpressionSyntax(Tokens);
-
-public record ArrayInitializerSyntax(IEnumerable Tokens, ExpressionSyntax Capacity, TypeSyntax ElementType) : ExpressionSyntax(Tokens);
-
-public record ArrayIndexAccessSyntax(IEnumerable Tokens, ExpressionSyntax Target, ExpressionSyntax Index) : ExpressionSyntax(Tokens);
-
-public record AddressOfSyntax(IEnumerable Tokens, ExpressionSyntax Expression) : ExpressionSyntax(Tokens);
-
-public record LiteralSyntax(IEnumerable Tokens, string Value, LiteralKind Kind) : ExpressionSyntax(Tokens);
-
-public record StructFieldAccessSyntax(IEnumerable Tokens, ExpressionSyntax Target, string Member) : ExpressionSyntax(Tokens);
-
-public record StructInitializerSyntax(IEnumerable Tokens, Optional StructType, Dictionary Initializers) : ExpressionSyntax(Tokens);
-
-public record DereferenceSyntax(IEnumerable Tokens, ExpressionSyntax Expression) : ExpressionSyntax(Tokens);
\ No newline at end of file
diff --git a/src/compiler/NubLang/Parsing/Syntax/StatementSyntax.cs b/src/compiler/NubLang/Parsing/Syntax/StatementSyntax.cs
deleted file mode 100644
index acf1d8c..0000000
--- a/src/compiler/NubLang/Parsing/Syntax/StatementSyntax.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-using NubLang.Tokenization;
-
-namespace NubLang.Parsing.Syntax;
-
-public abstract record StatementSyntax(IEnumerable Tokens) : SyntaxNode(Tokens);
-
-public record StatementExpressionSyntax(IEnumerable Tokens, ExpressionSyntax Expression) : StatementSyntax(Tokens);
-
-public record ReturnSyntax(IEnumerable Tokens, Optional Value) : StatementSyntax(Tokens);
-
-public record AssignmentSyntax(IEnumerable Tokens, ExpressionSyntax Target, ExpressionSyntax Value) : StatementSyntax(Tokens);
-
-public record IfSyntax(IEnumerable Tokens, ExpressionSyntax Condition, BlockSyntax Body, Optional> Else) : StatementSyntax(Tokens);
-
-public record VariableDeclarationSyntax(IEnumerable Tokens, string Name, Optional ExplicitType, Optional Assignment) : StatementSyntax(Tokens);
-
-public record ContinueSyntax(IEnumerable Tokens) : StatementSyntax(Tokens);
-
-public record BreakSyntax(IEnumerable Tokens) : StatementSyntax(Tokens);
-
-public record WhileSyntax(IEnumerable Tokens, ExpressionSyntax Condition, BlockSyntax Body) : StatementSyntax(Tokens);
\ No newline at end of file
diff --git a/src/compiler/NubLang/Parsing/Syntax/SyntaxNode.cs b/src/compiler/NubLang/Parsing/Syntax/SyntaxNode.cs
deleted file mode 100644
index 7435d18..0000000
--- a/src/compiler/NubLang/Parsing/Syntax/SyntaxNode.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using NubLang.Tokenization;
-
-namespace NubLang.Parsing.Syntax;
-
-public abstract record SyntaxNode(IEnumerable Tokens);
-
-public record SyntaxTreeMetadata(string? ModuleName, IReadOnlyList Imports);
-
-public record SyntaxTree(IReadOnlyList Definitions, SyntaxTreeMetadata Metadata);
-
-public record BlockSyntax(IEnumerable Tokens, IReadOnlyList Statements) : SyntaxNode(Tokens);
\ No newline at end of file
diff --git a/src/compiler/NubLang/Parsing/Syntax/TypeSyntax.cs b/src/compiler/NubLang/Parsing/Syntax/TypeSyntax.cs
deleted file mode 100644
index 29ff911..0000000
--- a/src/compiler/NubLang/Parsing/Syntax/TypeSyntax.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-using NubLang.Tokenization;
-
-namespace NubLang.Parsing.Syntax;
-
-public abstract record TypeSyntax(IEnumerable Tokens) : SyntaxNode(Tokens);
-
-public record FuncTypeSyntax(IEnumerable Tokens, IReadOnlyList Parameters, TypeSyntax ReturnType) : TypeSyntax(Tokens);
-
-public record PointerTypeSyntax(IEnumerable Tokens, TypeSyntax BaseType) : TypeSyntax(Tokens);
-
-public record VoidTypeSyntax(IEnumerable Tokens) : TypeSyntax(Tokens);
-
-public record IntTypeSyntax(IEnumerable Tokens, bool Signed, int Width) : TypeSyntax(Tokens);
-
-public record FloatTypeSyntax(IEnumerable Tokens, int Width) : TypeSyntax(Tokens);
-
-public record BoolTypeSyntax(IEnumerable Tokens) : TypeSyntax(Tokens);
-
-public record StringTypeSyntax(IEnumerable Tokens) : TypeSyntax(Tokens);
-
-public record CStringTypeSyntax(IEnumerable Tokens) : TypeSyntax(Tokens);
-
-public record ArrayTypeSyntax(IEnumerable Tokens, TypeSyntax BaseType) : TypeSyntax(Tokens);
-
-public record CustomTypeSyntax(IEnumerable Tokens, string Module, string Name) : TypeSyntax(Tokens);
\ No newline at end of file
diff --git a/src/compiler/NubLang/Tokenization/Token.cs b/src/compiler/NubLang/Tokenization/Token.cs
deleted file mode 100644
index f300e04..0000000
--- a/src/compiler/NubLang/Tokenization/Token.cs
+++ /dev/null
@@ -1,81 +0,0 @@
-using NubLang.Code;
-
-namespace NubLang.Tokenization;
-
-public abstract class Token(SourceFileSpan fileSpan)
-{
- public SourceFileSpan FileSpan { get; } = fileSpan;
-}
-
-public class IdentifierToken(SourceFileSpan fileSpan, string value) : Token(fileSpan)
-{
- public string Value { get; } = value;
-}
-
-public class LiteralToken(SourceFileSpan fileSpan, LiteralKind kind, string value) : Token(fileSpan)
-{
- public LiteralKind Kind { get; } = kind;
- public string Value { get; } = value;
-}
-
-public enum LiteralKind
-{
- Integer,
- Float,
- String,
- Bool
-}
-
-public class SymbolToken(SourceFileSpan fileSpan, Symbol symbol) : Token(fileSpan)
-{
- public Symbol Symbol { get; } = symbol;
-}
-
-public enum Symbol
-{
- Func,
- Return,
- If,
- Else,
- While,
- Break,
- Continue,
- Colon,
- OpenParen,
- CloseParen,
- OpenBrace,
- CloseBrace,
- OpenBracket,
- CloseBracket,
- Comma,
- Period,
- Assign,
- Bang,
- Equal,
- NotEqual,
- LessThan,
- LessThanOrEqual,
- GreaterThan,
- GreaterThanOrEqual,
- Plus,
- Minus,
- Star,
- ForwardSlash,
- Struct,
- Caret,
- Ampersand,
- Let,
- Calls,
- Interface,
- For,
- Extern,
- Semi,
- Percent,
- LeftShift,
- RightShift,
- Pipe,
- And,
- Or,
- Module,
- Import,
-}
\ No newline at end of file
diff --git a/src/compiler/NubLang/Tokenization/Tokenizer.cs b/src/compiler/NubLang/Tokenization/Tokenizer.cs
deleted file mode 100644
index dda7393..0000000
--- a/src/compiler/NubLang/Tokenization/Tokenizer.cs
+++ /dev/null
@@ -1,264 +0,0 @@
-using NubLang.Code;
-using NubLang.Diagnostics;
-
-namespace NubLang.Tokenization;
-
-public sealed class Tokenizer
-{
- private static readonly Dictionary Keywords = new()
- {
- ["func"] = Symbol.Func,
- ["if"] = Symbol.If,
- ["else"] = Symbol.Else,
- ["while"] = Symbol.While,
- ["break"] = Symbol.Break,
- ["continue"] = Symbol.Continue,
- ["return"] = Symbol.Return,
- ["struct"] = Symbol.Struct,
- ["let"] = Symbol.Let,
- ["calls"] = Symbol.Calls,
- ["interface"] = Symbol.Interface,
- ["for"] = Symbol.For,
- ["extern"] = Symbol.Extern,
- ["module"] = Symbol.Module,
- };
-
- private static readonly Dictionary Symbols = new()
- {
- [['=', '=']] = Symbol.Equal,
- [['!', '=']] = Symbol.NotEqual,
- [['<', '=']] = Symbol.LessThanOrEqual,
- [['>', '=']] = Symbol.GreaterThanOrEqual,
- [['<', '<']] = Symbol.LeftShift,
- [['>', '>']] = Symbol.RightShift,
- [['&', '&']] = Symbol.And,
- [['|', '|']] = Symbol.Or,
- [[':']] = Symbol.Colon,
- [['(']] = Symbol.OpenParen,
- [[')']] = Symbol.CloseParen,
- [['{']] = Symbol.OpenBrace,
- [['}']] = Symbol.CloseBrace,
- [['[']] = Symbol.OpenBracket,
- [[']']] = Symbol.CloseBracket,
- [[',']] = Symbol.Comma,
- [['.']] = Symbol.Period,
- [['=']] = Symbol.Assign,
- [['<']] = Symbol.LessThan,
- [['>']] = Symbol.GreaterThan,
- [['+']] = Symbol.Plus,
- [['-']] = Symbol.Minus,
- [['*']] = Symbol.Star,
- [['/']] = Symbol.ForwardSlash,
- [['!']] = Symbol.Bang,
- [['^']] = Symbol.Caret,
- [['&']] = Symbol.Ampersand,
- [[';']] = Symbol.Semi,
- [['%']] = Symbol.Percent,
- [['|']] = Symbol.Pipe,
- };
-
- private static readonly (char[] Pattern, Symbol Symbol)[] OrderedSymbols = Symbols
- .OrderByDescending(kvp => kvp.Key.Length)
- .Select(kvp => (kvp.Key, kvp.Value))
- .ToArray();
-
- private readonly SourceFile _sourceFile;
- private readonly List _diagnostics = [];
- private int _index;
-
- public Tokenizer(SourceFile sourceFile)
- {
- _sourceFile = sourceFile;
- }
-
- public IReadOnlyList GetDiagnostics() => _diagnostics;
-
- public IEnumerable Tokenize()
- {
- _index = 0;
-
- while (Peek().TryGetValue(out var current))
- {
- if (char.IsWhiteSpace(current))
- {
- Next();
- continue;
- }
-
- if (current == '/' && Peek(1).TryGetValue(out var nextChar) && nextChar == '/')
- {
- while (Peek().TryGetValue(out var ch) && ch != '\n')
- {
- Next();
- }
-
- continue;
- }
-
- var tokenStartIndex = _index;
-
- if (char.IsLetter(current) || current == '_')
- {
- var buffer = string.Empty;
-
- while (Peek().TryGetValue(out var next) && (char.IsLetterOrDigit(next) || next == '_'))
- {
- buffer += next;
- Next();
- }
-
- if (Keywords.TryGetValue(buffer, out var keywordSymbol))
- {
- yield return new SymbolToken(GetSourceFileSpan(tokenStartIndex), keywordSymbol);
- continue;
- }
-
- if (buffer is "true" or "false")
- {
- yield return new LiteralToken(GetSourceFileSpan(tokenStartIndex), LiteralKind.Bool, buffer);
- continue;
- }
-
- yield return new IdentifierToken(GetSourceFileSpan(tokenStartIndex), buffer);
- continue;
- }
-
- if (char.IsDigit(current))
- {
- var isFloat = false;
- var buffer = string.Empty;
-
- while (Peek().TryGetValue(out var next))
- {
- if (next == '.')
- {
- if (isFloat)
- {
- throw new Exception("More than one period found in float literal");
- }
-
- isFloat = true;
- buffer += next;
- Next();
- }
- else if (char.IsDigit(next))
- {
- buffer += next;
- Next();
- }
- else
- {
- break;
- }
- }
-
- yield return new LiteralToken(GetSourceFileSpan(tokenStartIndex), isFloat ? LiteralKind.Float : LiteralKind.Integer, buffer);
- continue;
- }
-
- if (current == '"')
- {
- Next();
- var buffer = string.Empty;
-
- while (true)
- {
- if (!Peek().TryGetValue(out var next))
- {
- throw new Exception("Unclosed string literal");
- }
-
- if (next == '"')
- {
- Next();
- break;
- }
-
- buffer += next;
- Next();
- }
-
- yield return new LiteralToken(GetSourceFileSpan(tokenStartIndex), LiteralKind.String, buffer);
- continue;
- }
-
- var foundMatch = false;
- foreach (var (pattern, symbol) in OrderedSymbols)
- {
- for (var i = 0; i < pattern.Length; i++)
- {
- var c = Peek(i);
- if (!c.HasValue || c.Value != pattern[i]) break;
-
- if (i == pattern.Length - 1)
- {
- for (var j = 0; j <= i; j++)
- {
- Next();
- }
-
- yield return new SymbolToken(GetSourceFileSpan(tokenStartIndex), symbol);
- foundMatch = true;
- break;
- }
- }
-
- if (foundMatch)
- {
- break;
- }
- }
-
- if (foundMatch)
- {
- continue;
- }
-
- _diagnostics.Add(Diagnostic.Error($"Unknown token '{current}'").At(GetSourceFileSpan(tokenStartIndex)).Build());
- Next();
- }
- }
-
- private Optional Peek(int offset = 0)
- {
- if (_index + offset < _sourceFile.GetText().Length)
- {
- return _sourceFile.GetText()[_index + offset];
- }
-
- return Optional.Empty();
- }
-
- private void Next()
- {
- _index++;
- }
-
- private SourceFileSpan GetSourceFileSpan(int tokenStartIndex)
- {
- var start = CalculateSourceLocation(tokenStartIndex);
- var end = CalculateSourceLocation(_index);
- return new SourceFileSpan(_sourceFile, new SourceSpan(start, end));
- }
-
- private SourceLocation CalculateSourceLocation(int index)
- {
- var line = 1;
- var column = 1;
-
- for (var i = 0; i < index && i < _sourceFile.GetText().Length; i++)
- {
- if (_sourceFile.GetText()[i] == '\n')
- {
- line++;
- column = 1;
- }
- else
- {
- column++;
- }
- }
-
- return new SourceLocation(line, column);
- }
-}
\ No newline at end of file
diff --git a/src/compiler/NubLang/TypeChecking/Module.cs b/src/compiler/NubLang/TypeChecking/Module.cs
deleted file mode 100644
index e522ca7..0000000
--- a/src/compiler/NubLang/TypeChecking/Module.cs
+++ /dev/null
@@ -1,179 +0,0 @@
-using NubLang.Parsing.Syntax;
-using NubLang.TypeChecking.Node;
-
-namespace NubLang.TypeChecking;
-
-public class Module
-{
- public static IReadOnlyList CollectFromSyntaxTrees(IReadOnlyList syntaxTrees)
- {
- var modules = new Dictionary();
-
- foreach (var syntaxTree in syntaxTrees)
- {
- var name = syntaxTree.Metadata.ModuleName;
- if (name == null)
- {
- continue;
- }
-
- if (!modules.TryGetValue(name, out var module))
- {
- module = new Module(name, syntaxTree.Metadata.Imports);
- modules[name] = module;
- }
-
- foreach (var definition in syntaxTree.Definitions)
- {
- module.AddDefinition(definition);
- }
- }
-
- return modules.Values.ToList();
- }
-
- private readonly List _definitions = [];
-
- public Module(string name, IReadOnlyList imports)
- {
- Name = name;
- Imports = imports;
- }
-
- public string Name { get; }
- public IReadOnlyList Imports { get; }
-
- public IReadOnlyList Definitions => _definitions;
-
- private void AddDefinition(DefinitionSyntax syntax)
- {
- _definitions.Add(syntax);
- }
-}
-
-public class TypedModule
-{
- public TypedModule(string name, IReadOnlyList definitions)
- {
- Name = name;
- Definitions = definitions;
- }
-
- public string Name { get; }
- public IReadOnlyList Definitions { get; }
-}
-
-public class ModuleSignature
-{
- public static IReadOnlyDictionary CollectFromSyntaxTrees(IReadOnlyList syntaxTrees)
- {
- var modules = new Dictionary();
-
- foreach (var syntaxTree in syntaxTrees)
- {
- var moduleName = syntaxTree.Metadata.ModuleName;
- if (moduleName == null)
- {
- continue;
- }
-
- if (!modules.TryGetValue(moduleName, out var module))
- {
- module = new ModuleSignature();
- modules[moduleName] = module;
- }
-
- foreach (var def in syntaxTree.Definitions)
- {
- if (def.Exported)
- {
- switch (def)
- {
- case ExternFuncSyntax externFuncDef:
- {
- var parameters = externFuncDef.Signature.Parameters.Select(p => TypeResolver.ResolveType(p.Type, modules)).ToList();
- var returnType = TypeResolver.ResolveType(externFuncDef.Signature.ReturnType, modules);
- var type = new FuncTypeNode(parameters, returnType);
- module._functions.Add(externFuncDef.Name, type);
- break;
- }
- case FuncSyntax funcDef:
- {
- var parameters = funcDef.Signature.Parameters.Select(p => TypeResolver.ResolveType(p.Type, modules)).ToList();
- var returnType = TypeResolver.ResolveType(funcDef.Signature.ReturnType, modules);
- var type = new FuncTypeNode(parameters, returnType);
- module._functions.Add(funcDef.Name, type);
- break;
- }
- case InterfaceSyntax interfaceDef:
- {
- var functions = new List();
- for (var i = 0; i < interfaceDef.Functions.Count; i++)
- {
- var function = interfaceDef.Functions[i];
- var parameters = function.Signature.Parameters.Select(p => TypeResolver.ResolveType(p.Type, modules)).ToList();
- var returnType = TypeResolver.ResolveType(function.Signature.ReturnType, modules);
- functions.Add(new InterfaceTypeFunc(function.Name, new FuncTypeNode(parameters, returnType), i));
- }
-
- var type = new InterfaceTypeNode(moduleName, interfaceDef.Name, functions);
- module._interfaces.Add(type);
- break;
- }
- case StructSyntax structDef:
- {
- var fields = new List();
- foreach (var field in structDef.Fields)
- {
- fields.Add(new StructTypeField(field.Name, TypeResolver.ResolveType(field.Type, modules), field.Index, field.Value.HasValue));
- }
-
- var functions = new List();
- foreach (var function in structDef.Functions)
- {
- var parameters = function.Signature.Parameters.Select(p => TypeResolver.ResolveType(p.Type, modules)).ToList();
- var returnType = TypeResolver.ResolveType(function.Signature.ReturnType, modules);
- functions.Add(new StructTypeFunc(function.Name, new FuncTypeNode(parameters, returnType)));
- }
-
- var interfaceImplementations = new List();
- foreach (var interfaceImplementation in structDef.InterfaceImplementations)
- {
- if (interfaceImplementation is not CustomTypeSyntax customType)
- {
- throw new Exception("Interface implementation is not a custom type");
- }
-
- var resolvedType = TypeResolver.ResolveCustomType(customType.Module, customType.Name, modules);
- if (resolvedType is not InterfaceTypeNode interfaceType)
- {
- throw new Exception("Interface implementation is not a interface");
- }
-
- interfaceImplementations.Add(interfaceType);
- }
-
- var type = new StructTypeNode(moduleName, structDef.Name, fields, functions, interfaceImplementations);
- module._structs.Add(type);
- break;
- }
- default:
- {
- throw new ArgumentOutOfRangeException(nameof(def));
- }
- }
- }
- }
- }
-
- return modules;
- }
-
- private readonly List _structs = [];
- private readonly List _interfaces = [];
- private readonly Dictionary _functions = [];
-
- public IReadOnlyList StructTypes => _structs;
- public IReadOnlyList InterfaceTypes => _interfaces;
- public IReadOnlyDictionary Functions => _functions;
-}
\ No newline at end of file
diff --git a/src/compiler/NubLang/TypeChecking/Node/DefinitionNode.cs b/src/compiler/NubLang/TypeChecking/Node/DefinitionNode.cs
deleted file mode 100644
index 3a42cd3..0000000
--- a/src/compiler/NubLang/TypeChecking/Node/DefinitionNode.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-namespace NubLang.TypeChecking.Node;
-
-public abstract record DefinitionNode : Node;
-
-public record FuncParameterNode(string Name, TypeNode Type) : Node;
-
-public record FuncSignatureNode(IReadOnlyList Parameters, TypeNode ReturnType) : Node;
-
-public record LocalFuncNode(string Name, FuncSignatureNode Signature, BlockNode Body) : DefinitionNode;
-
-public record ExternFuncNode(string Name, string CallName, FuncSignatureNode Signature) : DefinitionNode;
-
-public record StructFieldNode(int Index, string Name, TypeNode Type, Optional Value) : Node;
-
-public record StructFuncNode(string Name, FuncSignatureNode Signature, BlockNode Body) : Node;
-
-public record StructNode(string Name, IReadOnlyList Fields, IReadOnlyList Functions, IReadOnlyList InterfaceImplementations) : DefinitionNode;
-
-public record InterfaceFuncNode(string Name, FuncSignatureNode Signature) : Node;
-
-public record InterfaceNode(string Name, IReadOnlyList Functions) : DefinitionNode;
\ No newline at end of file
diff --git a/src/compiler/NubLang/TypeChecking/Node/ExpressionNode.cs b/src/compiler/NubLang/TypeChecking/Node/ExpressionNode.cs
deleted file mode 100644
index df480cd..0000000
--- a/src/compiler/NubLang/TypeChecking/Node/ExpressionNode.cs
+++ /dev/null
@@ -1,72 +0,0 @@
-using NubLang.Tokenization;
-
-namespace NubLang.TypeChecking.Node;
-
-public enum UnaryOperator
-{
- Negate,
- Invert
-}
-
-public enum BinaryOperator
-{
- Equal,
- NotEqual,
- GreaterThan,
- GreaterThanOrEqual,
- LessThan,
- LessThanOrEqual,
- LogicalAnd,
- LogicalOr,
- Plus,
- Minus,
- Multiply,
- Divide,
- Modulo,
- LeftShift,
- RightShift,
- BitwiseAnd,
- BitwiseXor,
- BitwiseOr
-}
-
-public abstract record ExpressionNode(TypeNode Type) : Node;
-
-public abstract record LValueExpressionNode(TypeNode Type) : RValueExpressionNode(Type);
-public abstract record RValueExpressionNode(TypeNode Type) : ExpressionNode(Type);
-
-public record BinaryExpressionNode(TypeNode Type, ExpressionNode Left, BinaryOperator Operator, ExpressionNode Right) : RValueExpressionNode(Type);
-
-public record UnaryExpressionNode(TypeNode Type, UnaryOperator Operator, ExpressionNode Operand) : RValueExpressionNode(Type);
-
-public record FuncCallNode(TypeNode Type, ExpressionNode Expression, IReadOnlyList Parameters) : RValueExpressionNode(Type);
-
-public record StructFuncCallNode(TypeNode Type, string Name, StructTypeNode StructType, ExpressionNode StructExpression, IReadOnlyList Parameters) : RValueExpressionNode(Type);
-
-public record InterfaceFuncCallNode(TypeNode Type, string Name, InterfaceTypeNode InterfaceType, ExpressionNode InterfaceExpression, IReadOnlyList Parameters) : RValueExpressionNode(Type);
-
-public record VariableIdentifierNode(TypeNode Type, string Name) : LValueExpressionNode(Type);
-
-public record FuncParameterIdentifierNode(TypeNode Type, string Name) : RValueExpressionNode(Type);
-
-public record FuncIdentifierNode(TypeNode Type, string Module, string Name) : RValueExpressionNode(Type);
-
-public record ArrayInitializerNode(TypeNode Type, ExpressionNode Capacity, TypeNode ElementType) : RValueExpressionNode(Type);
-
-public record ArrayIndexAccessNode(TypeNode Type, ExpressionNode Target, ExpressionNode Index) : LValueExpressionNode(Type);
-
-public record AddressOfNode(TypeNode Type, LValueExpressionNode LValue) : RValueExpressionNode(Type);
-
-public record LiteralNode(TypeNode Type, string Value, LiteralKind Kind) : RValueExpressionNode(Type);
-
-public record StructFieldAccessNode(TypeNode Type, StructTypeNode StructType, ExpressionNode Target, string Field) : LValueExpressionNode(Type);
-
-public record StructInitializerNode(StructTypeNode StructType, Dictionary Initializers) : RValueExpressionNode(StructType);
-
-public record DereferenceNode(TypeNode Type, ExpressionNode Expression) : RValueExpressionNode(Type);
-
-public record ConvertToInterfaceNode(TypeNode Type, InterfaceTypeNode InterfaceType, StructTypeNode StructType, ExpressionNode Implementation) : RValueExpressionNode(Type);
-
-public record ConvertIntNode(TypeNode Type, ExpressionNode Value, IntTypeNode ValueType, IntTypeNode TargetType) : RValueExpressionNode(Type);
-
-public record ConvertFloatNode(TypeNode Type, ExpressionNode Value, FloatTypeNode ValueType, FloatTypeNode TargetType) : RValueExpressionNode(Type);
diff --git a/src/compiler/NubLang/TypeChecking/Node/Node.cs b/src/compiler/NubLang/TypeChecking/Node/Node.cs
deleted file mode 100644
index 4b75960..0000000
--- a/src/compiler/NubLang/TypeChecking/Node/Node.cs
+++ /dev/null
@@ -1,5 +0,0 @@
-namespace NubLang.TypeChecking.Node;
-
-public abstract record Node;
-
-public record BlockNode(IReadOnlyList Statements) : Node;
\ No newline at end of file
diff --git a/src/compiler/NubLang/TypeChecking/Node/StatementNode.cs b/src/compiler/NubLang/TypeChecking/Node/StatementNode.cs
deleted file mode 100644
index bd58462..0000000
--- a/src/compiler/NubLang/TypeChecking/Node/StatementNode.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-namespace NubLang.TypeChecking.Node;
-
-public record StatementNode : Node;
-
-public record StatementExpressionNode(ExpressionNode Expression) : StatementNode;
-
-public record ReturnNode(Optional Value) : StatementNode;
-
-public record AssignmentNode(LValueExpressionNode Target, ExpressionNode Value) : StatementNode;
-
-public record IfNode(ExpressionNode Condition, BlockNode Body, Optional> Else) : StatementNode;
-
-public record VariableDeclarationNode(string Name, Optional Assignment, TypeNode Type) : StatementNode;
-
-public record ContinueNode : StatementNode;
-
-public record BreakNode : StatementNode;
-
-public record WhileNode(ExpressionNode Condition, BlockNode Body) : StatementNode;
\ No newline at end of file
diff --git a/src/compiler/NubLang/TypeChecking/Node/TypeNode.cs b/src/compiler/NubLang/TypeChecking/Node/TypeNode.cs
deleted file mode 100644
index 55d29aa..0000000
--- a/src/compiler/NubLang/TypeChecking/Node/TypeNode.cs
+++ /dev/null
@@ -1,232 +0,0 @@
-using System.Diagnostics.CodeAnalysis;
-
-namespace NubLang.TypeChecking.Node;
-
-public abstract class TypeNode : IEquatable
-{
- public bool IsSimpleType([NotNullWhen(true)] out SimpleTypeNode? simpleType, [NotNullWhen(false)] out ComplexTypeNode? complexType)
- {
- if (this is SimpleTypeNode st)
- {
- complexType = null;
- simpleType = st;
- return true;
- }
-
- if (this is ComplexTypeNode ct)
- {
- complexType = ct;
- simpleType = null;
- return false;
- }
-
- throw new ArgumentException($"Type {this} is not a simple type nor a complex type");
- }
-
- public override bool Equals(object? obj) => obj is TypeNode other && Equals(other);
-
- public abstract bool Equals(TypeNode? other);
- public abstract override int GetHashCode();
- public abstract override string ToString();
-
- public static bool operator ==(TypeNode? left, TypeNode? right) => Equals(left, right);
- public static bool operator !=(TypeNode? left, TypeNode? right) => !Equals(left, right);
-}
-
-public enum StorageSize
-{
- Void,
- I8,
- I16,
- I32,
- I64,
- U8,
- U16,
- U32,
- U64,
- F32,
- F64
-}
-
-public abstract class SimpleTypeNode : TypeNode
-{
- public abstract StorageSize StorageSize { get; }
-}
-
-#region Simple types
-
-public class IntTypeNode(bool signed, int width) : SimpleTypeNode
-{
- public bool Signed { get; } = signed;
- public int Width { get; } = width;
-
- public override StorageSize StorageSize => Signed switch
- {
- true => Width switch
- {
- 8 => StorageSize.I8,
- 16 => StorageSize.I16,
- 32 => StorageSize.I32,
- 64 => StorageSize.I64,
- _ => throw new ArgumentOutOfRangeException(nameof(Width))
- },
- false => Width switch
- {
- 8 => StorageSize.U8,
- 16 => StorageSize.U16,
- 32 => StorageSize.U32,
- 64 => StorageSize.U64,
- _ => throw new ArgumentOutOfRangeException(nameof(Width))
- }
- };
-
- public override string ToString() => $"{(Signed ? "i" : "u")}{Width}";
- public override bool Equals(TypeNode? other) => other is IntTypeNode @int && @int.Width == Width && @int.Signed == Signed;
- public override int GetHashCode() => HashCode.Combine(typeof(IntTypeNode), Signed, Width);
-}
-
-public class FloatTypeNode(int width) : SimpleTypeNode
-{
- public int Width { get; } = width;
-
- public override StorageSize StorageSize => Width switch
- {
- 32 => StorageSize.F32,
- 64 => StorageSize.F64,
- _ => throw new ArgumentOutOfRangeException(nameof(Width))
- };
-
- public override string ToString() => $"f{Width}";
- public override bool Equals(TypeNode? other) => other is FloatTypeNode @int && @int.Width == Width;
- public override int GetHashCode() => HashCode.Combine(typeof(FloatTypeNode), Width);
-}
-
-public class BoolTypeNode : SimpleTypeNode
-{
- public override StorageSize StorageSize => StorageSize.U8;
-
- public override string ToString() => "bool";
- public override bool Equals(TypeNode? other) => other is BoolTypeNode;
- public override int GetHashCode() => HashCode.Combine(typeof(BoolTypeNode));
-}
-
-public class FuncTypeNode(IReadOnlyList parameters, TypeNode returnType) : SimpleTypeNode
-{
- public IReadOnlyList Parameters { get; } = parameters;
- public TypeNode ReturnType { get; } = returnType;
-
- public override StorageSize StorageSize => StorageSize.U64;
-
- public override string ToString() => $"func({string.Join(", ", Parameters)}): {ReturnType}";
- public override bool Equals(TypeNode? other) => other is FuncTypeNode func && ReturnType.Equals(func.ReturnType) && Parameters.SequenceEqual(func.Parameters);
-
- public override int GetHashCode()
- {
- var hash = new HashCode();
- hash.Add(typeof(FuncTypeNode));
- hash.Add(ReturnType);
- foreach (var param in Parameters)
- {
- hash.Add(param);
- }
-
- return hash.ToHashCode();
- }
-}
-
-public class PointerTypeNode(TypeNode baseType) : SimpleTypeNode
-{
- public TypeNode BaseType { get; } = baseType;
-
- public override StorageSize StorageSize => StorageSize.U64;
-
- public override string ToString() => "^" + BaseType;
- public override bool Equals(TypeNode? other) => other is PointerTypeNode pointer && BaseType.Equals(pointer.BaseType);
- public override int GetHashCode() => HashCode.Combine(typeof(PointerTypeNode), BaseType);
-}
-
-public class VoidTypeNode : SimpleTypeNode
-{
- public override StorageSize StorageSize => StorageSize.Void;
-
- public override string ToString() => "void";
- public override bool Equals(TypeNode? other) => other is VoidTypeNode;
- public override int GetHashCode() => HashCode.Combine(typeof(VoidTypeNode));
-}
-
-#endregion
-
-public abstract class ComplexTypeNode : TypeNode;
-
-#region Complex types
-
-public class CStringTypeNode : ComplexTypeNode
-{
- public override string ToString() => "cstring";
- public override bool Equals(TypeNode? other) => other is CStringTypeNode;
- public override int GetHashCode() => HashCode.Combine(typeof(CStringTypeNode));
-}
-
-public class StringTypeNode : ComplexTypeNode
-{
- public override string ToString() => "string";
- public override bool Equals(TypeNode? other) => other is StringTypeNode;
- public override int GetHashCode() => HashCode.Combine(typeof(StringTypeNode));
-}
-
-public class StructTypeField(string name, TypeNode type, int index, bool hasDefaultValue)
-{
- public string Name { get; } = name;
- public TypeNode Type { get; } = type;
- public int Index { get; } = index;
- public bool HasDefaultValue { get; } = hasDefaultValue;
-}
-
-public class StructTypeFunc(string name, FuncTypeNode type)
-{
- public string Name { get; } = name;
- public FuncTypeNode Type { get; } = type;
-}
-
-public class StructTypeNode(string module, string name, IReadOnlyList fields, IReadOnlyList functions, IReadOnlyList interfaceImplementations) : ComplexTypeNode
-{
- public string Module { get; } = module;
- public string Name { get; } = name;
- public IReadOnlyList Fields { get; set; } = fields;
- public IReadOnlyList Functions { get; set; } = functions;
- public IReadOnlyList InterfaceImplementations { get; set; } = interfaceImplementations;
-
- public override string ToString() => Name;
- public override bool Equals(TypeNode? other) => other is StructTypeNode structType && Name == structType.Name && Module == structType.Module;
- public override int GetHashCode() => HashCode.Combine(typeof(StructTypeNode), Name);
-}
-
-public class InterfaceTypeFunc(string name, FuncTypeNode type, int index)
-{
- public string Name { get; } = name;
- public FuncTypeNode Type { get; } = type;
- public int Index { get; } = index;
-}
-
-public class InterfaceTypeNode(string module, string name, IReadOnlyList functions) : ComplexTypeNode
-{
- public string Module { get; } = module;
- public string Name { get; } = name;
- public IReadOnlyList Functions { get; set; } = functions;
-
- public override string ToString() => Name;
- public override bool Equals(TypeNode? other) => other is InterfaceTypeNode interfaceType && Name == interfaceType.Name && Module == interfaceType.Module;
- public override int GetHashCode() => HashCode.Combine(typeof(InterfaceTypeNode), Name);
-}
-
-public class ArrayTypeNode(TypeNode elementType) : ComplexTypeNode
-{
- public TypeNode ElementType { get; } = elementType;
-
- public override string ToString() => "[]" + ElementType;
-
- public override bool Equals(TypeNode? other) => other is ArrayTypeNode array && ElementType.Equals(array.ElementType);
- public override int GetHashCode() => HashCode.Combine(typeof(ArrayTypeNode), ElementType);
-}
-
-#endregion
\ No newline at end of file
diff --git a/src/compiler/NubLang/TypeChecking/TypeChecker.cs b/src/compiler/NubLang/TypeChecking/TypeChecker.cs
deleted file mode 100644
index d636b43..0000000
--- a/src/compiler/NubLang/TypeChecking/TypeChecker.cs
+++ /dev/null
@@ -1,457 +0,0 @@
-using NubLang.Diagnostics;
-using NubLang.Parsing.Syntax;
-using NubLang.Tokenization;
-using NubLang.TypeChecking.Node;
-
-namespace NubLang.TypeChecking;
-
-public sealed class TypeChecker
-{
- private readonly Module _currentModule;
- private readonly IReadOnlyDictionary _moduleSignatures;
-
- private readonly Stack _scopes = [];
- private readonly Stack _funcReturnTypes = [];
- private readonly List _diagnostics = [];
-
- private Scope Scope => _scopes.Peek();
-
- public TypeChecker(Module currentModule, IReadOnlyDictionary moduleSignatures)
- {
- _currentModule = currentModule;
- _moduleSignatures = moduleSignatures.Where(x => currentModule.Imports.Contains(x.Key) || _currentModule.Name == x.Key).ToDictionary();
- }
-
- public IReadOnlyList GetDiagnostics() => _diagnostics;
-
- public TypedModule CheckModule()
- {
- _diagnostics.Clear();
- _scopes.Clear();
-
- var definitions = new List();
-
- foreach (var definition in _currentModule.Definitions)
- {
- try
- {
- definitions.Add(CheckDefinition(definition));
- }
- catch (TypeCheckerException e)
- {
- _diagnostics.Add(e.Diagnostic);
- }
- }
-
- return new TypedModule(_currentModule.Name, definitions);
- }
-
- private DefinitionNode CheckDefinition(DefinitionSyntax node)
- {
- return node switch
- {
- ExternFuncSyntax definition => CheckExternFuncDefinition(definition),
- InterfaceSyntax definition => CheckInterfaceDefinition(definition),
- FuncSyntax definition => CheckLocalFuncDefinition(definition),
- StructSyntax definition => CheckStructDefinition(definition),
- _ => throw new ArgumentOutOfRangeException(nameof(node))
- };
- }
-
- private InterfaceNode CheckInterfaceDefinition(InterfaceSyntax node)
- {
- throw new NotImplementedException();
- }
-
- private StructNode CheckStructDefinition(StructSyntax node)
- {
- var fields = new List();
- foreach (var field in node.Fields)
- {
- var value = Optional.Empty();
- if (field.Value.HasValue)
- {
- value = CheckExpression(field.Value.Value);
- }
-
- fields.Add(new StructFieldNode(field.Index, field.Name, ResolveType(field.Type), value));
- }
-
- var functions = new List();
- foreach (var function in node.Functions)
- {
- var scope = new Scope();
- // todo(nub31): Add this parameter
- foreach (var parameter in function.Signature.Parameters)
- {
- scope.Declare(new Identifier(parameter.Name, ResolveType(parameter.Type), IdentifierKind.FunctionParameter));
- }
-
- _funcReturnTypes.Push(ResolveType(function.Signature.ReturnType));
- var body = CheckBlock(function.Body, scope);
- _funcReturnTypes.Pop();
- functions.Add(new StructFuncNode(function.Name, CheckFuncSignature(function.Signature), body));
- }
-
- var interfaceImplementations = new List();
- foreach (var interfaceImplementation in node.InterfaceImplementations)
- {
- var type = ResolveType(interfaceImplementation);
- if (type is not InterfaceTypeNode interfaceType)
- {
- _diagnostics.Add(Diagnostic.Error($"Struct {node.Name} cannot implement non-struct type {interfaceImplementation}").At(interfaceImplementation).Build());
- continue;
- }
-
- interfaceImplementations.Add(interfaceType);
- }
-
- return new StructNode(node.Name, fields, functions, interfaceImplementations);
- }
-
- private ExternFuncNode CheckExternFuncDefinition(ExternFuncSyntax node)
- {
- return new ExternFuncNode(node.Name, node.CallName, CheckFuncSignature(node.Signature));
- }
-
- private LocalFuncNode CheckLocalFuncDefinition(FuncSyntax node)
- {
- var scope = new Scope();
- foreach (var parameter in node.Signature.Parameters)
- {
- scope.Declare(new Identifier(parameter.Name, ResolveType(parameter.Type), IdentifierKind.FunctionParameter));
- }
-
- _funcReturnTypes.Push(ResolveType(node.Signature.ReturnType));
- var body = CheckBlock(node.Body, scope);
- _funcReturnTypes.Pop();
- return new LocalFuncNode(node.Name, CheckFuncSignature(node.Signature), body);
- }
-
- private StatementNode CheckStatement(StatementSyntax node)
- {
- return node switch
- {
- AssignmentSyntax statement => CheckAssignment(statement),
- BreakSyntax => new BreakNode(),
- ContinueSyntax => new ContinueNode(),
- IfSyntax statement => CheckIf(statement),
- ReturnSyntax statement => CheckReturn(statement),
- StatementExpressionSyntax statement => CheckStatementExpression(statement),
- VariableDeclarationSyntax statement => CheckVariableDeclaration(statement),
- WhileSyntax statement => CheckWhile(statement),
- _ => throw new ArgumentOutOfRangeException(nameof(node))
- };
- }
-
- private StatementNode CheckAssignment(AssignmentSyntax statement)
- {
- throw new NotImplementedException();
- }
-
- private IfNode CheckIf(IfSyntax statement)
- {
- throw new NotImplementedException();
- }
-
- private ReturnNode CheckReturn(ReturnSyntax statement)
- {
- var value = Optional.Empty();
-
- if (statement.Value.HasValue)
- {
- value = CheckExpression(statement.Value.Value, _funcReturnTypes.Peek());
- }
-
- return new ReturnNode(value);
- }
-
- private StatementExpressionNode CheckStatementExpression(StatementExpressionSyntax statement)
- {
- return new StatementExpressionNode(CheckExpression(statement.Expression));
- }
-
- private VariableDeclarationNode CheckVariableDeclaration(VariableDeclarationSyntax statement)
- {
- TypeNode? type = null;
- ExpressionNode? assignmentNode = null;
-
- if (statement.ExplicitType.TryGetValue(out var explicitType))
- {
- type = ResolveType(explicitType);
- }
-
- if (statement.Assignment.TryGetValue(out var assignment))
- {
- assignmentNode = CheckExpression(assignment, type);
- type ??= assignmentNode.Type;
- }
-
- if (type == null)
- {
- throw new TypeCheckerException(Diagnostic.Error($"Cannot infer type of variable {statement.Name}").At(statement).Build());
- }
-
- Scope.Declare(new Identifier(statement.Name, type, IdentifierKind.Variable));
-
- return new VariableDeclarationNode(statement.Name, Optional.OfNullable(assignmentNode), type);
- }
-
- private WhileNode CheckWhile(WhileSyntax statement)
- {
- throw new NotImplementedException();
- }
-
- private FuncSignatureNode CheckFuncSignature(FuncSignatureSyntax statement)
- {
- var parameters = new List();
- foreach (var parameter in statement.Parameters)
- {
- parameters.Add(new FuncParameterNode(parameter.Name, ResolveType(parameter.Type)));
- }
-
- return new FuncSignatureNode(parameters, ResolveType(statement.ReturnType));
- }
-
- private ExpressionNode CheckExpression(ExpressionSyntax node, TypeNode? expectedType = null)
- {
- var result = node switch
- {
- AddressOfSyntax expression => CheckAddressOf(expression),
- ArrayIndexAccessSyntax expression => CheckArrayIndexAccess(expression),
- ArrayInitializerSyntax expression => CheckArrayInitializer(expression),
- BinaryExpressionSyntax expression => CheckBinaryExpression(expression),
- DereferenceSyntax expression => CheckDereference(expression),
- DotFuncCallSyntax expression => CheckDotFuncCall(expression),
- FuncCallSyntax expression => CheckFuncCall(expression),
- IdentifierSyntax expression => CheckIdentifier(expression),
- LiteralSyntax expression => CheckLiteral(expression, expectedType),
- StructFieldAccessSyntax expression => CheckStructFieldAccess(expression),
- StructInitializerSyntax expression => CheckStructInitializer(expression, expectedType),
- UnaryExpressionSyntax expression => CheckUnaryExpression(expression),
- _ => throw new ArgumentOutOfRangeException(nameof(node))
- };
-
- if (expectedType == null || result.Type == expectedType)
- {
- return result;
- }
-
- if (result.Type is StructTypeNode structType && expectedType is InterfaceTypeNode interfaceType)
- {
- return new ConvertToInterfaceNode(interfaceType, interfaceType, structType, result);
- }
-
- if (result.Type is IntTypeNode sourceIntType && expectedType is IntTypeNode targetIntType)
- {
- if (sourceIntType.Signed == targetIntType.Signed && sourceIntType.Width < targetIntType.Width)
- {
- return new ConvertIntNode(targetIntType, result, sourceIntType, targetIntType);
- }
- }
-
- if (result.Type is FloatTypeNode sourceFloatType && expectedType is FloatTypeNode targetFloatType)
- {
- if (sourceFloatType.Width < targetFloatType.Width)
- {
- return new ConvertFloatNode(targetFloatType, result, sourceFloatType, targetFloatType);
- }
- }
-
- throw new TypeCheckerException(Diagnostic.Error($"Cannot convert {result.Type} to {expectedType}").At(node).Build());
- }
-
- private AddressOfNode CheckAddressOf(AddressOfSyntax expression)
- {
- throw new NotImplementedException();
- }
-
- private ArrayIndexAccessNode CheckArrayIndexAccess(ArrayIndexAccessSyntax expression)
- {
- throw new NotImplementedException();
- }
-
- private ArrayInitializerNode CheckArrayInitializer(ArrayInitializerSyntax expression)
- {
- throw new NotImplementedException();
- }
-
- private BinaryExpressionNode CheckBinaryExpression(BinaryExpressionSyntax expression)
- {
- throw new NotImplementedException();
- }
-
- private DereferenceNode CheckDereference(DereferenceSyntax expression)
- {
- throw new NotImplementedException();
- }
-
- private FuncCallNode CheckFuncCall(FuncCallSyntax expression)
- {
- var accessor = CheckExpression(expression.Expression);
- if (accessor.Type is not FuncTypeNode funcType)
- {
- throw new TypeCheckerException(Diagnostic.Error($"Cannot call non-function type {accessor.Type}").At(expression.Expression).Build());
- }
-
- if (expression.Parameters.Count != funcType.Parameters.Count)
- {
- throw new TypeCheckerException(Diagnostic.Error($"Function {funcType} expects {funcType.Parameters} but got {expression.Parameters.Count} parameters").At(expression.Expression).Build());
- }
-
- var parameters = new List();
- for (var i = 0; i < expression.Parameters.Count; i++)
- {
- var parameter = expression.Parameters[i];
- var expectedType = funcType.Parameters[i];
-
- var parameterExpression = CheckExpression(parameter, expectedType);
- if (parameterExpression.Type != expectedType)
- {
- throw new Exception($"Parameter {i + 1} does not match the type {expectedType} for function {funcType}");
- }
-
- parameters.Add(parameterExpression);
- }
-
- return new FuncCallNode(funcType.ReturnType, accessor, parameters);
- }
-
- private ExpressionNode CheckDotFuncCall(DotFuncCallSyntax expression)
- {
- throw new NotImplementedException();
- }
-
- private ExpressionNode CheckIdentifier(IdentifierSyntax expression)
- {
- // If the identifier does not have a module specified, first check if a local variable or function parameter with that identifier exists
- if (!expression.Module.TryGetValue(out var moduleName))
- {
- var scopeIdent = Scope.Lookup(expression.Name);
- if (scopeIdent != null)
- {
- switch (scopeIdent.Kind)
- {
- case IdentifierKind.Variable:
- {
- return new VariableIdentifierNode(scopeIdent.Type, expression.Name);
- }
- case IdentifierKind.FunctionParameter:
- {
- return new FuncParameterIdentifierNode(scopeIdent.Type, expression.Name);
- }
- default:
- {
- throw new ArgumentOutOfRangeException();
- }
- }
- }
- }
-
- moduleName ??= _currentModule.Name;
- if (_moduleSignatures.TryGetValue(moduleName, out var module))
- {
- if (module.Functions.TryGetValue(expression.Name, out var function))
- {
- return new FuncIdentifierNode(function, moduleName, expression.Name);
- }
- }
-
- throw new TypeCheckerException(Diagnostic.Error($"Identifier {expression.Name} not found").At(expression).Build());
- }
-
- private LiteralNode CheckLiteral(LiteralSyntax expression, TypeNode? expectedType)
- {
- // todo(nub31): Check if the types can actually be represented as another one. For example, an int should be passed when a string is expected
- var type = expectedType ?? expression.Kind switch
- {
- LiteralKind.Integer => new IntTypeNode(true, 64),
- LiteralKind.Float => new FloatTypeNode(64),
- LiteralKind.String => new StringTypeNode(),
- LiteralKind.Bool => new BoolTypeNode(),
- _ => throw new ArgumentOutOfRangeException()
- };
-
- return new LiteralNode(type, expression.Value, expression.Kind);
- }
-
- private StructFieldAccessNode CheckStructFieldAccess(StructFieldAccessSyntax expression)
- {
- throw new NotImplementedException();
- }
-
- private StructInitializerNode CheckStructInitializer(StructInitializerSyntax expression, TypeNode? expectedType)
- {
- throw new NotImplementedException();
- }
-
- private UnaryExpressionNode CheckUnaryExpression(UnaryExpressionSyntax expression)
- {
- throw new NotImplementedException();
- }
-
- private BlockNode CheckBlock(BlockSyntax node, Scope? scope = null)
- {
- var statements = new List();
-
- _scopes.Push(scope ?? Scope.SubScope());
-
- foreach (var statement in node.Statements)
- {
- statements.Add(CheckStatement(statement));
- }
-
- _scopes.Pop();
-
- return new BlockNode(statements);
- }
-
- private TypeNode ResolveType(TypeSyntax fieldType)
- {
- return TypeResolver.ResolveType(fieldType, _moduleSignatures);
- }
-}
-
-public enum IdentifierKind
-{
- Variable,
- FunctionParameter
-}
-
-public record Identifier(string Name, TypeNode Type, IdentifierKind Kind);
-
-public class Scope(Scope? parent = null)
-{
- private readonly List _variables = [];
-
- public Identifier? Lookup(string name)
- {
- var variable = _variables.FirstOrDefault(x => x.Name == name);
- if (variable != null)
- {
- return variable;
- }
-
- return parent?.Lookup(name);
- }
-
- public void Declare(Identifier identifier)
- {
- _variables.Add(identifier);
- }
-
- public Scope SubScope()
- {
- return new Scope(this);
- }
-}
-
-public class TypeCheckerException : Exception
-{
- public Diagnostic Diagnostic { get; }
-
- public TypeCheckerException(Diagnostic diagnostic) : base(diagnostic.Message)
- {
- Diagnostic = diagnostic;
- }
-}
\ No newline at end of file
diff --git a/src/compiler/NubLang/TypeResolver.cs b/src/compiler/NubLang/TypeResolver.cs
deleted file mode 100644
index 972dec2..0000000
--- a/src/compiler/NubLang/TypeResolver.cs
+++ /dev/null
@@ -1,80 +0,0 @@
-using NubLang.Parsing.Syntax;
-using NubLang.TypeChecking;
-using NubLang.TypeChecking.Node;
-
-namespace NubLang;
-
-public static class TypeResolver
-{
- public static TypeNode ResolveType(TypeSyntax type, IReadOnlyDictionary modules)
- {
- return type switch
- {
- BoolTypeSyntax => new BoolTypeNode(),
- CStringTypeSyntax => new CStringTypeNode(),
- IntTypeSyntax i => new IntTypeNode(i.Signed, i.Width),
- CustomTypeSyntax c => ResolveCustomType(c.Module, c.Name, modules),
- FloatTypeSyntax f => new FloatTypeNode(f.Width),
- FuncTypeSyntax func => new FuncTypeNode(func.Parameters.Select(x => ResolveType(x, modules)).ToList(), ResolveType(func.ReturnType, modules)),
- ArrayTypeSyntax arr => new ArrayTypeNode(ResolveType(arr.BaseType, modules)),
- PointerTypeSyntax ptr => new PointerTypeNode(ResolveType(ptr.BaseType, modules)),
- StringTypeSyntax => new StringTypeNode(),
- VoidTypeSyntax => new VoidTypeNode(),
- _ => throw new NotSupportedException($"Unknown type syntax: {type}")
- };
- }
-
- public static TypeNode ResolveCustomType(string moduleName, string typeName, IReadOnlyDictionary modules)
- {
- if (!modules.TryGetValue(moduleName, out var module))
- {
- throw new Exception("Module not found: " + moduleName);
- }
-
- var structType = module.StructTypes.FirstOrDefault(x => x.Name == typeName);
- if (structType != null)
- {
- return structType;
- }
-
- var interfaceType = module.InterfaceTypes.FirstOrDefault(x => x.Name == typeName);
- if (interfaceType != null)
- {
- return interfaceType;
- }
-
- throw new Exception($"Type {typeName} not found in module {moduleName}");
- }
-
- public static StructTypeNode ResolveStructType(string moduleName, string structName, IReadOnlyDictionary modules)
- {
- if (!modules.TryGetValue(moduleName, out var module))
- {
- throw new Exception("Module not found: " + moduleName);
- }
-
- var structType = module.StructTypes.FirstOrDefault(x => x.Name == structName);
- if (structType != null)
- {
- return structType;
- }
-
- throw new Exception($"Struct type {structName} not found in module {moduleName}");
- }
-
- public static InterfaceTypeNode ResolveInterfaceType(string moduleName, string structName, IReadOnlyDictionary modules)
- {
- if (!modules.TryGetValue(moduleName, out var module))
- {
- throw new Exception("Module not found: " + moduleName);
- }
-
- var structType = module.InterfaceTypes.FirstOrDefault(x => x.Name == structName);
- if (structType != null)
- {
- return structType;
- }
-
- throw new Exception($"Interface type {structName} not found in module {moduleName}");
- }
-}
\ No newline at end of file
diff --git a/src/compiler/NubLang/Variant.cs b/src/compiler/NubLang/Variant.cs
deleted file mode 100644
index c9898b8..0000000
--- a/src/compiler/NubLang/Variant.cs
+++ /dev/null
@@ -1,75 +0,0 @@
-using System.Diagnostics.CodeAnalysis;
-
-namespace NubLang;
-
-public readonly struct Variant where T1 : notnull where T2 : notnull
-{
- public Variant()
- {
- throw new InvalidOperationException("Variant must be initialized with a value");
- }
-
- public Variant(T1 value)
- {
- _value = value;
- }
-
- public Variant(T2 value)
- {
- _value = value;
- }
-
- private readonly object _value;
-
- public void Match(Action on1, Action on2)
- {
- switch (_value)
- {
- case T1 v1:
- on1(v1);
- break;
- case T2 v2:
- on2(v2);
- break;
- default:
- throw new InvalidCastException();
- }
- }
-
- public T Match(Func on1, Func on2)
- {
- return _value switch
- {
- T1 v1 => on1(v1),
- T2 v2 => on2(v2),
- _ => throw new InvalidCastException()
- };
- }
-
- public bool IsCase1([NotNullWhen(true)] out T1? value)
- {
- if (_value is T1 converted)
- {
- value = converted;
- return true;
- }
-
- value = default;
- return false;
- }
-
- public bool IsCase2([NotNullWhen(true)] out T2? value)
- {
- if (_value is T2 converted)
- {
- value = converted;
- return true;
- }
-
- value = default;
- return false;
- }
-
- public static implicit operator Variant(T1 value) => new(value);
- public static implicit operator Variant(T2 value) => new(value);
-}
\ No newline at end of file
diff --git a/src/runtime/.clang-format b/src/runtime/.clang-format
deleted file mode 100644
index 277b2b7..0000000
--- a/src/runtime/.clang-format
+++ /dev/null
@@ -1,17 +0,0 @@
-IndentWidth: 4
-
-# Pointer formatting
-DerivePointerAlignment: false
-PointerAlignment: Left
-
-# Function formatting
-AllowShortFunctionsOnASingleLine: None
-
-# Control how short statements are placed
-AllowShortBlocksOnASingleLine: Never
-AllowShortIfStatementsOnASingleLine: Never
-AllowShortLoopsOnASingleLine: false
-
-SeparateDefinitionBlocks: Always
-
-BreakBeforeBraces: Stroustrup
diff --git a/src/runtime/.gitignore b/src/runtime/.gitignore
deleted file mode 100644
index 378eac2..0000000
--- a/src/runtime/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-build
diff --git a/src/runtime/makefile b/src/runtime/makefile
deleted file mode 100644
index ef774d8..0000000
--- a/src/runtime/makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-CC ?= x86_64-linux-gnu-gcc
-TARGET ?= x64
-
-CFLAGS = -Wall -Werror -Wextra -g
-
-libruntime: build/runtime.o
- $(CC) $(CFLAGS) -c targets/$(TARGET).s -o build/$(TARGET).o
-
-build/runtime.o: runtime/runtime.c
- mkdir -p build
- $(CC) $(CFLAGS) -c runtime/runtime.c -o build/runtime.o
-
-clean:
- rm -r build
diff --git a/src/runtime/runtime/runtime.c b/src/runtime/runtime/runtime.c
deleted file mode 100644
index 3a819e9..0000000
--- a/src/runtime/runtime/runtime.c
+++ /dev/null
@@ -1,47 +0,0 @@
-#include
-
-typedef struct nub_string {
- uint64_t size;
- uint8_t buffer[];
-} nub_string_t;
-
-uint64_t nub_cstring_length(const char* string)
-{
- uint64_t len = 0;
- while (string[len] != '\0') {
- len++;
- }
- return len;
-}
-
-uint64_t nub_string_length(const nub_string_t* string)
-{
- uint64_t count = 0;
- uint64_t i = 0;
-
- while (i < string->size) {
- uint8_t byte = string->buffer[i];
-
- if ((byte & 0b11000000) != 0b10000000) {
- count++;
- }
-
- i++;
- }
-
- return count;
-}
-
-void nub_memcpy(uint8_t* source, uint8_t* destination, uint64_t length)
-{
- for (uint64_t i = 0; i < length; i++) {
- destination[i] = source[i];
- }
-}
-
-void nub_memset(uint8_t* destination, uint8_t value, uint64_t count)
-{
- for (uint64_t i = 0; i < count; i++) {
- destination[i] = value;
- }
-}
diff --git a/src/runtime/targets/x64.s b/src/runtime/targets/x64.s
deleted file mode 100644
index f55a1d0..0000000
--- a/src/runtime/targets/x64.s
+++ /dev/null
@@ -1,10 +0,0 @@
-.intel_syntax noprefix
-
-.text
-.globl _start
-_start:
- mov rdi, rsp
- call main
- mov rdi, rax
- mov rax, 60
- syscall
diff --git a/src/vscode/.gitignore b/src/vscode/.gitignore
deleted file mode 100644
index c5e82d7..0000000
--- a/src/vscode/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-bin
\ No newline at end of file
diff --git a/src/vscode/language-configuration.json b/src/vscode/language-configuration.json
deleted file mode 100644
index 538ffc1..0000000
--- a/src/vscode/language-configuration.json
+++ /dev/null
@@ -1,29 +0,0 @@
-{
- "comments": {
- "lineComment": "//",
- "blockComment": ["/*", "*/"]
- },
- "brackets": [
- ["{", "}"],
- ["[", "]"],
- ["(", ")"]
- ],
- "autoClosingPairs": [
- ["{", "}"],
- ["[", "]"],
- ["(", ")"],
- ["\"", "\""],
- ["'", "'"]
- ],
- "surroundingPairs": [
- ["{", "}"],
- ["[", "]"],
- ["(", ")"],
- ["\"", "\""],
- ["'", "'"]
- ],
- "indentationRules": {
- "increaseIndentPattern": "^((?!\\/\\*).)*(\\{[^}\"'`]*|\\([^)\"'`]*|\\[[^\\]\"'`]*)$",
- "decreaseIndentPattern": "^((?!.*?\\/\\*).*\\*/)?\\s*[\\}\\]\\)].*$"
- }
-}
diff --git a/src/vscode/makefile b/src/vscode/makefile
deleted file mode 100644
index f2b1655..0000000
--- a/src/vscode/makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-vscode:
- mkdir -p bin
- npx vsce package -o bin/nub-lang.vsix
-
-clean:
- rm -r bin
\ No newline at end of file
diff --git a/src/vscode/package.json b/src/vscode/package.json
deleted file mode 100644
index a988628..0000000
--- a/src/vscode/package.json
+++ /dev/null
@@ -1,40 +0,0 @@
-{
- "name": "nub-lang",
- "displayName": "Nub Language Support",
- "description": "Syntax highlighting for Nub programming language",
- "version": "0.0.0",
- "publisher": "nub31",
- "repository": {
- "type": "git",
- "url": "https://git.oliste.no/nub31/nub-lang"
- },
- "license": "MIT",
- "engines": {
- "vscode": "^1.74.0"
- },
- "categories": [
- "Programming Languages"
- ],
- "contributes": {
- "languages": [
- {
- "id": "nub",
- "aliases": [
- "Nub",
- "nub"
- ],
- "extensions": [
- ".nub"
- ],
- "configuration": "./language-configuration.json"
- }
- ],
- "grammars": [
- {
- "language": "nub",
- "scopeName": "source.nub",
- "path": "./syntaxes/nub.tmLanguage.json"
- }
- ]
- }
-}
diff --git a/src/vscode/syntaxes/nub.tmLanguage.json b/src/vscode/syntaxes/nub.tmLanguage.json
deleted file mode 100644
index 4a4780c..0000000
--- a/src/vscode/syntaxes/nub.tmLanguage.json
+++ /dev/null
@@ -1,300 +0,0 @@
-{
- "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json",
- "name": "Nub",
- "scopeName": "source.nub",
- "patterns": [
- {
- "include": "#comments"
- },
- {
- "include": "#keywords"
- },
- {
- "include": "#modifiers"
- },
- {
- "include": "#types"
- },
- {
- "include": "#strings"
- },
- {
- "include": "#numbers"
- },
- {
- "include": "#operators"
- },
- {
- "include": "#function-definition"
- },
- {
- "include": "#struct-definition"
- },
- {
- "include": "#function-call"
- },
- {
- "include": "#identifiers"
- }
- ],
- "repository": {
- "comments": {
- "patterns": [
- {
- "name": "comment.line.double-slash.nub",
- "begin": "//",
- "end": "$"
- },
- {
- "name": "comment.block.nub",
- "begin": "/\\*",
- "end": "\\*/"
- }
- ]
- },
- "keywords": {
- "patterns": [
- {
- "name": "keyword.control.nub",
- "match": "\\b(if|else|while|break|continue|return|let)\\b"
- },
- {
- "name": "keyword.other.nub",
- "match": "\\b(namespace|func|struct|interface)\\b"
- }
- ]
- },
- "modifiers": {
- "patterns": [
- {
- "name": "storage.modifier.nub",
- "match": "\\b(export|extern|calls)\\b"
- }
- ]
- },
- "types": {
- "patterns": [
- {
- "include": "#function-type"
- },
- {
- "name": "storage.type.primitive.nub",
- "match": "\\b(i8|i16|i32|i64|u8|u16|u32|u64|f32|f64|bool|string|cstring|void|any)\\b"
- },
- {
- "name": "storage.type.array.nub",
- "match": "\\[\\]"
- },
- {
- "name": "storage.type.pointer.nub",
- "match": "\\^"
- }
- ]
- },
- "function-type": {
- "patterns": [
- {
- "begin": "\\b(func)\\s*\\(",
- "beginCaptures": {
- "1": {
- "name": "storage.type.function.nub"
- }
- },
- "end": "(?<=\\))(?:\\s*:\\s*([^\\s,;{}()]+))?",
- "endCaptures": {
- "1": {
- "name": "storage.type.nub"
- }
- },
- "patterns": [
- {
- "include": "#function-type-parameters"
- }
- ]
- }
- ]
- },
- "function-type-parameters": {
- "patterns": [
- {
- "match": "\\.\\.\\.",
- "name": "keyword.operator.variadic.nub"
- },
- {
- "include": "#types"
- },
- {
- "match": ",",
- "name": "punctuation.separator.nub"
- }
- ]
- },
- "strings": {
- "patterns": [
- {
- "name": "string.quoted.double.nub",
- "begin": "\"",
- "end": "\"",
- "patterns": [
- {
- "name": "constant.character.escape.nub",
- "match": "\\\\(n|t|r|\\\\|\"|')"
- },
- {
- "name": "constant.character.escape.nub",
- "match": "\\\\[0-7]{1,3}"
- },
- {
- "name": "constant.character.escape.nub",
- "match": "\\\\x[0-9A-Fa-f]{1,2}"
- }
- ]
- },
- {
- "name": "string.quoted.single.nub",
- "begin": "'",
- "end": "'",
- "patterns": [
- {
- "name": "constant.character.escape.nub",
- "match": "\\\\(n|t|r|\\\\|\"|')"
- }
- ]
- }
- ]
- },
- "numbers": {
- "patterns": [
- {
- "name": "constant.numeric.float.nub",
- "match": "\\b\\d+\\.\\d*([eE][+-]?\\d+)?[fF]?\\b"
- },
- {
- "name": "constant.numeric.integer.decimal.nub",
- "match": "\\b\\d+\\b"
- },
- {
- "name": "constant.numeric.integer.hexadecimal.nub",
- "match": "\\b0[xX][0-9A-Fa-f]+\\b"
- },
- {
- "name": "constant.numeric.integer.binary.nub",
- "match": "\\b0[bB][01]+\\b"
- }
- ]
- },
- "operators": {
- "patterns": [
- {
- "name": "keyword.operator.assignment.nub",
- "match": "="
- },
- {
- "name": "keyword.operator.comparison.nub",
- "match": "(==|!=|<=|>=|<|>)"
- },
- {
- "name": "keyword.operator.arithmetic.nub",
- "match": "(\\+|\\-|\\*|/)"
- },
- {
- "name": "keyword.operator.logical.nub",
- "match": "(&&|\\|\\||!)"
- },
- {
- "name": "keyword.operator.address.nub",
- "match": "&"
- },
- {
- "name": "keyword.operator.dereference.nub",
- "match": "\\^"
- },
- {
- "name": "keyword.operator.member-access.nub",
- "match": "\\."
- }
- ]
- },
- "function-definition": {
- "patterns": [
- {
- "begin": "\\b(global\\s+|extern\\s+)?(func)\\s+([a-zA-Z_][a-zA-Z0-9_]*)\\s*\\(",
- "beginCaptures": {
- "1": {
- "name": "storage.modifier.nub"
- },
- "2": {
- "name": "keyword.other.nub"
- },
- "3": {
- "name": "entity.name.function.nub"
- }
- },
- "end": "\\)",
- "patterns": [
- {
- "include": "#function-parameters"
- }
- ]
- }
- ]
- },
- "struct-definition": {
- "patterns": [
- {
- "match": "\\b(struct)\\s+([a-zA-Z_][a-zA-Z0-9_]*)\\b",
- "captures": {
- "1": {
- "name": "keyword.other.nub"
- },
- "2": {
- "name": "entity.name.type.struct.nub"
- }
- }
- }
- ]
- },
- "function-parameters": {
- "patterns": [
- {
- "match": "\\.\\.\\.",
- "name": "keyword.operator.variadic.nub"
- },
- {
- "match": "([a-zA-Z_][a-zA-Z0-9_]*)\\s*:\\s*",
- "captures": {
- "1": {
- "name": "variable.parameter.nub"
- }
- }
- },
- {
- "include": "#types"
- },
- {
- "include": "#identifiers"
- }
- ]
- },
- "function-call": {
- "patterns": [
- {
- "match": "([a-zA-Z_][a-zA-Z0-9_]*)\\s*(?=\\()",
- "captures": {
- "1": {
- "name": "entity.name.function.call.nub"
- }
- }
- }
- ]
- },
- "identifiers": {
- "patterns": [
- {
- "name": "variable.other.nub",
- "match": "\\b[a-zA-Z_][a-zA-Z0-9_]*\\b"
- }
- ]
- }
- }
-}
\ No newline at end of file