Open GoogleCodeExporter opened 8 years ago
Hi,
From what I see in reflector, the last line translates exactly to:
(op11 ? op12 : false) || (op21 ? op22 : false) ...
It might seem wrong, but 'A ? B : false' is in fact equivalent to A && B (also
'A ? true : B' is equivalent to 'A || B', they are even implemented this way -
see Operand.LogicalAnd/Or). See the following table (I hope it's easy enough to
understand - the values in parentheses are unused in the particular
calculation, square brackets mark the result - the point is that the
short-circuiting works exactly as with && :)
A B A && B A ? B : 0
0 0 [0] (0) 0 -(0)>[0]
0 1 [0] (1) 0 -(1)>[0]
1 0 1 ->[0] 1 >[0]
1 1 1 ->[1] 1 >[1]
I believe that the code appearing in reflector is different only because the
ordering of the instructions is a bit off for the && implementation. I can try
to fix it, but I'm giving it the lowest possible priority :)
Also, looking at the code you have provided - are you aware that there is an
implicit conversion operator for most primitive types, so that you can save
typing Operand.FromObject(...), as well as proper implementations of most
operators?
Your code could be rewritten as follows (if only for the sake of readability):
private void GenerateRule4(TypeGen typeGen)
{
CodeGen g = typeGen.Public.Static.Method(typeof(bool), "Rule04").Parameter(typeof(IOptionValueProvider), "options");
{
Operand options = g.Arg("options");
Operand op11 = options.Invoke("GetOptionValueAsInteger", 1010) == 100;
Operand op12 = Static.Invoke(typeof(string), "Compare", options.Invoke("GetOptionValueAsString", 1009), "-B", StringComparison.OrdinalIgnoreCase) == 0;
Operand op21 = options.Invoke("GetOptionValueAsInteger", 1010) == 125;
Operand op22 = Static.Invoke(typeof(string), "Compare", options.Invoke("GetOptionValueAsString", 1009), "S", StringComparison.OrdinalIgnoreCase) == 0;
Operand op31 = options.Invoke("GetOptionValueAsInteger", 1010) == 160;
Operand op32 = Static.Invoke(typeof(string), "Compare", options.Invoke("GetOptionValueAsString", 1009), "S", StringComparison.OrdinalIgnoreCase) == 0;
Operand op41 = options.Invoke("GetOptionValueAsInteger", 1010) == 200;
Operand op42 = Static.Invoke(typeof(string), "Compare", options.Invoke("GetOptionValueAsString", 1009), "S", StringComparison.OrdinalIgnoreCase) == 0;
g.Return((((op11 && op12) || (op21 && op22)) || (op31 && op32)) || (op41 && op42));
}
}
Hope this helps,
Stefan
Original comment by StefanSi...@gmail.com
on 20 Aug 2010 at 8:38
Thanks for the quick reply Stefan
I also figured that the logic seemed to be correctly translated. Was not sure
though whether the IL was correct and my limited experience with IL as this
point caused me to ask the question. As long as it is logically equivalent and
just as performant as the C# compiler code, I'm happy.
W.r.t the implicit operator - I'm already using that. I pasted an old sample,
but thanks for the tip. I still have a few cases out of the 30000 rules being
translated not generating correctly IL, but I have yet to determine whether it
is me not traversing the AST correctly or whether it is related to runsharp.
I'll let you know if I discover any further anomalies.
Thanks again for a great library.
Carel
Original comment by carel.l...@gmail.com
on 20 Aug 2010 at 8:54
Original issue reported on code.google.com by
carel.l...@gmail.com
on 20 Aug 2010 at 6:57