1
/* Copyright (C) 2004 - 2009 Versant Inc. http://www.db4o.com */
4
using System.Reflection;
5
using Db4objects.Db4o.Instrumentation.Api;
6
using Db4objects.Db4o.Internal;
7
using Db4objects.Db4o.NativeQueries.Expr.Cmp;
8
using Db4objects.Db4o.NativeQueries.Expr.Cmp.Operand;
9
using Db4objects.Db4o.NativeQueries.Optimization;
10
using Sharpen.Lang.Reflect;
12
namespace Db4objects.Db4o.NativeQueries.Optimization
14
internal sealed class ComparisonQueryGeneratingVisitor : IComparisonOperandVisitor
16
private object _predicate;
18
private object _value = null;
20
private readonly INativeClassFactory _classSource;
22
private readonly IReferenceResolver _resolver;
29
public void Visit(ConstValue operand)
31
_value = operand.Value();
34
public void Visit(FieldValue operand)
36
operand.Parent().Accept(this);
37
Type clazz = ((operand.Parent() is StaticFieldRoot) ? (Type)_value : _value.GetType
41
FieldInfo field = Reflection4.GetField(clazz, operand.FieldName());
42
_value = field.GetValue(_value);
46
// arg is ignored for static
47
Sharpen.Runtime.PrintStackTrace(exc);
51
internal object Add(object a, object b)
53
if (a is double || b is double)
55
return ((double)a) + ((double)b);
57
if (a is float || b is float)
59
return ((float)a) + ((float)b);
61
if (a is long || b is long)
63
return ((long)a) + ((long)b);
65
return ((int)a) + ((int)b);
68
internal object Subtract(object a, object b)
70
if (a is double || b is double)
72
return ((double)a) - ((double)b);
74
if (a is float || b is float)
76
return ((float)a) - ((float)b);
78
if (a is long || b is long)
80
return ((long)a) - ((long)b);
82
return ((int)a) - ((int)b);
85
internal object Multiply(object a, object b)
87
if (a is double || b is double)
89
return ((double)a) * ((double)b);
91
if (a is float || b is float)
93
return ((float)a) * ((float)b);
95
if (a is long || b is long)
97
return ((long)a) * ((long)b);
99
return ((int)a) * ((int)b);
102
internal object Divide(object a, object b)
104
if (a is double || b is double)
106
return ((double)a) / ((double)b);
108
if (a is float || b is float)
110
return ((float)a) / ((float)b);
112
if (a is long || b is long)
114
return ((long)a) / ((long)b);
116
return ((int)a) / ((int)b);
119
public void Visit(ArithmeticExpression operand)
121
operand.Left().Accept(this);
122
object left = _value;
123
operand.Right().Accept(this);
124
object right = _value;
125
switch (operand.Op().Id())
127
case ArithmeticOperator.AddId:
129
_value = Add(left, right);
133
case ArithmeticOperator.SubtractId:
135
_value = Subtract(left, right);
139
case ArithmeticOperator.MultiplyId:
141
_value = Multiply(left, right);
145
case ArithmeticOperator.DivideId:
147
_value = Divide(left, right);
153
public void Visit(CandidateFieldRoot root)
157
public void Visit(PredicateFieldRoot root)
162
public void Visit(StaticFieldRoot root)
166
_value = _classSource.ForName(root.Type.Name);
168
catch (TypeLoadException e)
170
Sharpen.Runtime.PrintStackTrace(e);
174
public void Visit(ArrayAccessValue operand)
176
operand.Parent().Accept(this);
177
object parent = _value;
178
operand.Index().Accept(this);
179
int index = (int)_value;
180
_value = Sharpen.Runtime.GetArrayValue(parent, index);
183
public void Visit(MethodCallValue operand)
185
operand.Parent().Accept(this);
186
object receiver = _value;
187
MethodInfo method = _resolver.Resolve(operand.Method);
190
_value = method.Invoke(IsStatic(method) ? null : receiver, Args(operand));
192
catch (Exception exc)
194
Sharpen.Runtime.PrintStackTrace(exc);
199
private object[] Args(MethodCallValue operand)
201
IComparisonOperand[] args = operand.Args;
202
object[] @params = new object[args.Length];
203
for (int paramIdx = 0; paramIdx < args.Length; paramIdx++)
205
args[paramIdx].Accept(this);
206
@params[paramIdx] = _value;
211
private bool IsStatic(MethodInfo method)
213
return NativeQueriesPlatform.IsStatic(method);
216
public ComparisonQueryGeneratingVisitor(object predicate, INativeClassFactory classSource
217
, IReferenceResolver resolver) : base()
219
_predicate = predicate;
220
_classSource = classSource;
221
_resolver = resolver;