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(); var syntaxTrees = new List(); 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(); 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(); 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;