context: using System;
  using Mono.Cecil.Cil;
  using Mono.Cecil.Metadata;
  
  namespace Mono.Debugger.Soft
  {
  	internal class ILInterpreter
  	{
  		MethodMirror method;
  
  		public ILInterpreter (MethodMirror method) {
  			this.method = method;
  		}
  
  		public Value Evaluate (Value this_val, Value[] args) {
  			var body = method.GetMethodBody ();
  
  			// Implement only the IL opcodes required to evaluate mcs compiled property accessors:
  			// IL_0000:  nop
  			// IL_0001:  ldarg.0
  			// IL_0002:  ldfld      int32 Tests::field_i
  			// IL_0007:  stloc.0
  			// IL_0008:  br         IL_000d
  			// IL_000d:  ldloc.0
  			// IL_000e:  ret
  			// ... or returns a simple constant:
  			// IL_0000:  ldc.i4 1024
  			// IL_0005:  conv.i8
  			// IL_0006:  ret
  			if (args != null && args.Length != 0)
  				throw new NotSupportedException ();
  
  			if (method.IsStatic || method.DeclaringType.IsValueType || this_val == null || !(this_val is ObjectMirror))
  				throw new NotSupportedException ();
  
  			var instructions = body.Instructions;
  			if (instructions.Count < 1 || instructions.Count > 16)
  				throw new NotSupportedException ();
  
  			var stack = new Value [16];
  			var ins = instructions [0];
  			Value locals_0 = null;
  			int ins_count = 0;
  			int sp = 0;
  
  			while (ins != null) {
  				if (ins_count > 16)
  					throw new NotImplementedException ();
  
  				var next = ins.Next;
  				ins_count++;
  
  				var op = ins.OpCode;
  				if (op == OpCodes.Nop) {
  				} else if (op == OpCodes.Ldarg_0) {
  					if (sp != 0)
  						throw new NotSupportedException ();
  
  					stack [sp++] = this_val;
  				} else if (op == OpCodes.Ldfld) {
  					if (sp != 1)
  						throw new NotSupportedException ();
  
  					var obj = (ObjectMirror) stack [--sp];
  					var field = (FieldInfoMirror) ins.Operand;
  					try {
  						stack [sp++] = obj.GetValue (field);
  					} catch (ArgumentException) {
  						throw new NotSupportedException ();
  					}
  				} else if (op == OpCodes.Ldc_I4_0) {
  					if (sp != 0)
  						throw new NotSupportedException ();
  
  					try {
  						stack [sp++] = new PrimitiveValue (method.VirtualMachine, 0);
  					} catch (ArgumentException) {
  						throw new NotSupportedException ();
  					}
  				} else if (op == OpCodes.Ldc_I4_1) {
  					if (sp != 0)
  						throw new NotSupportedException ();
  
  					try {
  						stack [sp++] = new PrimitiveValue (method.VirtualMachine, 1);
  					} catch (ArgumentException) {
  						throw new NotSupportedException ();
  					}
  				} else if (op == OpCodes.Ldc_I4_2) {
  					if (sp != 0)
  						throw new NotSupportedException ();
  
  					try {
  						stack [sp++] = new PrimitiveValue (method.VirtualMachine, 2);
  					} catch (ArgumentException) {
  						throw new NotSupportedException ();
  					}
  				} else if (op == OpCodes.Ldc_I4_3) {
  					if (sp != 0)
  						throw new NotSupportedException ();
  
  					try {
  						stack [sp++] = new PrimitiveValue (method.VirtualMachine, 3);
  					} catch (ArgumentException) {
  						throw new NotSupportedException ();
  					}
  				} else if (op == OpCodes.Ldc_I4_4) {
  					if (sp != 0)
  						throw new NotSupportedException ();
  
  					try {
  						stack [sp++] = new PrimitiveValue (method.VirtualMachine, 4);
  					} catch (ArgumentException) {
  						throw new NotSupportedException ();
  					}
  				} else if (op == OpCodes.Ldc_I4_5) {
  					if (sp != 0)
  						throw new NotSupportedException ();
  
  					try {
  						stack [sp++] = new PrimitiveValue (method.VirtualMachine, 5);
  					} catch (ArgumentException) {
  						throw new NotSupportedException ();
  					}
  				} else if (op == OpCodes.Ldc_I4_6) {
  					if (sp != 0)
  						throw new NotSupportedException ();
  
  					try {
  						stack [sp++] = new PrimitiveValue (method.VirtualMachine, 6);
  					} catch (ArgumentException) {
  						throw new NotSupportedException ();
  					}
  				} else if (op == OpCodes.Ldc_I4_7) {
  					if (sp != 0)
  						throw new NotSupportedException ();
  
  					try {
  						stack [sp++] = new PrimitiveValue (method.VirtualMachine, 7);
  					} catch (ArgumentException) {
  						throw new NotSupportedException ();
  					}
  				} else if (op == OpCodes.Ldc_I4_8) {
  					if (sp != 0)
  						throw new NotSupportedException ();
  
  					try {
  						stack [sp++] = new PrimitiveValue (method.VirtualMachine, 8);
  					} catch (ArgumentException) {
  						throw new NotSupportedException ();
  					}
  				} else if (op == OpCodes.Ldc_I4_M1) {
  					if (sp != 0)
  						throw new NotSupportedException ();
  
  					try {
  						stack [sp++] = new PrimitiveValue (method.VirtualMachine, -1);
  					} catch (ArgumentException) {
  						throw new NotSupportedException ();
  					}
  				} else if (op == OpCodes.Ldc_I4) {
  					if (sp != 0)
  						throw new NotSupportedException ();
  
  					try {
  						stack [sp++] = new PrimitiveValue (method.VirtualMachine, ins.Operand);
  					} catch (ArgumentException) {
  						throw new NotSupportedException ();
  					}
  				} else if (op == OpCodes.Ldc_I4_S) {
  					if (sp != 0)
  						throw new NotSupportedException ();
  
  					try {
  						stack [sp++] = new PrimitiveValue (method.VirtualMachine, ins.Operand);
  					} catch (ArgumentException) {
  						throw new NotSupportedException ();
  					}
  				} else if (op == OpCodes.Ldc_I8) {
  					if (sp != 0)
  						throw new NotSupportedException ();
  
  					try {
  						stack [sp++] = new PrimitiveValue (method.VirtualMachine, ins.Operand);
  					} catch (ArgumentException) {
  						throw new NotSupportedException ();
  					}
  				} else if (op == OpCodes.Ldc_R4) {
  					if (sp != 0)
  						throw new NotSupportedException ();
  
  					try {
  						stack [sp++] = new PrimitiveValue (method.VirtualMachine, ins.Operand);
  					} catch (ArgumentException) {
  						throw new NotSupportedException ();
  					}
  				} else if (op == OpCodes.Ldc_R8) {
  					if (sp != 0)
  						throw new NotSupportedException ();
  
  					try {
  						stack [sp++] = new PrimitiveValue (method.VirtualMachine, ins.Operand);
  					} catch (ArgumentException) {
  
gt: 						throw new NotSupportedException ();