1 /*
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 
17 #ifndef CONSTANT_EXPRESSION_H_
18 
19 #define CONSTANT_EXPRESSION_H_
20 
21 #include <android-base/macros.h>
22 #include <functional>
23 #include <memory>
24 #include <string>
25 #include <unordered_set>
26 #include <vector>
27 
28 #include "Reference.h"
29 #include "ScalarType.h"
30 
31 namespace android {
32 
33 struct LocalIdentifier;
34 
35 struct LiteralConstantExpression;
36 struct UnaryConstantExpression;
37 struct BinaryConstantExpression;
38 struct TernaryConstantExpression;
39 struct ReferenceConstantExpression;
40 
41 /**
42  * A constant expression is represented by a tree.
43  */
44 struct ConstantExpression {
45     static std::unique_ptr<ConstantExpression> Zero(ScalarType::Kind kind);
46     static std::unique_ptr<ConstantExpression> One(ScalarType::Kind kind);
47     static std::unique_ptr<ConstantExpression> ValueOf(ScalarType::Kind kind, uint64_t value);
48 
49     ConstantExpression(const std::string& expr);
~ConstantExpressionConstantExpression50     virtual ~ConstantExpression() {}
51 
52     virtual bool isReferenceConstantExpression() const;
53 
54     void surroundWithParens();
55 
56     // Proceeds recursive pass
57     // Makes sure to visit each node only once
58     // Used to provide lookup and lazy evaluation
59     status_t recursivePass(const std::function<status_t(ConstantExpression*)>& func,
60                            std::unordered_set<const ConstantExpression*>* visited,
61                            bool processBeforeDependencies);
62     status_t recursivePass(const std::function<status_t(const ConstantExpression*)>& func,
63                            std::unordered_set<const ConstantExpression*>* visited,
64                            bool processBeforeDependencies) const;
65 
66     // If this object is in an invalid state.
67     virtual status_t validate() const;
68 
69     // Evaluates current constant expression
70     // Doesn't call recursive evaluation, so must be called after dependencies
71     virtual void evaluate() = 0;
72 
73     std::vector<ConstantExpression*> getConstantExpressions();
74     virtual std::vector<const ConstantExpression*> getConstantExpressions() const = 0;
75 
76     std::vector<Reference<LocalIdentifier>*> getReferences();
77     virtual std::vector<const Reference<LocalIdentifier>*> getReferences() const;
78 
79     std::vector<Reference<Type>*> getTypeReferences();
80     virtual std::vector<const Reference<Type>*> getTypeReferences() const;
81 
82     // Recursive tree pass checkAcyclic return type.
83     // Stores cycle end for nice error messages.
84     struct CheckAcyclicStatus {
85         CheckAcyclicStatus(status_t status, const ConstantExpression* cycleEnd = nullptr,
86                            const ReferenceConstantExpression* lastReferenceExpression = nullptr);
87 
88         status_t status;
89 
90         // If a cycle is found, stores the end of cycle.
91         // While going back in recursion, this is used to stop printing the cycle.
92         const ConstantExpression* cycleEnd;
93 
94         // The last ReferenceConstantExpression visited on the cycle.
95         const ReferenceConstantExpression* lastReference;
96     };
97 
98     // Recursive tree pass that ensures that constant expressions definitions
99     // are acyclic.
100     CheckAcyclicStatus checkAcyclic(std::unordered_set<const ConstantExpression*>* visited,
101                                     std::unordered_set<const ConstantExpression*>* stack) const;
102 
103     /* Returns true iff the value has already been evaluated. */
104     bool isEvaluated() const;
105     /* Evaluated result in a string form with comment if applicable. */
106     std::string value() const;
107     /* Evaluated result in a string form with comment if applicable. */
108     std::string cppValue() const;
109     /* Evaluated result in a string form with comment if applicable. */
110     std::string javaValue() const;
111     /* Evaluated result in a string form, with given contextual kind. */
112     std::string value(ScalarType::Kind castKind) const;
113     /* Evaluated result in a string form, with given contextual kind. */
114     std::string cppValue(ScalarType::Kind castKind) const;
115     /* Evaluated result in a string form, with given contextual kind. */
116     std::string javaValue(ScalarType::Kind castKind) const;
117 
118     /* The expression representing this value for use in comments when the value is not needed */
119     const std::string& expression() const;
120 
121     /* Return a ConstantExpression that is 1 plus the original. */
122     std::unique_ptr<ConstantExpression> addOne(ScalarType::Kind baseKind);
123 
124     size_t castSizeT() const;
125 
126     // Marks that package proceeding is completed
127     // Post parse passes must be proceeded during owner package parsin
128     void setPostParseCompleted();
129 
130     /*
131      * Helper function for all cpp/javaValue methods.
132      * Returns a plain string (without any prefixes or suffixes, just the
133      * digits) converted from mValue.
134      */
135     std::string rawValue() const;
136     std::string rawValue(ScalarType::Kind castKind) const;
137 
138    private:
139     /* If the result value has been evaluated. */
140     bool mIsEvaluated = false;
141     /* The formatted expression. */
142     std::string mExpr;
143     /* The kind of the result value. */
144     ScalarType::Kind mValueKind;
145     /* The stored result value. */
146     uint64_t mValue;
147     /* true if description() does not offer more information than value(). */
148     bool mTrivialDescription = false;
149 
150     bool mIsPostParseCompleted = false;
151 
152     /*
153      * Helper function, gives suffix comment to add to value/cppValue/javaValue
154      */
155     std::string descriptionSuffix() const;
156 
157     /*
158      * Return the value casted to the given type.
159      * First cast it according to mValueKind, then cast it to T.
160      * Assumes !containsIdentifiers()
161      */
162     template <typename T>
163     T cast() const;
164 
165     friend struct LiteralConstantExpression;
166     friend struct UnaryConstantExpression;
167     friend struct BinaryConstantExpression;
168     friend struct TernaryConstantExpression;
169     friend struct ReferenceConstantExpression;
170     friend struct AttributeConstantExpression;
171 };
172 
173 struct LiteralConstantExpression : public ConstantExpression {
174     LiteralConstantExpression(ScalarType::Kind kind, uint64_t value);
175     LiteralConstantExpression(ScalarType::Kind kind, uint64_t value, const std::string& expr);
176     void evaluate() override;
177     std::vector<const ConstantExpression*> getConstantExpressions() const override;
178 
179     static LiteralConstantExpression* tryParse(const std::string& value);
180 };
181 
182 struct UnaryConstantExpression : public ConstantExpression {
183     UnaryConstantExpression(const std::string& mOp, ConstantExpression* value);
184     void evaluate() override;
185     std::vector<const ConstantExpression*> getConstantExpressions() const override;
186 
187    private:
188     ConstantExpression* const mUnary;
189     std::string mOp;
190 };
191 
192 struct BinaryConstantExpression : public ConstantExpression {
193     BinaryConstantExpression(ConstantExpression* lval, const std::string& op,
194                              ConstantExpression* rval);
195     void evaluate() override;
196     std::vector<const ConstantExpression*> getConstantExpressions() const override;
197 
198    private:
199     ConstantExpression* const mLval;
200     ConstantExpression* const mRval;
201     const std::string mOp;
202 };
203 
204 struct TernaryConstantExpression : public ConstantExpression {
205     TernaryConstantExpression(ConstantExpression* cond, ConstantExpression* trueVal,
206                               ConstantExpression* falseVal);
207     void evaluate() override;
208     std::vector<const ConstantExpression*> getConstantExpressions() const override;
209 
210    private:
211     ConstantExpression* const mCond;
212     ConstantExpression* const mTrueVal;
213     ConstantExpression* const mFalseVal;
214 };
215 
216 struct ReferenceConstantExpression : public ConstantExpression {
217     ReferenceConstantExpression(const Reference<LocalIdentifier>& value, const std::string& expr);
218 
219     bool isReferenceConstantExpression() const override;
220     void evaluate() override;
221     std::vector<const ConstantExpression*> getConstantExpressions() const override;
222     std::vector<const Reference<LocalIdentifier>*> getReferences() const override;
223 
224    private:
225     Reference<LocalIdentifier> mReference;
226 };
227 
228 // This constant expression is a compile-time calculatable expression based on another type
229 struct AttributeConstantExpression : public ConstantExpression {
230     AttributeConstantExpression(const Reference<Type>& value, const std::string& fqname,
231                                 const std::string& tag);
232 
233     status_t validate() const override;
234     void evaluate() override;
235 
236     std::vector<const ConstantExpression*> getConstantExpressions() const override;
237     std::vector<const Reference<Type>*> getTypeReferences() const override;
238 
239    private:
240     Reference<Type> mReference;
241     const std::string mTag;
242 };
243 
244 }  // namespace android
245 
246 #endif  // CONSTANT_EXPRESSION_H_
247