blob: cfa4d6f18efe7a3b00c69d03f54661ab02c94e72 [file] [log] [blame]
Laurent Le Brun6f23b132016-10-07 12:31:59 +00001// Copyright 2016 The Bazel Authors. All rights reserved.
Ulf Adams89f012d2015-02-26 13:39:28 +00002//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
Laurent Le Brun6f23b132016-10-07 12:31:59 +000014package com.google.devtools.skylark;
Ulf Adams89f012d2015-02-26 13:39:28 +000015
Francois-Rene Rideau36979612015-04-13 22:45:18 +000016import com.google.devtools.build.lib.events.Event;
17import com.google.devtools.build.lib.events.EventHandler;
laurentlbd3a039b2017-06-19 12:34:12 -040018import com.google.devtools.build.lib.events.EventKind;
Laurent Le Bruna6d8fe42016-11-28 18:14:54 +000019import com.google.devtools.build.lib.syntax.BuildFileAST;
Laurent Le Brun6f23b132016-10-07 12:31:59 +000020import com.google.devtools.build.lib.syntax.Environment;
laurentlbd3a039b2017-06-19 12:34:12 -040021import com.google.devtools.build.lib.syntax.EvalException;
Laurent Le Brun6f23b132016-10-07 12:31:59 +000022import com.google.devtools.build.lib.syntax.Mutability;
23import com.google.devtools.build.lib.syntax.Printer;
Ulf Adams89f012d2015-02-26 13:39:28 +000024import java.io.BufferedReader;
25import java.io.IOException;
26import java.io.InputStreamReader;
laurentlbe18ccda2017-08-10 23:00:53 +020027import java.nio.charset.Charset;
Laurent Le Brun733f4c72017-02-10 14:20:01 +000028import java.nio.charset.StandardCharsets;
29import java.nio.file.Files;
30import java.nio.file.Paths;
Ulf Adams89f012d2015-02-26 13:39:28 +000031
32/**
Laurent Le Brun6f23b132016-10-07 12:31:59 +000033 * Skylark is a standalone skylark intepreter. The environment doesn't
34 * contain Bazel-specific functions and variables. Load statements are
35 * forbidden for the moment.
Ulf Adams89f012d2015-02-26 13:39:28 +000036 */
Laurent Le Brun6f23b132016-10-07 12:31:59 +000037class Skylark {
Francois-Rene Rideaue6a46b82015-04-10 18:31:43 +000038 private static final String START_PROMPT = ">> ";
39 private static final String CONTINUATION_PROMPT = ".. ";
40
Laurent Le Brun733f4c72017-02-10 14:20:01 +000041 private static final EventHandler PRINT_HANDLER =
42 new EventHandler() {
43 @Override
44 public void handle(Event event) {
laurentlbd3a039b2017-06-19 12:34:12 -040045 if (event.getKind() == EventKind.ERROR) {
46 System.err.println(event.getMessage());
47 } else {
48 System.out.println(event.getMessage());
49 }
Laurent Le Brun733f4c72017-02-10 14:20:01 +000050 }
51 };
Francois-Rene Rideau36979612015-04-13 22:45:18 +000052
laurentlbe18ccda2017-08-10 23:00:53 +020053 private static final Charset CHARSET = StandardCharsets.ISO_8859_1;
Laurent Le Brun733f4c72017-02-10 14:20:01 +000054 private final BufferedReader reader =
laurentlbe18ccda2017-08-10 23:00:53 +020055 new BufferedReader(new InputStreamReader(System.in, CHARSET));
Laurent Le Brun6f23b132016-10-07 12:31:59 +000056 private final Mutability mutability = Mutability.create("interpreter");
Laurent Le Brun5e991982016-10-14 13:39:45 +000057 private final Environment env =
58 Environment.builder(mutability)
brandjon10a6b772017-10-20 20:48:30 +020059 .useDefaultSemantics()
Laurent Le Brun5e991982016-10-14 13:39:45 +000060 .setGlobals(Environment.DEFAULT_GLOBALS)
61 .setEventHandler(PRINT_HANDLER)
62 .build();
Francois-Rene Rideaue6a46b82015-04-10 18:31:43 +000063
Laurent Le Brun733f4c72017-02-10 14:20:01 +000064 private String prompt() {
Francois-Rene Rideaue6a46b82015-04-10 18:31:43 +000065 StringBuilder input = new StringBuilder();
Francois-Rene Rideau36979612015-04-13 22:45:18 +000066 System.out.print(START_PROMPT);
Ulf Adams89f012d2015-02-26 13:39:28 +000067 try {
brandjon95b04672017-09-22 23:33:38 -040068 String lineSeparator = "";
Francois-Rene Rideaue6a46b82015-04-10 18:31:43 +000069 while (true) {
70 String line = reader.readLine();
71 if (line == null) {
72 return null;
Ulf Adams89f012d2015-02-26 13:39:28 +000073 }
Francois-Rene Rideaue6a46b82015-04-10 18:31:43 +000074 if (line.isEmpty()) {
75 return input.toString();
76 }
brandjon95b04672017-09-22 23:33:38 -040077 input.append(lineSeparator).append(line);
78 lineSeparator = "\n";
Francois-Rene Rideau36979612015-04-13 22:45:18 +000079 System.out.print(CONTINUATION_PROMPT);
Ulf Adams89f012d2015-02-26 13:39:28 +000080 }
Francois-Rene Rideaue6a46b82015-04-10 18:31:43 +000081 } catch (IOException io) {
82 io.printStackTrace();
83 return null;
84 }
85 }
86
Laurent Le Brun733f4c72017-02-10 14:20:01 +000087 /** Provide a REPL evaluating Skylark code. */
Francois-Rene Rideaue6a46b82015-04-10 18:31:43 +000088 public void readEvalPrintLoop() {
89 String input;
Laurent Le Brun6f23b132016-10-07 12:31:59 +000090 while ((input = prompt()) != null) {
Francois-Rene Rideaue6a46b82015-04-10 18:31:43 +000091 try {
Laurent Le Bruna6d8fe42016-11-28 18:14:54 +000092 Object result = BuildFileAST.eval(env, input);
Francois-Rene Rideau36979612015-04-13 22:45:18 +000093 if (result != null) {
Francois-Rene Rideaud61f5312015-06-13 03:34:47 +000094 System.out.println(Printer.repr(result));
Francois-Rene Rideau36979612015-04-13 22:45:18 +000095 }
Francois-Rene Rideaue6a46b82015-04-10 18:31:43 +000096 } catch (Exception e) {
97 e.printStackTrace();
Ulf Adams89f012d2015-02-26 13:39:28 +000098 }
Ulf Adams89f012d2015-02-26 13:39:28 +000099 }
100 }
101
Laurent Le Brun733f4c72017-02-10 14:20:01 +0000102 /** Execute a Skylark file. */
Laurent Le Brund0ae2102017-02-10 19:22:37 +0000103 public int execute(String path) {
Laurent Le Brun733f4c72017-02-10 14:20:01 +0000104 String content;
105 try {
laurentlbe18ccda2017-08-10 23:00:53 +0200106 content = new String(Files.readAllBytes(Paths.get(path)), CHARSET);
Laurent Le Brun733f4c72017-02-10 14:20:01 +0000107 BuildFileAST.eval(env, content);
Laurent Le Brund0ae2102017-02-10 19:22:37 +0000108 return 0;
laurentlbd3a039b2017-06-19 12:34:12 -0400109 } catch (EvalException e) {
110 System.err.println(e.print());
111 return 1;
Laurent Le Brun733f4c72017-02-10 14:20:01 +0000112 } catch (Exception e) {
Jonathan Bluett-Duncan0df3ddbd2017-08-09 11:13:54 +0200113 e.printStackTrace(System.err);
Laurent Le Brund0ae2102017-02-10 19:22:37 +0000114 return 1;
Laurent Le Brun733f4c72017-02-10 14:20:01 +0000115 }
116 }
117
Ulf Adams89f012d2015-02-26 13:39:28 +0000118 public static void main(String[] args) {
Laurent Le Brund0ae2102017-02-10 19:22:37 +0000119 int ret = 0;
Laurent Le Brun6f23b132016-10-07 12:31:59 +0000120 if (args.length == 0) {
Laurent Le Bruna6d8fe42016-11-28 18:14:54 +0000121 new Skylark().readEvalPrintLoop();
Laurent Le Brun733f4c72017-02-10 14:20:01 +0000122 } else if (args.length == 1) {
Laurent Le Brund0ae2102017-02-10 19:22:37 +0000123 ret = new Skylark().execute(args[0]);
Laurent Le Brun6f23b132016-10-07 12:31:59 +0000124 } else {
Laurent Le Brun733f4c72017-02-10 14:20:01 +0000125 System.err.println("too many arguments");
Laurent Le Brund0ae2102017-02-10 19:22:37 +0000126 ret = 1;
Klaas Boesche0ec13b92015-11-06 12:16:03 +0000127 }
Laurent Le Brund0ae2102017-02-10 19:22:37 +0000128 System.exit(ret);
Ulf Adams89f012d2015-02-26 13:39:28 +0000129 }
130}