/// <inheritdoc/> public bool Transformation(QsCompilation compilation, out QsCompilation transformed) { // random "diagnostic" to check if diagnostics loading works this.GeneratedDiagnostics = new List <IRewriteStep.Diagnostic>() { new IRewriteStep.Diagnostic { Severity = CodeAnalysis.DiagnosticSeverity.Info, Message = "Invokation of the Q# compiler extension for C# generation to demonstrate execution on the simulation framework.", } }; var success = true; var outputFolder = this.AssemblyConstants.TryGetValue(ReservedKeywords.AssemblyConstants.OutputPath, out var path) ? path : null; var allSources = GetSourceFiles.Apply(compilation.Namespaces) // also generate the code for referenced libraries... // ... except when they are one of the packages that currently still already contains the C# code (temporary workaround): .Where(s => !Path.GetFileName(s).StartsWith("Microsoft.Quantum")); foreach (var source in allSources) { var content = SimulationCode.generate(source, CodegenContext.Create(compilation.Namespaces)); try { CompilationLoader.GeneratedFile(source, outputFolder ?? this.Name, ".g.cs", content); } catch { success = false; } } transformed = compilation; return(success); }
private static void GenerateFromBinary(string outputFolder, string pathToBinary) { CompilationLoader.ReadBinary(pathToBinary, out var syntaxTree); var allSources = GetSourceFiles.Apply(syntaxTree); // also generate the code for referenced libraries foreach (var source in allSources) { var content = SimulationCode.generate(source, syntaxTree); CompilationLoader.GeneratedFile(source, outputFolder, ".g.cs", content); } }
private static void GenerateFromBinary(string outputFolder, string pathToBinary) { var syntaxTree = CompilationLoader.ReadBinary(pathToBinary).ToArray(); var allSources = GetSourceFiles.Apply(syntaxTree).Where(file => file.Value.EndsWith(".qs")); foreach (var source in allSources) { var content = SimulationCode.generate(source, syntaxTree); CompilationLoader.GeneratedFile(source, outputFolder, ".g.cs", content); } }
public bool Transformation(QsCompilation compilation, out QsCompilation transformed) { var success = true; var allSources = GetSourceFiles.Apply(compilation.Namespaces) // also generate the code for referenced libraries... // ... except when they are one of the packages that currently still already contains the C# code (temporary workaround): .Where(s => !Path.GetFileName(s.Value).StartsWith("Microsoft.Quantum")); foreach (var source in allSources) { var content = SimulationCode.generate(source, compilation.Namespaces); try { CompilationLoader.GeneratedFile(source, this.OutputFolder ?? this.Name, ".g.cs", content); } catch { success = false; } } transformed = compilation; return(success); }
public bool Transformation(QsCompilation compilation, out QsCompilation transformed) { var context = CodegenContext.Create(compilation, _assemblyConstants); var sources = GetSourceFiles.Apply(compilation.Namespaces); foreach (var source in sources.Where(s => !s.Value.EndsWith(".dll", StringComparison.OrdinalIgnoreCase))) { var content = SimulationCode.generate(source, context); GeneratedFiles.Add(source.Value, content); } if (!compilation.EntryPoints.IsEmpty) { var callable = context.allCallables.First(c => c.Key == compilation.EntryPoints.First()).Value; var content = EntryPoint.generate(context, callable); NonNullable <string> entryPointName = NonNullable <string> .New(callable.SourceFile.Value + ".EntryPoint"); GeneratedFiles.Add(entryPointName.Value, content); } transformed = compilation; return(true); }
/// <summary> /// Builds the corresponding .net core assembly from the Q# syntax tree. /// </summary> private static AssemblyInfo BuildAssembly(Uri[] fileNames, QsCompiler.SyntaxTree.QsNamespace[] syntaxTree, IEnumerable <MetadataReference> references, QSharpLogger logger, string targetDll) { if (logger.HasErrors) { return(null); } logger.LogDebug($"Compiling the following Q# files: {string.Join(",", fileNames.Select(f => f.LocalPath))}"); try { // Generate C# simulation code from Q# syntax tree and convert it into C# syntax trees: var trees = new List <SyntaxTree>(); NonNullable <string> GetFileId(Uri uri) => CompilationUnitManager.TryGetFileId(uri, out var id) ? id : NonNullable <string> .New(uri.AbsolutePath); foreach (var file in fileNames) { var sourceFile = GetFileId(file); var code = SimulationCode.generate(sourceFile, syntaxTree); var tree = CSharpSyntaxTree.ParseText(code, encoding: UTF8Encoding.UTF8); trees.Add(tree); logger.LogDebug($"Generated the following C# code for {sourceFile.Value}:\n=============\n{code}\n=============\n"); } // Compile the C# syntax trees: var options = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, optimizationLevel: OptimizationLevel.Debug); var compilation = CSharpCompilation.Create( Path.GetFileNameWithoutExtension(targetDll), trees, references, options); // Generate the assembly from the C# compilation: using (var ms = new MemoryStream()) { EmitResult result = compilation.Emit(ms); if (!result.Success) { IEnumerable <Diagnostic> failures = result.Diagnostics.Where(diagnostic => diagnostic.IsWarningAsError || diagnostic.Severity == DiagnosticSeverity.Error); logger.LogError("IQS000", "Could not compile Roslyn dll from working folder."); foreach (Diagnostic diagnostic in failures) { logger.LogError(diagnostic.Id, diagnostic.GetMessage()); } return(null); } else { logger.LogDebug($"Assembly successfully generated. Caching at {targetDll}."); var data = ms.ToArray(); try { File.WriteAllBytes(targetDll, data); } catch (Exception e) { logger.LogError("IQS001", $"Unable to save assembly cache: {e.Message}."); } return(new AssemblyInfo(Assembly.Load(data), targetDll, syntaxTree)); } } } catch (Exception e) { logger.LogError("IQS002", $"Unexpected error compiling assembly: {e.Message}."); return(null); } }
/// <summary> /// Builds the corresponding .net core assembly from the Q# syntax tree. /// </summary> private AssemblyInfo BuildAssembly(ImmutableDictionary <Uri, string> sources, CompilerMetadata metadata, QSharpLogger logger, string dllName) { logger.LogDebug($"Compiling the following Q# files: {string.Join(",", sources.Keys.Select(f => f.LocalPath))}"); var qsCompilation = this.UpdateCompilation(sources, metadata.QsMetadatas, logger); if (logger.HasErrors) { return(null); } try { // Generate C# simulation code from Q# syntax tree and convert it into C# syntax trees: var trees = new List <SyntaxTree>(); NonNullable <string> GetFileId(Uri uri) => CompilationUnitManager.TryGetFileId(uri, out var id) ? id : NonNullable <string> .New(uri.AbsolutePath); foreach (var file in sources.Keys) { var sourceFile = GetFileId(file); var code = SimulationCode.generate(sourceFile, CodegenContext.Create(qsCompilation.Namespaces)); var tree = CSharpSyntaxTree.ParseText(code, encoding: UTF8Encoding.UTF8); trees.Add(tree); logger.LogDebug($"Generated the following C# code for {sourceFile.Value}:\n=============\n{code}\n=============\n"); } // Compile the C# syntax trees: var options = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, optimizationLevel: OptimizationLevel.Debug); var compilation = CSharpCompilation.Create( Path.GetFileNameWithoutExtension(dllName), trees, metadata.RoslynMetadatas, options); // Generate the assembly from the C# compilation: using (var ms = new MemoryStream()) using (var bsonStream = new MemoryStream()) { using var writer = new BsonDataWriter(bsonStream) { CloseOutput = false }; var fromSources = qsCompilation.Namespaces.Select(ns => FilterBySourceFile.Apply(ns, s => s.Value.EndsWith(".qs"))); Json.Serializer.Serialize(writer, new QsCompilation(fromSources.ToImmutableArray(), qsCompilation.EntryPoints)); var resourceDescription = new ResourceDescription ( resourceName: QsCompiler.ReservedKeywords.DotnetCoreDll.ResourceName, dataProvider: () => new MemoryStream(bsonStream.ToArray()), isPublic: true ); var result = compilation.Emit(ms, manifestResources: new[] { resourceDescription }); if (!result.Success) { IEnumerable <Diagnostic> failures = result.Diagnostics.Where(diagnostic => diagnostic.IsWarningAsError || diagnostic.Severity == DiagnosticSeverity.Error); logger.LogError("IQS000", "Could not compile Roslyn dll from working folder."); foreach (Diagnostic diagnostic in failures) { logger.LogError(diagnostic.Id, diagnostic.GetMessage()); } return(null); } else { logger.LogDebug($"Assembly successfully generated. Caching at {dllName}."); var data = ms.ToArray(); try { File.WriteAllBytes(dllName, data); } catch (Exception e) { logger.LogError("IQS001", $"Unable to save assembly cache: {e.Message}."); } return(new AssemblyInfo(Assembly.Load(data), dllName, fromSources.ToArray())); } } } catch (Exception e) { logger.LogError("IQS002", $"Unexpected error compiling assembly: {e.Message}."); return(null); } }