77e7585a35e9458de9e6b300557175452a5dc259
[mono.git] / mcs / class / Microsoft.JScript / Microsoft.JScript / PostOrPrefixOperator.cs
1 //
2 // PostOrPrefixOperator.cs:
3 //
4 // Author:
5 //      Cesar Lopez Nataren (cesar@ciencias.unam.mx)
6 //
7 // (C) 2003, Cesar Lopez Nataren
8 //
9
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30
31 using System;
32 using System.Diagnostics;
33 using System.Reflection.Emit;
34
35 namespace Microsoft.JScript {
36
37         public class PostOrPrefixOperator : UnaryOp {
38
39                 bool prefix;
40
41                 public PostOrPrefixOperator (int operatorTok)
42                 {
43                         oper = (JSToken) operatorTok;
44                 }
45
46                 internal PostOrPrefixOperator (AST parent, AST operand, JSToken oper, bool prefix)
47                 {
48                         this.parent = parent;
49                         this.operand = operand;
50                         this.oper = oper;
51                         this.prefix = prefix;
52                 }
53
54                 [DebuggerStepThroughAttribute]
55                 [DebuggerHiddenAttribute]
56                 public object EvaluatePostOrPrefix (ref object v)
57                 {
58                         throw new NotImplementedException ();
59                 }
60
61                 internal override bool Resolve (IdentificationTable context)
62                 {
63                         return operand.Resolve (context);
64                 }
65
66                 internal override bool Resolve (IdentificationTable context, bool no_effect)
67                 {
68                         if (operand is Exp)
69                                 return ((Exp) operand).Resolve (context, no_effect);
70                         else
71                                 return operand.Resolve (context);
72                 }
73
74                 internal override void Emit (EmitContext ec)
75                 {
76                         if (oper == JSToken.None)
77                                 operand.Emit (ec);
78                         else {
79                                 ILGenerator ig = ec.ig;
80                                 Type post_prefix = typeof (PostOrPrefixOperator);
81                                 LocalBuilder post_prefix_local = ig.DeclareLocal (post_prefix);
82                                 LocalBuilder tmp_obj = ig.DeclareLocal (typeof (object));
83
84                                 switch (this.oper) {
85                                 case JSToken.Increment:
86                                         if (prefix)
87                                                 ig.Emit (OpCodes.Ldc_I4_3);
88                                         else 
89                                                 ig.Emit (OpCodes.Ldc_I4_1);
90                                         break;
91                                 case JSToken.Decrement:
92                                         if (prefix)
93                                                 ig.Emit (OpCodes.Ldc_I4_2);
94                                         else
95                                                 ig.Emit (OpCodes.Ldc_I4_0);
96                                         break;
97                                 }
98
99                                 ig.Emit (OpCodes.Newobj, post_prefix.GetConstructor (new Type [] { typeof (int) }));
100                                 ig.Emit (OpCodes.Stloc, post_prefix_local);
101
102                                 if (operand is Identifier)
103                                         ((Identifier) operand).EmitLoad (ec);
104                                 else throw new NotImplementedException ();
105
106                                 ig.Emit (OpCodes.Stloc, tmp_obj);
107                                 ig.Emit (OpCodes.Ldloc, post_prefix_local);
108                                 ig.Emit (OpCodes.Ldloca_S, tmp_obj);
109                                 ig.Emit (OpCodes.Call, post_prefix.GetMethod ("EvaluatePostOrPrefix"));
110
111                                 //
112                                 // if does not appear as a global expression
113                                 //
114                                 if (prefix && !(parent is ScriptBlock)) {
115                                         ig.Emit (OpCodes.Dup);
116                                         ig.Emit (OpCodes.Stloc, tmp_obj);
117                                 }
118
119                                 if (operand is Identifier)
120                                         ((Identifier) operand).EmitStore (ec);
121                                 else throw new NotImplementedException ();
122
123                                 //
124                                 // If value will be used, load the
125                                 // temp var that holded the value
126                                 // before inc/dec was evaluated
127                                 //
128                                 if (!(parent is ScriptBlock || parent is FunctionDeclaration ||
129                                       parent is FunctionExpression || parent is Block))
130                                         ig.Emit (OpCodes.Ldloc, tmp_obj);
131                         }
132                 }
133         }
134 }