// 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
                   ));
        }
Exemple #3
0
            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));
                }