118 lines
2.9 KiB
C#
118 lines
2.9 KiB
C#
using System.Diagnostics;
|
|
using CLI;
|
|
using Generation.QBE;
|
|
using Syntax;
|
|
using Syntax.Diagnostics;
|
|
using Syntax.Parsing;
|
|
using Syntax.Tokenization;
|
|
using Syntax.Typing;
|
|
using Binder = Syntax.Typing.Binder;
|
|
|
|
const string BIN_DIR = "bin";
|
|
const string BIN_INT_DIR = "bin-int";
|
|
|
|
if (Directory.Exists(BIN_DIR))
|
|
{
|
|
Directory.Delete(BIN_DIR, true);
|
|
}
|
|
|
|
if (Directory.Exists(BIN_INT_DIR))
|
|
{
|
|
Directory.Delete(BIN_INT_DIR, true);
|
|
}
|
|
|
|
Directory.CreateDirectory(BIN_DIR);
|
|
Directory.CreateDirectory(BIN_INT_DIR);
|
|
|
|
var diagnostics = new List<Diagnostic>();
|
|
var syntaxTrees = new List<SyntaxTree>();
|
|
|
|
foreach (var file in args)
|
|
{
|
|
if (!File.Exists(file))
|
|
{
|
|
Console.Error.WriteLine($"File '{file}' does not exist");
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
foreach (var file in args)
|
|
{
|
|
var content = File.ReadAllText(file);
|
|
var sourceText = new SourceText(file, content);
|
|
|
|
var tokenizeResult = Tokenizer.Tokenize(sourceText, out var tokenizerDiagnostics);
|
|
diagnostics.AddRange(tokenizerDiagnostics);
|
|
|
|
var syntaxTree = Parser.ParseFile(tokenizeResult, file, out var parseDiagnostics);
|
|
diagnostics.AddRange(parseDiagnostics);
|
|
|
|
if (syntaxTree != null)
|
|
{
|
|
syntaxTrees.Add(syntaxTree);
|
|
}
|
|
else
|
|
{
|
|
throw new Exception();
|
|
}
|
|
}
|
|
|
|
var definitionTable = new DefinitionTable(syntaxTrees);
|
|
|
|
var boundSyntaxTrees = new List<BoundSyntaxTree>();
|
|
|
|
foreach (var syntaxTree in syntaxTrees)
|
|
{
|
|
boundSyntaxTrees.Add(Binder.Bind(syntaxTree, definitionTable));
|
|
}
|
|
|
|
var boundDefinitionTable = new BoundDefinitionTable(boundSyntaxTrees);
|
|
|
|
foreach (var diagnostic in diagnostics)
|
|
{
|
|
Console.Error.WriteLine(diagnostic.FormatANSI());
|
|
}
|
|
|
|
if (diagnostics.Any(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error))
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
var objectFiles = new List<string>();
|
|
|
|
objectFiles.Add("/home/oliste/repos/nub-lang/src/runtime/runtime.o");
|
|
|
|
foreach (var boundSyntaxTree in boundSyntaxTrees)
|
|
{
|
|
var relativeFilePath = Path.GetRelativePath(Environment.CurrentDirectory, boundSyntaxTree.FilePath);
|
|
var outputPath = Path.Combine(BIN_INT_DIR, relativeFilePath);
|
|
|
|
var outputDirectory = Path.GetDirectoryName(outputPath);
|
|
Debug.Assert(!string.IsNullOrWhiteSpace(outputDirectory));
|
|
Directory.CreateDirectory(outputDirectory);
|
|
|
|
var ssa = QBEGenerator.Emit(boundSyntaxTree, boundDefinitionTable);
|
|
var ssaPath = Path.ChangeExtension(outputPath, "ssa");
|
|
File.WriteAllText(ssaPath, ssa);
|
|
|
|
var asm = await QBE.Invoke(ssa);
|
|
if (asm == null)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
var asmPath = Path.ChangeExtension(outputPath, "s");
|
|
await File.WriteAllTextAsync(asmPath, asm);
|
|
|
|
var objPath = Path.ChangeExtension(outputPath, "o");
|
|
var asmSuccess = await GCC.Assemble(asmPath, objPath);
|
|
if (!asmSuccess)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
objectFiles.Add(objPath);
|
|
}
|
|
|
|
var linkSuccess = await GCC.Link(objectFiles, Path.Combine(BIN_DIR, "out"));
|
|
return linkSuccess ? 0 : 1; |