예제 #1
0
        public Warning(int errorCode, string error, SourceContext context)
            : base(errorCode, error, context)
        {
            // F:
            Contract.Requires(error != null);

            this.IsWarning = true;
        }
        public override void VisitStatementList(StatementList statements)
        {
            if (statements == null) return;

            for (int i = 0; i < statements.Count; i++)
            {
                var stmt = statements[i];
                if (stmt == null) continue;

                if (stmt.SourceContext.IsValid)
                {
                    this.currentSourceContext = stmt.SourceContext;
                }

                this.Visit(stmt);
            }
        }
예제 #3
0
 public override Compilation GetDummyCompilationFor(string fileName){
   if (this.dummyCompilationFor == null) this.dummyCompilationFor = new Hashtable();
   WeakReference wref = (WeakReference)this.dummyCompilationFor[fileName];
   if (wref != null && wref.IsAlive) return (Compilation)wref.Target;
   string fContents = null;
   if (File.Exists(fileName)){
     StreamReader sr = new StreamReader(fileName);
     fContents = sr.ReadToEnd(); sr.Close();
   }
   Compilation compilation = new Compilation();
   compilation.CompilerParameters = this.GetDummyCompilerParameters();
   compilation.TargetModule = new Module();
   DocumentText docText = new DocumentText(new StringSourceText(fContents, true));
   SourceContext sctx = new SourceContext(Compiler.CreateSpecSharpDocument(fileName, 0, docText));
   compilation.CompilationUnits = new CompilationUnitList(new CompilationUnitSnippet(new Identifier(fileName), new ParserFactory(), sctx));
   compilation.CompilationUnits[0].Compilation = compilation;
   this.dummyCompilationFor[fileName] = new WeakReference(compilation);
   return compilation;
 }
예제 #4
0
        public Error(int errorCode, string error, SourceContext context)
        {
            Contract.Requires(error != null);

            if (context.IsValid)
            {
                // F: Why context.Document != null? Added the assumption
                Contract.Assume(context.Document != null);

                this.FileName = context.Document.Name;
            }
            else
            {
                this.FileName = " "; // non-empty to prevent VS/msbuild from prepending EXEC 
            }

            this.Line = context.StartLine;
            this.Column = context.StartColumn;
            this.ErrorNumber = "CC" + errorCode;
            this.ErrorText = error;
        }
예제 #5
0
        //public override Block VisitBlock(Block block) {
        //  if(block.Statements != null && block.Statements.Count == 1) {
        //    Return r = block.Statements[0] as Return;
        //    if(r != null) {
        //      Statement s = this.VisitReturn(r);
        //      Block retBlock = s as Block;
        //      if(retBlock != null) {
        //        block.Statements = retBlock.Statements;
        //        return block;
        //      } else {
        //        return base.VisitBlock(block);
        //      }
        //    } else {
        //      return base.VisitBlock(block);
        //    }
        //  } else {
        //    return base.VisitBlock(block);
        //  }
        //}

        public override Statement VisitReturn(Return Return)
        {
            if (Return == null)
            {
                return null;
            }

            returnCount++;
            this.lastReturnSourceContext = Return.SourceContext;

            StatementList stmts = new StatementList();

            Return.Expression = this.VisitExpression(Return.Expression);

            if (Return.Expression != null)
            {
                MethodCall mc = Return.Expression as MethodCall;
                if (mc != null && mc.IsTailCall)
                {
                    mc.IsTailCall = false;
                }

                var assgnmt = new AssignmentStatement(result, Return.Expression);

                assgnmt.SourceContext = Return.SourceContext;
                stmts.Add(assgnmt);
            }

            // the branch is a "leave" out of the try block that the body will be
            // in.
            var branch = new Branch(null, newExit, false, false, this.leaveExceptionBody);
            branch.SourceContext = Return.SourceContext;

            stmts.Add(branch);

            return new Block(stmts);
        }
예제 #6
0
        private void CopyValidatorContracts(Method targetMethod, Method validatorMethodInstance, Expression targetObject,
            ExpressionList actuals, RequiresList Preconditions, SourceContext useSite, Block validatorPrefix)
        {
            // make sure to have extracted contracts from the validator method prior
            if (validatorMethodInstance.DeclaringType.DeclaringModule == targetMethod.DeclaringType.DeclaringModule)
            {
                var validatorMethod = validatorMethodInstance;

                while (validatorMethod.Template != null)
                {
                    validatorMethod = validatorMethod.Template;
                }

                this.VisitMethod(validatorMethod);
            }

            if (validatorMethodInstance.Contract == null) return;

            var copier = new AbbreviationDuplicator(validatorMethodInstance, targetMethod, this.contractNodes,
                validatorMethodInstance, targetObject, actuals);

            var validatorContract = HelperMethods.DuplicateContractAndClosureParts(copier, targetMethod,
                validatorMethodInstance, this.contractNodes, false);

            if (validatorContract == null) return;

            MoveValidatorRequires(targetMethod, validatorContract.Requires, Preconditions, useSite,
                validatorContract.ContractInitializer, validatorPrefix);
        }
예제 #7
0
        private void ExtractContractsForMethod(Method method, object dummy)
        {
            Contract.Requires(method != null);

            RequiresList preconditions = null;
            EnsuresList postconditions = null;
            RequiresList validations = null;
            EnsuresList modelPostconditions = null;

            //Console.WriteLine("Extracting contract for method {0}", method.FullName);

            // set its contract so pure is properly handled.
            var methodContract = method.Contract = new MethodContract(method);

            try
            {
                if (method.IsAbstract /* && contractClass == null */)
                {
                    // Abstract methods cannot have a body, so nothing to extract
                    return;
                }

                TypeNode /*?*/ closure = null;
                bool possiblyAsync;
                if (IsIteratorOrAsyncMethodCandidate(method, out possiblyAsync))
                {
                    closure = FindClosureClass(method);
                    if (closure != null)
                    {
                        this.ProcessClosureClass(method, closure, possiblyAsync);
                        return;
                    }
                }

                if (method.Body == null || method.Body.Statements == null)
                    return;

                // Find first source context, use it if no better one is found on errors

                // if (method.Body != null && method.Body.Statements != null)
                {
                    if (this.verbose)
                    {
                        Console.WriteLine(method.FullName);
                    }

                    bool found = false;
                    for (int i = 0, n = method.Body.Statements.Count; i < n && !found; i++)
                    {
                        Block b = method.Body.Statements[i] as Block;
                        if (b != null)
                        {
                            for (int j2 = 0, m = b.Statements == null ? 0 : b.Statements.Count; j2 < m; j2++)
                            {
                                Contract.Assert(m == b.Statements.Count, "loop invariant not inferred");

                                Statement s = b.Statements[j2];
                                if (s != null)
                                {
                                    SourceContext sctx = s.SourceContext;
                                    if (sctx.IsValid)
                                    {
                                        found = true;
                                        // s.SourceContext = new SourceContext(); // wipe out the source context because this statement will no longer be the first one in the method body if there are any contract calls
                                        this.currentMethodSourceContext = sctx;
                                        if (this.verbose)
                                        {
                                            Console.WriteLine("block {0}, statement {1}: ({2},{3})", i, j2, sctx.StartLine, sctx.StartColumn);
                                        }

                                        break;
                                    }
                                }
                            }
                        }
                    }
                }

                Block contractInitializerBlock = new Block(new StatementList());
                Block postPreamble = null;

                HelperMethods.StackDepthTracker dupStackTracker = new HelperMethods.StackDepthTracker();

                var contractLocalAliasingThis = HelperMethods.ExtractPreamble(method, this.contractNodes,
                    contractInitializerBlock, out postPreamble, ref dupStackTracker, this.isVB);

                bool saveErrorFound = this.errorFound;
                this.errorFound = false;

                // Extract pre- and postconditions

                if (method.Body != null && method.Body.Statements != null)
                {
                    this.CheapAndDirty(method, ref preconditions, ref postconditions, ref validations,
                        ref modelPostconditions, contractInitializerBlock, ref dupStackTracker);

                    if (this.errorFound)
                    {
                        method.ClearBody();

                        this.errorFound = saveErrorFound;
                        return;
                    }

                    this.errorFound = saveErrorFound;
                }

                // Sanitize contract by renaming local aliasing "this" to This

                if (contractLocalAliasingThis != null && method.ThisParameter != null)
                {
                    var renamer = new ContractLocalToThis(contractLocalAliasingThis, method.ThisParameter);
                    renamer.Visit(preconditions);
                    renamer.Visit(postconditions);
                    renamer.Visit(modelPostconditions);
                }

                // Split out async ensures

                var asyncPostconditions = SplitAsyncEnsures(ref postconditions, method);

                // Store contracts into the appropriate slots

                Contract.Assume(methodContract.RequiresCount == 0);
                Contract.Assume(methodContract.EnsuresCount == 0);
                Contract.Assume(methodContract.ModelEnsuresCount == 0);

                methodContract.ContractInitializer = contractInitializerBlock;
                methodContract.PostPreamble = postPreamble;
                methodContract.Requires = preconditions;
                methodContract.Ensures = postconditions;
                methodContract.AsyncEnsures = asyncPostconditions;
                methodContract.ModelEnsures = modelPostconditions;
                methodContract.Validations = validations;

                return;
            }
            catch (NotImplementedException ni)
            {
                // indicates a problem
                this.HandleError(method, 1099, "Contract extraction failed: " + ni.Message, default(SourceContext));
            }
            finally
            {
                // normalize contract by forcing IsPure to look at attributes and removing contract it is empty
                var isPure = methodContract.IsPure;

                if (!isPure && methodContract.RequiresCount == 0 &&
                    methodContract.EnsuresCount == 0 &&
                    methodContract.ModelEnsuresCount == 0 &&
                    methodContract.AsyncEnsuresCount == 0 &&
                    methodContract.ValidationsCount == 0)
                {
                    method.Contract = null;
                }
                else
                {
                    // turn helper method calls to Result, OldValue, ValueAtReturn into proper AST nodes.
                    this.extractionFinalizer.VisitMethodContract(methodContract);
                }
            }
        }
예제 #8
0
        private bool ExtractFromClump(StatementList contractClump, Method method, GatherLocals gatherLocals,
            RequiresList Preconditions, EnsuresList Postconditions, RequiresList validations,
            EnsuresList modelPostconditions, SourceContext defaultContext, Method originalMethod,
            Block contractInitializer, ref HelperMethods.StackDepthTracker dupStackTracker)
        {
            // set the state so that the contract clump is used for extraction (as opposed to the method body as it used to)
            StatementList stmts = contractClump;

            int beginning = 0;
            int n = stmts.Count;
            int seginning = HelperMethods.FindNextRealStatement(((Block) stmts[beginning]).Statements, 0);

            bool endContractFound = false;
            bool postConditionFound = false;

            SourceContext currentSourceContext;

            for (int i = beginning; i < n; i++)
            {
                Block b = (Block) stmts[i];
                if (b == null) continue;

                for (int j = 0, m = b.Statements == null ? 0 : b.Statements.Count; j < m; j++)
                {
                    if (dupStackTracker.IsValid && dupStackTracker.Depth >= 0)
                    {
                        b.Statements[j] = dupStackTracker.Visit(b.Statements[j]);
                    }

                    Statement s = b.Statements[j];
                    if (s == null) continue;

                    Block currentClump;
                    Throw t = null;
                    t = s as Throw;

                    Method calledMethod = HelperMethods.IsMethodCall(s);
                    if ((t != null ||
                         (calledMethod != null &&
                          calledMethod.DeclaringType != null &&
                          calledMethod.DeclaringType != this.contractNodes.ContractClass &&
                          HelperMethods.IsVoidType(calledMethod.ReturnType) &&
                          !this.contractNodes.IsContractOrValidatorOrAbbreviatorMethod(calledMethod))))
                    {
                        // Treat throw statements as (part of) a precondition

                        // don't accept "throw ..." unless it comes in the "precondition section"
                        // then treat the current clump as a precondition, but need to massage it a bit:
                        // all branches to the block just after the throw should be modified to be branches to
                        // a new manufactured block that sets a fresh local to "true". The
                        // throw itself should be changed to set the same local to "false". That way the
                        // clump can be treated as the value of precondition (because the branch polarity has
                        // already been negated as part of the code gen).

                        // This test was supposed to be a sanity check that the current block contained
                        // only "throw ..." or else "nop; throw ...". But I've also seen "ThrowHelper.Throw(...); nop",
                        // so I'm just going to comment this out for now.
                        //if (!((m == 1 && j == 0) || (m == 2 && j == 1))) {
                        //  Preconditions = new RequiresList();
                        //  Postconditions = new EnsuresList();
                        //  return; // throw new ExtractorException();
                        //}

                        Expression exception;

                        // The clump being extracted may contain code/blocks that represent (part of)
                        // the expression that is being thrown (if the original throw expression had
                        // control flow in it from boolean expressions and/or ternary expressions).

                        b.Statements[j] = null; // wipe out throw statement

                        currentClump = new Block(HelperMethods.ExtractClump(stmts, beginning, seginning, i, j));
                        int currentClumpLength = i - beginning + 1;

                        // there better be a next block because that must have been the target for all of the branches
                        // that didn't cause the throw to happen
                        if (!(i < n - 1))
                        {
                            this.HandleError(method, 1027, "Malformed contract.", s.SourceContext);
                            return false;
                        }

                        Block nextBlock = (Block) stmts[i + 1]; // cast succeeds because body is clump
                        Local valueOfPrecondition = new Local(Identifier.For("_preConditionHolds"), SystemTypes.Boolean);
                        Block preconditionHolds = new Block(new StatementList(new AssignmentStatement(valueOfPrecondition, Literal.True)));

                        ReplaceBranchTarget rbt = new ReplaceBranchTarget(nextBlock, preconditionHolds);
                        rbt.VisitBlock(currentClump);

                        int ILOffset;
                        CountPopExpressions cpe = new CountPopExpressions();
                        currentSourceContext = s.SourceContext;
                        cpe.Visit(s);

                        if (0 < cpe.PopOccurrences)
                        {
                            // then there is a set of blocks that represent the exception: the Reader
                            // was not able to decompile it back into an expression. Extract the set
                            // from the current clump and make it into a block expression

                            // Find the last block that has a branch to "preconditionHolds". After that are all of the blocks
                            // that represent the evaluation of the exception
                            int branchBlockIndex = currentClumpLength - 2;

                            // can't be the current block: that has the throw in it
                            while (0 <= branchBlockIndex)
                            {
                                Block possibleBranchBlock = currentClump.Statements[branchBlockIndex] as Block;
                                Branch br = possibleBranchBlock.Statements[possibleBranchBlock.Statements.Count - 1] as Branch;
                                if (br != null && br.Target == preconditionHolds)
                                {
                                    break;
                                }

                                branchBlockIndex--;
                            }

                            if (branchBlockIndex < 0)
                            {
                                this.HandleError(method, 1028, "Malformed exception constructor in contract.", defaultContext);
                                return false;
                            }

                            Block exceptionBlock =
                                new Block(HelperMethods.ExtractClump(currentClump.Statements, branchBlockIndex + 1, 0,
                                    currentClumpLength - 1,
                                    ((Block) currentClump.Statements[currentClumpLength - 1]).Statements.Count - 1));

                            exceptionBlock.Statements.Add(new ExpressionStatement(t.Expression));
                            SourceContext sctx = ((Block) exceptionBlock.Statements[0]).Statements[0].SourceContext;

                            if (sctx.IsValid)
                            {
                                currentSourceContext = sctx;
                            }
                            else
                            {
                                SourceContext tmp;
                                bool foundContext = HelperMethods.GetLastSourceContext(exceptionBlock.Statements, out tmp);
                                if (foundContext)
                                    currentSourceContext = tmp;
                            }

                            if (!CheckClump(method, gatherLocals, currentSourceContext, exceptionBlock)) return false;
                            
                            exception = new BlockExpression(exceptionBlock, SystemTypes.Exception);
                            ILOffset = t.ILOffset;
                        }
                        else
                        {
                            currentSourceContext = s.SourceContext;
                            if (t != null)
                            {
                                // then the statement is "throw ..."
                                exception = t.Expression;
                                ILOffset = t.ILOffset;
                            }
                            else
                            {
                                ExpressionStatement throwHelperCall = s as ExpressionStatement;

                                Debug.Assert(throwHelperCall != null);

                                exception = throwHelperCall.Expression;
                                ILOffset = s.ILOffset;
                            }

                            exception.SourceContext = currentSourceContext;
                            SourceContext tmp;

                            bool foundContext = HelperMethods.GetLastSourceContext(currentClump.Statements, out tmp);
                            if (foundContext)
                                currentSourceContext = tmp;
                        }

                        Block returnValueOfPrecondition = new Block(new StatementList(new ExpressionStatement(valueOfPrecondition)));
                        Statement extraAssumeFalse = this.ExtraAssumeFalseOnThrow();

                        Block preconditionFails =
                            new Block(new StatementList(new AssignmentStatement(valueOfPrecondition, Literal.False),
                                extraAssumeFalse, new Branch(null, returnValueOfPrecondition, true, false, false)));

                        //Block preconditionFails = new Block(new StatementList(new AssignmentStatement(valueOfPrecondition, Literal.False), new Branch(null, returnValueOfPrecondition, true, false, false)));
                        currentClump.Statements.Add(preconditionFails); // replace throw statement
                        currentClump.Statements.Add(preconditionHolds);
                        currentClump.Statements.Add(returnValueOfPrecondition);

                        if (!CheckClump(originalMethod, gatherLocals, currentSourceContext, currentClump)) return false;

                        BlockExpression be = new BlockExpression(currentClump, SystemTypes.Boolean);
                        be.SourceContext = currentSourceContext;

                        var ro = new RequiresOtherwise(be, exception);
                        ro.ILOffset = ILOffset;
                        ro.SourceContext = currentSourceContext;

                        if (postConditionFound)
                        {
                            HandleError(originalMethod, 1013, "Precondition found after postcondition.", currentSourceContext);
                            return false;
                        }

                        validations.Add(ro);

                        var req = new RequiresPlain(be, FindExceptionThrown.Find(exception));
                        req.IsFromValidation = true;
                        req.ILOffset = ro.ILOffset;
                        req.SourceContext = ro.SourceContext;

                        Preconditions.Add(req);
                    }
                    else
                    {
                        if (contractNodes.IsContractMethod(calledMethod))
                        {
                            // Treat calls to contract methods

                            if (endContractFound)
                            {
                                HandleError(originalMethod, 1012, "Contract call found after prior EndContractBlock.", s.SourceContext);
                                break;
                            }

                            if (contractNodes.IsEndContract(calledMethod))
                            {
                                endContractFound = true;
                                continue;
                            }

                            MethodCall mc = ((ExpressionStatement) s).Expression as MethodCall;
                            Expression arg = mc.Operands[0];
                            arg.SourceContext = s.SourceContext;
                            MethodContractElement mce;
                            currentSourceContext = s.SourceContext;
                            Expression condition;

                            if (beginning == i && seginning == j)
                            {
                                // Deal with the simple case: the reader decompiled the call into a single statement
                                condition = arg;
                            }
                            else
                            {
                                b.Statements[j] = new ExpressionStatement(arg);

                                // construct a clump from
                                // methodBody.Statements[beginning].Statements[seginning] to
                                // methodBody.Statements[i].Statements[j]
                                currentClump = new Block(HelperMethods.ExtractClump(stmts, beginning, seginning, i, j));
                                if (!currentSourceContext.IsValid)
                                {
                                    // then a good source context has not been found yet. Grovel around in the clump
                                    // to see if there is a better one
                                    SourceContext sctx;
                                    if (HelperMethods.FindContext(currentClump, currentSourceContext, out sctx))
                                        currentSourceContext = sctx;
                                }

                                if (!CheckClump(originalMethod, gatherLocals, currentSourceContext, currentClump))
                                    return false;

                                BlockExpression be = new BlockExpression(currentClump);
                                condition = be;
                            }

                            condition.SourceContext = currentSourceContext;
                            if (contractNodes.IsPlainPrecondition(calledMethod))
                            {
                                var req = new RequiresPlain(condition);
                                contractNodes.IsRequiresWithException(calledMethod, out req.ExceptionType);

                                mce = req;
                            }
                            else if (this.contractNodes.IsPostcondition(calledMethod))
                            {
                                mce = new EnsuresNormal(condition);
                            }
                            else if (contractNodes.IsExceptionalPostcondition(calledMethod))
                            {
                                EnsuresExceptional ee = new EnsuresExceptional(condition);
                                // Extract the type of exception.
                                ee.Type = calledMethod.TemplateArguments[0];
                                mce = ee;
                            }
                            else
                            {
                                throw new InvalidOperationException("Cannot recognize contract method");
                            }

                            mce.SourceContext = currentSourceContext;
                            mce.ILOffset = mc.ILOffset;
                            if (1 < mc.Operands.Count)
                            {
                                var candidate = SanitizeUserMessage(method, mc.Operands[1], currentSourceContext);
                                mce.UserMessage = candidate;
                            }
                            if (2 < mc.Operands.Count)
                            {
                                Literal lit = mc.Operands[2] as Literal;
                                if (lit != null)
                                {
                                    mce.SourceConditionText = lit;
                                }
                            }

                            // determine Model status

                            mce.UsesModels = CodeInspector.UsesModel(mce.Assertion, this.contractNodes);

                            // Check context rules

                            switch (mce.NodeType)
                            {
                                case NodeType.RequiresPlain:
                                    if (postConditionFound)
                                    {
                                        this.HandleError(originalMethod, 1014, "Precondition found after postcondition.", currentSourceContext);
                                        return false;
                                    }
                                    if (mce.UsesModels)
                                    {
                                        this.HandleError(originalMethod, 1073, "Preconditions may not refer to model members.", currentSourceContext);
                                        return false;
                                    }

                                    var rp = (RequiresPlain) mce;

                                    Preconditions.Add(rp);
                                    validations.Add(rp); // also add to the internal validation list
                                    break;

                                // TODO: check visibility of post conditions based on visibility of possible implementation
                                case NodeType.EnsuresNormal:
                                case NodeType.EnsuresExceptional:
                                    Ensures ensures = (Ensures) mce;
                                    if (mce.UsesModels)
                                    {
                                        if (this.IncludeModels)
                                        {
                                            modelPostconditions.Add(ensures);
                                        }
                                    }
                                    else
                                    {
                                        Postconditions.Add(ensures);
                                    }
                                    postConditionFound = true;
                                    break;
                            }
                        }
                        else if (ContractNodes.IsValidatorMethod(calledMethod))
                        {
                            // Treat calls to Contract validators

                            if (endContractFound)
                            {
                                this.HandleError(originalMethod, 1012,
                                    "Contract call found after prior EndContractBlock.", s.SourceContext);
                                break;
                            }

                            MethodCall mc = ((ExpressionStatement) s).Expression as MethodCall;
                            var memberBinding = (MemberBinding) mc.Callee;

                            currentSourceContext = s.SourceContext;
                            Statement validation;
                            Block validationPrefix;
                            if (beginning == i && seginning == j)
                            {
                                // Deal with the simple case: the reader decompiled the call into a single statement
                                validation = s;
                                validationPrefix = null;
                            }
                            else
                            {
                                // The clump may contain multiple statements ending in the validator call.
                                //   to extract the code as Requires<E>, we need to keep the statements preceeding
                                //   the validator call, as they may contain local initialization etc. These should go
                                //   into the first Requires<E> that the validator expands to. This way, if there are
                                //   no Requires<E> expanded from the validator, then the statements can be omitted.
                                //   At the same time, the statements won't be duplicated when validations are emitted.
                                //
                                //   If the validator call contains any pops, then the extraction must fail saying it
                                //   is too complicated.

                                // must null out statement with call before extract clump
                                b.Statements[j] = null; // we have a copy in mc, s
                                validationPrefix = new Block(HelperMethods.ExtractClump(stmts, beginning, seginning, i, j));

                                if (!currentSourceContext.IsValid)
                                {
                                    // then a good source context has not been found yet. Grovel around in the clump
                                    // to see if there is a better one
                                    SourceContext sctx;
                                    if (HelperMethods.FindContext(validationPrefix, currentSourceContext, out sctx))
                                        currentSourceContext = sctx;
                                }

                                if (CountPopExpressions.Count(mc) > 0)
                                {
                                    this.HandleError(method, 1071,
                                        "Arguments to contract validator call are too complicated. Please simplify.",
                                        currentSourceContext);
                                    return false;
                                }

                                if (!CheckClump(originalMethod, gatherLocals, currentSourceContext, validationPrefix))
                                    return false;

                                validation = new Block(new StatementList(validationPrefix, s));
                                validation.SourceContext = currentSourceContext;
                            }
                            var ro = new RequiresOtherwise(null, new BlockExpression(new Block(new StatementList(validation))));

                            validations.Add(ro);
                            CopyValidatorContracts(
                                method, calledMethod, memberBinding.TargetObject, mc.Operands,
                                Preconditions, currentSourceContext, validationPrefix);
                        }
                        else if (ContractNodes.IsAbbreviatorMethod(calledMethod))
                        {
                            // Treat calls to Contract abbreviators

                            if (endContractFound)
                            {
                                this.HandleError(originalMethod, 1012, "Contract call found after prior EndContractBlock.", s.SourceContext);
                                break;
                            }

                            MethodCall mc = ((ExpressionStatement) s).Expression as MethodCall;
                            var memberBinding = (MemberBinding) mc.Callee;
                            currentSourceContext = s.SourceContext;
                            if (beginning == i && seginning == j)
                            {
                                // Deal with the simple case: the reader decompiled the call into a single statement

                                // nothing to do. All is in the call and its arguments
                            }
                            else
                            {
                                // The clump may contain multiple statements ending in the abbreviator call.
                                // We need to keep the statements preceeding the abbreviator call and add them to the 
                                // contract initializer block. The reason we cannot add them to the first expansion contract
                                // of the abbreviator is that the abbreviator may give rise to closure initialization which will
                                // be hoisted into the closure initializer block. This closure initializer may refer to the
                                // locals initialized by the present statement sequence, so it must precede it. 
                                //
                                //   If the abbreviator call contains any pops, then the extraction must fail saying it
                                //   is too complicated.
                                // grab prefix of clump minus last call statement.

                                // must null out current call statement before we extract clump (ow. it stays in body)
                                b.Statements[j] = null;
                                currentClump = new Block(HelperMethods.ExtractClump(stmts, beginning, seginning, i, j));

                                if (!currentSourceContext.IsValid)
                                {
                                    // then a good source context has not been found yet. Grovel around in the clump
                                    // to see if there is a better one
                                    SourceContext sctx;
                                    if (HelperMethods.FindContext(currentClump, currentSourceContext, out sctx))
                                        currentSourceContext = sctx;
                                }

                                if (CountPopExpressions.Count(mc) > 0)
                                {
                                    this.HandleError(method, 1070,
                                        "Arguments to contract abbreviator call are too complicated. Please simplify.",
                                        currentSourceContext);
                                    return false;
                                }

                                if (!CheckClump(originalMethod, gatherLocals, currentSourceContext, currentClump))
                                    return false;

                                if (HelperMethods.IsNonTrivial(currentClump))
                                {
                                    contractInitializer.Statements.Add(currentClump);
                                }
                            }

                            CopyAbbreviatorContracts(method, calledMethod, memberBinding.TargetObject, mc.Operands,
                                Preconditions, Postconditions, currentSourceContext, validations, contractInitializer);
                        }
                        else
                        {
                            // important to continue here and accumulate blocks/statements for next contract!
                            if (i == beginning && j == seginning && s.NodeType == NodeType.Nop)
                            {
                                // nop following contract is often associated with previous code, so skip it
                                seginning = j + 1;
                            }

                            continue;
                        }
                    }

                    // Re-initialize current state after contract has been found

                    beginning = i;
                    seginning = j + 1;

                    //seginning = HelperMethods.FindNextRealStatement(((Block)stmts[i]).Statements, j + 1);
                    if (seginning < 0) seginning = 0;
                    
                    //b = (Block)stmts[i]; // IMPORTANT! Need this to keep "b" in sync
                }
            }

            if (this.verbose)
            {
                Console.WriteLine("\tNumber of Preconditions: " + Preconditions.Count);
                Console.WriteLine("\tNumber of Postconditions: " + Postconditions.Count);
            }

            return true;
        }
예제 #9
0
 public void HandleError(Method method, int errorCode, string s, SourceContext context)
 {
     if (context.IsValid)
     {
         CallErrorFound(new Error(errorCode, s, context));
     }
     else
     {
         CallErrorFound(new Error(errorCode,
             string.Format("{0}: In method {1}, assembly {2}", s, method.FullName,
                 method.DeclaringType.DeclaringModule.Location), context));
     }
 }
예제 #10
0
        private StatementList GetContractClumpFromMoveNext(Method iteratorMethod, Method moveNext,
            ContractNodes contractNodes, StatementList contractInitializer, out SourceContext defaultSourceContext,
            ref HelperMethods.StackDepthTracker dupStackTracker,
            out AssumeBlock originalContractPosition)
        {
            Contract.Requires(moveNext != null);
            Contract.Requires(moveNext.Body != null);
            Contract.Requires(moveNext.Body.Statements != null);
            Contract.Requires(contractInitializer != null);
            Contract.Requires(iteratorMethod != null);

            var linkerVersion = 0;
            if (iteratorMethod.DeclaringType != null && iteratorMethod.DeclaringType.DeclaringModule != null)
            {
                linkerVersion = iteratorMethod.DeclaringType.DeclaringModule.LinkerMajorVersion;
            }

            var initialState = moveNext.IsAsync ? -1 : 0;
            moveNext.MoveNextStartState = initialState;
            originalContractPosition = null;
            int statementIndex;

            Contract.Assume(moveNext.Body != null);
            Contract.Assume(moveNext.Body.Statements != null);

            int blockIndex = ContractStartInMoveNext(this.contractNodes, moveNext, out statementIndex, iteratorMethod);

            Contract.Assert(statementIndex >= 0, "should follow from the postcondiiton");

            if (blockIndex < 0)
            {
                // Couldn't find state 0 in MoveNext method
                // This can happen if the iterator is trivial (like yield break; )
                defaultSourceContext = default(SourceContext);
                return null;
            }

            int beginning = blockIndex; // the block number in the body of movenext
            int sbeginning = statementIndex; // the statement no. in the beginnning block after the preamble
            int blast = -1;

            // the block number in the body of movenext, of the last block where there is a contract call
            int slast = -1; // the statement no. in the blast block

            // Next we move sbeginning past the preamble area
            sbeginning = MovePastPreamble(iteratorMethod, moveNext, beginning, sbeginning, contractInitializer,
                contractNodes, ref dupStackTracker);

            Contract.Assert(moveNext.Body != null, "should be provable");
            Contract.Assert(moveNext.Body.Statements != null, "should be provable");

            if (sbeginning < 0 ||
                !this.FindLastBlockWithContracts(moveNext.Body.Statements, beginning, out blast, out slast))
            {
                if (verbose)
                {
                    if (moveNext.Name != null)
                    {
                        Console.WriteLine("Method {0} doesnt have a contract method invocation at the right place.", moveNext.Name.Name);
                    }
                }

                defaultSourceContext = default(SourceContext);
                return null;
            }

            Block methodBody = moveNext.Body;
            Block lastBlock = methodBody.Statements[blast] as Block;
            SourceContext lastContractSourceContext;

            if (lastBlock != null)
            {
                lastContractSourceContext = lastBlock.SourceContext;
                // probably not a good context, what to do if one can't be found?
                if (lastBlock.Statements != null && 0 <= slast && slast < lastBlock.Statements.Count)
                {
                    if (lastBlock.Statements[slast] != null)
                    {
                        lastContractSourceContext = lastBlock.Statements[slast].SourceContext;
                    }
                }
            }
            else
            {
                lastContractSourceContext = default(SourceContext);
            }

            // TODO: check the clump is not in a try-catch block. 

            originalContractPosition = new AssumeBlock(new StatementList());
            StatementList result = HelperMethods.ExtractClump(
                moveNext.Body.Statements, beginning, sbeginning, blast,
                slast, assumeBlock: originalContractPosition);

            defaultSourceContext = lastContractSourceContext;
            return result;
        }
예제 #11
0
            public void CheckInvariants(TypeNode t, InvariantList invariants)
            {
                Contract.Requires(invariants != null);

                this.assignmentFound = false;
                foreach (var i in invariants)
                {
                    if (i == null) continue;

                    this.lastSourceContext = i.SourceContext;
                    this.CurrentMethod = i;
                    
                    this.Visit(i);
                    
                    Contract.Assume(this.CurrentMethod != null);
                    
                    if (this.assignmentFound)
                    {
                        this.errorHandler(
                            new Error(1003,
                                "Malformed contract. Found Invariant after assignment in method '" + this.CurrentMethod.FullName + "'.", 
                                i.SourceContext));
                        
                        break;
                    }
                }
            }
예제 #12
0
 public override void StartTemplateParameters(System.Compiler.SourceContext context)
 {
     this.vsAuthoringSink.StartTemplateParameters(new SourceContext(context));
 }
예제 #13
0
파일: Reader.cs 프로젝트: modulexcite/IL2JS
    private bool ParseStatement(Block/*!*/ block) {
      //parse instructions and put in expression tree until an assignment, void call, branch target, or branch is encountered
      StatementList statementList = block.Statements;
      Expression expr = null;
      Statement statement = null;
      bool transferStatement = false;
      int startingAddress = 0;
#if !FxCop
      SourceContext sourceContext = new SourceContext();
      sourceContext.StartPos = this.counter;
#endif
#if !ROTOR
      if (this.method.contextForOffset != null){
        object sctx = this.method.contextForOffset[this.counter+1];
        if (sctx != null) sourceContext = (SourceContext)sctx;
      }
#endif
      while (true){
        bool isStatement = false;
        startingAddress = this.counter+1; //Add one so that it is never zero (the latter means no entry to the TrivialHashtable)
#if FxCop || ILOFFSETS
        this.ilOffset = this.counter;
        this.opCode = this.GetOpCode();
#else
        OpCode opCode = this.GetOpCode();
#endif
#if FxCop
        if (this.handlerMap.TryGetValue(this.ilOffset, out expr)){
          expr.sourceContext = sourceContext;
          expr.ILOffset = this.ilOffset;
          this.operandStack.Push(expr);
        }
#endif
        switch (opCode){
          case OpCode.Nop: statement = new Statement(NodeType.Nop); goto done;
          case OpCode.Break: statement = new Statement(NodeType.DebugBreak); goto done;
          case OpCode.Ldarg_0: expr = this.Parameters(0); break;
          case OpCode.Ldarg_1: expr = this.Parameters(1); break;
          case OpCode.Ldarg_2: expr = this.Parameters(2); break;
          case OpCode.Ldarg_3: expr = this.Parameters(3); break;
          case OpCode.Ldloc_0: expr = this.locals[0]; break;
          case OpCode.Ldloc_1: expr = this.locals[1]; break;
          case OpCode.Ldloc_2: expr = this.locals[2]; break;
          case OpCode.Ldloc_3: expr = this.locals[3]; break;
          case OpCode.Stloc_0: statement = new AssignmentStatement(this.locals[0], PopOperand()); goto done;
          case OpCode.Stloc_1: statement = new AssignmentStatement(this.locals[1], PopOperand()); goto done;
          case OpCode.Stloc_2: statement = new AssignmentStatement(this.locals[2], PopOperand()); goto done;
          case OpCode.Stloc_3: statement = new AssignmentStatement(this.locals[3], PopOperand()); goto done;
          case OpCode.Ldarg_S: expr = this.Parameters(this.GetByte()); break;
          case OpCode.Ldarga_S: expr = SetType(new UnaryExpression(this.Parameters(this.GetByte()), NodeType.AddressOf)); break;
          case OpCode.Starg_S: statement = new AssignmentStatement(this.Parameters(this.GetByte()), PopOperand()); goto done;
          case OpCode.Ldloc_S: expr = this.locals[this.GetByte()]; break;
          case OpCode.Ldloca_S: expr = SetType(new UnaryExpression(this.locals[this.GetByte()], NodeType.AddressOf)); break;
          case OpCode.Stloc_S: statement = new AssignmentStatement(this.locals[this.GetByte()], PopOperand()); goto done;
          case OpCode.Ldnull: expr = new Literal(null, CoreSystemTypes.Object); break;
          case OpCode.Ldc_I4_M1: expr = new Literal(-1, CoreSystemTypes.Int32); break;
          case OpCode.Ldc_I4_0: expr = new Literal(0, CoreSystemTypes.Int32); break;
          case OpCode.Ldc_I4_1: expr = new Literal(1, CoreSystemTypes.Int32); break;
          case OpCode.Ldc_I4_2: expr = new Literal(2, CoreSystemTypes.Int32); break;
          case OpCode.Ldc_I4_3: expr = new Literal(3, CoreSystemTypes.Int32); break;
          case OpCode.Ldc_I4_4: expr = new Literal(4, CoreSystemTypes.Int32); break;
          case OpCode.Ldc_I4_5: expr = new Literal(5, CoreSystemTypes.Int32); break;
          case OpCode.Ldc_I4_6: expr = new Literal(6, CoreSystemTypes.Int32); break;
          case OpCode.Ldc_I4_7: expr = new Literal(7, CoreSystemTypes.Int32); break;
          case OpCode.Ldc_I4_8: expr = new Literal(8, CoreSystemTypes.Int32); break;
          case OpCode.Ldc_I4_S: expr = new Literal((int)this.GetSByte(), CoreSystemTypes.Int32); break;
          case OpCode.Ldc_I4: expr = new Literal(this.GetInt32(), CoreSystemTypes.Int32); break;
          case OpCode.Ldc_I8: expr = new Literal(this.GetInt64(), CoreSystemTypes.Int64); break;
          case OpCode.Ldc_R4: expr = new Literal(this.GetSingle(), CoreSystemTypes.Single); break;
          case OpCode.Ldc_R8: expr = new Literal(this.GetDouble(), CoreSystemTypes.Double); break;
          case OpCode.Dup: statement = new ExpressionStatement(new Expression(NodeType.Dup)); goto done;
          case OpCode.Pop: statement = new ExpressionStatement(new UnaryExpression(PopOperand(), NodeType.Pop)); goto done;
          case OpCode.Jmp: expr = this.ParseCall(NodeType.Jmp, out isStatement); if (isStatement) goto done; break;
          case OpCode.Call: expr = this.ParseCall(NodeType.Call, out isStatement); if (isStatement) goto done; break;
          case OpCode.Calli: expr = this.ParseCalli(out isStatement); if (isStatement) goto done; break;
          case OpCode.Ret:
            Expression retVal = BodyParser.TypeIsVoid(this.method.ReturnType) ? null : PopOperand();
            statement = new Return(retVal); 
            transferStatement = true; goto done;
          case OpCode.Br_S: statement = this.ParseBranch(NodeType.Nop, 0, true, false); transferStatement = true; goto done;
          case OpCode.Brfalse_S: statement = this.ParseBranch(NodeType.LogicalNot, 1, true, false); transferStatement = true; goto done;
          case OpCode.Brtrue_S: statement = this.ParseBranch(NodeType.Nop, 1, true, false); transferStatement = true; goto done;
          case OpCode.Beq_S: statement = this.ParseBranch(NodeType.Eq, 2, true, false); transferStatement = true; goto done;
          case OpCode.Bge_S: statement = this.ParseBranch(NodeType.Ge, 2, true, false); transferStatement = true; goto done;
          case OpCode.Bgt_S: statement = this.ParseBranch(NodeType.Gt, 2, true, false); transferStatement = true; goto done;
          case OpCode.Ble_S: statement = this.ParseBranch(NodeType.Le, 2, true, false); transferStatement = true; goto done;
          case OpCode.Blt_S: statement = this.ParseBranch(NodeType.Lt, 2, true, false); transferStatement = true; goto done;
          case OpCode.Bne_Un_S: statement = this.ParseBranch(NodeType.Ne, 2, true, true); transferStatement = true; goto done;
          case OpCode.Bge_Un_S: statement = this.ParseBranch(NodeType.Ge, 2, true, true); transferStatement = true; goto done;
          case OpCode.Bgt_Un_S: statement = this.ParseBranch(NodeType.Gt, 2, true, true); transferStatement = true; goto done;
          case OpCode.Ble_Un_S: statement = this.ParseBranch(NodeType.Le, 2, true, true); transferStatement = true; goto done;
          case OpCode.Blt_Un_S: statement = this.ParseBranch(NodeType.Lt, 2, true, true); transferStatement = true; goto done;
          case OpCode.Br: statement = this.ParseBranch(NodeType.Nop, 0, false, false); transferStatement = true; goto done;
          case OpCode.Brfalse: statement = this.ParseBranch(NodeType.LogicalNot, 1, false, false); transferStatement = true; goto done;
          case OpCode.Brtrue: statement = this.ParseBranch(NodeType.Nop, 1, false, false); transferStatement = true; goto done;
          case OpCode.Beq: statement = this.ParseBranch(NodeType.Eq, 2, false, false); transferStatement = true; goto done;
          case OpCode.Bge: statement = this.ParseBranch(NodeType.Ge, 2, false, false); transferStatement = true; goto done;
          case OpCode.Bgt: statement = this.ParseBranch(NodeType.Gt, 2, false, false); transferStatement = true; goto done;
          case OpCode.Ble: statement = this.ParseBranch(NodeType.Le, 2, false, false); transferStatement = true; goto done;
          case OpCode.Blt: statement = this.ParseBranch(NodeType.Lt, 2, false, false); transferStatement = true; goto done;
          case OpCode.Bne_Un: statement = this.ParseBranch(NodeType.Ne, 2, false, true); transferStatement = true; goto done;
          case OpCode.Bge_Un: statement = this.ParseBranch(NodeType.Ge, 2, false, true); transferStatement = true; goto done;
          case OpCode.Bgt_Un: statement = this.ParseBranch(NodeType.Gt, 2, false, true); transferStatement = true; goto done;
          case OpCode.Ble_Un: statement = this.ParseBranch(NodeType.Le, 2, false, true); transferStatement = true; goto done;
          case OpCode.Blt_Un: statement = this.ParseBranch(NodeType.Lt, 2, false, true); transferStatement = true; goto done;
          case OpCode.Switch: statement = this.ParseSwitchInstruction(); transferStatement = true; goto done;
          case OpCode.Ldind_I1: expr = new AddressDereference(PopOperand(), CoreSystemTypes.Int8, this.isVolatile, this.alignment); break;
          case OpCode.Ldind_U1: expr = new AddressDereference(PopOperand(), CoreSystemTypes.UInt8, this.isVolatile, this.alignment); break;
          case OpCode.Ldind_I2: expr = new AddressDereference(PopOperand(), CoreSystemTypes.Int16, this.isVolatile, this.alignment); break;
          case OpCode.Ldind_U2: expr = new AddressDereference(PopOperand(), CoreSystemTypes.UInt16, this.isVolatile, this.alignment); break;
          case OpCode.Ldind_I4: expr = new AddressDereference(PopOperand(), CoreSystemTypes.Int32, this.isVolatile, this.alignment); break;
          case OpCode.Ldind_U4: expr = new AddressDereference(PopOperand(), CoreSystemTypes.UInt32, this.isVolatile, this.alignment); break;
          case OpCode.Ldind_I8: expr = new AddressDereference(PopOperand(), CoreSystemTypes.Int64, this.isVolatile, this.alignment); break;
          case OpCode.Ldind_I: expr = new AddressDereference(PopOperand(), CoreSystemTypes.IntPtr, this.isVolatile, this.alignment); break;
          case OpCode.Ldind_R4: expr = new AddressDereference(PopOperand(), CoreSystemTypes.Single, this.isVolatile, this.alignment); break;
          case OpCode.Ldind_R8: expr = new AddressDereference(PopOperand(), CoreSystemTypes.Double, this.isVolatile, this.alignment); break;
          case OpCode.Ldind_Ref: expr = new AddressDereference(PopOperand(), CoreSystemTypes.Object, this.isVolatile, this.alignment); break;
          case OpCode.Stind_Ref: statement = this.ParseStoreIndirect(CoreSystemTypes.Object); goto done;
          case OpCode.Stind_I1: statement = this.ParseStoreIndirect(CoreSystemTypes.Int8); goto done;
          case OpCode.Stind_I2: statement = this.ParseStoreIndirect(CoreSystemTypes.Int16); goto done;
          case OpCode.Stind_I4: statement = this.ParseStoreIndirect(CoreSystemTypes.Int32); goto done;
          case OpCode.Stind_I8: statement = this.ParseStoreIndirect(CoreSystemTypes.Int64); goto done;
          case OpCode.Stind_R4: statement = this.ParseStoreIndirect(CoreSystemTypes.Single); goto done;
          case OpCode.Stind_R8: statement = this.ParseStoreIndirect(CoreSystemTypes.Double); goto done;
          case OpCode.Add: expr = this.ParseBinaryOperation(NodeType.Add); break;
          case OpCode.Sub: expr = this.ParseBinaryOperation(NodeType.Sub); break;
          case OpCode.Mul: expr = this.ParseBinaryOperation(NodeType.Mul); break;
          case OpCode.Div: expr = this.ParseBinaryOperation(NodeType.Div); break;
          case OpCode.Div_Un: expr = this.ParseBinaryOperation(NodeType.Div_Un); break;
          case OpCode.Rem: expr = this.ParseBinaryOperation(NodeType.Rem); break;
          case OpCode.Rem_Un: expr = this.ParseBinaryOperation(NodeType.Rem_Un); break;
          case OpCode.And: expr = this.ParseBinaryOperation(NodeType.And); break;
          case OpCode.Or: expr = this.ParseBinaryOperation(NodeType.Or); break;
          case OpCode.Xor: expr = this.ParseBinaryOperation(NodeType.Xor); break;
          case OpCode.Shl: expr = this.ParseBinaryOperation(NodeType.Shl); break;
          case OpCode.Shr: expr = this.ParseBinaryOperation(NodeType.Shr); break;
          case OpCode.Shr_Un: expr = this.ParseBinaryOperation(NodeType.Shr_Un); break;
          case OpCode.Neg: expr = this.ParseUnaryOperation(NodeType.Neg); break;
          case OpCode.Not: expr = this.ParseUnaryOperation(NodeType.Not); break;
          case OpCode.Conv_I1: expr = new UnaryExpression(PopOperand(), NodeType.Conv_I1, CoreSystemTypes.Int8); break;
          case OpCode.Conv_I2: expr = new UnaryExpression(PopOperand(), NodeType.Conv_I2, CoreSystemTypes.Int16); break;
          case OpCode.Conv_I4: expr = new UnaryExpression(PopOperand(), NodeType.Conv_I4, CoreSystemTypes.Int32); break;
          case OpCode.Conv_I8: expr = new UnaryExpression(PopOperand(), NodeType.Conv_I8, CoreSystemTypes.Int64); break;
          case OpCode.Conv_R4: expr = new UnaryExpression(PopOperand(), NodeType.Conv_R4, CoreSystemTypes.Single); break;
          case OpCode.Conv_R8: expr = new UnaryExpression(PopOperand(), NodeType.Conv_R8, CoreSystemTypes.Double); break;
          case OpCode.Conv_U4: expr = new UnaryExpression(PopOperand(), NodeType.Conv_U4, CoreSystemTypes.UInt32); break;
          case OpCode.Conv_U8: expr = new UnaryExpression(PopOperand(), NodeType.Conv_U8, CoreSystemTypes.UInt64); break;
          case OpCode.Callvirt: expr = this.ParseCall(NodeType.Callvirt, out isStatement); if (isStatement) goto done; break;
          case OpCode.Cpobj: statement = this.ParseCopyObject(); goto done;
          case OpCode.Ldobj: expr = new AddressDereference(PopOperand(), (TypeNode)this.GetMemberFromToken(), this.isVolatile, this.alignment); break;
          case OpCode.Ldstr: expr = new Literal(this.GetStringFromToken(), CoreSystemTypes.String); break;
          case OpCode.Newobj: expr = this.ParseConstruct(); break;
          case OpCode.Castclass: expr = ParseTypeCheck(PopOperand(), (TypeNode)this.GetMemberFromToken(), NodeType.Castclass); break;
          case OpCode.Isinst: expr = ParseTypeCheck(PopOperand(), (TypeNode)this.GetMemberFromToken(), NodeType.Isinst); break;
          case OpCode.Conv_R_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_R_Un, CoreSystemTypes.Double); break;
          case OpCode.Unbox: expr = ParseTypeCheck(PopOperand(), (TypeNode)this.GetMemberFromToken(), NodeType.Unbox); break;
          case OpCode.Throw: statement = new Throw(PopOperand()); transferStatement = true; goto done;
          case OpCode.Ldfld: 
            expr = new MemberBinding(PopOperand(), this.GetMemberFromToken(), this.isVolatile, this.alignment);
            break;
          case OpCode.Ldflda: 
            expr = SetType(new UnaryExpression(new MemberBinding(PopOperand(), this.GetMemberFromToken(), this.isVolatile, this.alignment), NodeType.AddressOf)); 
            break;
          case OpCode.Stfld: statement = this.ParseStoreField(); goto done;
          case OpCode.Ldsfld: expr = new MemberBinding(null, this.GetMemberFromToken(), this.isVolatile, this.alignment); break;
          case OpCode.Ldsflda: expr = SetType(new UnaryExpression(new MemberBinding(null, this.GetMemberFromToken(), this.isVolatile, this.alignment), NodeType.AddressOf)); break;
          case OpCode.Stsfld: statement = new AssignmentStatement(new MemberBinding(null, this.GetMemberFromToken(), this.isVolatile, this.alignment), PopOperand()); goto done;
          case OpCode.Stobj: statement = this.ParseStoreIndirect((TypeNode)this.GetMemberFromToken()); goto done;
          case OpCode.Conv_Ovf_I1_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I1_Un, CoreSystemTypes.Int8); break;
          case OpCode.Conv_Ovf_I2_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I2_Un, CoreSystemTypes.Int16); break;
          case OpCode.Conv_Ovf_I4_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I4_Un, CoreSystemTypes.Int32); break;
          case OpCode.Conv_Ovf_I8_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I8_Un, CoreSystemTypes.Int64); break;
          case OpCode.Conv_Ovf_U1_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U1_Un, CoreSystemTypes.UInt8); break;
          case OpCode.Conv_Ovf_U2_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U2_Un, CoreSystemTypes.UInt16); break;
          case OpCode.Conv_Ovf_U4_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U4_Un, CoreSystemTypes.UInt32); break;
          case OpCode.Conv_Ovf_U8_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U8_Un, CoreSystemTypes.UInt64); break;
          case OpCode.Conv_Ovf_I_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I_Un, CoreSystemTypes.IntPtr); break;
          case OpCode.Conv_Ovf_U_Un: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U_Un, CoreSystemTypes.UIntPtr); break;
          case OpCode.Box: 
            TypeNode t = (TypeNode)this.GetMemberFromToken();
            TypeNode bt = t is EnumNode ? CoreSystemTypes.Enum : CoreSystemTypes.ValueType;
            expr = new BinaryExpression(PopOperand(), new Literal(t, CoreSystemTypes.Type), NodeType.Box, bt); break;
          case OpCode.Newarr: expr = this.ParseNewArray(); break;
          case OpCode.Ldlen: expr = new UnaryExpression(PopOperand(), NodeType.Ldlen, CoreSystemTypes.UIntPtr); break;
          case OpCode.Ldelema: expr = this.ParseArrayElementLoadAddress(); break;
          case OpCode.Ldelem_I1: 
          case OpCode.Ldelem_U1: 
          case OpCode.Ldelem_I2: 
          case OpCode.Ldelem_U2: 
          case OpCode.Ldelem_I4: 
          case OpCode.Ldelem_U4: 
          case OpCode.Ldelem_I8: 
          case OpCode.Ldelem_I: 
          case OpCode.Ldelem_R4: 
          case OpCode.Ldelem_R8: 
          case OpCode.Ldelem_Ref: expr = this.ParseArrayElementLoad(opCode, null); break;
          case OpCode.Stelem_I:
          case OpCode.Stelem_I1:
          case OpCode.Stelem_I2:
          case OpCode.Stelem_I4:
          case OpCode.Stelem_I8:
          case OpCode.Stelem_R4:
          case OpCode.Stelem_R8:
          case OpCode.Stelem_Ref: statement = this.ParseArrayElementAssignment(opCode); goto done;
          case OpCode.Ldelem: expr = this.ParseArrayElementLoad(opCode, null); break;
          case OpCode.Stelem: statement = this.ParseArrayElementAssignment(opCode); goto done;
          case OpCode.Unbox_Any: expr = ParseTypeCheck(PopOperand(), (TypeNode)this.GetMemberFromToken(), NodeType.UnboxAny); break;
          case OpCode.Conv_Ovf_I1: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I1, CoreSystemTypes.Int8); break;
          case OpCode.Conv_Ovf_U1: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U1, CoreSystemTypes.UInt8); break;
          case OpCode.Conv_Ovf_I2: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I2, CoreSystemTypes.Int16); break;
          case OpCode.Conv_Ovf_U2: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U2, CoreSystemTypes.UInt16); break;
          case OpCode.Conv_Ovf_I4: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I4, CoreSystemTypes.Int32); break;
          case OpCode.Conv_Ovf_U4: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U4, CoreSystemTypes.UInt32); break;
          case OpCode.Conv_Ovf_I8: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I8, CoreSystemTypes.Int64); break;
          case OpCode.Conv_Ovf_U8: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U8, CoreSystemTypes.UInt64); break;
          case OpCode.Refanyval: expr = new BinaryExpression(PopOperand(), new Literal(this.GetMemberFromToken(), CoreSystemTypes.Type), NodeType.Refanyval, CoreSystemTypes.IntPtr); break;
          case OpCode.Ckfinite: expr = this.ParseUnaryOperation(NodeType.Ckfinite); break;
          case OpCode.Mkrefany: expr = new BinaryExpression(PopOperand(), new Literal(this.GetMemberFromToken(), CoreSystemTypes.Type), NodeType.Mkrefany, CoreSystemTypes.DynamicallyTypedReference); break;
          case OpCode.Ldtoken: expr = ParseLoadRuntimeMetadataToken(); break;
          case OpCode.Conv_U2: expr = new UnaryExpression(PopOperand(), NodeType.Conv_U2, CoreSystemTypes.UInt16); break;
          case OpCode.Conv_U1: expr = new UnaryExpression(PopOperand(), NodeType.Conv_U1, CoreSystemTypes.UInt8); break;
          case OpCode.Conv_I: expr = new UnaryExpression(PopOperand(), NodeType.Conv_I, CoreSystemTypes.IntPtr); break;
          case OpCode.Conv_Ovf_I: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_I, CoreSystemTypes.IntPtr); break;
          case OpCode.Conv_Ovf_U: expr = new UnaryExpression(PopOperand(), NodeType.Conv_Ovf_U, CoreSystemTypes.UIntPtr); break;
          case OpCode.Add_Ovf: expr = this.ParseBinaryOperation(NodeType.Add_Ovf); break;
          case OpCode.Add_Ovf_Un: expr = this.ParseBinaryOperation(NodeType.Add_Ovf_Un); break;
          case OpCode.Mul_Ovf: expr = this.ParseBinaryOperation(NodeType.Mul_Ovf); break;
          case OpCode.Mul_Ovf_Un: expr = this.ParseBinaryOperation(NodeType.Mul_Ovf_Un); break;
          case OpCode.Sub_Ovf: expr = this.ParseBinaryOperation(NodeType.Sub_Ovf); break;
          case OpCode.Sub_Ovf_Un: expr = this.ParseBinaryOperation(NodeType.Sub_Ovf_Un); break;
          case OpCode.Endfinally: statement = new EndFinally(); transferStatement = true; goto done;
          case OpCode.Leave: statement = this.ParseBranch(NodeType.Nop, 0, false, false, true); transferStatement = true; goto done;
          case OpCode.Leave_S: statement = this.ParseBranch(NodeType.Nop, 0, true, false, true); transferStatement = true; goto done;
          case OpCode.Stind_I: statement = this.ParseStoreIndirect(CoreSystemTypes.IntPtr); goto done;
          case OpCode.Conv_U: expr = new UnaryExpression(PopOperand(), NodeType.Conv_U, CoreSystemTypes.UIntPtr); break;
          case OpCode.Arglist: expr = new Expression(NodeType.Arglist, CoreSystemTypes.ArgIterator); break;
          case OpCode.Ceq: expr = this.ParseBinaryComparison(NodeType.Ceq); break;
          case OpCode.Cgt: expr = this.ParseBinaryComparison(NodeType.Cgt); break;
          case OpCode.Cgt_Un: expr = this.ParseBinaryComparison(NodeType.Cgt_Un); break;
          case OpCode.Clt: expr = this.ParseBinaryComparison(NodeType.Clt); break;
          case OpCode.Clt_Un: expr = this.ParseBinaryComparison(NodeType.Clt_Un); break;
          case OpCode.Ldftn: expr = new UnaryExpression(new MemberBinding(null, this.GetMemberFromToken()), NodeType.Ldftn, CoreSystemTypes.IntPtr); break;
          case OpCode.Ldvirtftn: expr = new BinaryExpression(PopOperand(), new MemberBinding(null, this.GetMemberFromToken()), NodeType.Ldvirtftn, CoreSystemTypes.IntPtr); break;
          case OpCode.Ldarg: expr = this.Parameters((ushort)this.GetInt16()); break;
          case OpCode.Ldarga: expr = SetType(new UnaryExpression(this.Parameters((ushort)this.GetInt16()), NodeType.AddressOf)); break;
          case OpCode.Starg: statement = new AssignmentStatement(this.Parameters((ushort)this.GetInt16()), PopOperand()); goto done;
          case OpCode.Ldloc: expr = this.locals[(ushort)this.GetInt16()]; break;
          case OpCode.Ldloca: expr = SetType(new UnaryExpression(this.locals[(ushort)this.GetInt16()], NodeType.AddressOf)); break;
          case OpCode.Stloc: statement = new AssignmentStatement(this.locals[(ushort)this.GetInt16()], PopOperand()); goto done;
          case OpCode.Localloc: expr = new UnaryExpression(PopOperand(), NodeType.Localloc, CoreSystemTypes.Void); break;
          case OpCode.Endfilter: statement = new EndFilter(PopOperand()); transferStatement = true; goto done;
          case OpCode.Unaligned_: this.alignment = this.GetByte(); continue;
          case OpCode.Volatile_: this.isVolatile = true; continue;
          case OpCode.Tail_: this.isTailCall = true; continue;
          case OpCode.Initobj: statement = this.ParseInitObject(); goto done;
          case OpCode.Constrained_: this.constraint = this.GetMemberFromToken() as TypeNode; continue;
          case OpCode.Cpblk: expr = this.ParseTernaryOperation(NodeType.Cpblk); goto done;
          case OpCode.Initblk: expr = this.ParseTernaryOperation(NodeType.Initblk); goto done;
          case OpCode.Rethrow: statement = new Throw(null); statement.NodeType = NodeType.Rethrow; transferStatement = true; goto done;
          case OpCode.Sizeof: expr = new UnaryExpression(new Literal(this.GetMemberFromToken(), CoreSystemTypes.Type), NodeType.Sizeof, CoreSystemTypes.Int32); break;
          case OpCode.Refanytype: expr = new UnaryExpression(PopOperand(), NodeType.Refanytype, CoreSystemTypes.RuntimeTypeHandle); break;
          case OpCode.Readonly_: this.isReadOnly = true; continue;
          default: throw new InvalidMetadataException(ExceptionStrings.UnknownOpCode);
        }
        if (this.blockMap[this.counter+1] != null){
          transferStatement = true; //Falls through to the next basic block, so implicitly a "transfer" statement
          goto done;
        }
        //^ assume expr != null;
#if FxCop
        expr.sourceContext = sourceContext;
#endif
#if FxCop || ILOFFSETS
        expr.ILOffset = this.ilOffset;
#endif
        this.operandStack.Push(expr);
        this.isReadOnly = false;
        this.isVolatile = false;
        this.isTailCall = false;        
        this.alignment = -1;
      }
    done:
      for (int i = 0; i <= this.operandStack.top; i++){
        Expression e = this.operandStack.elements[i];
        //^ assume e != null;
        Statement s = new ExpressionStatement(e);
#if FxCop
        s.SourceContext = this.sourceContext;
#endif
#if FxCop || ILOFFSETS
        s.ILOffset = this.ilOffset;
#endif
        statementList.Add(s);
      }
      this.operandStack.top = -1;
      if (statement == null) {
        statement = new ExpressionStatement(expr);
#if FxCop
        expr.sourceContext = this.sourceContext;
#endif
#if FxCop || ILOFFSETS
        expr.ILOffset = this.ilOffset;
#endif
      }
      statement.SourceContext = sourceContext;
#if FxCop || ILOFFSETS
      statement.ILOffset = this.ilOffset;
#endif
#if ILOFFSETS
      this.lastSourceContext = sourceContext;
#endif
      statementList.Add(statement);
      if (transferStatement) return true;
      return this.blockMap[this.counter+1] != null;
    }
예제 #14
0
파일: Reader.cs 프로젝트: modulexcite/IL2JS
    internal Instruction ParseInstruction(){
      if (this.counter >= this.size) 
        return null;
      int offset = this.counter;
#if !ROTOR
      if (this.method.contextForOffset != null){
        object sctx = this.method.contextForOffset[offset+1];
        if (sctx != null) this.sourceContext = (SourceContext)sctx;
      }
#endif
      object value = null;
      OpCode opCode = this.GetOpCode();    
      switch(opCode){
        case OpCode.Nop:
        case OpCode.Break: 
          break;
        case OpCode.Ldarg_0: value = this.Parameters(0); break;
        case OpCode.Ldarg_1: value = this.Parameters(1); break;
        case OpCode.Ldarg_2: value = this.Parameters(2); break; 
        case OpCode.Ldarg_3: value = this.Parameters(3); break;
        case OpCode.Ldloc_0: value = this.locals[0]; break;
        case OpCode.Ldloc_1: value = this.locals[1]; break;
        case OpCode.Ldloc_2: value = this.locals[2]; break;
        case OpCode.Ldloc_3: value = this.locals[3]; break;
        case OpCode.Stloc_0: value = this.locals[0]; break;
        case OpCode.Stloc_1: value = this.locals[1]; break;
        case OpCode.Stloc_2: value = this.locals[2]; break;
        case OpCode.Stloc_3: value = this.locals[3]; break;
        case OpCode.Ldarg_S:  
        case OpCode.Ldarga_S:
        case OpCode.Starg_S:
          value = this.Parameters(this.GetByte()); break;
        case OpCode.Ldloc_S:
        case OpCode.Ldloca_S:
        case OpCode.Stloc_S:
          value = this.locals[this.GetByte()]; break;
        case OpCode.Ldnull: 
          break;
        case OpCode.Ldc_I4_M1: value = (Int32)(-1); break;
        case OpCode.Ldc_I4_0: value = (Int32)0; break;
        case OpCode.Ldc_I4_1: value = (Int32)1; break;
        case OpCode.Ldc_I4_2: value = (Int32)2; break;
        case OpCode.Ldc_I4_3: value = (Int32)3; break;
        case OpCode.Ldc_I4_4: value = (Int32)4; break;
        case OpCode.Ldc_I4_5: value = (Int32)5; break;
        case OpCode.Ldc_I4_6: value = (Int32)6; break;
        case OpCode.Ldc_I4_7: value = (Int32)7; break;
        case OpCode.Ldc_I4_8: value = (Int32)8; break;
        case OpCode.Ldc_I4_S: value = (Int32)this.GetSByte(); break;
        case OpCode.Ldc_I4: value = this.GetInt32(); break;
        case OpCode.Ldc_I8: value = this.GetInt64(); break;
        case OpCode.Ldc_R4: value = this.GetSingle(); break;
        case OpCode.Ldc_R8: value = this.GetDouble(); break;
        case OpCode.Dup:
        case OpCode.Pop: 
          break;
        case OpCode.Jmp: 
        case OpCode.Call:
          value = (Method)this.GetMemberFromToken(); break;
        case OpCode.Calli: 
          value = (FunctionPointer)this.reader.GetCalliSignature(this.GetInt32()); break;
        case OpCode.Ret: break;
        case OpCode.Br_S:
        case OpCode.Brfalse_S:
        case OpCode.Brtrue_S:
        case OpCode.Beq_S:
        case OpCode.Bge_S:
        case OpCode.Bgt_S:
        case OpCode.Ble_S:
        case OpCode.Blt_S:
        case OpCode.Bne_Un_S:
        case OpCode.Bge_Un_S:
        case OpCode.Bgt_Un_S:
        case OpCode.Ble_Un_S:
        case OpCode.Blt_Un_S:
          value = this.counter + 1 + this.GetSByte(); break;
        case OpCode.Br:
        case OpCode.Brfalse:
        case OpCode.Brtrue:
        case OpCode.Beq:
        case OpCode.Bge:
        case OpCode.Bgt:
        case OpCode.Ble:
        case OpCode.Blt:
        case OpCode.Bne_Un:
        case OpCode.Bge_Un:
        case OpCode.Bgt_Un:
        case OpCode.Ble_Un:
        case OpCode.Blt_Un:
          value = this.counter + 4 + this.GetInt32(); break;
        case OpCode.Switch: value = this.ParseSwitchInstruction(); break;        
        case OpCode.Ldind_I1: 
        case OpCode.Ldind_U1:
        case OpCode.Ldind_I2:
        case OpCode.Ldind_U2:
        case OpCode.Ldind_I4:
        case OpCode.Ldind_U4:
        case OpCode.Ldind_I8:
        case OpCode.Ldind_I:
        case OpCode.Ldind_R4:
        case OpCode.Ldind_R8:
        case OpCode.Ldind_Ref:
        case OpCode.Stind_Ref:
        case OpCode.Stind_I1:
        case OpCode.Stind_I2:
        case OpCode.Stind_I4:
        case OpCode.Stind_I8:
        case OpCode.Stind_R4:
        case OpCode.Stind_R8:
        case OpCode.Add:
        case OpCode.Sub:
        case OpCode.Mul:
        case OpCode.Div:
        case OpCode.Div_Un:
        case OpCode.Rem:
        case OpCode.Rem_Un:
        case OpCode.And:
        case OpCode.Or:
        case OpCode.Xor:
        case OpCode.Shl:
        case OpCode.Shr:
        case OpCode.Shr_Un:
        case OpCode.Neg:
        case OpCode.Not:
        case OpCode.Conv_I1:
        case OpCode.Conv_I2:
        case OpCode.Conv_I4:
        case OpCode.Conv_I8:
        case OpCode.Conv_R4:
        case OpCode.Conv_R8:
        case OpCode.Conv_U4:
        case OpCode.Conv_U8:
          break;
        case OpCode.Callvirt: value = (Method)this.GetMemberFromToken(); break;
        case OpCode.Cpobj:
        case OpCode.Ldobj: 
          value = (TypeNode)this.GetMemberFromToken(); break;
        case OpCode.Ldstr: value = this.GetStringFromToken(); break;          
        case OpCode.Newobj: value = (Method)this.GetMemberFromToken();break;
        case OpCode.Castclass:
        case OpCode.Isinst: 
          value = (TypeNode)this.GetMemberFromToken(); break;
        case OpCode.Conv_R_Un: break;       
        case OpCode.Unbox: value = (TypeNode)this.GetMemberFromToken(); break;
        case OpCode.Throw: break;
        case OpCode.Ldfld: 
        case OpCode.Ldflda:
        case OpCode.Stfld:
        case OpCode.Ldsfld:
        case OpCode.Ldsflda:
        case OpCode.Stsfld:
        case OpCode.Stobj:
          value = this.GetMemberFromToken(); break;
        case OpCode.Conv_Ovf_I1_Un:
        case OpCode.Conv_Ovf_I2_Un:
        case OpCode.Conv_Ovf_I4_Un:
        case OpCode.Conv_Ovf_I8_Un:
        case OpCode.Conv_Ovf_U1_Un:
        case OpCode.Conv_Ovf_U2_Un:
        case OpCode.Conv_Ovf_U4_Un:
        case OpCode.Conv_Ovf_U8_Un:
        case OpCode.Conv_Ovf_I_Un:
        case OpCode.Conv_Ovf_U_Un:
          break;
        case OpCode.Box:
        case OpCode.Newarr: value = (TypeNode)this.GetMemberFromToken(); break;
        case OpCode.Ldlen: break;
        case OpCode.Ldelema: value = (TypeNode)this.GetMemberFromToken(); break;
        case OpCode.Ldelem_I1:
        case OpCode.Ldelem_U1:
        case OpCode.Ldelem_I2:
        case OpCode.Ldelem_U2:
        case OpCode.Ldelem_I4:
        case OpCode.Ldelem_U4:
        case OpCode.Ldelem_I8:
        case OpCode.Ldelem_I:
        case OpCode.Ldelem_R4:
        case OpCode.Ldelem_R8:
        case OpCode.Ldelem_Ref: 
        case OpCode.Stelem_I:
        case OpCode.Stelem_I1:
        case OpCode.Stelem_I2:
        case OpCode.Stelem_I4:
        case OpCode.Stelem_I8:
        case OpCode.Stelem_R4:
        case OpCode.Stelem_R8:
        case OpCode.Stelem_Ref:
          break;
        case OpCode.Ldelem: 
          value = (TypeNode)this.GetMemberFromToken();
          break;
        case OpCode.Stelem: value = (TypeNode)this.GetMemberFromToken(); break;
        case OpCode.Unbox_Any: value = this.GetMemberFromToken(); break;
        case OpCode.Conv_Ovf_I1:
        case OpCode.Conv_Ovf_U1:
        case OpCode.Conv_Ovf_I2:
        case OpCode.Conv_Ovf_U2:
        case OpCode.Conv_Ovf_I4:
        case OpCode.Conv_Ovf_U4:
        case OpCode.Conv_Ovf_I8:
        case OpCode.Conv_Ovf_U8:
          break;
        case OpCode.Refanyval: value = this.GetMemberFromToken(); break;
        case OpCode.Ckfinite: break;
        case OpCode.Mkrefany: value = this.GetMemberFromToken(); break;
        case OpCode.Ldtoken: value = this.GetMemberFromToken(); break;
        case OpCode.Conv_U2:
        case OpCode.Conv_U1:
        case OpCode.Conv_I:
        case OpCode.Conv_Ovf_I:
        case OpCode.Conv_Ovf_U:
        case OpCode.Add_Ovf:
        case OpCode.Add_Ovf_Un:
        case OpCode.Mul_Ovf:
        case OpCode.Mul_Ovf_Un:
        case OpCode.Sub_Ovf:
        case OpCode.Sub_Ovf_Un:
        case OpCode.Endfinally: 
          break;
        case OpCode.Leave:   value = this.counter + 4 + this.GetInt32(); break; 
        case OpCode.Leave_S: value = this.counter + 1 + this.GetSByte(); break;
        case OpCode.Stind_I:
        case OpCode.Conv_U:
        case OpCode.Prefix7:
        case OpCode.Prefix6:
        case OpCode.Prefix5:
        case OpCode.Prefix4:
        case OpCode.Prefix3:
        case OpCode.Prefix2:
        case OpCode.Prefix1:
        case OpCode.Arglist:
        case OpCode.Ceq:
        case OpCode.Cgt:
        case OpCode.Cgt_Un:
        case OpCode.Clt:
        case OpCode.Clt_Un:
          break;
        case OpCode.Ldftn:
        case OpCode.Ldvirtftn:
          value = this.GetMemberFromToken(); break;
        case OpCode.Ldarg:
        case OpCode.Ldarga:
        case OpCode.Starg:
          value = this.Parameters(this.GetInt16()); break;
        case OpCode.Ldloc:
        case OpCode.Ldloca:
        case OpCode.Stloc:
          value = this.locals[this.GetInt16()]; break;
        case OpCode.Localloc:
        case OpCode.Endfilter:
          break;
        case OpCode.Unaligned_: value = this.GetByte(); break;
        case OpCode.Volatile_:
        case OpCode.Tail_:
          break;
        case OpCode.Initobj: value = (TypeNode)this.GetMemberFromToken(); break;
        case OpCode.Constrained_: value = this.GetMemberFromToken() as TypeNode; break;
        case OpCode.Cpblk: 
        case OpCode.Initblk:
          break;
        case OpCode.Rethrow:
          break;
        case OpCode.Sizeof: value = this.GetMemberFromToken(); break;
        case OpCode.Refanytype:
        case OpCode.Readonly_:
          break;
        default: throw new InvalidMetadataException(String.Format(CultureInfo.CurrentCulture, 
          ExceptionStrings.UnknownOpCodeEncountered, opCode.ToString("x")));
      }
      Instruction instruction = new Instruction(opCode, offset, value);
      instruction.SourceContext = this.sourceContext;
      return instruction;
    }
예제 #15
0
        private void CopyAbbreviatorContracts(Method targetMethod, Method abbreviatorMethodInstance,
            Expression targetObject, ExpressionList actuals, RequiresList Preconditions, EnsuresList Postconditions,
            SourceContext useSite, RequiresList validations, Block contractInitializer)
        {
            Contract.Requires(validations != null);

            // make sure to have extracted contracts from the abbreviator method prior
            if (abbreviatorMethodInstance.DeclaringType.DeclaringModule == targetMethod.DeclaringType.DeclaringModule)
            {
                var abbrevMethod = abbreviatorMethodInstance;

                while (abbrevMethod.Template != null)
                {
                    abbrevMethod = abbrevMethod.Template;
                }

                this.VisitMethod(abbrevMethod);
            }

            if (abbreviatorMethodInstance.Contract == null) return;

            var copier = new AbbreviationDuplicator(abbreviatorMethodInstance, targetMethod, this.contractNodes,
                abbreviatorMethodInstance, targetObject, actuals);

            var abbrevContract = HelperMethods.DuplicateContractAndClosureParts(copier, targetMethod,
                abbreviatorMethodInstance, this.contractNodes, true);

            if (abbrevContract == null) return;

            if (HelperMethods.IsNonTrivial(abbrevContract.ContractInitializer))
            {
                contractInitializer.Statements.Add(abbrevContract.ContractInitializer);
            }

            MoveAbbreviatorRequires(targetMethod, abbrevContract.Requires, Preconditions, validations, useSite);
            MoveAbbreviatorEnsures(targetMethod, abbrevContract.Ensures, Postconditions, useSite);
        }
예제 #16
0
        internal static bool FindContext(Block currentClump, SourceContext initialSourceContext, out SourceContext sctx)
        {
            sctx = initialSourceContext;

            if (currentClump == null || currentClump.Statements == null || currentClump.Statements.Count <= 0)
                return false;

            for (int i = 0, n = currentClump.Statements.Count; i < n; i++)
            {
                Block b = currentClump.Statements[i] as Block;
                
                if (b == null || b.Statements == null || b.Statements.Count <= 0) continue;
                
                for (int j = 0, m = b.Statements.Count; j < m; j++)
                {
                    Statement s = b.Statements[j];
                    if (s == null) continue;

                    if (s.NodeType != NodeType.Nop
                        // these are the source contexts the compiler puts in that correspond to things like method declarations, etc.
                        && s.SourceContext.IsValid)
                    {
                        sctx = s.SourceContext;
                        return true;
                    }
                }
            }

            return false;
        }
 public ContractAssumeAssertStatement(Expression expression, SourceContext sctx, string sourceText)
     : base(expression, sctx)
 {
     this.SourceText = sourceText;
 }
예제 #18
0
    private Method CreateWrapperMethod(bool virtcall, TypeNode virtcallConstraint, Method templateMethod, TypeNode templateType, TypeNode wrapperType, Method methodWithContract, Method instanceMethod, SourceContext callingContext)
    {
      bool isProtected = IsProtected(templateMethod);
      Identifier name = templateMethod.Name;
      if (virtcall) {
        if (virtcallConstraint != null) {
          name = Identifier.For("CV$" + name.Name);
        }
        else {
          name = Identifier.For("V$" + name.Name);
        }
      }
      else {
        name = Identifier.For("NV$" + name.Name);
      }
      Duplicator dup = new Duplicator(this.assemblyBeingRewritten, wrapperType);
      TypeNodeList typeParameters = null;
      TypeNodeList typeParameterFormals = new TypeNodeList();
      TypeNodeList typeParameterActuals = new TypeNodeList();

      if (templateMethod.TemplateParameters != null) {
        dup.FindTypesToBeDuplicated(templateMethod.TemplateParameters);
        typeParameters = dup.VisitTypeParameterList(templateMethod.TemplateParameters);
        for (int i = 0; i < typeParameters.Count; i++) {
          typeParameterFormals.Add(typeParameters[i]);
          typeParameterActuals.Add(templateMethod.TemplateParameters[i]);
        }
      }
      ITypeParameter constraintTypeParam = null;
      if (virtcallConstraint != null) {
        if (typeParameters == null) { typeParameters = new TypeNodeList(); }
        var constraint = templateMethod.DeclaringType;
        var classConstraint = constraint as Class;
        if (classConstraint != null) {
          var classParam = new MethodClassParameter();
          classParam.BaseClass = classConstraint;
          classParam.Name = Identifier.For("TC");
          classParam.DeclaringType = wrapperType;
          typeParameters.Add(classParam);
          constraintTypeParam = classParam;
        }
        else {
          var mtp = new MethodTypeParameter();
          Interface intf = constraint as Interface;
          if (intf != null) {
            mtp.Interfaces.Add(intf);
          }
          mtp.Name = Identifier.For("TC");
          mtp.DeclaringType = wrapperType;
          typeParameters.Add(mtp);
          constraintTypeParam = mtp;
        }
      }
      var consolidatedTemplateTypeParameters = templateType.ConsolidatedTemplateParameters;
      if (consolidatedTemplateTypeParameters != null && consolidatedTemplateTypeParameters.Count > 0) {
        var consolidatedWrapperTypeParameters = wrapperType.ConsolidatedTemplateParameters;
        for (int i = 0; i < consolidatedTemplateTypeParameters.Count; i++) {
          typeParameterFormals.Add(consolidatedWrapperTypeParameters[i]);
          typeParameterActuals.Add(consolidatedTemplateTypeParameters[i]);
        }
      }
      Specializer spec = null;
      if (typeParameterActuals.Count > 0) {
        spec = new Specializer(this.assemblyBeingRewritten, typeParameterActuals, typeParameterFormals);
      }
      var parameters = new ParameterList();
      var asTypeConstraintTypeParam = constraintTypeParam as TypeNode;

      if (!isProtected && !templateMethod.IsStatic) {
        TypeNode thisType = GetThisTypeInstance(templateType, wrapperType, asTypeConstraintTypeParam);
        parameters.Add(new Parameter(Identifier.For("@this"), thisType));
      }
      for (int i = 0; i < templateMethod.Parameters.Count; i++) {
        parameters.Add((Parameter)dup.VisitParameter(templateMethod.Parameters[i]));
      }
      var retType = dup.VisitTypeReference(templateMethod.ReturnType);
      if (spec != null) {
        parameters = spec.VisitParameterList(parameters);
        retType = spec.VisitTypeReference(retType);
      }

      var wrapperMethod = new Method(wrapperType, null, name, parameters, retType, null);
      RewriteHelper.TryAddCompilerGeneratedAttribute(wrapperMethod);

      if (isProtected) {
        wrapperMethod.Flags = templateMethod.Flags & ~MethodFlags.Abstract;
        wrapperMethod.CallingConvention = templateMethod.CallingConvention;
      }
      else {
        wrapperMethod.Flags |= MethodFlags.Static | MethodFlags.Assembly;
      }
      if (constraintTypeParam != null) {
        constraintTypeParam.DeclaringMember = wrapperMethod;
      }
      if (typeParameters != null) {
        if (spec != null) {
          typeParameters = spec.VisitTypeParameterList(typeParameters);
        }
        wrapperMethod.IsGeneric = true;
        wrapperMethod.TemplateParameters = typeParameters;
      }

      // create body
      var sl = new StatementList();
      Block b = new Block(sl);

      // insert requires
      AddRequiresToWrapperMethod(wrapperMethod, b, methodWithContract);

      // create original call
      var targetType = templateType;
      if (isProtected)
      {
        // need to use base chain instantiation of target type.
        targetType = instanceMethod.DeclaringType;
      }
      else
      {
        if (targetType.ConsolidatedTemplateParameters != null && targetType.ConsolidatedTemplateParameters.Count > 0)
        {
          // need selfinstantiation
          targetType = targetType.GetGenericTemplateInstance(this.assemblyBeingRewritten, wrapperType.ConsolidatedTemplateParameters);
        }
      }
      Method targetMethod = GetMatchingMethod(targetType, templateMethod, wrapperMethod);
      if (targetMethod.IsGeneric) {
        if (typeParameters.Count > targetMethod.TemplateParameters.Count) {
          // omit the extra constrained type arg.
          TypeNodeList origArgs = new TypeNodeList();
          for (int i = 0; i < targetMethod.TemplateParameters.Count; i++) {
            origArgs.Add(typeParameters[i]);
          }
          targetMethod = targetMethod.GetTemplateInstance(wrapperType, origArgs);
        }
        else {
          targetMethod = targetMethod.GetTemplateInstance(wrapperType, typeParameters);
        }
      }
      MethodCall call;
      NodeType callType = virtcall ? NodeType.Callvirt : NodeType.Call;
      if (isProtected) {
        var mb = new MemberBinding(wrapperMethod.ThisParameter, targetMethod);
        var elist = new ExpressionList(wrapperMethod.Parameters.Count);
        for (int i = 0; i < wrapperMethod.Parameters.Count; i++) {
          elist.Add(wrapperMethod.Parameters[i]);
        }
        call = new MethodCall(mb, elist, callType);
      }
      else if (templateMethod.IsStatic) {
        var elist = new ExpressionList(wrapperMethod.Parameters.Count);
        for (int i = 0; i < wrapperMethod.Parameters.Count; i++) {
          elist.Add(wrapperMethod.Parameters[i]);
        }
        call = new MethodCall(new MemberBinding(null, targetMethod), elist, callType);
      }
      else {
        var mb = new MemberBinding(wrapperMethod.Parameters[0], targetMethod);
        var elist = new ExpressionList(wrapperMethod.Parameters.Count - 1);
        for (int i = 1; i < wrapperMethod.Parameters.Count; i++) {
          elist.Add(wrapperMethod.Parameters[i]);
        }
        call = new MethodCall(mb, elist, callType);
      }
      if (constraintTypeParam != null) {
        call.Constraint = asTypeConstraintTypeParam;
      }
      if (HelperMethods.IsVoidType(templateMethod.ReturnType)) {
        sl.Add(new ExpressionStatement(call,callingContext));
        sl.Add(new Return(callingContext));
      }
      else {
        sl.Add(new Return(call,callingContext));
      }
      wrapperMethod.Body = b;

      wrapperType.Members.Add(wrapperMethod);
      return wrapperMethod;
    }
예제 #19
0
    internal Method WrapperMethod(Method instanceMethod, bool virtcall, TypeNode constraint, Method methodContainingCall, Method methodWithContract, SourceContext callingContext)
    {
      // for now disable the following
      //  - protected methods
      //  - constructors
      //  - base calls
      if (IsProtected(instanceMethod)) return null;
      if (instanceMethod is InstanceInitializer) return null;
      if (!virtcall && instanceMethod.IsVirtual) return null;

      var templateMethod = instanceMethod;
      while (templateMethod.Template != null) templateMethod = templateMethod.Template;

      var templateType = templateMethod.DeclaringType;
      TypeNode wrapperType;
      if (IsProtected(instanceMethod)) {
        // can only be called on "this" of derived type, so no wrapper class
        wrapperType = methodContainingCall.DeclaringType;
        while (wrapperType.Template != null) { wrapperType = wrapperType.Template; }
      }
      else {
        wrapperType = WrapperType(templateType);
      }
      var wrapperMethod = LookupWrapperMethod(virtcall, constraint, wrapperType, templateMethod);
      if (wrapperMethod == null) {
        wrapperMethod = CreateWrapperMethod(virtcall, constraint, templateMethod, templateType, wrapperType, methodWithContract, instanceMethod, callingContext);
        StoreWrapperMethod(virtcall, constraint, templateMethod, wrapperMethod);
      }
      return InstantiateWrapperMethod(constraint, wrapperMethod, instanceMethod);
    }
예제 #20
0
 public override StatementList VisitStatementList(StatementList statements)
 {
   if (statements == null) return null;
   for (int i = 0; i < statements.Count; i++)
   {
     var stmt = statements[i];
     if (stmt == null) continue;
     if (stmt.SourceContext.IsValid)
     {
       this.lastStmtContext = stmt.SourceContext;
     }
     statements[i] = (Statement)base.Visit(stmt);
   }
   return statements;
 }
예제 #21
0
    private static Statement WrapTryCatch(Method method, Statement statement)
    {
      Block afterCatches = new Block(new StatementList());
      Block tryBlock = new Block(new StatementList());
      Block blockAfterTryBody = new Block(null);
      tryBlock.Statements.Add(statement);
      tryBlock.Statements.Add(new Branch(null, afterCatches, false, true, true));
      tryBlock.Statements.Add(blockAfterTryBody);
      Block catchBlock = new Block(new StatementList());
      // emit code that pops the exception and fools fxcop
      Block branchTargetToFoolFxCop = new Block(null);
      var branch = new Branch(new Expression(NodeType.Pop), branchTargetToFoolFxCop);
      SourceContext hiddenContext = new SourceContext(HiddenDocument.Document);
      branch.SourceContext = hiddenContext;
      catchBlock.Statements.Add(branch);
      var rethrowStatement = new Throw();
      rethrowStatement.SourceContext = hiddenContext;
      rethrowStatement.NodeType = NodeType.Rethrow;
      catchBlock.Statements.Add(rethrowStatement);
      catchBlock.Statements.Add(branchTargetToFoolFxCop);
      var leave = new Branch(null, afterCatches, false, true, true);
      leave.SourceContext = hiddenContext;
      catchBlock.Statements.Add(leave);
      Block tryCatch = new Block(new StatementList());
      tryCatch.Statements.Add(tryBlock);
      tryCatch.Statements.Add(catchBlock);
      tryCatch.Statements.Add(afterCatches);

      if (method.ExceptionHandlers == null) method.ExceptionHandlers = new ExceptionHandlerList();

      ExceptionHandler exHandler = new ExceptionHandler();
      exHandler.TryStartBlock = tryBlock;
      exHandler.BlockAfterTryEnd = blockAfterTryBody;
      exHandler.HandlerStartBlock = catchBlock;
      exHandler.BlockAfterHandlerEnd = afterCatches;
      exHandler.FilterType = SystemTypes.Exception;
      exHandler.HandlerType = NodeType.Catch;
      method.ExceptionHandlers.Add(exHandler);

      return tryCatch;
    }
예제 #22
0
        private void MoveAbbreviatorEnsures(Method targetMethod, EnsuresList ensuresList, EnsuresList Postconditions, SourceContext useSite)
        {
            if (ensuresList == null) return;

            foreach (var ens in ensuresList)
            {
                if (!ens.DefSite.IsValid)
                {
                    ens.DefSite = ens.SourceContext;
                }

                ens.SourceContext = useSite;
                // re-sanitize user message for this context
                ens.UserMessage = SanitizeUserMessage(targetMethod, ens.UserMessage, useSite);

                Postconditions.Add(ens);
            }
        }
예제 #23
0
        /// <summary>
        /// </summary>
        /// <param name="validationContractInitializer">possibly empty initializer from closures in validators. Must be added as prefix to first requires</param>
        /// <param name="validationPrefix">Possibly empty statement list of code preceeding validator call. Must be added to first
        /// requires.</param>
        private void MoveValidatorRequires(Method targetMethod, RequiresList requiresList, RequiresList Preconditions,
            SourceContext useSite, Block validationContractInitializer, Block validationPrefix)
        {
            bool isFromValidation = true;

            if (requiresList == null) return;

            foreach (RequiresPlain req in requiresList)
            {
                if (!req.DefSite.IsValid)
                {
                    req.DefSite = req.SourceContext;
                }

                req.SourceContext = useSite;
                req.IsFromValidation = isFromValidation; // mark that we copied this from a validator when necessary

                // re-sanitize user message for this context
                req.UserMessage = SanitizeUserMessage(targetMethod, req.UserMessage, useSite);

                // check if first requires and add prefixes
                if (HelperMethods.IsNonTrivial(validationPrefix))
                {
                    req.Condition =
                        new BlockExpression(
                            new Block(new StatementList(validationPrefix, new ExpressionStatement(req.Condition))));
                    validationPrefix = null;
                }
                
                if (HelperMethods.IsNonTrivial(validationContractInitializer))
                {
                    req.Condition =
                        new BlockExpression(
                            new Block(new StatementList(validationContractInitializer,
                                new ExpressionStatement(req.Condition))));
                    validationContractInitializer = null;
                }

                Preconditions.Add(req);
            }
        }
예제 #24
0
        /// <summary>
        /// Tries to find the last statement in the clump that has a valid source context.
        /// </summary>
        /// <param name="clump">The clump to search in</param>
        /// <param name="sctx">The last source context in clump</param>
        /// <returns>true iff there exists a non-zero source context in clump</returns>
        internal static bool GetLastSourceContext(StatementList clump, out SourceContext sctx)
        {
            sctx = new SourceContext();
            
            bool found = false;
            
            if (clump == null || (!(0 < clump.Count))) return found;
            
            for (int i = clump.Count - 1; 0 <= i && !found; i--)
            {
                Block b = clump[i] as Block;
                if (b == null) continue;
                
                for (int j = b.Statements == null ? 0 : b.Statements.Count - 1; 0 <= j; j--)
                {
                    Statement s = b.Statements[j];
                    if (s == null) continue;
                    
                    if (s.NodeType == NodeType.Nop) continue; // skip curlys
                    
                    sctx = s.SourceContext;
                    
                    if (sctx.IsValid)
                    {
                        found = true;
                        break;
                    }
                }
            }

            return found;
        }
예제 #25
0
        private void MoveAbbreviatorRequires(Method targetMethod, RequiresList requiresList, RequiresList Preconditions,
            RequiresList validations, SourceContext useSite)
        {
            Contract.Requires(validations != null);

            if (requiresList == null) return;

            foreach (RequiresPlain req in requiresList)
            {
                if (!req.DefSite.IsValid)
                {
                    req.DefSite = req.SourceContext;
                }

                req.SourceContext = useSite;
                req.IsFromValidation = false;

                // re-sanitize user message for this context
                req.UserMessage = SanitizeUserMessage(targetMethod, req.UserMessage, useSite);

                Preconditions.Add(req);
                validations.Add(req); // we keep everything on both lists so we can emit for validation or standard
            }
        }
예제 #26
0
파일: Reader.cs 프로젝트: modulexcite/IL2JS
 internal StatementList/*!*/ ParseStatements() {
   this.tryMap = new Dictionary<Block, List<TryNode>>();
   this.handlerMap = new Dictionary<int, Expression>();
   this.ParseHeader();
   this.CreateBlocksForBranchTargets();
   currentBlock = null;
   this.sourceContext = new SourceContext();
   while (this.counter < size) {
     if (currentBlock == null) {
       currentBlock = Reader.GetOrCreateBlock(this.blockMap, this.counter);
     }
     bool endOfBasicBlock = this.ParseStatement(currentBlock);
     if (endOfBasicBlock) {
       currentBlock.SourceContext = currentBlock.Statements[0].SourceContext;
       currentBlock = null;
     }
   }
   Reader.GetOrCreateBlock(this.blockMap, this.counter);
   int counter = 0;
   Block block = new Block();
   block.Statements = new StatementList();
   ProcessBlock(block, ref counter, this.size, null);
   return block.Statements;
 }
예제 #27
0
        /// <summary>
        /// Only allows literal and static field reference based on visibility
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        private Expression SanitizeUserMessage(Method containing, Expression expression, SourceContext sc)
        {
            if (expression == null) return null;

            Member member;
            var result = SanitizeUserMessageInternal(containing, expression, out member);
            if (result != null)
            {
                // filter by visibility
                if (member != null && !HelperMethods.IsVisibleFrom(member, containing.DeclaringType)) return null;

                return result;
            }

            this.HandleError(containing, 1065,
                "User message to contract call can only be string literal, or a static field, or static property that is at least internally visible.",
                sc);

            return null;
        }
예제 #28
0
            public override void VisitStatementList(StatementList statements)
            {
                if (statements == null) return;

                for (int i = 0; i < statements.Count; i++)
                {
                    var st = statements[i];
                    if (st != null && st.SourceContext.IsValid)
                    {
                        lastSC = st.SourceContext;
                    }
                    
                    this.Visit(st);
                }
            }
예제 #29
0
        private void BadStuff(Method method, StatementList contractClump, SourceContext defaultSourceContext)
        {
            LookForBadStuff lfbs = new LookForBadStuff(this.contractNodes);
            lfbs.CheckForBadStuff(contractClump);

            if (lfbs.ReturnStatement != null)
            {
                SourceContext sctx = lfbs.ReturnStatement.SourceContext;
                if (!sctx.IsValid)
                    sctx = defaultSourceContext;

                this.HandleError(method, 1015, "Return statement found in contract section.", sctx);
                return;
            }

            if (lfbs.BadStuffFound)
            {
                this.HandleError(method, 1016,
                    "Contract.Assert/Contract.Assume cannot be used in contract section. Use only Requires and Ensures.",
                    defaultSourceContext);
            }
        }
예제 #30
0
            public void Check(Method currentMethod)
            {
                // F:
                Contract.Requires(currentMethod != null);

                if (currentMethod.Contract == null) return;

                this.CurrentMethod = currentMethod;
                this.assignmentFound = false;
                bool errorIssued = false;
                
                for (int i = 0; i < currentMethod.Contract.RequiresCount; i++)
                {
                    var req = currentMethod.Contract.Requires[i];
                    if (req == null) continue;

                    this.lastSourceContext = req.SourceContext;
                    
                    this.Visit(req);
                    
                    if (this.assignmentFound)
                    {
                        errorIssued = true;
                        
                        this.errorHandler(new Error(1004,
                            "Malformed contract. Found Requires after assignment in method '"
                            + currentMethod.FullName + "'.", req.SourceContext));
                        
                        break;
                    }
                }

                if (errorIssued) return;
                
                for (int i = 0; i < currentMethod.Contract.EnsuresCount; i++)
                {
                    var ens = currentMethod.Contract.Ensures[i];
                    if (ens == null) continue;

                    this.lastSourceContext = ens.SourceContext;
                    this.Visit(ens);
                    
                    if (this.assignmentFound)
                    {
                        errorIssued = true;
                        
                        this.errorHandler(new Error(1005,
                            "Malformed contract. Found Ensures after assignment in method '"
                            + currentMethod.FullName + "'.", ens.SourceContext));
                        
                        break;
                    }
                }

                if (errorIssued) return;
                
                for (int i = 0; i < currentMethod.Contract.AsyncEnsuresCount; i++)
                {
                    var ens = currentMethod.Contract.AsyncEnsures[i];
                    if (ens == null) continue;
                    
                    this.lastSourceContext = ens.SourceContext;
                    
                    this.Visit(ens);
                    
                    if (this.assignmentFound)
                    {
                        errorIssued = true;
                        this.errorHandler(new Error(1005,
                            "Malformed contract. Found Ensures after assignment in method '"
                            + currentMethod.FullName + "'.", ens.SourceContext));
                        break;
                    }
                }

                if (errorIssued) return;
                
                for (int i = 0; i < currentMethod.Contract.ModelEnsuresCount; i++)
                {
                    var ens = currentMethod.Contract.ModelEnsures[i];
                    
                    if (ens == null) continue;
                    
                    this.lastSourceContext = ens.SourceContext;

                    this.Visit(ens);

                    if (this.assignmentFound)
                    {
                        errorIssued = true;
                        
                        this.errorHandler(new Error(1005,
                            "Malformed contract. Found Ensures after assignment in method '"
                            + currentMethod.FullName + "'.", ens.SourceContext));
                        
                        break;
                    }
                }
            }
예제 #31
0
        private bool CheckClump(Method method, GatherLocals gatherLocals, SourceContext sctx, Block clump)
        {
            if (!HelperMethods.ClumpIsClosed(clump.Statements))
            {
                this.contractNodes.CallErrorFound(new Error(1017,
                    "Malformed contract section in method '" + method.FullName + "'", sctx));
                return false;
                //            throw new ExtractorException();
            }

            TypeNode t = method.DeclaringType;
            bool IsContractTypeForSomeOtherType = t == null
                ? false
                : HelperMethods.GetTypeFromAttribute(t, ContractNodes.ContractClassForAttributeName) != null;

            // We require that a contract class implement the interface it is holding contracts for. In addition, the methods in that class must be explicit
            // interface implementations. This creates a problem when the contracts need to refer to other methods in the interface. The "this" reference has
            // the wrong type: it needs to be the interface type. Writing an explicit cast before every reference is painful. It is better to allow the user
            // to create a local variable of the interface type and assign it before the contracts. This can't cause a problem with the local being used later
            // in the method body, because methods in contract classes don't have method bodies, just contracts. So don't check for re-use of locals for such
            // methods.
            //

            // Example of above comment

            //[ContractClass(typeof(ContractForJ))]
            //interface J{
            //  bool M(int x);
            //  [Pure]
            //  bool P { get; }
            //}

            //[ContractClassFor(typeof(J))]
            //class ContractForJ : J{
            //  bool J.M(int x) {
            //    J jThis = this;
            //    Contract.Requires(x != 3);
            //    Contract.Requires(jThis.P);
            //    Contract.Ensures(x != 5 || !jThis.P);
            //    return default(bool);
            //  }
            //  bool J.P {
            //    get {
            //      Contract.Ensures(Contract.Result<bool>());
            //      return default(bool);
            //    }
            //  }
            //}

            if (!IsContractTypeForSomeOtherType)
            {
                // First, make sure the clump doesn't use any locals that were used
                // in any previous contract, need a new instance each time
                CheckLocals checkLocals = new CheckLocals(gatherLocals);
                checkLocals.Visit(clump);

                if (!this.fSharp && checkLocals.reUseOfExistingLocal != null)
                {
                    this.HandleError(method, 1040,
                        "Reuse of existing local variable '" + checkLocals.reUseOfExistingLocal.Name.Name +
                        "' in contract.", sctx);
                    return false;
                }

                // If that test passes, then add in the locals used in the clump into the table of locals that have been used
                gatherLocals.Visit(clump);
            }

            return true;
        }