Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(42)

Unified Diff: tools/gn/functions.cc

Issue 212933008: Don't dynamically scope GN templates. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « tools/gn/function_template.cc ('k') | tools/gn/functions_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/gn/functions.cc
diff --git a/tools/gn/functions.cc b/tools/gn/functions.cc
index 8d146b2f7201a581c7b6b966c84783c650d012be..43cdcd36cf4f5ea6f09d393fed312300f4a21fe0 100644
--- a/tools/gn/functions.cc
+++ b/tools/gn/functions.cc
@@ -16,46 +16,10 @@
#include "tools/gn/scheduler.h"
#include "tools/gn/scope.h"
#include "tools/gn/settings.h"
+#include "tools/gn/template.h"
#include "tools/gn/token.h"
#include "tools/gn/value.h"
-namespace {
-
-// This is called when a template is invoked. When we see a template
-// declaration, that funciton is RunTemplate.
-Value RunTemplateInvocation(Scope* scope,
- const FunctionCallNode* invocation,
- const std::vector<Value>& args,
- BlockNode* block,
- const FunctionCallNode* rule,
- Err* err) {
- if (!EnsureNotProcessingImport(invocation, scope, err))
- return Value();
-
- Scope block_scope(scope);
- if (!FillTargetBlockScope(scope, invocation,
- invocation->function().value().as_string(),
- block, args, &block_scope, err))
- return Value();
-
- // Run the block for the rule invocation.
- block->ExecuteBlockInScope(&block_scope, err);
- if (err->has_error())
- return Value();
-
- // Now run the rule itself with that block as the current scope.
- rule->block()->ExecuteBlockInScope(&block_scope, err);
- if (err->has_error())
- return Value();
-
- block_scope.CheckForUnusedVars(err);
- return Value();
-}
-
-} // namespace
-
-// ----------------------------------------------------------------------------
-
bool EnsureNotProcessingImport(const ParseNode* node,
const Scope* scope,
Err* err) {
@@ -97,7 +61,7 @@ bool FillTargetBlockScope(const Scope* scope,
// the block in.
const Scope* default_scope = scope->GetTargetDefaults(target_type);
if (default_scope) {
- if (!default_scope->NonRecursiveMergeTo(block_scope, function,
+ if (!default_scope->NonRecursiveMergeTo(block_scope, false, function,
"target defaults", err))
return false;
}
@@ -331,16 +295,29 @@ const char kDefined_Help[] =
" Returns true if the given argument is defined. This is most useful in\n"
" templates to assert that the caller set things up properly.\n"
"\n"
+ " You can pass an identifier:\n"
+ " defined(foo)\n"
+ " which will return true or false depending on whether foo is defined in\n"
+ " the current scope.\n"
+ "\n"
+ " You can also check a named scope:\n"
+ " defined(foo.bar)\n"
+ " which returns true if both foo is defined and bar is defined on the\n"
+ " named scope foo. It will throw an error if foo is defined but is not\n"
+ " a scope.\n"
+ "\n"
"Example:\n"
"\n"
" template(\"mytemplate\") {\n"
" # To help users call this template properly...\n"
- " assert(defined(sources), \"Sources must be defined\")\n"
+ " assert(defined(invoker.sources), \"Sources must be defined\")\n"
"\n"
" # If we want to accept an optional \"values\" argument, we don't\n"
" # want to dereference something that may not be defined.\n"
- " if (!defined(outputs)) {\n"
- " outputs = []\n"
+ " if (defined(invoker.values)) {\n"
+ " values = invoker.values\n"
+ " } else {\n"
+ " values = \"some default value\"\n"
" }\n"
" }\n";
@@ -349,17 +326,42 @@ Value RunDefined(Scope* scope,
const ListNode* args_list,
Err* err) {
const std::vector<const ParseNode*>& args_vector = args_list->contents();
- const IdentifierNode* identifier = NULL;
- if (args_vector.size() != 1 ||
- !(identifier = args_vector[0]->AsIdentifier())) {
- *err = Err(function, "Bad argument to defined().",
- "defined() takes one argument which should be an identifier.");
+ if (args_vector.size() != 1) {
+ *err = Err(function, "Wrong number of arguments to defined().",
+ "Expecting exactly one.");
return Value();
}
- if (scope->GetValue(identifier->value().value()))
- return Value(function, true);
- return Value(function, false);
+ const IdentifierNode* identifier = args_vector[0]->AsIdentifier();
+ if (identifier) {
+ // Passed an identifier "defined(foo)".
+ if (scope->GetValue(identifier->value().value()))
+ return Value(function, true);
+ return Value(function, false);
+ }
+
+ const AccessorNode* accessor = args_vector[0]->AsAccessor();
+ if (accessor) {
+ // Passed an accessor "defined(foo.bar)".
+ if (accessor->member()) {
+ // The base of the accessor must be a scope if it's defined.
+ const Value* base = scope->GetValue(accessor->base().value());
+ if (!base)
+ return Value(function, false);
+ if (!base->VerifyTypeIs(Value::SCOPE, err))
+ return Value();
+
+ // Check the member inside the scope to see if its defined.
+ if (base->scope_value()->GetValue(accessor->member()->value().value()))
+ return Value(function, true);
+ return Value(function, false);
+ }
+ }
+
+ // Argument is invalid.
+ *err = Err(function, "Bad thing passed to defined().",
+ "It should be of the form defined(foo) or defined(foo.bar).");
+ return Value();
}
// getenv ----------------------------------------------------------------------
@@ -625,14 +627,13 @@ Value RunFunction(Scope* scope,
function_map.find(name.value());
if (found_function == function_map.end()) {
// No built-in function matching this, check for a template.
- const FunctionCallNode* rule =
+ const Template* templ =
scope->GetTemplate(function->function().value().as_string());
- if (rule) {
+ if (templ) {
Value args = args_list->Execute(scope, err);
if (err->has_error())
return Value();
- return RunTemplateInvocation(scope, function, args.list_value(), block,
- rule, err);
+ return templ->Invoke(scope, function, args.list_value(), block, err);
}
*err = Err(name, "Unknown function.");
« no previous file with comments | « tools/gn/function_template.cc ('k') | tools/gn/functions_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698