blob: 41a8adcee46f06906b80a29643302a76def2dfd7 [file] [log] [blame]
Shinichiro Hamaji1d545aa2015-06-23 15:29:13 +09001// Copyright 2015 Google Inc. All rights reserved
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
Fumitoshi Ukai744bb2b2015-06-25 00:10:52 +090015// +build ignore
16
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090017#include "value.h"
18
19#include <vector>
20
21#include "eval.h"
22#include "func.h"
23#include "log.h"
24#include "stringprintf.h"
25#include "strutil.h"
26#include "var.h"
27
28Evaluable::Evaluable() {
29}
30
31Evaluable::~Evaluable() {
32}
33
34shared_ptr<string> Evaluable::Eval(Evaluator* ev) const {
35 shared_ptr<string> s = make_shared<string>();
36 Eval(ev, s.get());
37 return s;
38}
39
40Value::Value() {
41}
42
43Value::~Value() {
44}
45
46string Value::DebugString() const {
Colin Cross3f186902015-07-29 17:14:53 -070047 if (static_cast<const Value*>(this)) {
Shinichiro Hamaji810fd032015-06-17 04:38:03 +090048 return NoLineBreak(DebugString_());
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090049 }
50 return "(null)";
51}
52
53class Literal : public Value {
54 public:
55 explicit Literal(StringPiece s)
56 : s_(s) {
57 }
58
59 StringPiece val() const { return s_; }
60
61 virtual void Eval(Evaluator*, string* s) const override {
62 s->append(s_.begin(), s_.end());
63 }
64
65 virtual string DebugString_() const override {
66 return s_.as_string();
67 }
68
69 private:
70 StringPiece s_;
71};
72
73class Expr : public Value {
74 public:
75 Expr() {
76 }
77
78 virtual ~Expr() {
79 for (Value* v : vals_) {
80 delete v;
81 }
82 }
83
84 // Takes the ownership of |v|.
85 void AddValue(Value* v) {
86 vals_.push_back(v);
87 }
88
89 virtual void Eval(Evaluator* ev, string* s) const override {
90 for (Value* v : vals_) {
91 v->Eval(ev, s);
92 }
93 }
94
95 virtual string DebugString_() const override {
96 string r;
97 for (Value* v : vals_) {
98 if (r.empty()) {
99 r += "Expr(";
100 } else {
101 r += ", ";
102 }
103 r += v->DebugString();
104 }
Shinichiro Hamajibaf2c382015-07-07 14:53:02 +0900105 if (!r.empty())
106 r += ")";
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900107 return r;
108 }
109
110 virtual Value* Compact() {
111 if (vals_.size() != 1) {
112 return this;
113 }
114 Value* r = vals_[0];
115 vals_.clear();
116 delete this;
117 return r;
118 }
119
120 private:
121 vector<Value*> vals_;
122};
123
Shinichiro Hamaji65489db2015-06-29 20:44:26 +0900124class SymRef : public Value {
125 public:
126 explicit SymRef(Symbol n)
127 : name_(n) {
128 }
129 virtual ~SymRef() {
130 }
131
132 virtual shared_ptr<string> Eval(Evaluator* ev) const override {
133 Var* v = ev->LookupVar(name_);
134 return v->Eval(ev);
135 }
136
137 virtual void Eval(Evaluator* ev, string* s) const override {
138 Var* v = ev->LookupVar(name_);
139 v->Eval(ev, s);
140 }
141
142 virtual string DebugString_() const override {
143 return StringPrintf("SymRef(%s)", name_.c_str());
144 }
145
146 private:
147 Symbol name_;
148};
149
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900150class VarRef : public Value {
151 public:
152 explicit VarRef(Value* n)
153 : name_(n) {
154 }
155 virtual ~VarRef() {
156 delete name_;
157 }
158
159 virtual shared_ptr<string> Eval(Evaluator* ev) const override {
160 shared_ptr<string> name = name_->Eval(ev);
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900161 Var* v = ev->LookupVar(Intern(*name));
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900162 return v->Eval(ev);
163 }
164
165 virtual void Eval(Evaluator* ev, string* s) const override {
166 shared_ptr<string> name = name_->Eval(ev);
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900167 Var* v = ev->LookupVar(Intern(*name));
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900168 v->Eval(ev, s);
169 }
170
171 virtual string DebugString_() const override {
172 return StringPrintf("VarRef(%s)", name_->DebugString().c_str());
173 }
174
175 private:
176 Value* name_;
177};
178
Shinichiro Hamaji02fc55b2015-06-16 17:19:07 +0900179class VarSubst : public Value {
180 public:
181 explicit VarSubst(Value* n, Value* p, Value* s)
182 : name_(n), pat_(p), subst_(s) {
183 }
184 virtual ~VarSubst() {
185 delete name_;
186 delete pat_;
187 delete subst_;
188 }
189
190 virtual void Eval(Evaluator* ev, string* s) const override {
191 shared_ptr<string> name = name_->Eval(ev);
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900192 Var* v = ev->LookupVar(Intern(*name));
Shinichiro Hamaji02fc55b2015-06-16 17:19:07 +0900193 shared_ptr<string> value = v->Eval(ev);
Shinichiro Hamajia6a17a42015-06-18 20:11:19 +0900194 shared_ptr<string> pat_str = pat_->Eval(ev);
Shinichiro Hamaji02fc55b2015-06-16 17:19:07 +0900195 shared_ptr<string> subst = subst_->Eval(ev);
Shinichiro Hamaji37591ce2015-06-16 19:36:05 +0900196 WordWriter ww(s);
Shinichiro Hamajia6a17a42015-06-18 20:11:19 +0900197 Pattern pat(*pat_str);
Shinichiro Hamaji02fc55b2015-06-16 17:19:07 +0900198 for (StringPiece tok : WordScanner(*value)) {
Shinichiro Hamaji37591ce2015-06-16 19:36:05 +0900199 ww.MaybeAddWhitespace();
Shinichiro Hamajia6a17a42015-06-18 20:11:19 +0900200 pat.AppendSubstRef(tok, *subst, s);
Shinichiro Hamaji02fc55b2015-06-16 17:19:07 +0900201 }
202 }
203
204 virtual string DebugString_() const override {
205 return StringPrintf("VarSubst(%s:%s=%s)",
206 name_->DebugString().c_str(),
207 pat_->DebugString().c_str(),
208 subst_->DebugString().c_str());
209 }
210
211 private:
212 Value* name_;
213 Value* pat_;
214 Value* subst_;
215};
216
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900217class Func : public Value {
218 public:
219 explicit Func(FuncInfo* fi)
220 : fi_(fi) {
221 }
222
Shinichiro Hamajid0e188e2015-06-16 18:53:01 +0900223 ~Func() {
224 for (Value* a : args_)
225 delete a;
226 }
227
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900228 virtual void Eval(Evaluator* ev, string* s) const override {
229 LOG("Invoke func %s(%s)", name(), JoinValues(args_, ",").c_str());
230 fi_->func(args_, ev, s);
231 }
232
233 virtual string DebugString_() const override {
234 return StringPrintf("Func(%s %s)",
235 fi_->name,
236 JoinValues(args_, ",").c_str());
237 }
238
239 void AddArg(Value* v) {
240 args_.push_back(v);
241 }
242
243 const char* name() const { return fi_->name; }
244 int arity() const { return fi_->arity; }
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900245 int min_arity() const { return fi_->min_arity; }
246 bool trim_space() const { return fi_->trim_space; }
247 bool trim_right_space_1st() const { return fi_->trim_right_space_1st; }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900248
249 private:
250 FuncInfo* fi_;
251 vector<Value*> args_;
252};
253
254static char CloseParen(char c) {
255 switch (c) {
256 case '(':
257 return ')';
258 case '{':
259 return '}';
260 }
261 return 0;
262}
263
264static size_t SkipSpaces(StringPiece s, const char* terms) {
265 for (size_t i = 0; i < s.size(); i++) {
266 char c = s[i];
Shinichiro Hamaji64cf8912015-06-26 09:25:19 +0900267 if (strchr(terms, c))
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900268 return i;
Shinichiro Hamaji64cf8912015-06-26 09:25:19 +0900269 if (!isspace(c)) {
270 if (c != '\\')
271 return i;
272 char n = s.get(i + 1);
273 if (n != '\r' && n != '\n')
274 return i;
275 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900276 }
277 return s.size();
278}
279
Shinichiro Hamaji4d77b842015-06-27 06:10:18 +0900280bool ShouldHandleComments(ParseExprOpt opt) {
281 return opt != ParseExprOpt::DEFINE && opt != ParseExprOpt::COMMAND;
282}
283
Shinichiro Hamaji663a35b2015-07-05 01:50:41 +0900284void ParseFunc(const Loc& loc,
285 Func* f, StringPiece s, size_t i, char* terms,
286 size_t* index_out) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900287 terms[1] = ',';
288 terms[2] = '\0';
289 i += SkipSpaces(s.substr(i), terms);
290 if (i == s.size()) {
291 *index_out = i;
Shinichiro Hamaji663a35b2015-07-05 01:50:41 +0900292 return;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900293 }
294
295 int nargs = 1;
296 while (true) {
297 if (f->arity() && nargs >= f->arity()) {
298 terms[1] = '\0'; // Drop ','.
299 }
300
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900301 if (f->trim_space()) {
Shinichiro Hamajic8b4b1c2015-07-07 14:57:53 +0900302 for (; i < s.size(); i++) {
303 if (isspace(s[i]))
304 continue;
305 if (s[i] == '\\') {
306 char c = s.get(i+1);
307 if (c == '\r' || c == '\n')
308 continue;
309 }
310 break;
311 }
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900312 }
313 const bool trim_right_space = (f->trim_space() ||
314 (nargs == 1 && f->trim_right_space_1st()));
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900315 size_t n;
Shinichiro Hamaji4d77b842015-06-27 06:10:18 +0900316 Value* v = ParseExprImpl(loc, s.substr(i), terms, ParseExprOpt::FUNC,
Shinichiro Hamaji66bd7bc2015-06-19 16:54:06 +0900317 &n, trim_right_space);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900318 // TODO: concatLine???
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900319 f->AddArg(v);
320 i += n;
Shinichiro Hamaji663a35b2015-07-05 01:50:41 +0900321 if (i == s.size()) {
322 ERROR("%s:%d: *** unterminated call to function '%s': "
323 "missing '%c'.",
324 LOCF(loc), f->name(), terms[0]);
325 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900326 nargs++;
327 if (s[i] == terms[0]) {
328 i++;
329 break;
330 }
331 i++; // Should be ','.
332 if (i == s.size())
333 break;
334 }
335
Shinichiro Hamajifead3b72015-06-18 15:31:15 +0900336 if (nargs <= f->min_arity()) {
Shinichiro Hamaji36b326f2015-06-26 08:56:13 +0900337 ERROR("%s:%d: *** insufficient number of arguments (%d) to function `%s'.",
338 LOCF(loc), nargs - 1, f->name());
Shinichiro Hamaji81b2d0f2015-06-16 19:25:35 +0900339 }
340
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900341 *index_out = i;
Shinichiro Hamaji663a35b2015-07-05 01:50:41 +0900342 return;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900343}
344
Shinichiro Hamaji36b326f2015-06-26 08:56:13 +0900345Value* ParseDollar(const Loc& loc, StringPiece s, size_t* index_out) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900346 CHECK(s.size() >= 2);
347 CHECK(s[0] == '$');
348 CHECK(s[1] != '$');
349
350 char cp = CloseParen(s[1]);
351 if (cp == 0) {
352 *index_out = 2;
Shinichiro Hamaji65489db2015-06-29 20:44:26 +0900353 return new SymRef(Intern(s.substr(1, 1)));
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900354 }
355
356 char terms[] = {cp, ':', ' ', 0};
357 for (size_t i = 2;;) {
358 size_t n;
Shinichiro Hamaji36b326f2015-06-26 08:56:13 +0900359 Value* vname = ParseExprImpl(loc, s.substr(i), terms,
360 ParseExprOpt::NORMAL, &n);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900361 i += n;
362 if (s[i] == cp) {
363 *index_out = i + 1;
Shinichiro Hamaji65489db2015-06-29 20:44:26 +0900364 if (Literal* lit = dynamic_cast<Literal*>(vname)) {
365 Value* r = new SymRef(Intern(lit->val()));
366 delete lit;
367 return r;
368 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900369 return new VarRef(vname);
370 }
371
Shinichiro Hamajia0315fc2015-06-26 08:15:55 +0900372 if (s[i] == ' ' || s[i] == '\\') {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900373 // ${func ...}
Shinichiro Hamaji65489db2015-06-29 20:44:26 +0900374 if (Literal* lit = dynamic_cast<Literal*>(vname)) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900375 if (FuncInfo* fi = GetFuncInfo(lit->val())) {
Shinichiro Hamajid0e188e2015-06-16 18:53:01 +0900376 delete lit;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900377 Func* func = new Func(fi);
Shinichiro Hamaji663a35b2015-07-05 01:50:41 +0900378 ParseFunc(loc, func, s, i+1, terms, index_out);
379 return func;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900380 }
381 }
382
383 // Not a function. Drop ' ' from |terms| and parse it
384 // again. This is inefficient, but this code path should be
385 // rarely used.
386 delete vname;
387 terms[2] = 0;
388 i = 2;
389 continue;
390 }
391
392 if (s[i] == ':') {
Shinichiro Hamaji02fc55b2015-06-16 17:19:07 +0900393 terms[2] = '\0';
394 terms[1] = '=';
395 size_t n;
Shinichiro Hamaji36b326f2015-06-26 08:56:13 +0900396 Value* pat = ParseExprImpl(loc, s.substr(i+1), terms,
397 ParseExprOpt::NORMAL, &n);
Shinichiro Hamaji02fc55b2015-06-16 17:19:07 +0900398 i += 1 + n;
399 if (s[i] == cp) {
400 Expr* v = new Expr;
401 v->AddValue(vname);
402 v->AddValue(new Literal(":"));
403 v->AddValue(pat);
Shinichiro Hamajif72e0242015-06-26 00:38:27 +0900404 *index_out = i + 1;
Shinichiro Hamaji02fc55b2015-06-16 17:19:07 +0900405 return new VarRef(v);
406 }
407
408 terms[1] = '\0';
Shinichiro Hamaji36b326f2015-06-26 08:56:13 +0900409 Value* subst = ParseExprImpl(loc, s.substr(i+1), terms,
410 ParseExprOpt::NORMAL, &n);
Shinichiro Hamaji02fc55b2015-06-16 17:19:07 +0900411 i += 1 + n;
Shinichiro Hamajif72e0242015-06-26 00:38:27 +0900412 *index_out = i + 1;
Shinichiro Hamaji02fc55b2015-06-16 17:19:07 +0900413 return new VarSubst(vname->Compact(), pat, subst);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900414 }
415
Shinichiro Hamaji0f7af702015-07-05 02:00:18 +0900416 // GNU make accepts expressions like $((). See unmatched_paren*.mk
417 // for detail.
Shinichiro Hamaji663a35b2015-07-05 01:50:41 +0900418 size_t found = s.find(cp);
Shinichiro Hamaji0f7af702015-07-05 02:00:18 +0900419 if (found != string::npos) {
420 *index_out = s.size();
421 return new SymRef(Intern(s.substr(2, found-2)));
422 }
Shinichiro Hamaji36b326f2015-06-26 08:56:13 +0900423 ERROR("%s:%d: *** unterminated variable reference.", LOCF(loc));
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900424 }
425}
426
Shinichiro Hamaji36b326f2015-06-26 08:56:13 +0900427Value* ParseExprImpl(const Loc& loc,
428 StringPiece s, const char* terms, ParseExprOpt opt,
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900429 size_t* index_out, bool trim_right_space) {
Shinichiro Hamaji47898a82015-06-19 16:45:33 +0900430 if (s.get(s.size() - 1) == '\r')
431 s.remove_suffix(1);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900432
433 Expr* r = new Expr;
434 size_t b = 0;
435 char save_paren = 0;
436 int paren_depth = 0;
437 size_t i;
438 for (i = 0; i < s.size(); i++) {
439 char c = s[i];
440 if (terms && strchr(terms, c)) {
441 break;
442 }
443
444 // Handle a comment.
Shinichiro Hamaji4d77b842015-06-27 06:10:18 +0900445 if (!terms && c == '#' && ShouldHandleComments(opt)) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900446 if (i > b)
447 r->AddValue(new Literal(s.substr(b, i-b)));
448 bool was_backslash = false;
449 for (; i < s.size() && !(s[i] == '\n' && !was_backslash); i++) {
450 was_backslash = !was_backslash && s[i] == '\\';
451 }
452 *index_out = i;
453 return r->Compact();
454 }
455
456 if (c == '$') {
457 if (i + 1 >= s.size()) {
458 break;
459 }
460
461 if (i > b)
462 r->AddValue(new Literal(s.substr(b, i-b)));
463
464 if (s[i+1] == '$') {
Shinichiro Hamaji388e8582015-07-03 16:51:46 +0900465 r->AddValue(new Literal(StringPiece("$")));
Shinichiro Hamajib8a2bb12015-06-26 09:04:57 +0900466 i += 1;
467 b = i + 1;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900468 continue;
469 }
470
471 if (terms && strchr(terms, s[i+1])) {
472 *index_out = i + 1;
473 return r->Compact();
474 }
475
476 size_t n;
Shinichiro Hamaji36b326f2015-06-26 08:56:13 +0900477 Value* v = ParseDollar(loc, s.substr(i), &n);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900478 i += n;
479 b = i;
480 i--;
481 r->AddValue(v);
482 continue;
483 }
484
Shinichiro Hamaji4d77b842015-06-27 06:10:18 +0900485 if ((c == '(' || c == '{') && opt == ParseExprOpt::FUNC) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900486 char cp = CloseParen(c);
487 if (terms && terms[0] == cp) {
488 paren_depth++;
489 save_paren = cp;
490 terms++;
491 } else if (cp == save_paren) {
492 paren_depth++;
493 }
494 continue;
495 }
496
497 if (c == save_paren) {
498 paren_depth--;
499 if (paren_depth == 0) {
500 terms--;
501 save_paren = 0;
502 }
503 }
504
Shinichiro Hamaji66bd7bc2015-06-19 16:54:06 +0900505 if (c == '\\' && i + 1 < s.size() && opt != ParseExprOpt::COMMAND) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900506 char n = s[i+1];
507 if (n == '\\') {
508 i++;
509 continue;
510 }
Shinichiro Hamaji4d77b842015-06-27 06:10:18 +0900511 if (n == '#' && ShouldHandleComments(opt)) {
Shinichiro Hamaji7fb82b02015-06-26 00:06:51 +0900512 r->AddValue(new Literal(s.substr(b, i-b)));
513 i++;
514 b = i;
515 continue;
516 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900517 if (n == '\r' || n == '\n') {
Shinichiro Hamajia0315fc2015-06-26 08:15:55 +0900518 if (terms && strchr(terms, ' ')) {
519 break;
520 }
Shinichiro Hamaji47898a82015-06-19 16:45:33 +0900521 if (i > b) {
Shinichiro Hamaji8f464582015-06-24 20:41:46 +0900522 r->AddValue(new Literal(TrimRightSpace(s.substr(b, i-b))));
Shinichiro Hamaji47898a82015-06-19 16:45:33 +0900523 }
Shinichiro Hamaji388e8582015-07-03 16:51:46 +0900524 r->AddValue(new Literal(StringPiece(" ")));
Shinichiro Hamaji8f464582015-06-24 20:41:46 +0900525 for (i++; i < s.size(); i++) {
526 if (!isspace(s[i]) &&
527 (s[i] != '\\' || (s.get(i+1) != '\r' && s.get(i+1) != '\n'))) {
528 break;
529 }
530 }
531 b = i;
532 i--;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900533 }
534 }
535 }
536
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900537 if (i > b) {
538 StringPiece rest = s.substr(b, i-b);
539 if (trim_right_space)
540 rest = TrimRightSpace(rest);
541 if (!rest.empty())
542 r->AddValue(new Literal(rest));
543 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900544 *index_out = i;
545 return r->Compact();
546}
547
Shinichiro Hamaji36b326f2015-06-26 08:56:13 +0900548Value* ParseExpr(const Loc& loc, StringPiece s, ParseExprOpt opt) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900549 size_t n;
Shinichiro Hamaji36b326f2015-06-26 08:56:13 +0900550 return ParseExprImpl(loc, s, NULL, opt, &n);
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900551}
552
Shinichiro Hamaji76ff9832015-06-18 17:11:22 +0900553string JoinValues(const vector<Value*>& vals, const char* sep) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900554 vector<string> val_strs;
555 for (Value* v : vals) {
556 val_strs.push_back(v->DebugString());
557 }
558 return JoinStrings(val_strs, sep);
559}
Shinichiro Hamaji4c469b32015-06-15 19:53:36 +0900560
Shinichiro Hamaji784b9952015-06-23 14:29:32 +0900561Value* NewExpr2(Value* v1, Value* v2) {
562 Expr* e = new Expr();
563 e->AddValue(v1);
564 e->AddValue(v2);
565 return e;
566}
567
Shinichiro Hamaji4c469b32015-06-15 19:53:36 +0900568Value* NewExpr3(Value* v1, Value* v2, Value* v3) {
569 Expr* e = new Expr();
570 e->AddValue(v1);
571 e->AddValue(v2);
572 e->AddValue(v3);
573 return e;
574}
575
Shinichiro Hamajib74b8902015-06-22 18:22:30 +0900576Value* NewLiteral(StringPiece s) {
Shinichiro Hamaji4c469b32015-06-15 19:53:36 +0900577 return new Literal(s);
578}