/// <summary> /// Creates a new array value of the given length. Expects a value of type i64 for the length of the array. /// Registers the value with the scope manager, unless registerWithScopeManager is set to false. /// </summary> /// <param name="length">Value of type i64 indicating the number of elements in the array</param> /// <param name="elementType">Q# type of the array elements</param> /// <param name="context">Generation context where constants are defined and generated if needed</param> internal ArrayValue(Value length, ResolvedType elementType, GenerationContext context, bool registerWithScopeManager = true) { this.sharedState = context; this.QSharpElementType = elementType; this.LlvmElementType = context.LlvmTypeFromQsharpType(elementType); this.length = this.CreateLengthCache(length); this.OpaquePointer = this.AllocateArray(registerWithScopeManager); }
/// <summary> /// Creates a new array value from the given opaque array of elements of the given type. /// </summary> /// <param name="array">The opaque pointer to the array data structure</param> /// <param name="length">Value of type i64 indicating the number of elements in the array; will be computed on demand if the given value is null</param> /// <param name="elementType">Q# type of the array elements</param> /// <param name="context">Generation context where constants are defined and generated if needed</param> internal ArrayValue(Value array, Value?length, ResolvedType elementType, GenerationContext context) { this.sharedState = context; this.QSharpElementType = elementType; this.LlvmElementType = context.LlvmTypeFromQsharpType(elementType); this.OpaquePointer = Types.IsArray(array.NativeType) ? array : throw new ArgumentException("expecting an opaque array"); this.length = length == null ? new IValue.Cached <Value>(context, this.GetLength) : this.CreateLengthCache(length); }
/// <summary> /// Creates a new tuple value representing a Q# value of user defined type. /// The casts to get the opaque and typed pointer respectively are executed lazily. When needed, /// the instructions are emitted using the current builder. /// Registers the value with the scope manager, unless registerWithScopeManager is set to false. /// </summary> /// <param name="elementTypes">The Q# types of the tuple items</param> /// <param name="context">Generation context where constants are defined and generated if needed</param> internal TupleValue(UserDefinedType?type, ImmutableArray <ResolvedType> elementTypes, GenerationContext context, bool registerWithScopeManager = true) { this.sharedState = context; this.customType = type; this.ElementTypes = elementTypes; this.StructType = this.sharedState.Types.TypedTuple(elementTypes.Select(context.LlvmTypeFromQsharpType)); this.opaquePointer = this.CreateOpaquePointerCache(this.AllocateTuple(registerWithScopeManager)); this.typedPointer = this.CreateTypedPointerCache(); this.tupleElementPointers = this.CreateTupleElementPointersCaches(); }
/// <summary> /// Creates a pointer that can store a value and provides a caching mechanism for accessing that value /// to avoid unnecessary loads. The pointer is instantiated with the given pointer. /// If the given pointer is null, a new pointer is created via an alloca instruction. /// </summary> /// <param name="pointer">Optional parameter to provide an existing pointer to use</param> /// <param name="type">The Q# type of the value that the pointer points to</param> /// <param name="context">Generation context where constants are defined and generated if needed</param> internal PointerValue(Value?pointer, ResolvedType type, GenerationContext context) { void Store(IValue v) => context.CurrentBuilder.Store(v.Value, this.pointer); IValue Reload() => context.Values.From( context.CurrentBuilder.Load(this.LlvmType, this.pointer), this.QSharpType); this.QSharpType = type; this.LlvmType = context.LlvmTypeFromQsharpType(this.QSharpType); this.pointer = pointer ?? context.CurrentBuilder.Alloca(this.LlvmType); this.cachedValue = new IValue.Cached <IValue>(context, Reload, Store); }
/// <summary> /// Creates a new tuple value representing a Q# value of user defined type from the given tuple pointer. /// The casts to get the opaque and typed pointer respectively are executed lazily. When needed, /// instructions are emitted using the current builder. /// </summary> /// <param name="type">Optionally the user defined type tha that the tuple represents</param> /// <param name="tuple">Either an opaque or a typed pointer to the tuple data structure</param> /// <param name="elementTypes">The Q# types of the tuple items</param> /// <param name="context">Generation context where constants are defined and generated if needed</param> internal TupleValue(UserDefinedType?type, Value tuple, ImmutableArray <ResolvedType> elementTypes, GenerationContext context) { var isTypedTuple = Types.IsTypedTuple(tuple.NativeType); var isOpaqueTuple = !tuple.IsNull && Types.IsTupleOrUnit(tuple.NativeType); if (!isTypedTuple && !isOpaqueTuple) { throw new ArgumentException("expecting either an opaque or a typed tuple"); } this.sharedState = context; this.customType = type; this.ElementTypes = elementTypes; this.StructType = this.sharedState.Types.TypedTuple(elementTypes.Select(context.LlvmTypeFromQsharpType)); this.opaquePointer = this.CreateOpaquePointerCache(isOpaqueTuple ? tuple : null); this.typedPointer = this.CreateTypedPointerCache(isTypedTuple ? tuple : null); this.tupleElementPointers = this.CreateTupleElementPointersCaches(); }