private Expression GenerateSubstitution(Subroutine sub, RegexReplace rm) { var scalar = Expression.Variable(typeof(P5Scalar)); var str = Expression.Variable(typeof(string)); var replace = Expression.Variable(typeof(IP5Any)); var init_scalar = Expression.Assign(scalar, Generate(sub, rm.Childs[0])); var init_str = Expression.Assign( str, Expression.Call( scalar, typeof(IP5Any).GetMethod("AsString"), Runtime)); var replace_list = new List<Expression>(); // at this point all nested scopes have been generated replace_list.Add( Expression.Assign(replace, ValueBlocks[rm.To])); // replace in string var rxstate = Expression.Field( Runtime, typeof(Runtime).GetField("LastMatch")); replace_list.Add( Expression.Call( scalar, typeof(P5Scalar).GetMethod("SpliceSubstring", new[] { typeof(Runtime), typeof(int), typeof(int), typeof(IP5Any) }), Runtime, Expression.Field( rxstate, typeof(RxResult).GetField("Start")), Expression.Subtract( Expression.Field( rxstate, typeof(RxResult).GetField("End")), Expression.Field( rxstate, typeof(RxResult).GetField("Start"))), replace)); // return true at end of replacement replace_list.Add(Expression.Constant(true)); var match = Expression.Call( Generate(sub, rm.Childs[1]), typeof(IP5Regex).GetMethod("MatchString"), Runtime, str, Expression.Constant(-1), Expression.Constant(false), GetSavedRxState(rm.Index)); var repl = Expression.Condition( match, Expression.Block(typeof(bool), replace_list), Expression.Constant(false)); var vars = new List<ParameterExpression>(); vars.Add(scalar); vars.Add(str); vars.Add(replace); var exps = new List<Expression>(); exps.Add(init_scalar); exps.Add(init_str); exps.Add( Expression.New( typeof(P5Scalar).GetConstructor(ProtoRuntimeBool), Runtime, repl)); return Expression.Block(typeof(P5Scalar), vars, exps); }
private Expression GenerateGlobalSubstitution(Subroutine sub, RegexReplace rm) { var scalar = Expression.Variable(typeof(P5Scalar)); var init_scalar = Expression.Assign(scalar, Generate(sub, rm.Childs[0])); var pos = Expression.Variable(typeof(int)); var count = Expression.Variable(typeof(int)); var matched = Expression.Variable(typeof(bool)); var str = Expression.Variable(typeof(string)); var replace = Expression.Variable(typeof(string)); var repl_list = Expression.Variable(typeof(List<RxReplacement>)); var init_str = Expression.Assign( str, Expression.Call( scalar, typeof(IP5Any).GetMethod("AsString"), Runtime)); var match = Expression.Call( Generate(sub, rm.Childs[1]), typeof(IP5Regex).GetMethod("MatchString"), Runtime, str, pos, Expression.Constant(false), GetSavedRxState(rm.Index)); var rxstate = Expression.Field( Runtime, typeof(Runtime).GetField("LastMatch")); var rx_end = Expression.Field( rxstate, typeof(RxResult).GetField("End")); var rx_start = Expression.Field( rxstate, typeof(RxResult).GetField("Start")); var if_match = new List<Expression>(); if_match.Add(Expression.PreIncrementAssign(count)); if_match.Add(Expression.Assign(matched, Expression.Constant(true))); if_match.Add(Expression.Assign(pos, rx_end)); // at this point all nested scopes have been generated if_match.Add(Expression.Assign( replace, Expression.Call( ValueBlocks[rm.To], typeof(IP5Any).GetMethod("AsString"), Runtime))); if_match.Add( Expression.Call( repl_list, typeof(List<RxReplacement>).GetMethod("Add"), Expression.New( typeof(RxReplacement).GetConstructor( new Type[] { typeof(string), typeof(int), typeof(int) }), replace, rx_start, rx_end))); var break_to = Expression.Label(typeof(void)); var loop = Expression.Loop( Expression.Block( Expression.IfThenElse( match, Expression.Block(typeof(void), if_match), Expression.Break(break_to))), break_to); // TODO save last match var vars = new List<ParameterExpression>(); vars.Add(scalar); vars.Add(pos); vars.Add(count); vars.Add(matched); vars.Add(str); vars.Add(replace); vars.Add(repl_list); var body = new List<Expression>(); body.Add(init_scalar); body.Add(init_str); body.Add(Expression.Assign(pos, Expression.Constant(-1))); body.Add(Expression.Assign(count, Expression.Constant(0))); body.Add(Expression.Assign(matched, Expression.Constant(false))); body.Add(Expression.Assign( repl_list, Expression.New( typeof(List<RxReplacement>).GetConstructor( new Type[0])))); body.Add(loop); // replace substrings body.Add( Expression.Call( typeof(P5Regex).GetMethod("ReplaceSubstrings"), Runtime, scalar, str, repl_list)); // return value var result = Expression.New( typeof(P5Scalar).GetConstructor(ProtoRuntimeInt), Runtime, count); body.Add( Expression.Condition( Expression.Equal( OpContext(rm), Expression.Constant(Opcode.ContextValues.LIST)), Expression.New( typeof(P5List).GetConstructor(ProtoRuntimeAny), Runtime, result), result, typeof(IP5Any))); return Expression.Block(typeof(IP5Any), vars, body); }