merge from trunk revisions 58933, 58935, 58936
[mono.git] / mcs / class / Microsoft.JScript / Microsoft.JScript / StrictEquality.cs
1 //
2 // StrictEquality.cs:
3 //
4 // Author:
5 //      Cesar Lopez Nataren (cesar@ciencias.unam.mx)
6 //
7 // (C) 2003, Cesar Lopez Nataren
8 // (C) 2005, Novell Inc. (http://novell.com)
9 //
10
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 // 
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31
32 using System;
33 using System.Reflection.Emit;
34
35 namespace Microsoft.JScript {
36
37         public class StrictEquality : BinaryOp {
38
39                 internal StrictEquality (AST parent, AST left, AST right, JSToken op, Location location)
40                         : base (parent, left, right, op, location)
41                 {
42                 }
43
44                 public static bool JScriptStrictEquals (object v1, object v2)
45                 {
46                         IConvertible ic1 = v1 as IConvertible;
47                         IConvertible ic2 = v2 as IConvertible;
48
49                         TypeCode tc1 = Convert.GetTypeCode (v1, ic1);
50                         TypeCode tc2 = Convert.GetTypeCode (v2, ic2);
51
52                         bool both_numbers = Convert.IsNumberTypeCode (tc1) && Convert.IsNumberTypeCode (tc2);
53                         if (tc1 != tc2 && !both_numbers)
54                                 return false;
55
56                         switch (tc1) {
57                         case TypeCode.DBNull:
58                         case TypeCode.Empty:
59                                 return true;
60
61                         case TypeCode.Boolean:
62                                 return ic1.ToBoolean (null) == ic2.ToBoolean (null);
63
64                         case TypeCode.String:
65                                 return ic1.ToString (null) == ic2.ToString (null);
66
67                         case TypeCode.Object:
68                                 if (v1 is ScriptFunction && v2 is ScriptFunction)
69                                         return v1 == v2 || v1.Equals (v2);
70                                 else
71                                         return v1 == v2;
72
73                         default:
74                                 if (both_numbers) {
75                                         double num1;
76                                         if (Convert.IsFloatTypeCode (tc1))
77                                                 num1 = ic1.ToDouble (null);
78                                         else
79                                                 num1 = (double) ic1.ToInt64 (null);
80
81                                         double num2;
82                                         if (Convert.IsFloatTypeCode (tc2))
83                                                 num2 = ic2.ToDouble (null);
84                                         else
85                                                 num2 = (double) ic2.ToInt64 (null);
86
87                                         return num1 == num2;
88                                 }
89                                 Console.WriteLine ("StrictEquality, tc1 = {0}, tc2 = {1}", tc1, tc2);
90                                 break;
91                         }
92                         throw new NotImplementedException ();
93                 }
94
95                 internal override bool Resolve (Environment env)
96                 {
97                         bool r = true;
98                         if (left != null)
99                                 r &= left.Resolve (env);
100                         if (right != null)
101                                 r &= right.Resolve (env);
102                         return r;
103                 }
104                 
105                 internal override bool Resolve (Environment env, bool no_effect)
106                 {
107                         this.no_effect = no_effect;
108                         return Resolve (env);
109                 }
110
111                 internal override void Emit (EmitContext ec)
112                 {
113                         if (left != null) {
114                                 left.Emit (ec);
115                                 CodeGenerator.EmitBox (ec.ig, left);
116                         }
117                         if (right != null) {
118                                 right.Emit (ec);
119                                 CodeGenerator.EmitBox (ec.ig, right);
120                         }
121                         ec.ig.Emit (OpCodes.Call, typeof (StrictEquality).GetMethod ("JScriptStrictEquals"));
122                 }
123         }
124 }