private static TypedExpression IdentifierForCallable(QsQualifiedName cName, TypeKind cType) =>
 SyntaxGenerator.AutoGeneratedExpression(
     ExpressionKind.NewIdentifier(
         Identifier.NewGlobalCallable(cName),
         QsNullable <ImmutableArray <ResolvedType> > .Null),
     cType,
     false);
                /// <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);
                }
                private (TypedExpression Id, TypedExpression Args)? IsValidScope(QsScope? scope)
                {
                    // if the scope has exactly one statement in it and that statement is a call like expression statement
                    if (scope != null &&
                        scope.Statements.Length == 1 &&
                        scope.Statements[0].Statement is QsStatementKind.QsExpressionStatement expr &&
                        expr.Item.ResolvedType.Resolution.IsUnitType &&
                        expr.Item.Expression is ExpressionKind.CallLikeExpression call &&
                        !TypedExpression.IsPartialApplication(expr.Item.Expression) &&
                        call.Item1.Expression is ExpressionKind.Identifier)
                    {
                        var newCallIdentifier = call.Item1;
                        var callTypeArguments = expr.Item.TypeParameterResolutions;

                        // This relies on anything having type parameters must be a global callable.
                        if (newCallIdentifier.Expression is ExpressionKind.Identifier id &&
                            id.Item1 is Identifier.GlobalCallable global &&
                            callTypeArguments.Any())
                        {
                            // We are dissolving the application of arguments here, so the call's type argument
                            // resolutions have to be moved to the 'identifier' sub expression.
                            var combination           = new TypeResolutionCombination(expr.Item);
                            var combinedTypeArguments = combination.CombinedResolutionDictionary.FilterByOrigin(global.Item);
                            QsCompilerError.Verify(combination.IsValid, "failed to combine type parameter resolution");

                            var globalCallable = this.SharedState.Compilation.Namespaces
                                                 .Where(ns => ns.Name.Equals(global.Item.Namespace))
                                                 .Callables()
                                                 .FirstOrDefault(c => c.FullName.Name.Equals(global.Item.Name));

                            QsCompilerError.Verify(globalCallable != null, $"Could not find the global reference {global.Item}.");

                            var callableTypeParameters = globalCallable.Signature.TypeParameters.Select(param =>
                            {
                                var name = param as QsLocalSymbol.ValidName;
                                QsCompilerError.Verify(!(name is null), "Invalid type parameter name.");
                                return(name);
                            });

                            newCallIdentifier = new TypedExpression(
                                ExpressionKind.NewIdentifier(
                                    id.Item1,
                                    QsNullable <ImmutableArray <ResolvedType> > .NewValue(
                                        callableTypeParameters
                                        .Select(x => combinedTypeArguments[Tuple.Create(global.Item, x.Item)]).ToImmutableArray())),
                                TypedExpression.AsTypeArguments(combinedTypeArguments),
                                call.Item1.ResolvedType,
                                call.Item1.InferredInformation,
                                call.Item1.Range);
                        }

                        return(newCallIdentifier, call.Item2);
                    }

                    return(null);
                }
                /// <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));
                }
 internal static TypedExpression CreateIdentifierExpression(Identifier id,
                                                            TypeArgsResolution typeArgsMapping, ResolvedType resolvedType) =>
 new TypedExpression
 (
     ExpressionKind.NewIdentifier(
         id,
         typeArgsMapping.Any()
             ? QsNullable <ImmutableArray <ResolvedType> > .NewValue(typeArgsMapping
                                                                     .Select(argMapping => argMapping.Item3) // This should preserve the order of the type args
                                                                     .ToImmutableArray())
             : QsNullable <ImmutableArray <ResolvedType> > .Null),
     typeArgsMapping,
     resolvedType,
     new InferredExpressionInformation(false, false),
     QsNullable <Tuple <QsPositionInfo, QsPositionInfo> > .Null
 );
Beispiel #6
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);
            }