Skip to content

Commit

Permalink
bazel syntax: add examples of interpreter API
Browse files Browse the repository at this point in the history
RELNOTES: N/A
PiperOrigin-RevId: 329940788
  • Loading branch information
adonovan authored and copybara-github committed Sep 3, 2020
1 parent 2bb3b73 commit 8f67892
Show file tree
Hide file tree
Showing 2 changed files with 127 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/test/java/com/google/devtools/build/lib/syntax/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ java_test(
# CpuProfilerTest.java doesn't run under OSS Bazel
"EvalUtilsTest.java",
"EvaluationTest.java",
"Examples.java",
"FunctionTest.java",
"MethodLibraryTest.java",
"MutabilityTest.java",
Expand Down
126 changes: 126 additions & 0 deletions src/test/java/com/google/devtools/build/lib/syntax/Examples.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
// Copyright 2020 The Bazel Authors. 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.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import java.io.IOException;
import net.starlark.java.annot.Param;
import net.starlark.java.annot.StarlarkGlobalLibrary;
import net.starlark.java.annot.StarlarkMethod;

/**
* Examples of typical API usage of the Starlark interpreter.<br>
* This is not a test, but it is checked by the compiler.
*/
final class Examples {

/**
* This example reads, parses, compiles, and executes a Starlark file. It returns the module,
* which holds the values of global variables.
*/
Module execFile(String filename)
throws IOException, SyntaxError.Exception, EvalException, InterruptedException {
// Read input from the named file.
ParserInput input = ParserInput.readFile(filename);

// Create the module that will be populated by executing the file.
// It holds the global variables, initially empty.
// Its predeclared environment defines only the standard builtins:
// None, True, len, and so on.
Module module = Module.create();

// Resolve, compile, and execute the file.
//
// The Mutability will be associated with all the values created by this thread.
// The try-with-resources statement ensures that all values become frozen
// after execution.
try (Mutability mu = Mutability.create(input.getFile())) {
StarlarkThread thread = new StarlarkThread(mu, StarlarkSemantics.DEFAULT);
Starlark.execFile(input, FileOptions.DEFAULT, module, thread);
}

return module;
}

/**
* This example evaluates a Starlark expression in the specified environment and returns its
* value.
*/
Object evalExpr(String expr, ImmutableMap<String, Object> env)
throws SyntaxError.Exception, EvalException, InterruptedException {
// The apparent file name (for error messages) will be "<expr>".
ParserInput input = ParserInput.fromString(expr, "<expr>");

// Create the module in which the expression is evaluated.
// It may define additional predeclared environment bindings.
Module module = Module.withPredeclared(StarlarkSemantics.DEFAULT, env);

// Resolve, compile, and execute the expression.
try (Mutability mu = Mutability.create(input.getFile())) {
StarlarkThread thread = new StarlarkThread(mu, StarlarkSemantics.DEFAULT);
return Starlark.eval(input, FileOptions.DEFAULT, module, thread);
}
}

/**
* This advanced example reads, parses, and compiles a Starlark file to a Program, then later
* executes it.
*/
Module compileThenExecute()
throws IOException, SyntaxError.Exception, EvalException, InterruptedException {
// Read and parse the named file.
ParserInput input = ParserInput.readFile("my/file.star");
StarlarkFile file = StarlarkFile.parse(input);

// Compile the program, with additional predeclared environment bindings.
Program prog = Program.compileFile(file, () -> ImmutableSet.of("zero", "square"));

// . . .

// TODO(adonovan): when supported, show how the compiled program can be
// saved and reloaded, to avoid repeating the cost of parsing and
// compilation.

// Execute the compiled program to populate a module.
// The module's predeclared environment must match the
// names provided during compilation.
Module module = Module.withPredeclared(StarlarkSemantics.DEFAULT, makeEnvironment());
try (Mutability mu = Mutability.create(prog.getFilename())) {
StarlarkThread thread = new StarlarkThread(mu, StarlarkSemantics.DEFAULT);
Starlark.execFileProgram(prog, module, thread);
}
return module;
}

/** This function shows how to construct a callable Starlark value from a Java method. */
ImmutableMap<String, Object> makeEnvironment() {
ImmutableMap.Builder<String, Object> env = ImmutableMap.builder();
env.put("zero", 0);
Starlark.addMethods(env, new MyFunctions(), StarlarkSemantics.DEFAULT); // adds 'square'
return env.build();
}

/** The methods of this class are accessible from Starlark. */
@StarlarkGlobalLibrary
static final class MyFunctions {
@StarlarkMethod(
name = "square",
parameters = {@Param(name = "x", type = int.class)},
doc = "Returns the square of its integer argument.")
public int square(int x) {
return x * x;
}
}
}

0 comments on commit 8f67892

Please sign in to comment.