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;
31 using System.Collections.Generic;
34 using Mono.CodeContracts.Static.AST;
35 using Mono.CodeContracts.Static.AST.Visitors;
36 using Mono.CodeContracts.Static.Analysis.ExpressionAnalysis.Decoding;
37 using Mono.CodeContracts.Static.Analysis.HeapAnalysis.Paths;
38 using Mono.CodeContracts.Static.ControlFlow;
39 using Mono.CodeContracts.Static.DataStructures;
40 using Mono.CodeContracts.Static.Providers;
42 namespace Mono.CodeContracts.Static.Proving {
43 internal abstract class BoxedExpression {
44 public virtual bool IsVariable
49 public virtual bool IsBooleanTyped
54 public virtual object UnderlyingVariable
59 public virtual PathElement[] AccessPath
64 public virtual bool IsConstant
69 public virtual object Constant
71 get { throw new InvalidOperationException (); }
74 public virtual object ConstantType
76 get { throw new InvalidOperationException (); }
79 public virtual bool IsSizeof
84 public virtual bool IsUnary
89 public virtual UnaryOperator UnaryOperator
91 get { throw new InvalidOperationException (); }
94 public virtual BoxedExpression UnaryArgument
96 get { throw new InvalidOperationException (); }
99 public virtual bool IsBinary
101 get { return false; }
104 public virtual BinaryOperator BinaryOperator
106 get { throw new InvalidOperationException (); }
109 public virtual BoxedExpression BinaryLeftArgument
111 get { throw new InvalidOperationException (); }
114 public virtual BoxedExpression BinaryRightArgument
116 get { throw new InvalidOperationException (); }
119 public virtual bool IsIsinst
121 get { return false; }
124 public virtual bool IsNull
126 get { return false; }
129 public virtual bool IsCast
131 get { return false; }
134 public virtual bool IsResult
136 get { return false; }
139 public virtual bool TryGetType (out object type)
145 public virtual bool IsBinaryExpression (out BinaryOperator op, out BoxedExpression left, out BoxedExpression right)
147 op = BinaryOperator.Add;
153 public virtual bool IsUnaryExpression (out UnaryOperator op, out BoxedExpression argument)
155 op = UnaryOperator.Conv_i;
160 public virtual bool Sizeof (out int size)
162 return false.Without (out size);
165 public virtual bool IsIsinstExpression (out BoxedExpression expr, out TypeNode type)
172 public abstract void AddFreeVariables (HashSet<BoxedExpression> set);
174 public virtual BoxedExpression Substitute (BoxedExpression what, BoxedExpression replace)
176 if (this == what || Equals (what))
179 return RecursiveSubstitute (what, replace);
182 public abstract BoxedExpression Substitute<Variable> (Func<Variable, BoxedExpression, BoxedExpression> map);
184 protected internal virtual BoxedExpression RecursiveSubstitute (BoxedExpression what, BoxedExpression replace)
189 public abstract Result ForwardDecode<Data, Result, Visitor> (PC pc, Visitor visitor, Data data)
190 where Visitor : IILVisitor<PC, Dummy, Dummy, Data, Result>;
192 public static BoxedExpression Var (object var)
194 return new VariableExpression (var);
197 public static BoxedExpression Const (object value, TypeNode type)
199 return new ConstantExpression (value, type);
202 public static BoxedExpression For<Variable, Expression> (Expression external, IFullExpressionDecoder<Variable, Expression> decoder)
203 where Expression : IEquatable<Expression>
205 return new ExternalBox<Variable, Expression> (external, decoder);
208 public static BoxedExpression MakeIsinst (TypeNode type, BoxedExpression arg)
210 return new IsinstExpression (arg, type);
213 public static BoxedExpression Convert<Variable, ExternalExpression> (ExternalExpression expr, IFullExpressionDecoder<Variable, ExternalExpression> decoder)
217 if (decoder.IsConstant (expr, out value, out type))
218 return new ConstantExpression (value, type);
219 if (decoder.IsNull (expr))
220 return new ConstantExpression (null, null);
223 if (decoder.IsVariable (expr, out variable)) {
224 Sequence<PathElement> variableAccessPath = decoder.GetVariableAccessPath (expr);
225 return new VariableExpression (variable, variableAccessPath);
228 if (decoder.IsSizeof (expr, out type)) {
230 return decoder.TrySizeOfAsConstant (expr, out sizeAsConstant) ? new SizeOfExpression (type, sizeAsConstant) : new SizeOfExpression (type);
233 ExternalExpression arg;
234 if (decoder.IsIsinst (expr, out arg, out type))
235 return new IsinstExpression (Convert (arg, decoder), type);
238 if (decoder.IsUnaryExpression (expr, out op, out arg))
239 return new UnaryExpression (op, Convert (arg, decoder));
242 ExternalExpression left;
243 ExternalExpression right;
244 if (!decoder.IsBinaryExpression (expr, out bop, out left, out right))
245 throw new InvalidOperationException ();
247 return new BinaryExpression (bop, Convert (left, decoder), Convert (right, decoder));
250 public static BoxedExpression Binary (BinaryOperator bop, BoxedExpression left, BoxedExpression right)
252 return new BinaryExpression (bop, left, right);
255 public static BoxedExpression Unary (UnaryOperator op, BoxedExpression arg)
257 return new UnaryExpression (op, arg);
260 #region Nested type: AssertExpression
261 public class AssertExpression : ContractExpression {
262 public AssertExpression (BoxedExpression condition, EdgeTag tag, APC pc) : base (condition, tag, pc)
266 #region Overrides of ContractExpression
267 public override Result ForwardDecode<Data, Result, Visitor> (PC pc, Visitor visitor, Data data)
269 return visitor.Assert (pc, this.Tag, Dummy.Value, data);
272 public override BoxedExpression Substitute<Variable1> (Func<Variable1, BoxedExpression, BoxedExpression> map)
274 BoxedExpression cond = this.Condition.Substitute (map);
275 if (cond == this.Condition)
280 return new AssertExpression (cond, this.Tag, this.Apc);
286 #region Nested type: AssumeExpression
287 public class AssumeExpression : ContractExpression {
288 public AssumeExpression (BoxedExpression condition, EdgeTag tag, APC pc)
289 : base (condition, tag, pc)
293 #region Overrides of ContractExpression
294 public override Result ForwardDecode<Data, Result, Visitor> (PC pc, Visitor visitor, Data data)
296 return visitor.Assume (pc, this.Tag, Dummy.Value, data);
299 public override BoxedExpression Substitute<Variable1> (Func<Variable1, BoxedExpression, BoxedExpression> map)
301 BoxedExpression cond = this.Condition.Substitute (map);
302 if (cond == this.Condition)
307 return new AssumeExpression (cond, this.Tag, this.Apc);
313 #region Nested type: BinaryExpression
314 public class BinaryExpression : BoxedExpression {
315 public readonly BoxedExpression Left;
316 public readonly BinaryOperator Op;
317 public readonly BoxedExpression Right;
319 public BinaryExpression (BinaryOperator op, BoxedExpression left, BoxedExpression right)
326 public override bool IsBinary
331 public override BoxedExpression BinaryLeftArgument
333 get { return this.Left; }
336 public override BoxedExpression BinaryRightArgument
338 get { return this.Right; }
341 public override BinaryOperator BinaryOperator
343 get { return this.Op; }
346 public override bool IsBinaryExpression (out BinaryOperator op, out BoxedExpression left, out BoxedExpression right)
354 #region Overrides of BoxedExpression
355 public override void AddFreeVariables (HashSet<BoxedExpression> set)
357 this.Left.AddFreeVariables (set);
358 this.Right.AddFreeVariables (set);
361 protected internal override BoxedExpression RecursiveSubstitute (BoxedExpression what, BoxedExpression replace)
363 BoxedExpression left = this.Left.Substitute (what, replace);
364 BoxedExpression right = this.Right.Substitute (what, replace);
365 if (left == this.Left && right == this.Right)
368 return new BinaryExpression (this.Op, left, right);
371 public override BoxedExpression Substitute<Variable> (Func<Variable, BoxedExpression, BoxedExpression> map)
373 BoxedExpression left = this.Left.Substitute (map);
377 BoxedExpression right = this.Right.Substitute (map);
381 if (this.Left == left && this.Right == right)
383 return new BinaryExpression (this.Op, left, right);
386 public override Result ForwardDecode<Data, Result, Visitor> (PC pc, Visitor visitor, Data data)
388 return visitor.Binary (pc, this.Op, Dummy.Value, Dummy.Value, Dummy.Value, data);
394 #region Nested type: CastExpression
395 public class CastExpression : BoxedExpression {
396 public readonly TypeNode CastToType;
397 public readonly BoxedExpression Expr;
399 public CastExpression (TypeNode castToType, BoxedExpression expr)
401 this.CastToType = castToType;
405 public override bool IsCast
410 public override PathElement[] AccessPath
412 get { return this.Expr.AccessPath; }
415 public override BoxedExpression BinaryLeftArgument
417 get { return this.Expr.BinaryLeftArgument; }
420 public override BoxedExpression BinaryRightArgument
422 get { return this.Expr.BinaryRightArgument; }
425 public override BinaryOperator BinaryOperator
427 get { return this.Expr.BinaryOperator; }
430 public override object Constant
432 get { return this.Expr.Constant; }
435 public override object ConstantType
437 get { return this.Expr.ConstantType; }
440 public override bool IsBinary
442 get { return this.Expr.IsBinary; }
445 public override bool IsBooleanTyped
447 get { return this.Expr.IsBooleanTyped; }
450 public override bool IsConstant
452 get { return this.Expr.IsConstant; }
456 public override bool IsSizeof
458 get { return this.Expr.IsSizeof; }
461 public override bool IsNull
463 get { return this.Expr.IsNull; }
466 public override bool IsIsinst
468 get { return this.Expr.IsIsinst; }
471 public override bool IsResult
473 get { return this.Expr.IsResult; }
476 public override bool IsUnary
478 get { return this.Expr.IsUnary; }
481 public override bool IsVariable
483 get { return this.Expr.IsVariable; }
486 public override BoxedExpression UnaryArgument
488 get { return this.Expr.UnaryArgument; }
491 public override UnaryOperator UnaryOperator
493 get { return this.Expr.UnaryOperator; }
496 public override object UnderlyingVariable
498 get { return this.Expr.UnderlyingVariable; }
502 public override void AddFreeVariables (HashSet<BoxedExpression> set)
504 this.Expr.AddFreeVariables (set);
507 public override BoxedExpression Substitute<Variable> (Func<Variable, BoxedExpression, BoxedExpression> map)
509 return this.Expr.Substitute (map);
512 public override Result ForwardDecode<Data, Result, Visitor> (PC pc, Visitor visitor, Data data)
514 return this.Expr.ForwardDecode<Data, Result, Visitor> (pc, visitor, data);
517 public override bool IsBinaryExpression (out BinaryOperator op, out BoxedExpression left, out BoxedExpression right)
519 return this.Expr.IsBinaryExpression (out op, out left, out right);
522 protected internal override BoxedExpression RecursiveSubstitute (BoxedExpression what, BoxedExpression replace)
524 return this.Expr.RecursiveSubstitute (what, replace);
527 public override BoxedExpression Substitute (BoxedExpression what, BoxedExpression replace)
529 return this.Expr.Substitute (what, replace);
532 public override bool IsUnaryExpression (out UnaryOperator op, out BoxedExpression argument)
534 return this.Expr.IsUnaryExpression (out op, out argument);
539 #region Nested type: ConstantExpression
540 public class ConstantExpression : BoxedExpression {
541 public readonly TypeNode Type;
542 public readonly object Value;
543 private readonly bool is_boolean;
545 public ConstantExpression (object value, TypeNode type)
546 : this (value, type, false)
550 public ConstantExpression (object value, TypeNode type, bool isBoolean)
554 this.is_boolean = isBoolean;
557 public override bool IsBooleanTyped
559 get { return this.is_boolean; }
562 public override bool IsConstant
567 public override object Constant
569 get { return this.Value; }
572 public override object ConstantType
574 get { return this.Type; }
577 public override bool IsNull
581 if (this.Value == null)
584 var conv = this.Value as IConvertible;
587 if (conv.ToInt32 (null) == 0)
598 public override void AddFreeVariables (HashSet<BoxedExpression> set)
602 public override BoxedExpression Substitute<Variable1> (Func<Variable1, BoxedExpression, BoxedExpression> map)
607 public override Result ForwardDecode<Data, Result, Visitor> (PC pc, Visitor visitor, Data data)
609 if (this.Value == null)
610 return visitor.LoadNull (pc, Dummy.Value, data);
612 return visitor.LoadConst (pc, this.Type, this.Value, Dummy.Value, data);
617 #region Nested type: ContractExpression
618 public abstract class ContractExpression : BoxedExpression {
619 public readonly APC Apc;
620 public readonly BoxedExpression Condition;
621 public readonly EdgeTag Tag;
623 public ContractExpression (BoxedExpression condition, EdgeTag tag, APC pc)
626 this.Condition = condition;
630 public override void AddFreeVariables (HashSet<BoxedExpression> set)
632 this.Condition.AddFreeVariables (set);
635 public abstract override Result ForwardDecode<Data, Result, Visitor> (PC pc, Visitor visitor, Data data);
636 public abstract override BoxedExpression Substitute<Variable> (Func<Variable, BoxedExpression, BoxedExpression> map);
640 #region Nested type: ExternalBox
641 public class ExternalBox<Variable, LabeledSymbol> : BoxedExpression
642 where LabeledSymbol : IEquatable<LabeledSymbol> {
643 private readonly IFullExpressionDecoder<Variable, LabeledSymbol> decoder;
644 private readonly LabeledSymbol expr;
645 private Optional<Tuple<bool, BinaryOperator, BoxedExpression, BoxedExpression>> binary;
647 private Optional<Tuple<bool, object, TypeNode>> constant;
648 private Optional<Tuple<bool, BoxedExpression, TypeNode>> isInst;
649 private Optional<Pair<bool, object>> isVar;
650 private Optional<Pair<bool, TypeNode>> type;
651 private Optional<Tuple<bool, UnaryOperator, BoxedExpression>> unary;
652 private Optional<object> var;
654 public ExternalBox (LabeledSymbol external, IFullExpressionDecoder<Variable, LabeledSymbol> decoder)
656 this.expr = external;
657 this.decoder = decoder;
660 public override bool IsBinary
664 Tuple<bool, BinaryOperator, BoxedExpression, BoxedExpression> binary;
665 TryGetBinaryFromCache (out binary);
670 public override BinaryOperator BinaryOperator
674 Tuple<bool, BinaryOperator, BoxedExpression, BoxedExpression> binary;
675 bool res = TryGetBinaryFromCache (out binary);
677 throw new InvalidOperationException ();
683 public override BoxedExpression BinaryLeftArgument
687 Tuple<bool, BinaryOperator, BoxedExpression, BoxedExpression> binary;
688 bool res = TryGetBinaryFromCache (out binary);
690 throw new InvalidOperationException ();
696 public override BoxedExpression BinaryRightArgument
700 Tuple<bool, BinaryOperator, BoxedExpression, BoxedExpression> binary;
701 bool res = TryGetBinaryFromCache (out binary);
703 throw new InvalidOperationException ();
709 public override bool IsConstant
713 Tuple<bool, object, TypeNode> consta;
714 TryGetConstantFromCache (out consta);
720 public override object Constant
724 Tuple<bool, object, TypeNode> consta;
725 if (!TryGetConstantFromCache (out consta))
726 throw new InvalidOperationException ();
732 public override object ConstantType
736 Tuple<bool, object, TypeNode> consta;
737 if (!TryGetConstantFromCache (out consta))
738 throw new InvalidOperationException();
744 public override bool IsIsinst
748 Tuple<bool, BoxedExpression, TypeNode> isinst;
749 TryGetIsInstFromCache (out isinst);
754 public override bool IsNull
756 get { return this.decoder.IsNull (this.expr); }
759 public override bool IsUnary
763 Tuple<bool, UnaryOperator, BoxedExpression> unary;
764 TryGetUnaryFromCache (out unary);
769 public override UnaryOperator UnaryOperator
773 Tuple<bool, UnaryOperator, BoxedExpression> unary;
774 if (!TryGetUnaryFromCache (out unary))
775 throw new InvalidOperationException();
780 public override BoxedExpression UnaryArgument
784 Tuple<bool, UnaryOperator, BoxedExpression> unary;
785 if (!TryGetUnaryFromCache (out unary))
786 throw new InvalidOperationException ();
791 public override bool IsSizeof
796 return this.decoder.IsSizeof (this.expr, out type);
800 public override bool IsVariable
804 Pair<bool, object> var1;
805 TryGetIsVariableFromCache (out var1);
810 public override object UnderlyingVariable
814 if (!this.var.IsValid)
815 this.var = this.decoder.UnderlyingVariable (this.expr);
817 return this.var.Value;
821 private bool TryGetBinaryFromCache (out Tuple<bool, BinaryOperator, BoxedExpression, BoxedExpression> binary)
823 if (this.binary.IsValid) {
824 binary = this.binary.Value;
830 bool res = this.decoder.IsBinaryExpression (this.expr, out op, out left, out right);
831 this.binary = binary = new Tuple<bool, BinaryOperator, BoxedExpression, BoxedExpression> (res, op, For (left, this.decoder), For (right, this.decoder));
836 private bool TryGetUnaryFromCache (out Tuple<bool, UnaryOperator, BoxedExpression> unary)
838 if (this.unary.IsValid) {
839 unary = this.unary.Value;
844 bool res = this.decoder.IsUnaryExpression (this.expr, out op, out arg);
845 this.unary = unary = new Tuple<bool, UnaryOperator, BoxedExpression> (res, op, For (arg, this.decoder));
850 private bool TryGetIsInstFromCache (out Tuple<bool, BoxedExpression, TypeNode> isinst)
852 if (this.isInst.IsValid) {
853 isinst = this.isInst.Value;
859 bool res = this.decoder.IsIsinst (this.expr, out arg, out type);
860 this.isInst = isinst = new Tuple<bool, BoxedExpression, TypeNode> (res, For (arg, this.decoder), type);
865 private bool TryGetConstantFromCache (out Tuple<bool, object, TypeNode> result)
867 if (this.constant.IsValid) {
868 result = this.constant.Value;
873 bool res = this.decoder.IsConstant (this.expr, out value, out type);
874 this.constant = result = new Tuple<bool, object, TypeNode> (res, value, type);
879 private bool TryGetTypeFromCache (out Pair<bool, TypeNode> result)
881 if (this.type.IsValid) {
882 result = this.type.Value;
887 bool res = this.decoder.TryGetType (this.expr, out type);
888 this.type = result = new Pair<bool, TypeNode> (res, type);
893 private bool TryGetIsVariableFromCache (out Pair<bool, object> result)
895 if (this.isVar.IsValid) {
896 result = this.isVar.Value;
901 bool res = this.decoder.IsVariable (this.expr, out value);
902 this.isVar = result = new Pair<bool, object> (res, value);
907 public override bool IsBinaryExpression (out BinaryOperator op, out BoxedExpression left, out BoxedExpression right)
909 Tuple<bool, BinaryOperator, BoxedExpression, BoxedExpression> bin;
910 if (!TryGetBinaryFromCache (out bin) || !bin.Item1) {
911 op = BinaryOperator.Add;
923 public override bool IsIsinstExpression (out BoxedExpression expr, out TypeNode type)
925 Tuple<bool, BoxedExpression, TypeNode> isinst;
926 if (!TryGetIsInstFromCache (out isinst) || !isinst.Item1) {
937 public override bool IsUnaryExpression (out UnaryOperator op, out BoxedExpression argument)
939 Tuple<bool, UnaryOperator, BoxedExpression> unary;
940 if (!TryGetUnaryFromCache (out unary) || !unary.Item1) {
941 op = UnaryOperator.Conv_i;
947 argument = unary.Item3;
951 protected internal override BoxedExpression RecursiveSubstitute (BoxedExpression what, BoxedExpression replace)
953 return Convert (this.expr, this.decoder).Substitute (what, replace);
956 public override void AddFreeVariables (HashSet<BoxedExpression> set)
958 this.decoder.AddFreeVariables (this.expr, new SetWrapper (set, this.decoder));
961 public override BoxedExpression Substitute<V> (Func<V, BoxedExpression, BoxedExpression> map)
963 return Convert (this.expr, this.decoder).Substitute (map);
966 public override bool TryGetType (out object type)
968 Pair<bool, TypeNode> result;
969 if (!TryGetTypeFromCache (out result) || !result.Key) {
978 public override Result ForwardDecode<Data, Result, Visitor> (PC pc, Visitor visitor, Data data)
980 Tuple<bool, object, TypeNode> constant;
981 if (TryGetConstantFromCache (out constant)) {
982 if (constant.Item2 != null)
983 return visitor.LoadConst (pc, constant.Item3, constant, Dummy.Value, data);
985 return visitor.LoadNull (pc, Dummy.Value, data);
990 if (this.decoder.IsUnaryExpression (this.expr, out op, out arg))
991 return visitor.Unary (pc, op, false, Dummy.Value, Dummy.Value, data);
996 if (this.decoder.IsBinaryExpression (this.expr, out bop, out left, out right))
997 return visitor.Binary (pc, bop, Dummy.Value, Dummy.Value, Dummy.Value, data);
999 if (this.decoder.IsIsinst (this.expr, out arg, out type))
1000 return visitor.Isinst (pc, type, Dummy.Value, Dummy.Value, data);
1001 if (this.decoder.IsNull (this.expr))
1002 return visitor.LoadNull (pc, Dummy.Value, data);
1003 if (this.decoder.IsSizeof (this.expr, out type))
1004 return visitor.Sizeof (pc, type, Dummy.Value, data);
1006 return visitor.Nop (pc, data);
1009 #region Nested type: SetWrapper
1010 private struct SetWrapper : ISet<LabeledSymbol>, IEnumerable<LabeledSymbol> {
1011 private readonly IFullExpressionDecoder<Variable, LabeledSymbol> decoder;
1012 private readonly HashSet<BoxedExpression> set;
1014 #region Implementation of IEnumerable
1015 public IEnumerator<LabeledSymbol> GetEnumerator ()
1017 throw new NotImplementedException ();
1020 IEnumerator IEnumerable.GetEnumerator ()
1022 return GetEnumerator ();
1026 public SetWrapper (HashSet<BoxedExpression> set, IFullExpressionDecoder<Variable, LabeledSymbol> decoder)
1029 this.decoder = decoder;
1032 #region Implementation of ICollection<ExternalExpression>
1033 public void Add (LabeledSymbol item)
1035 this.set.Add (For (item, this.decoder));
1038 bool ISet<LabeledSymbol>.Add (LabeledSymbol item)
1044 public void UnionWith (IEnumerable<LabeledSymbol> other)
1046 throw new NotImplementedException ();
1049 public void IntersectWith (IEnumerable<LabeledSymbol> other)
1051 throw new NotImplementedException ();
1054 public void ExceptWith (IEnumerable<LabeledSymbol> other)
1056 throw new NotImplementedException ();
1059 public void SymmetricExceptWith (IEnumerable<LabeledSymbol> other)
1061 throw new NotImplementedException ();
1064 public bool IsSubsetOf (IEnumerable<LabeledSymbol> other)
1066 throw new NotImplementedException ();
1069 public bool IsSupersetOf (IEnumerable<LabeledSymbol> other)
1071 throw new NotImplementedException ();
1074 public bool IsProperSupersetOf (IEnumerable<LabeledSymbol> other)
1076 throw new NotImplementedException ();
1079 public bool IsProperSubsetOf (IEnumerable<LabeledSymbol> other)
1081 throw new NotImplementedException ();
1084 public bool Overlaps (IEnumerable<LabeledSymbol> other)
1086 throw new NotImplementedException ();
1089 public bool SetEquals (IEnumerable<LabeledSymbol> other)
1091 throw new NotImplementedException ();
1095 public void Clear ()
1097 throw new NotImplementedException ();
1100 public bool Contains (LabeledSymbol item)
1102 throw new NotImplementedException ();
1105 public void CopyTo (LabeledSymbol[] array, int arrayIndex)
1107 throw new NotImplementedException ();
1110 public bool Remove (LabeledSymbol item)
1112 throw new NotImplementedException ();
1117 get { throw new NotImplementedException (); }
1120 public bool IsReadOnly
1122 get { throw new NotImplementedException (); }
1130 #region Nested type: IsinstExpression
1131 public class IsinstExpression : BoxedExpression {
1132 private readonly BoxedExpression arg;
1133 private readonly TypeNode type;
1135 public IsinstExpression (BoxedExpression boxedExpression, TypeNode type)
1137 this.arg = boxedExpression;
1141 public override bool IsIsinst
1143 get { return true; }
1146 public override BoxedExpression UnaryArgument
1148 get { return this.arg; }
1151 public override Result ForwardDecode<Data, Result, Visitor> (PC pc, Visitor visitor, Data data)
1153 return visitor.Isinst (pc, this.type, Dummy.Value, Dummy.Value, data);
1156 public override void AddFreeVariables (HashSet<BoxedExpression> set)
1158 this.arg.AddFreeVariables (set);
1161 public override BoxedExpression Substitute<Variable> (Func<Variable, BoxedExpression, BoxedExpression> map)
1163 BoxedExpression arg = this.arg.Substitute (map);
1164 if (arg == this.arg)
1169 return new IsinstExpression (arg, this.type);
1174 #region Nested type: OldExpression
1175 public class OldExpression : BoxedExpression {
1176 private const string ContractOldValueTemplate = "Contract.OldValue({0})";
1178 public readonly BoxedExpression Old;
1179 public readonly TypeNode Type;
1181 public OldExpression (BoxedExpression old, TypeNode type)
1187 #region Overrides of BoxedExpression
1188 public override void AddFreeVariables (HashSet<BoxedExpression> set)
1190 this.Old.AddFreeVariables (set);
1193 public override BoxedExpression Substitute<Variable1> (Func<Variable1, BoxedExpression, BoxedExpression> map)
1195 BoxedExpression old = this.Old.Substitute (map);
1196 if (old == this.Old)
1201 return new OldExpression (old, this.Type);
1204 public override bool IsBinaryExpression (out BinaryOperator op, out BoxedExpression left, out BoxedExpression right)
1206 return this.Old.IsBinaryExpression (out op, out left, out right);
1209 public override bool IsUnaryExpression (out UnaryOperator op, out BoxedExpression argument)
1211 return this.Old.IsUnaryExpression (out op, out argument);
1214 public override bool IsIsinstExpression (out BoxedExpression expr, out TypeNode type)
1216 return this.Old.IsIsinstExpression (out expr, out type);
1219 public override Result ForwardDecode<Data, Result, Visitor> (PC pc, Visitor visitor, Data data)
1221 return visitor.EndOld (pc, new PC (pc.Node, 0), this.Type, Dummy.Value, Dummy.Value, data);
1225 public override PathElement[] AccessPath
1227 get { return this.Old.AccessPath; }
1230 public override BoxedExpression BinaryLeftArgument
1232 get { return this.Old.BinaryLeftArgument; }
1235 public override BoxedExpression BinaryRightArgument
1237 get { return this.Old.BinaryRightArgument; }
1240 public override BinaryOperator BinaryOperator
1242 get { return this.Old.BinaryOperator; }
1245 public override object Constant
1247 get { return this.Old.Constant; }
1250 public override object ConstantType
1252 get { return this.Old.ConstantType; }
1255 public override bool IsBinary
1257 get { return this.Old.IsBinary; }
1260 public override bool IsConstant
1262 get { return this.Old.IsConstant; }
1265 public override bool IsSizeof
1267 get { return this.Old.IsSizeof; }
1270 public override bool IsNull
1272 get { return this.Old.IsNull; }
1275 public override bool IsIsinst
1277 get { return this.Old.IsIsinst; }
1280 public override bool IsUnary
1282 get { return this.Old.IsUnary; }
1285 public override bool IsVariable
1287 get { return this.Old.IsVariable; }
1290 public override BoxedExpression UnaryArgument
1292 get { return this.Old.UnaryArgument; }
1295 public override UnaryOperator UnaryOperator
1297 get { return this.Old.UnaryOperator; }
1300 public override object UnderlyingVariable
1302 get { return this.Old.UnderlyingVariable; }
1307 #region Nested type: PC
1309 public readonly int Index;
1310 public readonly BoxedExpression Node;
1312 public PC (BoxedExpression expr, int index)
1320 #region Nested type: ResultExpression
1321 public class ResultExpression : BoxedExpression {
1322 private const string ContractResultTemplate = "Contract.Result<{0}>()";
1324 public readonly TypeNode Type;
1326 public ResultExpression (TypeNode type)
1331 public override bool IsResult
1333 get { return true; }
1336 public override void AddFreeVariables (HashSet<BoxedExpression> set)
1340 public override BoxedExpression Substitute<Variable1> (Func<Variable1, BoxedExpression, BoxedExpression> map)
1345 public override Result ForwardDecode<Data, Result, Visitor> (PC pc, Visitor visitor, Data data)
1347 return visitor.LoadResult (pc, this.Type, Dummy.Value, Dummy.Value, data);
1352 #region Nested type: SizeOfExpression
1353 public class SizeOfExpression : BoxedExpression {
1354 public readonly int SizeAsConstant;
1355 public readonly TypeNode Type;
1357 public SizeOfExpression (TypeNode type, int sizeAsConstant)
1360 this.SizeAsConstant = sizeAsConstant;
1363 public SizeOfExpression (TypeNode type)
1368 public override bool IsSizeof
1370 get { return true; }
1373 public override bool Sizeof (out int size)
1375 size = SizeAsConstant;
1379 public override void AddFreeVariables (HashSet<BoxedExpression> set)
1383 public override BoxedExpression Substitute<Variable1> (Func<Variable1, BoxedExpression, BoxedExpression> map)
1388 public override Result ForwardDecode<Data, Result, Visitor> (PC pc, Visitor visitor, Data data)
1390 return visitor.Sizeof (pc, this.Type, Dummy.Value, data);
1395 #region Nested type: UnaryExpression
1396 public class UnaryExpression : BoxedExpression {
1397 public readonly BoxedExpression Argument;
1398 public readonly UnaryOperator Op;
1400 public UnaryExpression (UnaryOperator op, BoxedExpression argument)
1403 this.Argument = argument;
1406 public override bool IsUnary
1408 get { return true; }
1411 public override BoxedExpression UnaryArgument
1413 get { return this.Argument; }
1416 public override UnaryOperator UnaryOperator
1418 get { return this.Op; }
1421 public override bool IsUnaryExpression (out UnaryOperator op, out BoxedExpression argument)
1424 argument = this.Argument;
1428 public override void AddFreeVariables (HashSet<BoxedExpression> set)
1430 this.Argument.AddFreeVariables (set);
1433 public override BoxedExpression Substitute<Variable1> (Func<Variable1, BoxedExpression, BoxedExpression> map)
1435 BoxedExpression argument = this.Argument.Substitute (map);
1436 if (argument == this.Argument)
1438 if (argument == null)
1441 return new UnaryExpression (this.Op, argument);
1444 protected internal override BoxedExpression RecursiveSubstitute (BoxedExpression what, BoxedExpression replace)
1446 BoxedExpression argument = this.Argument.Substitute (what, replace);
1448 if (argument == this.Argument)
1451 return new UnaryExpression (this.Op, argument);
1454 public override Result ForwardDecode<Data, Result, Visitor> (PC pc, Visitor visitor, Data data)
1456 return visitor.Unary (pc, this.Op, false, Dummy.Value, Dummy.Value, data);
1459 public override bool Equals (object obj)
1464 var unary = obj as UnaryExpression;
1465 return unary != null && this.Op == unary.Op && this.Argument.Equals (unary.Argument);
1468 public override int GetHashCode ()
1470 return this.Op.GetHashCode () * 13 + (this.Argument == null ? 0 : this.Argument.GetHashCode ());
1476 #region Nested type: ValueAtReturnExpression
1477 public class ValueAtReturnExpression : BoxedExpression {
1478 private const string ContractValueAtReturnTemplate = "Contract.ValueAtReturn({0})";
1480 public readonly TypeNode Type;
1481 public readonly BoxedExpression Value;
1483 public ValueAtReturnExpression (BoxedExpression old, TypeNode type)
1489 #region Overrides of BoxedExpression
1490 public override void AddFreeVariables (HashSet<BoxedExpression> set)
1492 this.Value.AddFreeVariables (set);
1495 public override BoxedExpression Substitute<Variable1> (Func<Variable1, BoxedExpression, BoxedExpression> map)
1497 BoxedExpression value = this.Value.Substitute (map);
1498 if (value == this.Value)
1503 return new ValueAtReturnExpression (value, this.Type);
1506 public override bool IsBinaryExpression (out BinaryOperator op, out BoxedExpression left, out BoxedExpression right)
1508 return this.Value.IsBinaryExpression (out op, out left, out right);
1511 public override bool IsUnaryExpression (out UnaryOperator op, out BoxedExpression argument)
1513 return this.Value.IsUnaryExpression (out op, out argument);
1516 public override bool IsIsinstExpression (out BoxedExpression expr, out TypeNode type)
1518 return this.Value.IsIsinstExpression (out expr, out type);
1521 public override Result ForwardDecode<Data, Result, Visitor> (PC pc, Visitor visitor, Data data)
1523 throw new NotImplementedException ();
1527 public override PathElement[] AccessPath
1529 get { return this.Value.AccessPath; }
1532 public override BoxedExpression BinaryLeftArgument
1534 get { return this.Value.BinaryLeftArgument; }
1537 public override BoxedExpression BinaryRightArgument
1539 get { return this.Value.BinaryRightArgument; }
1542 public override BinaryOperator BinaryOperator
1544 get { return this.Value.BinaryOperator; }
1547 public override object Constant
1549 get { return this.Value.Constant; }
1552 public override object ConstantType
1554 get { return this.Value.ConstantType; }
1557 public override bool IsBinary
1559 get { return this.Value.IsBinary; }
1562 public override bool IsConstant
1564 get { return this.Value.IsConstant; }
1567 public override bool IsSizeof
1569 get { return this.Value.IsSizeof; }
1572 public override bool IsNull
1574 get { return this.Value.IsNull; }
1577 public override bool IsIsinst
1579 get { return this.Value.IsIsinst; }
1582 public override bool IsUnary
1584 get { return this.Value.IsUnary; }
1587 public override bool IsVariable
1589 get { return this.Value.IsVariable; }
1592 public override BoxedExpression UnaryArgument
1594 get { return this.Value.UnaryArgument; }
1597 public override UnaryOperator UnaryOperator
1599 get { return this.Value.UnaryOperator; }
1602 public override object UnderlyingVariable
1604 get { return this.Value.UnderlyingVariable; }
1609 #region Nested type: VariableExpression
1610 public class VariableExpression : BoxedExpression {
1611 private readonly PathElement[] Path;
1612 private readonly object UnderlyingVar;
1613 public readonly object VarType;
1615 public VariableExpression (object var)
1616 : this (var, (Sequence<PathElement>) null)
1620 public VariableExpression (object var, Sequence<PathElement> path)
1622 this.UnderlyingVar = var;
1623 this.Path = path != null ? path.AsEnumerable ().ToArray () : null;
1626 public VariableExpression (object var, Sequence<PathElement> path, object type)
1629 this.VarType = type;
1632 public VariableExpression (object var, PathElement[] path)
1634 this.UnderlyingVar = var;
1638 public VariableExpression (object var, PathElement[] path, object type)
1641 this.VarType = type;
1644 public override bool IsVariable
1646 get { return true; }
1649 public override object UnderlyingVariable
1651 get { return this.UnderlyingVar; }
1654 public override PathElement[] AccessPath
1656 get { return this.Path; }
1659 public override bool IsBooleanTyped
1661 get { return this.Path != null && this.Path [this.Path.Length - 1].IsBooleanTyped; }
1664 public override bool TryGetType (out object type)
1666 type = this.VarType;
1667 return type != null;
1670 public override void AddFreeVariables (HashSet<BoxedExpression> set)
1675 protected internal override BoxedExpression RecursiveSubstitute (BoxedExpression what, BoxedExpression replace)
1677 var varExpr = what as VariableExpression;
1678 if (varExpr != null && varExpr.UnderlyingVar.Equals (this.UnderlyingVar))
1684 public override Result ForwardDecode<Data, Result, Visitor> (PC pc, Visitor visitor, Data data)
1686 return visitor.Nop (pc, data);
1689 public override bool Equals (object obj)
1693 var boxedExpression = obj as BoxedExpression;
1694 if (boxedExpression != null && boxedExpression.IsVariable)
1695 return this.UnderlyingVar.Equals (boxedExpression.UnderlyingVariable);
1700 public override int GetHashCode ()
1702 return this.UnderlyingVariable != null ? 0 : this.UnderlyingVariable.GetHashCode ();
1705 public override BoxedExpression Substitute<Variable> (Func<Variable, BoxedExpression, BoxedExpression> map)
1707 if (!(this.UnderlyingVar is Variable))
1709 var variable = ((Variable) this.UnderlyingVar);
1710 return map (variable, this);