// Takes a single TypedExpression of type Result and puts in into a // value array expression with the given expression as its only item. static TypedExpression BoxResultInArray(TypedExpression expression) => new TypedExpression( ExpressionKind.NewValueArray(ImmutableArray.Create(expression)), TypeArgsResolution.Empty, ResolvedType.New(ResolvedTypeKind.NewArrayType(ResolvedType.New(ResolvedTypeKind.Result))), new InferredExpressionInformation(false, expression.InferredInformation.HasLocalQuantumDependency), QsNullable <Range> .Null);
/// <summary> /// Creates an array literal with the given items, setting the range information to Null. /// If no items are given, creates an empty array of type Unit[]. /// The resolved types for all of the given expressions must match, /// none of the given expressions should have a local quantum dependency, /// and all range information should be stripped from each given expression. /// </summary> internal static TypedExpression CreateValueArray(params TypedExpression[] expressions) { ResolvedType type = null; if (expressions.Any()) { type = expressions.First().ResolvedType; QsCompilerError.Verify(expressions.All(expr => expr.ResolvedType.Equals(type))); } else { type = ResolvedType.New(ResolvedTypeKind.UnitType); } return(new TypedExpression ( ExpressionKind.NewValueArray(expressions.ToImmutableArray()), TypeArgsResolution.Empty, ResolvedType.New(ResolvedTypeKind.NewArrayType(type)), new InferredExpressionInformation(false, false), QsNullable <Tuple <QsPositionInfo, QsPositionInfo> > .Null )); }
private (ResolvedSignature, IEnumerable <QsSpecialization>) MakeSpecializations( QsQualifiedName callableName, ResolvedType paramsType, SpecializationImplementation bodyImplementation) { QsSpecialization MakeSpec(QsSpecializationKind kind, ResolvedSignature signature, SpecializationImplementation impl) => new QsSpecialization( kind, callableName, ImmutableArray <QsDeclarationAttribute> .Empty, this.CurrentCallable.Callable.SourceFile, QsNullable <QsLocation> .Null, QsNullable <ImmutableArray <ResolvedType> > .Null, signature, impl, ImmutableArray <string> .Empty, QsComments.Empty); var adj = this.CurrentCallable.Adjoint; var ctl = this.CurrentCallable.Controlled; var ctlAdj = this.CurrentCallable.ControlledAdjoint; bool addAdjoint = false; bool addControlled = false; bool isSelfAdjoint = false; if (this.InWithinBlock) { addAdjoint = true; addControlled = false; } else if (this.InBody) { if (adj != null && adj.Implementation is SpecializationImplementation.Generated adjGen) { addAdjoint = adjGen.Item.IsInvert; isSelfAdjoint = adjGen.Item.IsSelfInverse; } if (ctl != null && ctl.Implementation is SpecializationImplementation.Generated ctlGen) { addControlled = ctlGen.Item.IsDistribute; } if (ctlAdj != null && ctlAdj.Implementation is SpecializationImplementation.Generated ctlAdjGen) { addAdjoint = addAdjoint || (ctlAdjGen.Item.IsInvert && ctl.Implementation.IsGenerated); addControlled = addControlled || (ctlAdjGen.Item.IsDistribute && adj.Implementation.IsGenerated); isSelfAdjoint = isSelfAdjoint || ctlAdjGen.Item.IsSelfInverse; } } else if (ctlAdj != null && ctlAdj.Implementation is SpecializationImplementation.Generated gen) { addControlled = this.InAdjoint && gen.Item.IsDistribute; addAdjoint = this.InControlled && gen.Item.IsInvert; isSelfAdjoint = gen.Item.IsSelfInverse; } var props = new List <OpProperty>(); if (addAdjoint) { props.Add(OpProperty.Adjointable); } if (addControlled) { props.Add(OpProperty.Controllable); } var newSig = new ResolvedSignature( this.CurrentCallable.Callable.Signature.TypeParameters, paramsType, ResolvedType.New(ResolvedTypeKind.UnitType), new CallableInformation(ResolvedCharacteristics.FromProperties(props), new InferredCallableInformation(isSelfAdjoint, false))); var controlledSig = new ResolvedSignature( newSig.TypeParameters, ResolvedType.New(ResolvedTypeKind.NewTupleType(ImmutableArray.Create( ResolvedType.New(ResolvedTypeKind.NewArrayType(ResolvedType.New(ResolvedTypeKind.Qubit))), newSig.ArgumentType))), newSig.ReturnType, newSig.Information); var specializations = new List <QsSpecialization>() { MakeSpec(QsSpecializationKind.QsBody, newSig, bodyImplementation) }; if (addAdjoint) { specializations.Add(MakeSpec( QsSpecializationKind.QsAdjoint, newSig, SpecializationImplementation.NewGenerated(QsGeneratorDirective.Invert))); } if (addControlled) { specializations.Add(MakeSpec( QsSpecializationKind.QsControlled, controlledSig, SpecializationImplementation.NewGenerated(QsGeneratorDirective.Distribute))); } if (addAdjoint && addControlled) { specializations.Add(MakeSpec( QsSpecializationKind.QsControlledAdjoint, controlledSig, SpecializationImplementation.NewGenerated(QsGeneratorDirective.Distribute))); } return(newSig, specializations); }
/// <summary> /// Creates an operation call from the conditional control API for non-literal Result comparisons. /// The equalityScope and inequalityScope cannot both be null. /// </summary> private TypedExpression CreateApplyConditionallyExpression(TypedExpression conditionExpr1, TypedExpression conditionExpr2, QsScope equalityScope, QsScope inequalityScope) { QsCompilerError.Verify(equalityScope != null || inequalityScope != null, $"Cannot have null for both equality and inequality scopes when creating ApplyConditionally expressions."); var(isEqualityValid, equalityId, equalityArgs) = this.IsValidScope(equalityScope); var(isInequaltiyValid, inequalityId, inequalityArgs) = this.IsValidScope(inequalityScope); if (!isEqualityValid && equalityScope != null) { return(null); // ToDo: Diagnostic message - equality block exists, but is not valid } if (!isInequaltiyValid && inequalityScope != null) { return(null); // ToDo: Diagnostic message - inequality block exists, but is not valid } if (equalityScope == null) { (equalityId, equalityArgs) = this.GetNoOp(); } else if (inequalityScope == null) { (inequalityId, inequalityArgs) = this.GetNoOp(); } // Get characteristic properties from global id var props = ImmutableHashSet <OpProperty> .Empty; if (equalityId.ResolvedType.Resolution is ResolvedTypeKind.Operation op) { props = op.Item2.Characteristics.GetProperties(); if (inequalityId != null && inequalityId.ResolvedType.Resolution is ResolvedTypeKind.Operation defaultOp) { props = props.Intersect(defaultOp.Item2.Characteristics.GetProperties()); } } BuiltIn controlOpInfo; (bool adj, bool ctl) = (props.Contains(OpProperty.Adjointable), props.Contains(OpProperty.Controllable)); if (adj && ctl) { controlOpInfo = BuiltIn.ApplyConditionallyCA; } else if (adj) { controlOpInfo = BuiltIn.ApplyConditionallyA; } else if (ctl) { controlOpInfo = BuiltIn.ApplyConditionallyC; } else { controlOpInfo = BuiltIn.ApplyConditionally; } // Takes a single TypedExpression of type Result and puts in into a // value array expression with the given expression as its only item. TypedExpression BoxResultInArray(TypedExpression expression) => new TypedExpression( ExpressionKind.NewValueArray(ImmutableArray.Create(expression)), TypeArgsResolution.Empty, ResolvedType.New(ResolvedTypeKind.NewArrayType(ResolvedType.New(ResolvedTypeKind.Result))), new InferredExpressionInformation(false, expression.InferredInformation.HasLocalQuantumDependency), QsNullable <Tuple <QsPositionInfo, QsPositionInfo> > .Null); var equality = this.CreateValueTupleExpression(equalityId, equalityArgs); var inequality = this.CreateValueTupleExpression(inequalityId, inequalityArgs); var controlArgs = this.CreateValueTupleExpression( BoxResultInArray(conditionExpr1), BoxResultInArray(conditionExpr2), equality, inequality); var targetArgsTypes = ImmutableArray.Create(equalityArgs.ResolvedType, inequalityArgs.ResolvedType); return(this.CreateControlCall(controlOpInfo, props, controlArgs, targetArgsTypes)); }