static Microsoft.CodeAnalysis.SyntaxTree GetLibraryModuleSyntaxTree(string filename) { if (Path.GetExtension(filename) == ".mylang") { if (MakeSyntaxAnalysis(filename, out Node syntaxTree)) { //initialize visitor RoslynTreeBuilderVisitor visitor = new RoslynTreeBuilderVisitor(Path.GetFileNameWithoutExtension(filename)); //run visitor syntaxTree.Visit(visitor); return(visitor.UnitNode.SyntaxTree); } else { throw new Exception($"Error in standard library: {Path.GetFileNameWithoutExtension(filename)}"); } } else if (Path.GetExtension(filename) == ".cs") { try { return(CSharpSyntaxTree.ParseText(File.ReadAllText(filename))); } catch { throw new Exception($"Error in standard library: {Path.GetFileNameWithoutExtension(filename)}"); } } else { throw new Exception($"Unknow item in standard library: {Path.GetFileNameWithoutExtension(filename)}"); } }
/// <summary> /// Compile the program which is setted by syntax tree /// </summary> /// <param name="syntaxTree">Syntax tree</param> static void Compile(Node syntaxTree, string outputFileName) { //initialize visitor RoslynTreeBuilderVisitor visitor = new RoslynTreeBuilderVisitor(); //run visitor syntaxTree.Visit(visitor); //get unit which prepared for compilation var programUnit = visitor.UnitNode; //get all location annotations and build location map var locationAnnotations = visitor.LocationAnnotations; var locationMap = GetLocationMap(programUnit, locationAnnotations); //get syntax trees of standard library var arraySyntaxTree = CSharpSyntaxTree.ParseText(File.ReadAllText("../../../MyCompilerLibrary/Array.cs")); var syntaxTrees = new List <Microsoft.CodeAnalysis.SyntaxTree> { programUnit.SyntaxTree }; foreach (var file in Directory.GetFiles("../../../MyCompilerLibrary/")) { syntaxTrees.Add(GetLibraryModuleSyntaxTree(file)); } CSharpCompilation compilation = CSharpCompilation.Create( "assemblyName", syntaxTrees, new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location), MetadataReference.CreateFromFile(Assembly.Load("System.Runtime").Location), MetadataReference.CreateFromFile(Assembly.Load("System.Console").Location), MetadataReference.CreateFromFile(Assembly.Load("System.Linq").Location), MetadataReference.CreateFromFile(typeof(System.Diagnostics.Stopwatch).Assembly.Location), }, new CSharpCompilationOptions( outputKind: OutputKind.ConsoleApplication, //set application type as console app optimizationLevel: OptimizationLevel.Release //set optimization level for Release mode ) ); string configPath = Path.GetDirectoryName(outputFileName) + "/" + Path.GetFileNameWithoutExtension(outputFileName) + ".runtimeconfig.json"; GenerateRuntimeConfig(configPath.TrimStart('/')); //generate runtime config //generate program to file using var exeStream = new FileStream(outputFileName, FileMode.Create); var emitResult = compilation.Emit(exeStream); //compile //if we have warnings, print them foreach (var error in emitResult.Diagnostics.Where(diagnostic => diagnostic.WarningLevel > 0 && diagnostic.WarningLevel < 4)) { Console.WriteLine(errorFormatter.GetErrorString(error, locationMap)); } if (!emitResult.Success) { //if we have errors, print them foreach (var error in emitResult.Diagnostics.Where(diagnostic => diagnostic.WarningLevel == 0)) { Console.WriteLine(errorFormatter.GetErrorString(error, locationMap)); } } //print C# source code which matches to builded Roslyn's syntax tree //Console.WriteLine("========== SOURCE CODE =========="); //Console.WriteLine(programUnit.NormalizeWhitespace().ToFullString()); }