blob: 084f9dfdc6262b7a47fa77d04e59e0e2bae0edca [file] [log] [blame]
Andreas Huber1aec3972016-08-26 09:26:32 -07001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Yifan Hong52165692016-08-12 18:06:40 -070017#include "ConstantExpression.h"
18
Yifan Hong57886972016-08-17 10:42:15 -070019#include <stdio.h>
20#include <string>
Yifan Hong57886972016-08-17 10:42:15 -070021#include <android-base/parseint.h>
22#include <android-base/logging.h>
23#include <sstream>
24
Yifan Hongf24fa852016-09-23 11:03:15 -070025#include "EnumType.h"
26
Yifan Hong57886972016-08-17 10:42:15 -070027// The macros are really nasty here. Consider removing
28// as many macros as possible.
29
30#define STREQ(__x__, __y__) (strcmp((__x__), (__y__)) == 0)
31#define OPEQ(__y__) STREQ(op, __y__)
32#define COMPUTE_UNARY(__op__) if(OPEQ(#__op__)) return __op__ val;
33#define COMPUTE_BINARY(__op__) if(OPEQ(#__op__)) return lval __op__ rval;
34#define OP_IS_BIN_ARITHMETIC (OPEQ("+") || OPEQ("-") || OPEQ("*") || OPEQ("/") || OPEQ("%"))
35#define OP_IS_BIN_BITFLIP (OPEQ("|") || OPEQ("^") || OPEQ("&"))
36#define OP_IS_BIN_COMP (OPEQ("<") || OPEQ(">") || OPEQ("<=") || OPEQ(">=") || OPEQ("==") || OPEQ("!="))
37#define OP_IS_BIN_SHIFT (OPEQ(">>") || OPEQ("<<"))
38#define OP_IS_BIN_LOGICAL (OPEQ("||") || OPEQ("&&"))
39#define SK(__x__) ScalarType::Kind::KIND_##__x__
Yifan Hongf24fa852016-09-23 11:03:15 -070040#define SHOULD_NOT_REACH() CHECK(false) << __LINE__ << ": should not reach here: "
Yifan Hong57886972016-08-17 10:42:15 -070041
42#define SWITCH_KIND(__cond__, __action__, __def__) \
Yifan Hong2bd3c1f2016-09-22 13:20:05 -070043 switch(__cond__) { \
44 case SK(BOOL): __action__(bool) \
45 case SK(UINT8): __action__(uint8_t) \
46 case SK(INT8): __action__(int8_t) \
47 case SK(UINT16): __action__(uint16_t) \
48 case SK(INT16): __action__(int16_t) \
49 case SK(UINT32): __action__(uint32_t) \
50 case SK(INT32): __action__(int32_t) \
51 case SK(UINT64): __action__(uint64_t) \
52 case SK(INT64): __action__(int64_t) \
53 default: __def__ \
54 } \
Yifan Hong52165692016-08-12 18:06:40 -070055
56namespace android {
57
Yifan Hongf24fa852016-09-23 11:03:15 -070058static inline bool isSupported(ScalarType::Kind kind) {
59 return SK(BOOL) == kind || ScalarType(kind).isValidEnumStorageType();
60}
61
Yifan Hong57886972016-08-17 10:42:15 -070062/* See docs at the end for details on integral promotion. */
63ScalarType::Kind integralPromotion(ScalarType::Kind in) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -070064 return SK(INT32) < in ? in : SK(INT32); // note that KIND_INT32 < KIND_UINT32
Yifan Hong52165692016-08-12 18:06:40 -070065}
66
Yifan Hong57886972016-08-17 10:42:15 -070067/* See docs at the end for details on usual arithmetic conversion. */
Yifan Hong2bd3c1f2016-09-22 13:20:05 -070068ScalarType::Kind usualArithmeticConversion(ScalarType::Kind lft,
69 ScalarType::Kind rgt) {
Yifan Hongf24fa852016-09-23 11:03:15 -070070 CHECK(isSupported(lft) && isSupported(rgt));
Yifan Hong2bd3c1f2016-09-22 13:20:05 -070071 // Kinds in concern: bool, (u)int[8|16|32|64]
72 if(lft == rgt) return lft; // easy case
73 if(lft == SK(BOOL)) return rgt;
74 if(rgt == SK(BOOL)) return lft;
75 bool isLftSigned = (lft == SK(INT8)) || (lft == SK(INT16))
76 || (lft == SK(INT32)) || (lft == SK(INT64));
77 bool isRgtSigned = (rgt == SK(INT8)) || (rgt == SK(INT16))
78 || (rgt == SK(INT32)) || (rgt == SK(INT64));
79 if(isLftSigned == isRgtSigned) return lft < rgt ? rgt : lft;
80 ScalarType::Kind unsignedRank = isLftSigned ? rgt : lft;
81 ScalarType::Kind signedRank = isLftSigned ? lft : rgt;
82 if(unsignedRank >= signedRank) return unsignedRank;
83 if(signedRank > unsignedRank) return signedRank;
Yifan Hong57886972016-08-17 10:42:15 -070084
Yifan Hong2bd3c1f2016-09-22 13:20:05 -070085 // Although there is such rule to return "the unsigned counterpart of
86 // the signed operand", it should not reach here in our HIDL grammar.
87 LOG(FATAL) << "Could not do usual arithmetic conversion for type "
88 << lft << "and" << rgt;
89 switch(signedRank) {
90 case SK(INT8): return SK(UINT8);
91 case SK(INT16): return SK(UINT16);
92 case SK(INT32): return SK(UINT32);
93 case SK(INT64): return SK(UINT64);
94 default: return SK(UINT64);
95 }
Yifan Hong52165692016-08-12 18:06:40 -070096}
Yifan Hong57886972016-08-17 10:42:15 -070097
98template <class T>
99T handleUnary(const char *op, T val) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700100 COMPUTE_UNARY(+)
101 COMPUTE_UNARY(-)
102 COMPUTE_UNARY(!)
103 COMPUTE_UNARY(~)
104 // Should not reach here.
Yifan Hongf24fa852016-09-23 11:03:15 -0700105 SHOULD_NOT_REACH() << "Could not handleUnary for " << op << " " << val;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700106 return static_cast<T>(0xdeadbeef);
Yifan Hong57886972016-08-17 10:42:15 -0700107}
108
109template <class T>
110T handleBinaryCommon(T lval, const char *op, T rval) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700111 COMPUTE_BINARY(+)
112 COMPUTE_BINARY(-)
113 COMPUTE_BINARY(*)
114 COMPUTE_BINARY(/)
115 COMPUTE_BINARY(%)
116 COMPUTE_BINARY(|)
117 COMPUTE_BINARY(^)
118 COMPUTE_BINARY(&)
119 // comparison operators: return 0 or 1 by nature.
120 COMPUTE_BINARY(==)
121 COMPUTE_BINARY(!=)
122 COMPUTE_BINARY(<)
123 COMPUTE_BINARY(>)
124 COMPUTE_BINARY(<=)
125 COMPUTE_BINARY(>=)
126 // Should not reach here.
Yifan Hongf24fa852016-09-23 11:03:15 -0700127 SHOULD_NOT_REACH() << "Could not handleBinaryCommon for "
128 << lval << " " << op << " " << rval;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700129 return static_cast<T>(0xdeadbeef);
Yifan Hong57886972016-08-17 10:42:15 -0700130}
131
132template <class T>
133T handleShift(T lval, const char *op, int64_t rval) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700134 // just cast rval to int64_t and it should fit.
135 COMPUTE_BINARY(>>)
136 COMPUTE_BINARY(<<)
137 // Should not reach here.
Yifan Hongf24fa852016-09-23 11:03:15 -0700138 SHOULD_NOT_REACH() << "Could not handleShift for"
139 << lval << " " << op << " " << rval;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700140 return static_cast<T>(0xdeadbeef);
Yifan Hong57886972016-08-17 10:42:15 -0700141}
142
143bool handleLogical(bool lval, const char *op, bool rval) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700144 COMPUTE_BINARY(||);
145 COMPUTE_BINARY(&&);
146 // Should not reach here.
Yifan Hongf24fa852016-09-23 11:03:15 -0700147 SHOULD_NOT_REACH() << "Could not handleLogical for"
148 << lval << " " << op << " " << rval;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700149 return false;
Yifan Hong57886972016-08-17 10:42:15 -0700150}
151
Yifan Hongf24fa852016-09-23 11:03:15 -0700152ConstantExpression::ConstantExpression() {
153}
154
Yifan Hongf509cb02017-04-03 12:19:25 -0700155// static
Yifan Hongf24fa852016-09-23 11:03:15 -0700156ConstantExpression ConstantExpression::Zero(ScalarType::Kind kind) {
Yifan Hongf509cb02017-04-03 12:19:25 -0700157 ConstantExpression ce = ValueOf(kind, 0);
158 ce.mExpr = "0";
Yifan Hongf24fa852016-09-23 11:03:15 -0700159 return ce;
160}
161
Yifan Hongf509cb02017-04-03 12:19:25 -0700162// static
163ConstantExpression ConstantExpression::One(ScalarType::Kind kind) {
164 ConstantExpression ce = ValueOf(kind, 1);
165 ce.mExpr = "1";
166 return ce;
167}
168
169// static
170ConstantExpression ConstantExpression::ValueOf(ScalarType::Kind kind, uint64_t value) {
171 ConstantExpression ce;
172 CHECK(isSupported(kind));
173
174 ce.mExpr = "";
175 ce.mType = kConstExprLiteral;
176 ce.mValueKind = kind;
177 ce.mValue = value;
178 ce.mTrivialDescription = true;
179 return ce;
180}
Yifan Hongf24fa852016-09-23 11:03:15 -0700181ConstantExpression::ConstantExpression(const ConstantExpression& other) {
182 *this = other;
183}
184
Yifan Hong5706a432016-11-02 09:44:18 -0700185/* Copy constructor, with the expr overriden and treated non-trivial */
Yifan Hongf24fa852016-09-23 11:03:15 -0700186ConstantExpression::ConstantExpression(const ConstantExpression& other, std::string expr) {
187 *this = other;
188 mExpr = expr;
Yifan Hong5706a432016-11-02 09:44:18 -0700189 mTrivialDescription = false;
Yifan Hongf24fa852016-09-23 11:03:15 -0700190}
191
192ConstantExpression& ConstantExpression::operator=(const ConstantExpression& other) {
193 mType = other.mType;
194 mValueKind = other.mValueKind;
195 mValue = other.mValue;
196 mExpr = other.mExpr;
Yifan Hong5706a432016-11-02 09:44:18 -0700197 mTrivialDescription = other.mTrivialDescription;
Yifan Hongf24fa852016-09-23 11:03:15 -0700198 return *this;
199}
200
Yifan Hong57886972016-08-17 10:42:15 -0700201/* Literals. */
Yifan Hongf24fa852016-09-23 11:03:15 -0700202ConstantExpression::ConstantExpression(const char *value)
Yifan Hong5706a432016-11-02 09:44:18 -0700203 : mExpr(value), mType(kConstExprLiteral), mTrivialDescription(true) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700204 const char* head = value, *tail = head + strlen(value) - 1;
205 bool isLong = false, isUnsigned = false;
206 bool isHex = (value[0] == '0' && (value[1] == 'x' || value[1] == 'X'));
207 while(tail >= head && (*tail == 'u' || *tail == 'U' || *tail == 'l' || *tail == 'L')) {
Yifan Hongf24fa852016-09-23 11:03:15 -0700208 isUnsigned |= (*tail == 'u' || *tail == 'U');
209 isLong |= (*tail == 'l' || *tail == 'L');
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700210 tail--;
Yifan Hong57886972016-08-17 10:42:15 -0700211 }
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700212 char *newVal = strndup(value, tail - head + 1);
213 bool parseOK = base::ParseUint(newVal, &mValue);
214 free(newVal);
Yifan Hongf24fa852016-09-23 11:03:15 -0700215 CHECK(parseOK) << "Could not parse as integer: " << value;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700216
217 // guess literal type.
218 if(isLong) {
219 if(isUnsigned) // ul
220 mValueKind = SK(UINT64);
221 else // l
222 mValueKind = SK(INT64);
223 } else { // no l suffix
224 if(isUnsigned) { // u
225 if(mValue <= UINT32_MAX)
226 mValueKind = SK(UINT32);
227 else
228 mValueKind = SK(UINT64);
229 } else { // no suffix
230 if(isHex) {
231 if(mValue <= INT32_MAX) // mValue always >= 0
232 mValueKind = SK(INT32);
233 else if(mValue <= UINT32_MAX)
234 mValueKind = SK(UINT32);
235 else if(mValue <= INT64_MAX) // mValue always >= 0
236 mValueKind = SK(INT64);
237 else if(mValue <= UINT64_MAX)
238 mValueKind = SK(UINT64);
239 } else {
240 if(mValue <= INT32_MAX) // mValue always >= 0
241 mValueKind = SK(INT32);
242 else
243 mValueKind = SK(INT64);
244 }
245 }
246 }
Yifan Hong57886972016-08-17 10:42:15 -0700247}
248
249/* Unary operations. */
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700250ConstantExpression::ConstantExpression(const char *op,
251 const ConstantExpression *value)
Yifan Hongf24fa852016-09-23 11:03:15 -0700252 : mExpr(std::string("(") + op + value->mExpr + ")"),
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700253 mType(kConstExprUnary),
254 mValueKind(value->mValueKind) {
Yifan Hongf24fa852016-09-23 11:03:15 -0700255
Yifan Hong57886972016-08-17 10:42:15 -0700256#define CASE_UNARY(__type__)\
257 mValue = handleUnary(op, static_cast<__type__>(value->mValue)); return;
258
Yifan Hongf24fa852016-09-23 11:03:15 -0700259 SWITCH_KIND(mValueKind, CASE_UNARY, SHOULD_NOT_REACH(); return;)
Yifan Hong52165692016-08-12 18:06:40 -0700260}
Yifan Hong57886972016-08-17 10:42:15 -0700261
262/* Binary operations. */
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700263ConstantExpression::ConstantExpression(const ConstantExpression *lval,
264 const char *op,
265 const ConstantExpression* rval)
Yifan Hongf24fa852016-09-23 11:03:15 -0700266 : mExpr(std::string("(") + lval->mExpr + " " + op + " " + rval->mExpr + ")"),
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700267 mType(kConstExprBinary)
Yifan Hong57886972016-08-17 10:42:15 -0700268{
Yifan Hong57886972016-08-17 10:42:15 -0700269
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700270 bool isArithmeticOrBitflip = OP_IS_BIN_ARITHMETIC || OP_IS_BIN_BITFLIP;
271
272 // CASE 1: + - * / % | ^ & < > <= >= == !=
273 if(isArithmeticOrBitflip || OP_IS_BIN_COMP) {
274 // promoted kind for both operands.
275 ScalarType::Kind promoted = usualArithmeticConversion(
276 integralPromotion(lval->mValueKind),
277 integralPromotion(rval->mValueKind));
278 // result kind.
279 mValueKind = isArithmeticOrBitflip
280 ? promoted // arithmetic or bitflip operators generates promoted type
281 : SK(BOOL); // comparison operators generates bool
282
283#define CASE_BINARY_COMMON(__type__)\
284 mValue = handleBinaryCommon(static_cast<__type__>(lval->mValue), op, static_cast<__type__>(rval->mValue)); return;
285
Yifan Hongf24fa852016-09-23 11:03:15 -0700286 SWITCH_KIND(promoted, CASE_BINARY_COMMON, SHOULD_NOT_REACH(); return;)
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700287 }
288
289 // CASE 2: << >>
290 if(OP_IS_BIN_SHIFT) {
291 mValueKind = integralPromotion(lval->mValueKind);
292 // instead of promoting rval, simply casting it to int64 should also be good.
293 int64_t numBits = rval->cast<int64_t>();
294 if(numBits < 0) {
295 // shifting with negative number of bits is undefined in C. In HIDL it
296 // is defined as shifting into the other direction.
297 op = OPEQ("<<") ? ">>" : "<<";
298 numBits = -numBits;
299 }
300
Yifan Hong57886972016-08-17 10:42:15 -0700301#define CASE_SHIFT(__type__)\
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700302 mValue = handleShift(static_cast<__type__>(lval->mValue), op, numBits); return;
Yifan Hong57886972016-08-17 10:42:15 -0700303
Yifan Hongf24fa852016-09-23 11:03:15 -0700304 SWITCH_KIND(mValueKind, CASE_SHIFT, SHOULD_NOT_REACH(); return;)
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700305 }
Yifan Hong57886972016-08-17 10:42:15 -0700306
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700307 // CASE 3: && ||
308 if(OP_IS_BIN_LOGICAL) {
309 mValueKind = SK(BOOL);
310 // easy; everything is bool.
311 mValue = handleLogical(lval->mValue, op, rval->mValue);
312 return;
313 }
Yifan Hong57886972016-08-17 10:42:15 -0700314
Yifan Hongf24fa852016-09-23 11:03:15 -0700315 SHOULD_NOT_REACH();
Yifan Hong57886972016-08-17 10:42:15 -0700316}
317
318/* Ternary ?: operation. */
Yifan Hong52165692016-08-12 18:06:40 -0700319ConstantExpression::ConstantExpression(const ConstantExpression *cond,
320 const ConstantExpression *trueVal,
321 const ConstantExpression *falseVal)
Yifan Hongf24fa852016-09-23 11:03:15 -0700322 : mExpr(std::string("(") + cond->mExpr + "?" + trueVal->mExpr
323 + ":" + falseVal->mExpr + ")"),
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700324 mType(kConstExprTernary) {
Yifan Hongf24fa852016-09-23 11:03:15 -0700325
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700326 // note: for ?:, unlike arithmetic ops, integral promotion is not necessary.
327 mValueKind = usualArithmeticConversion(trueVal->mValueKind,
328 falseVal->mValueKind);
Yifan Hong57886972016-08-17 10:42:15 -0700329
330#define CASE_TERNARY(__type__)\
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700331 mValue = cond->mValue ? (static_cast<__type__>(trueVal->mValue)) : (static_cast<__type__>(falseVal->mValue)); return;
Yifan Hong57886972016-08-17 10:42:15 -0700332
Yifan Hongf24fa852016-09-23 11:03:15 -0700333 SWITCH_KIND(mValueKind, CASE_TERNARY, SHOULD_NOT_REACH(); return;)
Yifan Hong52165692016-08-12 18:06:40 -0700334}
335
Yifan Hongf24fa852016-09-23 11:03:15 -0700336ConstantExpression ConstantExpression::addOne() const {
337 ConstantExpression myOne = ConstantExpression::One(mValueKind);
338 return ConstantExpression(this, "+", &myOne).toLiteral();
Yifan Hong52165692016-08-12 18:06:40 -0700339}
Yifan Hong57886972016-08-17 10:42:15 -0700340
Yifan Hongf24fa852016-09-23 11:03:15 -0700341ConstantExpression &ConstantExpression::toLiteral() {
342 mExpr = value();
343 mType = kConstExprLiteral;
344 return *this;
345}
346
347const std::string &ConstantExpression::description() const {
348 return mExpr;
Yifan Hong57886972016-08-17 10:42:15 -0700349}
350
Yifan Hong5706a432016-11-02 09:44:18 -0700351bool ConstantExpression::descriptionIsTrivial() const {
352 return mTrivialDescription;
353}
354
Yifan Hongfc610cd2016-09-22 13:34:45 -0700355std::string ConstantExpression::value() const {
Yifan Hongf24fa852016-09-23 11:03:15 -0700356 return rawValue(mValueKind);
357}
358
Yifan Hongc07b2022016-11-08 12:44:24 -0800359std::string ConstantExpression::value(ScalarType::Kind castKind) const {
360 return rawValue(castKind);
361}
362
Yifan Hongf24fa852016-09-23 11:03:15 -0700363std::string ConstantExpression::cppValue() const {
364 return cppValue(mValueKind);
Yifan Hong52165692016-08-12 18:06:40 -0700365}
366
Yifan Hongfc610cd2016-09-22 13:34:45 -0700367std::string ConstantExpression::cppValue(ScalarType::Kind castKind) const {
Yifan Hongf24fa852016-09-23 11:03:15 -0700368 std::string literal(rawValue(castKind));
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700369 // this is a hack to translate
370 // enum x : int64_t { y = 1l << 63 };
371 // into
372 // enum class x : int64_t { y = (int64_t)-9223372036854775808ull };
373 // by adding the explicit cast.
374 // Because 9223372036854775808 is uint64_t, and
375 // -(uint64_t)9223372036854775808 == 9223372036854775808 could not
376 // be narrowed to int64_t.
377 if(castKind == SK(INT64) && (int64_t)mValue == INT64_MIN) {
Yifan Hong3b320f82016-11-01 15:15:54 -0700378 return strdup(("static_cast<"
379 + ScalarType(SK(INT64)).getCppStackType() // "int64_t"
380 + ">(" + literal + "ull)").c_str());
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700381 }
Yifan Hong57886972016-08-17 10:42:15 -0700382
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700383 // add suffix if necessary.
384 if(castKind == SK(UINT32) || castKind == SK(UINT64)) literal += "u";
385 if(castKind == SK(UINT64) || castKind == SK(INT64)) literal += "ll";
Yifan Hongfc610cd2016-09-22 13:34:45 -0700386 return literal;
Yifan Hong57886972016-08-17 10:42:15 -0700387}
388
Yifan Hongf24fa852016-09-23 11:03:15 -0700389std::string ConstantExpression::javaValue() const {
390 return javaValue(mValueKind);
Yifan Hong19ca75a2016-08-31 10:20:03 -0700391}
392
Yifan Hongf24fa852016-09-23 11:03:15 -0700393std::string ConstantExpression::javaValue(ScalarType::Kind castKind) const {
394 switch(castKind) {
395 case SK(UINT64): return rawValue(SK(INT64)) + "L";
396 case SK(INT64): return rawValue(SK(INT64)) + "L";
397 case SK(UINT32): return rawValue(SK(INT32));
398 case SK(UINT16): return rawValue(SK(INT16));
399 case SK(UINT8) : return rawValue(SK(INT8));
400 case SK(BOOL) :
401 return this->cast<bool>() ? strdup("true") : strdup("false");
402 default: break;
403 }
404 return rawValue(castKind);
405}
406
407std::string ConstantExpression::rawValue(ScalarType::Kind castKind) const {
Yifan Hong57886972016-08-17 10:42:15 -0700408
Yifan Hongfc610cd2016-09-22 13:34:45 -0700409#define CASE_STR(__type__) return std::to_string(this->cast<__type__>());
Yifan Hong57886972016-08-17 10:42:15 -0700410
Yifan Hongf24fa852016-09-23 11:03:15 -0700411 SWITCH_KIND(castKind, CASE_STR, SHOULD_NOT_REACH(); return 0; );
Yifan Hong57886972016-08-17 10:42:15 -0700412}
413
Yifan Hong19ca75a2016-08-31 10:20:03 -0700414template<typename T>
415T ConstantExpression::cast() const {
Yifan Hong57886972016-08-17 10:42:15 -0700416
Yifan Hong19ca75a2016-08-31 10:20:03 -0700417#define CASE_CAST_T(__type__) return static_cast<T>(static_cast<__type__>(mValue));
Yifan Hong57886972016-08-17 10:42:15 -0700418
Yifan Hongf24fa852016-09-23 11:03:15 -0700419 SWITCH_KIND(mValueKind, CASE_CAST_T, SHOULD_NOT_REACH(); return 0; );
Yifan Hong57886972016-08-17 10:42:15 -0700420}
421
Yifan Honge77ca132016-09-27 10:49:05 -0700422size_t ConstantExpression::castSizeT() const {
423 return this->cast<size_t>();
424}
425
Yifan Hong57886972016-08-17 10:42:15 -0700426/*
427
428Evaluating expressions in HIDL language
429
430The following rules are mostly like that in:
431http://en.cppreference.com/w/cpp/language/operator_arithmetic
432http://en.cppreference.com/w/cpp/language/operator_logical
433http://en.cppreference.com/w/cpp/language/operator_comparison
434http://en.cppreference.com/w/cpp/language/operator_other
435
436The type of literal is the first type which the value
437can fit from the list of types depending on the suffix and bases.
438
439suffix decimal bases hexadecimal bases
440no suffix int32_t int32_t
441 int64_t uint32_t
442 int64_t
443 uint64_t
444
445u/U uint32_t (same as left)
446 uint64_t
447
448l/L int64_t int64_t
449
450ul/UL/uL/Ul uint64_t uint64_t
451
452
453Note: There are no negative integer literals.
454 -1 is the unary minus applied to 1.
455
456Unary arithmetic and bitwise operators (~ + -):
457 don't change the type of the argument.
458 (so -1u = -(1u) has type uint32_t)
459
460Binary arithmetic and bitwise operators (except shifts) (+ - * / % & | ^):
4611. Integral promotion is first applied on both sides.
4622. If both operands have the same type, no promotion is necessary.
4633. Usual arithmetic conversions.
464
465Integral promotion: if an operand is of a type with less than 32 bits,
466(including bool), it is promoted to int32_t.
467
468Usual arithmetic conversions:
4691. If operands are both signed or both unsigned, lesser conversion rank is
470 converted to greater conversion rank.
4712. Otherwise, if unsigned's rank >= signed's rank, -> unsigned's type
4723. Otherwise, if signed's type can hold all values in unsigned's type,
473 -> signed's type
4744. Otherwise, both converted to the unsigned counterpart of the signed operand's
475 type.
476rank: bool < int8_t < int16_t < int32_t < int64_t
477
478
479Shift operators (<< >>):
4801. Integral promotion is applied on both sides.
4812. For unsigned a, a << b discards bits that shifts out.
482 For signed non-negative a, a << b is legal if no bits shifts out, otherwise error.
483 For signed negative a, a << b gives error.
4843. For unsigned and signed non-negative a, a >> b discards bits that shifts out.
485 For signed negative a, a >> b discards bits that shifts out, and the signed
486 bit gets extended. ("arithmetic right shift")
4874. Shifting with negative number of bits is undefined. (Currently, the
488 parser will shift into the other direction. This behavior may change.)
4895. Shifting with number of bits exceeding the width of the type is undefined.
490 (Currently, 1 << 32 == 1. This behavior may change.)
491
492Logical operators (!, &&, ||):
4931. Convert first operand to bool. (true if non-zero, false otherwise)
4942. If short-circuited, return the result as type bool, value 1 or 0.
4953. Otherwise, convert second operand to bool, evaluate the result, and return
496 the result in the same fashion.
497
498Arithmetic comparison operators (< > <= >= == !=):
4991. Promote operands in the same way as binary arithmetic and bitwise operators.
500 (Integral promotion + Usual arithmetic conversions)
5012. Return type bool, value 0 or 1 the same way as logical operators.
502
503Ternary conditional operator (?:):
5041. Evaluate the conditional and evaluate the operands.
5052. Return type of expression is the type under usual arithmetic conversions on
506 the second and third operand. (No integral promotions necessary.)
507
508*/
509
Yifan Hong52165692016-08-12 18:06:40 -0700510} // namespace android
511