1
/* Copyright (C) 2004 - 2009 Versant Inc. http://www.db4o.com */
4
using Db4objects.Db4o.Instrumentation.Api;
5
using Db4objects.Db4o.NativeQueries.Expr.Cmp;
6
using Db4objects.Db4o.NativeQueries.Expr.Cmp.Operand;
7
using Db4objects.Db4o.NativeQueries.Instrumentation;
9
namespace Db4objects.Db4o.NativeQueries.Instrumentation
11
internal class ComparisonBytecodeGeneratingVisitor : IComparisonOperandVisitor
13
private IMethodBuilder _methodBuilder;
15
private ITypeRef _predicateClass;
17
private bool _inArithmetic = false;
19
private ITypeRef _opClass = null;
21
private ITypeRef _staticRoot = null;
23
public ComparisonBytecodeGeneratingVisitor(IMethodBuilder methodBuilder, ITypeRef
26
this._methodBuilder = methodBuilder;
27
this._predicateClass = predicateClass;
30
public virtual void Visit(ConstValue operand)
32
object value = operand.Value();
35
_opClass = TypeRef(value.GetType());
37
_methodBuilder.Ldc(value);
40
Box(_opClass, !_inArithmetic);
44
private ITypeRef TypeRef(Type type)
46
return _methodBuilder.References.ForType(type);
49
public virtual void Visit(FieldValue fieldValue)
51
ITypeRef lastFieldClass = fieldValue.Field.Type;
52
bool needConversion = lastFieldClass.IsPrimitive;
53
fieldValue.Parent().Accept(this);
54
if (_staticRoot != null)
56
_methodBuilder.LoadStaticField(fieldValue.Field);
60
_methodBuilder.LoadField(fieldValue.Field);
61
Box(lastFieldClass, !_inArithmetic && needConversion);
64
public virtual void Visit(CandidateFieldRoot root)
66
_methodBuilder.LoadArgument(1);
69
public virtual void Visit(PredicateFieldRoot root)
71
_methodBuilder.LoadArgument(0);
74
public virtual void Visit(StaticFieldRoot root)
76
_staticRoot = root.Type;
79
public virtual void Visit(ArrayAccessValue operand)
81
ITypeRef cmpType = DeduceFieldClass(operand.Parent()).ElementType;
82
operand.Parent().Accept(this);
83
bool outerInArithmetic = _inArithmetic;
85
operand.Index().Accept(this);
86
_inArithmetic = outerInArithmetic;
87
_methodBuilder.LoadArrayElement(cmpType);
88
Box(cmpType, !_inArithmetic);
91
public virtual void Visit(MethodCallValue operand)
93
IMethodRef method = operand.Method;
94
ITypeRef retType = method.ReturnType;
95
// FIXME: this should be handled within conversions
96
bool needConversion = retType.IsPrimitive;
97
operand.Parent().Accept(this);
98
bool oldInArithmetic = _inArithmetic;
99
for (int paramIdx = 0; paramIdx < operand.Args.Length; paramIdx++)
101
_inArithmetic = operand.Method.ParamTypes[paramIdx].IsPrimitive;
102
operand.Args[paramIdx].Accept(this);
104
_inArithmetic = oldInArithmetic;
105
_methodBuilder.Invoke(method, operand.CallingConvention);
106
Box(retType, !_inArithmetic && needConversion);
109
public virtual void Visit(ArithmeticExpression operand)
111
bool oldInArithmetic = _inArithmetic;
112
_inArithmetic = true;
113
operand.Left().Accept(this);
114
operand.Right().Accept(this);
115
ITypeRef operandType = ArithmeticType(operand);
116
switch (operand.Op().Id())
118
case ArithmeticOperator.AddId:
120
_methodBuilder.Add(operandType);
124
case ArithmeticOperator.SubtractId:
126
_methodBuilder.Subtract(operandType);
130
case ArithmeticOperator.MultiplyId:
132
_methodBuilder.Multiply(operandType);
136
case ArithmeticOperator.DivideId:
138
_methodBuilder.Divide(operandType);
144
throw new Exception("Unknown operand: " + operand.Op());
147
Box(_opClass, !oldInArithmetic);
148
_inArithmetic = oldInArithmetic;
151
// FIXME: need to map dX,fX,...
152
private void Box(ITypeRef boxedType, bool canApply)
158
_methodBuilder.Box(boxedType);
161
private ITypeRef DeduceFieldClass(IComparisonOperand fieldValue)
163
TypeDeducingVisitor visitor = new TypeDeducingVisitor(_methodBuilder.References,
165
fieldValue.Accept(visitor);
166
return visitor.OperandClass();
169
private ITypeRef ArithmeticType(IComparisonOperand operand)
171
if (operand is ConstValue)
173
return PrimitiveType(((ConstValue)operand).Value().GetType());
175
if (operand is FieldValue)
177
return ((FieldValue)operand).Field.Type;
179
if (operand is ArithmeticExpression)
181
ArithmeticExpression expr = (ArithmeticExpression)operand;
182
ITypeRef left = ArithmeticType(expr.Left());
183
ITypeRef right = ArithmeticType(expr.Right());
184
if (left == DoubleType() || right == DoubleType())
188
if (left == FloatType() || right == FloatType())
192
if (left == LongType() || right == LongType())
201
private ITypeRef PrimitiveType(Type klass)
203
if (klass == typeof(int) || klass == typeof(short) || klass == typeof(bool) || klass
208
if (klass == typeof(double))
212
if (klass == typeof(float))
216
if (klass == typeof(long))
220
return TypeRef(klass);
223
private ITypeRef IntType()
225
return TypeRef(typeof(int));
228
private ITypeRef LongType()
230
return TypeRef(typeof(long));
233
private ITypeRef FloatType()
235
return TypeRef(typeof(float));
238
private ITypeRef DoubleType()
240
return TypeRef(typeof(double));