Opcodes

Namespace: Razorvine.Pickle
We found 10 examples in language CSharp for this search. You will see 51 fragments of code.
        #region No parameters
        /// <summary>
        ///   <para>Prints <see cref="OpCodes.Add"/>:</para>
        ///   <para>"Add two values, returning a new value."</para>
        /// </summary>
        public static void Add() => Emit((ILOpCode)OpCodes.Add.Value);
        
        /// <summary>
        ///   <para>Prints <see cref="OpCodes.Add_Ovf"/>:</para>
        ///   <para>"Add signed integer values with overflow check."</para>
        /// </summary>
        public static void Add_Ovf() => Emit((ILOpCode)OpCodes.Add_Ovf.Value);
        
        /// <summary>
        ///   <para>Prints <see cref="OpCodes.Add_Ovf_Un"/>:</para>
        ///   <para>"Add unsigned integer values with overflow check."</para>
        /// </summary>
        public static void Add_Ovf_Un() => Emit((ILOpCode)OpCodes.Add_Ovf_Un.Value);
        
        /// <summary>
        ///   <para>Prints <see cref="OpCodes.And"/>:</para>
        ///   <para>"Bitwise AND of two integral values, returns an integral value."</para>
        /// </summary>
        public static void And() => Emit((ILOpCode)OpCodes.And.Value);
        
        /// <summary>
        ///   <para>Prints <see cref="OpCodes.Arglist"/>:</para>
        ///   <para>"Return argument list handle for the current method."</para>
        /// </summary>
        public static void Arglist() => Emit((ILOpCode)OpCodes.Arglist.Value);
        
        /// <summary>
        ///   <para>Prints <see cref="OpCodes.Break"/>:</para>
        ///   <para>"Inform a debugger that a breakpoint has been reached."</para>
        /// </summary>
        public static void Break() => Emit((ILOpCode)OpCodes.Break.Value);


		public static void EmitLoadCopConditionBit( GenerationContext context, int cop )
		{
			Debug.Assert( cop == 1 );
			context.ILGen.Emit( OpCodes.Ldarg_0 );
			context.ILGen.Emit( OpCodes.Ldfld, context.Core0Cp1 );
			context.ILGen.Emit( OpCodes.Call, context.Cp1ConditionBitGet );
		}

		public static void EmitStoreCopConditionBit( GenerationContext context, int cop )
		{
			Debug.Assert( cop == 1 );
			context.ILGen.Emit( OpCodes.Stloc_0 );
			context.ILGen.Emit( OpCodes.Ldarg_0 );
			context.ILGen.Emit( OpCodes.Ldfld, context.Core0Cp1 );
			context.ILGen.Emit( OpCodes.Ldloc_0 );
			context.ILGen.Emit( OpCodes.Conv_U1 );
			context.ILGen.Emit( OpCodes.Call, context.Cp1ConditionBitSet );
		}

			public static GenerationResult LUI( GenerationContext context, int pass, int address, uint code, byte opcode, byte rs, byte rt, ushort imm )
			{
				if( pass == 0 )
				{
					context.WriteRegisters[ rt ] = true;
				}
				else if( pass == 1 )
				{
					context.ILGen.Emit( OpCodes.Ldc_I4, ( int )( ( uint )imm << 16 ) );
					EmitStoreRegister( context, rt );
					//rt.Value = imm << 16;
				}
				return GenerationResult.Success;
			}

			public static GenerationResult BREAK( GenerationContext context, int pass, int address, uint code, byte opcode, byte rs, byte rt, byte rd, byte shamt, byte function )
			{
				if( pass == 0 )
				{
				}
				else if( pass == 1 )
				{
					context.ILGen.Emit( OpCodes.Call, typeof( Debugger ).GetMethod( "Break" ) );
				}
				return GenerationResult.Success;
			}

using System;
using System.Collections;
using System.Globalization;
using System.Reflection;
using System.Reflection.Emit;
using System.Threading;

#if NET_2_0
using System.Collections.Generic;
#endif

namespace System.Text.RegularExpressions {

	//
	// Compiler which generates IL bytecode to perform the matching instead of
	// interpreting a program.
	// For simplicity, we inherit from RxCompiler, and generate the IL code based
	// on the program generated by it. This also allows us to fallback to interpretation
	// if we can't handle something.
	// This is net 2.0, since 1.0 doesn't support DynamicMethods
	// FIXME: Add support for 1.0, and CompileToAssembly
	// FIXME: Overwrite RxCompiler methods so we don't have to decode char
	// matching opcodes
	//

#if NET_2_0
	class CILCompiler : RxCompiler, ICompiler {
		DynamicMethod[] eval_methods;
		bool[] eval_methods_defined;

		/*
		 * To avoid the overhead of decoding the countless opcode variants created
		 * by RxCompiler, we save the original, 'generic' version and its flags
		 * in these two tables.
		 */
		private Dictionary<int, int> generic_ops;
		private Dictionary<int, int> op_flags;
		private Dictionary<int, Label> labels;

		static FieldInfo fi_str = typeof (RxInterpreter).GetField ("str", BindingFlags.Instance|BindingFlags.NonPublic);
		static FieldInfo fi_string_start = typeof (RxInterpreter).GetField ("string_start", BindingFlags.Instance|BindingFlags.NonPublic);
		static FieldInfo fi_string_end = typeof (RxInterpreter).GetField ("string_end", BindingFlags.Instance|BindingFlags.NonPublic);
		static FieldInfo fi_program = typeof (RxInterpreter).GetField ("program", BindingFlags.Instance|BindingFlags.NonPublic);
		static FieldInfo fi_marks = typeof (RxInterpreter).GetField ("marks", BindingFlags.Instance|BindingFlags.NonPublic);
		static FieldInfo fi_groups = typeof (RxInterpreter).GetField ("groups", BindingFlags.Instance|BindingFlags.NonPublic);
		static FieldInfo fi_deep = typeof (RxInterpreter).GetField ("deep", BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic);
		static FieldInfo fi_stack = typeof (RxInterpreter).GetField ("stack", BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic);
		static FieldInfo fi_mark_start = typeof (Mark).GetField ("Start", BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic);
		static FieldInfo fi_mark_end = typeof (Mark).GetField ("End", BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic);
		//static FieldInfo fi_mark_index = typeof (Mark).GetField ("Index", BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic);

		static MethodInfo mi_stack_get_count, mi_stack_set_count, mi_stack_push, mi_stack_pop;
		static MethodInfo mi_set_start_of_match, mi_is_word_char, mi_reset_groups;
		static MethodInfo mi_checkpoint, mi_backtrack, mi_open, mi_close;
		static MethodInfo mi_get_last_defined, mi_mark_get_index, mi_mark_get_length;

		public static readonly bool trace_compile = Environment.GetEnvironmentVariable ("MONO_TRACE_RX_COMPILE") != null;

		public CILCompiler () {
			generic_ops = new Dictionary <int, int> ();
			op_flags = new Dictionary <int, int> ();
		}

		IMachineFactory ICompiler.GetMachineFactory () {
			byte[] code = new byte [curpos];
			Buffer.BlockCopy (program, 0, code, 0, curpos);

			eval_methods = new DynamicMethod [code.Length];
			eval_methods_defined = new bool [code.Length];

			// The main eval method
		    DynamicMethod main = GetEvalMethod (code, 11);

			if (main != null)
				return new RxInterpreterFactory (code, (EvalDelegate)main.CreateDelegate (typeof (EvalDelegate)));
			else
				return new RxInterpreterFactory (code, null);
		}

		DynamicMethod GetEvalMethod (byte[] program, int pc) {
			if (eval_methods_defined [pc])
				return eval_methods [pc];

			// FIXME: Recursion ?
			eval_methods_defined [pc] = true;

			eval_methods [pc] = CreateEvalMethod (program, pc);
			return eval_methods [pc];
		}

		private MethodInfo GetMethod (Type t, string name, ref MethodInfo cached) {
			if (cached == null) {
				cached = t.GetMethod (name, BindingFlags.Static|BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic);
				if (cached == null)
					throw new Exception ("Method not found: " + name);
			}
			return cached;
		}

		private MethodInfo GetMethod (string name, ref MethodInfo cached) {
			return GetMethod (typeof (RxInterpreter), name, ref cached);
	    }

		private int ReadInt (byte[] code, int pc) {
			int val = code [pc];
			val |= code [pc + 1] << 8;
			val |= code [pc + 2] << 16;
			val |= code [pc + 3] << 24;
			return val;
		}

		static OpFlags MakeFlags (bool negate, bool ignore, bool reverse, bool lazy) {
			OpFlags flags = 0;
			if (negate) flags |= OpFlags.Negate;
			if (ignore) flags |= OpFlags.IgnoreCase;
			if (reverse) flags |= OpFlags.RightToLeft;
			if (lazy) flags |= OpFlags.Lazy;

			return flags;
		}

		void EmitGenericOp (RxOp op, bool negate, bool ignore, bool reverse, bool lazy) {
			generic_ops [curpos] = (int)op;
			op_flags [curpos] = (int)MakeFlags (negate, ignore, reverse, false);
	    }

		public override void EmitOp (RxOp op, bool negate, bool ignore, bool reverse) {
			EmitGenericOp (op, negate, ignore, reverse, false);
			base.EmitOp (op, negate, ignore, reverse);
		}

		public override void EmitOpIgnoreReverse (RxOp op, bool ignore, bool reverse) {
			EmitGenericOp (op, false, ignore, reverse, false);
			base.EmitOpIgnoreReverse (op, ignore, reverse);
		}

		public override void EmitOpNegateReverse (RxOp op, bool negate, bool reverse) {
			EmitGenericOp (op, negate, false, reverse, false);
			base.EmitOpNegateReverse (op, negate, reverse);
		}

		class Frame {
			public Label label_pass, label_fail;

			public Frame (ILGenerator ilgen) {
				label_fail = ilgen.DefineLabel ();
				label_pass = ilgen.DefineLabel ();
			}				
		}

		LocalBuilder local_textinfo;

		/*
		 * Create a dynamic method which is equivalent to the RxInterpreter.EvalByteCode 
		 * method specialized to the given program and a given pc. Return the newly
		 * created method or null if a not-supported opcode was encountered.
		 */
		DynamicMethod CreateEvalMethod (byte[] program, int pc) {
			DynamicMethod m = new DynamicMethod ("Eval_" + pc, typeof (bool), new Type [] { typeof (RxInterpreter), typeof (int), typeof (int).MakeByRefType () }, typeof (RxInterpreter), true);
			ILGenerator ilgen = m.GetILGenerator ();

			/* 
			   Args:
			   interp - 0
			   strpos - 1
			   strpos_result - 2
			*/

			/*
			 * Recursive calls to EvalByteCode are inlined manually by calling 
			 * EmitEvalMethodBody with the pc of the recursive call. Frame objects hold
			 * the information required to link together the code generated by the recursive
			 * call with the rest of the code.
			 */
			Frame frame = new Frame (ilgen);

			/* Cache the textinfo used by Char.ToLower () */
			local_textinfo = ilgen.DeclareLocal (typeof (TextInfo));
			ilgen.Emit (OpCodes.Call, typeof (Thread).GetMethod ("get_CurrentThread"));
			ilgen.Emit (OpCodes.Call, typeof (Thread).GetMethod ("get_CurrentCulture"));
			ilgen.Emit (OpCodes.Call, typeof (CultureInfo).GetMethod ("get_TextInfo"));
			ilgen.Emit (OpCodes.Stloc, local_textinfo);

			m = EmitEvalMethodBody (m, ilgen, frame, program, pc, program.Length, false, false, out pc);
			if (m == null)
				return null;
				
			ilgen.MarkLabel (frame.label_pass);
			ilgen.Emit (OpCodes.Ldarg_2);
			ilgen.Emit (OpCodes.Ldarg_1);
			ilgen.Emit (OpCodes.Stind_I4);
			ilgen.Emit (OpCodes.Ldc_I4_1);
			ilgen.Emit (OpCodes.Ret);

			ilgen.MarkLabel (frame.label_fail);
			ilgen.Emit (OpCodes.Ldc_I4_0);
			ilgen.Emit (OpCodes.Ret);

			return m;
		}

		private int ReadShort (byte[] program, int pc) {
			return (int)program [pc] | ((int)program [pc + 1] << 8);
		}

		private Label CreateLabelForPC (ILGenerator ilgen, int pc) {
			if (labels == null)
				labels = new Dictionary <int, Label> ();
			Label l;
			if (!labels.TryGetValue (pc, out l)) {
				l = ilgen.DefineLabel ();
				labels [pc] = l;
			}

			return l;
		}

		private int GetILOffset (ILGenerator ilgen) {
			return (int)typeof (ILGenerator).GetField ("code_len", BindingFlags.Instance|BindingFlags.NonPublic).GetValue (ilgen);
		}

		/*
		 * Emit IL code for a sequence of opcodes between pc and end_pc. If there is a
		 * match, set strpos (Arg 1) to the position after the match, then 
		 * branch to frame.label_pass. Otherwise branch to frame.label_fail, 
		 * and leave strpos at an undefined position. The caller should 
		 * generate code to save the original value of strpos if it needs it.
		 * If one_op is true, only generate code for one opcode and set out_pc 
		 * to the next pc after the opcode.
		 * If no_bump is true, don't bump strpos in char matching opcodes.
		 * Keep this in synch with RxInterpreter.EvalByteCode (). It it is sync with
		 * the version in r111969.
		 * FIXME: Modify the regex tests so they are run with RegexOptions.Compiled as
		 * well.
		 */
		private DynamicMethod EmitEvalMethodBody (DynamicMethod m, ILGenerator ilgen,
												  Frame frame, byte[] program,
												  int pc, int end_pc,
 												  bool one_op, bool no_bump,
												  out int out_pc)
		{
			int start, length, end;

			out_pc = 0;

			int group_count = 1 + ReadShort (program, 1);

			while (pc < end_pc) {
				RxOp op = (RxOp)program [pc];

				// FIXME: Optimize this
				if (generic_ops.ContainsKey (pc))
					op = (RxOp)generic_ops [pc];

				if (trace_compile) {
					Console.WriteLine ("compiling {0} pc={1} end_pc={2}, il_offset=0x{3:x}", op, pc, end_pc, GetILOffset (ilgen));
				}

				if (labels != null) {
					Label l;
					if (labels.TryGetValue (pc, out l)) {
						ilgen.MarkLabel (l);
						labels.Remove (pc);
					}
				}

				if (RxInterpreter.trace_rx) {
					//Console.WriteLine ("evaluating: {0} at pc: {1}, strpos: {2}", op, pc, strpos);
					ilgen.Emit (OpCodes.Ldstr, "evaluating: {0} at pc: {1}, strpos: {2}");
					ilgen.Emit (OpCodes.Ldc_I4, (int)op);
					ilgen.Emit (OpCodes.Box, typeof (RxOp));
					ilgen.Emit (OpCodes.Ldc_I4, pc);
					ilgen.Emit (OpCodes.Box, typeof (int));
					ilgen.Emit (OpCodes.Ldarg_1);
					ilgen.Emit (OpCodes.Box, typeof (int));
					ilgen.Emit (OpCodes.Call, typeof (Console).GetMethod ("WriteLine", new Type [] { typeof (string), typeof (object), typeof (object), typeof (object) }));
				}

				switch (op) {
				case RxOp.Anchor:
				case RxOp.AnchorReverse: {
					bool reverse = (RxOp)program [pc] == RxOp.AnchorReverse;
					length = ReadShort (program, pc + 3);
					pc += ReadShort (program, pc + 1);

					// Optimize some common cases by inlining the code generated for the
					// anchor body 
					RxOp anch_op = (RxOp)program [pc];

					// FIXME: Do this even if the archor op is not the last in the regex
					if (!reverse && group_count == 1 && anch_op == RxOp.Char && (RxOp)program [pc + 2] == RxOp.True) {

						/*
						 * while (strpos < string_end) {
						 *   if (str [strpos] == program [pc + 1]) {
						 *     match_start = strpos;
						 *     strpos_result = strpos + 1;
						 *     marks [groups [0]].Start = strpos;
						 *     if (groups.Length > 1)
						 *		marks [groups [0]].End = res;
						 *     return true;
						 *   }
						 *   strpos ++;
						 * }
						 * return false;
						 */
						// Add some locals to avoid an indirection
						LocalBuilder local_string_end = ilgen.DeclareLocal (typeof (int));
						ilgen.Emit (OpCodes.Ldarg_0);
						ilgen.Emit (OpCodes.Ldfld, fi_string_end);
						ilgen.Emit (OpCodes.Stloc, local_string_end);
						LocalBuilder local_str = ilgen.DeclareLocal (typeof (string));
						ilgen.Emit (OpCodes.Ldarg_0);
						ilgen.Emit (OpCodes.Ldfld, fi_str);
						ilgen.Emit (OpCodes.Stloc, local_str);

						//while (strpos < string_end) {
						// -> Done at the end of the loop like mcs does
						Label l1 = ilgen.DefineLabel ();
						Label l2 = ilgen.DefineLabel ();
						ilgen.Emit (OpCodes.Br, l2);
						ilgen.MarkLabel (l1);

						//  if (str [strpos] == program [pc + 1]) {
						Label l3 = ilgen.DefineLabel ();
						ilgen.Emit (OpCodes.Ldloc, local_str);
						ilgen.Emit (OpCodes.Ldarg_1);
						ilgen.Emit (OpCodes.Callvirt, typeof (string).GetMethod ("get_Chars"));
						ilgen.Emit (OpCodes.Conv_I4);
						ilgen.Emit (OpCodes.Ldc_I4, (int)program [pc + 1]);
						ilgen.Emit (OpCodes.Beq, l3);

						// The true case is done after the loop

						//  }
						//  strpos++;
						ilgen.Emit (OpCodes.Ldarg_1);
						ilgen.Emit (OpCodes.Ldc_I4_1);
						ilgen.Emit (OpCodes.Add);
						ilgen.Emit (OpCodes.Starg, 1);
						//}
						ilgen.MarkLabel (l2);
						ilgen.Emit (OpCodes.Ldarg_1);
						ilgen.Emit (OpCodes.Ldloc, local_string_end);
						ilgen.Emit (OpCodes.Blt, l1);

						//return false;
						ilgen.Emit (OpCodes.Br, frame.label_fail);

						// True case
						ilgen.MarkLabel (l3);
						// call SetStartOfMatch (strpos)
						ilgen.Emit (OpCodes.Ldarg_0);
						ilgen.Emit (OpCodes.Ldarg_1);
						ilgen.Emit (OpCodes.Call, GetMethod (typeof (RxInterpreter), "SetStartOfMatch", ref mi_set_start_of_match));
						//  strpos++;
						ilgen.Emit (OpCodes.Ldarg_1);
						ilgen.Emit (OpCodes.Ldc_I4_1);
						ilgen.Emit (OpCodes.Add);
						ilgen.Emit (OpCodes.Starg, 1);
						//    return true;
						ilgen.Emit (OpCodes.Br, frame.label_pass);

					} else {
						// General case

						//Console.WriteLine ("Anchor op " + anch_op);

						// Add some locals to avoid an indirection
						LocalBuilder local_string_end = ilgen.DeclareLocal (typeof (int));
						ilgen.Emit (OpCodes.Ldarg_0);
						ilgen.Emit (OpCodes.Ldfld, fi_string_end);
						ilgen.Emit (OpCodes.Ldc_I4_1);
						ilgen.Emit (OpCodes.Add);
						ilgen.Emit (OpCodes.Stloc, local_string_end);

						//while (strpos < string_end + 1) {
						// -> Done at the end of the loop like mcs does
						Label l1 = ilgen.DefineLabel ();
						Label l2 = ilgen.DefineLabel ();
						ilgen.Emit (OpCodes.Br, l2);
						ilgen.MarkLabel (l1);

						//if (groups.Length > 1) {
						//	ResetGroups ();
						//	marks [groups [0]].Start = strpos;
						//}
						if (group_count > 1) {
							ilgen.Emit (OpCodes.Ldarg_0);
							ilgen.Emit (OpCodes.Call, GetMethod ("ResetGroups", ref mi_reset_groups));

							ilgen.Emit (OpCodes.Ldarg_0);
							ilgen.Emit (OpCodes.Ldfld, fi_marks);
							ilgen.Emit (OpCodes.Ldarg_0);
							ilgen.Emit (OpCodes.Ldfld, fi_groups);
							ilgen.Emit (OpCodes.Ldc_I4_0);
							ilgen.Emit (OpCodes.Ldelem_I4);
							ilgen.Emit (OpCodes.Ldelema, typeof (Mark));
							ilgen.Emit (OpCodes.Ldarg_1);
							ilgen.Emit (OpCodes.Stfld, fi_mark_start);
						}

						//  if (EvalByteCode (pc, strpos, ref res)) {

						Frame new_frame = new Frame (ilgen);

						//  old_stros = strpos;
						LocalBuilder local_old_strpos = ilgen.DeclareLocal (typeof (int));
						ilgen.Emit (OpCodes.Ldarg_1);
						ilgen.Emit (OpCodes.Stloc, local_old_strpos);

						m = EmitEvalMethodBody (m, ilgen, new_frame, program, pc, end_pc, false, false, out out_pc);
						if (m == null)
							return null;

						// Pass
						ilgen.MarkLabel (new_frame.label_pass);
						//    marks [groups [0]].Start = old_strpos;
						ilgen.Emit (OpCodes.Ldarg_0);
						ilgen.Emit (OpCodes.Ldfld, fi_marks);
						ilgen.Emit (OpCodes.Ldarg_0);
						ilgen.Emit (OpCodes.Ldfld, fi_groups);
						ilgen.Emit (OpCodes.Ldc_I4_0);
						ilgen.Emit (OpCodes.Ldelem_I4);
						ilgen.Emit (OpCodes.Ldelema, typeof (Mark));
						ilgen.Emit (OpCodes.Ldloc, local_old_strpos);
						ilgen.Emit (OpCodes.Stfld, fi_mark_start);
						//    if (groups.Length > 1)
						//		marks [groups [0]].End = res;
						if (group_count > 1) {
							ilgen.Emit (OpCodes.Ldarg_0);
							ilgen.Emit (OpCodes.Ldfld, fi_marks);
							ilgen.Emit (OpCodes.Ldarg_0);
							ilgen.Emit (OpCodes.Ldfld, fi_groups);
							ilgen.Emit (OpCodes.Ldc_I4_0);
							ilgen.Emit (OpCodes.Ldelem_I4);
							ilgen.Emit (OpCodes.Ldelema, typeof (Mark));
							ilgen.Emit (OpCodes.Ldarg_1);
							ilgen.Emit (OpCodes.Stfld, fi_mark_end);
						}

						//    return true;
						ilgen.Emit (OpCodes.Br, frame.label_pass);

						// Fail
						ilgen.MarkLabel (new_frame.label_fail);
						//  strpos = old_strpos +/- 1;
						ilgen.Emit (OpCodes.Ldloc, local_old_strpos);
						ilgen.Emit (OpCodes.Ldc_I4_1);
						if (reverse)
							ilgen.Emit (OpCodes.Sub);
						else
							ilgen.Emit (OpCodes.Add);
						ilgen.Emit (OpCodes.Starg, 1);
						//}
						ilgen.MarkLabel (l2);
						if (reverse) {
							ilgen.Emit (OpCodes.Ldarg_1);
							ilgen.Emit (OpCodes.Ldc_I4_0);
							ilgen.Emit (OpCodes.Bge, l1);
						} else {
							ilgen.Emit (OpCodes.Ldarg_1);
							ilgen.Emit (OpCodes.Ldloc, local_string_end);
							ilgen.Emit (OpCodes.Blt, l1);
						}
						//return false;
						ilgen.Emit (OpCodes.Br, frame.label_fail);
					}

					goto End;
				}
				case RxOp.Branch: {
					//if (EvalByteCode (pc + 3, strpos, ref res)) {

					int target_pc = pc + ReadShort (program, pc + 1);

					// Emit the rest of the code inline instead of making a recursive call
					Frame new_frame = new Frame (ilgen);

					//  old_strpos = strpos;
					LocalBuilder local_old_strpos = ilgen.DeclareLocal (typeof (int));
					ilgen.Emit (OpCodes.Ldarg_1);
					ilgen.Emit (OpCodes.Stloc, local_old_strpos);

					m = EmitEvalMethodBody (m, ilgen, new_frame, program, pc + 3, target_pc, false, false, out out_pc);
					if (m == null)
						return null;

					// Pass
					ilgen.MarkLabel (new_frame.label_pass);
					//  return true;
					ilgen.Emit (OpCodes.Br, frame.label_pass);

					// Fail
					ilgen.MarkLabel (new_frame.label_fail);
					//  strpos = old_strpos;
					ilgen.Emit (OpCodes.Ldloc, local_old_strpos);
					ilgen.Emit (OpCodes.Starg, 1);

					pc = target_pc;
					break;
				}
				case RxOp.Char:
				case RxOp.UnicodeChar:
				case RxOp.Range:
				case RxOp.UnicodeRange: {
					OpFlags flags = (OpFlags)op_flags [pc];
					bool negate = (flags & OpFlags.Negate) > 0;
					bool ignore = (flags & OpFlags.IgnoreCase) > 0;
					bool reverse = (flags & OpFlags.RightToLeft) > 0;

					//if (strpos < string_end) {
					Label l1 = ilgen.DefineLabel ();
					if (reverse) {
						ilgen.Emit (OpCodes.Ldarg_1);
						ilgen.Emit (OpCodes.Ldc_I4_0);
						ilgen.Emit (OpCodes.Ble, l1);
					} else {
						ilgen.Emit (OpCodes.Ldarg_1);
						ilgen.Emit (OpCodes.Ldarg_0);
						ilgen.Emit (OpCodes.Ldfld, fi_string_end);
						ilgen.Emit (OpCodes.Bge, l1);
					}

					if (ignore)
						ilgen.Emit (OpCodes.Ldloc, local_textinfo);

					//  int c = str [strpos];
					LocalBuilder local_c = ilgen.DeclareLocal (typeof (char));
					ilgen.Emit (OpCodes.Ldarg_0);
					ilgen.Emit (OpCodes.Ldfld, fi_str);
					ilgen.Emit (OpCodes.Ldarg_1);
					if (reverse) {
						ilgen.Emit (OpCodes.Ldc_I4_1);
						ilgen.Emit (OpCodes.Sub);
					}
					ilgen.Emit (OpCodes.Callvirt, typeof (string).GetMethod ("get_Chars"));
					if (ignore)
						ilgen.Emit (OpCodes.Callvirt, typeof (TextInfo).GetMethod ("ToLower", new Type [] { typeof (char) }));

					if (op == RxOp.Char) {
						ilgen.Emit (OpCodes.Conv_I4);
						ilgen.Emit (OpCodes.Ldc_I4, (int)program [pc + 1]);
						ilgen.Emit (negate ? OpCodes.Beq : OpCodes.Bne_Un, l1);

						pc += 2;
					} else if (op == RxOp.UnicodeChar) {
						ilgen.Emit (OpCodes.Conv_I4);
						ilgen.Emit (OpCodes.Ldc_I4, ReadShort (program, pc + 1));
						ilgen.Emit (negate ? OpCodes.Beq : OpCodes.Bne_Un, l1);

						pc += 3;
					} else if (op == RxOp.Range) {
						ilgen.Emit (OpCodes.Stloc, local_c);

						//  if (c >= program [pc + 1] && c <= program [pc + 2]) {
						if (negate) {
							Label l3 = ilgen.DefineLabel ();

							ilgen.Emit (OpCodes.Ldloc, local_c);
							ilgen.Emit (OpCodes.Ldc_I4, (int)program [pc + 1]);
							ilgen.Emit (OpCodes.Blt, l3);
							ilgen.Emit (OpCodes.Ldloc, local_c);
							ilgen.Emit (OpCodes.Ldc_I4, (int)program [pc + 2]);
							ilgen.Emit (OpCodes.Bgt, l3);
							ilgen.Emit (OpCodes.Br, l1);
							ilgen.MarkLabel (l3);
						} else {
							ilgen.Emit (OpCodes.Ldloc, local_c);
							ilgen.Emit (OpCodes.Ldc_I4, (int)program [pc + 1]);
							ilgen.Emit (OpCodes.Blt, l1);
							ilgen.Emit (OpCodes.Ldloc, local_c);
							ilgen.Emit (OpCodes.Ldc_I4, (int)program [pc + 2]);
							ilgen.Emit (OpCodes.Bgt, l1);
						}

						pc += 3;
					} else if (op == RxOp.UnicodeRange) {
						ilgen.Emit (OpCodes.Stloc, local_c);

						//  if (c >= program [pc + 1] && c <= program [pc + 2]) {
						if (negate) {
							Label l3 = ilgen.DefineLabel ();

							ilgen.Emit (OpCodes.Ldloc, local_c);
							ilgen.Emit (OpCodes.Ldc_I4, ReadShort (program, pc + 1));
							ilgen.Emit (OpCodes.Blt, l3);
							ilgen.Emit (OpCodes.Ldloc, local_c);
							ilgen.Emit (OpCodes.Ldc_I4, ReadShort (program, pc + 3));
							ilgen.Emit (OpCodes.Bgt, l3);
							ilgen.Emit (OpCodes.Br, l1);
							ilgen.MarkLabel (l3);
						} else {
							ilgen.Emit (OpCodes.Ldloc, local_c);
							ilgen.Emit (OpCodes.Ldc_I4, ReadShort (program, pc + 1));
							ilgen.Emit (OpCodes.Blt, l1);
							ilgen.Emit (OpCodes.Ldloc, local_c);
							ilgen.Emit (OpCodes.Ldc_I4, ReadShort (program, pc + 3));
							ilgen.Emit (OpCodes.Bgt, l1);
						}

						pc += 5;
					} else {
						throw new NotSupportedException ();
					}

					//ilgen.EmitWriteLine ("HIT:" + (char)program [pc + 1]);
					if (!no_bump) {
						//  strpos++ / strpos--;
						ilgen.Emit (OpCodes.Ldarg_1);
						ilgen.Emit (OpCodes.Ldc_I4_1);
						if (reverse)
							ilgen.Emit (OpCodes.Sub);
						else
							ilgen.Emit (OpCodes.Add);
						ilgen.Emit (OpCodes.Starg, 1);
					}
					Label l2 = ilgen.DefineLabel ();
					ilgen.Emit (OpCodes.Br, l2);
					//}
					ilgen.MarkLabel (l1);
					//return false;
					ilgen.Emit (OpCodes.Br, frame.label_fail);
					ilgen.MarkLabel (l2);

					break;
				}
				case RxOp.True: {
					//  return true;
					ilgen.Emit (OpCodes.Br, frame.label_pass);
					pc++;
					break;
				}
				case RxOp.False: {
					//  return false;
					ilgen.Emit (OpCodes.Br, frame.label_fail);
					pc++;
					break;
				}
				case RxOp.AnyPosition: {
					pc++;
					break;
				}
				case RxOp.StartOfString: {
					//if (strpos != 0)
					//	return false;
					ilgen.Emit (OpCodes.Ldarg_1);
					ilgen.Emit (OpCodes.Ldc_I4_0);
					ilgen.Emit (OpCodes.Bgt, frame.label_fail);
					pc++;
					break;
				}
				case RxOp.StartOfLine: {
					// FIXME: windows line endings
					//if (!(strpos == 0 || str [strpos - 1] == '\n'))
					//	return false;
					Label l = ilgen.DefineLabel ();
					ilgen.Emit (OpCodes.Ldarg_1);
					ilgen.Emit (OpCodes.Ldc_I4_0);
					ilgen.Emit (OpCodes.Beq, l);
					ilgen.Emit (OpCodes.Ldarg_0);
					ilgen.Emit (OpCodes.Ldfld, fi_str);
					ilgen.Emit (OpCodes.Ldarg_1);
					ilgen.Emit (OpCodes.Ldc_I4_1);
					ilgen.Emit (OpCodes.Sub);
					ilgen.Emit (OpCodes.Callvirt, typeof (string).GetMethod ("get_Chars"));
					ilgen.Emit (OpCodes.Ldc_I4, (int)'\n');
					ilgen.Emit (OpCodes.Beq, l);
					ilgen.Emit (OpCodes.Br, frame.label_fail);
					ilgen.MarkLabel (l);

					pc++;
					break;
				}
				case RxOp.StartOfScan: {
					//if (strpos != string_start)
					//	return false;
					ilgen.Emit (OpCodes.Ldarg_1);
					ilgen.Emit (OpCodes.Ldarg_0);
					ilgen.Emit (OpCodes.Ldfld, fi_string_start);
					ilgen.Emit (OpCodes.Bne_Un, frame.label_fail);
					pc++;
					break;
				}
				case RxOp.End: {
					//if (!(strpos == string_end || (strpos == string_end - 1 && str [strpos] == '\n')))
					//	return false;
					Label l = ilgen.DefineLabel ();

					ilgen.Emit (OpCodes.Ldarg_1);
					ilgen.Emit (OpCodes.Ldarg_0);
					ilgen.Emit (OpCodes.Ldfld, fi_string_end);
					ilgen.Emit (OpCodes.Beq, l);

					Label l2 = ilgen.DefineLabel ();
					ilgen.Emit (OpCodes.Ldarg_1);
					ilgen.Emit (OpCodes.Ldarg_0);
					ilgen.Emit (OpCodes.Ldfld, fi_string_end);
					ilgen.Emit (OpCodes.Ldc_I4_1);
					ilgen.Emit (OpCodes.Sub);
					ilgen.Emit (OpCodes.Bne_Un, l2);
					ilgen.Emit (OpCodes.Ldarg_0);
					ilgen.Emit (OpCodes.Ldfld, fi_str);
					ilgen.Emit (OpCodes.Ldarg_1);
					ilgen.Emit (OpCodes.Callvirt, typeof (string).GetMethod ("get_Chars"));
					ilgen.Emit (OpCodes.Ldc_I4, (int)'\n');
					ilgen.Emit (OpCodes.Bne_Un, l2);
					ilgen.Emit (OpCodes.Br, l);
					ilgen.MarkLabel (l2);

					ilgen.Emit (OpCodes.Br, frame.label_fail);
					ilgen.MarkLabel (l);

					pc++;
					break;
				}
				case RxOp.EndOfString: {
					//if (strpos != string_end)
					//	return false;
					ilgen.Emit (OpCodes.Ldarg_1);
					ilgen.Emit (OpCodes.Ldarg_0);
					ilgen.Emit (OpCodes.Ldfld, fi_string_end);
					ilgen.Emit (OpCodes.Bne_Un, frame.label_fail);
					pc++;
					break;
				}
				case RxOp.EndOfLine: {
					//if (!(strpos == string_end || str [strpos] == '\n'))
					//	return false;
					Label l_match = ilgen.DefineLabel ();
					ilgen.Emit (OpCodes.Ldarg_1);
					ilgen.Emit (OpCodes.Ldarg_0);
					ilgen.Emit (OpCodes.Ldfld, fi_string_end);
					ilgen.Emit (OpCodes.Beq, l_match);
					ilgen.Emit (OpCodes.Ldarg_0);
					ilgen.Emit (OpCodes.Ldfld, fi_str);
					ilgen.Emit (OpCodes.Ldarg_1);
					ilgen.Emit (OpCodes.Callvirt, typeof (string).GetMethod ("get_Chars"));
					ilgen.Emit (OpCodes.Ldc_I4, (int)'\n');
					ilgen.Emit (OpCodes.Beq, l_match);
					ilgen.Emit (OpCodes.Br, frame.label_fail);
					ilgen.MarkLabel (l_match);
					
					pc++;
					break;
				}
				case RxOp.WordBoundary:
				case RxOp.NoWordBoundary: {
					bool negate = op == RxOp.NoWordBoundary;

					//if (string_end == 0)
					//	return false;
					ilgen.Emit (OpCodes.Ldarg_0);
					ilgen.Emit (OpCodes.Ldfld, fi_string_end);
					ilgen.Emit (OpCodes.Ldc_I4_0);
					ilgen.Emit (OpCodes.Beq, frame.label_fail);

					Label l_match = ilgen.DefineLabel ();

					//if (strpos == 0) {
					Label l1 = ilgen.DefineLabel ();
					ilgen.Emit (OpCodes.Ldarg_1);
					ilgen.Emit (OpCodes.Ldc_I4_0);
					ilgen.Emit (OpCodes.Bne_Un, l1);
					//if (!IsWordChar (str [strpos])) {
					//  return false;
					ilgen.Emit (OpCodes.Ldarg_0);
					ilgen.Emit (OpCodes.Ldfld, fi_str);
					ilgen.Emit (OpCodes.Ldarg_1);
					ilgen.Emit (OpCodes.Callvirt, typeof (string).GetMethod ("get_Chars"));
					ilgen.Emit (OpCodes.Call, GetMethod ("IsWordChar", ref mi_is_word_char));
					ilgen.Emit (negate ? OpCodes.Brtrue : OpCodes.Brfalse, frame.label_fail);
					ilgen.Emit (OpCodes.Br, l_match);

					//} else if (strpos == string_end) {
					ilgen.MarkLabel (l1);
					Label l2 = ilgen.DefineLabel ();
					ilgen.Emit (OpCodes.Ldarg_1);
					ilgen.Emit (OpCodes.Ldarg_0);
					ilgen.Emit (OpCodes.Ldfld, fi_string_end);
					ilgen.Emit (OpCodes.Bne_Un, l2);
					//if (!IsWordChar (str [strpos - 1])) {
					//  return false;
					ilgen.Emit (OpCodes.Ldarg_0);
					ilgen.Emit (OpCodes.Ldfld, fi_str);
					ilgen.Emit (OpCodes.Ldarg_1);
					ilgen.Emit (OpCodes.Ldc_I4_1);
					ilgen.Emit (OpCodes.Sub);
					ilgen.Emit (OpCodes.Callvirt, typeof (string).GetMethod ("get_Chars"));
					ilgen.Emit (OpCodes.Call, GetMethod ("IsWordChar", ref mi_is_word_char));
					ilgen.Emit (negate ? OpCodes.Brtrue : OpCodes.Brfalse, frame.label_fail);
					ilgen.Emit (OpCodes.Br, l_match);

					//} else {
					ilgen.MarkLabel (l2);
					//if (IsWordChar (str [strpos]) == IsWordChar (str [strpos - 1])) {
					//  return false;
					ilgen.Emit (OpCodes.Ldarg_0);
					ilgen.Emit (OpCodes.Ldfld, fi_str);
					ilgen.Emit (OpCodes.Ldarg_1);
					ilgen.Emit (OpCodes.Callvirt, typeof (string).GetMethod ("get_Chars"));
					ilgen.Emit (OpCodes.Call, GetMethod ("IsWordChar", ref mi_is_word_char));
					ilgen.Emit (OpCodes.Ldarg_0);
					ilgen.Emit (OpCodes.Ldfld, fi_str);
					ilgen.Emit (OpCodes.Ldarg_1);
					ilgen.Emit (OpCodes.Ldc_I4_1);
					ilgen.Emit (OpCodes.Sub);
					ilgen.Emit (OpCodes.Callvirt, typeof (string).GetMethod ("get_Chars"));
					ilgen.Emit (OpCodes.Call, GetMethod ("IsWordChar", ref mi_is_word_char));
					ilgen.Emit (negate ? OpCodes.Bne_Un : OpCodes.Beq, frame.label_fail);
					ilgen.Emit (OpCodes.Br, l_match);

					ilgen.MarkLabel (l_match);

					pc++;
					break;
				}
				case RxOp.Bitmap:
				case RxOp.UnicodeBitmap: {
					OpFlags flags = (OpFlags)op_flags [pc];
					bool negate = (flags & OpFlags.Negate) > 0;
					bool ignore = (flags & OpFlags.IgnoreCase) > 0;
					bool reverse = (flags & OpFlags.RightToLeft) > 0;
					bool unicode = (op == RxOp.UnicodeBitmap);

					//if (strpos < string_end) {
					Label l1 = ilgen.DefineLabel ();
					Label l2 = ilgen.DefineLabel ();
					Label l_match = ilgen.DefineLabel ();
					if (reverse) {
						ilgen.Emit (OpCodes.Ldarg_1);
						ilgen.Emit (OpCodes.Ldc_I4_0);
						ilgen.Emit (OpCodes.Ble, l1);
					} else {
						ilgen.Emit (OpCodes.Ldarg_1);
						ilgen.Emit (OpCodes.Ldarg_0);
						ilgen.Emit (OpCodes.Ldfld, fi_string_end);
						ilgen.Emit (OpCodes.Bge, l1);
					}
					//  int c = str [strpos];
					LocalBuilder local_c = ilgen.DeclareLocal (typeof (int));
					if (ignore)
						ilgen.Emit (OpCodes.Ldloc, local_textinfo);
					ilgen.Emit (OpCodes.Ldarg_0);
					ilgen.Emit (OpCodes.Ldfld, fi_str);
					ilgen.Emit (OpCodes.Ldarg_1);
					if (reverse) {
						ilgen.Emit (OpCodes.Ldc_I4_1);
						ilgen.Emit (OpCodes.Sub);
					}
					ilgen.Emit (OpCodes.Callvirt, typeof (string).GetMethod ("get_Chars"));
					ilgen.Emit (OpCodes.Conv_I4);
					if (ignore)
						ilgen.Emit (OpCodes.Callvirt, typeof (TextInfo).GetMethod ("ToLower", new Type [] { typeof (char) }));
					//  c -= program [pc + 1];
					if (unicode) {
						ilgen.Emit (OpCodes.Ldc_I4, ReadShort (program, pc + 1));
						ilgen.Emit (OpCodes.Sub);
						ilgen.Emit (OpCodes.Stloc, local_c);
						length = ReadShort (program, pc + 3);
						pc += 5;
					} else {
						ilgen.Emit (OpCodes.Ldc_I4, (int)program [pc + 1]);
						ilgen.Emit (OpCodes.Sub);
						ilgen.Emit (OpCodes.Stloc, local_c);
						length =  program [pc + 2];
						pc += 3;
					}
					//  if (c < 0 || c >= (length << 3))
					//    return false;
					ilgen.Emit (OpCodes.Ldloc, local_c);
					ilgen.Emit (OpCodes.Ldc_I4_0);
					ilgen.Emit (OpCodes.Blt, negate ? l_match : frame.label_fail);
					ilgen.Emit (OpCodes.Ldloc, local_c);
					ilgen.Emit (OpCodes.Ldc_I4, length << 3);
					ilgen.Emit (OpCodes.Bge, negate ? l_match : frame.label_fail);

					// Optimized version for small bitmaps
					if (length <= 4) {
						uint bitmap = program [pc];
						
						if (length > 1)
							bitmap |= ((uint)program [pc + 1] << 8);
						if (length > 2)
							bitmap |= ((uint)program [pc + 2] << 16);
						if (length > 3)
							bitmap |= ((uint)program [pc + 3] << 24);

						//if ((bitmap >> c) & 1)
						ilgen.Emit (OpCodes.Ldc_I4, bitmap);
						ilgen.Emit (OpCodes.Ldloc, local_c);
						ilgen.Emit (OpCodes.Shr_Un);
						ilgen.Emit (OpCodes.Ldc_I4_1);
						ilgen.Emit (OpCodes.And);
						ilgen.Emit (negate ? OpCodes.Brtrue : OpCodes.Brfalse, l1);
					} else {
						//  if ((program [pc + (c >> 3)] & (1 << (c & 0x7))) != 0) {
						ilgen.Emit (OpCodes.Ldarg_0);
						ilgen.Emit (OpCodes.Ldfld, fi_program);
						ilgen.Emit (OpCodes.Ldloc, local_c);
						ilgen.Emit (OpCodes.Ldc_I4_3);
						ilgen.Emit (OpCodes.Shr);
						ilgen.Emit (OpCodes.Ldc_I4, pc);
						ilgen.Emit (OpCodes.Add);
						ilgen.Emit (OpCodes.Ldelem_I1);
						ilgen.Emit (OpCodes.Ldc_I4_1);
						ilgen.Emit (OpCodes.Ldloc, local_c);
						ilgen.Emit (OpCodes.Ldc_I4, 7);
						ilgen.Emit (OpCodes.And);
						ilgen.Emit (OpCodes.Shl);
						ilgen.Emit (OpCodes.And);
						ilgen.Emit (OpCodes.Ldc_I4_0);
						ilgen.Emit (negate ? OpCodes.Bne_Un : OpCodes.Beq, l1);
					}
					ilgen.MarkLabel (l_match);
					if (!no_bump) {
						//  strpos++ / strpos--;
						ilgen.Emit (OpCodes.Ldarg_1);
						ilgen.Emit (OpCodes.Ldc_I4_1);
						if (reverse)
							ilgen.Emit (OpCodes.Sub);
						else
							ilgen.Emit (OpCodes.Add);
						ilgen.Emit (OpCodes.Starg, 1);
					}
					//    continue;
					ilgen.Emit (OpCodes.Br, l2);
					//  }
					//}
					//return false;
					ilgen.MarkLabel (l1);
					ilgen.Emit (OpCodes.Br, frame.label_fail);

					ilgen.MarkLabel (l2);

					pc += length;
					break;
				}
				case RxOp.String:
				case RxOp.UnicodeString: {
					OpFlags flags = (OpFlags)op_flags [pc];
					bool ignore = (flags & OpFlags.IgnoreCase) > 0;
					bool reverse = (flags & OpFlags.RightToLeft) > 0;
					bool unicode = (op == RxOp.UnicodeString);

					if (unicode) {
						start = pc + 3;
						length = ReadShort (program, pc + 1);
					} else {
						start = pc + 2;
						length = program [pc + 1];
					}
					//if (strpos + length > string_end)
					//	return false;
					if (reverse) {
						ilgen.Emit (OpCodes.Ldarg_1);
						ilgen.Emit (OpCodes.Ldc_I4, length);
						ilgen.Emit (OpCodes.Blt, frame.label_fail);
					} else {
						ilgen.Emit (OpCodes.Ldarg_1);
						ilgen.Emit (OpCodes.Ldc_I4, length);
						ilgen.Emit (OpCodes.Add);
						ilgen.Emit (OpCodes.Ldarg_0);
						ilgen.Emit (OpCodes.Ldfld, fi_string_end);
						ilgen.Emit (OpCodes.Bgt, frame.label_fail);
					}

					/* Avoid unsafe code in Moonlight build */
#if false && !NET_2_1
					// FIXME:
					if (reverse || unicode)
						throw new NotImplementedException ();
					int i;
					LocalBuilder local_strptr = ilgen.DeclareLocal (typeof (char).MakePointerType ());
					// char *strptr = &str.start_char + strpos
					ilgen.Emit (OpCodes.Ldarg_0);
					ilgen.Emit (OpCodes.Ldfld, fi_str);
					ilgen.Emit (OpCodes.Ldflda, typeof (String).GetField ("start_char", BindingFlags.Instance|BindingFlags.NonPublic));
					ilgen.Emit (OpCodes.Ldarg_1);
					ilgen.Emit (OpCodes.Ldc_I4_1);
					ilgen.Emit (OpCodes.Shl);
					ilgen.Emit (OpCodes.Add);
					ilgen.Emit (OpCodes.Stloc, local_strptr);

					end = start + length;
					for (i = 0; i < length; ++i) {
						// if (*(strptr + i) != program [start + i])
						//   return false;
						if (ignore)
							ilgen.Emit (OpCodes.Ldloc, local_textinfo);
						ilgen.Emit (OpCodes.Ldloc, local_strptr);
						ilgen.Emit (OpCodes.Ldc_I4, i * 2);
						ilgen.Emit (OpCodes.Add);
						ilgen.Emit (OpCodes.Ldind_I2);
						if (ignore)
							ilgen.Emit (OpCodes.Callvirt, typeof (TextInfo).GetMethod ("ToLower", new Type [] { typeof (char) }));
						ilgen.Emit (OpCodes.Ldc_I4, (int)program [start + i]);
						ilgen.Emit (OpCodes.Bne_Un, frame.label_fail);
					}

					// strpos += length
					ilgen.Emit (OpCodes.Ldarg_1);
					ilgen.Emit (OpCodes.Ldc_I4, length);
					ilgen.Emit (OpCodes.Add);
					ilgen.Emit (OpCodes.Starg, 1);

#else
					// Allocate a local for 'str' to save an indirection
					LocalBuilder local_str = ilgen.DeclareLocal (typeof (string));
					ilgen.Emit (OpCodes.Ldarg_0);
					ilgen.Emit (OpCodes.Ldfld, fi_str);
					ilgen.Emit (OpCodes.Stloc, local_str);

					if (reverse) {
						// strpos -= length;
						ilgen.Emit (OpCodes.Ldarg_1);
						ilgen.Emit (OpCodes.Ldc_I4, length);
						ilgen.Emit (OpCodes.Sub);
						ilgen.Emit (OpCodes.Starg, 1);
					}

					// FIXME: Emit a loop for long strings
					end = start + (unicode ? length * 2 : length);
					while (start < end) {
						//if (str [strpos] != program [start])
						//	return false;
						if (ignore)
							ilgen.Emit (OpCodes.Ldloc, local_textinfo);
						ilgen.Emit (OpCodes.Ldloc, local_str);
						ilgen.Emit (OpCodes.Ldarg_1);
						ilgen.Emit (OpCodes.Callvirt, typeof (string).GetMethod ("get_Chars"));
						if (ignore)
							ilgen.Emit (OpCodes.Callvirt, typeof (TextInfo).GetMethod ("ToLower", new Type [] { typeof (char) }));
						ilgen.Emit (OpCodes.Ldc_I4, unicode ? ReadShort (program, start) : (int)program [start]);
						ilgen.Emit (OpCodes.Bne_Un, frame.label_fail);
						//strpos++;
						ilgen.Emit (OpCodes.Ldarg_1);
						ilgen.Emit (OpCodes.Ldc_I4_1);
						ilgen.Emit (OpCodes.Add);
						ilgen.Emit (OpCodes.Starg, 1);

						if (unicode)
							start += 2;
						else
							start ++;
					}

					if (reverse) {
						// strpos -= length;
						ilgen.Emit (OpCodes.Ldarg_1);
						ilgen.Emit (OpCodes.Ldc_I4, length);
						ilgen.Emit (OpCodes.Sub);
						ilgen.Emit (OpCodes.Starg, 1);
					}
#endif

					pc = end;
					break;
				}
				case RxOp.OpenGroup: {
					//Open (program [pc + 1] | (program [pc + 2] << 8), strpos);
					int group_id = ReadShort (program, pc + 1);
					ilgen.Emit (OpCodes.Ldarg_0);
					ilgen.Emit (OpCodes.Ldc_I4, group_id);
					ilgen.Emit (OpCodes.Ldarg_1);
					ilgen.Emit (OpCodes.Call, GetMethod ("Open", ref mi_open));

					pc += 3;
					break;
				}
				case RxOp.CloseGroup: {
					//Close (program [pc + 1] | (program [pc + 2] << 8), strpos);
					int group_id = ReadShort (program, pc + 1);
					ilgen.Emit (OpCodes.Ldarg_0);
					ilgen.Emit (OpCodes.Ldc_I4, group_id);
					ilgen.Emit (OpCodes.Ldarg_1);
					ilgen.Emit (OpCodes.Call, GetMethod ("Close", ref mi_close));

					pc += 3;
					break;
				}
				case RxOp.Jump: {
					int target_pc = pc + ReadShort (program, pc + 1);
					if (target_pc > end_pc)
						/* 
						 * This breaks the our code generation logic, see
						 * https://bugzilla.novell.com/show_bug.cgi?id=466151
						 * for an example.
						 */
						return null;
					if (trace_compile)
						Console.WriteLine ("\tjump target: {0}", target_pc);
					if (labels == null)
						labels = new Dictionary <int, Label> ();
					Label l = CreateLabelForPC (ilgen, target_pc);
					ilgen.Emit (OpCodes.Br, l);
					pc += 3;
 					break;
				}
				case RxOp.Test: {
					int target1 = pc + ReadShort (program, pc + 1);
					int target2 = pc + ReadShort (program, pc + 3);

					if (trace_compile)
						Console.WriteLine ("\temitting <test_expr>");

					//  old_stros = strpos;
					LocalBuilder local_old_strpos = ilgen.DeclareLocal (typeof (int));
					ilgen.Emit (OpCodes.Ldarg_1);
					ilgen.Emit (OpCodes.Stloc, local_old_strpos);

					Frame new_frame = new Frame (ilgen);
					m = EmitEvalMethodBody (m, ilgen, new_frame, program, pc + 5, target1 < target2 ? target1 : target2, false, false, out pc);
					if (m == null)
						return null;						

					if (trace_compile) {
						Console.WriteLine ("\temitted <test_expr>");
						Console.WriteLine ("\ttarget1 = {0}", target1);
						Console.WriteLine ("\ttarget2 = {0}", target2);
					}

					Label l1 = CreateLabelForPC (ilgen, target1);
					Label l2 = CreateLabelForPC (ilgen, target2);

					// Pass
					ilgen.MarkLabel (new_frame.label_pass);
					//  strpos = old_strpos;
					ilgen.Emit (OpCodes.Ldloc, local_old_strpos);
					ilgen.Emit (OpCodes.Starg, 1);
					ilgen.Emit (OpCodes.Br, l1);
						
					// Fail
					ilgen.MarkLabel (new_frame.label_fail);
					//  strpos = old_strpos;
					ilgen.Emit (OpCodes.Ldloc, local_old_strpos);
					ilgen.Emit (OpCodes.Starg, 1);
					ilgen.Emit (OpCodes.Br, l2);

					// Continue at pc, which should equal to target1
					break;
				}
				case RxOp.SubExpression: {
					int target = pc + ReadShort (program, pc + 1);

					if (trace_compile)
						Console.WriteLine ("\temitting <sub_expr>");

					//  old_stros = strpos;
					LocalBuilder local_old_strpos = ilgen.DeclareLocal (typeof (int));
					ilgen.Emit (OpCodes.Ldarg_1);
					ilgen.Emit (OpCodes.Stloc, local_old_strpos);

					Frame new_frame = new Frame (ilgen);
					m = EmitEvalMethodBody (m, ilgen, new_frame, program, pc + 3, target, false, false, out pc);
					if (m == null)
						return null;						

					if (trace_compile) {
						Console.WriteLine ("\temitted <sub_expr>");
						Console.WriteLine ("\ttarget = {0}", target);
					}

					Label l1 = CreateLabelForPC (ilgen, target);

					// Pass
					ilgen.MarkLabel (new_frame.label_pass);
					ilgen.Emit (OpCodes.Br, l1);
						
					// Fail
					ilgen.MarkLabel (new_frame.label_fail);
					//  strpos = old_strpos;
					ilgen.Emit (OpCodes.Ldloc, local_old_strpos);
					ilgen.Emit (OpCodes.Starg, 1);
					ilgen.Emit (OpCodes.Br, frame.label_fail);

					// Continue at pc, which should equal to target
					break;
				}
				case RxOp.TestCharGroup: {
					int char_group_end = pc + ReadShort (program, pc + 1);
					pc += 3;

					Label label_match = ilgen.DefineLabel ();

					/* Determine the negate/reverse flags by examining the first op */
					OpFlags flags = (OpFlags)op_flags [pc];

					/* Determine whenever this is a negated character class */
					/* If it is, then the conditions are ANDed together, not ORed */
					bool revert = (flags & OpFlags.Negate) > 0;
					bool reverse = (flags & OpFlags.RightToLeft) > 0;

					/*
					 * Generate code for all the matching ops in the group
					 */
					while (pc < char_group_end) {
						Frame new_frame = new Frame (ilgen);
						m = EmitEvalMethodBody (m, ilgen, new_frame, program, pc, Int32.MaxValue, true, true, out pc);
						if (m == null)
							return null;						

						if (!revert) {
							// Pass
							ilgen.MarkLabel (new_frame.label_pass);
							ilgen.Emit (OpCodes.Br, label_match);
						
							// Fail
							// Just fall through to the next test
							ilgen.MarkLabel (new_frame.label_fail);
						} else {
							// Pass
							// Just fall through to the next test
							ilgen.MarkLabel (new_frame.label_pass);
							Label l2 = ilgen.DefineLabel ();
							ilgen.Emit (OpCodes.Br, l2);

							// Fail
							// Fail completely
							ilgen.MarkLabel (new_frame.label_fail);
							ilgen.Emit (OpCodes.Br, frame.label_fail);

							ilgen.MarkLabel (l2);
						}
					}

					if (revert) {
						/* Success */
						ilgen.Emit (OpCodes.Br, label_match);
					} else {
						// If we reached here, all the matching ops have failed
						ilgen.Emit (OpCodes.Br, frame.label_fail);
					}

					ilgen.MarkLabel (label_match);

					//  strpos++ / strpos--;
					ilgen.Emit (OpCodes.Ldarg_1);
					ilgen.Emit (OpCodes.Ldc_I4_1);
					if (reverse)
						ilgen.Emit (OpCodes.Sub);
					else
						ilgen.Emit (OpCodes.Add);
					ilgen.Emit (OpCodes.Starg, 1);

					break;
				}
				case RxOp.FastRepeat:
				case RxOp.FastRepeatLazy: {
					/*
					 * A FastRepeat is a simplified version of Repeat which does
					 * not contain another repeat inside, so backtracking is 
					 * easier.
					 * FIXME: Implement faster backtracking versions for
					 * simple inner exceptions like chars/strings.
					 */
					bool lazy = program [pc] == (byte)RxOp.FastRepeatLazy;
					int tail = pc + ReadShort (program, pc + 1);
 					start = ReadInt (program, pc + 3);
 					end = ReadInt (program, pc + 7);
					//Console.WriteLine ("min: {0}, max: {1} tail: {2}", start, end, tail);

					//  deep = null;
					ilgen.Emit (OpCodes.Ldarg_0);
					ilgen.Emit (OpCodes.Ldnull);
					ilgen.Emit (OpCodes.Stfld, fi_deep);

					LocalBuilder local_length = ilgen.DeclareLocal (typeof (int));

					ilgen.Emit (OpCodes.Ldc_I4_0);
					ilgen.Emit (OpCodes.Stloc, local_length);

					LocalBuilder local_old_strpos = ilgen.DeclareLocal (typeof (int));
					
					// First match at least 'start' items
					if (start > 0) {
						//for (length = 0; length < start; ++length) {
						Label l_loop_footer = ilgen.DefineLabel ();
						ilgen.Emit (OpCodes.Br, l_loop_footer);
						Label l_loop_body = ilgen.DefineLabel ();
						ilgen.MarkLabel (l_loop_body);

						// int old_strpos = strpos;
						ilgen.Emit (OpCodes.Ldarg_1);
						ilgen.Emit (OpCodes.Stloc, local_old_strpos);
						
						// if (!EvalByteCode (pc + 11, strpos, ref res))
						Frame new_frame = new Frame (ilgen);
						m = EmitEvalMethodBody (m, ilgen, new_frame, program, pc + 11, tail, false, false, out out_pc);
						if (m == null)
							return null;

						// Fail
						// return false;
						ilgen.MarkLabel (new_frame.label_fail);
						ilgen.Emit (OpCodes.Br, frame.label_fail);

						// Pass
						ilgen.MarkLabel (new_frame.label_pass);
						// length++
						ilgen.Emit (OpCodes.Ldloc, local_length);
						ilgen.Emit (OpCodes.Ldc_I4_1);
						ilgen.Emit (OpCodes.Add);
						ilgen.Emit (OpCodes.Stloc, local_length);
						// Loop footer
						ilgen.MarkLabel (l_loop_footer);
						ilgen.Emit (OpCodes.Ldloc, local_length);
						ilgen.Emit (OpCodes.Ldc_I4, start);
						ilgen.Emit (OpCodes.Blt, l_loop_body);
					}

					if (lazy) {
						Label l_loop_footer = ilgen.DefineLabel ();
						//while (true) {
						ilgen.Emit (OpCodes.Br, l_loop_footer);
						Label l_loop_body = ilgen.DefineLabel ();
						ilgen.MarkLabel (l_loop_body);
						// Match the tail
						//  int cp = Checkpoint ();
						LocalBuilder local_cp = ilgen.DeclareLocal (typeof (int));
						ilgen.Emit (OpCodes.Ldarg_0);
						ilgen.Emit (OpCodes.Call, GetMethod ("Checkpoint", ref mi_checkpoint));
						ilgen.Emit (OpCodes.Stloc, local_cp);

						// int old_strpos = strpos;
						ilgen.Emit (OpCodes.Ldarg_1);
						ilgen.Emit (OpCodes.Stloc, local_old_strpos);

						//  if (EvalByteCode (tail, strpos, ref res)) {
						Frame new_frame = new Frame (ilgen);
						m = EmitEvalMethodBody (m, ilgen, new_frame, program, tail, end_pc, false, false, out out_pc);
						if (m == null)
							return null;

						// Success:
						ilgen.MarkLabel (new_frame.label_pass);
						//    return true;
						ilgen.Emit (OpCodes.Br, frame.label_pass);

						// Fail:
						ilgen.MarkLabel (new_frame.label_fail);
						//  Backtrack (cp);
						ilgen.Emit (OpCodes.Ldarg_0);
						ilgen.Emit (OpCodes.Ldloc, local_cp);
						ilgen.Emit (OpCodes.Call, GetMethod ("Backtrack", ref mi_backtrack));
						// strpos = old_strpos;
						ilgen.Emit (OpCodes.Ldloc, local_old_strpos);
						ilgen.Emit (OpCodes.Starg, 1);

						//if (length >= end)
						//  return false;
						ilgen.Emit (OpCodes.Ldloc, local_length);
						ilgen.Emit (OpCodes.Ldc_I4, end);
						ilgen.Emit (OpCodes.Bge, frame.label_fail);

						// Match an item
						//if (!EvalByteCode (pc + 11, strpos, ref res))
						new_frame = new Frame (ilgen);
						m = EmitEvalMethodBody (m, ilgen, new_frame, program, pc + 11, tail, false, false, out out_pc);
						if (m == null)
							return null;

						// Success:
						ilgen.MarkLabel (new_frame.label_pass);
						// length ++;
						ilgen.Emit (OpCodes.Ldloc, local_length);
						ilgen.Emit (OpCodes.Ldc_I4_1);
						ilgen.Emit (OpCodes.Add);
						ilgen.Emit (OpCodes.Stloc, local_length);
						ilgen.Emit (OpCodes.Br, l_loop_body);
						
						// Fail:
						ilgen.MarkLabel (new_frame.label_fail);
						// return false;
						ilgen.Emit (OpCodes.Br, frame.label_fail);

						// Loop footer
						ilgen.MarkLabel (l_loop_footer);
						ilgen.Emit (OpCodes.Br, l_loop_body);
					} else {
						// Then match as many items as possible, recording
						// backtracking information
						
						//int old_stack_size = stack.Count;
						LocalBuilder local_old_stack_size = ilgen.DeclareLocal (typeof (int));
						ilgen.Emit (OpCodes.Ldarg_0);
						ilgen.Emit (OpCodes.Ldflda, fi_stack);
						ilgen.Emit (OpCodes.Call, GetMethod (typeof (RxInterpreter.IntStack), "get_Count", ref mi_stack_get_count));
						ilgen.Emit (OpCodes.Stloc, local_old_stack_size);
						//while (length < end) {
						Label l_loop_footer = ilgen.DefineLabel ();
						ilgen.Emit (OpCodes.Br, l_loop_footer);
						Label l_loop_body = ilgen.DefineLabel ();
						ilgen.MarkLabel (l_loop_body);
						//  int cp = Checkpoint ();
						LocalBuilder local_cp = ilgen.DeclareLocal (typeof (int));
						ilgen.Emit (OpCodes.Ldarg_0);
						ilgen.Emit (OpCodes.Call, GetMethod ("Checkpoint", ref mi_checkpoint));
						ilgen.Emit (OpCodes.Stloc, local_cp);

						// int old_strpos = strpos;
						ilgen.Emit (OpCodes.Ldarg_1);
						ilgen.Emit (OpCodes.Stloc, local_old_strpos);

						//  if (!EvalByteCode (pc + 11, strpos, ref res)) {
						Frame new_frame = new Frame (ilgen);
						m = EmitEvalMethodBody (m, ilgen, new_frame, program, pc + 11, tail, false, false, out out_pc);
						if (m == null)
							return null;

						// Fail:
						ilgen.MarkLabel (new_frame.label_fail);
						// strpos = old_strpos
						ilgen.Emit (OpCodes.Ldloc, local_old_strpos);
						ilgen.Emit (OpCodes.Starg, 1);
						//    Backtrack (cp);
						ilgen.Emit (OpCodes.Ldarg_0);
						ilgen.Emit (OpCodes.Ldloc, local_cp);
						ilgen.Emit (OpCodes.Call, GetMethod ("Backtrack", ref mi_backtrack));

						//    break;
						Label l_after_loop = ilgen.DefineLabel ();
						ilgen.Emit (OpCodes.Br, l_after_loop);

						// Success:
						ilgen.MarkLabel (new_frame.label_pass);

						//stack.Push (cp);
						ilgen.Emit (OpCodes.Ldarg_0);
						ilgen.Emit (OpCodes.Ldflda, fi_stack);
						ilgen.Emit (OpCodes.Ldloc, local_cp);
						ilgen.Emit (OpCodes.Call, GetMethod (typeof (RxInterpreter.IntStack), "Push", ref mi_stack_push));
						//stack.Push (strpos);
						ilgen.Emit (OpCodes.Ldarg_0);
						ilgen.Emit (OpCodes.Ldflda, fi_stack);
						ilgen.Emit (OpCodes.Ldloc, local_old_strpos);
						ilgen.Emit (OpCodes.Call, GetMethod (typeof (RxInterpreter.IntStack), "Push", ref mi_stack_push));
						// length++
						ilgen.Emit (OpCodes.Ldloc, local_length);
						ilgen.Emit (OpCodes.Ldc_I4_1);
						ilgen.Emit (OpCodes.Add);
						ilgen.Emit (OpCodes.Stloc, local_length);
						// Loop footer
						ilgen.MarkLabel (l_loop_footer);
						ilgen.Emit (OpCodes.Ldloc, local_length);
						ilgen.Emit (OpCodes.Ldc_I4, end);
						ilgen.Emit (OpCodes.Blt, l_loop_body);

						ilgen.MarkLabel (l_after_loop);

						// Then, match the tail, backtracking as necessary.

						//while (true) {
						l_loop_footer = ilgen.DefineLabel ();
						ilgen.Emit (OpCodes.Br, l_loop_footer);
						l_loop_body = ilgen.DefineLabel ();
						ilgen.MarkLabel (l_loop_body);

						if (RxInterpreter.trace_rx) {
							ilgen.Emit (OpCodes.Ldstr, "matching tail at: {0}");
							ilgen.Emit (OpCodes.Ldarg_1);
							ilgen.Emit (OpCodes.Box, typeof (int));
							ilgen.Emit (OpCodes.Call, typeof (Console).GetMethod ("WriteLine", new Type [] { typeof (string), typeof (object) }));
						}

						//  if (EvalByteCode (tail, strpos, ref res)) {
						new_frame = new Frame (ilgen);
						m = EmitEvalMethodBody (m, ilgen, new_frame, program, tail, end_pc, false, false, out out_pc);
						if (m == null)
							return null;

						// Success:
						ilgen.MarkLabel (new_frame.label_pass);

						if (RxInterpreter.trace_rx) {
							ilgen.Emit (OpCodes.Ldstr, "tail matched at: {0}");
							ilgen.Emit (OpCodes.Ldarg_1);
							ilgen.Emit (OpCodes.Box, typeof (int));
							ilgen.Emit (OpCodes.Call, typeof (Console).GetMethod ("WriteLine", new Type [] { typeof (string), typeof (object) }));
						}

						//	stack.Count = old_stack_size;
						ilgen.Emit (OpCodes.Ldarg_0);
						ilgen.Emit (OpCodes.Ldflda, fi_stack);
						ilgen.Emit (OpCodes.Ldloc, local_old_stack_size);
						ilgen.Emit (OpCodes.Call, GetMethod (typeof (RxInterpreter.IntStack), "set_Count", ref mi_stack_set_count));
						//  return true;
						ilgen.Emit (OpCodes.Br, frame.label_pass);

						// Fail:
						ilgen.MarkLabel (new_frame.label_fail);

						if (RxInterpreter.trace_rx) {
							ilgen.Emit (OpCodes.Ldstr, "tail failed to match at: {0}");
							ilgen.Emit (OpCodes.Ldarg_1);
							ilgen.Emit (OpCodes.Box, typeof (int));
							ilgen.Emit (OpCodes.Call, typeof (Console).GetMethod ("WriteLine", new Type [] { typeof (string), typeof (object) }));
						}

						//  if (stack.Count == old_stack_size)
						//		return false;
						ilgen.Emit (OpCodes.Ldarg_0);
						ilgen.Emit (OpCodes.Ldflda, fi_stack);
						ilgen.Emit (OpCodes.Call, GetMethod (typeof (RxInterpreter.IntStack), "get_Count", ref mi_stack_get_count));
						ilgen.Emit (OpCodes.Ldloc, local_old_stack_size);
						ilgen.Emit (OpCodes.Beq, frame.label_fail);
						
						// Backtrack
						//strpos = stack.Pop ();
						ilgen.Emit (OpCodes.Ldarg_0);
						ilgen.Emit (OpCodes.Ldflda, fi_stack);
						ilgen.Emit (OpCodes.Call, GetMethod (typeof (RxInterpreter.IntStack), "Pop", ref mi_stack_pop));
						ilgen.Emit (OpCodes.Starg, 1);
						//Backtrack (stack.Pop ());
						ilgen.Emit (OpCodes.Ldarg_0);
						ilgen.Emit (OpCodes.Ldarg_0);
						ilgen.Emit (OpCodes.Ldflda, fi_stack);
						ilgen.Emit (OpCodes.Call, GetMethod (typeof (RxInterpreter.IntStack), "Pop", ref mi_stack_pop));
						ilgen.Emit (OpCodes.Call, GetMethod ("Backtrack", ref mi_backtrack));

						if (RxInterpreter.trace_rx) {
							//Console.WriteLine ("backtracking to: {0}", strpos);
							ilgen.Emit (OpCodes.Ldstr, "backtracking to: {0}");
							ilgen.Emit (OpCodes.Ldarg_1);
							ilgen.Emit (OpCodes.Box, typeof (int));
							ilgen.Emit (OpCodes.Call, typeof (Console).GetMethod ("WriteLine", new Type [] { typeof (string), typeof (object) }));
						}

						// Loop footer
						ilgen.MarkLabel (l_loop_footer);
						ilgen.Emit (OpCodes.Br, l_loop_body);
					}

					// We already processed the tail
					pc = out_pc;
					goto End;
				}

				case RxOp.CategoryAny:
				case RxOp.CategoryAnySingleline:
				case RxOp.CategoryWord:
				case RxOp.CategoryDigit:
				case RxOp.CategoryWhiteSpace:
				case RxOp.CategoryEcmaWord:
				case RxOp.CategoryEcmaWhiteSpace:
				case RxOp.CategoryUnicodeSpecials:
				case RxOp.CategoryUnicode: {
					OpFlags flags = (OpFlags)op_flags [pc];
					bool negate = (flags & OpFlags.Negate) > 0;
					bool reverse = (flags & OpFlags.RightToLeft) > 0;

					//if (strpos < string_end) {
					Label l_nomatch = ilgen.DefineLabel ();
					if (reverse) {
						ilgen.Emit (OpCodes.Ldarg_1);
						ilgen.Emit (OpCodes.Ldc_I4_0);
						ilgen.Emit (OpCodes.Ble, l_nomatch);
					} else {
						ilgen.Emit (OpCodes.Ldarg_1);
						ilgen.Emit (OpCodes.Ldarg_0);
						ilgen.Emit (OpCodes.Ldfld, fi_string_end);
						ilgen.Emit (OpCodes.Bge, l_nomatch);
					}

					//  int c = str [strpos];
					LocalBuilder local_c = ilgen.DeclareLocal (typeof (char));
					ilgen.Emit (OpCodes.Ldarg_0);
					ilgen.Emit (OpCodes.Ldfld, fi_str);
					ilgen.Emit (OpCodes.Ldarg_1);
					if (reverse) {
						ilgen.Emit (OpCodes.Ldc_I4_1);
						ilgen.Emit (OpCodes.Sub);
					}
					ilgen.Emit (OpCodes.Callvirt, typeof (string).GetMethod ("get_Chars"));
					ilgen.Emit (OpCodes.Stloc, local_c);

					Label l_match = ilgen.DefineLabel ();

					Label l_true, l_false;

					l_true = negate ? l_nomatch : l_match;
					l_false = negate ? l_match : l_nomatch;

					switch (op) {
					case RxOp.CategoryAny:
						// if (str [strpos] != '\n') {
						ilgen.Emit (OpCodes.Ldloc, local_c);
						ilgen.Emit (OpCodes.Ldc_I4, (int)'\n');
						ilgen.Emit (OpCodes.Bne_Un, l_true);
						break;
					case RxOp.CategoryAnySingleline:
						ilgen.Emit (OpCodes.Br, l_true);
						break;
					case RxOp.CategoryWord:
						//  if (Char.IsLetterOrDigit (c) || Char.GetUnicodeCategory (c) == UnicodeCategory.ConnectorPunctuation) {
						ilgen.Emit (OpCodes.Ldloc, local_c);
						ilgen.Emit (OpCodes.Call, typeof (Char).GetMethod ("IsLetterOrDigit", new Type [] { typeof (char) }));
						ilgen.Emit (OpCodes.Brtrue, l_true);
						ilgen.Emit (OpCodes.Ldloc, local_c);
						ilgen.Emit (OpCodes.Call, typeof (Char).GetMethod ("GetUnicodeCategory", new Type [] { typeof (char) }));
						ilgen.Emit (OpCodes.Ldc_I4, (int)UnicodeCategory.ConnectorPunctuation);
						ilgen.Emit (OpCodes.Beq, l_true);
						break;
					case RxOp.CategoryDigit:
						// if (Char.IsDigit (c)) {
						ilgen.Emit (OpCodes.Ldloc, local_c);
						ilgen.Emit (OpCodes.Call, typeof (Char).GetMethod ("IsDigit", new Type [] { typeof (char) }));
						ilgen.Emit (OpCodes.Brtrue, l_true);
						break;
					case RxOp.CategoryWhiteSpace:
						// if (Char.IsWhiteSpace (c)) {
						ilgen.Emit (OpCodes.Ldloc, local_c);
						ilgen.Emit (OpCodes.Call, typeof (Char).GetMethod ("IsWhiteSpace", new Type [] { typeof (char) }));
						ilgen.Emit (OpCodes.Brtrue, l_true);
						break;
					case RxOp.CategoryEcmaWord:
						// if ('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || '0' <= c && c <= '9' || c == '_') {
						ilgen.Emit (OpCodes.Ldloc, local_c);
						ilgen.Emit (OpCodes.Ldc_I4, (int)'a' - 1);
						ilgen.Emit (OpCodes.Cgt);
						ilgen.Emit (OpCodes.Ldloc, local_c);
						ilgen.Emit (OpCodes.Ldc_I4, (int)'z' + 1);
						ilgen.Emit (OpCodes.Clt);
						ilgen.Emit (OpCodes.And);
						ilgen.Emit (OpCodes.Brtrue, l_true);

						ilgen.Emit (OpCodes.Ldloc, local_c);
						ilgen.Emit (OpCodes.Ldc_I4, (int)'A' - 1);
						ilgen.Emit (OpCodes.Cgt);
						ilgen.Emit (OpCodes.Ldloc, local_c);
						ilgen.Emit (OpCodes.Ldc_I4, (int)'Z' + 1);
						ilgen.Emit (OpCodes.Clt);
						ilgen.Emit (OpCodes.And);
						ilgen.Emit (OpCodes.Brtrue, l_true);

						ilgen.Emit (OpCodes.Ldloc, local_c);
						ilgen.Emit (OpCodes.Ldc_I4, (int)'0' - 1);
						ilgen.Emit (OpCodes.Cgt);
						ilgen.Emit (OpCodes.Ldloc, local_c);
						ilgen.Emit (OpCodes.Ldc_I4, (int)'9' + 1);
						ilgen.Emit (OpCodes.Clt);
						ilgen.Emit (OpCodes.And);
						ilgen.Emit (OpCodes.Brtrue, l_true);

						ilgen.Emit (OpCodes.Ldloc, local_c);
						ilgen.Emit (OpCodes.Ldc_I4, (int)'_');
						ilgen.Emit (OpCodes.Beq, l_true);
						break;
					case RxOp.CategoryEcmaWhiteSpace:
						// if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == '\v') {
						ilgen.Emit (OpCodes.Ldloc, local_c);
						ilgen.Emit (OpCodes.Ldc_I4, (int)' ');
						ilgen.Emit (OpCodes.Beq, l_true);
						ilgen.Emit (OpCodes.Ldloc, local_c);
						ilgen.Emit (OpCodes.Ldc_I4, (int)'\t');
						ilgen.Emit (OpCodes.Beq, l_true);
						ilgen.Emit (OpCodes.Ldloc, local_c);
						ilgen.Emit (OpCodes.Ldc_I4, (int)'\n');
						ilgen.Emit (OpCodes.Beq, l_true);
						ilgen.Emit (OpCodes.Ldloc, local_c);
						ilgen.Emit (OpCodes.Ldc_I4, (int)'\r');
						ilgen.Emit (OpCodes.Beq, l_true);
						ilgen.Emit (OpCodes.Ldloc, local_c);
						ilgen.Emit (OpCodes.Ldc_I4, (int)'\f');
						ilgen.Emit (OpCodes.Beq, l_true);
						ilgen.Emit (OpCodes.Ldloc, local_c);
						ilgen.Emit (OpCodes.Ldc_I4, (int)'\v');
						ilgen.Emit (OpCodes.Beq, l_true);
						break;
					case RxOp.CategoryUnicodeSpecials:
						// if ('\uFEFF' <= c && c <= '\uFEFF' || '\uFFF0' <= c && c <= '\uFFFD') {
						ilgen.Emit (OpCodes.Ldloc, local_c);
						ilgen.Emit (OpCodes.Ldc_I4, (int)'\uFEFF' - 1);
						ilgen.Emit (OpCodes.Cgt);
						ilgen.Emit (OpCodes.Ldloc, local_c);
						ilgen.Emit (OpCodes.Ldc_I4, (int)'\uFEFF' + 1);
						ilgen.Emit (OpCodes.Clt);
						ilgen.Emit (OpCodes.And);
						ilgen.Emit (OpCodes.Brtrue, l_true);

						ilgen.Emit (OpCodes.Ldloc, local_c);
						ilgen.Emit (OpCodes.Ldc_I4, (int)'\uFFF0' - 1);
						ilgen.Emit (OpCodes.Cgt);
						ilgen.Emit (OpCodes.Ldloc, local_c);
						ilgen.Emit (OpCodes.Ldc_I4, (int)'\uFFFD' + 1);
						ilgen.Emit (OpCodes.Clt);
						ilgen.Emit (OpCodes.And);
						ilgen.Emit (OpCodes.Brtrue, l_true);
						break;
					case RxOp.CategoryUnicode:
						// if (Char.GetUnicodeCategory (c) == (UnicodeCategory)program [pc + 1]) {						
						ilgen.Emit (OpCodes.Ldloc, local_c);
						ilgen.Emit (OpCodes.Call, typeof (Char).GetMethod ("GetUnicodeCategory", new Type [] { typeof (char) }));
						ilgen.Emit (OpCodes.Ldc_I4, (int)program [pc + 1]);
						ilgen.Emit (OpCodes.Beq, l_true);
						break;
					}

					ilgen.Emit (OpCodes.Br, l_false);

					ilgen.MarkLabel (l_match);

					//    strpos++;
					if (!no_bump) {
						ilgen.Emit (OpCodes.Ldarg_1);
						ilgen.Emit (OpCodes.Ldc_I4_1);
						if (reverse)
							ilgen.Emit (OpCodes.Sub);
						else
							ilgen.Emit (OpCodes.Add);
						ilgen.Emit (OpCodes.Starg, 1);
					}
					//  }
					Label l2 = ilgen.DefineLabel ();
					ilgen.Emit (OpCodes.Br, l2);
					//}
					ilgen.MarkLabel (l_nomatch);
					//return false;
					ilgen.Emit (OpCodes.Br, frame.label_fail);

					ilgen.MarkLabel (l2);

					if (op == RxOp.CategoryUnicode)
						pc += 2;
					else
						pc++;
					break;
				}
				case RxOp.Reference: {
					OpFlags flags = (OpFlags)op_flags [pc];
					bool ignore = (flags & OpFlags.IgnoreCase) > 0;
					bool reverse = (flags & OpFlags.RightToLeft) > 0;

					//length = GetLastDefined (program [pc + 1] | ((int)program [pc + 2] << 8));
					LocalBuilder loc_length = ilgen.DeclareLocal (typeof (int));
					ilgen.Emit (OpCodes.Ldarg_0);
					ilgen.Emit (OpCodes.Ldc_I4, ReadShort (program, pc + 1)); 
					ilgen.Emit (OpCodes.Call, GetMethod (typeof (RxInterpreter), "GetLastDefined", ref mi_get_last_defined));					
					ilgen.Emit (OpCodes.Stloc, loc_length);
					//if (length < 0)
					//  return false;
					ilgen.Emit (OpCodes.Ldloc, loc_length);
					ilgen.Emit (OpCodes.Ldc_I4_0);
					ilgen.Emit (OpCodes.Blt, frame.label_fail);
					//start = marks [length].Index;
					LocalBuilder loc_start = ilgen.DeclareLocal (typeof (int));
					ilgen.Emit (OpCodes.Ldarg_0);
					ilgen.Emit (OpCodes.Ldfld, fi_marks);
					ilgen.Emit (OpCodes.Ldloc, loc_length);
					ilgen.Emit (OpCodes.Ldelema, typeof (Mark));
					ilgen.Emit (OpCodes.Call, GetMethod (typeof (Mark), "get_Index", ref mi_mark_get_index));
					ilgen.Emit (OpCodes.Stloc, loc_start);
					// length = marks [length].Length;
					ilgen.Emit (OpCodes.Ldarg_0);
					ilgen.Emit (OpCodes.Ldfld, fi_marks);
					ilgen.Emit (OpCodes.Ldloc, loc_length);
					ilgen.Emit (OpCodes.Ldelema, typeof (Mark));
					ilgen.Emit (OpCodes.Call, GetMethod (typeof (Mark), "get_Length", ref mi_mark_get_length));
					ilgen.Emit (OpCodes.Stloc, loc_length);
					if (reverse) {
						//ptr -= length;
						ilgen.Emit (OpCodes.Ldarg_1);
						ilgen.Emit (OpCodes.Ldloc, loc_length);
						ilgen.Emit (OpCodes.Sub);
						ilgen.Emit (OpCodes.Starg, 1);
						//if (ptr < 0)
						//goto Fail;
						ilgen.Emit (OpCodes.Ldarg_1);
						ilgen.Emit (OpCodes.Ldc_I4_0);
						ilgen.Emit (OpCodes.Blt, frame.label_fail);
					} else {
						//if (strpos + length > string_end)
						//  return false;
						ilgen.Emit (OpCodes.Ldarg_1);
						ilgen.Emit (OpCodes.Ldloc, loc_length);
						ilgen.Emit (OpCodes.Add);
						ilgen.Emit (OpCodes.Ldarg_0);
						ilgen.Emit (OpCodes.Ldfld, fi_string_end);
						ilgen.Emit (OpCodes.Bgt, frame.label_fail);
					}

					LocalBuilder local_str = ilgen.DeclareLocal (typeof (string));
					ilgen.Emit (OpCodes.Ldarg_0);
					ilgen.Emit (OpCodes.Ldfld, fi_str);
					ilgen.Emit (OpCodes.Stloc, local_str);

					// end = start + length;
					LocalBuilder loc_end = ilgen.DeclareLocal (typeof (int));
					ilgen.Emit (OpCodes.Ldloc, loc_start);
					ilgen.Emit (OpCodes.Ldloc, loc_length);
					ilgen.Emit (OpCodes.Add);
					ilgen.Emit (OpCodes.Stloc, loc_end);
					//for (; start < end; ++start) {
					Label l_loop_footer = ilgen.DefineLabel ();
					ilgen.Emit (OpCodes.Br, l_loop_footer);
					Label l_loop_body = ilgen.DefineLabel ();
					ilgen.MarkLabel (l_loop_body);
					//if (str [strpos] != str [start])
					//return false;
					if (ignore)
						ilgen.Emit (OpCodes.Ldloc, local_textinfo);
					ilgen.Emit (OpCodes.Ldloc, local_str);
					ilgen.Emit (OpCodes.Ldarg_1);
					ilgen.Emit (OpCodes.Callvirt, typeof (string).GetMethod ("get_Chars"));
					if (ignore)
						ilgen.Emit (OpCodes.Callvirt, typeof (TextInfo).GetMethod ("ToLower", new Type [] { typeof (char) }));
					if (ignore)
						ilgen.Emit (OpCodes.Ldloc, local_textinfo);
					ilgen.Emit (OpCodes.Ldloc, local_str);
					ilgen.Emit (OpCodes.Ldloc, loc_start);
					ilgen.Emit (OpCodes.Callvirt, typeof (string).GetMethod ("get_Chars"));
					if (ignore)
						ilgen.Emit (OpCodes.Callvirt, typeof (TextInfo).GetMethod ("ToLower", new Type [] { typeof (char) }));
					ilgen.Emit (OpCodes.Bne_Un, frame.label_fail);
					// strpos++;
					ilgen.Emit (OpCodes.Ldarg_1);
					ilgen.Emit (OpCodes.Ldc_I4_1);
					ilgen.Emit (OpCodes.Add);
					ilgen.Emit (OpCodes.Starg, 1);
					// start++
					ilgen.Emit (OpCodes.Ldloc, loc_start);
					ilgen.Emit (OpCodes.Ldc_I4_1);
					ilgen.Emit (OpCodes.Add);
					ilgen.Emit (OpCodes.Stloc, loc_start);
					// Loop footer
					ilgen.MarkLabel (l_loop_footer);
					ilgen.Emit (OpCodes.Ldloc, loc_start);
					ilgen.Emit (OpCodes.Ldloc, loc_end);
					ilgen.Emit (OpCodes.Blt, l_loop_body);

					if (reverse) {
						//ptr -= length;
						ilgen.Emit (OpCodes.Ldarg_1);
						ilgen.Emit (OpCodes.Ldloc, loc_length);
						ilgen.Emit (OpCodes.Sub);
						ilgen.Emit (OpCodes.Starg, 1);
					}

					pc += 3;
					break;
				}
				case RxOp.Repeat:
				case RxOp.RepeatLazy:
				case RxOp.IfDefined:
					// FIXME:
					if (RxInterpreter.trace_rx || trace_compile)
						Console.WriteLine ("Opcode " + op + " not supported.");
					return null;
				default:
					throw new NotImplementedException ("Opcode '" + op + "' not supported by the regex->IL compiler.");
			    }

				if (one_op)
					break;
			}

			End:

			out_pc = pc;

			return m;
		}
	}
#else
	class CILCompiler : RxCompiler {
	}
#endif

}



			public static GenerationResult SUB( GenerationContext context, int pass, int address, uint code, byte fmt, byte fs, byte ft, byte fd, byte function )
			{
				if( pass == 0 )
				{
				}
				else if( pass == 1 )
				{
					EmitLoadRegisters( context, fs, ft, fmt );
					context.ILGen.Emit( OpCodes.Sub );
					EmitStoreRegister( context, fd, fmt );
				}
				return GenerationResult.Success;
			}

			public static GenerationResult DIV( GenerationContext context, int pass, int address, uint code, byte fmt, byte fs, byte ft, byte fd, byte function )
			{
				if( pass == 0 )
				{
				}
				else if( pass == 1 )
				{
					EmitLoadRegisters( context, fs, ft, fmt );
					context.ILGen.Emit( OpCodes.Div );
					EmitStoreRegister( context, fd, fmt );
				}
				return GenerationResult.Success;
			}

			public static GenerationResult SQRT( GenerationContext context, int pass, int address, uint code, byte fmt, byte fs, byte ft, byte fd, byte function )
			{
				if( pass == 0 )
				{
				}
				else if( pass == 1 )
				{
					EmitLoadRegister( context, fs, fmt );
					context.ILGen.Emit( OpCodes.Call, typeof( Math ).GetMethod( "Sqrt" ) );
					EmitStoreRegister( context, fd, fmt );
				}
				return GenerationResult.Success;
			}

			public static GenerationResult ABS( GenerationContext context, int pass, int address, uint code, byte fmt, byte fs, byte ft, byte fd, byte function )
			{
				if( pass == 0 )
				{
				}
				else if( pass == 1 )
				{
					EmitLoadRegister( context, fs, fmt );
					context.ILGen.Emit( OpCodes.Call, typeof( Math ).GetMethod( "Abs" ) );
					EmitStoreRegister( context, fd, fmt );
				}
				return GenerationResult.Success;
			}

			public static GenerationResult NEG( GenerationContext context, int pass, int address, uint code, byte fmt, byte fs, byte ft, byte fd, byte function )
			{
				if( pass == 0 )
				{
				}
				else if( pass == 1 )
				{
					EmitLoadRegister( context, fs, fmt );
					context.ILGen.Emit( OpCodes.Neg );
					EmitStoreRegister( context, fd, fmt );
				}
				return GenerationResult.Success;
			}

        public static LocalBuilder Increment(this ILGenerator ilg, LocalBuilder variable, int step = 1)
        {
            ilg.Emit(OpCodes.Ldloc, variable);
            Load32BitIntegerConstant(ilg, step);
            ilg.Emit(OpCodes.Add);
            ilg.Emit(OpCodes.Stloc, variable);
            return variable;
        }

        public static LocalBuilder Decrement(this ILGenerator ilg, LocalBuilder variable, int step = 1)
        {
            ilg.Emit(OpCodes.Ldloc, variable);
            Load32BitIntegerConstant(ilg, step);
            ilg.Emit(OpCodes.Sub);
            ilg.Emit(OpCodes.Stloc, variable);
            return variable;
        }

        public static LocalBuilder DeclareIntegerVariable(this ILGenerator ilg, int value = 0)
        {
            LocalBuilder intVariable = ilg.DeclareLocal(typeof(int));
            Load32BitIntegerConstant(ilg, value);
            ilg.Emit(OpCodes.Stloc, intVariable);

            return intVariable;
        }

        public static LocalBuilder ReassignIntegerVariable(this ILGenerator ilg, LocalBuilder variable, int value = 0)
        {
            Load32BitIntegerConstant(ilg, value);
            ilg.Emit(OpCodes.Stloc, variable);

            return variable;
        }

        public static LocalBuilder CreateArray<T>(this ILGenerator ilg, int size, string name = "")
        {
            LocalBuilder array = ilg.DeclareLocal(typeof(T[]));
            array.SetLocalSymInfo(name);
            Load32BitIntegerConstant(ilg, size);
            ilg.Emit(OpCodes.Newarr, typeof(T));
            ilg.Emit(OpCodes.Stloc, array);
            return array;
        }

        public static void Load32BitIntegerConstant(ILGenerator ilg, int constant)
        {
            if (IntegerConstants32bit.ContainsKey(constant))
            {
                ilg.Emit(IntegerConstants32bit[constant]);
                return;
            }

            ilg.Emit(OpCodes.Ldc_I4, constant);
        }


			public override bool ContainsEmitWithAwait ()
			{
				throw new NotSupportedException ();
			}

			public override Expression CreateExpressionTree (ResolveContext ec)
			{
				throw new NotSupportedException ("ET");
			}

			protected override Expression DoResolve (ResolveContext ec)
			{
				return null;
			}

			protected override void CloneTo (CloneContext clonectx, Expression t)
			{
			}

			public override void Emit (EmitContext ec)
			{
			}

			public override object Accept (StructuralVisitor visitor)
			{
				return visitor.Visit (this);
			}

        //public static T Clone<T>(this T entityObject) where T : EntityObject, new()
        //{
        //    return EntityCloner<T>.Clone(entityObject);
        //}

        //public static T CloneWithGraph<T>(this T entityObject) where T : EntityObject, new()
        //{
        //    return EntityCloner<T>.CloneWithGraph(entityObject);
        //}

        public static T Clone<T>(this T source) where T : AppFramework.Entities.IDataEntity, new()
        {
            DataContractSerializer dcs = new DataContractSerializer(typeof(T));
            using (MemoryStream ms = new MemoryStream())
            {
                dcs.WriteObject(ms, source);
                ms.Position = 0;
                return (T)dcs.ReadObject(ms);
            }
        }

        private static bool AllowClonePropertyStep1(PropertyInfo pi)
        {

            return !(typeof(EntityObject).IsAssignableFrom(pi.PropertyType) ||

                pi.PropertyType.IsGenericType && pi.PropertyType.GetGenericTypeDefinition() == typeof(EntityCollection<>));

        }



        private static DynamicMethod GenerateCloneMethod(Func<PropertyInfo, bool> step1, Func<PropertyInfo, bool> step2)
        {

            var dynamicMethod = new DynamicMethod("Clone", typeof(T), new Type[] { typeof(T), typeof(List<EntityObject>), typeof(Func<EntityObject, List<EntityObject>, EntityObject>) });

            var cloneIlGenerator = dynamicMethod.GetILGenerator();

            cloneIlGenerator.Emit(OpCodes.Ldarg_0);

            var argNotNullLabel = cloneIlGenerator.DefineLabel();

            cloneIlGenerator.Emit(OpCodes.Brtrue_S, argNotNullLabel);

            cloneIlGenerator.Emit(OpCodes.Ldnull);

            cloneIlGenerator.Emit(OpCodes.Ret);

            cloneIlGenerator.MarkLabel(argNotNullLabel);

            CopyObject(step1, step2, cloneIlGenerator, typeof(T), () => cloneIlGenerator.Emit(OpCodes.Ldarg_0), () => cloneIlGenerator.Emit(OpCodes.Ldarg_1), () => cloneIlGenerator.Emit(OpCodes.Ldarg_2));

            cloneIlGenerator.Emit(OpCodes.Ret);

            return dynamicMethod;

        }



        private static void CopyObject(Func<PropertyInfo, bool> step1, Func<PropertyInfo, bool> step2, ILGenerator cloneIlGenerator, Type typeT, Action getSource, Action getEntitiesList, Action getCloneLinkedEntities)
        {

            EntityAlreadyCloned(cloneIlGenerator, getEntitiesList, getSource);

            cloneIlGenerator.Emit(OpCodes.Castclass, typeT);

            var value = cloneIlGenerator.DeclareLocal(typeT);

            cloneIlGenerator.Emit(OpCodes.Stloc_S, value);

            cloneIlGenerator.Emit(OpCodes.Ldloc_S, value);

            var endExistingConditionMethodLabel = cloneIlGenerator.DefineLabel();

            cloneIlGenerator.Emit(OpCodes.Brtrue, endExistingConditionMethodLabel);

            cloneIlGenerator.Emit(OpCodes.Newobj, typeT.GetConstructor(new Type[0]));

            cloneIlGenerator.Emit(OpCodes.Stloc_S, value);

            CopyProps(step1, step2, cloneIlGenerator, value, typeT, getSource, getEntitiesList, getCloneLinkedEntities);

            cloneIlGenerator.MarkLabel(endExistingConditionMethodLabel);

            cloneIlGenerator.Emit(OpCodes.Ldloc, value);

        }



        private static void CopyProps(Func<PropertyInfo, bool> step1, Func<PropertyInfo, bool> step2, ILGenerator cloneIlGenerator, LocalBuilder value, Type typeT, Action getSource, Action getEntitiesList, Action getCloneLinkedEntities)
        {

            foreach (var prop in typeT.GetProperties().Where(p => p.CanRead && p.CanWrite && step1 != null && step1(p)))

                ClonePerStep(step1, step2, cloneIlGenerator, value, typeT, getSource, getEntitiesList, getCloneLinkedEntities, prop);

            getEntitiesList();

            cloneIlGenerator.Emit(OpCodes.Ldloc, value);

            cloneIlGenerator.Emit(OpCodes.Callvirt, typeof(List<EntityObject>).GetMethod("Add"));

            foreach (var prop in typeT.GetProperties().Where(p => p.CanRead && p.CanWrite && step2 != null && step2(p)))

                ClonePerStep(step1, step2, cloneIlGenerator, value, typeT, getSource, getEntitiesList, getCloneLinkedEntities, prop);

        }



        private static void ClonePerStep(Func<PropertyInfo, bool> step1, Func<PropertyInfo, bool> step2, ILGenerator cloneIlGenerator, LocalBuilder value, Type typeT, Action getSource, Action getEntitiesList, Action getCloneLinkedEntities, PropertyInfo prop)
        {

            if (typeof(ComplexObject).IsAssignableFrom(prop.PropertyType))
            {

                ConstructorInfo complexObjectCtor = prop.PropertyType.GetConstructor(new Type[0]);

                if (complexObjectCtor != null)
                {

                    cloneIlGenerator.Emit(OpCodes.Ldloc, value);

                    var sourceComplexTypeProp = cloneIlGenerator.DeclareLocal(prop.PropertyType);

                    var valueComplexTypeProp = cloneIlGenerator.DeclareLocal(prop.PropertyType);

                    getSource();

                    cloneIlGenerator.Emit(OpCodes.Callvirt, typeT.GetMethod("get_" + prop.Name));

                    cloneIlGenerator.Emit(OpCodes.Stloc_S, sourceComplexTypeProp);

                    cloneIlGenerator.Emit(OpCodes.Newobj, complexObjectCtor);

                    cloneIlGenerator.Emit(OpCodes.Stloc_S, valueComplexTypeProp);

                    cloneIlGenerator.Emit(OpCodes.Ldloc_S, valueComplexTypeProp);

                    cloneIlGenerator.Emit(OpCodes.Callvirt, typeT.GetMethod("set_" + prop.Name));

                    CopyProps(step1, step2, cloneIlGenerator, valueComplexTypeProp, prop.PropertyType, () => cloneIlGenerator.Emit(OpCodes.Ldloc, sourceComplexTypeProp), getEntitiesList, getCloneLinkedEntities);

                }

            }

            else if (prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(EntityReference<>))

                CopyEntityReference(cloneIlGenerator, () => cloneIlGenerator.Emit(OpCodes.Ldloc, value), typeT, getSource, prop, false);

            else if (typeof(EntityObject).IsAssignableFrom(prop.PropertyType))
            {

                if (prop.PropertyType.GetConstructor(new Type[0]) != null)
                {

                    var entityObjectProp = cloneIlGenerator.DeclareLocal(prop.PropertyType);

                    getSource();

                    cloneIlGenerator.Emit(OpCodes.Callvirt, typeT.GetMethod("get_" + prop.Name));

                    cloneIlGenerator.Emit(OpCodes.Stloc_S, entityObjectProp);

                    cloneIlGenerator.Emit(OpCodes.Ldloc_S, entityObjectProp);

                    var entityObjectNullLabel = cloneIlGenerator.DefineLabel();

                    cloneIlGenerator.Emit(OpCodes.Brfalse_S, entityObjectNullLabel);

                    cloneIlGenerator.Emit(OpCodes.Ldloc, value);

                    getCloneLinkedEntities();

                    cloneIlGenerator.Emit(OpCodes.Ldloc_S, entityObjectProp);

                    getEntitiesList();

                    cloneIlGenerator.Emit(OpCodes.Callvirt, typeof(Func<EntityObject, List<EntityObject>, EntityObject>).GetMethod("Invoke"));

                    cloneIlGenerator.Emit(OpCodes.Castclass, prop.PropertyType);

                    cloneIlGenerator.Emit(OpCodes.Callvirt, typeT.GetMethod("set_" + prop.Name));

                    cloneIlGenerator.MarkLabel(entityObjectNullLabel);

                }

            }

            else if (prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(EntityCollection<>))
            {

                var entityCollectionSourceProp = cloneIlGenerator.DeclareLocal(prop.PropertyType);

                getSource();

                cloneIlGenerator.Emit(OpCodes.Callvirt, typeT.GetMethod("get_" + prop.Name));

                cloneIlGenerator.Emit(OpCodes.Stloc_S, entityCollectionSourceProp);

                cloneIlGenerator.Emit(OpCodes.Ldloc_S, entityCollectionSourceProp);

                var entityCollectionNullLabel = cloneIlGenerator.DefineLabel();

                cloneIlGenerator.Emit(OpCodes.Brfalse_S, entityCollectionNullLabel);

                cloneIlGenerator.Emit(OpCodes.Ldloc, value);

                var entityCollectionValueProp = cloneIlGenerator.DeclareLocal(prop.PropertyType);

                cloneIlGenerator.Emit(OpCodes.Newobj, prop.PropertyType.GetConstructor(new Type[0]));

                Type subEntityType = prop.PropertyType.GetGenericArguments()[0];

                if (subEntityType.GetConstructor(new Type[0]) != null)
                {

                    cloneIlGenerator.Emit(OpCodes.Stloc_S, entityCollectionValueProp);

                    var entityCollectionSourceEnumerator = cloneIlGenerator.DeclareLocal(typeof(IEnumerator<>).MakeGenericType(subEntityType));

                    cloneIlGenerator.Emit(OpCodes.Ldloc_S, entityCollectionSourceProp);

                    cloneIlGenerator.Emit(OpCodes.Callvirt, prop.PropertyType.GetMethod("GetEnumerator"));

                    cloneIlGenerator.Emit(OpCodes.Stloc_S, entityCollectionSourceEnumerator);

                    var startAddEntityCollectionLabel = cloneIlGenerator.DefineLabel();

                    var endAddEntityCollectionLabel = cloneIlGenerator.DefineLabel();

                    cloneIlGenerator.MarkLabel(startAddEntityCollectionLabel);

                    cloneIlGenerator.Emit(OpCodes.Ldloc_S, entityCollectionSourceEnumerator);

                    cloneIlGenerator.Emit(OpCodes.Callvirt, typeof(IEnumerator).GetMethod("MoveNext"));

                    cloneIlGenerator.Emit(OpCodes.Brfalse_S, endAddEntityCollectionLabel);

                    var subEntityObject = cloneIlGenerator.DeclareLocal(subEntityType);

                    cloneIlGenerator.Emit(OpCodes.Ldloc_S, entityCollectionSourceEnumerator);

                    cloneIlGenerator.Emit(OpCodes.Callvirt, typeof(IEnumerator<>).MakeGenericType(subEntityType).GetMethod("get_Current"));

                    cloneIlGenerator.Emit(OpCodes.Stloc_S, subEntityObject);

                    cloneIlGenerator.Emit(OpCodes.Ldloc_S, entityCollectionValueProp);

                    getCloneLinkedEntities();

                    cloneIlGenerator.Emit(OpCodes.Ldloc_S, subEntityObject);

                    getEntitiesList();

                    cloneIlGenerator.Emit(OpCodes.Callvirt, typeof(Func<EntityObject, List<EntityObject>, EntityObject>).GetMethod("Invoke"));

                    cloneIlGenerator.Emit(OpCodes.Castclass, subEntityType);

                    cloneIlGenerator.Emit(OpCodes.Callvirt, prop.PropertyType.GetMethod("Add", new Type[] { subEntityType }));

                    cloneIlGenerator.Emit(OpCodes.Br_S, startAddEntityCollectionLabel);

                    cloneIlGenerator.MarkLabel(endAddEntityCollectionLabel);

                    cloneIlGenerator.Emit(OpCodes.Ldloc_S, entityCollectionValueProp);

                }

                cloneIlGenerator.Emit(OpCodes.Callvirt, typeT.GetMethod("set_" + prop.Name));

                cloneIlGenerator.MarkLabel(entityCollectionNullLabel);

            }

            else
            {

                cloneIlGenerator.Emit(OpCodes.Ldloc, value);

                getSource();

                cloneIlGenerator.Emit(OpCodes.Callvirt, typeT.GetMethod("get_" + prop.Name));

                cloneIlGenerator.Emit(OpCodes.Callvirt, typeT.GetMethod("set_" + prop.Name));

            }

        }

        LuaTable __luaInterface_getLuaTable();
        public object extractGenerated(IntPtr luaState,int stackPos)
        {
            return CodeGeneration.Instance.GetDelegate(delegateType,translator.getFunction(luaState,stackPos));
        }
        public object extractGenerated(IntPtr luaState,int stackPos)
        {
            return CodeGeneration.Instance.GetClassInstance(klass,translator.getTable(luaState,stackPos));
        }

        /*
         *  Generates an event handler that calls a Lua function
         */
        private Type GenerateEvent(Type eventHandlerType)
        {
            string typeName;
            lock(this)
            {
                typeName = "LuaGeneratedClass" + luaClassNumber;
                luaClassNumber++;
            }
            // Define a public class in the assembly, called typeName
            TypeBuilder myType=newModule.DefineType(typeName,TypeAttributes.Public,eventHandlerParent);

            // Defines the handler method. Its signature is void(object,<subclassofEventArgs>)
            Type[] paramTypes = new Type[2];
            paramTypes[0]=typeof(object);
            paramTypes[1]=eventHandlerType;
            Type returnType=typeof(void);
            MethodBuilder handleMethod=myType.DefineMethod("HandleEvent",
                MethodAttributes.Public|MethodAttributes.HideBySig,
                returnType,paramTypes);

            // Emits the IL for the method. It loads the arguments
            // and calls the handleEvent method of the base class
            ILGenerator generator=handleMethod.GetILGenerator( );
            generator.Emit(OpCodes.Ldarg_0);
            generator.Emit(OpCodes.Ldarg_1);
            generator.Emit(OpCodes.Ldarg_2);
            MethodInfo miGenericEventHandler;
            miGenericEventHandler=eventHandlerParent.GetMethod("handleEvent");
            generator.Emit(OpCodes.Call,miGenericEventHandler);
            // returns
            generator.Emit(OpCodes.Ret);

            // creates the new type
            return myType.CreateType();
        }

        /*
         * Generates a type that can be used for instantiating a delegate
         * of the provided type, given a Lua function.
         */
        private Type GenerateDelegate(Type delegateType)
        {
            string typeName;
            lock(this)
            {
                typeName = "LuaGeneratedClass" + luaClassNumber;
                luaClassNumber++;
            }
            // Define a public class in the assembly, called typeName
            TypeBuilder myType=newModule.DefineType(typeName,TypeAttributes.Public,delegateParent);

            // Defines the delegate method with the same signature as the
            // Invoke method of delegateType
            MethodInfo invokeMethod=delegateType.GetMethod("Invoke");
            ParameterInfo[] paramInfo=invokeMethod.GetParameters();
            Type[] paramTypes=new Type[paramInfo.Length];
            Type returnType=invokeMethod.ReturnType;

            // Counts out and ref params, for use later
            int nOutParams=0; int nOutAndRefParams=0;
            for(int i=0;i<paramTypes.Length;i++)
            {
                paramTypes[i]=paramInfo[i].ParameterType;
                if((!paramInfo[i].IsIn) && paramInfo[i].IsOut)
                    nOutParams++;
                if(paramTypes[i].IsByRef)
                    nOutAndRefParams++;
            }
            int[] refArgs=new int[nOutAndRefParams];

            MethodBuilder delegateMethod=myType.DefineMethod("CallFunction",
                invokeMethod.Attributes,
                returnType,paramTypes);

            // Generates the IL for the method
            ILGenerator generator=delegateMethod.GetILGenerator( );

            generator.DeclareLocal(typeof(object[])); // original arguments
            generator.DeclareLocal(typeof(object[])); // with out-only arguments removed
            generator.DeclareLocal(typeof(int[])); // indexes of out and ref arguments
            if(!(returnType == typeof(void)))  // return value
                generator.DeclareLocal(returnType);
            else
                generator.DeclareLocal(typeof(object));
            // Initializes local variables
            generator.Emit(OpCodes.Ldc_I4,paramTypes.Length);
            generator.Emit(OpCodes.Newarr,typeof(object));
            generator.Emit(OpCodes.Stloc_0);
            generator.Emit(OpCodes.Ldc_I4,paramTypes.Length-nOutParams);
            generator.Emit(OpCodes.Newarr,typeof(object));
            generator.Emit(OpCodes.Stloc_1);
            generator.Emit(OpCodes.Ldc_I4,nOutAndRefParams);
            generator.Emit(OpCodes.Newarr,typeof(int));
            generator.Emit(OpCodes.Stloc_2);
            // Stores the arguments in the local variables
            for(int iArgs=0,iInArgs=0,iOutArgs=0;iArgs<paramTypes.Length;iArgs++)
            {
                generator.Emit(OpCodes.Ldloc_0);
                generator.Emit(OpCodes.Ldc_I4,iArgs);
                generator.Emit(OpCodes.Ldarg,iArgs+1);
                if(paramTypes[iArgs].IsByRef)
                {
                    if(paramTypes[iArgs].GetElementType().IsValueType)
                    {
                        generator.Emit(OpCodes.Ldobj,paramTypes[iArgs].GetElementType());
                        generator.Emit(OpCodes.Box,paramTypes[iArgs].GetElementType());
                    } else generator.Emit(OpCodes.Ldind_Ref);
                }
                else
                {
                    if(paramTypes[iArgs].IsValueType)
                        generator.Emit(OpCodes.Box,paramTypes[iArgs]);
                }
                generator.Emit(OpCodes.Stelem_Ref);
                if(paramTypes[iArgs].IsByRef)
                {
                    generator.Emit(OpCodes.Ldloc_2);
                    generator.Emit(OpCodes.Ldc_I4,iOutArgs);
                    generator.Emit(OpCodes.Ldc_I4,iArgs);
                    generator.Emit(OpCodes.Stelem_I4);
                    refArgs[iOutArgs]=iArgs;
                    iOutArgs++;
                }
                if(paramInfo[iArgs].IsIn || (!paramInfo[iArgs].IsOut))
                {
                    generator.Emit(OpCodes.Ldloc_1);
                    generator.Emit(OpCodes.Ldc_I4,iInArgs);
                    generator.Emit(OpCodes.Ldarg,iArgs+1);
                    if(paramTypes[iArgs].IsByRef)
                    {
                        if(paramTypes[iArgs].GetElementType().IsValueType)
                        {
                            generator.Emit(OpCodes.Ldobj,paramTypes[iArgs].GetElementType());
                            generator.Emit(OpCodes.Box,paramTypes[iArgs].GetElementType());
                        }
                        else generator.Emit(OpCodes.Ldind_Ref);
                    }
                    else
                    {
                        if(paramTypes[iArgs].IsValueType)
                            generator.Emit(OpCodes.Box,paramTypes[iArgs]);
                    }
                    generator.Emit(OpCodes.Stelem_Ref);
                    iInArgs++;
                }
            }
            // Calls the callFunction method of the base class
            generator.Emit(OpCodes.Ldarg_0);
            generator.Emit(OpCodes.Ldloc_0);
            generator.Emit(OpCodes.Ldloc_1);
            generator.Emit(OpCodes.Ldloc_2);
            MethodInfo miGenericEventHandler;
            miGenericEventHandler=delegateParent.GetMethod("callFunction");
            generator.Emit(OpCodes.Call,miGenericEventHandler);
            // Stores return value
            if(returnType == typeof(void))
            {
                generator.Emit(OpCodes.Pop);
                generator.Emit(OpCodes.Ldnull);
            }
            else if(returnType.IsValueType)
            {
                generator.Emit(OpCodes.Unbox,returnType);
                generator.Emit(OpCodes.Ldobj,returnType);
            } else generator.Emit(OpCodes.Castclass,returnType);
            generator.Emit(OpCodes.Stloc_3);
            // Stores new value of out and ref params
            for(int i=0;i<refArgs.Length;i++)
            {
                generator.Emit(OpCodes.Ldarg,refArgs[i]+1);
                generator.Emit(OpCodes.Ldloc_0);
                generator.Emit(OpCodes.Ldc_I4,refArgs[i]);
                generator.Emit(OpCodes.Ldelem_Ref);
                if(paramTypes[refArgs[i]].GetElementType().IsValueType)
                {
                    generator.Emit(OpCodes.Unbox,paramTypes[refArgs[i]].GetElementType());
                    generator.Emit(OpCodes.Ldobj,paramTypes[refArgs[i]].GetElementType());
                    generator.Emit(OpCodes.Stobj,paramTypes[refArgs[i]].GetElementType());
                }
                else
                {
                    generator.Emit(OpCodes.Castclass,paramTypes[refArgs[i]].GetElementType());
                    generator.Emit(OpCodes.Stind_Ref);
                }
            }
            // Returns
            if(!(returnType == typeof(void)))
                generator.Emit(OpCodes.Ldloc_3);
            generator.Emit(OpCodes.Ret);

            // creates the new type
            return myType.CreateType();
        }

        /*
         * Generates an implementation of klass, if it is an interface, or
         * a subclass of klass that delegates its virtual methods to a Lua table.
         */
        public void GenerateClass(Type klass,out Type newType,out Type[][] returnTypes, LuaTable luaTable)
        {
            string typeName;
            lock(this)
            {
                typeName = "LuaGeneratedClass" + luaClassNumber;
                luaClassNumber++;
            }
            TypeBuilder myType;
            // Define a public class in the assembly, called typeName
            if(klass.IsInterface)
                myType=newModule.DefineType(typeName,TypeAttributes.Public,typeof(object),new Type[] { klass,typeof(ILuaGeneratedType) });
            else
                myType=newModule.DefineType(typeName,TypeAttributes.Public,klass,new Type[] { typeof(ILuaGeneratedType) });
            // Field that stores the Lua table
            FieldBuilder luaTableField=myType.DefineField("__luaInterface_luaTable",typeof(LuaTable),FieldAttributes.Public);
            // Field that stores the return types array
            FieldBuilder returnTypesField=myType.DefineField("__luaInterface_returnTypes",typeof(Type[][]),FieldAttributes.Public);
            // Generates the constructor for the new type, it takes a Lua table and an array
            // of return types and stores them in the respective fields
            ConstructorBuilder constructor=
                myType.DefineConstructor(MethodAttributes.Public,CallingConventions.Standard,new Type[] { typeof(LuaTable),typeof(Type[][]) });
            ILGenerator generator=constructor.GetILGenerator();
            generator.Emit(OpCodes.Ldarg_0);
            if(klass.IsInterface)
                generator.Emit(OpCodes.Call,typeof(object).GetConstructor(Type.EmptyTypes));
            else
                generator.Emit(OpCodes.Call,klass.GetConstructor(Type.EmptyTypes));
            generator.Emit(OpCodes.Ldarg_0);
            generator.Emit(OpCodes.Ldarg_1);
            generator.Emit(OpCodes.Stfld,luaTableField);
            generator.Emit(OpCodes.Ldarg_0);
            generator.Emit(OpCodes.Ldarg_2);
            generator.Emit(OpCodes.Stfld,returnTypesField);
            generator.Emit(OpCodes.Ret);
            // Generates overriden versions of the klass' public and protected virtual methods that have been explicitly specfied
            BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
            MethodInfo[] classMethods=klass.GetMethods(flags);
            returnTypes=new Type[classMethods.Length][];
            int i=0;
            foreach(MethodInfo method in classMethods)
            {
                if(klass.IsInterface)
                {
                    GenerateMethod(myType,method,
                        MethodAttributes.HideBySig|MethodAttributes.Virtual|MethodAttributes.NewSlot,
                        i,luaTableField,returnTypesField,false,out returnTypes[i]);
                    i++;
                }
                else
                {
                    if(!method.IsPrivate && !method.IsFinal && method.IsVirtual)
                    {
                        if (luaTable[method.Name] != null) {
                            GenerateMethod(myType,method,(method.Attributes|MethodAttributes.NewSlot)^MethodAttributes.NewSlot,i,
                                luaTableField,returnTypesField,true,out returnTypes[i]);
                            i++;
                        }
                    }
                }
            }
            // Generates an implementation of the __luaInterface_getLuaTable method
            MethodBuilder returnTableMethod=myType.DefineMethod("__luaInterface_getLuaTable",
                MethodAttributes.Public|MethodAttributes.HideBySig|MethodAttributes.Virtual,
                typeof(LuaTable),new Type[0]);
            myType.DefineMethodOverride(returnTableMethod,typeof(ILuaGeneratedType).GetMethod("__luaInterface_getLuaTable"));
            generator=returnTableMethod.GetILGenerator();
            generator.Emit(OpCodes.Ldarg_0);
            generator.Emit(OpCodes.Ldfld,luaTableField);
            generator.Emit(OpCodes.Ret);
            // Creates the type
            newType=myType.CreateType();
        }


        #region [   PROPERTY GET SET   ]
        internal string GetTypeAssemblyName(Type t)
        {
            string val = "";
            if (_tyname.TryGetValue(t, out val))
                return val;
            else
            {
                string s = t.AssemblyQualifiedName;
                _tyname.Add(t, s);
                return s;
            }
        }

        internal Type GetTypeFromCache(string typename)
        {
            Type val = null;
            if (_typecache.TryGetValue(typename, out val))
                return val;
            else
            {
                Type t = LoadType(typename);
                _typecache.Add(typename, t);
                return t;
            }
        }

        internal object FastCreateInstance(Type objtype)
        {
            try
            {
                CreateObject c = null;
                if (_constrcache.TryGetValue(objtype, out c))
                {
                    return c();
                }
                else
                {
                    if (objtype.IsClass)
                    {
                        DynamicMethod dynMethod = new DynamicMethod("_", objtype, null);
                        ILGenerator ilGen = dynMethod.GetILGenerator();
                        ilGen.Emit(OpCodes.Newobj, objtype.GetConstructor(Type.EmptyTypes));
                        ilGen.Emit(OpCodes.Ret);
                        c = (CreateObject)dynMethod.CreateDelegate(typeof(CreateObject));
                        _constrcache.Add(objtype, c);
                    }
                    else // structs
                    {
                        DynamicMethod dynMethod = new DynamicMethod("_", typeof(object), null);
                        ILGenerator ilGen = dynMethod.GetILGenerator();
                        var lv = ilGen.DeclareLocal(objtype);
                        ilGen.Emit(OpCodes.Ldloca_S, lv);
                        ilGen.Emit(OpCodes.Initobj, objtype);
                        ilGen.Emit(OpCodes.Ldloc_0);
                        ilGen.Emit(OpCodes.Box, objtype);
                        ilGen.Emit(OpCodes.Ret);
                        c = (CreateObject)dynMethod.CreateDelegate(typeof(CreateObject));
                        _constrcache.Add(objtype, c);
                    }
                    return c();
                }
            }
            catch (Exception exc)
            {
                throw new Exception(string.Format("Failed to fast create instance for type '{0}' from assemebly '{1}'",
                    objtype.FullName, objtype.AssemblyQualifiedName), exc);
            }
        }

        internal static GenericSetter CreateSetField(Type type, FieldInfo fieldInfo)
        {
            Type[] arguments = new Type[2];
            arguments[0] = arguments[1] = typeof(object);

            DynamicMethod dynamicSet = new DynamicMethod("_", typeof(object), arguments, type);

            ILGenerator il = dynamicSet.GetILGenerator();

            if (!type.IsClass) // structs
            {
                var lv = il.DeclareLocal(type);
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Unbox_Any, type);
                il.Emit(OpCodes.Stloc_0);
                il.Emit(OpCodes.Ldloca_S, lv);
                il.Emit(OpCodes.Ldarg_1);
                if (fieldInfo.FieldType.IsClass)
                    il.Emit(OpCodes.Castclass, fieldInfo.FieldType);
                else
                    il.Emit(OpCodes.Unbox_Any, fieldInfo.FieldType);
                il.Emit(OpCodes.Stfld, fieldInfo);
                il.Emit(OpCodes.Ldloc_0);
                il.Emit(OpCodes.Box, type);
                il.Emit(OpCodes.Ret);
            }
            else
            {
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldarg_1);
                if (fieldInfo.FieldType.IsValueType)
                    il.Emit(OpCodes.Unbox_Any, fieldInfo.FieldType);
                il.Emit(OpCodes.Stfld, fieldInfo);
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ret);
            }
            return (GenericSetter)dynamicSet.CreateDelegate(typeof(GenericSetter));
        }

        internal static GenericSetter CreateSetMethod(Type type, PropertyInfo propertyInfo)
        {
            MethodInfo setMethod = propertyInfo.GetSetMethod();
            if (setMethod == null)
                return null;

            Type[] arguments = new Type[2];
            arguments[0] = arguments[1] = typeof(object);

            DynamicMethod setter = new DynamicMethod("_", typeof(object), arguments);
            ILGenerator il = setter.GetILGenerator();

            if (!type.IsClass) // structs
            {
                var lv = il.DeclareLocal(type);
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Unbox_Any, type);
                il.Emit(OpCodes.Stloc_0);
                il.Emit(OpCodes.Ldloca_S, lv);
                il.Emit(OpCodes.Ldarg_1);
                if (propertyInfo.PropertyType.IsClass)
                    il.Emit(OpCodes.Castclass, propertyInfo.PropertyType);
                else
                    il.Emit(OpCodes.Unbox_Any, propertyInfo.PropertyType);
                il.EmitCall(OpCodes.Call, setMethod, null);
                il.Emit(OpCodes.Ldloc_0);
                il.Emit(OpCodes.Box, type);
            }
            else
            {
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Castclass, propertyInfo.DeclaringType);
                il.Emit(OpCodes.Ldarg_1);
                if (propertyInfo.PropertyType.IsClass)
                    il.Emit(OpCodes.Castclass, propertyInfo.PropertyType);
                else
                    il.Emit(OpCodes.Unbox_Any, propertyInfo.PropertyType);
                il.EmitCall(OpCodes.Callvirt, setMethod, null);
                il.Emit(OpCodes.Ldarg_0);
            }

            il.Emit(OpCodes.Ret);

            return (GenericSetter)setter.CreateDelegate(typeof(GenericSetter));
        }

        internal static GenericGetter CreateGetField(Type type, FieldInfo fieldInfo)
        {
            DynamicMethod dynamicGet = new DynamicMethod("_", typeof(object), new Type[] { typeof(object) }, type);

            ILGenerator il = dynamicGet.GetILGenerator();

            if (!type.IsClass) // structs
            {
                var lv = il.DeclareLocal(type);
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Unbox_Any, type);
                il.Emit(OpCodes.Stloc_0);
                il.Emit(OpCodes.Ldloca_S, lv);
                il.Emit(OpCodes.Ldfld, fieldInfo);
                if (fieldInfo.FieldType.IsValueType)
                    il.Emit(OpCodes.Box, fieldInfo.FieldType);
            }
            else
            {
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldfld, fieldInfo);
                if (fieldInfo.FieldType.IsValueType)
                    il.Emit(OpCodes.Box, fieldInfo.FieldType);
            }

            il.Emit(OpCodes.Ret);

            return (GenericGetter)dynamicGet.CreateDelegate(typeof(GenericGetter));
        }


    void InjectHelper()
    {
        var typeAttributes = TypeAttributes.AnsiClass | TypeAttributes.Sealed | TypeAttributes.Abstract | TypeAttributes.AutoClass;
        var targetType = new TypeDefinition(ModuleDefinition.Name + ".Resourcer", "ResourceHelper", typeAttributes, TypeSystem.ObjectReference);
        ModuleDefinition.Types.Add(targetType);
        var fieldDefinition = new FieldDefinition("assembly", FieldAttributes.Static | FieldAttributes.Private, AssemblyTypeReference)
        {
            DeclaringType = targetType
        };
        targetType.Fields.Add(fieldDefinition);
        InjectConstructor(targetType, fieldDefinition);

        InjectAsStream(targetType, fieldDefinition);
        InjectAsStreamReader(targetType, fieldDefinition);
        InjectAsString(targetType, fieldDefinition);
    }

    void InjectAsStream(TypeDefinition targetType, FieldDefinition fieldDefinition)
    {
        AsStreamMethod = new MethodDefinition("AsStream", staticMethodAttributes, StreamTypeReference);
        var pathParam = new ParameterDefinition(TypeSystem.StringReference);
        AsStreamMethod.Parameters.Add(pathParam);
        AsStreamMethod.Body.InitLocals = true;
        var inst = AsStreamMethod.Body.Instructions;
        inst.Add(Instruction.Create(OpCodes.Ldsfld, fieldDefinition));
        inst.Add(Instruction.Create(OpCodes.Ldarg, pathParam));
        inst.Add(Instruction.Create(OpCodes.Callvirt, GetManifestResourceStreamMethod));
        inst.Add(Instruction.Create(OpCodes.Ret));
        targetType.Methods.Add(AsStreamMethod);
    }

    void InjectAsStreamReader(TypeDefinition targetType, FieldDefinition fieldDefinition)
    {
        AsStreamReaderMethod = new MethodDefinition("AsStreamReader", staticMethodAttributes, StreamReaderTypeReference);
        var streamVariable = new VariableDefinition(StreamTypeReference);
        AsStreamReaderMethod.Body.Variables.Add(streamVariable);
        var pathParam = new ParameterDefinition(TypeSystem.StringReference);
        AsStreamReaderMethod.Parameters.Add(pathParam);
        AsStreamReaderMethod.Body.InitLocals = true;
        var inst = AsStreamReaderMethod.Body.Instructions;

        var skipReturn = Instruction.Create(OpCodes.Nop);

        inst.Add(Instruction.Create(OpCodes.Ldsfld, fieldDefinition));
        inst.Add(Instruction.Create(OpCodes.Ldarg, pathParam));
        inst.Add(Instruction.Create(OpCodes.Callvirt, GetManifestResourceStreamMethod));

        inst.Add(Instruction.Create(OpCodes.Stloc, streamVariable));
        inst.Add(Instruction.Create(OpCodes.Ldloc, streamVariable));
        inst.Add(Instruction.Create(OpCodes.Brtrue_S, skipReturn));

        inst.Add(Instruction.Create(OpCodes.Ldnull));
        inst.Add(Instruction.Create(OpCodes.Ret));
        inst.Add(skipReturn);

        inst.Add(Instruction.Create(OpCodes.Ldloc, streamVariable));
        inst.Add(Instruction.Create(OpCodes.Newobj, StreamReaderConstructorReference));
        inst.Add(Instruction.Create(OpCodes.Ret));
        targetType.Methods.Add(AsStreamReaderMethod);
    }

    void InjectAsString(TypeDefinition targetType, FieldDefinition assemblyField)
    {
        AsStringMethod = new MethodDefinition("AsString", staticMethodAttributes, TypeSystem.StringReference);
        var pathParam = new ParameterDefinition(TypeSystem.StringReference);
        AsStringMethod.Parameters.Add(pathParam);

        AsStringMethod.Body.InitLocals = true;
        var readerVar = new VariableDefinition(StreamReaderTypeReference);
        AsStringMethod.Body.Variables.Add(readerVar);
        var streamVar = new VariableDefinition(StreamTypeReference);
        AsStringMethod.Body.Variables.Add(streamVar);
        var stringVar = new VariableDefinition(TypeSystem.StringReference);
        AsStringMethod.Body.Variables.Add(stringVar);

        var inst = AsStringMethod.Body.Instructions;

        //24
        var assignStreamBeforeReaderConstr = Instruction.Create(OpCodes.Ldloc, streamVar);
        //47
        var assignStringBeforeReturn = Instruction.Create(OpCodes.Ldloc, stringVar);
        //3d
        var assignStreamBeforeDispose = Instruction.Create(OpCodes.Ldloc, streamVar);
        //46
        var endFinally = Instruction.Create(OpCodes.Endfinally);


        inst.Add(Instruction.Create(OpCodes.Ldnull));
        inst.Add(Instruction.Create(OpCodes.Stloc, readerVar));
        inst.Add(Instruction.Create(OpCodes.Ldnull));
        inst.Add(Instruction.Create(OpCodes.Stloc, streamVar));
        var assignAssemblyField = Instruction.Create(OpCodes.Ldsfld, assemblyField);
        inst.Add(assignAssemblyField);
        inst.Add(Instruction.Create(OpCodes.Ldarg, pathParam));
        inst.Add(Instruction.Create(OpCodes.Callvirt, GetManifestResourceStreamMethod));
        inst.Add(Instruction.Create(OpCodes.Stloc, streamVar));
        inst.Add(Instruction.Create(OpCodes.Ldloc, streamVar));
        inst.Add(Instruction.Create(OpCodes.Brtrue_S, assignStreamBeforeReaderConstr));
        inst.Add(Instruction.Create(OpCodes.Ldstr, "Could not find a resource named '"));
        inst.Add(Instruction.Create(OpCodes.Ldarg, pathParam));
        inst.Add(Instruction.Create(OpCodes.Ldstr, "'."));
        inst.Add(Instruction.Create(OpCodes.Call, ConcatReference));
        inst.Add(Instruction.Create(OpCodes.Newobj, ExceptionConstructorReference));
        inst.Add(Instruction.Create(OpCodes.Throw));

        inst.Add(assignStreamBeforeReaderConstr);
        inst.Add(Instruction.Create(OpCodes.Newobj, StreamReaderConstructorReference));
        inst.Add(Instruction.Create(OpCodes.Stloc, readerVar));
        inst.Add(Instruction.Create(OpCodes.Ldloc, readerVar));
        inst.Add(Instruction.Create(OpCodes.Callvirt, ReadToEndMethod));
        inst.Add(Instruction.Create(OpCodes.Stloc, stringVar));
        inst.Add(Instruction.Create(OpCodes.Leave_S, assignStringBeforeReturn));
        var assignReaderBeforeNullCheck = Instruction.Create(OpCodes.Ldloc, readerVar);
        inst.Add(assignReaderBeforeNullCheck);
        inst.Add(Instruction.Create(OpCodes.Brfalse_S, assignStreamBeforeDispose));
        inst.Add(Instruction.Create(OpCodes.Ldloc, readerVar));
        inst.Add(Instruction.Create(OpCodes.Callvirt, DisposeTextReaderMethod));
        inst.Add(assignStreamBeforeDispose);
        inst.Add(Instruction.Create(OpCodes.Brfalse_S, endFinally));
        inst.Add(Instruction.Create(OpCodes.Ldloc, streamVar));
        inst.Add(Instruction.Create(OpCodes.Callvirt, DisposeStreamMethod));
        inst.Add(endFinally);
        inst.Add(assignStringBeforeReturn);
        inst.Add(Instruction.Create(OpCodes.Ret));

        var finallyHandler = new ExceptionHandler(ExceptionHandlerType.Finally)
        {
            TryStart = assignAssemblyField,
            TryEnd = assignReaderBeforeNullCheck,
            HandlerStart = assignReaderBeforeNullCheck,
            HandlerEnd = assignStringBeforeReturn
        };
        AsStringMethod.Body.ExceptionHandlers.Add(finallyHandler);
        AsStringMethod.Body.SimplifyMacros();
        targetType.Methods.Add(AsStringMethod);
    }

    void InjectConstructor(TypeDefinition targetType, FieldDefinition fieldDefinition)
    {
        const MethodAttributes attributes = MethodAttributes.Static
                                            | MethodAttributes.SpecialName
                                            | MethodAttributes.RTSpecialName
                                            | MethodAttributes.HideBySig
                                            | MethodAttributes.Private;
        var staticConstructor = new MethodDefinition(".cctor", attributes, TypeSystem.VoidReference);
        targetType.Methods.Add(staticConstructor);
        var instructions = staticConstructor.Body.Instructions;
        instructions.Add(Instruction.Create(OpCodes.Ldtoken, targetType));
        instructions.Add(Instruction.Create(OpCodes.Call, GetTypeFromHandle));
        instructions.Add(Instruction.Create(OpCodes.Call, GetTypeInfo));
        instructions.Add(Instruction.Create(OpCodes.Callvirt, GetAssembly));
        instructions.Add(Instruction.Create(OpCodes.Stsfld, fieldDefinition));
        instructions.Add(Instruction.Create(OpCodes.Ret));
    }

Razorvine.Pickle.Opcodes : Object

Fields :

public static Byte MARK
public static Byte STOP
public static Byte POP
public static Byte POP_MARK
public static Byte DUP
public static Byte FLOAT
public static Byte INT
public static Byte BININT
public static Byte BININT1
public static Byte LONG
public static Byte BININT2
public static Byte NONE
public static Byte PERSID
public static Byte BINPERSID
public static Byte REDUCE
public static Byte STRING
public static Byte BINSTRING
public static Byte SHORT_BINSTRING
public static Byte UNICODE
public static Byte BINUNICODE
public static Byte APPEND
public static Byte BUILD
public static Byte GLOBAL
public static Byte DICT
public static Byte EMPTY_DICT
public static Byte APPENDS
public static Byte GET
public static Byte BINGET
public static Byte INST
public static Byte LONG_BINGET
public static Byte LIST
public static Byte EMPTY_LIST
public static Byte OBJ
public static Byte PUT
public static Byte BINPUT
public static Byte LONG_BINPUT
public static Byte SETITEM
public static Byte TUPLE
public static Byte EMPTY_TUPLE
public static Byte SETITEMS
public static Byte BINFLOAT
public static String TRUE
public static String FALSE
public static Byte PROTO
public static Byte NEWOBJ
public static Byte EXT1
public static Byte EXT2
public static Byte EXT4
public static Byte TUPLE1
public static Byte TUPLE2
public static Byte TUPLE3
public static Byte NEWTRUE
public static Byte NEWFALSE
public static Byte LONG1
public static Byte LONG4
public static Byte BINBYTES
public static Byte SHORT_BINBYTES
public static Byte SHORT_BINUNICODE
public static Byte BINUNICODE8
public static Byte BINBYTES8
public static Byte EMPTY_SET
public static Byte ADDITEMS
public static Byte FROZENSET
public static Byte MEMOIZE
public static Byte FRAME
public static Byte NEWOBJ_EX
public static Byte STACK_GLOBAL
public static Byte BYTEARRAY8
public static Byte NEXT_BUFFER
public static Byte READONLY_BUFFER

Methods :

public Type GetType()
public String ToString()
public Boolean Equals(Object obj = )
public Int32 GetHashCode()

Other methods