1 //------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //------------------------------------------------------------
4 namespace System.ServiceModel.Dispatcher
5 {
6     using System.Runtime;
7 
8     internal enum MathOperator
9     {
10         None,
11         Plus,
12         Minus,
13         Div,
14         Multiply,
15         Mod,
16         Negate
17     }
18 
19     internal class MathOpcode : Opcode
20     {
21         MathOperator mathOp;
22 
MathOpcode(OpcodeID id, MathOperator op)23         internal MathOpcode(OpcodeID id, MathOperator op)
24             : base(id)
25         {
26             this.mathOp = op;
27         }
28 
Equals(Opcode op)29         internal override bool Equals(Opcode op)
30         {
31             if (base.Equals(op))
32             {
33                 return (this.mathOp == ((MathOpcode) op).mathOp);
34             }
35 
36             return false;
37         }
38 
39 #if DEBUG_FILTER
ToString()40         public override string ToString()
41         {
42             return string.Format("{0} {1}", base.ToString(), this.mathOp.ToString());
43         }
44 #endif
45     }
46 
47     internal class PlusOpcode : MathOpcode
48     {
PlusOpcode()49         internal PlusOpcode()
50             : base(OpcodeID.Plus, MathOperator.Plus)
51         {
52         }
53 
Eval(ProcessingContext context)54         internal override Opcode Eval(ProcessingContext context)
55         {
56             StackFrame argX = context.TopArg;
57             StackFrame argY = context.SecondArg;
58             Fx.Assert(argX.Count == argY.Count, "");
59 
60             Value[] values = context.Values;
61 
62             for (int x = argX.basePtr, y = argY.basePtr; x <= argX.endPtr; ++x, ++y)
63             {
64                 Fx.Assert(values[x].IsType(ValueDataType.Double), "");
65                 Fx.Assert(values[y].IsType(ValueDataType.Double), "");
66                 values[y].Add(values[x].Double);
67             }
68 
69             context.PopFrame();
70             return this.next;
71         }
72     }
73 
74     internal class MinusOpcode : MathOpcode
75     {
MinusOpcode()76         internal MinusOpcode()
77             : base(OpcodeID.Minus, MathOperator.Minus)
78         {
79         }
80 
Eval(ProcessingContext context)81         internal override Opcode Eval(ProcessingContext context)
82         {
83             StackFrame argX = context.TopArg;
84             StackFrame argY = context.SecondArg;
85             Fx.Assert(argX.Count == argY.Count, "");
86 
87             Value[] values = context.Values;
88 
89             for (int x = argX.basePtr, y = argY.basePtr; x <= argX.endPtr; ++x, ++y)
90             {
91                 Fx.Assert(values[x].IsType(ValueDataType.Double), "");
92                 Fx.Assert(values[y].IsType(ValueDataType.Double), "");
93                 values[y].Double = values[x].Double - values[y].Double;
94             }
95 
96             context.PopFrame();
97             return this.next;
98         }
99     }
100 
101     internal class MultiplyOpcode : MathOpcode
102     {
MultiplyOpcode()103         internal MultiplyOpcode()
104             : base(OpcodeID.Multiply, MathOperator.Multiply)
105         {
106         }
107 
Eval(ProcessingContext context)108         internal override Opcode Eval(ProcessingContext context)
109         {
110             StackFrame argX = context.TopArg;
111             StackFrame argY = context.SecondArg;
112             Fx.Assert(argX.Count == argY.Count, "");
113 
114             Value[] values = context.Values;
115 
116             for (int x = argX.basePtr, y = argY.basePtr; x <= argX.endPtr; ++x, ++y)
117             {
118                 Fx.Assert(values[x].IsType(ValueDataType.Double), "");
119                 Fx.Assert(values[y].IsType(ValueDataType.Double), "");
120                 values[y].Multiply(values[x].Double);
121             }
122 
123             context.PopFrame();
124             return this.next;
125         }
126     }
127 
128     internal class DivideOpcode : MathOpcode
129     {
DivideOpcode()130         internal DivideOpcode()
131             : base(OpcodeID.Divide, MathOperator.Div)
132         {
133         }
134 
Eval(ProcessingContext context)135         internal override Opcode Eval(ProcessingContext context)
136         {
137             StackFrame argX = context.TopArg;
138             StackFrame argY = context.SecondArg;
139             Fx.Assert(argX.Count == argY.Count, "");
140             Value[] values = context.Values;
141 
142             for (int x = argX.basePtr, y = argY.basePtr; x <= argX.endPtr; ++x, ++y)
143             {
144                 Fx.Assert(values[x].IsType(ValueDataType.Double), "");
145                 Fx.Assert(values[y].IsType(ValueDataType.Double), "");
146                 values[y].Double = values[x].Double / values[y].Double;
147             }
148 
149             context.PopFrame();
150             return this.next;
151         }
152     }
153 
154     internal class ModulusOpcode : MathOpcode
155     {
ModulusOpcode()156         internal ModulusOpcode()
157             : base(OpcodeID.Mod, MathOperator.Mod)
158         {
159         }
160 
Eval(ProcessingContext context)161         internal override Opcode Eval(ProcessingContext context)
162         {
163             StackFrame argX = context.TopArg;
164             StackFrame argY = context.SecondArg;
165             Value[] values = context.Values;
166 
167             Fx.Assert(argX.Count == argY.Count, "");
168             for (int x = argX.basePtr, y = argY.basePtr; x <= argX.endPtr; ++x, ++y)
169             {
170                 Fx.Assert(values[x].IsType(ValueDataType.Double), "");
171                 Fx.Assert(values[y].IsType(ValueDataType.Double), "");
172                 values[y].Double = values[x].Double % values[y].Double;
173             }
174 
175             context.PopFrame();
176             return this.next;
177         }
178     }
179 
180     internal class NegateOpcode : MathOpcode
181     {
NegateOpcode()182         internal NegateOpcode()
183             : base(OpcodeID.Negate, MathOperator.Negate)
184         {
185         }
186 
Eval(ProcessingContext context)187         internal override Opcode Eval(ProcessingContext context)
188         {
189             StackFrame frame = context.TopArg;
190             Value[] values = context.Values;
191 
192             for (int i = frame.basePtr; i <= frame.endPtr; ++i)
193             {
194                 values[i].Negate();
195             }
196             return this.next;
197         }
198     }
199 
200 }
201