aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/syntax
diff options
context:
space:
mode:
authorGravatar Dmitry Lomov <dslomov@google.com>2017-03-01 10:09:32 +0000
committerGravatar Yue Gan <yueg@google.com>2017-03-01 12:36:29 +0000
commit01120026dc313ee7ad9ea95069a29252eb19173b (patch)
tree2121c64fcdd383586d131ba2900f793be5eedceb /src/main/java/com/google/devtools/build/lib/syntax
parent220b6390fcdb775bafc55793d2a722c44e08d30a (diff)
Export exportable values as we go instead of at the end of evaluation.
This simplifies implementation of attr.* functions and helps make declared provider implementation simpler. -- PiperOrigin-RevId: 148867326 MOS_MIGRATED_REVID=148867326
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/syntax')
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/BuildFileAST.java67
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/LValue.java30
2 files changed, 81 insertions, 16 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/BuildFileAST.java b/src/main/java/com/google/devtools/build/lib/syntax/BuildFileAST.java
index a0f6a33367..b1f079a14b 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/BuildFileAST.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/BuildFileAST.java
@@ -194,27 +194,52 @@ public class BuildFileAST extends ASTNode {
public boolean exec(Environment env, EventHandler eventHandler) throws InterruptedException {
boolean ok = true;
for (Statement stmt : stmts) {
- try {
- stmt.exec(env);
- } catch (EvalException e) {
+ if (!execTopLevelStatement(stmt, env, eventHandler)) {
ok = false;
- // Do not report errors caused by a previous parsing error, as it has already been
- // reported.
- if (e.isDueToIncompleteAST()) {
- continue;
- }
- // When the exception is raised from another file, report first the location in the
- // BUILD file (as it is the most probable cause for the error).
- Location exnLoc = e.getLocation();
- Location nodeLoc = stmt.getLocation();
- eventHandler.handle(Event.error(
- (exnLoc == null || !nodeLoc.getPath().equals(exnLoc.getPath())) ? nodeLoc : exnLoc,
- e.getMessage()));
}
}
return ok;
}
+ /**
+ * Executes tol-level statement of this build file in a given Environment.
+ *
+ * <p>If, for any reason, execution of a statement cannot be completed, an {@link EvalException}
+ * is thrown by {@link Statement#exec(Environment)}. This exception is caught here and reported
+ * through reporter. In effect, there is a
+ * "try/except" block around every top level statement. Such exceptions are not ignored, though:
+ * they are visible via the return value. Rules declared in a package containing any error
+ * (including loading-phase semantical errors that cannot be checked here) must also be considered
+ * "in error".
+ *
+ * <p>Note that this method will not affect the value of {@link #containsErrors()}; that refers
+ * only to lexer/parser errors.
+ *
+ * @return true if no error occurred during execution.
+ */
+
+ public boolean execTopLevelStatement(Statement stmt, Environment env,
+ EventHandler eventHandler) throws InterruptedException {
+ try {
+ stmt.exec(env);
+ return true;
+ } catch (EvalException e) {
+ // Do not report errors caused by a previous parsing error, as it has already been
+ // reported.
+ if (e.isDueToIncompleteAST()) {
+ return false;
+ }
+ // When the exception is raised from another file, report first the location in the
+ // BUILD file (as it is the most probable cause for the error).
+ Location exnLoc = e.getLocation();
+ Location nodeLoc = stmt.getLocation();
+ eventHandler.handle(Event.error(
+ (exnLoc == null || !nodeLoc.getPath().equals(exnLoc.getPath())) ? nodeLoc : exnLoc,
+ e.getMessage()));
+ return false;
+ }
+ }
+
@Override
public String toString() {
return "BuildFileAST" + getStatements();
@@ -348,10 +373,20 @@ public class BuildFileAST extends ASTNode {
@Nullable
public static Object eval(Environment env, String... input)
throws EvalException, InterruptedException {
+ BuildFileAST ast = parseAndValidateSkylarkString(env, input);
+ return ast.eval(env);
+ }
+
+ /**
+ * Parses and validates the lines from input and return the the AST
+ * In case of error during validation, it throws an EvalException.
+ */
+ public static BuildFileAST parseAndValidateSkylarkString(Environment env, String[] input)
+ throws EvalException {
BuildFileAST ast = parseSkylarkString(env.getEventHandler(), input);
ValidationEnvironment valid = new ValidationEnvironment(env);
valid.validateAst(ast.getStatements());
- return ast.eval(env);
+ return ast;
}
/**
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/LValue.java b/src/main/java/com/google/devtools/build/lib/syntax/LValue.java
index 22d686bf4e..ecc72073fe 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/LValue.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/LValue.java
@@ -14,6 +14,7 @@
package com.google.devtools.build.lib.syntax;
+import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.events.Location;
import com.google.devtools.build.lib.util.Preconditions;
import java.io.Serializable;
@@ -73,6 +74,35 @@ public class LValue implements Serializable {
}
}
+ /**
+ * Returns all names bound by this LValue.
+ *
+ * Examples:
+ * <ul>
+ * <li><{@code x = ...} binds x.</li>
+ * <li><{@code x, [y,z] = ..} binds x, y, z.</li>
+ * <li><{@code x[5] = ..} does not bind any names.</li>
+ * </ul>
+ */
+ public ImmutableSet<String> boundNames() {
+ ImmutableSet.Builder<String> result = ImmutableSet.builder();
+ collectBoundNames(expr, result);
+ return result.build();
+ }
+
+ private static void collectBoundNames(Expression lhs, ImmutableSet.Builder<String> result) {
+ if (lhs instanceof Identifier) {
+ result.add(((Identifier) lhs).getName());
+ return;
+ }
+ if (lhs instanceof ListLiteral) {
+ ListLiteral variables = (ListLiteral) lhs;
+ for (Expression expression : variables.getElements()) {
+ collectBoundNames(expression, result);
+ }
+ }
+ }
+
private static void doAssign(
Environment env, Location loc, Expression lhs, Object result)
throws EvalException, InterruptedException {