blob: 0da871224d1525fc5e8f9194d35d37fbbfa9673e [file] [log] [blame]
Shinichiro Hamaji776ca302015-06-06 03:52:48 +09001#include "eval.h"
2
3#include "ast.h"
4#include "file.h"
5#include "rule.h"
6#include "strutil.h"
7#include "value.h"
8#include "var.h"
9
10EvalResult::~EvalResult() {
11 for (Rule* r : rules)
12 delete r;
13 for (auto p : rule_vars)
14 delete p.second;
15 delete vars;
16}
17
18Evaluator::Evaluator(const Vars* vars)
19 : in_vars_(vars),
20 vars_(new Vars()),
21 last_rule_(NULL) {
22}
23
24Evaluator::~Evaluator() {
25 for (Rule* r : rules_) {
26 delete r;
27 }
28 delete vars_;
29 // for (auto p : rule_vars) {
30 // delete p.second;
31 // }
32}
33
34void Evaluator::EvalAssign(const AssignAST* ast) {
35 loc_ = ast->loc();
36 last_rule_ = NULL;
37
38 const char* origin = "file";
39
40 StringPiece lhs = Intern(*ast->lhs->Eval(this));
41 Var* rhs = NULL;
Shinichiro Hamaji4c469b32015-06-15 19:53:36 +090042 bool needs_assign = true;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090043 switch (ast->op) {
44 case AssignOp::COLON_EQ:
45 rhs = new SimpleVar(ast->rhs->Eval(this), origin);
46 break;
47 case AssignOp::EQ:
48 rhs = new RecursiveVar(ast->rhs, origin);
49 break;
50 case AssignOp::PLUS_EQ: {
51 Var* prev = LookupVarInCurrentScope(lhs);
52 if (!prev->IsDefined()) {
53 rhs = new RecursiveVar(ast->rhs, origin);
54 } else {
Shinichiro Hamaji4c469b32015-06-15 19:53:36 +090055 prev->AppendVar(this, ast->rhs);
56 rhs = prev;
57 needs_assign = false;
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090058 }
59 break;
60 }
61 case AssignOp::QUESTION_EQ: {
62 Var* prev = LookupVarInCurrentScope(lhs);
63 if (!prev->IsDefined()) {
64 rhs = new RecursiveVar(ast->rhs, origin);
65 } else {
66 // TODO
67 abort();
68 }
69 break;
70 }
71 }
72
73 LOG("Assign: %.*s=%s", SPF(lhs), rhs->DebugString().c_str());
Shinichiro Hamaji4c469b32015-06-15 19:53:36 +090074 if (needs_assign)
75 vars_->Assign(lhs, rhs);
Shinichiro Hamaji776ca302015-06-06 03:52:48 +090076}
77
78void Evaluator::EvalRule(const RuleAST* ast) {
79 loc_ = ast->loc();
80 last_rule_ = NULL;
81
82 shared_ptr<string> expr = ast->expr->Eval(this);
83 // See semicolon.mk.
84 if (expr->find_first_not_of(" \t\n;") == string::npos)
85 return;
86
87 Rule* rule = new Rule;
88 rule->loc = loc_;
89 rule->Parse(*expr);
90
91 LOG("Rule: %s", rule->DebugString().c_str());
92 rules_.push_back(rule);
93 last_rule_ = rule;
94}
95
96void Evaluator::EvalCommand(const CommandAST* ast) {
97 loc_ = ast->loc();
98
99 if (!last_rule_) {
100 // TODO:
101 ERROR("TODO");
102 }
103
104 last_rule_->cmds.push_back(ast->expr);
105 LOG("Command: %s", ast->expr->DebugString().c_str());
106}
107
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900108void Evaluator::EvalIf(const IfAST* ast) {
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900109 bool is_true;
110 StringPiece lhs = Intern(*ast->lhs->Eval(this));
111 switch (ast->op) {
112 case CondOp::IFDEF:
113 case CondOp::IFNDEF: {
114 Var* v = LookupVarInCurrentScope(lhs);
115 shared_ptr<string> s = v->Eval(this);
116 is_true = s->empty() == (ast->op == CondOp::IFNDEF);
117 break;
118 }
119 case CondOp::IFEQ:
120 case CondOp::IFNEQ: {
121 ERROR("TODO");
122 break;
123 }
124 default:
125 CHECK(false);
126 }
127
128 const vector<AST*>* asts;
129 if (is_true) {
Shinichiro Hamaji2847f092015-06-17 15:48:37 +0900130 asts = &ast->true_asts;
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900131 } else {
Shinichiro Hamaji2847f092015-06-17 15:48:37 +0900132 asts = &ast->false_asts;
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900133 }
134 for (AST* a : *asts) {
Shinichiro Hamaji6cb1c252015-06-17 16:22:51 +0900135 LOG("%s", a->DebugString().c_str());
Shinichiro Hamaji7e256df2015-06-17 15:33:11 +0900136 a->Eval(this);
137 }
Shinichiro Hamaji42b625f2015-06-16 23:07:21 +0900138}
139
140void Evaluator::EvalInclude(const IncludeAST* ast) {
141 ERROR("TODO");
142}
143
144void Evaluator::EvalExport(const ExportAST* ast) {
145 ERROR("TODO");
146}
147
Shinichiro Hamaji776ca302015-06-06 03:52:48 +0900148Var* Evaluator::LookupVar(StringPiece name) {
149 // TODO: TSV.
150 Var* v = vars_->Lookup(name);
151 if (v->IsDefined())
152 return v;
153 return in_vars_->Lookup(name);
154}
155
156Var* Evaluator::LookupVarInCurrentScope(StringPiece name) {
157 // TODO: TSV.
158 Var* v = vars_->Lookup(name);
159 if (v->IsDefined())
160 return v;
161 return in_vars_->Lookup(name);
162}
163
164EvalResult* Evaluator::GetEvalResult() {
165 EvalResult* er = new EvalResult;
166 er->rules.swap(rules_);
167 er->vars = vars_;
168 vars_ = NULL;
169 er->rule_vars.swap(rule_vars_);
170 return er;
171}
Shinichiro Hamaji9619b362015-06-16 16:13:25 +0900172
173void Evaluator::Error(const string& msg) {
Shinichiro Hamaji8ee8c372015-06-16 16:19:40 +0900174 ERROR("%s:%d: %s", LOCF(loc_), msg.c_str());
Shinichiro Hamaji9619b362015-06-16 16:13:25 +0900175}