5 // Alexander Chebaturkin (chebaturkin@gmail.com)
7 // Copyright (C) 2011 Alexander Chebaturkin
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 using System.Collections.Generic;
31 using Mono.CodeContracts.Static.AST;
32 using Mono.CodeContracts.Static.ControlFlow.Blocks;
33 using Mono.CodeContracts.Static.ControlFlow.Subroutines.Builders;
34 using Mono.CodeContracts.Static.Providers;
36 namespace Mono.CodeContracts.Static.ControlFlow.Subroutines {
37 class MethodSubroutine<Label, Handler> : SubroutineWithHandlers<Label, Handler>, IMethodInfo {
38 private readonly Method method;
39 private HashSet<BlockWithLabels<Label>> blocks_ending_in_return_point;
41 public MethodSubroutine (SubroutineFacade subroutineFacade, Method method)
42 : base (subroutineFacade)
47 public MethodSubroutine (SubroutineFacade SubroutineFacade,
48 Method method, Label startLabel,
49 SubroutineWithHandlersBuilder<Label, Handler> builder) : base (SubroutineFacade, startLabel, builder)
52 IMetaDataProvider metaDataProvider = this.SubroutineFacade.MetaDataProvider;
53 builder.BuildBlocks (startLabel, this);
54 BlockWithLabels<Label> targetBlock = GetTargetBlock (startLabel);
57 TypeNode type = metaDataProvider.DeclaringType (method);
58 Subroutine invariant = this.SubroutineFacade.GetInvariant (type);
59 if (invariant != null && !metaDataProvider.IsConstructor (method) && !metaDataProvider.IsStatic (method)) {
60 AddEdgeSubroutine (Entry, targetBlock, invariant, EdgeTag.Entry);
61 Subroutine requires = this.SubroutineFacade.GetRequires (method);
63 AddEdgeSubroutine (Entry, targetBlock, requires, EdgeTag.Entry);
65 AddEdgeSubroutine (Entry, targetBlock, this.SubroutineFacade.GetRequires (method), EdgeTag.Entry);
67 if (this.blocks_ending_in_return_point == null)
70 Subroutine ensures = this.SubroutineFacade.GetEnsures (method);
71 bool putInvariantAfterExit = !metaDataProvider.IsStatic (method)
72 && !metaDataProvider.IsFinalizer (method) && !metaDataProvider.IsDispose (method);
73 foreach (var block in this.blocks_ending_in_return_point) {
74 if (putInvariantAfterExit)
75 AddEdgeSubroutine (block, Exit, invariant, EdgeTag.Exit);
76 AddEdgeSubroutine (block, Exit, ensures, EdgeTag.Exit);
79 if (ensures != null) {
80 throw new NotImplementedException();
83 this.blocks_ending_in_return_point = null;
86 #region Overrides of Subroutine
87 public override void Initialize ()
92 #region Overrides of SubroutineBase<Label>
93 public override void AddReturnBlock (BlockWithLabels<Label> block)
95 if (this.blocks_ending_in_return_point == null)
96 this.blocks_ending_in_return_point = new HashSet<BlockWithLabels<Label>> ();
98 this.blocks_ending_in_return_point.Add (block);
100 base.AddReturnBlock (block);
104 #region Implementation of IMethodInfo<Method>
107 get { return this.method; }
111 public override SubroutineKind Kind
113 get { return SubroutineKind.Method; }
116 public override bool HasReturnValue
118 get { return !this.SubroutineFacade.MetaDataProvider.IsVoidMethod (this.method); }
121 public override bool IsMethod
126 public override bool IsConstructor
128 get { return this.SubroutineFacade.MetaDataProvider.IsConstructor (this.method); }
131 public override string Name
133 get { return this.SubroutineFacade.MetaDataProvider.FullName (this.method); }