blob: eba28e1e46bf43504820dd36146c24c087eea461 [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
155ConstantExpression ConstantExpression::Zero(ScalarType::Kind kind) {
Yifan Hong30b5d1f2017-04-03 12:19:25 -0700156 ConstantExpression ce = ValueOf(kind, 0);
157 ce.mExpr = "0";
Yifan Hongf24fa852016-09-23 11:03:15 -0700158 return ce;
159}
160
Yifan Hong30b5d1f2017-04-03 12:19:25 -0700161ConstantExpression ConstantExpression::One(ScalarType::Kind kind) {
162 ConstantExpression ce = ValueOf(kind, 1);
163 ce.mExpr = "1";
164 return ce;
165}
166
Yifan Hong30b5d1f2017-04-03 12:19:25 -0700167ConstantExpression ConstantExpression::ValueOf(ScalarType::Kind kind, uint64_t value) {
168 ConstantExpression ce;
169 CHECK(isSupported(kind));
170
171 ce.mExpr = "";
172 ce.mType = kConstExprLiteral;
173 ce.mValueKind = kind;
174 ce.mValue = value;
175 ce.mTrivialDescription = true;
176 return ce;
177}
Yifan Hongf24fa852016-09-23 11:03:15 -0700178ConstantExpression::ConstantExpression(const ConstantExpression& other) {
179 *this = other;
180}
181
Yifan Hong5706a432016-11-02 09:44:18 -0700182/* Copy constructor, with the expr overriden and treated non-trivial */
Yifan Hongf24fa852016-09-23 11:03:15 -0700183ConstantExpression::ConstantExpression(const ConstantExpression& other, std::string expr) {
184 *this = other;
185 mExpr = expr;
Yifan Hong5706a432016-11-02 09:44:18 -0700186 mTrivialDescription = false;
Yifan Hongf24fa852016-09-23 11:03:15 -0700187}
188
189ConstantExpression& ConstantExpression::operator=(const ConstantExpression& other) {
190 mType = other.mType;
191 mValueKind = other.mValueKind;
192 mValue = other.mValue;
193 mExpr = other.mExpr;
Yifan Hong5706a432016-11-02 09:44:18 -0700194 mTrivialDescription = other.mTrivialDescription;
Yifan Hongf24fa852016-09-23 11:03:15 -0700195 return *this;
196}
197
Yifan Hong57886972016-08-17 10:42:15 -0700198/* Literals. */
Yifan Hongf24fa852016-09-23 11:03:15 -0700199ConstantExpression::ConstantExpression(const char *value)
Yifan Hong5706a432016-11-02 09:44:18 -0700200 : mExpr(value), mType(kConstExprLiteral), mTrivialDescription(true) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700201 const char* head = value, *tail = head + strlen(value) - 1;
202 bool isLong = false, isUnsigned = false;
203 bool isHex = (value[0] == '0' && (value[1] == 'x' || value[1] == 'X'));
204 while(tail >= head && (*tail == 'u' || *tail == 'U' || *tail == 'l' || *tail == 'L')) {
Yifan Hongf24fa852016-09-23 11:03:15 -0700205 isUnsigned |= (*tail == 'u' || *tail == 'U');
206 isLong |= (*tail == 'l' || *tail == 'L');
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700207 tail--;
Yifan Hong57886972016-08-17 10:42:15 -0700208 }
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700209 char *newVal = strndup(value, tail - head + 1);
210 bool parseOK = base::ParseUint(newVal, &mValue);
211 free(newVal);
Yifan Hongf24fa852016-09-23 11:03:15 -0700212 CHECK(parseOK) << "Could not parse as integer: " << value;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700213
214 // guess literal type.
215 if(isLong) {
216 if(isUnsigned) // ul
217 mValueKind = SK(UINT64);
218 else // l
219 mValueKind = SK(INT64);
220 } else { // no l suffix
221 if(isUnsigned) { // u
222 if(mValue <= UINT32_MAX)
223 mValueKind = SK(UINT32);
224 else
225 mValueKind = SK(UINT64);
226 } else { // no suffix
227 if(isHex) {
228 if(mValue <= INT32_MAX) // mValue always >= 0
229 mValueKind = SK(INT32);
230 else if(mValue <= UINT32_MAX)
231 mValueKind = SK(UINT32);
232 else if(mValue <= INT64_MAX) // mValue always >= 0
233 mValueKind = SK(INT64);
234 else if(mValue <= UINT64_MAX)
235 mValueKind = SK(UINT64);
236 } else {
237 if(mValue <= INT32_MAX) // mValue always >= 0
238 mValueKind = SK(INT32);
239 else
240 mValueKind = SK(INT64);
241 }
242 }
243 }
Yifan Hong57886972016-08-17 10:42:15 -0700244}
245
246/* Unary operations. */
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700247ConstantExpression::ConstantExpression(const char *op,
248 const ConstantExpression *value)
Yifan Hongf24fa852016-09-23 11:03:15 -0700249 : mExpr(std::string("(") + op + value->mExpr + ")"),
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700250 mType(kConstExprUnary),
251 mValueKind(value->mValueKind) {
Yifan Hongf24fa852016-09-23 11:03:15 -0700252
Yifan Hong57886972016-08-17 10:42:15 -0700253#define CASE_UNARY(__type__)\
254 mValue = handleUnary(op, static_cast<__type__>(value->mValue)); return;
255
Yifan Hongf24fa852016-09-23 11:03:15 -0700256 SWITCH_KIND(mValueKind, CASE_UNARY, SHOULD_NOT_REACH(); return;)
Yifan Hong52165692016-08-12 18:06:40 -0700257}
Yifan Hong57886972016-08-17 10:42:15 -0700258
259/* Binary operations. */
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700260ConstantExpression::ConstantExpression(const ConstantExpression *lval,
261 const char *op,
262 const ConstantExpression* rval)
Yifan Hongf24fa852016-09-23 11:03:15 -0700263 : mExpr(std::string("(") + lval->mExpr + " " + op + " " + rval->mExpr + ")"),
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700264 mType(kConstExprBinary)
Yifan Hong57886972016-08-17 10:42:15 -0700265{
Yifan Hong57886972016-08-17 10:42:15 -0700266
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700267 bool isArithmeticOrBitflip = OP_IS_BIN_ARITHMETIC || OP_IS_BIN_BITFLIP;
268
269 // CASE 1: + - * / % | ^ & < > <= >= == !=
270 if(isArithmeticOrBitflip || OP_IS_BIN_COMP) {
271 // promoted kind for both operands.
272 ScalarType::Kind promoted = usualArithmeticConversion(
273 integralPromotion(lval->mValueKind),
274 integralPromotion(rval->mValueKind));
275 // result kind.
276 mValueKind = isArithmeticOrBitflip
277 ? promoted // arithmetic or bitflip operators generates promoted type
278 : SK(BOOL); // comparison operators generates bool
279
280#define CASE_BINARY_COMMON(__type__)\
281 mValue = handleBinaryCommon(static_cast<__type__>(lval->mValue), op, static_cast<__type__>(rval->mValue)); return;
282
Yifan Hongf24fa852016-09-23 11:03:15 -0700283 SWITCH_KIND(promoted, CASE_BINARY_COMMON, SHOULD_NOT_REACH(); return;)
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700284 }
285
286 // CASE 2: << >>
287 if(OP_IS_BIN_SHIFT) {
288 mValueKind = integralPromotion(lval->mValueKind);
289 // instead of promoting rval, simply casting it to int64 should also be good.
290 int64_t numBits = rval->cast<int64_t>();
291 if(numBits < 0) {
292 // shifting with negative number of bits is undefined in C. In HIDL it
293 // is defined as shifting into the other direction.
294 op = OPEQ("<<") ? ">>" : "<<";
295 numBits = -numBits;
296 }
297
Yifan Hong57886972016-08-17 10:42:15 -0700298#define CASE_SHIFT(__type__)\
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700299 mValue = handleShift(static_cast<__type__>(lval->mValue), op, numBits); return;
Yifan Hong57886972016-08-17 10:42:15 -0700300
Yifan Hongf24fa852016-09-23 11:03:15 -0700301 SWITCH_KIND(mValueKind, CASE_SHIFT, SHOULD_NOT_REACH(); return;)
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700302 }
Yifan Hong57886972016-08-17 10:42:15 -0700303
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700304 // CASE 3: && ||
305 if(OP_IS_BIN_LOGICAL) {
306 mValueKind = SK(BOOL);
307 // easy; everything is bool.
308 mValue = handleLogical(lval->mValue, op, rval->mValue);
309 return;
310 }
Yifan Hong57886972016-08-17 10:42:15 -0700311
Yifan Hongf24fa852016-09-23 11:03:15 -0700312 SHOULD_NOT_REACH();
Yifan Hong57886972016-08-17 10:42:15 -0700313}
314
315/* Ternary ?: operation. */
Yifan Hong52165692016-08-12 18:06:40 -0700316ConstantExpression::ConstantExpression(const ConstantExpression *cond,
317 const ConstantExpression *trueVal,
318 const ConstantExpression *falseVal)
Yifan Hongf24fa852016-09-23 11:03:15 -0700319 : mExpr(std::string("(") + cond->mExpr + "?" + trueVal->mExpr
320 + ":" + falseVal->mExpr + ")"),
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700321 mType(kConstExprTernary) {
Yifan Hongf24fa852016-09-23 11:03:15 -0700322
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700323 // note: for ?:, unlike arithmetic ops, integral promotion is not necessary.
324 mValueKind = usualArithmeticConversion(trueVal->mValueKind,
325 falseVal->mValueKind);
Yifan Hong57886972016-08-17 10:42:15 -0700326
327#define CASE_TERNARY(__type__)\
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700328 mValue = cond->mValue ? (static_cast<__type__>(trueVal->mValue)) : (static_cast<__type__>(falseVal->mValue)); return;
Yifan Hong57886972016-08-17 10:42:15 -0700329
Yifan Hongf24fa852016-09-23 11:03:15 -0700330 SWITCH_KIND(mValueKind, CASE_TERNARY, SHOULD_NOT_REACH(); return;)
Yifan Hong52165692016-08-12 18:06:40 -0700331}
332
Yifan Hongf24fa852016-09-23 11:03:15 -0700333ConstantExpression ConstantExpression::addOne() const {
334 ConstantExpression myOne = ConstantExpression::One(mValueKind);
335 return ConstantExpression(this, "+", &myOne).toLiteral();
Yifan Hong52165692016-08-12 18:06:40 -0700336}
Yifan Hong57886972016-08-17 10:42:15 -0700337
Yifan Hongf24fa852016-09-23 11:03:15 -0700338ConstantExpression &ConstantExpression::toLiteral() {
339 mExpr = value();
340 mType = kConstExprLiteral;
341 return *this;
342}
343
344const std::string &ConstantExpression::description() const {
345 return mExpr;
Yifan Hong57886972016-08-17 10:42:15 -0700346}
347
Yifan Hong5706a432016-11-02 09:44:18 -0700348bool ConstantExpression::descriptionIsTrivial() const {
349 return mTrivialDescription;
350}
351
Yifan Hongfc610cd2016-09-22 13:34:45 -0700352std::string ConstantExpression::value() const {
Yifan Hongf24fa852016-09-23 11:03:15 -0700353 return rawValue(mValueKind);
354}
355
Yifan Hongc07b2022016-11-08 12:44:24 -0800356std::string ConstantExpression::value(ScalarType::Kind castKind) const {
357 return rawValue(castKind);
358}
359
Yifan Hongf24fa852016-09-23 11:03:15 -0700360std::string ConstantExpression::cppValue() const {
361 return cppValue(mValueKind);
Yifan Hong52165692016-08-12 18:06:40 -0700362}
363
Yifan Hongfc610cd2016-09-22 13:34:45 -0700364std::string ConstantExpression::cppValue(ScalarType::Kind castKind) const {
Yifan Hongf24fa852016-09-23 11:03:15 -0700365 std::string literal(rawValue(castKind));
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700366 // this is a hack to translate
367 // enum x : int64_t { y = 1l << 63 };
368 // into
369 // enum class x : int64_t { y = (int64_t)-9223372036854775808ull };
370 // by adding the explicit cast.
371 // Because 9223372036854775808 is uint64_t, and
372 // -(uint64_t)9223372036854775808 == 9223372036854775808 could not
373 // be narrowed to int64_t.
374 if(castKind == SK(INT64) && (int64_t)mValue == INT64_MIN) {
Yifan Hong3b320f82016-11-01 15:15:54 -0700375 return strdup(("static_cast<"
376 + ScalarType(SK(INT64)).getCppStackType() // "int64_t"
377 + ">(" + literal + "ull)").c_str());
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700378 }
Yifan Hong57886972016-08-17 10:42:15 -0700379
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700380 // add suffix if necessary.
381 if(castKind == SK(UINT32) || castKind == SK(UINT64)) literal += "u";
382 if(castKind == SK(UINT64) || castKind == SK(INT64)) literal += "ll";
Yifan Hongfc610cd2016-09-22 13:34:45 -0700383 return literal;
Yifan Hong57886972016-08-17 10:42:15 -0700384}
385
Yifan Hongf24fa852016-09-23 11:03:15 -0700386std::string ConstantExpression::javaValue() const {
387 return javaValue(mValueKind);
Yifan Hong19ca75a2016-08-31 10:20:03 -0700388}
389
Yifan Hongf24fa852016-09-23 11:03:15 -0700390std::string ConstantExpression::javaValue(ScalarType::Kind castKind) const {
391 switch(castKind) {
392 case SK(UINT64): return rawValue(SK(INT64)) + "L";
393 case SK(INT64): return rawValue(SK(INT64)) + "L";
394 case SK(UINT32): return rawValue(SK(INT32));
395 case SK(UINT16): return rawValue(SK(INT16));
396 case SK(UINT8) : return rawValue(SK(INT8));
397 case SK(BOOL) :
398 return this->cast<bool>() ? strdup("true") : strdup("false");
399 default: break;
400 }
401 return rawValue(castKind);
402}
403
404std::string ConstantExpression::rawValue(ScalarType::Kind castKind) const {
Yifan Hong57886972016-08-17 10:42:15 -0700405
Yifan Hongfc610cd2016-09-22 13:34:45 -0700406#define CASE_STR(__type__) return std::to_string(this->cast<__type__>());
Yifan Hong57886972016-08-17 10:42:15 -0700407
Yifan Hongf24fa852016-09-23 11:03:15 -0700408 SWITCH_KIND(castKind, CASE_STR, SHOULD_NOT_REACH(); return 0; );
Yifan Hong57886972016-08-17 10:42:15 -0700409}
410
Yifan Hong19ca75a2016-08-31 10:20:03 -0700411template<typename T>
412T ConstantExpression::cast() const {
Yifan Hong57886972016-08-17 10:42:15 -0700413
Yifan Hong19ca75a2016-08-31 10:20:03 -0700414#define CASE_CAST_T(__type__) return static_cast<T>(static_cast<__type__>(mValue));
Yifan Hong57886972016-08-17 10:42:15 -0700415
Yifan Hongf24fa852016-09-23 11:03:15 -0700416 SWITCH_KIND(mValueKind, CASE_CAST_T, SHOULD_NOT_REACH(); return 0; );
Yifan Hong57886972016-08-17 10:42:15 -0700417}
418
Yifan Honge77ca132016-09-27 10:49:05 -0700419size_t ConstantExpression::castSizeT() const {
420 return this->cast<size_t>();
421}
422
Yifan Hong57886972016-08-17 10:42:15 -0700423/*
424
425Evaluating expressions in HIDL language
426
427The following rules are mostly like that in:
428http://en.cppreference.com/w/cpp/language/operator_arithmetic
429http://en.cppreference.com/w/cpp/language/operator_logical
430http://en.cppreference.com/w/cpp/language/operator_comparison
431http://en.cppreference.com/w/cpp/language/operator_other
432
433The type of literal is the first type which the value
434can fit from the list of types depending on the suffix and bases.
435
436suffix decimal bases hexadecimal bases
437no suffix int32_t int32_t
438 int64_t uint32_t
439 int64_t
440 uint64_t
441
442u/U uint32_t (same as left)
443 uint64_t
444
445l/L int64_t int64_t
446
447ul/UL/uL/Ul uint64_t uint64_t
448
449
450Note: There are no negative integer literals.
451 -1 is the unary minus applied to 1.
452
453Unary arithmetic and bitwise operators (~ + -):
454 don't change the type of the argument.
455 (so -1u = -(1u) has type uint32_t)
456
457Binary arithmetic and bitwise operators (except shifts) (+ - * / % & | ^):
4581. Integral promotion is first applied on both sides.
4592. If both operands have the same type, no promotion is necessary.
4603. Usual arithmetic conversions.
461
462Integral promotion: if an operand is of a type with less than 32 bits,
463(including bool), it is promoted to int32_t.
464
465Usual arithmetic conversions:
4661. If operands are both signed or both unsigned, lesser conversion rank is
467 converted to greater conversion rank.
4682. Otherwise, if unsigned's rank >= signed's rank, -> unsigned's type
4693. Otherwise, if signed's type can hold all values in unsigned's type,
470 -> signed's type
4714. Otherwise, both converted to the unsigned counterpart of the signed operand's
472 type.
473rank: bool < int8_t < int16_t < int32_t < int64_t
474
475
476Shift operators (<< >>):
4771. Integral promotion is applied on both sides.
4782. For unsigned a, a << b discards bits that shifts out.
479 For signed non-negative a, a << b is legal if no bits shifts out, otherwise error.
480 For signed negative a, a << b gives error.
4813. For unsigned and signed non-negative a, a >> b discards bits that shifts out.
482 For signed negative a, a >> b discards bits that shifts out, and the signed
483 bit gets extended. ("arithmetic right shift")
4844. Shifting with negative number of bits is undefined. (Currently, the
485 parser will shift into the other direction. This behavior may change.)
4865. Shifting with number of bits exceeding the width of the type is undefined.
487 (Currently, 1 << 32 == 1. This behavior may change.)
488
489Logical operators (!, &&, ||):
4901. Convert first operand to bool. (true if non-zero, false otherwise)
4912. If short-circuited, return the result as type bool, value 1 or 0.
4923. Otherwise, convert second operand to bool, evaluate the result, and return
493 the result in the same fashion.
494
495Arithmetic comparison operators (< > <= >= == !=):
4961. Promote operands in the same way as binary arithmetic and bitwise operators.
497 (Integral promotion + Usual arithmetic conversions)
4982. Return type bool, value 0 or 1 the same way as logical operators.
499
500Ternary conditional operator (?:):
5011. Evaluate the conditional and evaluate the operands.
5022. Return type of expression is the type under usual arithmetic conversions on
503 the second and third operand. (No integral promotions necessary.)
504
505*/
506
Yifan Hong52165692016-08-12 18:06:40 -0700507} // namespace android
508