...
This commit is contained in:
5
build.sh
5
build.sh
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
@@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user