Author: zoltan
Date: 2008-02-13 09:30:06 -0500 (Wed, 13 Feb 2008)
New Revision: 95580
Modified:
trunk/mcs/class/System/System.Text.RegularExpressions/ChangeLog
trunk/mcs/class/System/System.Text.RegularExpressions/RxCompiler.cs
trunk/mcs/class/System/System.Text.RegularExpressions/RxInterpreter.cs
Log:
2008-02-13 Zoltan Varga <[EMAIL PROTECTED]>
* RxInterpreter.cs RxCompiler.cs: First version of regex IL compiler.
Modified: trunk/mcs/class/System/System.Text.RegularExpressions/ChangeLog
===================================================================
--- trunk/mcs/class/System/System.Text.RegularExpressions/ChangeLog
2008-02-13 14:29:49 UTC (rev 95579)
+++ trunk/mcs/class/System/System.Text.RegularExpressions/ChangeLog
2008-02-13 14:30:06 UTC (rev 95580)
@@ -1,4 +1,7 @@
+2008-02-13 Zoltan Varga <[EMAIL PROTECTED]>
+ * RxInterpreter.cs RxCompiler.cs: First version of regex IL compiler.
+
Wed Feb 13 13:18:12 CET 2008 Paolo Molaro <[EMAIL PROTECTED]>
* RxCompiler.cs, RxInterpreter.cs, RxOp.cs: unicode categories and
Modified: trunk/mcs/class/System/System.Text.RegularExpressions/RxCompiler.cs
===================================================================
--- trunk/mcs/class/System/System.Text.RegularExpressions/RxCompiler.cs
2008-02-13 14:29:49 UTC (rev 95579)
+++ trunk/mcs/class/System/System.Text.RegularExpressions/RxCompiler.cs
2008-02-13 14:30:06 UTC (rev 95580)
@@ -1,6 +1,8 @@
using System;
using System.Collections;
using System.Globalization;
+using System.Reflection;
+using System.Reflection.Emit;
namespace System.Text.RegularExpressions {
@@ -39,8 +41,8 @@
}
class RxCompiler : ICompiler {
- byte[] program = new byte [32];
- int curpos = 0;
+ protected byte[] program = new byte [32];
+ protected int curpos = 0;
public RxCompiler () {
}
@@ -109,7 +111,7 @@
Buffer.BlockCopy (program, 0, code, 0, curpos);
//Console.WriteLine ("Program size: {0}", curpos);
- return new RxInterpreterFactory (code);
+ return new RxInterpreterFactory (code, null);
}
public void EmitFalse ()
@@ -686,13 +688,507 @@
}
+ //
+ // 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: Emit one method with a switch instead of many methods
+ // FIXME: Avoid ref ptr, since it is bad for register allocation
+ //
+
+#if NET_2_0
+ class CILCompiler : RxCompiler, ICompiler {
+ DynamicMethod[] eval_methods;
+ bool[] eval_methods_defined;
+
+ 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 FieldInfo GetInterpreterField (string name) {
+ return typeof (RxInterpreter).GetField (name,
BindingFlags.Instance|BindingFlags.NonPublic);
+ }
+
+ private MethodInfo GetInterpreterMethod (string name) {
+ return typeof (RxInterpreter).GetMethod (name,
BindingFlags.Instance|BindingFlags.NonPublic);
+ }
+
+ private string GetString (ushort[] program, int pc) {
+ int len = program[pc + 1];
+ int str = pc + 2;
+
+ char[] cs = new char[len];
+ for (int i = 0; i < len; ++ i)
+ cs[i] = (char)program[str ++];
+
+ return new string (cs);
+ }
+
+ 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;
+ }
+
+ private MethodInfo GetEvalMethodWithFallback (byte[] program,
int pc, out bool fallback) {
+ DynamicMethod eval = GetEvalMethod (program, pc);
+ fallback = eval != null;
+ if (eval != null) {
+ fallback = false;
+ return eval;
+ } else {
+ fallback = true;
+ return GetInterpreterMethod ("EvalByteCode");
+ }
+ }
+
+ //
+ // Create a dynamic method which is the Interpreter.Eval method
specialized
+ // to the given program and a given pc.
+ // Keep this in synch with Interpreter.Eval ()
+ //
+ 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
+ */
+
+ int start, length, end;
+ bool fallback;
+
+ Label label_fail = ilgen.DefineLabel ();
+
+ while (true) {
+ RxOp op = (RxOp)program [pc];
+
+ switch (op) {
+ case RxOp.Anchor: {
+ length = program [pc + 3] | (program
[pc + 4] << 8);
+ pc += program [pc + 1] | (program [pc +
2] << 8);
+
+ // FIXME: Group support
+
+ // 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 (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;
+ * 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,
GetInterpreterField ("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,
GetInterpreterField ("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.Bne_Un, l3);
+
+ // match_start = strpos;
+ ilgen.Emit (OpCodes.Ldarg_0);
+ ilgen.Emit (OpCodes.Ldarg_1);
+ ilgen.Emit (OpCodes.Stfld,
GetInterpreterField ("match_start"));
+ // strpos_result = strpos +
1;
+ ilgen.Emit (OpCodes.Ldarg_2);
+ ilgen.Emit (OpCodes.Ldarg_1);
+ ilgen.Emit (OpCodes.Ldc_I4_1);
+ ilgen.Emit (OpCodes.Add);
+ ilgen.Emit (OpCodes.Stind_I4);
+ // return true;
+ ilgen.Emit (OpCodes.Ldc_I4_1);
+ ilgen.Emit (OpCodes.Ret);
+ // }
+ ilgen.MarkLabel (l3);
+ // 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,
label_fail);
+ } else {
+ // General case
+
+ //Console.WriteLine ("Anchor op
" + anch_op);
+
+ //while (strpos < string_end) {
+ Label l1 = ilgen.DefineLabel ();
+ Label l2 = ilgen.DefineLabel ();
+ ilgen.MarkLabel (l1);
+ ilgen.Emit (OpCodes.Ldarg_1);
+ ilgen.Emit (OpCodes.Ldarg_0);
+ ilgen.Emit (OpCodes.Ldfld,
GetInterpreterField ("string_end"));
+ ilgen.Emit (OpCodes.Bge, l2);
+ // int res = strpos;
+ LocalBuilder local_res =
ilgen.DeclareLocal (typeof (int));
+ ilgen.Emit (OpCodes.Ldarg_1);
+ ilgen.Emit (OpCodes.Stloc,
local_res);
+ // if (EvalByteCode (pc,
strpos, ref res)) {
+ Label l3 = ilgen.DefineLabel ();
+ MethodInfo eval =
GetEvalMethodWithFallback (program, pc, out fallback);
+ ilgen.Emit (OpCodes.Ldarg_0);
+ if (fallback)
+ ilgen.Emit
(OpCodes.Ldc_I4, pc);
+ ilgen.Emit (OpCodes.Ldarg_1);
+ ilgen.Emit (OpCodes.Ldloca,
local_res);
+ ilgen.Emit (OpCodes.Call, eval);
+ ilgen.Emit (OpCodes.Brfalse,
l3);
+ // match_start = strpos;
+ ilgen.Emit (OpCodes.Ldarg_0);
+ ilgen.Emit (OpCodes.Ldarg_1);
+ ilgen.Emit (OpCodes.Stfld,
GetInterpreterField ("match_start"));
+ // strpos_result = res;
+ ilgen.Emit (OpCodes.Ldarg_2);
+ ilgen.Emit (OpCodes.Ldloc,
local_res);
+ ilgen.Emit (OpCodes.Stind_I4);
+ // return true;
+ ilgen.Emit (OpCodes.Ldc_I4_1);
+ ilgen.Emit (OpCodes.Ret);
+ // }
+ ilgen.MarkLabel (l3);
+ // strpos++;
+ ilgen.Emit (OpCodes.Ldarg_1);
+ ilgen.Emit (OpCodes.Ldc_I4_1);
+ ilgen.Emit (OpCodes.Add);
+ ilgen.Emit (OpCodes.Starg, 1);
+ //}
+ ilgen.Emit (OpCodes.Br, l1);
+ ilgen.MarkLabel (l2);
+ //return false;
+ ilgen.Emit (OpCodes.Ldc_I4_0);
+ ilgen.Emit (OpCodes.Ret);
+ }
+
+ goto End;
+ }
+ case RxOp.Branch: {
+ //int res = 0;
+ LocalBuilder local_res =
ilgen.DeclareLocal (typeof (int));
+ // FIXME: Emit a branch around the rest
of the code instead
+ //if (EvalByteCode (pc + 3, strpos, ref
res)) {
+ Label l1 = ilgen.DefineLabel ();
+ MethodInfo eval =
GetEvalMethodWithFallback (program, pc + 3, out fallback);
+ ilgen.Emit (OpCodes.Ldarg_0);
+ if (fallback)
+ ilgen.Emit (OpCodes.Ldc_I4, pc
+ 3);
+ ilgen.Emit (OpCodes.Ldarg_1);
+ ilgen.Emit (OpCodes.Ldloca, local_res);
+ ilgen.Emit (OpCodes.Call, eval);
+ ilgen.Emit (OpCodes.Brfalse, l1);
+ // strpos_result = res;
+ ilgen.Emit (OpCodes.Ldarg_2);
+ ilgen.Emit (OpCodes.Ldloc, local_res);
+ ilgen.Emit (OpCodes.Stind_I4);
+ // return true;
+ ilgen.Emit (OpCodes.Ldc_I4_1);
+ ilgen.Emit (OpCodes.Ret);
+ //}
+ ilgen.MarkLabel (l1);
+
+ pc += program [pc + 1] | (program [pc +
2] << 8);
+ break;
+ }
+ case RxOp.Char: {
+ //if (strpos < string_end && (str
[strpos] == program [pc + 1])) {
+ Label l1 = ilgen.DefineLabel ();
+ ilgen.Emit (OpCodes.Ldarg_1);
+ ilgen.Emit (OpCodes.Ldarg_0);
+ ilgen.Emit (OpCodes.Ldfld,
GetInterpreterField ("string_end"));
+ ilgen.Emit (OpCodes.Bge, l1);
+ ilgen.Emit (OpCodes.Ldarg_0);
+ ilgen.Emit (OpCodes.Ldfld,
GetInterpreterField ("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.Bne_Un, l1);
+ // strpos++;
+ ilgen.Emit (OpCodes.Ldarg_1);
+ ilgen.Emit (OpCodes.Ldc_I4_1);
+ 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.Ldc_I4_0);
+ ilgen.Emit (OpCodes.Ret);
+ ilgen.MarkLabel (l2);
+
+ pc += 2;
+ break;
+ }
+ case RxOp.True: {
+ //strpos_result = strpos;
+ ilgen.Emit (OpCodes.Ldarg_2);
+ ilgen.Emit (OpCodes.Ldarg_1);
+ ilgen.Emit (OpCodes.Stind_I4);
+ // return true;
+ ilgen.Emit (OpCodes.Ldc_I4_1);
+ ilgen.Emit (OpCodes.Ret);
+ goto End;
+ }
+ case RxOp.False: {
+ // return false;
+ ilgen.Emit (OpCodes.Ldc_I4_0);
+ ilgen.Emit (OpCodes.Ret);
+ goto End;
+ }
+ case RxOp.Bitmap: {
+ //if (strpos < string_end) {
+ Label l1 = ilgen.DefineLabel ();
+ Label l2 = ilgen.DefineLabel ();
+ ilgen.Emit (OpCodes.Ldarg_1);
+ ilgen.Emit (OpCodes.Ldarg_0);
+ ilgen.Emit (OpCodes.Ldfld,
GetInterpreterField ("string_end"));
+ ilgen.Emit (OpCodes.Bge, l1);
+ // int c = str [strpos];
+ LocalBuilder local_c =
ilgen.DeclareLocal (typeof (int));
+ ilgen.Emit (OpCodes.Ldarg_0);
+ ilgen.Emit (OpCodes.Ldfld,
GetInterpreterField ("str"));
+ ilgen.Emit (OpCodes.Ldarg_1);
+ ilgen.Emit (OpCodes.Callvirt, typeof
(string).GetMethod ("get_Chars"));
+ ilgen.Emit (OpCodes.Conv_I4);
+ // c -= program [pc + 1];
+ ilgen.Emit (OpCodes.Ldc_I4,
(int)program [pc + 1]);
+ ilgen.Emit (OpCodes.Sub);
+ ilgen.Emit (OpCodes.Stloc, local_c);
+ length = program [pc + 2];
+ // if (c < 0 || c >= (length << 3))
+ // return false;
+ ilgen.Emit (OpCodes.Ldloc, local_c);
+ ilgen.Emit (OpCodes.Ldc_I4_0);
+ ilgen.Emit (OpCodes.Blt, label_fail);
+ ilgen.Emit (OpCodes.Ldloc, local_c);
+ ilgen.Emit (OpCodes.Ldc_I4, length <<
3);
+ ilgen.Emit (OpCodes.Bge, label_fail);
+ pc += 3;
+
+ // 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 (OpCodes.Brfalse,
l1);
+ } else {
+ // if ((program [pc + (c >>
3)] & (1 << (c & 0x7))) != 0) {
+ ilgen.Emit (OpCodes.Ldarg_0);
+ ilgen.Emit (OpCodes.Ldfld,
GetInterpreterField ("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 (OpCodes.Beq, l1);
+ }
+ // strpos++;
+ ilgen.Emit (OpCodes.Ldarg_1);
+ ilgen.Emit (OpCodes.Ldc_I4_1);
+ ilgen.Emit (OpCodes.Add);
+ ilgen.Emit (OpCodes.Starg, 1);
+ // continue;
+ ilgen.Emit (OpCodes.Br, l2);
+ // }
+ //}
+ //return false;
+ ilgen.MarkLabel (l1);
+ ilgen.Emit (OpCodes.Ldc_I4_0);
+ ilgen.Emit (OpCodes.Ret);
+
+ ilgen.MarkLabel (l2);
+
+ pc += length;
+ break;
+ }
+ case RxOp.String: {
+ start = pc + 2;
+ length = program [pc + 1];
+ //if (strpos + length > string_end)
+ // return false;
+ ilgen.Emit (OpCodes.Ldarg_1);
+ ilgen.Emit (OpCodes.Ldc_I4, length);
+ ilgen.Emit (OpCodes.Add);
+ ilgen.Emit (OpCodes.Ldarg_0);
+ ilgen.Emit (OpCodes.Ldfld,
GetInterpreterField ("string_end"));
+ ilgen.Emit (OpCodes.Bgt, label_fail);
+
+ /* Avoid unsafe code in Moonlight build
*/
+#if false && !NET_2_1
+ LocalBuilder local_strptr =
ilgen.DeclareLocal (typeof (char).MakePointerType ());
+ // char *strptr = &str.start_char +
strpos
+ ilgen.Emit (OpCodes.Ldarg_0);
+ ilgen.Emit (OpCodes.Ldfld,
GetInterpreterField ("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 (; start < end; ++start) {
+ // if (*(strptr + start) !=
program [start])
+ // return false;
+ ilgen.Emit (OpCodes.Ldloc,
local_strptr);
+ ilgen.Emit (OpCodes.Ldc_I4,
start * 2);
+ ilgen.Emit (OpCodes.Add);
+ ilgen.Emit (OpCodes.Ldind_I2);
+ ilgen.Emit (OpCodes.Ldc_I4,
(int)program [start]);
+ ilgen.Emit (OpCodes.Bne_Un,
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,
GetInterpreterField ("str"));
+ ilgen.Emit (OpCodes.Stloc, local_str);
+
+ // FIXME: Emit a loop for long strings
+ end = start + length;
+ for (; start < end; ++start) {
+ //if (str [strpos] != program
[start])
+ // return false;
+ ilgen.Emit (OpCodes.Ldloc,
local_str);
+ ilgen.Emit (OpCodes.Ldarg_1);
+ ilgen.Emit (OpCodes.Callvirt,
typeof (string).GetMethod ("get_Chars"));
+ ilgen.Emit (OpCodes.Ldc_I4,
(int)program [start]);
+ ilgen.Emit (OpCodes.Bne_Un,
label_fail);
+ //strpos++;
+ ilgen.Emit (OpCodes.Ldarg_1);
+ ilgen.Emit (OpCodes.Ldc_I4_1);
+ ilgen.Emit (OpCodes.Add);
+ ilgen.Emit (OpCodes.Starg, 1);
+ }
+#endif
+
+ pc = end;
+ break;
+ }
+ case RxOp.Jump:
+ pc += program [pc + 1] | (program [pc +
2] << 8);
+ continue;
+ default:
+ Console.WriteLine ("Opcode " + op + "
not supported.");
+ return null;
+ }
+ }
+
+ End:
+ ilgen.MarkLabel (label_fail);
+ ilgen.Emit (OpCodes.Ldc_I4_0);
+ ilgen.Emit (OpCodes.Ret);
+
+ return m;
+ }
+ }
+#else
+ class CILCompiler : RxCompiler {
+ }
+#endif
+
class RxInterpreterFactory : IMachineFactory {
- public RxInterpreterFactory (byte[] program) {
+ public RxInterpreterFactory (byte[] program, EvalDelegate
eval_del) {
this.program = program;
+ this.eval_del = eval_del;
}
public IMachine NewInstance () {
- return new RxInterpreter (program);
+ return new RxInterpreter (program, eval_del);
}
public int GroupCount {
@@ -711,6 +1207,7 @@
private IDictionary mapping;
private byte[] program;
+ private EvalDelegate eval_del;
private string[] namesMapping;
}
Modified: trunk/mcs/class/System/System.Text.RegularExpressions/RxInterpreter.cs
===================================================================
--- trunk/mcs/class/System/System.Text.RegularExpressions/RxInterpreter.cs
2008-02-13 14:29:49 UTC (rev 95579)
+++ trunk/mcs/class/System/System.Text.RegularExpressions/RxInterpreter.cs
2008-02-13 14:30:06 UTC (rev 95580)
@@ -5,6 +5,8 @@
namespace System.Text.RegularExpressions {
+ internal delegate bool EvalDelegate (RxInterpreter interp, int strpos,
ref int strpos_result);
+
class RxInterpreter: BaseMachine {
byte[] program;
string str;
@@ -13,6 +15,7 @@
int group_count;
int match_start;
int[] groups;
+ EvalDelegate eval_del; // optimized EvalByteCode method created
by the CILCompiler
Mark[] marks = null; // mark stack
int mark_start; // start of current checkpoint
@@ -27,9 +30,10 @@
return val;
}
- public RxInterpreter (byte[] program)
+ public RxInterpreter (byte[] program, EvalDelegate eval_del)
{
this.program = program;
+ this.eval_del = eval_del;
group_count = 1 + (program [1] | (program [2] << 8));
groups = new int [group_count];
}
@@ -39,7 +43,14 @@
string_start = start;
string_end = end;
int res = 0;
- if (EvalByteCode (11, start, ref res)) {
+
+ bool match;
+ if (eval_del != null) {
+ match = eval_del (this, start, ref res);
+ } else {
+ match = EvalByteCode (11, start, ref res);
+ }
+ if (match) {
Match m = new Match (regex, this, text, end, 0,
match_start, res - match_start);
return m;
}
_______________________________________________
Mono-patches maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches