From 8b4e193438256a611ccdb336661e1276f4499e3d Mon Sep 17 00:00:00 2001 From: nub31 Date: Thu, 12 Jun 2025 23:04:47 +0200 Subject: [PATCH] ... --- build.sh | 5 +- src/lang/Nub.Lang.CLI/Program.cs | 64 +++++++++++++++++++-- src/lang/Nub.Lang/Diagnostics/Diagnostic.cs | 2 +- src/lang/Nub.Lang/Source.cs | 12 ++-- 4 files changed, 69 insertions(+), 14 deletions(-) diff --git a/build.sh b/build.sh index 5d7c77b..4c6ec11 100755 --- a/build.sh +++ b/build.sh @@ -8,9 +8,8 @@ rm -rf bin-int/* bin/* nub example -find bin-int -name '*.ssa' | while read -r file; do - qbe "$file" > "bin-int/$(basename "${file}" .ssa).s" - as "bin-int/$(basename "${file}" .ssa).s" -o "bin-int/$(basename "${file}" .ssa).o" +find bin-int -name '*.s' | while read -r file; do + as "$file" -o "bin-int/$(basename "${file}" .s).o" done find src/runtime -name '*.s' | while read -r file; do diff --git a/src/lang/Nub.Lang.CLI/Program.cs b/src/lang/Nub.Lang.CLI/Program.cs index 4987893..f84926c 100644 --- a/src/lang/Nub.Lang.CLI/Program.cs +++ b/src/lang/Nub.Lang.CLI/Program.cs @@ -1,4 +1,5 @@ -using Nub.Lang; +using System.Diagnostics; +using Nub.Lang; using Nub.Lang.Frontend; using Nub.Lang.Frontend.Generation; using Nub.Lang.Frontend.Lexing; @@ -22,13 +23,16 @@ if (!Directory.Exists(srcDir)) var error = false; +Dictionary sourceTexts = []; List compilationUnits = []; foreach (var file in Directory.EnumerateFiles(srcDir, "*.nub", SearchOption.AllDirectories)) { var content = File.ReadAllText(file); - var tokenizeResult = Lexer.Tokenize(new SourceText(file, content)); + var sourceText = new SourceText(file, content); + + var tokenizeResult = Lexer.Tokenize(sourceText); tokenizeResult.PrintAllDiagnostics(); error = error || tokenizeResult.HasErrors; @@ -39,6 +43,7 @@ foreach (var file in Directory.EnumerateFiles(srcDir, "*.nub", SearchOption.AllD if (parseResult.Value != null) { compilationUnits.Add(parseResult.Value); + sourceTexts[parseResult.Value] = sourceText; } } @@ -54,10 +59,61 @@ foreach (var compilationUnit in compilationUnits) var typeCheckResult = TypeChecker.Check(compilationUnit, definitionTable); typeCheckResult.PrintAllDiagnostics(); error = error || typeCheckResult.HasErrors; +} - var result = QBEGenerator.Generate(compilationUnit, definitionTable); +if (error) +{ + return 1; +} - File.WriteAllText($"bin-int/{Guid.NewGuid():N}.ssa", result); +foreach (var compilationUnit in compilationUnits) +{ + var ssaCode = QBEGenerator.Generate(compilationUnit, definitionTable); + + var sourceFileName = Path.GetFileNameWithoutExtension(sourceTexts[compilationUnit].Path); + var sourceHash = Math.Abs(sourceTexts[compilationUnit].Path.GetHashCode()).ToString("x8"); + var timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString("x"); + var baseOutputName = $"{sourceFileName}_{sourceHash}_{timestamp}"; + + try + { + using var qbeProcess = new Process(); + qbeProcess.StartInfo = new ProcessStartInfo + { + FileName = "qbe", + UseShellExecute = false, + RedirectStandardInput = true, + RedirectStandardOutput = true, + RedirectStandardError = true, + CreateNoWindow = true + }; + + qbeProcess.Start(); + + await qbeProcess.StandardInput.WriteAsync(ssaCode); + qbeProcess.StandardInput.Close(); + + var assemblyCode = await qbeProcess.StandardOutput.ReadToEndAsync(); + var qbeErrors = await qbeProcess.StandardError.ReadToEndAsync(); + + await qbeProcess.WaitForExitAsync(); + + if (qbeProcess.ExitCode != 0) + { + Console.Error.WriteLine($"QBE failed for {sourceTexts[compilationUnit].Path}:"); + Console.Error.WriteLine(qbeErrors); + error = true; + continue; + } + + var asmPath = Path.Combine("bin-int", $"{baseOutputName}.s"); + await File.WriteAllTextAsync(asmPath, assemblyCode); + } + catch (Exception ex) + { + Console.Error.WriteLine($"Error invoking QBE for {sourceTexts[compilationUnit].Path}: {ex.Message}"); + error = true; + } } return error ? 1 : 0; \ No newline at end of file diff --git a/src/lang/Nub.Lang/Diagnostics/Diagnostic.cs b/src/lang/Nub.Lang/Diagnostics/Diagnostic.cs index 8644ef4..b6b151a 100644 --- a/src/lang/Nub.Lang/Diagnostics/Diagnostic.cs +++ b/src/lang/Nub.Lang/Diagnostics/Diagnostic.cs @@ -72,7 +72,7 @@ public class Diagnostic if (Span.HasValue) { - var locationText = $" at {Span.Value.Text.Name}:{Span}"; + var locationText = $" at {Span.Value.Text.Path}:{Span}"; sb.Append(ConsoleColors.Colorize(locationText, ConsoleColors.Faint)); } diff --git a/src/lang/Nub.Lang/Source.cs b/src/lang/Nub.Lang/Source.cs index 4fc1410..c2d3ef7 100644 --- a/src/lang/Nub.Lang/Source.cs +++ b/src/lang/Nub.Lang/Source.cs @@ -74,13 +74,13 @@ public struct SourceText : IEquatable { private int _lines = -1; - public SourceText(string name, string content) + public SourceText(string path, string content) { - Name = name ?? throw new ArgumentNullException(nameof(name)); + Path = path ?? throw new ArgumentNullException(nameof(path)); Content = content ?? throw new ArgumentNullException(nameof(content)); } - public string Name { get; } + public string Path { get; } public string Content { get; } public int LineCount() @@ -109,7 +109,7 @@ public struct SourceText : IEquatable public bool Equals(SourceText other) { - return Name == other.Name && Content == other.Content; + return Path == other.Path && Content == other.Content; } public override bool Equals([NotNullWhen(true)] object? obj) @@ -119,12 +119,12 @@ public struct SourceText : IEquatable public override int GetHashCode() { - return HashCode.Combine(Name, Content); + return HashCode.Combine(Path, Content); } public override string ToString() { - return Name; + return Path; } public static bool operator ==(SourceText left, SourceText right) => left.Equals(right);