From b1ee45c1e48cb0c3e329d320d62f1005f537dc85 Mon Sep 17 00:00:00 2001 From: Jon Ross-Perkins Date: Fri, 12 May 2023 08:00:43 -0700 Subject: [PATCH] Extract ParseAndExecute as its own library. (#2813) Currently ParseAndExecute-style logic is done in main.cpp and a test. #2799 is adding another test that needs it, as is #2811. Also more clearly marks fuzzing as testing. This is being extracted out of #2799 in order to try unblocking progress while review continues. --- explorer/BUILD | 8 +- explorer/common/BUILD | 10 ++ .../{interpreter => common}/trace_stream.h | 6 +- explorer/fuzzing/BUILD | 6 +- explorer/fuzzing/ast_to_proto.cpp | 4 +- explorer/fuzzing/ast_to_proto.h | 4 +- explorer/fuzzing/ast_to_proto_main.cpp | 8 +- explorer/fuzzing/explorer_fuzzer.cpp | 2 +- explorer/fuzzing/fuzzer_util.cpp | 27 ++--- explorer/fuzzing/fuzzer_util.h | 6 +- explorer/fuzzing/fuzzer_util_test.cpp | 4 +- explorer/interpreter/BUILD | 58 ++++------- explorer/interpreter/exec_program.h | 2 +- explorer/interpreter/interpreter.h | 2 +- explorer/interpreter/type_checker.h | 2 +- explorer/main.cpp | 85 +++------------- explorer/parse_and_execute/BUILD | 25 +++++ .../parse_and_execute/parse_and_execute.cpp | 98 +++++++++++++++++++ .../parse_and_execute/parse_and_execute.h | 28 ++++++ explorer/syntax/BUILD | 9 +- 20 files changed, 226 insertions(+), 168 deletions(-) rename explorer/{interpreter => common}/trace_stream.h (92%) create mode 100644 explorer/parse_and_execute/BUILD create mode 100644 explorer/parse_and_execute/parse_and_execute.cpp create mode 100644 explorer/parse_and_execute/parse_and_execute.h diff --git a/explorer/BUILD b/explorer/BUILD index 14416596b468..9ce363327793 100644 --- a/explorer/BUILD +++ b/explorer/BUILD @@ -21,12 +21,8 @@ cc_library( hdrs = ["main.h"], deps = [ "//common:error", - "//explorer/common:arena", - "//explorer/common:nonnull", - "//explorer/interpreter:exec_program", - "//explorer/interpreter:trace_stream", - "//explorer/syntax", - "//explorer/syntax:prelude", + "//explorer/common:trace_stream", + "//explorer/parse_and_execute", "@llvm-project//llvm:Support", ], ) diff --git a/explorer/common/BUILD b/explorer/common/BUILD index b2c684ddb4da..8a39c3263ef7 100644 --- a/explorer/common/BUILD +++ b/explorer/common/BUILD @@ -48,3 +48,13 @@ cc_library( "//common:ostream", ], ) + +cc_library( + name = "trace_stream", + hdrs = ["trace_stream.h"], + deps = [ + "//common:check", + "//common:ostream", + "//explorer/common:nonnull", + ], +) diff --git a/explorer/interpreter/trace_stream.h b/explorer/common/trace_stream.h similarity index 92% rename from explorer/interpreter/trace_stream.h rename to explorer/common/trace_stream.h index a5698fa1d2f7..330c38ca91d4 100644 --- a/explorer/interpreter/trace_stream.h +++ b/explorer/common/trace_stream.h @@ -2,8 +2,8 @@ // Exceptions. See /LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -#ifndef CARBON_EXPLORER_INTERPRETER_TRACE_STREAM_H_ -#define CARBON_EXPLORER_INTERPRETER_TRACE_STREAM_H_ +#ifndef CARBON_EXPLORER_COMMON_TRACE_STREAM_H_ +#define CARBON_EXPLORER_COMMON_TRACE_STREAM_H_ #include #include @@ -59,4 +59,4 @@ class TraceStream { } // namespace Carbon -#endif // CARBON_EXPLORER_INTERPRETER_TRACE_STREAM_H_ +#endif // CARBON_EXPLORER_COMMON_TRACE_STREAM_H_ diff --git a/explorer/fuzzing/BUILD b/explorer/fuzzing/BUILD index 1f25225d5f99..15b19a5fadf6 100644 --- a/explorer/fuzzing/BUILD +++ b/explorer/fuzzing/BUILD @@ -29,7 +29,6 @@ cc_binary( "//explorer/common:arena", "//explorer/syntax", "@com_google_protobuf//:protobuf_headers", - "@llvm-project//llvm:Support", ], ) @@ -65,10 +64,7 @@ cc_library( "//common/fuzzing:carbon_cc_proto", "//common/fuzzing:proto_to_carbon_lib", "//explorer/ast", - "//explorer/interpreter:exec_program", - "//explorer/interpreter:trace_stream", - "//explorer/syntax", - "//explorer/syntax:prelude", + "//explorer/parse_and_execute", "@bazel_tools//tools/cpp/runfiles", "@com_google_protobuf//:protobuf_headers", "@llvm-project//llvm:Support", diff --git a/explorer/fuzzing/ast_to_proto.cpp b/explorer/fuzzing/ast_to_proto.cpp index 179388a9f25a..d9b9aff29a7e 100644 --- a/explorer/fuzzing/ast_to_proto.cpp +++ b/explorer/fuzzing/ast_to_proto.cpp @@ -10,7 +10,7 @@ #include "explorer/ast/expression.h" #include "llvm/Support/Casting.h" -namespace Carbon { +namespace Carbon::Testing { using ::llvm::cast; using ::llvm::dyn_cast; @@ -854,4 +854,4 @@ auto AstToProto(const AST& ast) -> Fuzzing::Carbon { return carbon; } -} // namespace Carbon +} // namespace Carbon::Testing diff --git a/explorer/fuzzing/ast_to_proto.h b/explorer/fuzzing/ast_to_proto.h index a7660595b238..eac3c696bcdf 100644 --- a/explorer/fuzzing/ast_to_proto.h +++ b/explorer/fuzzing/ast_to_proto.h @@ -8,11 +8,11 @@ #include "common/fuzzing/carbon.pb.h" #include "explorer/ast/ast.h" -namespace Carbon { +namespace Carbon::Testing { // Builds a protobuf representation of `ast`. auto AstToProto(const AST& ast) -> Fuzzing::Carbon; -} // namespace Carbon +} // namespace Carbon::Testing #endif // CARBON_EXPLORER_FUZZING_AST_TO_PROTO_H_ diff --git a/explorer/fuzzing/ast_to_proto_main.cpp b/explorer/fuzzing/ast_to_proto_main.cpp index c8812e77c438..ed3d096729d5 100644 --- a/explorer/fuzzing/ast_to_proto_main.cpp +++ b/explorer/fuzzing/ast_to_proto_main.cpp @@ -19,10 +19,10 @@ #include "explorer/fuzzing/ast_to_proto.h" #include "explorer/syntax/parse.h" -namespace Carbon { +namespace Carbon::Testing { auto Main(int argc, char** argv) -> ErrorOr { - Carbon::SetWorkingDirForBazel(); + SetWorkingDirForBazel(); if (argc != 2) { return Error("Syntax: ast_to_proto "); @@ -54,10 +54,10 @@ auto Main(int argc, char** argv) -> ErrorOr { return Success(); } -} // namespace Carbon +} // namespace Carbon::Testing auto main(int argc, char** argv) -> int { - auto err = Carbon::Main(argc, argv); + auto err = Carbon::Testing::Main(argc, argv); if (!err.ok()) { std::cerr << err.error().message() << "\n"; return EXIT_FAILURE; diff --git a/explorer/fuzzing/explorer_fuzzer.cpp b/explorer/fuzzing/explorer_fuzzer.cpp index 55721951f51e..ce0ccc4cd89b 100644 --- a/explorer/fuzzing/explorer_fuzzer.cpp +++ b/explorer/fuzzing/explorer_fuzzer.cpp @@ -10,5 +10,5 @@ DEFINE_TEXT_PROTO_FUZZER(const Carbon::Fuzzing::Carbon& input) { // Only verifying it doesn't crash. - (void)Carbon::ParseAndExecute(input); + (void)Carbon::Testing::ParseAndExecuteProto(input); } diff --git a/explorer/fuzzing/fuzzer_util.cpp b/explorer/fuzzing/fuzzer_util.cpp index ac84bda253a7..7aa330c98094 100644 --- a/explorer/fuzzing/fuzzer_util.cpp +++ b/explorer/fuzzing/fuzzer_util.cpp @@ -9,15 +9,12 @@ #include "common/check.h" #include "common/error.h" #include "common/fuzzing/proto_to_carbon.h" -#include "explorer/interpreter/exec_program.h" -#include "explorer/interpreter/trace_stream.h" -#include "explorer/syntax/parse.h" -#include "explorer/syntax/prelude.h" +#include "explorer/parse_and_execute/parse_and_execute.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" #include "tools/cpp/runfiles/runfiles.h" -namespace Carbon { +namespace Carbon::Testing { auto GetRunfilesFile(const std::string& file) -> ErrorOr { using bazel::tools::cpp::runfiles::Runfiles; @@ -35,26 +32,14 @@ auto GetRunfilesFile(const std::string& file) -> ErrorOr { return full_path; } -auto ParseAndExecute(const Fuzzing::Carbon& carbon) -> ErrorOr { - const std::string source = ProtoToCarbon(carbon, /*maybe_add_main=*/true); - - Arena arena; - CARBON_ASSIGN_OR_RETURN(AST ast, - ParseFromString(&arena, "Fuzzer.carbon", source, - /*parser_debug=*/false)); +auto ParseAndExecuteProto(const Fuzzing::Carbon& carbon) -> ErrorOr { const ErrorOr prelude_path = GetRunfilesFile("carbon/explorer/data/prelude.carbon"); // Can't do anything without a prelude, so it's a fatal error. CARBON_CHECK(prelude_path.ok()) << prelude_path.error(); - AddPrelude(*prelude_path, &arena, &ast.declarations, - &ast.num_prelude_declarations); - TraceStream trace_stream; - - // Use llvm::nulls() to suppress output from the Print intrinsic. - CARBON_ASSIGN_OR_RETURN( - ast, AnalyzeProgram(&arena, ast, &trace_stream, &llvm::nulls())); - return ExecProgram(&arena, ast, &trace_stream, &llvm::nulls()); + const std::string source = ProtoToCarbon(carbon, /*maybe_add_main=*/true); + return ParseAndExecute(*prelude_path, source); } -} // namespace Carbon +} // namespace Carbon::Testing diff --git a/explorer/fuzzing/fuzzer_util.h b/explorer/fuzzing/fuzzer_util.h index d584adf3b180..79cc71a5d044 100644 --- a/explorer/fuzzing/fuzzer_util.h +++ b/explorer/fuzzing/fuzzer_util.h @@ -9,16 +9,16 @@ #include "common/fuzzing/carbon.pb.h" #include "explorer/ast/ast.h" -namespace Carbon { +namespace Carbon::Testing { // Parses and executes a fuzzer-generated program. // Returns program result if execution was successful. -auto ParseAndExecute(const Fuzzing::Carbon& carbon) -> ErrorOr; +auto ParseAndExecuteProto(const Fuzzing::Carbon& carbon) -> ErrorOr; // Returns a full path for a file under bazel runfiles. // Exposed for testing. auto GetRunfilesFile(const std::string& file) -> ErrorOr; -} // namespace Carbon +} // namespace Carbon::Testing #endif // CARBON_EXPLORER_FUZZING_FUZZER_UTIL_H_ diff --git a/explorer/fuzzing/fuzzer_util_test.cpp b/explorer/fuzzing/fuzzer_util_test.cpp index 69c3fd6eee07..62e26b9f3495 100644 --- a/explorer/fuzzing/fuzzer_util_test.cpp +++ b/explorer/fuzzing/fuzzer_util_test.cpp @@ -16,7 +16,7 @@ namespace Carbon::Testing { namespace { -TEST(FuzzerUtilTest, ParseAndExecute) { +TEST(FuzzerUtilTest, ParseAndExecuteProto) { const ErrorOr carbon_proto = ParseCarbonTextProto(R"( compilation_unit { package_statement { package_name: "P" } @@ -42,7 +42,7 @@ TEST(FuzzerUtilTest, ParseAndExecute) { } })"); ASSERT_TRUE(carbon_proto.ok()); - const ErrorOr result = ParseAndExecute(*carbon_proto); + const ErrorOr result = ParseAndExecuteProto(*carbon_proto); ASSERT_TRUE(result.ok()) << "Execution failed: " << result.error(); EXPECT_EQ(*result, 0); } diff --git a/explorer/interpreter/BUILD b/explorer/interpreter/BUILD index ffd12c3f5639..dd1a6b13434e 100644 --- a/explorer/interpreter/BUILD +++ b/explorer/interpreter/BUILD @@ -2,7 +2,7 @@ # Exceptions. See /LICENSE for license information. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -package(default_visibility = ["//explorer:__pkg__"]) +package(default_visibility = ["//explorer/parse_and_execute:__pkg__"]) cc_library( name = "action", @@ -56,21 +56,17 @@ cc_library( name = "exec_program", srcs = ["exec_program.cpp"], hdrs = ["exec_program.h"], - visibility = [ - "//explorer:__pkg__", - "//explorer/fuzzing:__pkg__", - ], deps = [ ":interpreter", ":resolve_control_flow", ":resolve_names", ":resolve_unformed", - ":trace_stream", ":type_checker", "//common:check", "//common:ostream", "//explorer/ast", "//explorer/common:arena", + "//explorer/common:trace_stream", "@llvm-project//llvm:Support", ], ) @@ -114,7 +110,6 @@ cc_library( ":action_stack", ":heap", ":stack", - ":trace_stream", "//common:check", "//common:error", "//common:ostream", @@ -122,6 +117,7 @@ cc_library( "//explorer/common:arena", "//explorer/common:error_builders", "//explorer/common:source_location", + "//explorer/common:trace_stream", "@llvm-project//llvm:Support", ], ) @@ -175,20 +171,6 @@ cc_library( ], ) -cc_library( - name = "trace_stream", - hdrs = ["trace_stream.h"], - visibility = [ - "//explorer:__pkg__", - "//explorer/fuzzing:__pkg__", - ], - deps = [ - "//common:check", - "//common:ostream", - "//explorer/common:nonnull", - ], -) - cc_library( name = "type_checker", srcs = [ @@ -211,7 +193,6 @@ cc_library( ":dictionary", ":interpreter", ":pattern_analysis", - ":trace_stream", ":type_structure", "//common:check", "//common:enum_base", @@ -222,22 +203,7 @@ cc_library( "//explorer/common:error_builders", "//explorer/common:nonnull", "//explorer/common:source_location", - "@llvm-project//llvm:Support", - ], -) - -cc_library( - name = "type_structure", - srcs = [ - "type_structure.cpp", - ], - hdrs = [ - "type_structure.h", - ], - deps = [ - "//common:ostream", - "//explorer/ast", - "//explorer/common:nonnull", + "//explorer/common:trace_stream", "@llvm-project//llvm:Support", ], ) @@ -259,3 +225,19 @@ cc_library( "@llvm-project//llvm:Support", ], ) + +cc_library( + name = "type_structure", + srcs = [ + "type_structure.cpp", + ], + hdrs = [ + "type_structure.h", + ], + deps = [ + "//common:ostream", + "//explorer/ast", + "//explorer/common:nonnull", + "@llvm-project//llvm:Support", + ], +) diff --git a/explorer/interpreter/exec_program.h b/explorer/interpreter/exec_program.h index 8f372b759611..12998d2c0cb6 100644 --- a/explorer/interpreter/exec_program.h +++ b/explorer/interpreter/exec_program.h @@ -10,7 +10,7 @@ #define CARBON_EXPLORER_INTERPRETER_EXEC_PROGRAM_H_ #include "explorer/ast/ast.h" -#include "explorer/interpreter/trace_stream.h" +#include "explorer/common/trace_stream.h" #include "llvm/Support/raw_ostream.h" namespace Carbon { diff --git a/explorer/interpreter/interpreter.h b/explorer/interpreter/interpreter.h index fdc896af6cbb..15a48d017277 100644 --- a/explorer/interpreter/interpreter.h +++ b/explorer/interpreter/interpreter.h @@ -15,9 +15,9 @@ #include "explorer/ast/expression.h" #include "explorer/ast/pattern.h" #include "explorer/ast/value.h" +#include "explorer/common/trace_stream.h" #include "explorer/interpreter/action.h" #include "explorer/interpreter/heap.h" -#include "explorer/interpreter/trace_stream.h" #include "llvm/ADT/ArrayRef.h" namespace Carbon { diff --git a/explorer/interpreter/type_checker.h b/explorer/interpreter/type_checker.h index 60e36331b2ac..a7a3f859f1a5 100644 --- a/explorer/interpreter/type_checker.h +++ b/explorer/interpreter/type_checker.h @@ -19,12 +19,12 @@ #include "explorer/ast/statement.h" #include "explorer/ast/value.h" #include "explorer/common/nonnull.h" +#include "explorer/common/trace_stream.h" #include "explorer/interpreter/builtins.h" #include "explorer/interpreter/dictionary.h" #include "explorer/interpreter/impl_scope.h" #include "explorer/interpreter/interpreter.h" #include "explorer/interpreter/matching_impl_set.h" -#include "explorer/interpreter/trace_stream.h" #include "llvm/ADT/identity.h" namespace Carbon { diff --git a/explorer/main.cpp b/explorer/main.cpp index 34e68d07e6f7..2ca8fe012ac7 100644 --- a/explorer/main.cpp +++ b/explorer/main.cpp @@ -15,12 +15,8 @@ #include #include "common/error.h" -#include "explorer/common/arena.h" -#include "explorer/common/nonnull.h" -#include "explorer/interpreter/exec_program.h" -#include "explorer/interpreter/trace_stream.h" -#include "explorer/syntax/parse.h" -#include "explorer/syntax/prelude.h" +#include "explorer/common/trace_stream.h" +#include "explorer/parse_and_execute/parse_and_execute.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" @@ -85,81 +81,22 @@ auto ExplorerMain(int argc, char** argv, void* static_for_main_addr, } } - auto time_start = std::chrono::system_clock::now(); - - Arena arena; - AST ast; - if (ErrorOr parse_result = Parse(&arena, input_file_name, parser_debug); - parse_result.ok()) { - ast = *std::move(parse_result); - } else { - llvm::errs() << "SYNTAX ERROR: " << parse_result.error() << "\n"; - return EXIT_FAILURE; - } - - auto time_after_parse = std::chrono::system_clock::now(); - - AddPrelude(prelude_file_name, &arena, &ast.declarations, - &ast.num_prelude_declarations); - - auto time_after_prelude = std::chrono::system_clock::now(); - - // Semantically analyze the parsed program. - if (ErrorOr analyze_result = - AnalyzeProgram(&arena, ast, &trace_stream, &llvm::outs()); - analyze_result.ok()) { - ast = *std::move(analyze_result); - } else { - llvm::errs() << "COMPILATION ERROR: " << analyze_result.error() << "\n"; - return EXIT_FAILURE; - } - - auto time_after_analyze = std::chrono::system_clock::now(); - - // Run the program. - auto ret = EXIT_SUCCESS; - if (ErrorOr exec_result = - ExecProgram(&arena, ast, &trace_stream, &llvm::outs()); - exec_result.ok()) { + ErrorOr result = + ParseAndExecuteFile(prelude_file_name, input_file_name, parser_debug, + &trace_stream, &llvm::outs()); + if (result.ok()) { // Print the return code to stdout. - llvm::outs() << "result: " << *exec_result << "\n"; + llvm::outs() << "result: " << *result << "\n"; // When there's a dedicated trace file, print the return code to it too. if (scoped_trace_stream) { - trace_stream << "result: " << *exec_result << "\n"; + trace_stream << "result: " << *result << "\n"; } + return EXIT_SUCCESS; } else { - llvm::errs() << "RUNTIME ERROR: " << exec_result.error() << "\n"; - ret = EXIT_FAILURE; + llvm::errs() << result.error() << "\n"; + return EXIT_FAILURE; } - - auto time_after_exec = std::chrono::system_clock::now(); - - if (trace_stream.is_enabled()) { - trace_stream << "Timings:\n" - << "- Parse: " - << std::chrono::duration_cast( - time_after_parse - time_start) - .count() - << "ms\n" - << "- AddPrelude: " - << std::chrono::duration_cast( - time_after_prelude - time_after_parse) - .count() - << "ms\n" - << "- AnalyzeProgram: " - << std::chrono::duration_cast( - time_after_analyze - time_after_prelude) - .count() - << "ms\n" - << "- ExecProgram: " - << std::chrono::duration_cast( - time_after_exec - time_after_analyze) - .count() - << "ms\n"; - } - - return ret; } } // namespace Carbon diff --git a/explorer/parse_and_execute/BUILD b/explorer/parse_and_execute/BUILD new file mode 100644 index 000000000000..93eb002126f1 --- /dev/null +++ b/explorer/parse_and_execute/BUILD @@ -0,0 +1,25 @@ +# Part of the Carbon Language project, under the Apache License v2.0 with LLVM +# Exceptions. See /LICENSE for license information. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +load("//bazel/cc_toolchains:defs.bzl", "cc_env") + +package(default_visibility = [ + "//explorer:__pkg__", + "//explorer/fuzzing:__pkg__", +]) + +cc_library( + name = "parse_and_execute", + srcs = ["parse_and_execute.cpp"], + hdrs = ["parse_and_execute.h"], + deps = [ + "//common:check", + "//common:error", + "//explorer/common:trace_stream", + "//explorer/interpreter:exec_program", + "//explorer/syntax", + "//explorer/syntax:prelude", + "@llvm-project//llvm:Support", + ], +) diff --git a/explorer/parse_and_execute/parse_and_execute.cpp b/explorer/parse_and_execute/parse_and_execute.cpp new file mode 100644 index 000000000000..43fe63109d7e --- /dev/null +++ b/explorer/parse_and_execute/parse_and_execute.cpp @@ -0,0 +1,98 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include "explorer/parse_and_execute/parse_and_execute.h" + +#include + +#include "common/check.h" +#include "common/error.h" +#include "explorer/interpreter/exec_program.h" +#include "explorer/syntax/parse.h" +#include "explorer/syntax/prelude.h" +#include "llvm/ADT/ScopeExit.h" + +namespace Carbon { + +// Returns a scope exit function for printing the timing of a step on scope +// exit. Note the use prints step timings in reverse order. +static auto PrintTimingOnExit(TraceStream* trace_stream, const char* label, + std::chrono::steady_clock::time_point* cursor) { + auto end = std::chrono::steady_clock::now(); + auto duration = end - *cursor; + *cursor = end; + + return llvm::make_scope_exit([=]() { + if (trace_stream->is_enabled()) { + *trace_stream << "Time elapsed in " << label << ": " + << std::chrono::duration_cast( + duration) + .count() + << "ms\n"; + } + }); +} + +static auto ParseAndExecuteHelper(std::function(Arena*)> parse, + const std::string& prelude_path, + Nonnull trace_stream, + Nonnull print_stream) + -> ErrorOr { + Arena arena; + auto cursor = std::chrono::steady_clock::now(); + + ErrorOr parse_result = parse(&arena); + auto print_parse_time = PrintTimingOnExit(trace_stream, "Parse", &cursor); + if (!parse_result.ok()) { + return ErrorBuilder() << "SYNTAX ERROR: " << parse_result.error(); + } + + AddPrelude(prelude_path, &arena, &parse_result->declarations, + &parse_result->num_prelude_declarations); + auto print_prelude_time = + PrintTimingOnExit(trace_stream, "AddPrelude", &cursor); + + // Semantically analyze the parsed program. + ErrorOr analyze_result = + AnalyzeProgram(&arena, *parse_result, trace_stream, print_stream); + auto print_analyze_time = + PrintTimingOnExit(trace_stream, "AnalyzeProgram", &cursor); + if (!analyze_result.ok()) { + return ErrorBuilder() << "COMPILATION ERROR: " << analyze_result.error(); + } + + // Run the program. + ErrorOr exec_result = + ExecProgram(&arena, *analyze_result, trace_stream, print_stream); + auto print_exec_time = + PrintTimingOnExit(trace_stream, "ExecProgram", &cursor); + if (!exec_result.ok()) { + return ErrorBuilder() << "RUNTIME ERROR: " << exec_result.error(); + } + return exec_result; +} + +auto ParseAndExecuteFile(const std::string& prelude_path, + const std::string& input_file_name, bool parser_debug, + Nonnull trace_stream, + Nonnull print_stream) + -> ErrorOr { + auto parse = [&](Arena* arena) { + return Parse(arena, input_file_name, parser_debug); + }; + return ParseAndExecuteHelper(parse, prelude_path, trace_stream, print_stream); +} + +auto ParseAndExecute(const std::string& prelude_path, const std::string& source) + -> ErrorOr { + auto parse = [&](Arena* arena) { + return ParseFromString(arena, "test.carbon", source, + /*parser_debug=*/false); + }; + TraceStream trace_stream; + return ParseAndExecuteHelper(parse, prelude_path, &trace_stream, + &llvm::nulls()); +} + +} // namespace Carbon diff --git a/explorer/parse_and_execute/parse_and_execute.h b/explorer/parse_and_execute/parse_and_execute.h new file mode 100644 index 000000000000..e3ca0ad0623b --- /dev/null +++ b/explorer/parse_and_execute/parse_and_execute.h @@ -0,0 +1,28 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef CARBON_EXPLORER_PARSE_AND_EXECUTE_PARSE_AND_EXECUTE_H_ +#define CARBON_EXPLORER_PARSE_AND_EXECUTE_PARSE_AND_EXECUTE_H_ + +#include "common/error.h" +#include "explorer/common/trace_stream.h" + +namespace Carbon { + +// Parses and executes the input file, returning the program result on success. +// This API is intended for use by main execution. +auto ParseAndExecuteFile(const std::string& prelude_path, + const std::string& input_file_name, bool parser_debug, + Nonnull trace_stream, + Nonnull print_stream) + -> ErrorOr; + +// Parses and executes the source, returning the program result on success. +// Discards output. +auto ParseAndExecute(const std::string& prelude_path, const std::string& source) + -> ErrorOr; + +} // namespace Carbon + +#endif // CARBON_EXPLORER_PARSE_AND_EXECUTE_PARSE_AND_EXECUTE_H_ diff --git a/explorer/syntax/BUILD b/explorer/syntax/BUILD index 5baf65941bf1..03df0e9d1aa1 100644 --- a/explorer/syntax/BUILD +++ b/explorer/syntax/BUILD @@ -2,10 +2,7 @@ # Exceptions. See /LICENSE for license information. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -package(default_visibility = [ - "//explorer:__pkg__", - "//explorer/fuzzing:__pkg__", -]) +package(default_visibility = ["//explorer/parse_and_execute:__pkg__"]) cc_library( name = "bison_wrap", @@ -75,6 +72,10 @@ cc_library( "-Wno-unused-function", "-Wno-writable-strings", ], + visibility = [ + "//explorer/fuzzing:__pkg__", + "//explorer/parse_and_execute:__pkg__", + ], deps = [ ":bison_wrap", "//common:check",