///// <summary>
    ///// Use this constructor for translating expressions that do *not* occur
    ///// within the context of the statements in a method body.
    ///// </summary>
    //public ExpressionTraverser(Sink sink)
    //  : this(sink, null)
    //{ }

    /// <summary>
    /// Use this constructor for translating expressions that do occur within
    /// the context of the statements in a method body.
    /// </summary>
    public ExpressionTraverser(Sink sink, StatementTraverser/*?*/ statementTraverser, bool contractContext, bool expressionIsStatement)
    {
      this.sink = sink;
      this.StmtTraverser = statementTraverser;
      TranslatedExpressions = new Stack<Bpl.Expr>();

      this.contractContext = contractContext;
      this.currentExpressionIsOpAssignStatement = expressionIsStatement;
    }
        /// <summary>
        ///
        /// </summary>
        /// <remarks>(mschaef) Works, but still a stub</remarks>
        /// <param name="conditionalStatement"></param>
        public override void TraverseChildren(IConditionalStatement conditionalStatement)
        {
            StatementTraverser  thenTraverser = this.factory.MakeStatementTraverser(this.sink, this.PdbReader, this.contractContext);
            StatementTraverser  elseTraverser = this.factory.MakeStatementTraverser(this.sink, this.PdbReader, this.contractContext);
            ExpressionTraverser condTraverser = this.factory.MakeExpressionTraverser(this.sink, this, this.contractContext);

            if (this.sink.Options.instrumentBranches)
            {
                var tok = conditionalStatement.Token();
                thenTraverser.StmtBuilder.Add(
                    new Bpl.AssumeCmd(tok, Bpl.Expr.True, new Bpl.QKeyValue(Bpl.Token.NoToken, "breadcrumb", new List <object> {
                    Bpl.Expr.Literal(this.sink.UniqueNumberAcrossAllAssemblies)
                }, null))
                    );
                elseTraverser.StmtBuilder.Add(
                    new Bpl.AssumeCmd(tok, Bpl.Expr.True, new Bpl.QKeyValue(Bpl.Token.NoToken, "breadcrumb", new List <object> {
                    Bpl.Expr.Literal(this.sink.UniqueNumberAcrossAllAssemblies)
                }, null))
                    );
            }

            condTraverser.Traverse(conditionalStatement.Condition);
            thenTraverser.Traverse(conditionalStatement.TrueBranch);
            elseTraverser.Traverse(conditionalStatement.FalseBranch);

            Bpl.Expr conditionExpr = condTraverser.TranslatedExpressions.Pop();
            Bpl.Type conditionType = this.sink.CciTypeToBoogie(conditionalStatement.Condition.Type);
            if (conditionType == this.sink.Heap.RefType)
            {
                conditionExpr = Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Neq, conditionExpr, Bpl.Expr.Ident(this.sink.Heap.NullRef));
            }
            else if (conditionType == Bpl.Type.Int)
            {
                conditionExpr = Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Neq, conditionExpr, Bpl.Expr.Literal(0));
            }
            else
            {
                System.Diagnostics.Debug.Assert(conditionType == Bpl.Type.Bool);
            }

            Bpl.IfCmd ifcmd = new Bpl.IfCmd(conditionalStatement.Token(),
                                            conditionExpr,
                                            thenTraverser.StmtBuilder.Collect(conditionalStatement.TrueBranch.Token()),
                                            null,
                                            elseTraverser.StmtBuilder.Collect(conditionalStatement.FalseBranch.Token())
                                            );

            StmtBuilder.Add(ifcmd);
        }
예제 #3
0
        /// <summary>
        ///
        /// </summary>
        public override void TraverseChildren(IMethodDefinition method)
        {
            if (TranslationHelper.HasAttribute(method, "BCTOmitAttribute"))
            {
                return;
            }

            if (method.IsStaticConstructor)
            {
                this.sawCctor = true;
            }

            bool isEventAddOrRemove = method.IsSpecialName && (method.Name.Value.StartsWith("add_") || method.Name.Value.StartsWith("remove_"));

            if (isEventAddOrRemove)
            {
                return;
            }


            Sink.ProcedureInfo procInfo;
            IMethodDefinition  stubMethod = null;

            if (IsStubMethod(method, out stubMethod))
            {
                procInfo = this.sink.FindOrCreateProcedure(stubMethod);
            }
            else
            {
                procInfo = this.sink.FindOrCreateProcedure(method);
            }

            if (method.IsAbstract || method.IsExternal || TranslationHelper.HasAttribute(method, "BCTOmitImplementationAttribute")
                // CCI is currently hacked to skip decompiling all method bodies in
                // compiler-generated classes.  This is nontrivial to test for here, so
                // just omit implementation of all methods whose bodies haven't been
                // decompiled, at risk of silently hiding other problems.
                || !(method.Body is ISourceMethodBody))
            {
                // we're done, just define the procedure
                return;
            }

            this.sink.BeginMethod(method);
            var decl      = procInfo.Decl;
            var proc      = decl as Bpl.Procedure;
            var formalMap = procInfo.FormalMap;

            if (this.entryPoint != null && method.InternedKey == this.entryPoint.InternedKey)
            {
                decl.AddAttribute("entrypoint");
            }

            try {
                StatementTraverser stmtTraverser = this.Factory.MakeStatementTraverser(this.sink, this.PdbReader, false);

                // Manually set the beginning of the method as the source location for
                // BCT synthetic code until we traverse the first real statement, which
                // will automatically pick up its source location.  Needed for record
                // calls to show up in the trace.
                stmtTraverser.EmitSourceContext(method);

                if (!method.IsStatic)
                {
                    stmtTraverser.AddRecordCall("this",
                                                sink.CciTypeToBoogie(method.ContainingType),
                                                new Bpl.IdentifierExpr(Bpl.Token.NoToken, sink.ThisVariable));
                }

                #region Add assignments from In-Params to local-Params

                foreach (MethodParameter mparam in formalMap)
                {
                    if (mparam.inParameterCopy != null)
                    {
                        Bpl.IToken tok = method.Token();
                        Bpl.Expr   rhs = new Bpl.IdentifierExpr(tok, mparam.inParameterCopy);
                        stmtTraverser.AddRecordCall(mparam.underlyingParameter.Name.Value,
                                                    mparam.inParameterCopy.TypedIdent.Type, rhs);
                        stmtTraverser.StmtBuilder.Add(Bpl.Cmd.SimpleAssign(tok,
                                                                           new Bpl.IdentifierExpr(tok, mparam.outParameterCopy), rhs));
                    }
                }

                #endregion

                #region For non-deferring ctors and all cctors, initialize all fields to null-equivalent values
                var inits = InitializeFieldsInConstructor(method);
                if (0 < inits.Count)
                {
                    foreach (var s in inits)
                    {
                        stmtTraverser.Traverse(s);
                    }
                }
                #endregion

                #region Translate method attributes
                // Don't need an expression translator because there is a limited set of things
                // that can appear as arguments to custom attributes
                // TODO: decode enum values
                try {
                    foreach (var a in method.Attributes)
                    {
                        var attrName = TypeHelper.GetTypeName(a.Type);
                        if (attrName.EndsWith("Attribute"))
                        {
                            attrName = attrName.Substring(0, attrName.Length - 9);
                        }
                        var args = new List <object>();
                        foreach (var c in a.Arguments)
                        {
                            var mdc = c as IMetadataConstant;
                            if (mdc != null)
                            {
                                object o;
                                if (mdc.Type.IsEnum)
                                {
                                    var lit = Bpl.Expr.Literal((int)mdc.Value);
                                    lit.Type = Bpl.Type.Int;
                                    o        = lit;
                                }
                                else
                                {
                                    switch (mdc.Type.TypeCode)
                                    {
                                    case PrimitiveTypeCode.Boolean:
                                        o = (bool)mdc.Value ? Bpl.Expr.True : Bpl.Expr.False;
                                        break;

                                    case PrimitiveTypeCode.Int32:
                                        var lit = Bpl.Expr.Literal((int)mdc.Value);
                                        lit.Type = Bpl.Type.Int;
                                        o        = lit;
                                        break;

                                    case PrimitiveTypeCode.String:
                                        o = mdc.Value;
                                        break;

                                    default:
                                        throw new InvalidCastException("Invalid metadata constant type");
                                    }
                                }
                                args.Add(o);
                            }
                        }
                        decl.AddAttribute(attrName, args.ToArray());
                    }
                } catch (InvalidCastException) {
                    Console.WriteLine("Warning: Cannot translate custom attributes for method\n    '{0}':",
                                      MemberHelper.GetMethodSignature(method, NameFormattingOptions.None));
                    Console.WriteLine("    >>Skipping attributes, continuing with method translation");
                }
                #endregion

                #region Translate body
                var helperTypes = stmtTraverser.TranslateMethod(method);
                if (helperTypes != null)
                {
                    this.privateTypes.AddRange(helperTypes);
                }
                #endregion

                #region Create Local Vars For Implementation
                List <Bpl.Variable> vars = new List <Bpl.Variable>();
                foreach (MethodParameter mparam in formalMap)
                {
                    if (!mparam.underlyingParameter.IsByReference)
                    {
                        vars.Add(mparam.outParameterCopy);
                    }
                }
                foreach (Bpl.Variable v in this.sink.LocalVarMap.Values)
                {
                    vars.Add(v);
                }
                // LocalExcVariable holds the exception thrown by any method called from this method, even if this method swallows all exceptions
                if (0 < this.sink.Options.modelExceptions)
                {
                    vars.Add(procInfo.LocalExcVariable);
                }
                vars.Add(procInfo.LabelVariable);
                List <Bpl.Variable> vseq = new List <Bpl.Variable>(vars.ToArray());
                #endregion

                var translatedBody = stmtTraverser.StmtBuilder.Collect(Bpl.Token.NoToken);

                #region Add implementation to Boogie program
                if (proc != null)
                {
                    Bpl.Implementation impl =
                        new Bpl.Implementation(method.Token(),
                                               decl.Name,
                                               new List <Bpl.TypeVariable>(),
                                               decl.InParams,
                                               decl.OutParams,
                                               vseq,
                                               translatedBody);

                    impl.Proc = proc;
                    this.sink.TranslatedProgram.AddTopLevelDeclaration(impl);
                }
                else // method is translated as a function
                //var func = decl as Bpl.Function;
                //Contract.Assume(func != null);
                //var blocks = new List<Bpl.Block>();
                //var counter = 0;
                //var returnValue = decl.OutParams[0];
                //foreach (var bb in translatedBody.BigBlocks) {
                //  var label = bb.LabelName ?? "L" + counter++.ToString();
                //  var newTransferCmd = (bb.tc is Bpl.ReturnCmd)
                //    ? new Bpl.ReturnExprCmd(bb.tc.tok, Bpl.Expr.Ident(returnValue))
                //    : bb.tc;
                //  var b = new Bpl.Block(bb.tok, label, bb.simpleCmds, newTransferCmd);
                //  blocks.Add(b);
                //}
                //var localVars = new List<Bpl.Variable>();
                //localVars.Add(returnValue);
                //func.Body = new Bpl.CodeExpr(localVars, blocks);
                {
                }
                #endregion
            } catch (TranslationException te) {
                Console.WriteLine("Translation error in body of \n    '{0}':",
                                  MemberHelper.GetMethodSignature(method, NameFormattingOptions.None));
                Console.WriteLine("\t" + te.Message + "\n" + te.StackTrace);
            } catch (Exception e) {
                Console.WriteLine("Error encountered during translation of \n    '{0}':",
                                  MemberHelper.GetMethodSignature(method, NameFormattingOptions.None));
                Console.WriteLine("\t>>" + e.Message + "\n" + e.StackTrace);
            } finally {
            }
        }
 public virtual ExpressionTraverser MakeExpressionTraverser(Sink sink, StatementTraverser/*?*/ statementTraverser, bool contractContext, bool expressionIsOpAssignStatement = false) {
   return new ExpressionTraverser(sink, statementTraverser, contractContext, expressionIsOpAssignStatement);
 }
 public CLRExpressionSemantics(Sink sink, StatementTraverser/*?*/ statementTraverser, bool contractContext, bool expressionIsStatement)
   : base(sink, statementTraverser, contractContext, expressionIsStatement) { }
 public override ExpressionTraverser MakeExpressionTraverser(Sink sink, StatementTraverser/*?*/ statementTraverser, bool contractContext, bool expressionIsStatement) {
   return new CLRExpressionSemantics(sink, statementTraverser, contractContext, expressionIsStatement);
 }
예제 #7
0
        /// <summary>
        ///
        /// </summary>
        public override void TraverseChildren(IMethodDefinition method)
        {
            if (method.IsStaticConstructor)
            {
                this.sawCctor = true;
            }

            bool isEventAddOrRemove = method.IsSpecialName && (method.Name.Value.StartsWith("add_") || method.Name.Value.StartsWith("remove_"));

            if (isEventAddOrRemove)
            {
                return;
            }


            Sink.ProcedureInfo procInfo;
            IMethodDefinition  stubMethod = null;

            if (IsStubMethod(method, out stubMethod))
            {
                procInfo = this.sink.FindOrCreateProcedure(stubMethod);
            }
            else
            {
                procInfo = this.sink.FindOrCreateProcedure(method);
            }

            if (method.IsAbstract || method.IsExternal) // we're done, just define the procedure
            {
                return;
            }

            this.sink.BeginMethod(method);
            var decl      = procInfo.Decl;
            var proc      = decl as Bpl.Procedure;
            var formalMap = procInfo.FormalMap;

            if (this.entryPoint != null && method.InternedKey == this.entryPoint.InternedKey)
            {
                decl.AddAttribute("entrypoint");
            }

            // FEEDBACK inline handler methods to avoid more false alarms
            if (PhoneCodeHelper.instance().PhoneFeedbackToggled&& PhoneCodeHelper.instance().isMethodInputHandlerOrFeedbackOverride(method) &&
                !PhoneCodeHelper.instance().isMethodIgnoredForFeedback(method))
            {
                proc.AddAttribute("inline", new Bpl.LiteralExpr(Bpl.Token.NoToken, Microsoft.Basetypes.BigNum.ONE));
                PhoneCodeHelper.instance().trackCallableMethod(proc);
            }

            try {
                StatementTraverser stmtTraverser = this.Factory.MakeStatementTraverser(this.sink, this.PdbReader, false);

                // FEEDBACK if this is a feedback method it will be plagued with false asserts. They will trigger if $Exception becomes other than null
                // FEEDBACK for modular analysis we need it to be non-null at the start
                // FEEDBACK also, callee is obviously non null
                IMethodDefinition translatedMethod = sink.getMethodBeingTranslated();
                if (PhoneCodeHelper.instance().PhoneFeedbackToggled&& translatedMethod != null &&
                    PhoneCodeHelper.instance().isMethodInputHandlerOrFeedbackOverride(translatedMethod))
                {
                    // assign null to exception
                    List <Bpl.AssignLhs> assignee          = new List <Bpl.AssignLhs>();
                    Bpl.AssignLhs        exceptionAssignee = new Bpl.SimpleAssignLhs(Bpl.Token.NoToken, Bpl.Expr.Ident(this.sink.Heap.ExceptionVariable));
                    assignee.Add(exceptionAssignee);
                    List <Bpl.Expr> value = new List <Bpl.Expr>();
                    value.Add(Bpl.Expr.Ident(this.sink.Heap.NullRef));
                    Bpl.Cmd exceptionAssign = new Bpl.AssignCmd(Bpl.Token.NoToken, assignee, value);
                    stmtTraverser.StmtBuilder.Add(exceptionAssign);
                }

                #region Add assignments from In-Params to local-Params

                foreach (MethodParameter mparam in formalMap)
                {
                    if (mparam.inParameterCopy != null)
                    {
                        Bpl.IToken tok = method.Token();
                        stmtTraverser.StmtBuilder.Add(Bpl.Cmd.SimpleAssign(tok,
                                                                           new Bpl.IdentifierExpr(tok, mparam.outParameterCopy),
                                                                           new Bpl.IdentifierExpr(tok, mparam.inParameterCopy)));
                    }
                }

                #endregion

                #region For non-deferring ctors and all cctors, initialize all fields to null-equivalent values
                var inits = InitializeFieldsInConstructor(method);
                if (0 < inits.Count)
                {
                    foreach (var s in inits)
                    {
                        stmtTraverser.Traverse(s);
                    }
                }
                #endregion

                #region Translate method attributes
                // Don't need an expression translator because there is a limited set of things
                // that can appear as arguments to custom attributes
                // TODO: decode enum values
                try {
                    foreach (var a in method.Attributes)
                    {
                        var attrName = TypeHelper.GetTypeName(a.Type);
                        if (attrName.EndsWith("Attribute"))
                        {
                            attrName = attrName.Substring(0, attrName.Length - 9);
                        }
                        var args = new List <object>();
                        foreach (var c in a.Arguments)
                        {
                            var mdc = c as IMetadataConstant;
                            if (mdc != null)
                            {
                                object o;
                                if (mdc.Type.IsEnum)
                                {
                                    var lit = Bpl.Expr.Literal((int)mdc.Value);
                                    lit.Type = Bpl.Type.Int;
                                    o        = lit;
                                }
                                else
                                {
                                    switch (mdc.Type.TypeCode)
                                    {
                                    case PrimitiveTypeCode.Boolean:
                                        o = (bool)mdc.Value ? Bpl.Expr.True : Bpl.Expr.False;
                                        break;

                                    case PrimitiveTypeCode.Int32:
                                        var lit = Bpl.Expr.Literal((int)mdc.Value);
                                        lit.Type = Bpl.Type.Int;
                                        o        = lit;
                                        break;

                                    case PrimitiveTypeCode.String:
                                        o = mdc.Value;
                                        break;

                                    default:
                                        throw new InvalidCastException("Invalid metadata constant type");
                                    }
                                }
                                args.Add(o);
                            }
                        }
                        decl.AddAttribute(attrName, args.ToArray());
                    }
                } catch (InvalidCastException) {
                    Console.WriteLine("Warning: Cannot translate custom attributes for method\n    '{0}':",
                                      MemberHelper.GetMethodSignature(method, NameFormattingOptions.None));
                    Console.WriteLine("    >>Skipping attributes, continuing with method translation");
                }
                #endregion

                #region Translate body
                var helperTypes = stmtTraverser.TranslateMethod(method);
                if (helperTypes != null)
                {
                    this.privateTypes.AddRange(helperTypes);
                }
                #endregion

                #region Create Local Vars For Implementation
                List <Bpl.Variable> vars = new List <Bpl.Variable>();
                foreach (MethodParameter mparam in formalMap)
                {
                    if (!mparam.underlyingParameter.IsByReference)
                    {
                        vars.Add(mparam.outParameterCopy);
                    }
                }
                foreach (Bpl.Variable v in this.sink.LocalVarMap.Values)
                {
                    vars.Add(v);
                }
                // LocalExcVariable holds the exception thrown by any method called from this method, even if this method swallows all exceptions
                if (0 < this.sink.Options.modelExceptions)
                {
                    vars.Add(procInfo.LocalExcVariable);
                }
                vars.Add(procInfo.LabelVariable);
                List <Bpl.Variable> vseq = new List <Bpl.Variable>(vars.ToArray());
                #endregion

                var translatedBody = stmtTraverser.StmtBuilder.Collect(Bpl.Token.NoToken);

                #region Add implementation to Boogie program
                if (proc != null)
                {
                    Bpl.Implementation impl =
                        new Bpl.Implementation(method.Token(),
                                               decl.Name,
                                               new List <Bpl.TypeVariable>(),
                                               decl.InParams,
                                               decl.OutParams,
                                               vseq,
                                               translatedBody);

                    impl.Proc = proc;
                    this.sink.TranslatedProgram.AddTopLevelDeclaration(impl);
                }
                else // method is translated as a function
                //var func = decl as Bpl.Function;
                //Contract.Assume(func != null);
                //var blocks = new List<Bpl.Block>();
                //var counter = 0;
                //var returnValue = decl.OutParams[0];
                //foreach (var bb in translatedBody.BigBlocks) {
                //  var label = bb.LabelName ?? "L" + counter++.ToString();
                //  var newTransferCmd = (bb.tc is Bpl.ReturnCmd)
                //    ? new Bpl.ReturnExprCmd(bb.tc.tok, Bpl.Expr.Ident(returnValue))
                //    : bb.tc;
                //  var b = new Bpl.Block(bb.tok, label, bb.simpleCmds, newTransferCmd);
                //  blocks.Add(b);
                //}
                //var localVars = new List<Bpl.Variable>();
                //localVars.Add(returnValue);
                //func.Body = new Bpl.CodeExpr(localVars, blocks);
                {
                }
                #endregion
            } catch (TranslationException te) {
                Console.WriteLine("Translation error in body of \n    '{0}':",
                                  MemberHelper.GetMethodSignature(method, NameFormattingOptions.None));
                Console.WriteLine("\t" + te.Message);
            } catch (Exception e) {
                Console.WriteLine("Error encountered during translation of \n    '{0}':",
                                  MemberHelper.GetMethodSignature(method, NameFormattingOptions.None));
                Console.WriteLine("\t>>" + e.Message);
            } finally {
            }
        }
 public virtual ExpressionTraverser MakeExpressionTraverser(Sink sink, StatementTraverser /*?*/ statementTraverser, bool contractContext, bool expressionIsOpAssignStatement = false)
 {
     return(new ExpressionTraverser(sink, statementTraverser, contractContext, expressionIsOpAssignStatement));
 }
 public SourceContextEmitter(StatementTraverser parent)
 {
     this.parent = parent;
 }
예제 #10
0
 public override ExpressionTraverser MakeExpressionTraverser(Sink sink, StatementTraverser /*?*/ statementTraverser, bool contractContext, bool expressionIsStatement)
 {
     return(new CLRExpressionSemantics(sink, statementTraverser, contractContext, expressionIsStatement));
 }
예제 #11
0
 public CLRExpressionSemantics(Sink sink, StatementTraverser /*?*/ statementTraverser, bool contractContext, bool expressionIsStatement)
     : base(sink, statementTraverser, contractContext, expressionIsStatement)
 {
 }
예제 #12
0
 public CLRExpressionSemantics(Sink sink, StatementTraverser/*?*/ statementTraverser)
   : base(sink, statementTraverser) { }
예제 #13
0
 public override ExpressionTraverser MakeExpressionTraverser(Sink sink, StatementTraverser/*?*/ statementTraverser) {
   return new CLRExpressionSemantics(sink, statementTraverser);
 }
예제 #14
0
 public WholeProgramExpressionSemantics(WholeProgram parent, Sink sink, StatementTraverser /*?*/ statementTraverser, bool contractContext, bool expressionIsStatement)
     : base(sink, statementTraverser, contractContext, expressionIsStatement)
 {
     this.parent   = parent;
     this.subTypes = parent.subTypes;
 }
예제 #15
0
 public virtual ExpressionTraverser MakeExpressionTraverser(Sink sink, StatementTraverser/*?*/ statementTraverser) { return new ExpressionTraverser(sink, statementTraverser); }
        public override void TraverseChildren(ITryCatchFinallyStatement tryCatchFinallyStatement)
        {
            if (this.sink.Options.modelExceptions == 0)
            {
                this.Traverse(tryCatchFinallyStatement.TryBody);
                if (tryCatchFinallyStatement.FinallyBody != null)
                {
                    this.Traverse(tryCatchFinallyStatement.FinallyBody);
                }
                return;
            }

            this.sink.nestedTryCatchFinallyStatements.Add(new Tuple <ITryCatchFinallyStatement, Sink.TryCatchFinallyContext>(tryCatchFinallyStatement, Sink.TryCatchFinallyContext.InTry));
            this.Traverse(tryCatchFinallyStatement.TryBody);
            StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(this.sink.LabelVariable), Bpl.Expr.Literal(-1)));
            StmtBuilder.Add(new Bpl.GotoCmd(Bpl.Token.NoToken, new List <string>(new string[] { this.sink.FindOrCreateFinallyLabel(tryCatchFinallyStatement) })));
            this.sink.nestedTryCatchFinallyStatements.RemoveAt(this.sink.nestedTryCatchFinallyStatements.Count - 1);

            StmtBuilder.AddLabelCmd(this.sink.FindOrCreateCatchLabel(tryCatchFinallyStatement));
            StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(this.sink.LocalExcVariable), Bpl.Expr.Ident(this.sink.Heap.ExceptionVariable)));
            StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(this.sink.Heap.ExceptionVariable), Bpl.Expr.Ident(this.sink.Heap.NullRef)));
            List <Bpl.StmtList> catchStatements = new List <Bpl.StmtList>();
            List <Bpl.Expr>     typeReferences  = new List <Bpl.Expr>();

            this.sink.nestedTryCatchFinallyStatements.Add(new Tuple <ITryCatchFinallyStatement, Sink.TryCatchFinallyContext>(tryCatchFinallyStatement, Sink.TryCatchFinallyContext.InCatch));
            foreach (ICatchClause catchClause in tryCatchFinallyStatement.CatchClauses)
            {
                typeReferences.Insert(0, this.sink.FindOrCreateTypeReference(catchClause.ExceptionType, true));
                StatementTraverser catchTraverser = this.factory.MakeStatementTraverser(this.sink, this.PdbReader, this.contractContext);
                if (catchClause.ExceptionContainer != Dummy.LocalVariable)
                {
                    Bpl.Variable catchClauseVariable = this.sink.FindOrCreateLocalVariable(catchClause.ExceptionContainer);
                    catchTraverser.StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(catchClauseVariable), Bpl.Expr.Ident(this.sink.LocalExcVariable)));
                }
                catchTraverser.Traverse(catchClause.Body);
                catchTraverser.StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(this.sink.LabelVariable), Bpl.Expr.Literal(-1)));
                catchTraverser.StmtBuilder.Add(new Bpl.GotoCmd(Bpl.Token.NoToken, new List <string>(new string[] { this.sink.FindOrCreateFinallyLabel(tryCatchFinallyStatement) })));
                catchStatements.Insert(0, catchTraverser.StmtBuilder.Collect(catchClause.Token()));
            }
            Bpl.IfCmd elseIfCmd        = new Bpl.IfCmd(Bpl.Token.NoToken, Bpl.Expr.Literal(false), TranslationHelper.BuildStmtList(new Bpl.ReturnCmd(Bpl.Token.NoToken)), null, null);
            Bpl.Expr  dynTypeOfOperand = this.sink.Heap.DynamicType(Bpl.Expr.Ident(this.sink.LocalExcVariable));
            for (int i = 0; i < catchStatements.Count; i++)
            {
                Bpl.Expr expr = new Bpl.NAryExpr(Bpl.Token.NoToken, new Bpl.FunctionCall(this.sink.Heap.Subtype), new List <Bpl.Expr>(new Bpl.Expr[] { dynTypeOfOperand, typeReferences[i] }));
                elseIfCmd = new Bpl.IfCmd(Bpl.Token.NoToken, expr, catchStatements[i], elseIfCmd, null);
            }
            this.StmtBuilder.Add(elseIfCmd);
            this.StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(this.sink.Heap.ExceptionVariable), Bpl.Expr.Ident(this.sink.LocalExcVariable)));
            RaiseException();
            this.sink.nestedTryCatchFinallyStatements.RemoveAt(this.sink.nestedTryCatchFinallyStatements.Count - 1);

            this.StmtBuilder.AddLabelCmd(this.sink.FindOrCreateFinallyLabel(tryCatchFinallyStatement));
            if (tryCatchFinallyStatement.FinallyBody != null)
            {
                this.sink.nestedTryCatchFinallyStatements.Add(new Tuple <ITryCatchFinallyStatement, Sink.TryCatchFinallyContext>(tryCatchFinallyStatement, Sink.TryCatchFinallyContext.InFinally));
                Bpl.Variable savedExcVariable   = this.sink.CreateFreshLocal(this.sink.Heap.RefType);
                Bpl.Variable savedLabelVariable = this.sink.CreateFreshLocal(Bpl.Type.Int);
                StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(savedExcVariable), Bpl.Expr.Ident(this.sink.Heap.ExceptionVariable)));
                StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(savedLabelVariable), Bpl.Expr.Ident(this.sink.LabelVariable)));
                this.Traverse(tryCatchFinallyStatement.FinallyBody);
                StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(this.sink.Heap.ExceptionVariable), Bpl.Expr.Ident(savedExcVariable)));
                StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(this.sink.LabelVariable), Bpl.Expr.Ident(savedLabelVariable)));
                this.sink.nestedTryCatchFinallyStatements.RemoveAt(this.sink.nestedTryCatchFinallyStatements.Count - 1);
            }
            GenerateDispatchContinuation(tryCatchFinallyStatement);
            StmtBuilder.AddLabelCmd(this.sink.FindOrCreateContinuationLabel(tryCatchFinallyStatement));
            Bpl.Expr raiseExpr = Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Neq, Bpl.Expr.Ident(this.sink.Heap.ExceptionVariable), Bpl.Expr.Ident(this.sink.Heap.NullRef));
            RaiseException(raiseExpr);
        }
예제 #17
0
 /// <summary>
 /// Use this constructor for translating expressions that do occur within
 /// the context of the statements in a method body.
 /// </summary>
 public ExpressionTraverser(Sink sink, StatementTraverser/*?*/ statementTraverser) {
   this.sink = sink;
   HeapVariable = sink.HeapVariable;
   this.StmtTraverser = statementTraverser;
   TranslatedExpressions = new Stack<Bpl.Expr>();
 }
 public SourceContextEmitter(StatementTraverser parent) {
   this.parent = parent;
 }