/// <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);
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 );
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); }
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> /// 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); }