This repository was archived by the owner on Jan 12, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 55
Expand file tree
/
Copy pathAssemblyInfo.cs
More file actions
130 lines (107 loc) · 5.06 KB
/
AssemblyInfo.cs
File metadata and controls
130 lines (107 loc) · 5.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System.Reflection;
using Microsoft.Quantum.QsCompiler.CompilationBuilder;
using Microsoft.Quantum.IQSharp.Common;
using Microsoft.Quantum.QsCompiler.SyntaxTree;
using Microsoft.Quantum.QsCompiler;
using System.IO;
namespace Microsoft.Quantum.IQSharp
{
/// <summary>
/// This class stores the information about a .net core assembly.
/// If the assembly was built from Q# code, then it also keeps track of the list of Operations
/// defined in it, plus the corresponding SyntaxTree.
/// </summary>
public class AssemblyInfo : IEquatable<AssemblyInfo>
{
/// List of operations found. Calculated on demand.
private Lazy<OperationInfo[]> _operations;
/// <summary>
/// Constructor for non Q# compiled assemblies.
/// </summary>
public AssemblyInfo(Assembly assembly) : this(assembly, location: null, syntaxTree: null, qirBitcode: null)
{
}
/// <summary>
/// Constructor for Q# compiled assemblies.
/// </summary>
/// <remarks>
/// If <paramref name="qirBitcode"/> is not <c>null</c>, its
/// contents will be read by this constructor, and its position
/// will not be reset. That is, the position of <paramref name="qirBitcode" />
/// after this call will be that set by the <see cref="System.IO.Stream.CopyTo(Stream)"/>
/// method (generally, the end of the QIR bitcode stream).
/// </remarks>
public AssemblyInfo(Assembly? assembly, string? location, QsNamespace[]? syntaxTree, Stream? qirBitcode)
{
Assembly = assembly;
Location = location ?? assembly?.Location;
SyntaxTree = syntaxTree;
_operations = new Lazy<OperationInfo[]>(InitOperations);
// If QIR bitcode is provided, read it into a new memory stream
// owned by this object.
if (qirBitcode != null)
{
var memoryStream = new MemoryStream();
qirBitcode.CopyTo(memoryStream);
memoryStream.Seek(0, SeekOrigin.Begin);
QirBitcode = memoryStream;
}
}
/// <summary>
/// The actual Assembly we're wrapping.
/// </summary>
public Assembly? Assembly { get; }
/// <summary>
/// The path (location) in disk of this assembly.
/// </summary>
public string? Location { get; }
/// <summary>
/// For Q#-based assemblies, the corresponding SyntaxTree.
/// </summary>
public QsNamespace[]? SyntaxTree { get; }
/// <summary>
/// The stream from which QIR bitcode for the entry point can be read.
/// </summary>
public Stream? QirBitcode { get; }
/// <summary>
/// For Q#-based assemblies, the corresponding operations found in the SyntaxTree.
/// </summary>
public IEnumerable<OperationInfo> Operations => _operations.Value;
/// <summary>
/// Used to lazily calculate operations in an assembly.
/// Assumes that all Types in the Assembly are for operations.
/// </summary>
private OperationInfo[] InitOperations()
{
if (Assembly == null) return new OperationInfo[0];
// Parse the assembly headers to find which types are operation or function types.
var logger = new QSharpLogger(null);
var refs = ProjectManager.LoadReferencedAssemblies(new[] { Location }, d => logger.Log(d), ex => logger.Log(ex), ignoreDllResources: false);
var callables = refs.SelectMany(pair => pair.Value.Callables);
var ops = new List<OperationInfo>();
foreach (var callable in callables)
{
// Find the associated type.
var fullName = callable.QualifiedName.ToFullName();
var type = Assembly.GetType(fullName);
var info = new OperationInfo(type, callable);
ops.Add(info);
}
// Makes sure Deprecated operations are pushed to the bottom so that they are resolved second:
return ops
.OrderBy(op => op.Header.Attributes.Any(BuiltIn.MarksDeprecation) ? 1 : 0)
.ToArray();
}
#region Equals
public override string? ToString() => Assembly?.ToString();
public override bool Equals(object obj) => Equals(obj as AssemblyInfo);
public bool Equals(AssemblyInfo? other) => Assembly?.FullName == other?.Assembly?.FullName;
public override int GetHashCode() => Assembly?.FullName?.GetHashCode() ?? 0;
public static bool operator ==(AssemblyInfo info1, AssemblyInfo info2) => info1?.Assembly?.FullName == info2?.Assembly?.FullName;
public static bool operator !=(AssemblyInfo info1, AssemblyInfo info2) => !(info1 == info2);
#endregion
public static AssemblyInfo? Create(Assembly? assembly) => assembly == null ? null : new AssemblyInfo(assembly);
}
}