Revert "Revert "ConstantExpression lazy evaluation""
This reverts commit a549b71629b6bc28ac1d99d34a0f3b3005c90aad.
Reason for revert: mac build issue fixed by adding virtual destructor
Test: builds, hidl_test
Test: builds on mac
Bug: 64532323
Change-Id: I10a142649bc1eb304b267372129e850235004f6e
diff --git a/ConstantExpression.cpp b/ConstantExpression.cpp
index eba28e1..fe0ff4c 100644
--- a/ConstantExpression.cpp
+++ b/ConstantExpression.cpp
@@ -23,12 +23,12 @@
#include <sstream>
#include "EnumType.h"
+#include "Scope.h" // LocalIdentifier
// The macros are really nasty here. Consider removing
// as many macros as possible.
-#define STREQ(__x__, __y__) (strcmp((__x__), (__y__)) == 0)
-#define OPEQ(__y__) STREQ(op, __y__)
+#define OPEQ(__y__) (std::string(op) == std::string(__y__))
#define COMPUTE_UNARY(__op__) if(OPEQ(#__op__)) return __op__ val;
#define COMPUTE_BINARY(__op__) if(OPEQ(#__op__)) return lval __op__ rval;
#define OP_IS_BIN_ARITHMETIC (OPEQ("+") || OPEQ("-") || OPEQ("*") || OPEQ("/") || OPEQ("%"))
@@ -96,7 +96,7 @@
}
template <class T>
-T handleUnary(const char *op, T val) {
+T handleUnary(const std::string& op, T val) {
COMPUTE_UNARY(+)
COMPUTE_UNARY(-)
COMPUTE_UNARY(!)
@@ -107,7 +107,7 @@
}
template <class T>
-T handleBinaryCommon(T lval, const char *op, T rval) {
+T handleBinaryCommon(T lval, const std::string& op, T rval) {
COMPUTE_BINARY(+)
COMPUTE_BINARY(-)
COMPUTE_BINARY(*)
@@ -130,7 +130,7 @@
}
template <class T>
-T handleShift(T lval, const char *op, int64_t rval) {
+T handleShift(T lval, const std::string& op, int64_t rval) {
// just cast rval to int64_t and it should fit.
COMPUTE_BINARY(>>)
COMPUTE_BINARY(<<)
@@ -140,7 +140,7 @@
return static_cast<T>(0xdeadbeef);
}
-bool handleLogical(bool lval, const char *op, bool rval) {
+bool handleLogical(bool lval, const std::string& op, bool rval) {
COMPUTE_BINARY(||);
COMPUTE_BINARY(&&);
// Should not reach here.
@@ -149,66 +149,51 @@
return false;
}
-ConstantExpression::ConstantExpression() {
+std::unique_ptr<ConstantExpression> ConstantExpression::Zero(ScalarType::Kind kind) {
+ return ValueOf(kind, 0);
}
-ConstantExpression ConstantExpression::Zero(ScalarType::Kind kind) {
- ConstantExpression ce = ValueOf(kind, 0);
- ce.mExpr = "0";
- return ce;
+std::unique_ptr<ConstantExpression> ConstantExpression::One(ScalarType::Kind kind) {
+ return ValueOf(kind, 1);
}
-ConstantExpression ConstantExpression::One(ScalarType::Kind kind) {
- ConstantExpression ce = ValueOf(kind, 1);
- ce.mExpr = "1";
- return ce;
+std::unique_ptr<ConstantExpression> ConstantExpression::ValueOf(ScalarType::Kind kind,
+ uint64_t value) {
+ return std::make_unique<LiteralConstantExpression>(kind, value);
}
-ConstantExpression ConstantExpression::ValueOf(ScalarType::Kind kind, uint64_t value) {
- ConstantExpression ce;
+bool ConstantExpression::isEvaluated() const {
+ return mIsEvaluated;
+}
+
+LiteralConstantExpression::LiteralConstantExpression(ScalarType::Kind kind, uint64_t value) {
CHECK(isSupported(kind));
-
- ce.mExpr = "";
- ce.mType = kConstExprLiteral;
- ce.mValueKind = kind;
- ce.mValue = value;
- ce.mTrivialDescription = true;
- return ce;
-}
-ConstantExpression::ConstantExpression(const ConstantExpression& other) {
- *this = other;
+ mTrivialDescription = true;
+ mExpr = std::to_string(value);
+ mValueKind = kind;
+ mValue = value;
+ mIsEvaluated = true;
}
-/* Copy constructor, with the expr overriden and treated non-trivial */
-ConstantExpression::ConstantExpression(const ConstantExpression& other, std::string expr) {
- *this = other;
- mExpr = expr;
- mTrivialDescription = false;
-}
+LiteralConstantExpression::LiteralConstantExpression(const std::string& value) {
+ CHECK(!value.empty());
+ mIsEvaluated = true;
+ mTrivialDescription = true;
+ mExpr = value;
-ConstantExpression& ConstantExpression::operator=(const ConstantExpression& other) {
- mType = other.mType;
- mValueKind = other.mValueKind;
- mValue = other.mValue;
- mExpr = other.mExpr;
- mTrivialDescription = other.mTrivialDescription;
- return *this;
-}
-
-/* Literals. */
-ConstantExpression::ConstantExpression(const char *value)
- : mExpr(value), mType(kConstExprLiteral), mTrivialDescription(true) {
- const char* head = value, *tail = head + strlen(value) - 1;
bool isLong = false, isUnsigned = false;
- bool isHex = (value[0] == '0' && (value[1] == 'x' || value[1] == 'X'));
- while(tail >= head && (*tail == 'u' || *tail == 'U' || *tail == 'l' || *tail == 'L')) {
- isUnsigned |= (*tail == 'u' || *tail == 'U');
- isLong |= (*tail == 'l' || *tail == 'L');
- tail--;
+ bool isHex = (value[0] == '0' && value.length() > 1 && (value[1] == 'x' || value[1] == 'X'));
+
+ auto rbegin = value.rbegin();
+ auto rend = value.rend();
+ for (; rbegin != rend && (*rbegin == 'u' || *rbegin == 'U' || *rbegin == 'l' || *rbegin == 'L');
+ ++rbegin) {
+ isUnsigned |= (*rbegin == 'u' || *rbegin == 'U');
+ isLong |= (*rbegin == 'l' || *rbegin == 'L');
}
- char *newVal = strndup(value, tail - head + 1);
+ std::string newVal(value.begin(), rbegin.base());
+ CHECK(!newVal.empty());
bool parseOK = base::ParseUint(newVal, &mValue);
- free(newVal);
CHECK(parseOK) << "Could not parse as integer: " << value;
// guess literal type.
@@ -243,47 +228,56 @@
}
}
-/* Unary operations. */
-ConstantExpression::ConstantExpression(const char *op,
- const ConstantExpression *value)
- : mExpr(std::string("(") + op + value->mExpr + ")"),
- mType(kConstExprUnary),
- mValueKind(value->mValueKind) {
+void LiteralConstantExpression::evaluate() {
+ // Evaluated in constructor
+ CHECK(isEvaluated());
+}
-#define CASE_UNARY(__type__)\
- mValue = handleUnary(op, static_cast<__type__>(value->mValue)); return;
+void UnaryConstantExpression::evaluate() {
+ if (isEvaluated()) return;
+ value->evaluate();
+ mIsEvaluated = true;
+
+ mExpr = std::string("(") + op + value->description() + ")";
+ mValueKind = value->mValueKind;
+
+#define CASE_UNARY(__type__) \
+ mValue = handleUnary(op, static_cast<__type__>(value->mValue)); \
+ return;
SWITCH_KIND(mValueKind, CASE_UNARY, SHOULD_NOT_REACH(); return;)
}
-/* Binary operations. */
-ConstantExpression::ConstantExpression(const ConstantExpression *lval,
- const char *op,
- const ConstantExpression* rval)
- : mExpr(std::string("(") + lval->mExpr + " " + op + " " + rval->mExpr + ")"),
- mType(kConstExprBinary)
-{
+void BinaryConstantExpression::evaluate() {
+ if (isEvaluated()) return;
+ lval->evaluate();
+ rval->evaluate();
+ mIsEvaluated = true;
+
+ mExpr = std::string("(") + lval->description() + " " + op + " " + rval->description() + ")";
bool isArithmeticOrBitflip = OP_IS_BIN_ARITHMETIC || OP_IS_BIN_BITFLIP;
// CASE 1: + - * / % | ^ & < > <= >= == !=
if(isArithmeticOrBitflip || OP_IS_BIN_COMP) {
// promoted kind for both operands.
- ScalarType::Kind promoted = usualArithmeticConversion(
- integralPromotion(lval->mValueKind),
- integralPromotion(rval->mValueKind));
+ ScalarType::Kind promoted = usualArithmeticConversion(integralPromotion(lval->mValueKind),
+ integralPromotion(rval->mValueKind));
// result kind.
mValueKind = isArithmeticOrBitflip
? promoted // arithmetic or bitflip operators generates promoted type
: SK(BOOL); // comparison operators generates bool
-#define CASE_BINARY_COMMON(__type__)\
- mValue = handleBinaryCommon(static_cast<__type__>(lval->mValue), op, static_cast<__type__>(rval->mValue)); return;
+#define CASE_BINARY_COMMON(__type__) \
+ mValue = handleBinaryCommon(static_cast<__type__>(lval->mValue), op, \
+ static_cast<__type__>(rval->mValue)); \
+ return;
SWITCH_KIND(promoted, CASE_BINARY_COMMON, SHOULD_NOT_REACH(); return;)
}
// CASE 2: << >>
+ std::string newOp = op;
if(OP_IS_BIN_SHIFT) {
mValueKind = integralPromotion(lval->mValueKind);
// instead of promoting rval, simply casting it to int64 should also be good.
@@ -291,12 +285,13 @@
if(numBits < 0) {
// shifting with negative number of bits is undefined in C. In HIDL it
// is defined as shifting into the other direction.
- op = OPEQ("<<") ? ">>" : "<<";
+ newOp = OPEQ("<<") ? std::string(">>") : std::string("<<");
numBits = -numBits;
}
-#define CASE_SHIFT(__type__)\
- mValue = handleShift(static_cast<__type__>(lval->mValue), op, numBits); return;
+#define CASE_SHIFT(__type__) \
+ mValue = handleShift(static_cast<__type__>(lval->mValue), newOp, numBits); \
+ return;
SWITCH_KIND(mValueKind, CASE_SHIFT, SHOULD_NOT_REACH(); return;)
}
@@ -312,56 +307,73 @@
SHOULD_NOT_REACH();
}
-/* Ternary ?: operation. */
-ConstantExpression::ConstantExpression(const ConstantExpression *cond,
- const ConstantExpression *trueVal,
- const ConstantExpression *falseVal)
- : mExpr(std::string("(") + cond->mExpr + "?" + trueVal->mExpr
- + ":" + falseVal->mExpr + ")"),
- mType(kConstExprTernary) {
+void TernaryConstantExpression::evaluate() {
+ if (isEvaluated()) return;
+ cond->evaluate();
+ trueVal->evaluate();
+ falseVal->evaluate();
+ mIsEvaluated = true;
+
+ mExpr = std::string("(") + cond->description() + "?" + trueVal->description() + ":" +
+ falseVal->description() + ")";
// note: for ?:, unlike arithmetic ops, integral promotion is not necessary.
- mValueKind = usualArithmeticConversion(trueVal->mValueKind,
- falseVal->mValueKind);
+ mValueKind = usualArithmeticConversion(trueVal->mValueKind, falseVal->mValueKind);
-#define CASE_TERNARY(__type__)\
- mValue = cond->mValue ? (static_cast<__type__>(trueVal->mValue)) : (static_cast<__type__>(falseVal->mValue)); return;
+#define CASE_TERNARY(__type__) \
+ mValue = cond->mValue ? (static_cast<__type__>(trueVal->mValue)) \
+ : (static_cast<__type__>(falseVal->mValue)); \
+ return;
SWITCH_KIND(mValueKind, CASE_TERNARY, SHOULD_NOT_REACH(); return;)
}
-ConstantExpression ConstantExpression::addOne() const {
- ConstantExpression myOne = ConstantExpression::One(mValueKind);
- return ConstantExpression(this, "+", &myOne).toLiteral();
+void ReferenceConstantExpression::evaluate() {
+ if (isEvaluated()) return;
+
+ ConstantExpression* expr = value->constExpr();
+ CHECK(expr != nullptr);
+ expr->evaluate();
+
+ mValueKind = expr->mValueKind;
+ mValue = expr->mValue;
+ mIsEvaluated = true;
}
-ConstantExpression &ConstantExpression::toLiteral() {
- mExpr = value();
- mType = kConstExprLiteral;
- return *this;
+std::unique_ptr<ConstantExpression> ConstantExpression::addOne(ScalarType::Kind baseKind) {
+ auto ret = std::make_unique<BinaryConstantExpression>(
+ this, "+", ConstantExpression::One(baseKind).release());
+ ret->mTrivialDescription = true;
+ return ret;
}
-const std::string &ConstantExpression::description() const {
+const std::string& ConstantExpression::description() const {
+ CHECK(isEvaluated());
return mExpr;
}
bool ConstantExpression::descriptionIsTrivial() const {
+ CHECK(isEvaluated());
return mTrivialDescription;
}
std::string ConstantExpression::value() const {
+ CHECK(isEvaluated());
return rawValue(mValueKind);
}
std::string ConstantExpression::value(ScalarType::Kind castKind) const {
+ CHECK(isEvaluated());
return rawValue(castKind);
}
std::string ConstantExpression::cppValue() const {
+ CHECK(isEvaluated());
return cppValue(mValueKind);
}
std::string ConstantExpression::cppValue(ScalarType::Kind castKind) const {
+ CHECK(isEvaluated());
std::string literal(rawValue(castKind));
// this is a hack to translate
// enum x : int64_t { y = 1l << 63 };
@@ -384,10 +396,12 @@
}
std::string ConstantExpression::javaValue() const {
+ CHECK(isEvaluated());
return javaValue(mValueKind);
}
std::string ConstantExpression::javaValue(ScalarType::Kind castKind) const {
+ CHECK(isEvaluated());
switch(castKind) {
case SK(UINT64): return rawValue(SK(INT64)) + "L";
case SK(INT64): return rawValue(SK(INT64)) + "L";
@@ -402,6 +416,7 @@
}
std::string ConstantExpression::rawValue(ScalarType::Kind castKind) const {
+ CHECK(isEvaluated());
#define CASE_STR(__type__) return std::to_string(this->cast<__type__>());
@@ -410,6 +425,7 @@
template<typename T>
T ConstantExpression::cast() const {
+ CHECK(isEvaluated());
#define CASE_CAST_T(__type__) return static_cast<T>(static_cast<__type__>(mValue));
@@ -417,9 +433,28 @@
}
size_t ConstantExpression::castSizeT() const {
+ CHECK(isEvaluated());
return this->cast<size_t>();
}
+UnaryConstantExpression::UnaryConstantExpression(const std::string& op, ConstantExpression* value)
+ : value(value), op(op) {}
+
+BinaryConstantExpression::BinaryConstantExpression(ConstantExpression* lval, const std::string& op,
+ ConstantExpression* rval)
+ : lval(lval), rval(rval), op(op) {}
+
+TernaryConstantExpression::TernaryConstantExpression(ConstantExpression* cond,
+ ConstantExpression* trueVal,
+ ConstantExpression* falseVal)
+ : cond(cond), trueVal(trueVal), falseVal(falseVal) {}
+
+ReferenceConstantExpression::ReferenceConstantExpression(const Reference<LocalIdentifier>& value,
+ const std::string& expr)
+ : value(value) {
+ mExpr = expr;
+}
+
/*
Evaluating expressions in HIDL language
diff --git a/ConstantExpression.h b/ConstantExpression.h
index 2c955d4..a6648bb 100644
--- a/ConstantExpression.h
+++ b/ConstantExpression.h
@@ -19,45 +19,41 @@
#define CONSTANT_EXPRESSION_H_
#include <android-base/macros.h>
+#include <memory>
#include <string>
+
+#include "Reference.h"
#include "ScalarType.h"
namespace android {
+struct LocalIdentifier;
+
+struct LiteralConstantExpression;
+struct UnaryConstantExpression;
+struct BinaryConstantExpression;
+struct TernaryConstantExpression;
+struct ReferenceConstantExpression;
+
/**
* A constant expression is represented by a tree.
*/
struct ConstantExpression {
+ static std::unique_ptr<ConstantExpression> Zero(ScalarType::Kind kind);
+ static std::unique_ptr<ConstantExpression> One(ScalarType::Kind kind);
+ static std::unique_ptr<ConstantExpression> ValueOf(ScalarType::Kind kind, uint64_t value);
- enum ConstExprType {
- kConstExprLiteral,
- kConstExprUnary,
- kConstExprBinary,
- kConstExprTernary
- };
+ virtual ~ConstantExpression() {}
- /* Default constructor. */
- ConstantExpression();
- /* Copy constructor. */
- ConstantExpression(const ConstantExpression& other);
- /* Copy constructor, with the expr overriden. */
- ConstantExpression(const ConstantExpression& other, std::string expr);
- /* Literals */
- ConstantExpression(const char *value);
- /* binary operations */
- ConstantExpression(const ConstantExpression *value1,
- const char *op, const ConstantExpression* value2);
- /* unary operations */
- ConstantExpression(const char *op, const ConstantExpression *value);
- /* ternary ?: */
- ConstantExpression(const ConstantExpression *cond,
- const ConstantExpression *trueVal,
- const ConstantExpression *falseVal);
+ /*
+ * Runs recursive evaluation.
+ * Provides sort of lazy computation,
+ * mainly used for forward identifier reference.
+ */
+ virtual void evaluate() = 0;
- static ConstantExpression Zero(ScalarType::Kind kind);
- static ConstantExpression One(ScalarType::Kind kind);
- static ConstantExpression ValueOf(ScalarType::Kind kind, uint64_t value);
-
+ /* Returns true iff the value has already been evaluated. */
+ bool isEvaluated() const;
/* Evaluated result in a string form. */
std::string value() const;
/* Evaluated result in a string form. */
@@ -70,22 +66,21 @@
std::string cppValue(ScalarType::Kind castKind) const;
/* Evaluated result in a string form, with given contextual kind. */
std::string javaValue(ScalarType::Kind castKind) const;
- /* Original expression with type. */
- const std::string &description() const;
+ /* Formatted expression with type. */
+ const std::string& description() const;
/* See mTrivialDescription */
bool descriptionIsTrivial() const;
/* Return a ConstantExpression that is 1 plus the original. */
- ConstantExpression addOne() const;
- /* Assignment operator. */
- ConstantExpression& operator=(const ConstantExpression& other);
+ std::unique_ptr<ConstantExpression> addOne(ScalarType::Kind baseKind);
size_t castSizeT() const;
-private:
+ private:
+ /* If the result value has been evaluated. */
+ bool mIsEvaluated = false;
+
/* The formatted expression. */
std::string mExpr;
- /* The type of the expression. Hints on its original form. */
- ConstExprType mType;
/* The kind of the result value. */
ScalarType::Kind mValueKind;
/* The stored result value. */
@@ -99,15 +94,65 @@
* digits) converted from mValue.
*/
std::string rawValue(ScalarType::Kind castKind) const;
- /* Trim unnecessary information. Only mValue and mValueKind is kept. */
- ConstantExpression &toLiteral();
/*
* Return the value casted to the given type.
* First cast it according to mValueKind, then cast it to T.
* Assumes !containsIdentifiers()
*/
- template <typename T> T cast() const;
+ template <typename T>
+ T cast() const;
+
+ friend struct LiteralConstantExpression;
+ friend struct UnaryConstantExpression;
+ friend struct BinaryConstantExpression;
+ friend struct TernaryConstantExpression;
+ friend struct ReferenceConstantExpression;
+};
+
+struct LiteralConstantExpression : public ConstantExpression {
+ LiteralConstantExpression(ScalarType::Kind kind, uint64_t value);
+ LiteralConstantExpression(const std::string& value);
+ void evaluate() override;
+};
+
+struct UnaryConstantExpression : public ConstantExpression {
+ UnaryConstantExpression(const std::string& op, ConstantExpression* value);
+ void evaluate() override;
+
+ private:
+ ConstantExpression* const value;
+ std::string op;
+};
+
+struct BinaryConstantExpression : public ConstantExpression {
+ BinaryConstantExpression(ConstantExpression* lval, const std::string& op,
+ ConstantExpression* rval);
+ void evaluate() override;
+
+ private:
+ ConstantExpression* const lval;
+ ConstantExpression* const rval;
+ const std::string op;
+};
+
+struct TernaryConstantExpression : public ConstantExpression {
+ TernaryConstantExpression(ConstantExpression* cond, ConstantExpression* trueVal,
+ ConstantExpression* falseVal);
+ void evaluate() override;
+
+ private:
+ ConstantExpression* const cond;
+ ConstantExpression* const trueVal;
+ ConstantExpression* const falseVal;
+};
+
+struct ReferenceConstantExpression : public ConstantExpression {
+ ReferenceConstantExpression(const Reference<LocalIdentifier>& value, const std::string& expr);
+ void evaluate() override;
+
+ private:
+ Reference<LocalIdentifier> value;
};
} // namespace android
diff --git a/EnumType.cpp b/EnumType.cpp
index 9f70287..02c6c69 100644
--- a/EnumType.cpp
+++ b/EnumType.cpp
@@ -692,18 +692,16 @@
return mValue;
}
-void EnumValue::autofill(const EnumValue *prev, const ScalarType *type) {
- if(mValue != nullptr)
- return;
+void EnumValue::autofill(const EnumValue* prev, const ScalarType* type) {
+ if (mValue != nullptr) return;
mIsAutoFill = true;
- ConstantExpression *value = new ConstantExpression();
- if(prev == nullptr) {
- *value = ConstantExpression::Zero(type->getKind());
+ if (prev == nullptr) {
+ mValue = ConstantExpression::Zero(type->getKind()).release();
} else {
CHECK(prev->mValue != nullptr);
- *value = prev->mValue->addOne();
+ mValue = prev->mValue->addOne(type->getKind()).release();
}
- mValue = value;
+ mValue->evaluate();
}
bool EnumValue::isAutoFill() const {
diff --git a/EnumType.h b/EnumType.h
index 35db597..95a6174 100644
--- a/EnumType.h
+++ b/EnumType.h
@@ -131,14 +131,14 @@
std::string javaValue(ScalarType::Kind castKind) const;
std::string comment() const;
void autofill(const EnumValue *prev, const ScalarType *type);
- ConstantExpression *constExpr() const;
+ ConstantExpression* constExpr() const override;
bool isAutoFill() const;
bool isEnumValue() const override;
std::string mName;
- ConstantExpression *mValue;
+ ConstantExpression* mValue;
bool mIsAutoFill;
DISALLOW_COPY_AND_ASSIGN(EnumValue);
diff --git a/Interface.cpp b/Interface.cpp
index 805d81c..78d42ad 100644
--- a/Interface.cpp
+++ b/Interface.cpp
@@ -28,6 +28,7 @@
#include <unistd.h>
#include <iostream>
+#include <memory>
#include <sstream>
#include <android-base/logging.h>
@@ -287,10 +288,8 @@
}
static void emitDigestChain(
- Formatter &out,
- const std::string &prefix,
- const std::vector<const Interface *> &chain,
- std::function<std::string(const ConstantExpression &)> byteToString) {
+ Formatter& out, const std::string& prefix, const std::vector<const Interface*>& chain,
+ std::function<std::string(std::unique_ptr<ConstantExpression>)> byteToString) {
out.join(chain.begin(), chain.end(), ",\n", [&] (const auto &iface) {
const Hash &hash = Hash::getHash(iface->location().begin().filename());
out << prefix;
@@ -319,8 +318,8 @@
std::vector<const Interface *> chain = typeChain();
out << "_hidl_cb(";
out.block([&] {
- emitDigestChain(out, "(" + digestType->getInternalDataCppType() + ")",
- chain, [](const auto &e){return e.cppValue();});
+ emitDigestChain(out, "(" + digestType->getInternalDataCppType() + ")", chain,
+ [](const auto& e) { return e->cppValue(); });
});
out << ");\n";
out << "return ::android::hardware::Void();\n";
@@ -333,7 +332,7 @@
out.indent(2, [&] {
// No need for dimensions when elements are explicitly provided.
emitDigestChain(out, "new " + digestType->getJavaType(false /* forInitializer */),
- chain, [](const auto &e){return e.javaValue();});
+ chain, [](const auto& e) { return e->javaValue(); });
});
out << "));\n";
} } } /* javaImpl */
diff --git a/Scope.cpp b/Scope.cpp
index 13a6f28..1cee4f8 100644
--- a/Scope.cpp
+++ b/Scope.cpp
@@ -200,5 +200,9 @@
return false;
}
+ConstantExpression* LocalIdentifier::constExpr() const {
+ return nullptr;
+}
+
} // namespace android
diff --git a/Scope.h b/Scope.h
index 599182f..6a34a59 100644
--- a/Scope.h
+++ b/Scope.h
@@ -25,6 +25,7 @@
namespace android {
+struct ConstantExpression;
struct Formatter;
struct Interface;
struct LocalIdentifier;
@@ -88,6 +89,8 @@
LocalIdentifier();
virtual ~LocalIdentifier();
virtual bool isEnumValue() const;
+
+ virtual ConstantExpression* constExpr() const;
};
} // namespace android
diff --git a/hidl-gen_y.yy b/hidl-gen_y.yy
index 805f671..9a083c7 100644
--- a/hidl-gen_y.yy
+++ b/hidl-gen_y.yy
@@ -425,6 +425,7 @@
: const_expr
{
$$ = new std::vector<ConstantExpression *>;
+ $1->evaluate();
$$->push_back($1);
}
| '{' annotation_const_expr_values '}' { $$ = $2; }
@@ -434,11 +435,13 @@
: const_expr
{
$$ = new std::vector<ConstantExpression *>;
+ $1->evaluate();
$$->push_back($1);
}
| annotation_const_expr_values ',' const_expr
{
$$ = $1;
+ $3->evaluate();
$$->push_back($3);
}
;
@@ -757,7 +760,7 @@
;
const_expr
- : INTEGER { $$ = new ConstantExpression($1); }
+ : INTEGER { $$ = new LiteralConstantExpression($1); }
| fqname
{
if(!$1->isValidValueName()) {
@@ -766,6 +769,7 @@
<< @1 << ".\n";
YYERROR;
}
+
if($1->isIdentifier()) {
std::string identifier = $1->name();
LocalIdentifier *iden = (*scope)->lookupIdentifier(identifier);
@@ -779,8 +783,8 @@
<< " is not an enum value at " << @1 << ".\n";
YYERROR;
}
- $$ = new ConstantExpression(
- *(static_cast<EnumValue *>(iden)->constExpr()), $1->string());
+ $$ = new ReferenceConstantExpression(
+ Reference<LocalIdentifier>(iden, convertYYLoc(@1)), $1->string());
} else {
std::string errorMsg;
EnumValue* v = ast->lookupEnumValue(*$1, &errorMsg, *scope);
@@ -789,42 +793,42 @@
YYERROR;
}
- // TODO: Support Reference
- $$ = new ConstantExpression(*(v->constExpr()), $1->string());
+ $$ = new ReferenceConstantExpression(
+ Reference<LocalIdentifier>(v, convertYYLoc(@1)), $1->string());
}
}
| const_expr '?' const_expr ':' const_expr
{
- $$ = new ConstantExpression($1, $3, $5);
+ $$ = new TernaryConstantExpression($1, $3, $5);
}
- | const_expr LOGICAL_OR const_expr { $$ = new ConstantExpression($1, "||", $3); }
- | const_expr LOGICAL_AND const_expr { $$ = new ConstantExpression($1, "&&", $3); }
- | const_expr '|' const_expr { $$ = new ConstantExpression($1, "|" , $3); }
- | const_expr '^' const_expr { $$ = new ConstantExpression($1, "^" , $3); }
- | const_expr '&' const_expr { $$ = new ConstantExpression($1, "&" , $3); }
- | const_expr EQUALITY const_expr { $$ = new ConstantExpression($1, "==", $3); }
- | const_expr NEQ const_expr { $$ = new ConstantExpression($1, "!=", $3); }
- | const_expr '<' const_expr { $$ = new ConstantExpression($1, "<" , $3); }
- | const_expr '>' const_expr { $$ = new ConstantExpression($1, ">" , $3); }
- | const_expr LEQ const_expr { $$ = new ConstantExpression($1, "<=", $3); }
- | const_expr GEQ const_expr { $$ = new ConstantExpression($1, ">=", $3); }
- | const_expr LSHIFT const_expr { $$ = new ConstantExpression($1, "<<", $3); }
- | const_expr RSHIFT const_expr { $$ = new ConstantExpression($1, ">>", $3); }
- | const_expr '+' const_expr { $$ = new ConstantExpression($1, "+" , $3); }
- | const_expr '-' const_expr { $$ = new ConstantExpression($1, "-" , $3); }
- | const_expr '*' const_expr { $$ = new ConstantExpression($1, "*" , $3); }
- | const_expr '/' const_expr { $$ = new ConstantExpression($1, "/" , $3); }
- | const_expr '%' const_expr { $$ = new ConstantExpression($1, "%" , $3); }
- | '+' const_expr %prec UNARY_PLUS { $$ = new ConstantExpression("+", $2); }
- | '-' const_expr %prec UNARY_MINUS { $$ = new ConstantExpression("-", $2); }
- | '!' const_expr { $$ = new ConstantExpression("!", $2); }
- | '~' const_expr { $$ = new ConstantExpression("~", $2); }
+ | const_expr LOGICAL_OR const_expr { $$ = new BinaryConstantExpression($1, "||", $3); }
+ | const_expr LOGICAL_AND const_expr { $$ = new BinaryConstantExpression($1, "&&", $3); }
+ | const_expr '|' const_expr { $$ = new BinaryConstantExpression($1, "|" , $3); }
+ | const_expr '^' const_expr { $$ = new BinaryConstantExpression($1, "^" , $3); }
+ | const_expr '&' const_expr { $$ = new BinaryConstantExpression($1, "&" , $3); }
+ | const_expr EQUALITY const_expr { $$ = new BinaryConstantExpression($1, "==", $3); }
+ | const_expr NEQ const_expr { $$ = new BinaryConstantExpression($1, "!=", $3); }
+ | const_expr '<' const_expr { $$ = new BinaryConstantExpression($1, "<" , $3); }
+ | const_expr '>' const_expr { $$ = new BinaryConstantExpression($1, ">" , $3); }
+ | const_expr LEQ const_expr { $$ = new BinaryConstantExpression($1, "<=", $3); }
+ | const_expr GEQ const_expr { $$ = new BinaryConstantExpression($1, ">=", $3); }
+ | const_expr LSHIFT const_expr { $$ = new BinaryConstantExpression($1, "<<", $3); }
+ | const_expr RSHIFT const_expr { $$ = new BinaryConstantExpression($1, ">>", $3); }
+ | const_expr '+' const_expr { $$ = new BinaryConstantExpression($1, "+" , $3); }
+ | const_expr '-' const_expr { $$ = new BinaryConstantExpression($1, "-" , $3); }
+ | const_expr '*' const_expr { $$ = new BinaryConstantExpression($1, "*" , $3); }
+ | const_expr '/' const_expr { $$ = new BinaryConstantExpression($1, "/" , $3); }
+ | const_expr '%' const_expr { $$ = new BinaryConstantExpression($1, "%" , $3); }
+ | '+' const_expr %prec UNARY_PLUS { $$ = new UnaryConstantExpression("+", $2); }
+ | '-' const_expr %prec UNARY_MINUS { $$ = new UnaryConstantExpression("-", $2); }
+ | '!' const_expr { $$ = new UnaryConstantExpression("!", $2); }
+ | '~' const_expr { $$ = new UnaryConstantExpression("~", $2); }
| '(' const_expr ')' { $$ = $2; }
| '(' error ')'
{
ast->addSyntaxError();
// to avoid segfaults
- $$ = new ConstantExpression(ConstantExpression::Zero(ScalarType::KIND_INT32));
+ $$ = ConstantExpression::Zero(ScalarType::KIND_INT32).release();
}
;
@@ -1020,7 +1024,7 @@
enum_value
: valid_identifier { $$ = new EnumValue($1); }
- | valid_identifier '=' const_expr { $$ = new EnumValue($1, $3); }
+ | valid_identifier '=' const_expr { $3->evaluate(); $$ = new EnumValue($1, $3); }
;
enum_values
@@ -1096,6 +1100,8 @@
YYERROR;
}
+
+ $3->evaluate();
if (type.isResolved() && type->isArray()) {
$$ = new ArrayType(static_cast<ArrayType*>(type.get()), $3);
} else {
@@ -1105,6 +1111,7 @@
| array_type '[' const_expr ']'
{
$$ = $1;
+ $3->evaluate();
$$->appendDimension($3);
}
;