Changeset View
Standalone View
llvm/include/llvm/Support/FileCheck.h
Show All 34 Lines | 26 | struct FileCheckRequest { | |||
---|---|---|---|---|---|
35 | bool Verbose = false; | 35 | bool Verbose = false; | ||
36 | bool VerboseVerbose = false; | 36 | bool VerboseVerbose = false; | ||
37 | }; | 37 | }; | ||
38 | 38 | | |||
39 | //===----------------------------------------------------------------------===// | 39 | //===----------------------------------------------------------------------===// | ||
40 | // Numeric substitution handling code. | 40 | // Numeric substitution handling code. | ||
41 | //===----------------------------------------------------------------------===// | 41 | //===----------------------------------------------------------------------===// | ||
42 | 42 | | |||
43 | /// Class representing a numeric variable with a given value in a numeric | 43 | /// Base class representing the AST of a given numeric expression. | ||
jhenderson: Are there other kinds of expressions except "numeric expressions"? Just wondering if we can… | |||||
thopreAuthorUnsubmitted Done ReplyThere's only numeric expression indeed but wouldn't the use of "expression" only induce the reader into thinking it only applies when there is an operator involved? Numeric expression as it stands also cover a single numeric variable in a numeric substitution. Also if changing to expression only, should I remove the "numeric" adjective in the documentation as well? thopre: There's only numeric expression indeed but wouldn't the use of "expression" only induce the… | |||||
probinsonUnsubmitted Done ReplyI think "expression" does not necessarily imply an operator, at least not to a programmer. probinson: I think "expression" does not necessarily imply an operator, at least not to a programmer.
You… | |||||
44 | /// expression. Each definition of a variable gets its own instance of this | 44 | class FileCheckNumExprAST { | ||
45 | /// class. Variable uses share the same instance as their respective | 45 | public: | ||
46 | virtual ~FileCheckNumExprAST() = default; | ||||
47 | | ||||
48 | /// Evaluates and \returns the value of the expression represented by this | ||||
49 | /// AST. | ||||
50 | virtual Optional<uint64_t> eval() const = 0; | ||||
51 | | ||||
52 | /// Appends names of undefined variables used in the expression represented | ||||
53 | /// by this AST. Must be overriden in any subclass representing an expression | ||||
54 | /// that can contain a variable. | ||||
Done ReplyAs things stand, this only can represent an unsigned literal. I think you'll want to support negative literals or unary negation operands fairly quickly. Otherwise, the expression "-1" doesn't work. I'm also slightly concerned in the current form that somebody could try to use FileCheckExpressionLiteral for negative numbers, and get surprising results. Perhaps worth updating the comment to say that the class represents an unsigned integer literal. jhenderson: As things stand, this only can represent an unsigned literal. I think you'll want to support… | |||||
55 | virtual void | ||||
56 | appendUndefVarNames(std::vector<StringRef> &UndefVarNames) const {} | ||||
57 | }; | ||||
58 | | ||||
59 | /// Class representing a literal in the AST of a numeric expression. | ||||
60 | class FileCheckNumExprLiteral : public FileCheckNumExprAST { | ||||
Done ReplyPerhaps "Construct a literal with the specified value." jhenderson: Perhaps "Construct a literal with the specified value." | |||||
Done Replylitteral -> literal jhenderson: litteral -> literal | |||||
61 | private: | ||||
62 | /// Actual value of the literal. | ||||
63 | uint64_t Value; | ||||
64 | | ||||
65 | public: | ||||
66 | /// Constructor for an unsigned literal. | ||||
67 | FileCheckNumExprLiteral(uint64_t Val) : Value(Val) {} | ||||
jhendersonUnsubmitted Done ReplyAre there plans for signed literals later? If not, then I'd get rid of "unsigned" from the comment. jhenderson: Are there plans for signed literals later? If not, then I'd get rid of "unsigned" from the… | |||||
thopreAuthorUnsubmitted Done ReplyThere are but the comment can be changed when they are introduced. Fixed. thopre: There are but the comment can be changed when they are introduced. Fixed. | |||||
Done ReplyI think "Class to represent an undefined variable error, which quotes that variable's name when printed." would be a bit more concise. jhenderson: I think "Class to represent an undefined variable error, which quotes that variable's name when… | |||||
68 | | ||||
69 | /// Evaluates and returns the value of the expression represented by this | ||||
70 | /// AST. Therefore, \returns the literal's value. | ||||
jhendersonUnsubmitted Done ReplyYou could probably simplify this down to \returns the literal's value. jhenderson: You could probably simplify this down to `\returns the literal's value.` | |||||
71 | Optional<uint64_t> eval() const { return Value; } | ||||
72 | }; | ||||
73 | | ||||
74 | /// Class representing a numeric variable with a given value in the AST of a | ||||
75 | /// numeric expression. Each definition of a variable gets its own instance of | ||||
76 | /// this class. Variable uses share the same instance as their respective | ||||
46 | /// definition. | 77 | /// definition. | ||
Done Replydefinition -> definitions jhenderson: definition -> definitions | |||||
47 | class FileCheckNumericVariable { | 78 | class FileCheckNumericVariable : public FileCheckNumExprAST { | ||
48 | private: | 79 | private: | ||
49 | /// Name of the numeric variable. | 80 | /// Name of the numeric variable. | ||
50 | StringRef Name; | 81 | StringRef Name; | ||
51 | 82 | | |||
52 | /// Value of numeric variable, if defined, or None otherwise. | 83 | /// Value of numeric variable, if defined, or None otherwise. | ||
53 | Optional<uint64_t> Value; | 84 | Optional<uint64_t> Value; | ||
54 | 85 | | |||
55 | /// Line number where this variable is defined. Used to determine whether a | 86 | /// Line number where this variable is defined. Used to determine whether a | ||
56 | /// variable is defined on the same line as a given use. | 87 | /// variable is defined on the same line as a given use. | ||
57 | size_t DefLineNumber; | 88 | size_t DefLineNumber; | ||
58 | 89 | | |||
59 | public: | 90 | public: | ||
60 | /// Constructor for a variable \p Name defined at line \p DefLineNumber. | 91 | /// Constructor for a variable \p Name defined at line \p DefLineNumber. | ||
61 | FileCheckNumericVariable(size_t DefLineNumber, StringRef Name) | 92 | FileCheckNumericVariable(size_t DefLineNumber, StringRef Name) | ||
62 | : Name(Name), DefLineNumber(DefLineNumber) {} | 93 | : Name(Name), DefLineNumber(DefLineNumber) {} | ||
63 | 94 | | |||
64 | /// Constructor for numeric variable \p Name with a known \p Value at parse | 95 | /// Constructor for numeric variable \p Name with a known \p Value at parse | ||
65 | /// time (e.g. the @LINE numeric variable). | 96 | /// time (e.g. the @LINE numeric variable). | ||
66 | FileCheckNumericVariable(StringRef Name, uint64_t Value) | 97 | FileCheckNumericVariable(StringRef Name, uint64_t Value) | ||
67 | : Name(Name), Value(Value), DefLineNumber(0) {} | 98 | : Name(Name), Value(Value), DefLineNumber(0) {} | ||
68 | 99 | | |||
69 | /// \returns name of that numeric variable. | 100 | /// \returns name of that numeric variable. | ||
70 | StringRef getName() const { return Name; } | 101 | StringRef getName() const { return Name; } | ||
71 | 102 | | |||
72 | /// \returns value of this numeric variable. | 103 | /// Evaluates and returns the value of the expression represented by this | ||
73 | Optional<uint64_t> getValue() const { return Value; } | 104 | /// AST. Therefore, \returns this variable's value. | ||
jhendersonUnsubmitted Done ReplySimilar comment to above. No need to explain that its evaluating the expression for a single variable. Just keep the "returns this variable's value" part. jhenderson: Similar comment to above. No need to explain that its evaluating the expression for a single… | |||||
105 | Optional<uint64_t> eval() const { return Value; } | ||||
arichardsonUnsubmitted Done ReplyMaybe this should use Expected instead of Optional to report errors? arichardson: Maybe this should use Expected instead of Optional to report errors? | |||||
106 | | ||||
107 | /// Appends numeric variable's name to UndefVarNames if undefined. | ||||
108 | void appendUndefVarNames(std::vector<StringRef> &UndefVarNames) const; | ||||
Done ReplyIf you made this eval() return an error if the variable is undefined, it would nicely separate concerns of use versus definition (see my comment a bit further down about shared_ptrs). jhenderson: If you made this eval() return an error if the variable is undefined, it would nicely separate… | |||||
74 | 109 | | |||
75 | /// Sets value of this numeric variable if not defined. \returns whether the | 110 | /// Sets value of this numeric variable if not defined. \returns whether the | ||
76 | /// variable was already defined. | 111 | /// variable was already defined. | ||
77 | bool setValue(uint64_t Value); | 112 | bool setValue(uint64_t Value); | ||
78 | 113 | | |||
79 | /// Clears value of this numeric variable. \returns whether the variable was | 114 | /// Clears value of this numeric variable. \returns whether the variable was | ||
80 | /// already undefined. | 115 | /// already undefined. | ||
81 | bool clearValue(); | 116 | bool clearValue(); | ||
82 | 117 | | |||
83 | /// \returns the line number where this variable is defined. | 118 | /// \returns the line number where this variable is defined. | ||
84 | size_t getDefLineNumber() { return DefLineNumber; } | 119 | size_t getDefLineNumber() { return DefLineNumber; } | ||
85 | }; | 120 | }; | ||
86 | 121 | | |||
87 | /// Type of functions evaluating a given binary operation. | 122 | /// Type of functions evaluating a given binary operation. | ||
88 | using binop_eval_t = uint64_t (*)(uint64_t, uint64_t); | 123 | using binop_eval_t = uint64_t (*)(uint64_t, uint64_t); | ||
89 | 124 | | |||
90 | /// Class representing a numeric expression consisting of either a single | 125 | /// Class representing a single binary operation in the AST of a numeric | ||
91 | /// numeric variable or a binary operation between a numeric variable and an | 126 | /// expression. | ||
92 | /// immediate. | 127 | class FileCheckASTBinop : public FileCheckNumExprAST { | ||
93 | class FileCheckNumExpr { | | |||
94 | private: | 128 | private: | ||
95 | /// Left operand. | 129 | /// Left operand. | ||
96 | FileCheckNumericVariable *LeftOp; | 130 | std::shared_ptr<FileCheckNumExprAST> LeftOp; | ||
jhendersonUnsubmitted Done ReplyDo these need to be shared_ptrs? Do multiple places need ownership, or is it sufficient that only place has it? Same question applies for all uses of shared_ptr further down. jhenderson: Do these need to be shared_ptrs? Do multiple places need ownership, or is it sufficient that… | |||||
thopreAuthorUnsubmitted Done ReplySome AST nodes are referenced from a single place only (eg. literals and binary operations) while numeric variables can be shared among several numeric substitutions, eg. "add r[[#REG]], r[[#REG+1]], 42" would have 2 pointers to the class instance for REG. In the first case std::unique_ptr could be used, while in the latter case std::shared_ptr would make sense. The problem comes from AST nodes being referred via FileCheckAST * pointers (since each operand can be either of the possible nodes) and thus I need to decide on a given pointer type for all nodes. I could go with regular pointers and keep an array of pointer in FileCheckPatternContext to all nodes created for them to be freed all at once when matching is done. Wouldn't change much over what is happening now since substitutions are only deleted once all pattern have been matched and substitutions points to the AST indirectly. Does that sound good? thopre: Some AST nodes are referenced from a single place only (eg. literals and binary operations)… | |||||
jhendersonUnsubmitted Done ReplyI wonder whether it might make more sense to separate the concept of variables from the AST. The AST could have a variable reference class in it, which refers by raw pointer to a variable definition. An AST expression then solely "owns" each subexpression, whilst something higher up (e.g. the Context - not sure about this), owns the variables and contains the definitions. That way each item in the tree is only owned by its parents, which feels more logical. Does that make sense? As things stand the fact that a single FileCheckNumericVariable can be owned by multiple places implies it's not really a tree at all. (In graph theory a tree has no cross-references - everything is owned by a single parent only). jhenderson: I wonder whether it might make more sense to separate the concept of variables from the AST. | |||||
97 | 131 | | |||
98 | /// Right operand. | 132 | /// Right operand. | ||
99 | uint64_t RightOp; | 133 | std::shared_ptr<FileCheckNumExprAST> RightOp; | ||
100 | 134 | | |||
101 | /// Pointer to function that can evaluate this binary operation. | 135 | /// Pointer to function that can evaluate this binary operation. | ||
102 | binop_eval_t EvalBinop; | 136 | binop_eval_t EvalBinop; | ||
103 | 137 | | |||
104 | public: | 138 | public: | ||
105 | FileCheckNumExpr(binop_eval_t EvalBinop, | 139 | FileCheckASTBinop(binop_eval_t EvalBinop, | ||
106 | FileCheckNumericVariable *OperandLeft, uint64_t OperandRight) | 140 | std::shared_ptr<FileCheckNumExprAST> OperandLeft, | ||
141 | std::shared_ptr<FileCheckNumExprAST> OperandRight) | ||||
107 | : LeftOp(OperandLeft), RightOp(OperandRight), EvalBinop(EvalBinop) {} | 142 | : LeftOp(OperandLeft), RightOp(OperandRight), EvalBinop(EvalBinop) {} | ||
108 | 143 | | |||
109 | /// Evaluates the value of this numeric expression, using EvalBinop to | 144 | /// Evaluates the value of the binary operation represented by this AST, | ||
110 | /// perform the binary operation it consists of. \returns None if the numeric | 145 | /// using EvalBinop on the result of recursively evaluating the operands. | ||
111 | /// variable used is undefined, or the expression value otherwise. | 146 | /// \returns None if any numeric variable used is undefined, or the | ||
Done ReplyThis should say "returns an error if a subexpression returns an error, or ..." jhenderson: This should say "returns an error if a subexpression returns an error, or ..." | |||||
Done ReplyI prefer the description of the return value to give the expected/normal case first, and the error case afterward. So, \returns the expression value, or an error ... probinson: I prefer the description of the return value to give the expected/normal case first, and the… | |||||
147 | /// expression value otherwise. | ||||
112 | Optional<uint64_t> eval() const; | 148 | Optional<uint64_t> eval() const; | ||
113 | 149 | | |||
114 | /// \returns the name of the undefined variable used in this expression if | 150 | /// Appends names of undefined variables used in any of the operands of this | ||
115 | /// any or an empty string otherwise. | 151 | /// binary operation. | ||
116 | StringRef getUndefVarName() const; | 152 | void appendUndefVarNames(std::vector<StringRef> &UndefVarNames) const; | ||
jhendersonUnsubmitted Done ReplyCould this use a MutableArrayRef? jhenderson: Could this use a `MutableArrayRef`? | |||||
117 | }; | 153 | }; | ||
118 | 154 | | |||
119 | class FileCheckPatternContext; | 155 | class FileCheckPatternContext; | ||
120 | 156 | | |||
121 | /// Class representing a substitution to perform in the RegExStr string. | 157 | /// Class representing a substitution to perform in the RegExStr string. | ||
122 | class FileCheckSubstitution { | 158 | class FileCheckSubstitution { | ||
123 | protected: | 159 | protected: | ||
124 | /// Pointer to a class instance holding, among other things, the table with | 160 | /// Pointer to a class instance holding, among other things, the table with | ||
Show All 24 Lines | 176 | public: | |||
149 | 185 | | |||
150 | /// \returns the index where the substitution is to be performed in RegExStr. | 186 | /// \returns the index where the substitution is to be performed in RegExStr. | ||
151 | size_t getIndex() const { return InsertIdx; } | 187 | size_t getIndex() const { return InsertIdx; } | ||
152 | 188 | | |||
153 | /// \returns a string containing the result of the substitution represented | 189 | /// \returns a string containing the result of the substitution represented | ||
154 | /// by this class instance or None if substitution failed. | 190 | /// by this class instance or None if substitution failed. | ||
155 | virtual Optional<std::string> getResult() const = 0; | 191 | virtual Optional<std::string> getResult() const = 0; | ||
156 | 192 | | |||
157 | /// \returns the name of the variable used in this substitution if undefined, | 193 | /// Records in \p UndefVarNames the name of the variables used in this | ||
158 | /// or an empty string otherwise. | 194 | /// substitution, if undefined. | ||
jhendersonUnsubmitted Done ReplyHow about "the name of the undefined variables used in this substitution"? Also use "Appends" instead of "Records" to show that it doesn't override the old ones. Same comments apply to the other examples of getUndefVarNames. jhenderson: How about "the name of the undefined variables used in this substitution"?
Also use "Appends"… | |||||
159 | virtual StringRef getUndefVarName() const = 0; | 195 | virtual void | ||
196 | getUndefVarNames(std::vector<StringRef> &UndefVarNames) const = 0; | ||||
160 | }; | 197 | }; | ||
161 | 198 | | |||
162 | class FileCheckStringSubstitution : public FileCheckSubstitution { | 199 | class FileCheckStringSubstitution : public FileCheckSubstitution { | ||
163 | public: | 200 | public: | ||
164 | FileCheckStringSubstitution(FileCheckPatternContext *Context, | 201 | FileCheckStringSubstitution(FileCheckPatternContext *Context, | ||
165 | StringRef VarName, size_t InsertIdx) | 202 | StringRef VarName, size_t InsertIdx) | ||
166 | : FileCheckSubstitution(Context, VarName, InsertIdx) {} | 203 | : FileCheckSubstitution(Context, VarName, InsertIdx) {} | ||
167 | 204 | | |||
168 | /// \returns the text that the string variable in this substitution matched | 205 | /// \returns the text that the string variable in this substitution matched | ||
169 | /// when defined, or None if the variable is undefined. | 206 | /// when defined, or None if the variable is undefined. | ||
170 | Optional<std::string> getResult() const override; | 207 | Optional<std::string> getResult() const override; | ||
171 | 208 | | |||
172 | /// \returns the name of the string variable used in this substitution if | 209 | /// Records in \p UndefVarNames the name of the string variables used in this | ||
173 | /// undefined, or an empty string otherwise. | 210 | /// substitution, if undefined. | ||
jhendersonUnsubmitted Done ReplyWhat if some string variables are defined and others aren't? The comment as it stands suggests that all are stored. If that's not intended, I'd rephrase it as "the name of the undefined string variables used in this substitution" jhenderson: What if some string variables are defined and others aren't? The comment as it stands suggests… | |||||
174 | StringRef getUndefVarName() const override; | 211 | void getUndefVarNames(std::vector<StringRef> &UndefVarNames) const override; | ||
175 | }; | 212 | }; | ||
176 | 213 | | |||
177 | class FileCheckNumericSubstitution : public FileCheckSubstitution { | 214 | class FileCheckNumericSubstitution : public FileCheckSubstitution { | ||
178 | private: | 215 | private: | ||
179 | /// Pointer to the class representing the numeric expression whose value is | 216 | /// Pointer to the class representing the numeric expression whose value is | ||
180 | /// to be substituted. | 217 | /// to be substituted. | ||
181 | FileCheckNumExpr *NumExpr; | 218 | std::shared_ptr<FileCheckNumExprAST> NumExprAST; | ||
182 | 219 | | |||
183 | public: | 220 | public: | ||
184 | FileCheckNumericSubstitution(FileCheckPatternContext *Context, StringRef Expr, | 221 | FileCheckNumericSubstitution(FileCheckPatternContext *Context, StringRef Expr, | ||
185 | FileCheckNumExpr *NumExpr, size_t InsertIdx) | 222 | std::shared_ptr<FileCheckNumExprAST> NumExprAST, | ||
186 | : FileCheckSubstitution(Context, Expr, InsertIdx), NumExpr(NumExpr) {} | 223 | size_t InsertIdx) | ||
224 | : FileCheckSubstitution(Context, Expr, InsertIdx), | ||||
225 | NumExprAST(NumExprAST) {} | ||||
187 | 226 | | |||
188 | /// \returns a string containing the result of evaluating the numeric | 227 | /// \returns a string containing the result of evaluating the numeric | ||
189 | /// expression in this substitution, or None if evaluation failed. | 228 | /// expression in this substitution, or None if evaluation failed. | ||
190 | Optional<std::string> getResult() const override; | 229 | Optional<std::string> getResult() const override; | ||
191 | 230 | | |||
192 | /// \returns the name of the numeric variable used in this substitution if | 231 | /// Records in \p UndefVarNames the name of the numeric variables used in | ||
193 | /// undefined, or an empty string otherwise. | 232 | /// this substitution, if undefined. | ||
194 | StringRef getUndefVarName() const override; | 233 | void getUndefVarNames(std::vector<StringRef> &UndefVarNames) const override; | ||
195 | }; | 234 | }; | ||
196 | 235 | | |||
197 | //===----------------------------------------------------------------------===// | 236 | //===----------------------------------------------------------------------===// | ||
198 | // Pattern handling code. | 237 | // Pattern handling code. | ||
199 | //===----------------------------------------------------------------------===// | 238 | //===----------------------------------------------------------------------===// | ||
200 | 239 | | |||
201 | namespace Check { | 240 | namespace Check { | ||
202 | 241 | | |||
▲ Show 20 Lines • Show All 58 Lines • ▼ Show 20 Line(s) | 289 | private: | |||
261 | 300 | | |||
262 | /// When matching a given pattern, this holds the pointers to the classes | 301 | /// When matching a given pattern, this holds the pointers to the classes | ||
263 | /// representing the last definitions of numeric variables defined in | 302 | /// representing the last definitions of numeric variables defined in | ||
264 | /// previous patterns. Earlier definitions of the variables, if any, have | 303 | /// previous patterns. Earlier definitions of the variables, if any, have | ||
265 | /// their own class instance not referenced by this table. When matching a | 304 | /// their own class instance not referenced by this table. When matching a | ||
266 | /// pattern all definitions for that pattern are recorded in the | 305 | /// pattern all definitions for that pattern are recorded in the | ||
267 | /// NumericVariableDefs table in the FileCheckPattern instance of that | 306 | /// NumericVariableDefs table in the FileCheckPattern instance of that | ||
268 | /// pattern. | 307 | /// pattern. | ||
269 | StringMap<FileCheckNumericVariable *> GlobalNumericVariableTable; | 308 | StringMap<std::shared_ptr<FileCheckNumericVariable>> | ||
270 | 309 | GlobalNumericVariableTable; | |||
271 | /// Vector holding pointers to all parsed numeric expressions. Used to | | |||
272 | /// automatically free the numeric expressions once they are guaranteed to no | | |||
273 | /// longer be used. | | |||
274 | std::vector<std::unique_ptr<FileCheckNumExpr>> NumExprs; | | |||
275 | | ||||
276 | /// Vector holding pointers to all parsed numeric variables. Used to | | |||
277 | /// automatically free them once they are guaranteed to no longer be used. | | |||
278 | std::vector<std::unique_ptr<FileCheckNumericVariable>> NumericVariables; | | |||
279 | 310 | | |||
280 | /// Vector holding pointers to all substitutions. Used to automatically free | 311 | /// Vector holding pointers to all substitutions. Used to automatically free | ||
281 | /// them once they are guaranteed to no longer be used. | 312 | /// them once they are guaranteed to no longer be used. | ||
282 | std::vector<std::unique_ptr<FileCheckSubstitution>> Substitutions; | 313 | std::vector<std::unique_ptr<FileCheckSubstitution>> Substitutions; | ||
283 | 314 | | |||
284 | public: | 315 | public: | ||
285 | /// \returns the value of string variable \p VarName or None if no such | 316 | /// \returns the value of string variable \p VarName or None if no such | ||
286 | /// variable has been defined. | 317 | /// variable has been defined. | ||
287 | Optional<StringRef> getPatternVarValue(StringRef VarName); | 318 | Optional<StringRef> getPatternVarValue(StringRef VarName); | ||
288 | 319 | | |||
289 | /// Defines string and numeric variables from definitions given on the | 320 | /// Defines string and numeric variables from definitions given on the | ||
290 | /// command line, passed as a vector of [#]VAR=VAL strings in | 321 | /// command line, passed as a vector of [#]VAR=VAL strings in | ||
291 | /// \p CmdlineDefines. Reports any error to \p SM and \returns whether an | 322 | /// \p CmdlineDefines. Reports any error to \p SM and \returns whether an | ||
292 | /// error occured. | 323 | /// error occured. | ||
293 | bool defineCmdlineVariables(std::vector<std::string> &CmdlineDefines, | 324 | bool defineCmdlineVariables(std::vector<std::string> &CmdlineDefines, | ||
294 | SourceMgr &SM); | 325 | SourceMgr &SM); | ||
295 | 326 | | |||
296 | /// Undefines local variables (variables whose name does not start with a '$' | 327 | /// Undefines local variables (variables whose name does not start with a '$' | ||
297 | /// sign), i.e. removes them from GlobalVariableTable and from | 328 | /// sign), i.e. removes them from GlobalVariableTable and from | ||
298 | /// GlobalNumericVariableTable and also clears the value of numeric | 329 | /// GlobalNumericVariableTable and also clears the value of numeric | ||
299 | /// variables. | 330 | /// variables. | ||
300 | void clearLocalVars(); | 331 | void clearLocalVars(); | ||
301 | 332 | | |||
302 | private: | 333 | private: | ||
303 | /// Makes a new numeric expression instance and registers it for destruction | | |||
304 | /// when the context is destroyed. | | |||
305 | FileCheckNumExpr *makeNumExpr(binop_eval_t EvalBinop, | | |||
306 | FileCheckNumericVariable *OperandLeft, | | |||
307 | uint64_t OperandRight); | | |||
308 | | ||||
309 | /// Makes a new numeric variable and registers it for destruction when the | | |||
310 | /// context is destroyed. | | |||
311 | template <class... Types> | | |||
312 | FileCheckNumericVariable *makeNumericVariable(Types... args); | | |||
313 | | ||||
314 | /// Makes a new string substitution and registers it for destruction when the | 334 | /// Makes a new string substitution and registers it for destruction when the | ||
315 | /// context is destroyed. | 335 | /// context is destroyed. | ||
316 | FileCheckSubstitution *makeStringSubstitution(StringRef VarName, | 336 | FileCheckSubstitution *makeStringSubstitution(StringRef VarName, | ||
317 | size_t InsertIdx); | 337 | size_t InsertIdx); | ||
318 | 338 | | |||
319 | /// Makes a new numeric substitution and registers it for destruction when | 339 | /// Makes a new numeric substitution and registers it for destruction when | ||
320 | /// the context is destroyed. | 340 | /// the context is destroyed. | ||
321 | FileCheckSubstitution *makeNumericSubstitution(StringRef Expr, | 341 | FileCheckSubstitution * | ||
322 | FileCheckNumExpr *NumExpr, | 342 | makeNumericSubstitution(StringRef Expr, | ||
343 | std::shared_ptr<FileCheckNumExprAST> NumExprAST, | ||||
323 | size_t InsertIdx); | 344 | size_t InsertIdx); | ||
324 | }; | 345 | }; | ||
325 | 346 | | |||
326 | class FileCheckPattern { | 347 | class FileCheckPattern { | ||
327 | SMLoc PatternLoc; | 348 | SMLoc PatternLoc; | ||
328 | 349 | | |||
329 | /// A fixed string to match as the pattern or empty if this pattern requires | 350 | /// A fixed string to match as the pattern or empty if this pattern requires | ||
330 | /// a regex match. | 351 | /// a regex match. | ||
▲ Show 20 Lines • Show All 80 Lines • ▼ Show 20 Line(s) | 413 | public: | |||
411 | /// Parses \p Expr for the definition of a numeric variable, returning an | 432 | /// Parses \p Expr for the definition of a numeric variable, returning an | ||
412 | /// error if \p Context already holds a string variable with the same name. | 433 | /// error if \p Context already holds a string variable with the same name. | ||
413 | /// \returns whether parsing fails, in which case errors are reported on | 434 | /// \returns whether parsing fails, in which case errors are reported on | ||
414 | /// \p SM. Otherwise, sets \p Name to the name of the parsed numeric | 435 | /// \p SM. Otherwise, sets \p Name to the name of the parsed numeric | ||
415 | /// variable. | 436 | /// variable. | ||
416 | static bool parseNumericVariableDefinition(StringRef &Expr, StringRef &Name, | 437 | static bool parseNumericVariableDefinition(StringRef &Expr, StringRef &Name, | ||
417 | FileCheckPatternContext *Context, | 438 | FileCheckPatternContext *Context, | ||
418 | const SourceMgr &SM); | 439 | const SourceMgr &SM); | ||
419 | /// Parses \p Expr for a numeric substitution block. \returns the class | 440 | /// Parses \p Expr for a numeric substitution block. Parameter \p Legacy | ||
420 | /// representing the AST of the numeric expression whose value must be | 441 | /// indicates whether Expr should be a legacy numeric substitution block. | ||
jhendersonUnsubmitted Done ReplyWhat's a "legacy numeric substitution block"? jhenderson: What's a "legacy numeric substitution block"? | |||||
thopreAuthorUnsubmitted Done ReplyIt refers to the "legacy use of @LINE" mentioned in the section "FileCheck Pseudo Numeric Variables" of the documentation, namely [[@LINE]] and [[@LINE+offset]] instead of the same with a '#' sign. Would "indicates whether Expr is a legacy use of @LINE" be clearer? Or perhaps "legacy @LINE expression"? If not, any other suggestion? thopre: It refers to the "legacy use of @LINE" mentioned in the section "FileCheck Pseudo Numeric… | |||||
probinsonUnsubmitted Done ReplyI don't know about James but I would prefer that the commentary say "legacy @LINE expression" and the parameter could be named LineExpr. probinson: I don't know about James but I would prefer that the commentary say "legacy @LINE expression"… | |||||
thopreAuthorUnsubmitted Done ReplyI went for LegacyLineExpr then since when false @LINE is also allowed and when true it limits what can be done with @LINE. thopre: I went for LegacyLineExpr then since when false @LINE is also allowed and when true it limits… | |||||
jhendersonUnsubmitted Done ReplyHow about IsLegacyLineExpr? It's a bit more verbose but maybe a little clearer too. Otherwise LegacyLineExpr is okay. It's just that the variable isn't actually an expression itself. jhenderson: How about `IsLegacyLineExpr`? It's a bit more verbose but maybe a little clearer too. Otherwise… | |||||
421 | /// substituted, or nullptr if parsing fails, in which case errors are | 442 | /// Sets \p NumExprAST to point to the class instance representing the | ||
Done Replysubstitued -> substituted jhenderson: substitued -> substituted | |||||
422 | /// reported on \p SM. Sets \p DefinedNumericVariable to point to the class | 443 | /// numeric expression whose value must be substituted. Also sets | ||
423 | /// representing the numeric variable defined in this numeric substitution | 444 | /// \p DefinedNumericVariable to point to the class representing the numeric | ||
424 | /// block, or nullptr if this block does not define any variable. | 445 | /// variable defined in this numeric substitution block, or nullptr if this | ||
425 | FileCheckNumExpr *parseNumericSubstitutionBlock( | 446 | /// block does not defined any variable. \returns whether parsing fails, in | ||
jhendersonUnsubmitted Done Replydefined -> define jhenderson: defined -> define | |||||
426 | StringRef Expr, FileCheckNumericVariable *&DefinedNumericVariable, | 447 | /// which case errors are reported on \p SM. | ||
448 | bool parseNumericSubstitutionBlock( | ||||
449 | StringRef Expr, std::shared_ptr<FileCheckNumExprAST> &NumExprAST, | ||||
450 | FileCheckNumericVariable *&DefinedNumericVariable, bool Legacy, | ||||
427 | const SourceMgr &SM) const; | 451 | const SourceMgr &SM) const; | ||
428 | /// Parses the pattern in \p PatternStr and initializes this FileCheckPattern | 452 | /// Parses the pattern in \p PatternStr and initializes this FileCheckPattern | ||
429 | /// instance accordingly. | 453 | /// instance accordingly. | ||
430 | /// | 454 | /// | ||
431 | /// \p Prefix provides which prefix is being matched, \p Req describes the | 455 | /// \p Prefix provides which prefix is being matched, \p Req describes the | ||
432 | /// global options that influence the parsing such as whitespace | 456 | /// global options that influence the parsing such as whitespace | ||
433 | /// canonicalization, \p SM provides the SourceMgr used for error reports. | 457 | /// canonicalization, \p SM provides the SourceMgr used for error reports. | ||
434 | /// \returns true in case of an error, false otherwise. | 458 | /// \returns true in case of an error, false otherwise. | ||
435 | bool parsePattern(StringRef PatternStr, StringRef Prefix, SourceMgr &SM, | 459 | bool parsePattern(StringRef PatternStr, StringRef Prefix, SourceMgr &SM, | ||
436 | const FileCheckRequest &Req); | 460 | const FileCheckRequest &Req); | ||
437 | /// Matches the pattern string against the input buffer \p Buffer | 461 | /// Matches the pattern string against the input buffer \p Buffer | ||
438 | /// | 462 | /// | ||
439 | /// \returns the position that is matched or npos if there is no match. If | 463 | /// \returns the position that is matched or npos if there is no match. If | ||
440 | /// there is a match, updates \p MatchLen with the size of the matched | 464 | /// there is a match, updates \p MatchLen with the size of the matched | ||
441 | /// string. | 465 | /// string. | ||
442 | /// | 466 | /// | ||
443 | /// The GlobalVariableTable StringMap in the FileCheckPatternContext class | 467 | /// The GlobalVariableTable StringMap in the FileCheckPatternContext class | ||
444 | /// instance provides the current values of FileCheck string variables and | 468 | /// instance provides the current values of FileCheck string variables and | ||
445 | /// is updated if this match defines new values. Likewise, the | 469 | /// is updated if this match defines new values. Likewise, the | ||
446 | /// GlobalNumericVariableTable StringMap in the same class provides the | 470 | /// GlobalNumericVariableTable StringMap in the same class provides the | ||
447 | /// current values of FileCheck numeric variables and is updated if this | 471 | /// current values of FileCheck numeric variables and is updated if this | ||
448 | /// match defines new numeric values. | 472 | /// match defines new numeric values. | ||
449 | size_t match(StringRef Buffer, size_t &MatchLen, const SourceMgr &SM) const; | 473 | size_t match(StringRef Buffer, size_t &MatchLen, const SourceMgr &SM) const; | ||
450 | /// Prints the value of successful substitutions or the name of the undefined | 474 | /// Prints the value of successful substitutions or the name of the undefined | ||
451 | /// string or numeric variable preventing a successful substitution. | 475 | /// string or numeric variables preventing a successful substitution. | ||
452 | void printSubstitutions(const SourceMgr &SM, StringRef Buffer, | 476 | void printSubstitutions(const SourceMgr &SM, StringRef Buffer, | ||
453 | SMRange MatchRange = None) const; | 477 | SMRange MatchRange = None) const; | ||
454 | void printFuzzyMatch(const SourceMgr &SM, StringRef Buffer, | 478 | void printFuzzyMatch(const SourceMgr &SM, StringRef Buffer, | ||
455 | std::vector<FileCheckDiag> *Diags) const; | 479 | std::vector<FileCheckDiag> *Diags) const; | ||
456 | 480 | | |||
457 | bool hasVariable() const { | 481 | bool hasVariable() const { | ||
458 | return !(Substitutions.empty() && VariableDefs.empty()); | 482 | return !(Substitutions.empty() && VariableDefs.empty()); | ||
459 | } | 483 | } | ||
Show All 12 Lines | 489 | private: | |||
472 | /// Finds the closing sequence of a regex variable usage or definition. | 496 | /// Finds the closing sequence of a regex variable usage or definition. | ||
473 | /// | 497 | /// | ||
474 | /// \p Str has to point in the beginning of the definition (right after the | 498 | /// \p Str has to point in the beginning of the definition (right after the | ||
475 | /// opening sequence). \p SM holds the SourceMgr used for error repporting. | 499 | /// opening sequence). \p SM holds the SourceMgr used for error repporting. | ||
476 | /// \returns the offset of the closing sequence within Str, or npos if it | 500 | /// \returns the offset of the closing sequence within Str, or npos if it | ||
477 | /// was not found. | 501 | /// was not found. | ||
478 | size_t FindRegexVarEnd(StringRef Str, SourceMgr &SM); | 502 | size_t FindRegexVarEnd(StringRef Str, SourceMgr &SM); | ||
479 | 503 | | |||
480 | /// Parses \p Expr for the use of a numeric variable. \returns the pointer to | 504 | /// Parses \p Expr for the use of a numeric variable. \returns the pointer to | ||
481 | /// the class instance representing that variable if successful, or nullptr | 505 | /// the class instance representing that variable if successful, or nullptr | ||
482 | /// otherwise, in which case errors are reported on \p SM. | 506 | /// otherwise, in which case errors are reported on \p SM. | ||
483 | FileCheckNumericVariable *parseNumericVariableUse(StringRef &Expr, | 507 | std::shared_ptr<FileCheckNumericVariable> | ||
Done ReplyThis comment still mentions Expr and SM. grimar: This comment still mentions `Expr` and `SM`. | |||||
508 | parseNumericVariableUse(StringRef &Expr, const SourceMgr &SM) const; | ||||
509 | enum AllowedOperand { LegacyVar, LegacyLiteral, Any }; | ||||
jhendersonUnsubmitted Done ReplyI don't like the terminology "Legacy", as it doesn't convey any useful meaning, unless defined somewhere clearly. jhenderson: I don't like the terminology "Legacy", as it doesn't convey any useful meaning, unless defined… | |||||
thopreAuthorUnsubmitted Done ReplySee above. thopre: See above. | |||||
Done ReplyThese could be { LineVar, Literal, Any } perhaps. probinson: These could be `{ LineVar, Literal, Any }` perhaps. | |||||
Done ReplyPerhaps worth making this an enum class. jhenderson: Perhaps worth making this an `enum class`. | |||||
510 | /// Parses \p Expr for use of a numeric operand. Accepts both literal values | ||||
511 | /// and numeric variables, depending on the value of \p AllowedOperandFlag. | ||||
Done ReplyI don't see a parameter named AllowedOperandFlag. probinson: I don't see a parameter named AllowedOperandFlag. | |||||
512 | /// \returns the class representing that operand in the AST of the numeric | ||||
513 | /// expression or nullptr if parsing fails in which case errors are reported | ||||
Done Reply"against \p SM"? I'm not sure I understand this change in terminology. jhenderson: "against \p SM"? I'm not sure I understand this change in terminology. | |||||
Done ReplyI've used it in other place already. I'm using "against" because the diagnostic relates to the buffer held by SM (it is created via SM.GetMessage) thopre: I've used it in other place already. I'm using "against" because the diagnostic relates to the… | |||||
Done ReplyIs my explanation satisfying or do you want to use another phrasing? thopre: Is my explanation satisfying or do you want to use another phrasing? | |||||
Done ReplyYes, it's fine. Not the phrasing I would use but I don't care much about it. jhenderson: Yes, it's fine. Not the phrasing I would use but I don't care much about it. | |||||
514 | /// on \p SM. | ||||
515 | std::shared_ptr<FileCheckNumExprAST> | ||||
516 | parseNumericOperand(StringRef &Expr, enum AllowedOperand AO, | ||||
jhendersonUnsubmitted Done ReplyI don't think you need enum here. Same applies throughout the code. jhenderson: I don't think you need `enum` here. Same applies throughout the code. | |||||
484 | const SourceMgr &SM) const; | 517 | const SourceMgr &SM) const; | ||
485 | /// Parses \p Expr for a binary operation. | 518 | /// Parses \p Expr for a binary operation. The left operand of this binary | ||
486 | /// \returns the class representing the binary operation of the numeric | 519 | /// operation is given in \p LeftOp and \p Legacy indicates whether we are | ||
Done Reply\p LineExpr ... parsing a @LINE expression. probinson: \p LineExpr ... parsing a @LINE expression. | |||||
487 | /// expression, or nullptr if parsing fails, in which case errors are | 520 | /// parsing a legacy numeric expression. \returns the class representing the | ||
488 | /// reported on \p SM. | 521 | /// binary operation in the AST of the numeric expression, or nullptr if | ||
489 | FileCheckNumExpr *parseBinop(StringRef &Expr, const SourceMgr &SM) const; | 522 | /// parsing fails, in which case errors are reported on \p SM. | ||
523 | std::shared_ptr<FileCheckNumExprAST> | ||||
524 | parseBinop(StringRef &Expr, std::shared_ptr<FileCheckNumExprAST> LeftOp, | ||||
525 | bool Legacy, const SourceMgr &SM) const; | ||||
490 | }; | 526 | }; | ||
491 | 527 | | |||
492 | //===----------------------------------------------------------------------===// | 528 | //===----------------------------------------------------------------------===// | ||
493 | /// Summary of a FileCheck diagnostic. | 529 | /// Summary of a FileCheck diagnostic. | ||
494 | //===----------------------------------------------------------------------===// | 530 | //===----------------------------------------------------------------------===// | ||
495 | 531 | | |||
496 | struct FileCheckDiag { | 532 | struct FileCheckDiag { | ||
497 | /// What is the FileCheck directive for this diagnostic? | 533 | /// What is the FileCheck directive for this diagnostic? | ||
▲ Show 20 Lines • Show All 137 Lines • Show Last 20 Lines |
Are there other kinds of expressions except "numeric expressions"? Just wondering if we can simplify the terminology a little e.g. by simply referring to them as expressions and the FileCheckNumExprAST can become FileCheckExpressionAST.