Exemple #1
0
        /// <summary>
        /// Translates a C# type into a Silver type.
        /// </summary>
        /// <param name="typeSymbol">A C# type.</param>
        /// <param name="where">A syntaxnode for error diagnostic if the type is not supported in Silver.</param>
        /// <param name="error">This error is triggered if the type is not supported in Silver.</param>
        /// <returns>Silver name for the type.</returns>
        public static SilverType TranslateType(ITypeSymbol typeSymbol, SyntaxNode where, out Error error)
        {
            error = null;
            if (typeSymbol == null)
            {
                error = new Error(Diagnostics.SSIL204_OtherLocalizedError, where, "Unknown type (is the type declared in a file submitted to Soothsharp?)");
                return(SilverType.Error);
            }
            switch (typeSymbol.GetQualifiedName())
            {
            case "System.Int32":
            case "System.Byte":
            case "System.SByte":
            case "System.Int16":
            case "System.UInt16":
            case "System.UInt32":
            case "System.Int64":
            case "System.UInt64":
                return(SilverType.Int);

            case "System.Boolean":
                return(SilverType.Bool);

            case "System.Single":
            case "System.Double":
            case "System.Decimal":
            case "System.Char":
                error = new Error(Diagnostics.SSIL106_TypeNotSupported, where, typeSymbol.GetQualifiedName());
                return(SilverType.Error);

            case ContractsTranslator.PermissionType:
                return(SilverType.Perm);

            case "System.Void":
                return(SilverType.Void);

            case SeqTranslator.SeqClassWithoutEndDot:
                INamedTypeSymbol namedType = (INamedTypeSymbol)typeSymbol;
                var firstTypeArgument      = namedType.TypeArguments[0];
                return(SilverType.Seq(TranslateType(firstTypeArgument, where, out error)));

            default:
                if (typeSymbol.TypeKind == TypeKind.Enum)
                {
                    return(SilverType.Int);
                }
                return(SilverType.Ref);
            }
        }
Exemple #2
0
        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>
        /// This is called when an invocation sharpnode determines that this silvernode must be a statement in Viper code; this method
        /// then, if in <see cref="PurityContext.PureOrFail"/> context, changes this result into an error; or, if in <see cref="PurityContext.Purifiable"/>
        /// context, moves this result's <see cref="Silvernode"/> to <see cref="PrependTheseSilvernodes"/> and performs the prepending.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="type">The Silver type of this silvernode.</param>
        /// <param name="impurityReason">The reason why this silvernode must be a statement.</param>
        internal void AsImpureAssertion(TranslationContext context, SilverType type, string impurityReason)
        {
            switch (context.PurityContext)
            {
            case PurityContext.PureOrFail:
                this.Errors.Add(new Error(Diagnostics.SSIL114_NotPureContext, this.Silvernode.OriginalNode, impurityReason));
                break;

            case PurityContext.Purifiable:
                var newTempVar           = context.Process.IdentifierTranslator.RegisterNewUniqueIdentifier();
                VarStatementSilvernode v = new VarStatementSilvernode(newTempVar, type, null);
                AssignmentSilvernode   a = new AssignmentSilvernode(new IdentifierSilvernode(newTempVar),
                                                                    this.Silvernode, null);
                this.PrependTheseSilvernodes.Add(v);
                this.PrependTheseSilvernodes.Add(a);
                this.Silvernode = new IdentifierSilvernode(newTempVar);
                break;

            case PurityContext.PurityNotRequired:
                break;
            }
        }
Exemple #4
0
        /// <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);
        }