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;
41 namespace Mono.CodeContracts.Static.Proving {
42 internal abstract class BoxedExpression {
43 public virtual bool IsVariable
48 public virtual bool IsBooleanTyped
53 public virtual object UnderlyingVariable
58 public virtual PathElement[] AccessPath
63 public virtual bool IsConstant
68 public virtual object Constant
70 get { throw new InvalidOperationException (); }
73 public virtual object ConstantType
75 get { throw new InvalidOperationException (); }
78 public virtual bool IsSizeof
83 public virtual bool IsUnary
88 public virtual UnaryOperator UnaryOperator
90 get { throw new InvalidOperationException (); }
93 public virtual BoxedExpression UnaryArgument
95 get { throw new InvalidOperationException (); }
98 public virtual bool IsBinary
100 get { return false; }
103 public virtual BinaryOperator BinaryOperator
105 get { throw new InvalidOperationException (); }
108 public virtual BoxedExpression BinaryLeftArgument
110 get { throw new InvalidOperationException (); }
113 public virtual BoxedExpression BinaryRightArgument
115 get { throw new InvalidOperationException (); }
118 public virtual bool IsIsinst
120 get { return false; }
123 public virtual bool IsNull
125 get { return false; }
128 public virtual bool IsCast
130 get { return false; }
133 public virtual bool IsResult
135 get { return false; }
138 public virtual bool TryGetType (out object type)
144 public virtual bool IsBinaryExpression (out BinaryOperator op, out BoxedExpression left, out BoxedExpression right)
146 op = BinaryOperator.Add;
152 public virtual bool IsUnaryExpression (out UnaryOperator op, out BoxedExpression argument)
154 op = UnaryOperator.Conv_i;
159 public virtual bool IsIsinstExpression (out BoxedExpression expr, out TypeNode type)
166 public abstract void AddFreeVariables (HashSet<BoxedExpression> set);
168 public virtual BoxedExpression Substitute (BoxedExpression what, BoxedExpression replace)
170 if (this == what || Equals (what))
173 return RecursiveSubstitute (what, replace);
176 public abstract BoxedExpression Substitute<Variable> (Func<Variable, BoxedExpression, BoxedExpression> map);
178 protected internal virtual BoxedExpression RecursiveSubstitute (BoxedExpression what, BoxedExpression replace)
183 public abstract Result ForwardDecode<Data, Result, Visitor> (PC pc, Visitor visitor, Data data)
184 where Visitor : IILVisitor<PC, Dummy, Dummy, Data, Result>;
186 public static BoxedExpression Var (object var)
188 return new VariableExpression (var);
191 public static BoxedExpression For<Variable, Expression> (Expression external, IFullExpressionDecoder<Variable, Expression> decoder)
192 where Expression : IEquatable<Expression>
194 return new ExternalBox<Variable, Expression> (external, decoder);
197 public static BoxedExpression MakeIsinst (TypeNode type, BoxedExpression arg)
199 return new IsinstExpression (arg, type);
202 public static BoxedExpression Convert<Variable, ExternalExpression> (ExternalExpression expr, IFullExpressionDecoder<Variable, ExternalExpression> decoder)
206 if (decoder.IsConstant (expr, out value, out type))
207 return new ConstantExpression (value, type);
208 if (decoder.IsNull (expr))
209 return new ConstantExpression (null, null);
212 if (decoder.IsVariable (expr, out variable)) {
213 LispList<PathElement> variableAccessPath = decoder.GetVariableAccessPath (expr);
214 return new VariableExpression (variable, variableAccessPath);
217 if (decoder.IsSizeof (expr, out type)) {
219 return decoder.TrySizeOfAsConstant (expr, out sizeAsConstant) ? new SizeOfExpression (type, sizeAsConstant) : new SizeOfExpression (type);
222 ExternalExpression arg;
223 if (decoder.IsIsinst (expr, out arg, out type))
224 return new IsinstExpression (Convert (arg, decoder), type);
227 if (decoder.IsUnaryExpression (expr, out op, out arg))
228 return new UnaryExpression (op, Convert (arg, decoder));
231 ExternalExpression left;
232 ExternalExpression right;
233 if (!decoder.IsBinaryExpression (expr, out bop, out left, out right))
234 throw new InvalidOperationException ();
236 return new BinaryExpression (bop, Convert (left, decoder), Convert (right, decoder));
239 #region Nested type: AssertExpression
240 public class AssertExpression : ContractExpression {
241 public AssertExpression (BoxedExpression condition, EdgeTag tag, APC pc) : base (condition, tag, pc)
245 #region Overrides of ContractExpression
246 public override Result ForwardDecode<Data, Result, Visitor> (PC pc, Visitor visitor, Data data)
248 return visitor.Assert (pc, this.Tag, Dummy.Value, data);
251 public override BoxedExpression Substitute<Variable1> (Func<Variable1, BoxedExpression, BoxedExpression> map)
253 BoxedExpression cond = this.Condition.Substitute (map);
254 if (cond == this.Condition)
259 return new AssertExpression (cond, this.Tag, this.Apc);
265 #region Nested type: AssumeExpression
266 public class AssumeExpression : ContractExpression {
267 public AssumeExpression (BoxedExpression condition, EdgeTag tag, APC pc)
268 : base (condition, tag, pc)
272 #region Overrides of ContractExpression
273 public override Result ForwardDecode<Data, Result, Visitor> (PC pc, Visitor visitor, Data data)
275 return visitor.Assume (pc, this.Tag, Dummy.Value, data);
278 public override BoxedExpression Substitute<Variable1> (Func<Variable1, BoxedExpression, BoxedExpression> map)
280 BoxedExpression cond = this.Condition.Substitute (map);
281 if (cond == this.Condition)
286 return new AssumeExpression (cond, this.Tag, this.Apc);
292 #region Nested type: BinaryExpression
293 public class BinaryExpression : BoxedExpression {
294 public readonly BoxedExpression Left;
295 public readonly BinaryOperator Op;
296 public readonly BoxedExpression Right;
298 public BinaryExpression (BinaryOperator op, BoxedExpression left, BoxedExpression right)
305 public override bool IsBinary
310 public override BoxedExpression BinaryLeftArgument
312 get { return this.Left; }
315 public override BoxedExpression BinaryRightArgument
317 get { return this.Right; }
320 public override BinaryOperator BinaryOperator
322 get { return this.Op; }
325 public override bool IsBinaryExpression (out BinaryOperator op, out BoxedExpression left, out BoxedExpression right)
333 #region Overrides of BoxedExpression
334 public override void AddFreeVariables (HashSet<BoxedExpression> set)
336 this.Left.AddFreeVariables (set);
337 this.Right.AddFreeVariables (set);
340 protected internal override BoxedExpression RecursiveSubstitute (BoxedExpression what, BoxedExpression replace)
342 BoxedExpression left = this.Left.Substitute (what, replace);
343 BoxedExpression right = this.Right.Substitute (what, replace);
344 if (left == this.Left && right == this.Right)
347 return new BinaryExpression (this.Op, left, right);
350 public override BoxedExpression Substitute<Variable> (Func<Variable, BoxedExpression, BoxedExpression> map)
352 BoxedExpression left = this.Left.Substitute (map);
356 BoxedExpression right = this.Right.Substitute (map);
360 if (this.Left == left && this.Right == right)
362 return new BinaryExpression (this.Op, left, right);
365 public override Result ForwardDecode<Data, Result, Visitor> (PC pc, Visitor visitor, Data data)
367 return visitor.Binary (pc, this.Op, Dummy.Value, Dummy.Value, Dummy.Value, data);
373 #region Nested type: CastExpression
374 public class CastExpression : BoxedExpression {
375 public readonly TypeNode CastToType;
376 public readonly BoxedExpression Expr;
378 public CastExpression (TypeNode castToType, BoxedExpression expr)
380 this.CastToType = castToType;
384 public override bool IsCast
389 public override PathElement[] AccessPath
391 get { return this.Expr.AccessPath; }
394 public override BoxedExpression BinaryLeftArgument
396 get { return this.Expr.BinaryLeftArgument; }
399 public override BoxedExpression BinaryRightArgument
401 get { return this.Expr.BinaryRightArgument; }
404 public override BinaryOperator BinaryOperator
406 get { return this.Expr.BinaryOperator; }
409 public override object Constant
411 get { return this.Expr.Constant; }
414 public override object ConstantType
416 get { return this.Expr.ConstantType; }
419 public override bool IsBinary
421 get { return this.Expr.IsBinary; }
424 public override bool IsBooleanTyped
426 get { return this.Expr.IsBooleanTyped; }
429 public override bool IsConstant
431 get { return this.Expr.IsConstant; }
435 public override bool IsSizeof
437 get { return this.Expr.IsSizeof; }
440 public override bool IsNull
442 get { return this.Expr.IsNull; }
445 public override bool IsIsinst
447 get { return this.Expr.IsIsinst; }
450 public override bool IsResult
452 get { return this.Expr.IsResult; }
455 public override bool IsUnary
457 get { return this.Expr.IsUnary; }
460 public override bool IsVariable
462 get { return this.Expr.IsVariable; }
465 public override BoxedExpression UnaryArgument
467 get { return this.Expr.UnaryArgument; }
470 public override UnaryOperator UnaryOperator
472 get { return this.Expr.UnaryOperator; }
475 public override object UnderlyingVariable
477 get { return this.Expr.UnderlyingVariable; }
481 public override void AddFreeVariables (HashSet<BoxedExpression> set)
483 this.Expr.AddFreeVariables (set);
486 public override BoxedExpression Substitute<Variable> (Func<Variable, BoxedExpression, BoxedExpression> map)
488 return this.Expr.Substitute (map);
491 public override Result ForwardDecode<Data, Result, Visitor> (PC pc, Visitor visitor, Data data)
493 return this.Expr.ForwardDecode<Data, Result, Visitor> (pc, visitor, data);
496 public override bool IsBinaryExpression (out BinaryOperator op, out BoxedExpression left, out BoxedExpression right)
498 return this.Expr.IsBinaryExpression (out op, out left, out right);
501 protected internal override BoxedExpression RecursiveSubstitute (BoxedExpression what, BoxedExpression replace)
503 return this.Expr.RecursiveSubstitute (what, replace);
506 public override BoxedExpression Substitute (BoxedExpression what, BoxedExpression replace)
508 return this.Expr.Substitute (what, replace);
511 public override bool IsUnaryExpression (out UnaryOperator op, out BoxedExpression argument)
513 return this.Expr.IsUnaryExpression (out op, out argument);
518 #region Nested type: ConstantExpression
519 public class ConstantExpression : BoxedExpression {
520 public readonly TypeNode Type;
521 public readonly object Value;
522 private readonly bool is_boolean;
524 public ConstantExpression (object value, TypeNode type)
525 : this (value, type, false)
529 public ConstantExpression (object value, TypeNode type, bool isBoolean)
533 this.is_boolean = isBoolean;
536 public override bool IsBooleanTyped
538 get { return this.is_boolean; }
541 public override bool IsConstant
546 public override object Constant
548 get { return this.Value; }
551 public override object ConstantType
553 get { return this.Type; }
556 public override bool IsNull
560 if (this.Value == null)
563 var conv = this.Value as IConvertible;
566 if (conv.ToInt32 (null) == 0)
577 public override void AddFreeVariables (HashSet<BoxedExpression> set)
581 public override BoxedExpression Substitute<Variable1> (Func<Variable1, BoxedExpression, BoxedExpression> map)
586 public override Result ForwardDecode<Data, Result, Visitor> (PC pc, Visitor visitor, Data data)
588 if (this.Value == null)
589 return visitor.LoadNull (pc, Dummy.Value, data);
591 return visitor.LoadConst (pc, this.Type, this.Value, Dummy.Value, data);
596 #region Nested type: ContractExpression
597 public abstract class ContractExpression : BoxedExpression {
598 public readonly APC Apc;
599 public readonly BoxedExpression Condition;
600 public readonly EdgeTag Tag;
602 public ContractExpression (BoxedExpression condition, EdgeTag tag, APC pc)
605 this.Condition = condition;
609 public override void AddFreeVariables (HashSet<BoxedExpression> set)
611 this.Condition.AddFreeVariables (set);
614 public abstract override Result ForwardDecode<Data, Result, Visitor> (PC pc, Visitor visitor, Data data);
615 public abstract override BoxedExpression Substitute<Variable> (Func<Variable, BoxedExpression, BoxedExpression> map);
619 #region Nested type: ExternalBox
620 public class ExternalBox<Variable, LabeledSymbol> : BoxedExpression
621 where LabeledSymbol : IEquatable<LabeledSymbol> {
622 private readonly IFullExpressionDecoder<Variable, LabeledSymbol> decoder;
623 private readonly LabeledSymbol expr;
624 private Optional<Tuple<bool, BinaryOperator, BoxedExpression, BoxedExpression>> binary;
626 private Optional<Tuple<bool, object, TypeNode>> constant;
627 private Optional<Tuple<bool, BoxedExpression, TypeNode>> isInst;
628 private Optional<Pair<bool, object>> isVar;
629 private Optional<Pair<bool, TypeNode>> type;
630 private Optional<Tuple<bool, UnaryOperator, BoxedExpression>> unary;
631 private Optional<object> var;
633 public ExternalBox (LabeledSymbol external, IFullExpressionDecoder<Variable, LabeledSymbol> decoder)
635 this.expr = external;
636 this.decoder = decoder;
639 public override bool IsBinary
643 Tuple<bool, BinaryOperator, BoxedExpression, BoxedExpression> binary;
644 TryGetBinaryFromCache (out binary);
649 public override BinaryOperator BinaryOperator
653 Tuple<bool, BinaryOperator, BoxedExpression, BoxedExpression> binary;
654 bool res = TryGetBinaryFromCache (out binary);
656 throw new InvalidOperationException ();
662 public override BoxedExpression BinaryLeftArgument
666 Tuple<bool, BinaryOperator, BoxedExpression, BoxedExpression> binary;
667 bool res = TryGetBinaryFromCache (out binary);
669 throw new InvalidOperationException ();
675 public override BoxedExpression BinaryRightArgument
679 Tuple<bool, BinaryOperator, BoxedExpression, BoxedExpression> binary;
680 bool res = TryGetBinaryFromCache (out binary);
682 throw new InvalidOperationException ();
688 public override bool IsConstant
692 Tuple<bool, object, TypeNode> consta;
693 TryGetConstantFromCache (out consta);
699 public override object Constant
703 Tuple<bool, object, TypeNode> consta;
704 if (!TryGetConstantFromCache (out consta))
705 throw new InvalidOperationException ();
711 public override object ConstantType
715 Tuple<bool, object, TypeNode> consta;
716 if (!TryGetConstantFromCache (out consta))
717 throw new InvalidOperationException();
723 public override bool IsIsinst
727 Tuple<bool, BoxedExpression, TypeNode> isinst;
728 TryGetIsInstFromCache (out isinst);
733 public override bool IsNull
735 get { return this.decoder.IsNull (this.expr); }
738 public override bool IsUnary
742 Tuple<bool, UnaryOperator, BoxedExpression> unary;
743 TryGetUnaryFromCache (out unary);
748 public override UnaryOperator UnaryOperator
752 Tuple<bool, UnaryOperator, BoxedExpression> unary;
753 if (!TryGetUnaryFromCache (out unary))
754 throw new InvalidOperationException();
759 public override BoxedExpression UnaryArgument
763 Tuple<bool, UnaryOperator, BoxedExpression> unary;
764 if (!TryGetUnaryFromCache (out unary))
765 throw new InvalidOperationException ();
770 public override bool IsSizeof
775 return this.decoder.IsSizeof (this.expr, out type);
779 public override bool IsVariable
783 Pair<bool, object> var1;
784 TryGetIsVariableFromCache (out var1);
789 public override object UnderlyingVariable
793 if (!this.var.IsValid)
794 this.var = this.decoder.UnderlyingVariable (this.expr);
796 return this.var.Value;
800 private bool TryGetBinaryFromCache (out Tuple<bool, BinaryOperator, BoxedExpression, BoxedExpression> binary)
802 if (this.binary.IsValid) {
803 binary = this.binary.Value;
809 bool res = this.decoder.IsBinaryExpression (this.expr, out op, out left, out right);
810 this.binary = binary = new Tuple<bool, BinaryOperator, BoxedExpression, BoxedExpression> (res, op, For (left, this.decoder), For (right, this.decoder));
815 private bool TryGetUnaryFromCache (out Tuple<bool, UnaryOperator, BoxedExpression> unary)
817 if (this.unary.IsValid) {
818 unary = this.unary.Value;
823 bool res = this.decoder.IsUnaryExpression (this.expr, out op, out arg);
824 this.unary = unary = new Tuple<bool, UnaryOperator, BoxedExpression> (res, op, For (arg, this.decoder));
829 private bool TryGetIsInstFromCache (out Tuple<bool, BoxedExpression, TypeNode> isinst)
831 if (this.isInst.IsValid) {
832 isinst = this.isInst.Value;
838 bool res = this.decoder.IsIsinst (this.expr, out arg, out type);
839 this.isInst = isinst = new Tuple<bool, BoxedExpression, TypeNode> (res, For (arg, this.decoder), type);
844 private bool TryGetConstantFromCache (out Tuple<bool, object, TypeNode> result)
846 if (this.constant.IsValid) {
847 result = this.constant.Value;
852 bool res = this.decoder.IsConstant (this.expr, out value, out type);
853 this.constant = result = new Tuple<bool, object, TypeNode> (res, value, type);
858 private bool TryGetTypeFromCache (out Pair<bool, TypeNode> result)
860 if (this.type.IsValid) {
861 result = this.type.Value;
866 bool res = this.decoder.TryGetType (this.expr, out type);
867 this.type = result = new Pair<bool, TypeNode> (res, type);
872 private bool TryGetIsVariableFromCache (out Pair<bool, object> result)
874 if (this.isVar.IsValid) {
875 result = this.isVar.Value;
880 bool res = this.decoder.IsVariable (this.expr, out value);
881 this.isVar = result = new Pair<bool, object> (res, value);
886 public override bool IsBinaryExpression (out BinaryOperator op, out BoxedExpression left, out BoxedExpression right)
888 Tuple<bool, BinaryOperator, BoxedExpression, BoxedExpression> bin;
889 if (!TryGetBinaryFromCache (out bin) || !bin.Item1) {
890 op = BinaryOperator.Add;
902 public override bool IsIsinstExpression (out BoxedExpression expr, out TypeNode type)
904 Tuple<bool, BoxedExpression, TypeNode> isinst;
905 if (!TryGetIsInstFromCache (out isinst) || !isinst.Item1) {
916 public override bool IsUnaryExpression (out UnaryOperator op, out BoxedExpression argument)
918 Tuple<bool, UnaryOperator, BoxedExpression> unary;
919 if (!TryGetUnaryFromCache (out unary) || !unary.Item1) {
920 op = UnaryOperator.Conv_i;
926 argument = unary.Item3;
930 protected internal override BoxedExpression RecursiveSubstitute (BoxedExpression what, BoxedExpression replace)
932 return Convert (this.expr, this.decoder).Substitute (what, replace);
935 public override void AddFreeVariables (HashSet<BoxedExpression> set)
937 this.decoder.AddFreeVariables (this.expr, new SetWrapper (set, this.decoder));
940 public override BoxedExpression Substitute<V> (Func<V, BoxedExpression, BoxedExpression> map)
942 return Convert (this.expr, this.decoder).Substitute (map);
945 public override bool TryGetType (out object type)
947 Pair<bool, TypeNode> result;
948 if (!TryGetTypeFromCache (out result) || !result.Key) {
957 public override Result ForwardDecode<Data, Result, Visitor> (PC pc, Visitor visitor, Data data)
959 Tuple<bool, object, TypeNode> constant;
960 if (TryGetConstantFromCache (out constant)) {
961 if (constant.Item2 != null)
962 return visitor.LoadConst (pc, constant.Item3, constant, Dummy.Value, data);
964 return visitor.LoadNull (pc, Dummy.Value, data);
969 if (this.decoder.IsUnaryExpression (this.expr, out op, out arg))
970 return visitor.Unary (pc, op, false, Dummy.Value, Dummy.Value, data);
975 if (this.decoder.IsBinaryExpression (this.expr, out bop, out left, out right))
976 return visitor.Binary (pc, bop, Dummy.Value, Dummy.Value, Dummy.Value, data);
978 if (this.decoder.IsIsinst (this.expr, out arg, out type))
979 return visitor.Isinst (pc, type, Dummy.Value, Dummy.Value, data);
980 if (this.decoder.IsNull (this.expr))
981 return visitor.LoadNull (pc, Dummy.Value, data);
982 if (this.decoder.IsSizeof (this.expr, out type))
983 return visitor.Sizeof (pc, type, Dummy.Value, data);
985 return visitor.Nop (pc, data);
988 #region Nested type: SetWrapper
989 private struct SetWrapper : ISet<LabeledSymbol>, IEnumerable<LabeledSymbol> {
990 private readonly IFullExpressionDecoder<Variable, LabeledSymbol> decoder;
991 private readonly HashSet<BoxedExpression> set;
993 #region Implementation of IEnumerable
994 public IEnumerator<LabeledSymbol> GetEnumerator ()
996 throw new NotImplementedException ();
999 IEnumerator IEnumerable.GetEnumerator ()
1001 return GetEnumerator ();
1005 public SetWrapper (HashSet<BoxedExpression> set, IFullExpressionDecoder<Variable, LabeledSymbol> decoder)
1008 this.decoder = decoder;
1011 #region Implementation of ICollection<ExternalExpression>
1012 public void Add (LabeledSymbol item)
1014 this.set.Add (For (item, this.decoder));
1017 bool ISet<LabeledSymbol>.Add (LabeledSymbol item)
1023 public void UnionWith (IEnumerable<LabeledSymbol> other)
1025 throw new NotImplementedException ();
1028 public void IntersectWith (IEnumerable<LabeledSymbol> other)
1030 throw new NotImplementedException ();
1033 public void ExceptWith (IEnumerable<LabeledSymbol> other)
1035 throw new NotImplementedException ();
1038 public void SymmetricExceptWith (IEnumerable<LabeledSymbol> other)
1040 throw new NotImplementedException ();
1043 public bool IsSubsetOf (IEnumerable<LabeledSymbol> other)
1045 throw new NotImplementedException ();
1048 public bool IsSupersetOf (IEnumerable<LabeledSymbol> other)
1050 throw new NotImplementedException ();
1053 public bool IsProperSupersetOf (IEnumerable<LabeledSymbol> other)
1055 throw new NotImplementedException ();
1058 public bool IsProperSubsetOf (IEnumerable<LabeledSymbol> other)
1060 throw new NotImplementedException ();
1063 public bool Overlaps (IEnumerable<LabeledSymbol> other)
1065 throw new NotImplementedException ();
1068 public bool SetEquals (IEnumerable<LabeledSymbol> other)
1070 throw new NotImplementedException ();
1074 public void Clear ()
1076 throw new NotImplementedException ();
1079 public bool Contains (LabeledSymbol item)
1081 throw new NotImplementedException ();
1084 public void CopyTo (LabeledSymbol[] array, int arrayIndex)
1086 throw new NotImplementedException ();
1089 public bool Remove (LabeledSymbol item)
1091 throw new NotImplementedException ();
1096 get { throw new NotImplementedException (); }
1099 public bool IsReadOnly
1101 get { throw new NotImplementedException (); }
1109 #region Nested type: IsinstExpression
1110 public class IsinstExpression : BoxedExpression {
1111 private readonly BoxedExpression arg;
1112 private readonly TypeNode type;
1114 public IsinstExpression (BoxedExpression boxedExpression, TypeNode type)
1116 this.arg = boxedExpression;
1120 public override bool IsIsinst
1122 get { return true; }
1125 public override BoxedExpression UnaryArgument
1127 get { return this.arg; }
1130 public override Result ForwardDecode<Data, Result, Visitor> (PC pc, Visitor visitor, Data data)
1132 return visitor.Isinst (pc, this.type, Dummy.Value, Dummy.Value, data);
1135 public override void AddFreeVariables (HashSet<BoxedExpression> set)
1137 this.arg.AddFreeVariables (set);
1140 public override BoxedExpression Substitute<Variable> (Func<Variable, BoxedExpression, BoxedExpression> map)
1142 BoxedExpression arg = this.arg.Substitute (map);
1143 if (arg == this.arg)
1148 return new IsinstExpression (arg, this.type);
1153 #region Nested type: OldExpression
1154 public class OldExpression : BoxedExpression {
1155 private const string ContractOldValueTemplate = "Contract.OldValue({0})";
1157 public readonly BoxedExpression Old;
1158 public readonly TypeNode Type;
1160 public OldExpression (BoxedExpression old, TypeNode type)
1166 #region Overrides of BoxedExpression
1167 public override void AddFreeVariables (HashSet<BoxedExpression> set)
1169 this.Old.AddFreeVariables (set);
1172 public override BoxedExpression Substitute<Variable1> (Func<Variable1, BoxedExpression, BoxedExpression> map)
1174 BoxedExpression old = this.Old.Substitute (map);
1175 if (old == this.Old)
1180 return new OldExpression (old, this.Type);
1183 public override bool IsBinaryExpression (out BinaryOperator op, out BoxedExpression left, out BoxedExpression right)
1185 return this.Old.IsBinaryExpression (out op, out left, out right);
1188 public override bool IsUnaryExpression (out UnaryOperator op, out BoxedExpression argument)
1190 return this.Old.IsUnaryExpression (out op, out argument);
1193 public override bool IsIsinstExpression (out BoxedExpression expr, out TypeNode type)
1195 return this.Old.IsIsinstExpression (out expr, out type);
1198 public override Result ForwardDecode<Data, Result, Visitor> (PC pc, Visitor visitor, Data data)
1200 return visitor.EndOld (pc, new PC (pc.Node, 0), this.Type, Dummy.Value, Dummy.Value, data);
1204 public override PathElement[] AccessPath
1206 get { return this.Old.AccessPath; }
1209 public override BoxedExpression BinaryLeftArgument
1211 get { return this.Old.BinaryLeftArgument; }
1214 public override BoxedExpression BinaryRightArgument
1216 get { return this.Old.BinaryRightArgument; }
1219 public override BinaryOperator BinaryOperator
1221 get { return this.Old.BinaryOperator; }
1224 public override object Constant
1226 get { return this.Old.Constant; }
1229 public override object ConstantType
1231 get { return this.Old.ConstantType; }
1234 public override bool IsBinary
1236 get { return this.Old.IsBinary; }
1239 public override bool IsConstant
1241 get { return this.Old.IsConstant; }
1244 public override bool IsSizeof
1246 get { return this.Old.IsSizeof; }
1249 public override bool IsNull
1251 get { return this.Old.IsNull; }
1254 public override bool IsIsinst
1256 get { return this.Old.IsIsinst; }
1259 public override bool IsUnary
1261 get { return this.Old.IsUnary; }
1264 public override bool IsVariable
1266 get { return this.Old.IsVariable; }
1269 public override BoxedExpression UnaryArgument
1271 get { return this.Old.UnaryArgument; }
1274 public override UnaryOperator UnaryOperator
1276 get { return this.Old.UnaryOperator; }
1279 public override object UnderlyingVariable
1281 get { return this.Old.UnderlyingVariable; }
1286 #region Nested type: PC
1288 public readonly int Index;
1289 public readonly BoxedExpression Node;
1291 public PC (BoxedExpression expr, int index)
1299 #region Nested type: ResultExpression
1300 public class ResultExpression : BoxedExpression {
1301 private const string ContractResultTemplate = "Contract.Result<{0}>()";
1303 public readonly TypeNode Type;
1305 public ResultExpression (TypeNode type)
1310 public override bool IsResult
1312 get { return true; }
1315 public override void AddFreeVariables (HashSet<BoxedExpression> set)
1319 public override BoxedExpression Substitute<Variable1> (Func<Variable1, BoxedExpression, BoxedExpression> map)
1324 public override Result ForwardDecode<Data, Result, Visitor> (PC pc, Visitor visitor, Data data)
1326 return visitor.LoadResult (pc, this.Type, Dummy.Value, Dummy.Value, data);
1331 #region Nested type: SizeOfExpression
1332 public class SizeOfExpression : BoxedExpression {
1333 public readonly int SizeAsConstant;
1334 public readonly TypeNode Type;
1336 public SizeOfExpression (TypeNode type, int sizeAsConstant)
1339 this.SizeAsConstant = sizeAsConstant;
1342 public SizeOfExpression (TypeNode type)
1347 public override bool IsSizeof
1349 get { return true; }
1352 public override void AddFreeVariables (HashSet<BoxedExpression> set)
1356 public override BoxedExpression Substitute<Variable1> (Func<Variable1, BoxedExpression, BoxedExpression> map)
1361 public override Result ForwardDecode<Data, Result, Visitor> (PC pc, Visitor visitor, Data data)
1363 return visitor.Sizeof (pc, this.Type, Dummy.Value, data);
1368 #region Nested type: UnaryExpression
1369 public class UnaryExpression : BoxedExpression {
1370 public readonly BoxedExpression Argument;
1371 public readonly UnaryOperator Op;
1373 public UnaryExpression (UnaryOperator op, BoxedExpression argument)
1376 this.Argument = argument;
1379 public override bool IsUnary
1381 get { return true; }
1384 public override BoxedExpression UnaryArgument
1386 get { return this.Argument; }
1389 public override UnaryOperator UnaryOperator
1391 get { return this.Op; }
1394 public override bool IsUnaryExpression (out UnaryOperator op, out BoxedExpression argument)
1397 argument = this.Argument;
1401 public override void AddFreeVariables (HashSet<BoxedExpression> set)
1403 this.Argument.AddFreeVariables (set);
1406 public override BoxedExpression Substitute<Variable1> (Func<Variable1, BoxedExpression, BoxedExpression> map)
1408 BoxedExpression argument = this.Argument.Substitute (map);
1409 if (argument == this.Argument)
1411 if (argument == null)
1414 return new UnaryExpression (this.Op, argument);
1417 protected internal override BoxedExpression RecursiveSubstitute (BoxedExpression what, BoxedExpression replace)
1419 BoxedExpression argument = this.Argument.Substitute (what, replace);
1421 if (argument == this.Argument)
1424 return new UnaryExpression (this.Op, argument);
1427 public override Result ForwardDecode<Data, Result, Visitor> (PC pc, Visitor visitor, Data data)
1429 return visitor.Unary (pc, this.Op, false, Dummy.Value, Dummy.Value, data);
1432 public override bool Equals (object obj)
1437 var unary = obj as UnaryExpression;
1438 return unary != null && this.Op == unary.Op && this.Argument.Equals (unary.Argument);
1441 public override int GetHashCode ()
1443 return this.Op.GetHashCode () * 13 + (this.Argument == null ? 0 : this.Argument.GetHashCode ());
1449 #region Nested type: ValueAtReturnExpression
1450 public class ValueAtReturnExpression : BoxedExpression {
1451 private const string ContractValueAtReturnTemplate = "Contract.ValueAtReturn({0})";
1453 public readonly TypeNode Type;
1454 public readonly BoxedExpression Value;
1456 public ValueAtReturnExpression (BoxedExpression old, TypeNode type)
1462 #region Overrides of BoxedExpression
1463 public override void AddFreeVariables (HashSet<BoxedExpression> set)
1465 this.Value.AddFreeVariables (set);
1468 public override BoxedExpression Substitute<Variable1> (Func<Variable1, BoxedExpression, BoxedExpression> map)
1470 BoxedExpression value = this.Value.Substitute (map);
1471 if (value == this.Value)
1476 return new ValueAtReturnExpression (value, this.Type);
1479 public override bool IsBinaryExpression (out BinaryOperator op, out BoxedExpression left, out BoxedExpression right)
1481 return this.Value.IsBinaryExpression (out op, out left, out right);
1484 public override bool IsUnaryExpression (out UnaryOperator op, out BoxedExpression argument)
1486 return this.Value.IsUnaryExpression (out op, out argument);
1489 public override bool IsIsinstExpression (out BoxedExpression expr, out TypeNode type)
1491 return this.Value.IsIsinstExpression (out expr, out type);
1494 public override Result ForwardDecode<Data, Result, Visitor> (PC pc, Visitor visitor, Data data)
1496 throw new NotImplementedException ();
1500 public override PathElement[] AccessPath
1502 get { return this.Value.AccessPath; }
1505 public override BoxedExpression BinaryLeftArgument
1507 get { return this.Value.BinaryLeftArgument; }
1510 public override BoxedExpression BinaryRightArgument
1512 get { return this.Value.BinaryRightArgument; }
1515 public override BinaryOperator BinaryOperator
1517 get { return this.Value.BinaryOperator; }
1520 public override object Constant
1522 get { return this.Value.Constant; }
1525 public override object ConstantType
1527 get { return this.Value.ConstantType; }
1530 public override bool IsBinary
1532 get { return this.Value.IsBinary; }
1535 public override bool IsConstant
1537 get { return this.Value.IsConstant; }
1540 public override bool IsSizeof
1542 get { return this.Value.IsSizeof; }
1545 public override bool IsNull
1547 get { return this.Value.IsNull; }
1550 public override bool IsIsinst
1552 get { return this.Value.IsIsinst; }
1555 public override bool IsUnary
1557 get { return this.Value.IsUnary; }
1560 public override bool IsVariable
1562 get { return this.Value.IsVariable; }
1565 public override BoxedExpression UnaryArgument
1567 get { return this.Value.UnaryArgument; }
1570 public override UnaryOperator UnaryOperator
1572 get { return this.Value.UnaryOperator; }
1575 public override object UnderlyingVariable
1577 get { return this.Value.UnderlyingVariable; }
1582 #region Nested type: VariableExpression
1583 public class VariableExpression : BoxedExpression {
1584 private readonly PathElement[] Path;
1585 private readonly object UnderlyingVar;
1586 public readonly object VarType;
1588 public VariableExpression (object var)
1589 : this (var, (LispList<PathElement>) null)
1593 public VariableExpression (object var, LispList<PathElement> path)
1595 this.UnderlyingVar = var;
1596 this.Path = path != null ? path.AsEnumerable ().ToArray () : null;
1599 public VariableExpression (object var, LispList<PathElement> path, object type)
1602 this.VarType = type;
1605 public VariableExpression (object var, PathElement[] path)
1607 this.UnderlyingVar = var;
1611 public VariableExpression (object var, PathElement[] path, object type)
1614 this.VarType = type;
1617 public override bool IsVariable
1619 get { return true; }
1622 public override object UnderlyingVariable
1624 get { return this.UnderlyingVar; }
1627 public override PathElement[] AccessPath
1629 get { return this.Path; }
1632 public override bool IsBooleanTyped
1634 get { return this.Path != null && this.Path [this.Path.Length - 1].IsBooleanTyped; }
1637 public override bool TryGetType (out object type)
1639 type = this.VarType;
1640 return type != null;
1643 public override void AddFreeVariables (HashSet<BoxedExpression> set)
1648 protected internal override BoxedExpression RecursiveSubstitute (BoxedExpression what, BoxedExpression replace)
1650 var varExpr = what as VariableExpression;
1651 if (varExpr != null && varExpr.UnderlyingVar.Equals (this.UnderlyingVar))
1657 public override Result ForwardDecode<Data, Result, Visitor> (PC pc, Visitor visitor, Data data)
1659 return visitor.Nop (pc, data);
1662 public override bool Equals (object obj)
1666 var boxedExpression = obj as BoxedExpression;
1667 if (boxedExpression != null && boxedExpression.IsVariable)
1668 return this.UnderlyingVar.Equals (boxedExpression.UnderlyingVariable);
1673 public override int GetHashCode ()
1675 return this.UnderlyingVariable != null ? 0 : this.UnderlyingVariable.GetHashCode ();
1678 public override BoxedExpression Substitute<Variable> (Func<Variable, BoxedExpression, BoxedExpression> map)
1680 if (!(this.UnderlyingVar is Variable))
1682 var variable = ((Variable) this.UnderlyingVar);
1683 return map (variable, this);