コード例 #1
0
 /// <summary>
 /// Creates a value tuple expression containing the given expressions.
 /// </summary>
 private TypedExpression CreateValueTupleExpression(params TypedExpression[] expressions) =>
 new TypedExpression(
     ExpressionKind.NewValueTuple(expressions.ToImmutableArray()),
     TypeArgsResolution.Empty,
     ResolvedType.New(ResolvedTypeKind.NewTupleType(expressions.Select(expr => expr.ResolvedType).ToImmutableArray())),
     new InferredExpressionInformation(false, expressions.Any(exp => exp.InferredInformation.HasLocalQuantumDependency)),
     QsNullable <Tuple <QsPositionInfo, QsPositionInfo> > .Null);
コード例 #2
0
                /// <summary>
                /// Gets an identifier and argument tuple for the built-in operation NoOp.
                /// </summary>
                private (TypedExpression, TypedExpression) GetNoOp()
                {
                    var opInfo = BuiltIn.NoOp;

                    var properties      = new[] { OpProperty.Adjointable, OpProperty.Controllable };
                    var characteristics = new CallableInformation(
                        ResolvedCharacteristics.FromProperties(properties),
                        new InferredCallableInformation(((BuiltInKind.Operation)opInfo.Kind).IsSelfAdjoint, false));

                    var unitType      = ResolvedType.New(ResolvedTypeKind.UnitType);
                    var operationType = ResolvedType.New(ResolvedTypeKind.NewOperation(
                                                             Tuple.Create(unitType, unitType),
                                                             characteristics));

                    var args = new TypedExpression(
                        ExpressionKind.UnitValue,
                        TypeArgsResolution.Empty,
                        unitType,
                        new InferredExpressionInformation(false, false),
                        QsNullable <Tuple <QsPositionInfo, QsPositionInfo> > .Null);
                    var typeArgs = ImmutableArray.Create(unitType);

                    var identifier = new TypedExpression(
                        ExpressionKind.NewIdentifier(
                            Identifier.NewGlobalCallable(opInfo.FullName),
                            QsNullable <ImmutableArray <ResolvedType> > .NewValue(typeArgs)),
                        typeArgs
                        .Zip(((BuiltInKind.Operation)opInfo.Kind).TypeParameters, (type, param) => Tuple.Create(opInfo.FullName, param, type))
                        .ToImmutableArray(),
                        operationType,
                        new InferredExpressionInformation(false, false),
                        QsNullable <Tuple <QsPositionInfo, QsPositionInfo> > .Null);

                    return(identifier, args);
                }
コード例 #3
0
 // 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);
コード例 #4
0
 public override ResolvedTypeKind OnTypeParameter(QsTypeParameter tp)
 {
     if (this.SharedState.TypeParams.TryGetValue(Tuple.Create(tp.Origin, tp.TypeName), out var typeParam))
     {
         return(typeParam.Resolution);
     }
     return(ResolvedTypeKind.NewTypeParameter(tp));
 }
コード例 #5
0
 internal static TypedExpression CreateValueTupleExpression(params TypedExpression[] expressions) =>
 new TypedExpression
 (
     ExpressionKind.NewValueTuple(expressions.ToImmutableArray()),
     TypeArgsResolution.Empty,
     ResolvedType.New(ResolvedTypeKind.NewTupleType(expressions.Select(expr => expr.ResolvedType).ToImmutableArray())),
     new InferredExpressionInformation(false, false),
     QsNullable <Tuple <QsPositionInfo, QsPositionInfo> > .Null
 );
コード例 #6
0
        internal static ResolvedType GetOperationType(IEnumerable <OpProperty> props, ResolvedType argumentType)
        {
            var characteristics = new CallableInformation(
                ResolvedCharacteristics.FromProperties(props),
                InferredCallableInformation.NoInformation);

            return(ResolvedType.New(ResolvedTypeKind.NewOperation(
                                        Tuple.Create(argumentType, ResolvedType.New(ResolvedTypeKind.UnitType)),
                                        characteristics)));
        }
コード例 #7
0
            private (QsCallable, ResolvedType) GenerateOperation(QsScope contents)
            {
                var newName = UniqueVariableNames.PrependGuid(this.CurrentCallable.Callable.FullName);

                var knownVariables = contents.KnownSymbols.Variables;

                var parameters = QsTuple <LocalVariableDeclaration <QsLocalSymbol> > .NewQsTuple(knownVariables
                                                                                                 .Select(var => QsTuple <LocalVariableDeclaration <QsLocalSymbol> > .NewQsTupleItem(new LocalVariableDeclaration <QsLocalSymbol>(
                                                                                                                                                                                        QsLocalSymbol.NewValidName(var.VariableName),
                                                                                                                                                                                        var.Type,
                                                                                                                                                                                        new InferredExpressionInformation(false, false),
                                                                                                                                                                                        var.Position,
                                                                                                                                                                                        var.Range)))
                                                                                                 .ToImmutableArray());

                var paramTypes = ResolvedType.New(ResolvedTypeKind.UnitType);

                if (knownVariables.Length == 1)
                {
                    paramTypes = knownVariables.First().Type;
                }
                else if (knownVariables.Length > 1)
                {
                    paramTypes = ResolvedType.New(ResolvedTypeKind.NewTupleType(knownVariables
                                                                                .Select(var => var.Type)
                                                                                .ToImmutableArray()));
                }

                var(signature, specializations) = this.MakeSpecializations(newName, paramTypes, SpecializationImplementation.NewProvided(parameters, contents));

                var generatedCallable = new QsCallable(
                    QsCallableKind.Operation,
                    newName,
                    ImmutableArray <QsDeclarationAttribute> .Empty,
                    new Modifiers(AccessModifier.Internal),
                    this.CurrentCallable.Callable.SourceFile,
                    QsNullable <QsLocation> .Null,
                    signature,
                    parameters,
                    specializations.ToImmutableArray(),
                    ImmutableArray <string> .Empty,
                    QsComments.Empty);

                // Change the origin of all type parameter references to use the new name and make all variables immutable
                generatedCallable = UpdateGeneratedOp.Apply(generatedCallable, knownVariables, this.CurrentCallable.Callable.FullName, newName);

                return(generatedCallable, signature.ArgumentType);
            }
コード例 #8
0
                /// <summary>
                /// Creates an operation call from the conditional control API, given information
                /// about which operation to call and with what arguments.
                /// </summary>
                private TypedExpression CreateControlCall(BuiltIn opInfo, IEnumerable <OpProperty> properties, TypedExpression args, IEnumerable <ResolvedType> typeArgs)
                {
                    var characteristics = new CallableInformation(
                        ResolvedCharacteristics.FromProperties(properties),
                        new InferredCallableInformation(((BuiltInKind.Operation)opInfo.Kind).IsSelfAdjoint, false));

                    var unitType      = ResolvedType.New(ResolvedTypeKind.UnitType);
                    var operationType = ResolvedType.New(ResolvedTypeKind.NewOperation(
                                                             Tuple.Create(args.ResolvedType, unitType),
                                                             characteristics));

                    // Build the surrounding control call
                    var identifier = new TypedExpression(
                        ExpressionKind.NewIdentifier(
                            Identifier.NewGlobalCallable(opInfo.FullName),
                            typeArgs.Any()
                            ? QsNullable <ImmutableArray <ResolvedType> > .NewValue(typeArgs.ToImmutableArray())
                            : QsNullable <ImmutableArray <ResolvedType> > .Null),
                        typeArgs
                        .Zip(((BuiltInKind.Operation)opInfo.Kind).TypeParameters, (type, param) => Tuple.Create(opInfo.FullName, param, type))
                        .ToImmutableArray(),
                        operationType,
                        new InferredExpressionInformation(false, false),
                        QsNullable <Tuple <QsPositionInfo, QsPositionInfo> > .Null);

                    // Creates type resolutions for the call expression
                    var opTypeArgResolutions = typeArgs
                                               .SelectMany(x =>
                                                           x.Resolution is ResolvedTypeKind.TupleType tup
                            ? tup.Item
                            : ImmutableArray.Create(x))
                                               .Where(x => x.Resolution.IsTypeParameter)
                                               .Select(x => (x.Resolution as ResolvedTypeKind.TypeParameter).Item)
                                               .GroupBy(x => (x.Origin, x.TypeName))
                                               .Select(group =>
                    {
                        var typeParam = group.First();
                        return(Tuple.Create(typeParam.Origin, typeParam.TypeName, ResolvedType.New(ResolvedTypeKind.NewTypeParameter(typeParam))));
                    })
                                               .ToImmutableArray();

                    return(new TypedExpression(
                               ExpressionKind.NewCallLikeExpression(identifier, args),
                               opTypeArgResolutions,
                               unitType,
                               new InferredExpressionInformation(false, true),
                               QsNullable <Tuple <QsPositionInfo, QsPositionInfo> > .Null));
                }
コード例 #9
0
 internal CallableDetails(QsCallable callable)
 {
     this.Callable = callable;
     // ToDo: this may need to be adapted once we support type specializations
     this.Adjoint = callable.Specializations.FirstOrDefault(spec => spec.Kind == QsSpecializationKind.QsAdjoint);
     this.Controlled = callable.Specializations.FirstOrDefault(spec => spec.Kind == QsSpecializationKind.QsControlled);
     this.ControlledAdjoint = callable.Specializations.FirstOrDefault(spec => spec.Kind == QsSpecializationKind.QsControlledAdjoint);
     // ToDo: this may need to be per-specialization
     this.TypeParameters = callable.Signature.TypeParameters.Any(param => param.IsValidName)
     ? QsNullable<ImmutableArray<ResolvedType>>.NewValue(callable.Signature.TypeParameters
         .Where(param => param.IsValidName)
         .Select(param =>
             ResolvedType.New(ResolvedTypeKind.NewTypeParameter(new QsTypeParameter(
                 callable.FullName,
                 ((QsLocalSymbol.ValidName)param).Item,
                 QsNullable<Range>.Null))))
         .ToImmutableArray())
     : QsNullable<ImmutableArray<ResolvedType>>.Null;
 }
コード例 #10
0
        /// <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
                   ));
        }
コード例 #11
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);
            }
コード例 #12
0
            /// <summary>
            /// Generates a new operation with the body's contents. All the known variables at the
            /// start of the block will become parameters to the new operation, and the operation
            /// will have all the valid type parameters of the calling context as type parameters.
            /// The generated operation is returned, along with a call to the new operation is
            /// also returned with all the type parameters and known variables being forwarded to
            /// the new operation as arguments.
            ///
            /// The given body should be validated with the SharedState.IsValidScope before using this function.
            /// </summary>
            public bool LiftBody(QsScope body, out QsCallable callable, out QsStatement callStatement)
            {
                if (!this.IsValidScope)
                {
                    callable      = null;
                    callStatement = null;
                    return(false);
                }

                var(generatedOp, originalArgumentType) = this.GenerateOperation(body);
                var generatedOpType = ResolvedType.New(ResolvedTypeKind.NewOperation(
                                                           Tuple.Create(
                                                               originalArgumentType,
                                                               ResolvedType.New(ResolvedTypeKind.UnitType)),
                                                           generatedOp.Signature.Information));

                // Forward the type parameters of the parent callable to the type arguments of the call to the generated operation.
                var typeArguments = this.CurrentCallable.TypeParameters;
                var generatedOpId = new TypedExpression(
                    ExpressionKind.NewIdentifier(
                        Identifier.NewGlobalCallable(generatedOp.FullName),
                        typeArguments),
                    typeArguments.IsNull
                        ? TypeArgsResolution.Empty
                        : typeArguments.Item
                    .Select(type => Tuple.Create(generatedOp.FullName, ((ResolvedTypeKind.TypeParameter)type.Resolution).Item.TypeName, type))
                    .ToImmutableArray(),
                    generatedOpType,
                    new InferredExpressionInformation(false, false),
                    QsNullable <Tuple <QsPositionInfo, QsPositionInfo> > .Null);

                var             knownSymbols = body.KnownSymbols.Variables;
                TypedExpression arguments    = null;

                if (knownSymbols.Any())
                {
                    var argumentArray = knownSymbols
                                        .Select(var => new TypedExpression(
                                                    ExpressionKind.NewIdentifier(
                                                        Identifier.NewLocalVariable(var.VariableName),
                                                        QsNullable <ImmutableArray <ResolvedType> > .Null),
                                                    TypeArgsResolution.Empty,
                                                    var.Type,
                                                    var.InferredInformation,
                                                    QsNullable <Tuple <QsPositionInfo, QsPositionInfo> > .Null))
                                        .ToImmutableArray();

                    arguments = new TypedExpression(
                        ExpressionKind.NewValueTuple(argumentArray),
                        TypeArgsResolution.Empty,
                        ResolvedType.New(ResolvedTypeKind.NewTupleType(argumentArray.Select(expr => expr.ResolvedType).ToImmutableArray())),
                        new InferredExpressionInformation(false, argumentArray.Any(exp => exp.InferredInformation.HasLocalQuantumDependency)),
                        QsNullable <Tuple <QsPositionInfo, QsPositionInfo> > .Null);
                }
                else
                {
                    arguments = new TypedExpression(
                        ExpressionKind.UnitValue,
                        TypeArgsResolution.Empty,
                        ResolvedType.New(ResolvedTypeKind.UnitType),
                        new InferredExpressionInformation(false, false),
                        QsNullable <Tuple <QsPositionInfo, QsPositionInfo> > .Null);
                }

                var call = new TypedExpression(
                    ExpressionKind.NewCallLikeExpression(generatedOpId, arguments),
                    typeArguments.IsNull
                        ? TypeArgsResolution.Empty
                        : typeArguments.Item
                    .Select(type => Tuple.Create(this.CurrentCallable.Callable.FullName, ((ResolvedTypeKind.TypeParameter)type.Resolution).Item.TypeName, type))
                    .ToImmutableArray(),
                    ResolvedType.New(ResolvedTypeKind.UnitType),
                    new InferredExpressionInformation(false, true),
                    QsNullable <Tuple <QsPositionInfo, QsPositionInfo> > .Null);

                // set output parameters
                callable      = generatedOp;
                callStatement = new QsStatement(
                    QsStatementKind.NewQsExpressionStatement(call),
                    LocalDeclarations.Empty,
                    QsNullable <QsLocation> .Null,
                    QsComments.Empty);

                return(true);
            }
コード例 #13
0
                /// <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));
                }