aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/google/devtools/build')
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/SkylarkModules.java8
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/Environment.java10
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/EvaluationContext.java223
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/Lexer.java3
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/Parser.java8
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/SkylarkSignatureProcessor.java16
6 files changed, 253 insertions, 15 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/SkylarkModules.java b/src/main/java/com/google/devtools/build/lib/rules/SkylarkModules.java
index 7d1e17647b..500edcc4cb 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/SkylarkModules.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/SkylarkModules.java
@@ -22,6 +22,7 @@ import com.google.devtools.build.lib.events.EventHandler;
import com.google.devtools.build.lib.packages.MethodLibrary;
import com.google.devtools.build.lib.packages.SkylarkNativeModule;
import com.google.devtools.build.lib.syntax.Environment;
+import com.google.devtools.build.lib.syntax.EvaluationContext;
import com.google.devtools.build.lib.syntax.Function;
import com.google.devtools.build.lib.syntax.SkylarkBuiltin;
import com.google.devtools.build.lib.syntax.SkylarkEnvironment;
@@ -38,7 +39,7 @@ import java.util.Map;
/**
* A class to handle all Skylark modules, to create and setup Validation and regular Environments.
*/
-// TODO(bazel-team): move that to syntax/ and
+// TODO(bazel-team): move that to the syntax package and
// let each extension register itself in a static { } statement.
public class SkylarkModules {
@@ -138,6 +139,11 @@ public class SkylarkModules {
return new ValidationEnvironment(CollectionUtils.toImmutable(builtIn));
}
+ public static EvaluationContext newEvaluationContext(EventHandler eventHandler) {
+ return EvaluationContext.newSkylarkContext(
+ getNewEnvironment(eventHandler), getValidationEnvironment());
+ }
+
/**
* Collects the SkylarkFunctions from the fields of the class of the object parameter
* and adds them into the builder.
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Environment.java b/src/main/java/com/google/devtools/build/lib/syntax/Environment.java
index 456007f9ba..bd595127fc 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/Environment.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/Environment.java
@@ -135,14 +135,18 @@ public class Environment {
this.eventHandler = Preconditions.checkNotNull(eventHandler);
}
+ public EventHandler getEventHandler() {
+ return eventHandler;
+ }
+
// Sets up the global environment
private void setupGlobal() {
// In Python 2.x, True and False are global values and can be redefined by the user.
// In Python 3.x, they are keywords. We implement them as values, for the sake of
// simplicity. We define them as Boolean objects.
- env.put("False", FALSE);
- env.put("True", TRUE);
- env.put("None", NONE);
+ update("False", FALSE);
+ update("True", TRUE);
+ update("None", NONE);
}
public boolean isSkylarkEnabled() {
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/EvaluationContext.java b/src/main/java/com/google/devtools/build/lib/syntax/EvaluationContext.java
new file mode 100644
index 0000000000..c361bb3fca
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/syntax/EvaluationContext.java
@@ -0,0 +1,223 @@
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.lib.syntax;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Joiner;
+import com.google.common.base.Preconditions;
+import com.google.devtools.build.lib.events.Event;
+import com.google.devtools.build.lib.events.EventHandler;
+import com.google.devtools.build.lib.events.EventKind;
+import com.google.devtools.build.lib.packages.CachingPackageLocator;
+import com.google.devtools.build.lib.syntax.Environment.NoSuchVariableException;
+import com.google.devtools.build.lib.vfs.Path;
+
+import java.util.List;
+
+import javax.annotation.Nullable;
+
+/**
+ * Context for the evaluation of programs.
+ */
+public final class EvaluationContext {
+
+ @Nullable private EventHandler eventHandler;
+ private Environment env;
+ @Nullable private ValidationEnvironment validationEnv;
+ private boolean parsePython;
+
+ private EvaluationContext(EventHandler eventHandler, Environment env,
+ @Nullable ValidationEnvironment validationEnv, boolean parsePython) {
+ this.eventHandler = eventHandler;
+ this.env = env;
+ this.validationEnv = validationEnv;
+ this.parsePython = parsePython;
+ }
+
+ /**
+ * The fail fast handler, which throws a runtime exception whenever we encounter an error event.
+ */
+ public static final EventHandler FAIL_FAST_HANDLER = new EventHandler() {
+ @Override
+ public void handle(Event event) {
+ Preconditions.checkArgument(
+ !EventKind.ERRORS_AND_WARNINGS.contains(event.getKind()), event);
+ }
+ };
+
+ public static final EventHandler PRINT_HANDLER = new EventHandler() {
+ @Override
+ public void handle(Event event) {
+ System.out.print(event.getMessage());
+ }
+ };
+
+ public static EvaluationContext newBuildContext(EventHandler eventHandler, Environment env,
+ boolean parsePython) {
+ return new EvaluationContext(eventHandler, env, null, parsePython);
+ }
+
+ public static EvaluationContext newBuildContext(EventHandler eventHandler, Environment env) {
+ return newBuildContext(eventHandler, env, false);
+ }
+
+ public static EvaluationContext newBuildContext(EventHandler eventHandler) {
+ return newBuildContext(eventHandler, new Environment());
+ }
+
+ public static EvaluationContext newSkylarkContext(
+ Environment env, ValidationEnvironment validationEnv) {
+ return new EvaluationContext(env.getEventHandler(), env, validationEnv, false);
+ }
+
+ public static EvaluationContext newSkylarkContext(EventHandler eventHandler) {
+ return newSkylarkContext(new SkylarkEnvironment(eventHandler), new ValidationEnvironment());
+ }
+
+ public Environment getEnvironment() {
+ return env;
+ }
+
+ public EventHandler getEventHandler() {
+ return eventHandler;
+ }
+
+ public ValidationEnvironment getValidationEnvironment() {
+ return validationEnv;
+ }
+
+ /** Base context for Skylark evaluation for internal use only, while initializing builtins */
+ static final EvaluationContext SKYLARK_INITIALIZATION = newSkylarkContext(FAIL_FAST_HANDLER);
+
+ /** Mock package locator */
+ private static final class EmptyPackageLocator implements CachingPackageLocator {
+ @Override
+ public Path getBuildFileForPackage(String packageName) {
+ return null;
+ }
+ }
+
+ /** An empty package locator */
+ private static final CachingPackageLocator EMPTY_PACKAGE_LOCATOR = new EmptyPackageLocator();
+
+ /** Create a Lexer without a supporting file */
+ @VisibleForTesting
+ Lexer createLexer(String... input) {
+ return new Lexer(ParserInputSource.create(Joiner.on("\n").join(input), null),
+ eventHandler);
+ }
+
+ /** Is this a Skylark evaluation context? */
+ public boolean isSkylark() {
+ return env.isSkylarkEnabled();
+ }
+
+ /** Parse a string without a supporting file, returning statements and comments */
+ @VisibleForTesting
+ Parser.ParseResult parseFileWithComments(String... input) {
+ return isSkylark()
+ ? Parser.parseFileForSkylark(createLexer(input), eventHandler, null, validationEnv)
+ : Parser.parseFile(createLexer(input), eventHandler, EMPTY_PACKAGE_LOCATOR, parsePython);
+ }
+
+ /** Parse a string without a supporting file, returning statements only */
+ @VisibleForTesting
+ List<Statement> parseFile(String... input) {
+ return parseFileWithComments(input).statements;
+ }
+
+ /** Parse an Expression from string without a supporting file */
+ @VisibleForTesting
+ Expression parseExpression(String... input) {
+ return Parser.parseExpression(createLexer(input), eventHandler);
+ }
+
+ /** Evaluate an Expression */
+ @VisibleForTesting
+ Object evalExpression(Expression expression) throws EvalException, InterruptedException {
+ return expression.eval(env);
+ }
+
+ /** Evaluate an Expression as parsed from String-s */
+ Object evalExpression(String... input) throws EvalException, InterruptedException {
+ return evalExpression(parseExpression(input));
+ }
+
+ /** Parse a build (not Skylark) Statement from string without a supporting file */
+ @VisibleForTesting
+ Statement parseStatement(String... input) {
+ return Parser.parseStatement(createLexer(input), eventHandler);
+ }
+
+ /**
+ * Evaluate a Statement
+ * @param statement the Statement
+ * @return the value of the evaluation, if it's an Expression, or else null
+ */
+ @Nullable private Object eval(Statement statement) throws EvalException, InterruptedException {
+ if (statement instanceof ExpressionStatement) {
+ return evalExpression(((ExpressionStatement) statement).getExpression());
+ }
+ statement.exec(env);
+ return null;
+ }
+
+ /**
+ * Evaluate a list of Statement-s
+ * @return the value of the last statement if it's an Expression or else null
+ */
+ @Nullable private Object eval(List<Statement> statements)
+ throws EvalException, InterruptedException {
+ Object last = null;
+ for (Statement statement : statements) {
+ last = eval(statement);
+ }
+ return last;
+ }
+
+ /** Update a variable in the environment, in fluent style */
+ public EvaluationContext update(String varname, Object value) throws EvalException {
+ env.update(varname, value);
+ if (validationEnv != null) {
+ validationEnv.update(
+ varname, SkylarkType.typeForInference(SkylarkType.of(value.getClass())), null);
+ }
+ return this;
+ }
+
+ /** Lookup a variable in the environment */
+ public Object lookup(String varname) throws NoSuchVariableException {
+ return env.lookup(varname);
+ }
+
+ /** Print a String in this context */
+ public void print(String msg) {
+ if (msg != null) {
+ eventHandler.handle(new Event(EventKind.STDOUT, null, msg));
+ }
+ }
+
+ /** Print a String in this context */
+ public void println(String msg) {
+ if (msg != null) {
+ print(msg + "\n");
+ }
+ }
+
+ /** Evaluate a series of statements */
+ public Object eval(String... input) throws EvalException, InterruptedException {
+ return eval(parseFile(input));
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Lexer.java b/src/main/java/com/google/devtools/build/lib/syntax/Lexer.java
index fd68bdea09..86b8de7b1d 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/Lexer.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/Lexer.java
@@ -164,7 +164,8 @@ public final class Lexer {
@Override
public PathFragment getPath() {
- return lineNumberTable.getPath(getStartOffset()).asFragment();
+ Path path = lineNumberTable.getPath(getStartOffset());
+ return path != null ? path.asFragment() : null;
}
@Override
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Parser.java b/src/main/java/com/google/devtools/build/lib/syntax/Parser.java
index e8c30c393f..75b8db8b4c 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/Parser.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/Parser.java
@@ -212,7 +212,13 @@ class Parser {
@VisibleForTesting
public static Statement parseStatement(
Lexer lexer, EventHandler eventHandler) {
- return new Parser(lexer, eventHandler, null).parseSmallStatement();
+ Parser parser = new Parser(lexer, eventHandler, null);
+ Statement result = parser.parseSmallStatement();
+ while (parser.token.kind == TokenKind.NEWLINE) {
+ parser.nextToken();
+ }
+ parser.expect(TokenKind.EOF);
+ return result;
}
/**
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkSignatureProcessor.java b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkSignatureProcessor.java
index c772038276..6d7b1dbb1f 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkSignatureProcessor.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkSignatureProcessor.java
@@ -82,15 +82,15 @@ public class SkylarkSignatureProcessor {
paramList.add(getParameter(name, starParam, enforcedTypes, doc, undocumented,
/*mandatory=*/false, /*star=*/true, /*starStar=*/false, /*defaultValue=*/null));
}
+ for (Param param : annotation.mandatoryNamedOnly()) {
+ paramList.add(getParameter(name, param, enforcedTypes, doc, undocumented,
+ /*mandatory=*/true, /*star=*/false, /*starStar=*/false, /*defaultValue=*/null));
+ }
for (Param param : annotation.optionalNamedOnly()) {
paramList.add(getParameter(name, param, enforcedTypes, doc, undocumented,
/*mandatory=*/false, /*star=*/false, /*starStar=*/false,
/*defaultValue=*/getDefaultValue(param, defaultValuesIterator)));
}
- for (Param param : annotation.mandatoryNamedOnly()) {
- paramList.add(getParameter(name, param, enforcedTypes, doc, undocumented,
- /*mandatory=*/true, /*star=*/false, /*starStar=*/false, /*defaultValue=*/null));
- }
if (annotation.extraKeywords().length > 0) {
Preconditions.checkArgument(annotation.extraKeywords().length == 1);
paramList.add(
@@ -190,13 +190,11 @@ public class SkylarkSignatureProcessor {
return Environment.NONE;
} else {
try {
- // TODO(bazel-team): when we have Evaluation, remove the throw and uncomment the return.
- throw new RuntimeException("Not Implemented Yet!");
- // return new Evaluation ().eval(param.defaultValue());
+ return EvaluationContext.SKYLARK_INITIALIZATION.evalExpression(param.defaultValue());
} catch (Exception e) {
throw new RuntimeException(String.format(
- "Exception while processing @SkylarkSignature.Param %s, default value %s: %s",
- param.name(), param.defaultValue(), e.getMessage()), e);
+ "Exception while processing @SkylarkSignature.Param %s, default value %s",
+ param.name(), param.defaultValue()), e);
}
}
}