This commit is contained in:
nub31
2025-06-12 23:04:47 +02:00
parent 5a7164bd33
commit 32a341508c
4 changed files with 69 additions and 14 deletions

View File

@@ -8,9 +8,8 @@ rm -rf bin-int/* bin/*
nub example nub example
find bin-int -name '*.ssa' | while read -r file; do find bin-int -name '*.s' | while read -r file; do
qbe "$file" > "bin-int/$(basename "${file}" .ssa).s" as "$file" -o "bin-int/$(basename "${file}" .s).o"
as "bin-int/$(basename "${file}" .ssa).s" -o "bin-int/$(basename "${file}" .ssa).o"
done done
find src/runtime -name '*.s' | while read -r file; do find src/runtime -name '*.s' | while read -r file; do

View File

@@ -1,4 +1,5 @@
using Nub.Lang; using System.Diagnostics;
using Nub.Lang;
using Nub.Lang.Frontend; using Nub.Lang.Frontend;
using Nub.Lang.Frontend.Generation; using Nub.Lang.Frontend.Generation;
using Nub.Lang.Frontend.Lexing; using Nub.Lang.Frontend.Lexing;
@@ -22,13 +23,16 @@ if (!Directory.Exists(srcDir))
var error = false; var error = false;
Dictionary<CompilationUnit, SourceText> sourceTexts = [];
List<CompilationUnit> compilationUnits = []; List<CompilationUnit> compilationUnits = [];
foreach (var file in Directory.EnumerateFiles(srcDir, "*.nub", SearchOption.AllDirectories)) foreach (var file in Directory.EnumerateFiles(srcDir, "*.nub", SearchOption.AllDirectories))
{ {
var content = File.ReadAllText(file); 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(); tokenizeResult.PrintAllDiagnostics();
error = error || tokenizeResult.HasErrors; error = error || tokenizeResult.HasErrors;
@@ -39,6 +43,7 @@ foreach (var file in Directory.EnumerateFiles(srcDir, "*.nub", SearchOption.AllD
if (parseResult.Value != null) if (parseResult.Value != null)
{ {
compilationUnits.Add(parseResult.Value); compilationUnits.Add(parseResult.Value);
sourceTexts[parseResult.Value] = sourceText;
} }
} }
@@ -54,10 +59,61 @@ foreach (var compilationUnit in compilationUnits)
var typeCheckResult = TypeChecker.Check(compilationUnit, definitionTable); var typeCheckResult = TypeChecker.Check(compilationUnit, definitionTable);
typeCheckResult.PrintAllDiagnostics(); typeCheckResult.PrintAllDiagnostics();
error = error || typeCheckResult.HasErrors; 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; return error ? 1 : 0;

View File

@@ -72,7 +72,7 @@ public class Diagnostic
if (Span.HasValue) 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)); sb.Append(ConsoleColors.Colorize(locationText, ConsoleColors.Faint));
} }

View File

@@ -74,13 +74,13 @@ public struct SourceText : IEquatable<SourceText>
{ {
private int _lines = -1; 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)); Content = content ?? throw new ArgumentNullException(nameof(content));
} }
public string Name { get; } public string Path { get; }
public string Content { get; } public string Content { get; }
public int LineCount() public int LineCount()
@@ -109,7 +109,7 @@ public struct SourceText : IEquatable<SourceText>
public bool Equals(SourceText other) 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) public override bool Equals([NotNullWhen(true)] object? obj)
@@ -119,12 +119,12 @@ public struct SourceText : IEquatable<SourceText>
public override int GetHashCode() public override int GetHashCode()
{ {
return HashCode.Combine(Name, Content); return HashCode.Combine(Path, Content);
} }
public override string ToString() public override string ToString()
{ {
return Name; return Path;
} }
public static bool operator ==(SourceText left, SourceText right) => left.Equals(right); public static bool operator ==(SourceText left, SourceText right) => left.Equals(right);