blob: a93d307a283d2e76bd5ddf0efd1ea283da13b78b [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 "eval.h"
18
Shinichiro Hamaji861bd642015-06-19 16:59:13 +090019#include <errno.h>
Shinichiro Hamaji6e6de8d2015-06-18 11:12:58 +090020#include <glob.h>
Shinichiro Hamaji861bd642015-06-19 16:59:13 +090021#include <string.h>
Shinichiro Hamaji6e6de8d2015-06-18 11:12:58 +090022
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090023#include "ast.h"
24#include "file.h"
Shinichiro Hamaji6e6de8d2015-06-18 11:12:58 +090025#include "file_cache.h"
Shinichiro Hamaji45a0c762015-06-26 06:47:10 +090026#include "parser.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090027#include "rule.h"
28#include "strutil.h"
Shinichiro Hamajie7992752015-06-29 18:38:35 +090029#include "symtab.h"
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090030#include "value.h"
31#include "var.h"
32
33EvalResult::~EvalResult() {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090034 for (auto p : rule_vars)
35 delete p.second;
36 delete vars;
37}
38
39Evaluator::Evaluator(const Vars* vars)
40 : in_vars_(vars),
41 vars_(new Vars()),
Shinichiro Hamaji784b9952015-06-23 14:29:32 +090042 last_rule_(NULL),
Shinichiro Hamajife002942015-07-02 03:42:27 +090043 current_scope_(NULL),
44 avoid_io_(false) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090045}
46
47Evaluator::~Evaluator() {
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +090048 // delete vars_;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090049 // for (auto p : rule_vars) {
50 // delete p.second;
51 // }
52}
53
Shinichiro Hamajie7992752015-06-29 18:38:35 +090054Var* Evaluator::EvalRHS(Symbol lhs, Value* rhs_v, StringPiece orig_rhs,
Shinichiro Hamaji420f7752015-06-26 04:02:02 +090055 AssignOp op, bool is_override) {
Shinichiro Hamajif62e9a72015-06-26 04:18:21 +090056 VarOrigin origin = (
57 (is_bootstrap_ ? VarOrigin::DEFAULT :
58 is_override ? VarOrigin::OVERRIDE : VarOrigin::FILE));
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090059
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090060 Var* rhs = NULL;
Shinichiro Hamaji4c469b32015-06-15 19:53:36 +090061 bool needs_assign = true;
Shinichiro Hamaji784b9952015-06-23 14:29:32 +090062 switch (op) {
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090063 case AssignOp::COLON_EQ:
Shinichiro Hamaji784b9952015-06-23 14:29:32 +090064 rhs = new SimpleVar(rhs_v->Eval(this), origin);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090065 break;
66 case AssignOp::EQ:
Shinichiro Hamaji784b9952015-06-23 14:29:32 +090067 rhs = new RecursiveVar(rhs_v, origin, orig_rhs);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090068 break;
69 case AssignOp::PLUS_EQ: {
70 Var* prev = LookupVarInCurrentScope(lhs);
71 if (!prev->IsDefined()) {
Shinichiro Hamaji784b9952015-06-23 14:29:32 +090072 rhs = new RecursiveVar(rhs_v, origin, orig_rhs);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090073 } else {
Shinichiro Hamaji784b9952015-06-23 14:29:32 +090074 prev->AppendVar(this, rhs_v);
Shinichiro Hamaji4c469b32015-06-15 19:53:36 +090075 rhs = prev;
76 needs_assign = false;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090077 }
78 break;
79 }
80 case AssignOp::QUESTION_EQ: {
81 Var* prev = LookupVarInCurrentScope(lhs);
82 if (!prev->IsDefined()) {
Shinichiro Hamaji784b9952015-06-23 14:29:32 +090083 rhs = new RecursiveVar(rhs_v, origin, orig_rhs);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090084 } else {
Shinichiro Hamajibef30602015-06-18 17:14:01 +090085 rhs = prev;
86 needs_assign = false;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090087 }
88 break;
89 }
90 }
91
Shinichiro Hamajie7992752015-06-29 18:38:35 +090092 LOG("Assign: %s=%s", lhs.c_str(), rhs->DebugString().c_str());
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +090093 if (needs_assign) {
94 return rhs;
95 }
96 return NULL;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090097}
98
Shinichiro Hamaji784b9952015-06-23 14:29:32 +090099void Evaluator::EvalAssign(const AssignAST* ast) {
100 loc_ = ast->loc();
101 last_rule_ = NULL;
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900102 Symbol lhs = Intern(*ast->lhs->Eval(this));
Shinichiro Hamaji0d4deb62015-06-26 07:47:17 +0900103 if (lhs.empty())
104 Error("*** empty variable name.");
Shinichiro Hamaji0ea9e912015-06-26 04:24:38 +0900105 Var* rhs = EvalRHS(lhs, ast->rhs, ast->orig_rhs, ast->op,
106 ast->directive == AssignDirective::OVERRIDE);
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900107 if (rhs)
108 vars_->Assign(lhs, rhs);
Shinichiro Hamaji784b9952015-06-23 14:29:32 +0900109}
110
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900111void Evaluator::EvalRule(const RuleAST* ast) {
112 loc_ = ast->loc();
113 last_rule_ = NULL;
114
115 shared_ptr<string> expr = ast->expr->Eval(this);
116 // See semicolon.mk.
117 if (expr->find_first_not_of(" \t\n;") == string::npos)
118 return;
119
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +0900120 Rule* rule;
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900121 RuleVarAssignment rule_var;
Shinichiro Hamaji2928f462015-06-23 20:24:53 +0900122 ParseRule(loc_, *expr, ast->term, &rule, &rule_var);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900123
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +0900124 if (rule) {
Shinichiro Hamaji2928f462015-06-23 20:24:53 +0900125 if (ast->term == ';') {
126 rule->cmds.push_back(ast->after_term);
127 }
128
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +0900129 LOG("Rule: %s", rule->DebugString().c_str());
Shinichiro Hamaji0562c302015-06-19 15:30:49 +0900130 rules_.push_back(shared_ptr<Rule>(rule));
Shinichiro Hamaji9b16bda2015-06-19 14:25:17 +0900131 last_rule_ = rule;
132 return;
133 }
134
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900135 for (Symbol output : rule_var.outputs) {
Shinichiro Hamaji2a047892015-06-29 13:56:41 +0900136 auto p = rule_vars_.emplace(output, nullptr);
Shinichiro Hamaji784b9952015-06-23 14:29:32 +0900137 if (p.second) {
138 p.first->second = new Vars;
139 }
140
141 Value* rhs = ast->after_term;
142 if (!rule_var.rhs.empty()) {
143 Value* lit = NewLiteral(rule_var.rhs);
144 if (rhs) {
Shinichiro Hamaji5e3e3d22015-06-24 16:53:44 +0900145 // TODO: We always insert two whitespaces around the
146 // terminator. Preserve whitespaces properly.
147 if (ast->term == ';') {
148 rhs = NewExpr3(lit, NewLiteral(STRING_PIECE(" ; ")), rhs);
149 } else {
150 rhs = NewExpr3(lit, NewLiteral(STRING_PIECE(" = ")), rhs);
151 }
Shinichiro Hamaji784b9952015-06-23 14:29:32 +0900152 } else {
153 rhs = lit;
154 }
155 }
156
157 current_scope_ = p.first->second;
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900158 Symbol lhs = Intern(rule_var.lhs);
Shinichiro Hamajiffc52c32015-06-23 16:51:07 +0900159 Var* rhs_var = EvalRHS(lhs, rhs, STRING_PIECE("*TODO*"), rule_var.op);
160 if (rhs_var)
161 current_scope_->Assign(lhs, new RuleVar(rhs_var, rule_var.op));
Shinichiro Hamaji784b9952015-06-23 14:29:32 +0900162 current_scope_ = NULL;
163 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900164}
165
166void Evaluator::EvalCommand(const CommandAST* ast) {
167 loc_ = ast->loc();
168
169 if (!last_rule_) {
170 // TODO:
171 ERROR("TODO");
172 }
173
174 last_rule_->cmds.push_back(ast->expr);
Shinichiro Hamajiff4584d2015-06-24 17:45:14 +0900175 if (last_rule_->cmd_lineno == 0)
176 last_rule_->cmd_lineno = ast->loc().lineno;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900177 LOG("Command: %s", ast->expr->DebugString().c_str());
178}
179
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900180void Evaluator::EvalIf(const IfAST* ast) {
Shinichiro Hamaji6e6de8d2015-06-18 11:12:58 +0900181 loc_ = ast->loc();
Shinichiro Hamaji6e6de8d2015-06-18 11:12:58 +0900182
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900183 bool is_true;
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900184 switch (ast->op) {
185 case CondOp::IFDEF:
186 case CondOp::IFNDEF: {
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900187 Symbol lhs = Intern(*ast->lhs->Eval(this));
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900188 Var* v = LookupVarInCurrentScope(lhs);
189 shared_ptr<string> s = v->Eval(this);
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900190 is_true = (s->empty() == (ast->op == CondOp::IFNDEF));
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900191 break;
192 }
193 case CondOp::IFEQ:
194 case CondOp::IFNEQ: {
Shinichiro Hamajid146f4c2015-06-17 17:51:24 +0900195 shared_ptr<string> lhs = ast->lhs->Eval(this);
196 shared_ptr<string> rhs = ast->rhs->Eval(this);
197 is_true = ((*lhs == *rhs) == (ast->op == CondOp::IFEQ));
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900198 break;
199 }
200 default:
201 CHECK(false);
Shinichiro Hamaji8d503012015-07-03 16:26:15 +0900202 abort();
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900203 }
204
205 const vector<AST*>* asts;
206 if (is_true) {
Shinichiro Hamaji2847f092015-06-17 15:48:37 +0900207 asts = &ast->true_asts;
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900208 } else {
Shinichiro Hamaji2847f092015-06-17 15:48:37 +0900209 asts = &ast->false_asts;
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900210 }
211 for (AST* a : *asts) {
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +0900212 LOG("%s", a->DebugString().c_str());
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900213 a->Eval(this);
214 }
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900215}
216
Shinichiro Hamaji6e6de8d2015-06-18 11:12:58 +0900217void Evaluator::DoInclude(const char* fname, bool should_exist) {
Shinichiro Hamaji94d7a612015-06-29 18:16:11 +0900218 if (!should_exist && g_ignore_optional_include_pattern &&
219 Pattern(g_ignore_optional_include_pattern).Match(fname)) {
220 return;
221 }
222
Shinichiro Hamaji6e6de8d2015-06-18 11:12:58 +0900223 Makefile* mk = MakefileCacheManager::Get()->ReadMakefile(fname);
224 if (!mk->Exists()) {
225 if (should_exist) {
226 Error(StringPrintf(
Shinichiro Hamaji861bd642015-06-19 16:59:13 +0900227 "%s: %s\n"
228 "NOTE: kati does not support generating missing makefiles",
229 fname, strerror(errno)));
Shinichiro Hamaji6e6de8d2015-06-18 11:12:58 +0900230 }
231 return;
232 }
233
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900234 Var* var_list = LookupVar(Intern("MAKEFILE_LIST"));
235 var_list->AppendVar(this, NewLiteral(Intern(TrimLeadingCurdir(fname)).str()));
Shinichiro Hamaji6e6de8d2015-06-18 11:12:58 +0900236 for (AST* ast : mk->asts()) {
237 LOG("%s", ast->DebugString().c_str());
238 ast->Eval(this);
239 }
240}
241
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900242void Evaluator::EvalInclude(const IncludeAST* ast) {
Shinichiro Hamaji6e6de8d2015-06-18 11:12:58 +0900243 loc_ = ast->loc();
244 last_rule_ = NULL;
245
246 shared_ptr<string> pats = ast->expr->Eval(this);
247 for (StringPiece pat : WordScanner(*pats)) {
248 ScopedTerminator st(pat);
249 if (pat.find_first_of("?*[") != string::npos) {
250 glob_t gl;
251 glob(pat.data(), GLOB_NOSORT, NULL, &gl);
252 for (size_t i = 0; i < gl.gl_pathc; i++) {
253 DoInclude(gl.gl_pathv[i], ast->should_exist);
254 }
255 globfree(&gl);
256 } else {
257 DoInclude(pat.data(), ast->should_exist);
258 }
259 }
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900260}
261
262void Evaluator::EvalExport(const ExportAST* ast) {
Shinichiro Hamaji6e6de8d2015-06-18 11:12:58 +0900263 loc_ = ast->loc();
264 last_rule_ = NULL;
265
Shinichiro Hamaji45a0c762015-06-26 06:47:10 +0900266 shared_ptr<string> exports = ast->expr->Eval(this);
267 for (StringPiece tok : WordScanner(*exports)) {
268 size_t equal_index = tok.find('=');
269 if (equal_index == string::npos) {
270 exports_[Intern(tok)] = ast->is_export;
271 } else if (equal_index == 0 ||
272 (equal_index == 1 &&
273 (tok[0] == ':' || tok[0] == '?' || tok[0] == '+'))) {
274 // Do not export tokens after an assignment.
275 break;
276 } else {
277 StringPiece lhs, rhs;
278 AssignOp op;
279 ParseAssignStatement(tok, equal_index, &lhs, &rhs, &op);
280 exports_[Intern(lhs)] = ast->is_export;
281 }
282 }
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900283}
284
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900285Var* Evaluator::LookupVar(Symbol name) {
Shinichiro Hamaji784b9952015-06-23 14:29:32 +0900286 if (current_scope_) {
287 Var* v = current_scope_->Lookup(name);
288 if (v->IsDefined())
289 return v;
290 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900291 Var* v = vars_->Lookup(name);
292 if (v->IsDefined())
293 return v;
294 return in_vars_->Lookup(name);
295}
296
Shinichiro Hamajie7992752015-06-29 18:38:35 +0900297Var* Evaluator::LookupVarInCurrentScope(Symbol name) {
Shinichiro Hamaji784b9952015-06-23 14:29:32 +0900298 if (current_scope_) {
299 return current_scope_->Lookup(name);
300 }
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900301 Var* v = vars_->Lookup(name);
302 if (v->IsDefined())
303 return v;
304 return in_vars_->Lookup(name);
305}
306
Shinichiro Hamaji9619b362015-06-16 16:13:25 +0900307void Evaluator::Error(const string& msg) {
Shinichiro Hamaji8ee8c372015-06-16 16:19:40 +0900308 ERROR("%s:%d: %s", LOCF(loc_), msg.c_str());
Shinichiro Hamaji9619b362015-06-16 16:13:25 +0900309}