1/*
2 * Copyright (C) 2008 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#ifndef ResultType_h
27#define ResultType_h
28
29namespace JSC {
30
31    struct ResultType {
32        friend struct OperandTypes;
33
34        typedef char Type;
35        static const Type TypeInt32 = 1;
36
37        static const Type TypeMaybeNumber = 0x04;
38        static const Type TypeMaybeString = 0x08;
39        static const Type TypeMaybeNull   = 0x10;
40        static const Type TypeMaybeBool   = 0x20;
41        static const Type TypeMaybeOther  = 0x40;
42
43        static const Type TypeBits = TypeMaybeNumber | TypeMaybeString | TypeMaybeNull | TypeMaybeBool | TypeMaybeOther;
44
45        explicit ResultType(Type type)
46            : m_type(type)
47        {
48        }
49
50        bool isInt32()
51        {
52            return m_type & TypeInt32;
53        }
54
55        bool definitelyIsNumber()
56        {
57            return (m_type & TypeBits) == TypeMaybeNumber;
58        }
59
60        bool definitelyIsString()
61        {
62            return (m_type & TypeBits) == TypeMaybeString;
63        }
64
65        bool definitelyIsBoolean()
66        {
67            return (m_type & TypeBits) == TypeMaybeBool;
68        }
69
70        bool mightBeNumber()
71        {
72            return m_type & TypeMaybeNumber;
73        }
74
75        bool isNotNumber()
76        {
77            return !mightBeNumber();
78        }
79
80        static ResultType nullType()
81        {
82            return ResultType(TypeMaybeNull);
83        }
84
85        static ResultType booleanType()
86        {
87            return ResultType(TypeMaybeBool);
88        }
89
90        static ResultType numberType()
91        {
92            return ResultType(TypeMaybeNumber);
93        }
94
95        static ResultType numberTypeIsInt32()
96        {
97            return ResultType(TypeInt32 | TypeMaybeNumber);
98        }
99
100        static ResultType stringOrNumberType()
101        {
102            return ResultType(TypeMaybeNumber | TypeMaybeString);
103        }
104
105        static ResultType stringType()
106        {
107            return ResultType(TypeMaybeString);
108        }
109
110        static ResultType unknownType()
111        {
112            return ResultType(TypeBits);
113        }
114
115        static ResultType forAdd(ResultType op1, ResultType op2)
116        {
117            if (op1.definitelyIsNumber() && op2.definitelyIsNumber())
118                return numberType();
119            if (op1.definitelyIsString() || op2.definitelyIsString())
120                return stringType();
121            return stringOrNumberType();
122        }
123
124        // Unlike in C, a logical op produces the value of the
125        // last expression evaluated (and not true or false).
126        static ResultType forLogicalOp(ResultType op1, ResultType op2)
127        {
128            if (op1.definitelyIsBoolean() && op2.definitelyIsBoolean())
129                return booleanType();
130            if (op1.definitelyIsNumber() && op2.definitelyIsNumber())
131                return numberType();
132            if (op1.definitelyIsString() && op2.definitelyIsString())
133                return stringType();
134            return unknownType();
135        }
136
137        static ResultType forBitOp()
138        {
139            return numberTypeIsInt32();
140        }
141
142    private:
143        Type m_type;
144    };
145
146    struct OperandTypes
147    {
148        OperandTypes(ResultType first = ResultType::unknownType(), ResultType second = ResultType::unknownType())
149        {
150            // We have to initialize one of the int to ensure that
151            // the entire struct is initialized.
152            m_u.i = 0;
153            m_u.rds.first = first.m_type;
154            m_u.rds.second = second.m_type;
155        }
156
157        union {
158            struct {
159                ResultType::Type first;
160                ResultType::Type second;
161            } rds;
162            int i;
163        } m_u;
164
165        ResultType first()
166        {
167            return ResultType(m_u.rds.first);
168        }
169
170        ResultType second()
171        {
172            return ResultType(m_u.rds.second);
173        }
174
175        int toInt()
176        {
177            return m_u.i;
178        }
179        static OperandTypes fromInt(int value)
180        {
181            OperandTypes types;
182            types.m_u.i = value;
183            return types;
184        }
185    };
186
187} // namespace JSC
188
189#endif // ResultType_h
190