public static TranslationResult Constructor(List <ExpressionSharpnode> arguments, TranslationContext context, ITypeSymbol typeArgument, SyntaxNode originalNode) { var silvernodes = new List <Silvernode>(); var errors = new List <Error>(); List <StatementSilvernode> prepend = new List <Trees.Silver.StatementSilvernode>(); // Translate initial members foreach (var arg in arguments) { var res = arg.Translate(context.ChangePurityContext(PurityContext.Purifiable)); silvernodes.Add(res.Silvernode); errors.AddRange(res.Errors); prepend.AddRange(res.PrependTheseSilvernodes); } Silvernode result; if (arguments.Count == 0) { // No arguments = use the Seq[Int] construction Error err; SilverType silverType = TypeTranslator.TranslateType(typeArgument, null, out err); if (err != null) { errors.Add(err); } result = new SimpleSequenceSilvernode(originalNode, "Seq[", new TypeSilvernode(null, silverType), "]()"); } else { // Some arguments - use the Seq construction with type inference // ReSharper disable once UseObjectOrCollectionInitializer List <Silvernode> args = new List <Silvernode>(); args.Add("Seq("); for (int i = 0; i < silvernodes.Count; i++) { args.Add(silvernodes[i]); if (i != silvernodes.Count - 1) { args.Add(", "); } } args.Add(")"); result = new SimpleSequenceSilvernode(originalNode, args.ToArray()); } return(TranslationResult.FromSilvernode(result, errors).AndPrepend(prepend)); }
/// <summary> /// Translates the method or constructor. /// </summary> public TranslationResult TranslateSelf() { Identifier identifier = GetSubroutineIdentifier(); SilverKind silverKind = SilverKind.Method; TranslationResult result = new TranslationResult(); bool isAbstract = false; // Determine whether it should be translated at all. var attributes = this.MethodSymbol.GetAttributes(); switch (VerificationSettings.ShouldVerify(attributes, this.Context.VerifyUnmarkedItems)) { case VerificationSetting.DoNotVerify: return(TranslationResult.FromSilvernode(new SinglelineCommentSilvernode($"Method {this.MethodSymbol.GetQualifiedName()} skipped because it was marked [Unverified].", this.OriginalNode))); case VerificationSetting.Contradiction: return(TranslationResult.Error(this.OriginalNode, Diagnostics.SSIL113_VerificationSettingsContradiction)); case VerificationSetting.Verify: break; default: throw new InvalidOperationException("Nonexistent verification settings."); } // Determine whether it will result in a predicate, function or method, and whether it's abstract. foreach (var attribute in attributes) { switch (attribute.AttributeClass.GetQualifiedName()) { case ContractsTranslator.PredicateAttribute: if (silverKind == SilverKind.Method && !this.IsConstructor) { silverKind = SilverKind.Predicate; } else { return(TranslationResult.Error(this.OriginalNode, Diagnostics.SSIL116_MethodAttributeContradiction)); } break; case ContractsTranslator.PureAttribute: if (silverKind == SilverKind.Method && !this.IsConstructor) { silverKind = SilverKind.Function; } else { return(TranslationResult.Error(this.OriginalNode, Diagnostics.SSIL116_MethodAttributeContradiction)); } break; case ContractsTranslator.AbstractAttribute: case ContractsTranslator.SignatureOnlyAttribute: if (this.IsConstructor) { return(TranslationResult.Error(this.OriginalNode, Diagnostics.SSIL117_ConstructorMustNotBeAbstract)); } isAbstract = true; break; // Ignore other attributes. } } if (Context.MarkEverythingAbstract) { isAbstract = true; } // Translate the method body TranslationContext bodyContext = this.Context; if (silverKind == SilverKind.Function || silverKind == SilverKind.Predicate) { bodyContext = new TranslationContext(this.Context) { IsFunctionOrPredicateBlock = true, PurityContext = PurityContext.PureOrFail }; } TranslationResult body = this.BodySharpnode.Translate(bodyContext); result.Errors.AddRange(body.Errors); // Translate parameters var silverParameters = new List <ParameterSilvernode>(); if (!this.IsConstructor && !this.MethodSymbol.IsStatic) { silverParameters.Add(new ParameterSilvernode(new Identifier(Constants.SilverThis), new TypeSilvernode(null, SilverType.Ref), null)); } for (int i = 0; i < this.Parameters.Count; i++) { ParameterSharpnode sharpnode = this.Parameters[i]; var symbol = this.MethodSymbol.Parameters[i]; var rrs = sharpnode.Translate(this.Context, symbol); silverParameters.Add(rrs.Silvernode as ParameterSilvernode); result.Errors.AddRange(rrs.Errors); } // Prepare silvernodes before composing them var silName = new IdentifierSilvernode(identifier); var silOriginalnode = this.OriginalNode; var silParameters = silverParameters; string silReturnValueName = Constants.SilverReturnVariableName; if (this.IsConstructor) { silReturnValueName = Constants.SilverThis; } if (silverKind != SilverKind.Method) { silReturnValueName = "result"; // "result" is a Silver keyword } Error diagnostic; SilverType silverReturnType = TypeTranslator.TranslateType(this.IsConstructor ? this.ConstructorClass : this.MethodSymbol.ReturnType, null, out diagnostic); if (diagnostic != null) { result.Errors.Add(diagnostic); } var silTypeSilvernode = new TypeSilvernode(null, silverReturnType); var silVerificationConditions = body.Contracts; var silBlock = body.Silvernode as BlockSilvernode; // Error checking if (silverReturnType == SilverType.Void && silverKind == SilverKind.Function) { return(TranslationResult.Error(this.OriginalNode, Diagnostics.SSIL118_FunctionsMustHaveAReturnType)); } if (silverReturnType != SilverType.Bool && silverKind == SilverKind.Predicate) { return(TranslationResult.Error(this.OriginalNode, Diagnostics.SSIL119_PredicateMustBeBool)); } // Constructors first need to call the initializer if (this.IsConstructor) { silBlock.Prepend(new AssignmentSilvernode(Constants.SilverThis, new CallSilvernode(this.Context.Process.IdentifierTranslator.GetIdentifierReferenceWithTag(this.ConstructorClass, Constants.InitializerTag), new List <Silvernode>(), SilverType.Ref, null), null)); } // Methods need "label end" at the end; this may be removed by optimization further in the translation process if (silverKind == SilverKind.Method) { silBlock.Add(new LabelSilvernode(Constants.SilverMethodEndLabel, null)); } // Put it all together switch (silverKind) { case SilverKind.Method: result.Silvernode = new MethodSilvernode(silOriginalnode, silName, silParameters, silReturnValueName, silTypeSilvernode, silVerificationConditions, isAbstract ? null : silBlock); break; case SilverKind.Function: result.Silvernode = new FunctionSilvernode(silOriginalnode, silName, silParameters, silReturnValueName, silTypeSilvernode, silVerificationConditions, isAbstract ? null : silBlock); break; case SilverKind.Predicate: result.Silvernode = new PredicateSilvernode(silOriginalnode, silName, silParameters, silReturnValueName, silTypeSilvernode, silVerificationConditions, isAbstract ? null : silBlock); break; default: throw new InvalidOperationException("Nonexistent silverkind."); } return(result); }