public void FormattedBookByName_ReturnsCorrectResult() { Book b = new Book("1", "name1", "author1", "publisher1", 2019, 100, 10); string expectedString = "Book: Name - name1"; b = new NameDecorator(b); Assert.AreEqual(expectedString, b.ToString()); }
/// <summary> /// Adds a TargetInstruction attribute to each intrinsic callable that doesn't have one, /// unless the automatically determined target instruction name conflicts with another target instruction name. /// The automatically determined name of the target instruction is the lower case version of the unqualified callable name. /// Type constructors and generic callables are left unchanged. /// </summary> /// <returns>Returns true if all missing attributes have been successfully added and false if some attributes could not be added.</returns> /// <exception cref="InvalidOperationException">All intrinsic callables need to have exactly one body specialization.</exception> public static bool TryAddMissingTargetInstructionAttributes(QsCompilation compilation, out QsCompilation transformed) { var success = true; List <string> instructionNames = new List <string>(); // populate the intruction names with all manually specified ones first foreach (var callable in compilation.Namespaces.Callables()) { var manuallySpecified = SymbolResolution.TryGetTargetInstructionName(callable.Attributes); if (manuallySpecified.IsValue) { instructionNames.Add(manuallySpecified.Item); } } QsCallable AddAttribute(QsCallable callable) { if (callable.Specializations.Length != 1) { throw new InvalidOperationException("intrinsic callable needs to have exactly one body specialization"); } var instructionName = callable.FullName.Name.ToLowerInvariant(); if (instructionNames.Contains(instructionName)) { success = false; return(callable); } return(callable.AddAttribute( AttributeUtils.BuildAttribute( BuiltIn.TargetInstruction.FullName, AttributeUtils.StringArgument(instructionName)))); } QsNamespace AddAttributes(QsNamespace ns) { var elements = ns.Elements.Select(element => element is QsNamespaceElement.QsCallable callable && callable.Item.IsIntrinsic && callable.Item.Signature.TypeParameters.Length == 0 && !NameDecorator.IsAutoGeneratedName(callable.Item.FullName) && !callable.Item.Kind.IsTypeConstructor && !callable.Item.Attributes.Any(BuiltIn.DefinesTargetInstruction) ? QsNamespaceElement.NewQsCallable(AddAttribute(callable.Item)) : element); return(new QsNamespace(ns.Name, elements.ToImmutableArray(), ns.Documentation)); } var namespaces = compilation.Namespaces.Select(AddAttributes).ToImmutableArray(); transformed = new QsCompilation(namespaces, compilation.EntryPoints); return(success); }
public override QsCallable OnCallableDeclaration(QsCallable c) { var unmangledName = NameDecorator.OriginalNameFromMonomorphized(c.FullName); if (this.SharedState.Functions.BuiltIn.ContainsKey(unmangledName)) { return(c); } this.context.SetCurrentCallable(c); c = base.OnCallableDeclaration(c); this.context.SetCurrentCallable(null); return(c); }
private (QsCallable, ResolvedType) GenerateOperation(CallableDetails callable, QsScope contents) { var newName = NameDecorator.PrependGuid(callable.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(callable, newName, paramTypes, SpecializationImplementation.NewProvided(parameters, contents)); var generatedCallable = new QsCallable( QsCallableKind.Operation, newName, ImmutableArray <QsDeclarationAttribute> .Empty, Access.Internal, callable.Callable.Source, 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, callable.Callable.FullName, newName); return(generatedCallable, signature.ArgumentType); }
public void FormattedBookByAllFields_ReturnsCorrectResult() { Book b = new Book("1", "name1", "author1", "publisher1", 2019, 100, 10); string expectedString = "Book: Isbn - 1 Name - name1 Author - author1 Publisher - publisher1 " + "Year of publication - 2019 Count of page - 100 Price - 10"; b = new IsbnDecorator(b); b = new NameDecorator(b); b = new AuthorDecorator(b); b = new PublisherDecorator(b); b = new PublicationYearDecorator(b); b = new PageCountDecorator(b); b = new PriceDecorator(b); Assert.AreEqual(expectedString, b.ToString()); }
/// <summary> /// Performs Monomorphization on the given compilation. If the keepAllIntrinsics parameter /// is set to true, then unused intrinsics will not be removed from the resulting compilation. /// </summary> public static QsCompilation Apply(QsCompilation compilation, bool keepAllIntrinsics = true) { var globals = compilation.Namespaces.GlobalCallableResolutions(); var concretizations = new List <QsCallable>(); var concreteNames = new Dictionary <ConcreteCallGraphNode, QsQualifiedName>(); var nodes = new ConcreteCallGraph(compilation).Nodes // Remove specialization information so that we only deal with the full callables. // Note: this only works fine if for all nodes in the call graph, // all existing functor specializations and their dependencies are also in the call graph. .Select(n => new ConcreteCallGraphNode(n.CallableName, QsSpecializationKind.QsBody, n.ParamResolutions)) .ToImmutableHashSet(); var getAccessModifiers = new GetAccessModifiers((typeName) => GetAccessModifier(compilation.Namespaces.GlobalTypeResolutions(), typeName)); // Loop through the nodes, getting a list of concrete callables foreach (var node in nodes) { // If there is a call to an unknown callable, throw exception if (!globals.TryGetValue(node.CallableName, out QsCallable originalGlobal)) { throw new ArgumentException($"Couldn't find definition for callable: {node.CallableName}"); } if (node.ParamResolutions.Any()) { // Get concrete name var concreteName = NameDecorator.PrependGuid(node.CallableName); // Add to concrete name mapping concreteNames[node] = concreteName; // Generate the concrete version of the callable var concrete = ReplaceTypeParamImplementations.Apply(originalGlobal, node.ParamResolutions, getAccessModifiers); concretizations.Add( concrete.WithFullName(oldName => concreteName) .WithSpecializations(specs => specs.Select(spec => spec.WithParent(_ => concreteName)).ToImmutableArray())); } else { concretizations.Add(originalGlobal); } } GetConcreteIdentifierFunc getConcreteIdentifier = (globalCallable, types) => GetConcreteIdentifier(concreteNames, globalCallable, types); var intrinsicCallableSet = globals .Where(kvp => kvp.Value.Specializations.Any(spec => spec.Implementation.IsIntrinsic)) .Select(kvp => kvp.Key) .ToImmutableHashSet(); var final = new List <QsCallable>(); // Loop through concretizations, replacing all references to generics with their concrete counterparts foreach (var callable in concretizations) { final.Add(ReplaceTypeParamCalls.Apply(callable, getConcreteIdentifier, intrinsicCallableSet)); } return(ResolveGenerics.Apply(compilation, final, intrinsicCallableSet, keepAllIntrinsics)); }
/// <summary> /// Performs Monomorphization on the given compilation. If the monomorphizeIntrinsics parameter /// is set to false, then intrinsics will not be monomorphized. /// </summary> public static QsCompilation Apply(QsCompilation compilation, bool monomorphizeIntrinsics = false) { var globals = compilation.Namespaces.GlobalCallableResolutions(); var concretizations = new List <QsCallable>(); var concreteNamesMap = new Dictionary <ConcreteCallGraphNode, QsQualifiedName>(); var nodesWithResolutions = new ConcreteCallGraph(compilation).Nodes // Remove specialization information so that we only deal with the full callables. // Note: this only works fine if for all nodes in the call graph, // all existing functor specializations and their dependencies are also in the call graph. .Select(n => new ConcreteCallGraphNode(n.CallableName, QsSpecializationKind.QsBody, n.ParamResolutions)) .Where(n => n.ParamResolutions.Any()) .ToImmutableHashSet(); var getAccessModifiers = new GetAccessModifiers((typeName) => GetAccessModifier(compilation.Namespaces.GlobalTypeResolutions(), typeName)); // Loop through the nodes, getting a list of concrete callables foreach (var node in nodesWithResolutions) { // If there is a call to an unknown callable, throw exception if (!globals.TryGetValue(node.CallableName, out var originalGlobal)) { throw new ArgumentException($"Couldn't find definition for callable: {node.CallableName}"); } if (monomorphizeIntrinsics || !originalGlobal.IsIntrinsic) { // Get concrete name var concreteName = NameDecorator.PrependGuid(node.CallableName); // Add to concrete name mapping concreteNamesMap[node] = concreteName; // Generate the concrete version of the callable var concrete = ReplaceTypeParamImplementations.Apply(originalGlobal, node.ParamResolutions, getAccessModifiers) .WithFullName(oldName => concreteName) .WithSpecializations(specs => specs.Select(spec => spec.WithParent(_ => concreteName)).ToImmutableArray()); concretizations.Add(concrete); } } var callablesByNamespace = concretizations.ToLookup(x => x.FullName.Namespace); var namespacesWithImpls = compilation.Namespaces.Select(ns => { var elemsToAdd = callablesByNamespace[ns.Name].Select(call => QsNamespaceElement.NewQsCallable(call)); return(ns.WithElements(elems => elems .Where(elem => !(elem is QsNamespaceElement.QsCallable call) || !IsGeneric(call.Item) || (call.Item.IsIntrinsic && !monomorphizeIntrinsics) || BuiltIn.RewriteStepDependencies.Contains(call.Item.FullName)) .Concat(elemsToAdd) .ToImmutableArray())); }).ToImmutableArray(); var compWithImpls = new QsCompilation(namespacesWithImpls, compilation.EntryPoints); GetConcreteIdentifierFunc getConcreteIdentifier = (globalCallable, types) => GetConcreteIdentifier(concreteNamesMap, globalCallable, types); var intrinsicsToKeep = monomorphizeIntrinsics ? ImmutableHashSet <QsQualifiedName> .Empty : globals .Where(kvp => kvp.Value.Specializations.Any(spec => spec.Implementation.IsIntrinsic)) .Select(kvp => kvp.Key) .ToImmutableHashSet(); return(ReplaceTypeParamCalls.Apply(compWithImpls, getConcreteIdentifier, intrinsicsToKeep)); }