From 96517a1ee3884cd9211697cda14bc9fef980ee7c Mon Sep 17 00:00:00 2001 From: Jon Ross-Perkins Date: Wed, 2 Aug 2023 14:44:16 -0700 Subject: [PATCH] Migrate explorer tests to file_test and remove lit support. (#3050) This migrates explorer tests to file_test, using the new --autoupdate functionality. Per discussion, the trace tests that were using "not" output are mostly migrated to checking full output. The main exception is tests that were including trace output from the prelude: the prelude output is pretty long (multiple MB already) and I think it wasn't the intent to include, only trace output from the small program. This is the remaining use of lit support, so the supporting libraries are also removed here. --- explorer/BUILD | 15 +- explorer/README.md | 25 - explorer/autoupdate_lit_testdata.py | 35 -- explorer/autoupdate_testdata.py | 32 -- .../BUILD => explorer/autoupdate_testdata.sh | 12 +- explorer/autoupdate_trace_testdata.py | 42 -- explorer/file_test.cpp | 45 +- explorer/lit_testdata/BUILD | 35 -- .../lit_testdata/fail_compile_error.carbon | 14 - explorer/lit_testdata/hello.carbon | 16 - explorer/lit_testdata/lit.cfg.py | 1 - explorer/lit_testdata/trace.carbon | 66 --- .../lit_testdata/trace_file_filters.carbon | 31 - explorer/testdata/assert/fail_assert.carbon | 2 +- explorer/testdata/assert/fail_convert.carbon | 2 +- .../basic_syntax}/zero.carbon | 2 - ...ete_base_without_virtual_destructor.carbon | 2 +- .../fail_left_shift_large_rhs.carbon | 2 +- .../fail_left_shift_negative_rhs.carbon | 2 +- .../fail_right_shift_large_rhs.carbon | 2 +- .../fail_right_shift_negative_rhs.carbon | 2 +- .../optional/fail_optional_get_empty.carbon | 2 +- .../testdata/random/fail_empty_range.carbon | 2 +- .../testdata/random/fail_reverse_range.carbon | 2 +- explorer/testdata/trace/context_all.carbon | 22 + explorer/testdata/trace/context_main.carbon | 160 ++++++ .../testdata/trace/context_prelude.carbon | 19 + .../trace/phase_all.carbon} | 195 +++---- .../phase_control_flow_resolution.carbon | 19 + .../testdata/trace/phase_declarations.carbon | 26 + .../testdata/trace/phase_execution.carbon | 78 +++ .../trace/phase_name_resolution.carbon | 34 ++ .../trace/phase_source_program.carbon | 26 + explorer/testdata/trace/phase_timing.carbon | 22 + .../testdata/trace/phase_type_checking.carbon | 52 ++ ...phase_unformed_variables_resolution.carbon | 22 + testing/file_test/autoupdate.cpp | 103 +++- testing/file_test/autoupdate.h | 4 +- testing/file_test/file_test_base.cpp | 78 ++- testing/file_test/file_test_base.h | 7 +- testing/lit_test/__init__.py | 0 testing/lit_test/lit.cfg.py | 58 -- testing/lit_test/lit_test.py | 57 -- testing/lit_test/merge_output.py | 38 -- testing/lit_test/rules.bzl | 66 --- testing/scripts/__init__.py | 0 testing/scripts/autoupdate_testdata_base.py | 542 ------------------ toolchain/lexer/lexer_file_test.cpp | 4 +- 48 files changed, 772 insertions(+), 1251 deletions(-) delete mode 100755 explorer/autoupdate_lit_testdata.py delete mode 100755 explorer/autoupdate_testdata.py rename testing/lit_test/BUILD => explorer/autoupdate_testdata.sh (54%) mode change 100644 => 100755 delete mode 100755 explorer/autoupdate_trace_testdata.py delete mode 100644 explorer/lit_testdata/BUILD delete mode 100644 explorer/lit_testdata/fail_compile_error.carbon delete mode 100644 explorer/lit_testdata/hello.carbon delete mode 120000 explorer/lit_testdata/lit.cfg.py delete mode 100644 explorer/lit_testdata/trace.carbon delete mode 100644 explorer/lit_testdata/trace_file_filters.carbon rename explorer/{lit_testdata => testdata/basic_syntax}/zero.carbon (70%) create mode 100644 explorer/testdata/trace/context_all.carbon create mode 100644 explorer/testdata/trace/context_main.carbon create mode 100644 explorer/testdata/trace/context_prelude.carbon rename explorer/{trace_testdata/full_trace.carbon => testdata/trace/phase_all.carbon} (76%) create mode 100644 explorer/testdata/trace/phase_control_flow_resolution.carbon create mode 100644 explorer/testdata/trace/phase_declarations.carbon create mode 100644 explorer/testdata/trace/phase_execution.carbon create mode 100644 explorer/testdata/trace/phase_name_resolution.carbon create mode 100644 explorer/testdata/trace/phase_source_program.carbon create mode 100644 explorer/testdata/trace/phase_timing.carbon create mode 100644 explorer/testdata/trace/phase_type_checking.carbon create mode 100644 explorer/testdata/trace/phase_unformed_variables_resolution.carbon delete mode 100644 testing/lit_test/__init__.py delete mode 100644 testing/lit_test/lit.cfg.py delete mode 100644 testing/lit_test/lit_test.py delete mode 100644 testing/lit_test/merge_output.py delete mode 100644 testing/lit_test/rules.bzl delete mode 100644 testing/scripts/__init__.py delete mode 100755 testing/scripts/autoupdate_testdata_base.py diff --git a/explorer/BUILD b/explorer/BUILD index 076a1f034740..441e368af351 100644 --- a/explorer/BUILD +++ b/explorer/BUILD @@ -51,6 +51,7 @@ cc_library( "//testing/file_test:file_test_base", "//testing/util:test_raw_ostream", "@com_google_absl//absl/flags:flag", + "@com_googlesource_code_re2//:re2", ], ) @@ -58,11 +59,11 @@ file_test( name = "file_test", size = "small", shard_count = 20, - tests = glob([ - "testdata/**/*.carbon", - "trace_testdata/**/*.carbon", - ]), - deps = [":file_test_common"], + tests = glob(["testdata/**/*.carbon"]), + deps = [ + ":file_test_common", + "@com_googlesource_code_re2//:re2", + ], ) file_test( @@ -71,14 +72,14 @@ file_test( args = ["--trace"], shard_count = 30, tests = glob( - # This omits trace_testdata because that's run with trace in the - # default mode. ["testdata/**/*.carbon"], exclude = [ # `limits` tests check for various limit conditions (such as an # infinite loop). The tests collectively don't test tracing # because it creates substantial additional overhead. "testdata/limits/**", + # `trace` tests do tracing by default. + "testdata/trace/**", # Expensive tests to trace. "testdata/assoc_const/rewrite_large_type.carbon", "testdata/linked_list/typed_linked_list.carbon", diff --git a/explorer/README.md b/explorer/README.md index 15e2228779d1..5b777b0a9226 100644 --- a/explorer/README.md +++ b/explorer/README.md @@ -117,31 +117,6 @@ To explain this boilerplate: braces indicate a contained regular expression. - The `package` is required in all test files, per normal Carbon syntax rules. -### lit tests - -The [`lit_testdata/`](lit_testdata/) subdirectory includes other example -programs. - -These tests make use of LLVM's -[lit](https://llvm.org/docs/CommandGuide/lit.html) and -[FileCheck](https://llvm.org/docs/CommandGuide/FileCheck.html). - -They share most of their header with those in `testdata`, with an additional -`RUN` rule: - -``` -// RUN: %{explorer-run} -// RUN: %{explorer-run-trace} -``` - -The `RUN` lines indicate two commands for `lit` to execute using the file: one -without trace and debug output, one with. - -- `RUN:` will be followed by the `not` command when failure is expected. In - particular, `RUN: not %{explorer-run}`. -- The full command is in `lit.cfg.py`; it will run explorer and pass results - to [`FileCheck`](https://llvm.org/docs/CommandGuide/FileCheck.html). - ### Useful commands - `./autoupdate_testdata.py` -- Updates expected output. diff --git a/explorer/autoupdate_lit_testdata.py b/explorer/autoupdate_lit_testdata.py deleted file mode 100755 index 127aa3922ce1..000000000000 --- a/explorer/autoupdate_lit_testdata.py +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env python3 - -"""Updates the CHECK: lines in tests with an AUTOUPDATE line.""" - -__copyright__ = """ -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 -""" - -import subprocess -import sys -from pathlib import Path - - -def main() -> None: - # Subprocess to the main script in order to avoid Python import behaviors. - this_py = Path(__file__).resolve() - autoupdate_py = this_py.parent.parent.joinpath( - "testing", "scripts", "autoupdate_testdata_base.py" - ) - args = [ - str(autoupdate_py), - # Flags to configure for explorer testing. - "--tool=explorer", - "--testdata=explorer/lit_testdata", - "--lit_run=%{explorer} | %{FileCheck-strict}", - "--lit_run=%{explorer} --parser_debug --trace_file=- | " - "%{FileCheck-allow-unmatched}", - ] + sys.argv[1:] - exit(subprocess.call(args)) - - -if __name__ == "__main__": - main() diff --git a/explorer/autoupdate_testdata.py b/explorer/autoupdate_testdata.py deleted file mode 100755 index ea8ee6222dad..000000000000 --- a/explorer/autoupdate_testdata.py +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env python3 - -"""Updates the CHECK: lines in tests with an AUTOUPDATE line.""" - -__copyright__ = """ -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 -""" - -import subprocess -import sys -from pathlib import Path - - -def main() -> None: - # Subprocess to the main script in order to avoid Python import behaviors. - this_py = Path(__file__).resolve() - autoupdate_py = this_py.parent.parent.joinpath( - "testing", "scripts", "autoupdate_testdata_base.py" - ) - args = [ - str(autoupdate_py), - # Flags to configure for explorer testing. - "--tool=explorer", - "--testdata=explorer/testdata", - ] + sys.argv[1:] - exit(subprocess.call(args)) - - -if __name__ == "__main__": - main() diff --git a/testing/lit_test/BUILD b/explorer/autoupdate_testdata.sh old mode 100644 new mode 100755 similarity index 54% rename from testing/lit_test/BUILD rename to explorer/autoupdate_testdata.sh index 3b77481dbedb..994b15d7f3a2 --- a/testing/lit_test/BUILD +++ b/explorer/autoupdate_testdata.sh @@ -1,12 +1,8 @@ +#!/usr/bin/env bash + # 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 -package(default_visibility = ["//visibility:public"]) - -exports_files(["lit_test.py"]) - -py_binary( - name = "merge_output", - srcs = ["merge_output.py"], -) +bazel run -c opt --test_sharding_strategy=disabled //explorer:file_test \ + -- --autoupdate diff --git a/explorer/autoupdate_trace_testdata.py b/explorer/autoupdate_trace_testdata.py deleted file mode 100755 index aa5a53ef27fc..000000000000 --- a/explorer/autoupdate_trace_testdata.py +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/env python3 - -"""Updates the CHECK: lines in tests with an AUTOUPDATE line.""" - -__copyright__ = """ -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 -""" - -import subprocess -import sys -from pathlib import Path - - -def main() -> None: - # Subprocess to the main script in order to avoid Python import behaviors. - this_py = Path(__file__).resolve() - autoupdate_py = this_py.parent.parent.joinpath( - "testing", "scripts", "autoupdate_testdata_base.py" - ) - - args = [ - str(autoupdate_py), - # Flags to configure for explorer testing. - "--tool=explorer", - "--testdata=explorer/trace_testdata", - "--autoupdate_arg=--trace_file=-", - "--autoupdate_arg=-trace_phase=all", - "--extra_check_replacement", - r".+Time elapsed in (\S+): (\d+)ms", - r"Time elapsed in (\S+): (\d+)ms", - r"Time elapsed in \1: {{[0-9]+}}ms", - # Do not perform line number replacement. - "--line_number_pattern", - "(?!)", - ] + sys.argv[1:] - exit(subprocess.call(args)) - - -if __name__ == "__main__": - main() diff --git a/explorer/file_test.cpp b/explorer/file_test.cpp index 3e9785f974a3..19d83239dbe2 100644 --- a/explorer/file_test.cpp +++ b/explorer/file_test.cpp @@ -4,6 +4,7 @@ #include "absl/flags/flag.h" #include "explorer/main.h" +#include "re2/re2.h" #include "testing/file_test/file_test_base.h" #include "testing/util/test_raw_ostream.h" @@ -17,7 +18,13 @@ namespace { class ExplorerFileTest : public FileTestBase { public: - using FileTestBase::FileTestBase; + explicit ExplorerFileTest(std::filesystem::path path) + : FileTestBase(std::move(path)), + prelude_line_re_(R"(prelude.carbon:(\d+))"), + timing_re_(R"((Time elapsed in \w+: )\d+(ms))") { + CARBON_CHECK(prelude_line_re_.ok()) << prelude_line_re_.error(); + CARBON_CHECK(timing_re_.ok()) << timing_re_.error(); + } auto Run(const llvm::SmallVector& test_args, const llvm::SmallVector& test_files, @@ -52,13 +59,9 @@ class ExplorerFileTest : public FileTestBase { args.push_back(arg.data()); } - // Trace output is only checked for a few tests. - bool check_trace_output = - path().string().find("trace_testdata/") != std::string::npos; - int exit_code = ExplorerMain( args.size(), args.data(), /*install_path=*/"", PreludePath, stdout, - stderr, check_trace_output ? stdout : trace_stream_, fs); + stderr, check_trace_output() ? stdout : trace_stream_, fs); return exit_code == EXIT_SUCCESS; } @@ -83,7 +86,37 @@ class ExplorerFileTest : public FileTestBase { return args; } + auto GetLineNumberReplacement(llvm::ArrayRef filenames) + -> LineNumberReplacement override { + if (check_trace_output()) { + return {.has_file = false, + .pattern = R"((DO NOT MATCH))", + // The `{{{{` becomes `{{`. + .line_formatv = "{{{{ *}}{0}"}; + } + return FileTestBase::GetLineNumberReplacement(filenames); + } + + auto DoExtraCheckReplacements(std::string& check_line) -> void override { + // Ignore the resulting column of EndOfFile because it's often the end of + // the CHECK comment. + RE2::GlobalReplace(&check_line, prelude_line_re_, + R"(prelude.carbon:{{\\d+}})"); + if (check_trace_output()) { + // Replace timings in trace output. + RE2::GlobalReplace(&check_line, timing_re_, R"(\1{{\\d+}}\2)"); + } + } + + private: + // Trace output is directly checked for a few tests. + auto check_trace_output() -> bool { + return path().string().find("/trace/") != std::string::npos; + } + TestRawOstream trace_stream_; + RE2 prelude_line_re_; + RE2 timing_re_; }; } // namespace diff --git a/explorer/lit_testdata/BUILD b/explorer/lit_testdata/BUILD deleted file mode 100644 index 61957166d745..000000000000 --- a/explorer/lit_testdata/BUILD +++ /dev/null @@ -1,35 +0,0 @@ -# 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/sh_run:rules.bzl", "glob_sh_run") -load("//testing/lit_test:rules.bzl", "glob_lit_tests") - -glob_lit_tests( - name = "all_lit_tests", - data = [ - "//explorer", - "//testing/lit_test:merge_output", - "@llvm-project//llvm:FileCheck", - "@llvm-project//llvm:not", - ], - driver = "lit.cfg.py", - test_file_exts = ["carbon"], -) - -glob_sh_run( - args = ["$(location //explorer)"], - data = ["//explorer"], - file_exts = ["carbon"], -) - -glob_sh_run( - args = [ - "$(location //explorer)", - "--parser_debug", - "--trace_file=-", - ], - data = ["//explorer"], - file_exts = ["carbon"], - run_ext = "verbose", -) diff --git a/explorer/lit_testdata/fail_compile_error.carbon b/explorer/lit_testdata/fail_compile_error.carbon deleted file mode 100644 index 928f6329d13d..000000000000 --- a/explorer/lit_testdata/fail_compile_error.carbon +++ /dev/null @@ -1,14 +0,0 @@ -// 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 -// -// NOAUTOUPDATE -// RUN: %{not} %{explorer} | %{FileCheck-strict} -// RUN: %{not} %{explorer} --parser_debug --trace_file=- | %{FileCheck-allow-unmatched} - -package ExplorerTest api; - -// Just needs to produce an error to validate basic structure. -fn Main() -> i32 { -// CHECK:STDERR: COMPILATION ERROR: {{.*}}/explorer/lit_testdata/fail_compile_error.carbon:[[@LINE+1]]: {{.*}} -} diff --git a/explorer/lit_testdata/hello.carbon b/explorer/lit_testdata/hello.carbon deleted file mode 100644 index 2d47f6940265..000000000000 --- a/explorer/lit_testdata/hello.carbon +++ /dev/null @@ -1,16 +0,0 @@ -// 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 -// -// AUTOUPDATE -// RUN: %{explorer} | %{FileCheck-strict} -// RUN: %{explorer} --parser_debug --trace_file=- | %{FileCheck-allow-unmatched} -// CHECK:STDOUT: Hello -// CHECK:STDOUT: result: 0 - -package ExplorerTest api; - -fn Main() -> i32 { - Print("Hello"); - return 0; -} diff --git a/explorer/lit_testdata/lit.cfg.py b/explorer/lit_testdata/lit.cfg.py deleted file mode 120000 index 232aeeaeaf42..000000000000 --- a/explorer/lit_testdata/lit.cfg.py +++ /dev/null @@ -1 +0,0 @@ -../../testing/lit_test/lit.cfg.py \ No newline at end of file diff --git a/explorer/lit_testdata/trace.carbon b/explorer/lit_testdata/trace.carbon deleted file mode 100644 index 529300725e26..000000000000 --- a/explorer/lit_testdata/trace.carbon +++ /dev/null @@ -1,66 +0,0 @@ -// 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 -// -// A lot of output is elided: this is only checking for a few things for simple -// sanity checking on --parser_debug --trace_file=- along with filter flags output. -// -// NOAUTOUPDATE -// RUN: %{explorer} --parser_debug --trace_file=- -trace_file_context=all | %{FileCheck-allow-unmatched} --check-prefixes=NO-SOURCE,NO-NAMES,NO-PRELUDE,NO-FLOW,NO-TYPE,NO-UNFORMED,NO-DECLS,EXEC,NO-TIMING -// RUN: %{explorer} --parser_debug --trace_file=- -trace_file_context=all -trace_phase=execution | %{FileCheck-allow-unmatched} --check-prefixes=NO-SOURCE,NO-NAMES,NO-PRELUDE,NO-FLOW,NO-TYPE,NO-UNFORMED,NO-DECLS,EXEC,NO-TIMING -// RUN: %{explorer} --parser_debug --trace_file=- -trace_file_context=all -trace_phase=source_program | %{FileCheck-allow-unmatched} --check-prefixes=SOURCE,NO-NAMES,NO-PRELUDE,NO-FLOW,NO-TYPE,NO-UNFORMED,NO-DECLS,NO-EXEC,NO-TIMING -// RUN: %{explorer} --parser_debug --trace_file=- -trace_file_context=all -trace_phase=name_resolution | %{FileCheck-allow-unmatched} --check-prefixes=NO-SOURCE,NAMES,NO-PRELUDE,NO-FLOW,NO-TYPE,NO-UNFORMED,NO-DECLS,NO-EXEC,NO-TIMING -// RUN: %{explorer} --parser_debug --trace_file=- -trace_file_context=all -trace_phase=control_flow_resolution | %{FileCheck-allow-unmatched} --check-prefixes=NO-SOURCE,NO-NAMES,NO-PRELUDE,FLOW,NO-TYPE,NO-UNFORMED,NO-DECLS,NO-EXEC,NO-TIMING -// RUN: %{explorer} --parser_debug --trace_file=- -trace_file_context=all -trace_phase=type_checking | %{FileCheck-allow-unmatched} --check-prefixes=NO-SOURCE,NO-NAMES,NO-PRELUDE,NO-FLOW,TYPE,NO-UNFORMED,NO-DECLS,NO-EXEC,NO-TIMING -// RUN: %{explorer} --parser_debug --trace_file=- -trace_file_context=all -trace_phase=unformed_variables_resolution | %{FileCheck-allow-unmatched} --check-prefixes=NO-SOURCE,NO-NAMES,NO-PRELUDE,NO-FLOW,NO-TYPE,UNFORMED,NO-DECLS,NO-EXEC,NO-TIMING -// RUN: %{explorer} --parser_debug --trace_file=- -trace_file_context=all -trace_phase=declarations | %{FileCheck-allow-unmatched} --check-prefixes=NO-SOURCE,NO-NAMES,NO-PRELUDE,NO-FLOW,NO-TYPE,NO-UNFORMED,DECLS,NO-EXEC,NO-TIMING -// RUN: %{explorer} --parser_debug --trace_file=- -trace_file_context=all -trace_phase=timing | %{FileCheck-allow-unmatched} --check-prefixes=NO-SOURCE,NO-NAMES,NO-PRELUDE,NO-FLOW,NO-TYPE,NO-UNFORMED,NO-DECLS,NO-EXEC,TIMING -// RUN: %{explorer} --parser_debug --trace_file=- -trace_file_context=all -trace_phase=all | %{FileCheck-allow-unmatched} --check-prefixes=SOURCE,NAMES,NO-PRELUDE,FLOW,TYPE,UNFORMED,DECLS,EXEC,TIMING -// RUN: %{explorer} --parser_debug --trace_file=- -trace_file_context=all -trace_phase=source_program,declarations | %{FileCheck-allow-unmatched} --check-prefixes=SOURCE,NO-NAMES,NO-PRELUDE,NO-FLOW,NO-TYPE,NO-UNFORMED,DECLS,NO-EXEC,NO-TIMING -// NO-SOURCE-NOT:STDOUT: ********** source program ********** -// SOURCE:STDOUT: ********** source program ********** -// NO-SOURCE-NOT:STDOUT: interface TestInterface { -// SOURCE:STDOUT: interface TestInterface { -// NO-NAMES-NOT:STDOUT: ********** resolving names ********** -// NAMES:STDOUT: ********** resolving names ********** -// NO-PRELUDE-NOT:STDOUT: interface ImplicitAs { -// NO-FLOW-NOT:STDOUT: ********** resolving control flow ********** -// FLOW:STDOUT: ********** resolving control flow ********** -// NO-TYPE-NOT:STDOUT: ********** type checking ********** -// TYPE:STDOUT: ********** type checking ********** -// NO-TYPE-NOT:STDOUT: ** declaring interface TestInterface -// TYPE:STDOUT: ** declaring interface TestInterface -// NO-UNFORMED-NOT:STDOUT: ********** resolving unformed variables ********** -// UNFORMED:STDOUT: ********** resolving unformed variables ********** -// NO-DECLS-NOT:STDOUT: ********** printing declarations ********** -// DECLS:STDOUT: ********** printing declarations ********** -// NO-DECLS-NOT:STDOUT: interface TestInterface { -// DECLS:STDOUT: interface TestInterface { -// NO-EXEC-NOT:STDOUT: ********** starting execution ********** -// EXEC:STDOUT: ********** starting execution ********** -// NO-EXEC-NOT:STDOUT: ********** initializing globals ********** -// EXEC:STDOUT: ********** initializing globals ********** -// NO-EXEC-NOT:STDOUT: ********** calling main function ********** -// EXEC:STDOUT: ********** calling main function ********** -// NO-EXEC-NOT:STDOUT: --- step exp Main() .0. (:0) ---> -// EXEC:STDOUT: --- step exp Main() .0. (:0) ---> -// NO-EXEC-NOT:STDOUT: interpreter result: 0 -// EXEC:STDOUT: interpreter result: 0 -// NO-TIMING-NOT:STDOUT: ********** printing timing ********** -// TIMING:STDOUT: ********** printing timing ********** -// NO-TIMING-NOT:STDOUT: Time elapsed in ExecProgram: {{[0-9]+}}ms -// TIMING:STDOUT: Time elapsed in ExecProgram: {{[0-9]+}}ms -// NO-TIMING-NOT:STDOUT: Time elapsed in AnalyzeProgram: {{[0-9]+}}ms -// TIMING:STDOUT: Time elapsed in AnalyzeProgram: {{[0-9]+}}ms -// NO-TIMING-NOT:STDOUT: Time elapsed in AddPrelude: {{[0-9]+}}ms -// TIMING:STDOUT: Time elapsed in AddPrelude: {{[0-9]+}}ms -// NO-TIMING-NOT:STDOUT: Time elapsed in Parse: {{[0-9]+}}ms -// TIMING:STDOUT: Time elapsed in Parse: {{[0-9]+}}ms - -package ExplorerTest api; - -interface TestInterface {} - -fn Main() -> i32 { - return 0; -} diff --git a/explorer/lit_testdata/trace_file_filters.carbon b/explorer/lit_testdata/trace_file_filters.carbon deleted file mode 100644 index dc75164af8bc..000000000000 --- a/explorer/lit_testdata/trace_file_filters.carbon +++ /dev/null @@ -1,31 +0,0 @@ -// 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 -// -// A lot of output is elided: this is only checking for a few things for simple -// sanity checking on --parser_debug --trace_file=- along with file context -// filter flags output. -// -// NOAUTOUPDATE -// RUN: %{explorer} --parser_debug --trace_file=- -trace_phase=all -trace_file_context=main | %{FileCheck-allow-unmatched} --check-prefixes=MAIN,NO-PRELUDE -// RUN: %{explorer} --parser_debug --trace_file=- -trace_phase=all -trace_file_context=prelude | %{FileCheck-allow-unmatched} --check-prefixes=NO-MAIN,PRELUDE -// RUN: %{explorer} --parser_debug --trace_file=- -trace_phase=all -trace_file_context=all | %{FileCheck-allow-unmatched} --check-prefixes=MAIN,PRELUDE -// RUN: %{explorer} --parser_debug --trace_file=- -trace_phase=all -trace_file_context=main,prelude | %{FileCheck-allow-unmatched} --check-prefixes=MAIN,PRELUDE -// NO-PRELUDE-NOT:STDOUT: ** declaring interface As -// PRELUDE:STDOUT: ** declaring interface As -// NO-MAIN-NOT:STDOUT: ** declaring function Main -// MAIN:STDOUT: ** declaring function Main -// NO-PRELUDE-NOT:STDOUT: interface As { -// PRELUDE:STDOUT: interface As { -// NO-MAIN-NOT:STDOUT: fn Main ()-> i32 { -// MAIN:STDOUT: fn Main ()-> i32 { -// NO-MAIN-NOT:STDOUT: --- step exp Main() .0. (:0) ---> -// MAIN:STDOUT: --- step exp Main() .0. (:0) ---> - -package ExplorerTest api; - -interface TestInterface {} - -fn Main() -> i32 { - return 0; -} diff --git a/explorer/testdata/assert/fail_assert.carbon b/explorer/testdata/assert/fail_assert.carbon index adee17e917ba..577c96767a8d 100644 --- a/explorer/testdata/assert/fail_assert.carbon +++ b/explorer/testdata/assert/fail_assert.carbon @@ -3,7 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // // AUTOUPDATE -// CHECK:STDERR: RUNTIME ERROR: {{.*}}/explorer/data/prelude.carbon:{{.*}}: "HALLO WELT" +// CHECK:STDERR: RUNTIME ERROR: /explorer/data/prelude.carbon:{{\d+}}: "HALLO WELT" package ExplorerTest api; diff --git a/explorer/testdata/assert/fail_convert.carbon b/explorer/testdata/assert/fail_convert.carbon index 14850834eb79..4b4633105444 100644 --- a/explorer/testdata/assert/fail_convert.carbon +++ b/explorer/testdata/assert/fail_convert.carbon @@ -3,7 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // // AUTOUPDATE -// CHECK:STDERR: RUNTIME ERROR: {{.*}}/explorer/data/prelude.carbon:{{.*}}: "Fail" +// CHECK:STDERR: RUNTIME ERROR: /explorer/data/prelude.carbon:{{\d+}}: "Fail" package ExplorerTest api; diff --git a/explorer/lit_testdata/zero.carbon b/explorer/testdata/basic_syntax/zero.carbon similarity index 70% rename from explorer/lit_testdata/zero.carbon rename to explorer/testdata/basic_syntax/zero.carbon index 792edc95a15d..0dd08dd99e6e 100644 --- a/explorer/lit_testdata/zero.carbon +++ b/explorer/testdata/basic_syntax/zero.carbon @@ -3,8 +3,6 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // // AUTOUPDATE -// RUN: %{explorer} | %{FileCheck-strict} -// RUN: %{explorer} --parser_debug --trace_file=- | %{FileCheck-allow-unmatched} // CHECK:STDOUT: result: 0 package ExplorerTest api; diff --git a/explorer/testdata/destructor/fail_delete_base_without_virtual_destructor.carbon b/explorer/testdata/destructor/fail_delete_base_without_virtual_destructor.carbon index b41544187c28..f93b2ffc0a6c 100644 --- a/explorer/testdata/destructor/fail_delete_base_without_virtual_destructor.carbon +++ b/explorer/testdata/destructor/fail_delete_base_without_virtual_destructor.carbon @@ -3,7 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // // AUTOUPDATE -// CHECK:STDERR: RUNTIME ERROR: {{.*}}/explorer/data/prelude.carbon:{{.*}}: Deallocating a derived class from base class pointer requires a virtual destructor +// CHECK:STDERR: RUNTIME ERROR: /explorer/data/prelude.carbon:{{\d+}}: Deallocating a derived class from base class pointer requires a virtual destructor package ExplorerTest api; diff --git a/explorer/testdata/operators/fail_left_shift_large_rhs.carbon b/explorer/testdata/operators/fail_left_shift_large_rhs.carbon index 86ed85194971..3eb36e6f090c 100644 --- a/explorer/testdata/operators/fail_left_shift_large_rhs.carbon +++ b/explorer/testdata/operators/fail_left_shift_large_rhs.carbon @@ -3,7 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // // AUTOUPDATE -// CHECK:STDERR: RUNTIME ERROR: {{.*}}/explorer/data/prelude.carbon:{{.*}}: Integer overflow +// CHECK:STDERR: RUNTIME ERROR: /explorer/data/prelude.carbon:{{\d+}}: Integer overflow package ExplorerTest api; diff --git a/explorer/testdata/operators/fail_left_shift_negative_rhs.carbon b/explorer/testdata/operators/fail_left_shift_negative_rhs.carbon index a633e90577ac..9866b0e71bfc 100644 --- a/explorer/testdata/operators/fail_left_shift_negative_rhs.carbon +++ b/explorer/testdata/operators/fail_left_shift_negative_rhs.carbon @@ -3,7 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // // AUTOUPDATE -// CHECK:STDERR: RUNTIME ERROR: {{.*}}/explorer/data/prelude.carbon:{{.*}}: Integer overflow +// CHECK:STDERR: RUNTIME ERROR: /explorer/data/prelude.carbon:{{\d+}}: Integer overflow package ExplorerTest api; diff --git a/explorer/testdata/operators/fail_right_shift_large_rhs.carbon b/explorer/testdata/operators/fail_right_shift_large_rhs.carbon index 22bb572a3b58..8aa0c384e940 100644 --- a/explorer/testdata/operators/fail_right_shift_large_rhs.carbon +++ b/explorer/testdata/operators/fail_right_shift_large_rhs.carbon @@ -3,7 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // // AUTOUPDATE -// CHECK:STDERR: RUNTIME ERROR: {{.*}}/explorer/data/prelude.carbon:{{.*}}: Integer overflow +// CHECK:STDERR: RUNTIME ERROR: /explorer/data/prelude.carbon:{{\d+}}: Integer overflow package ExplorerTest api; diff --git a/explorer/testdata/operators/fail_right_shift_negative_rhs.carbon b/explorer/testdata/operators/fail_right_shift_negative_rhs.carbon index c0a99e5d691c..9cc9ab6a15bb 100644 --- a/explorer/testdata/operators/fail_right_shift_negative_rhs.carbon +++ b/explorer/testdata/operators/fail_right_shift_negative_rhs.carbon @@ -3,7 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // // AUTOUPDATE -// CHECK:STDERR: RUNTIME ERROR: {{.*}}/explorer/data/prelude.carbon:{{.*}}: Integer overflow +// CHECK:STDERR: RUNTIME ERROR: /explorer/data/prelude.carbon:{{\d+}}: Integer overflow package ExplorerTest api; diff --git a/explorer/testdata/optional/fail_optional_get_empty.carbon b/explorer/testdata/optional/fail_optional_get_empty.carbon index f1aab77d6144..c2f0d1560a69 100644 --- a/explorer/testdata/optional/fail_optional_get_empty.carbon +++ b/explorer/testdata/optional/fail_optional_get_empty.carbon @@ -3,7 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // // AUTOUPDATE -// CHECK:STDERR: RUNTIME ERROR: {{.*}}/explorer/data/prelude.carbon:{{.*}}: "Attempted to unwrap empty Optional" +// CHECK:STDERR: RUNTIME ERROR: /explorer/data/prelude.carbon:{{\d+}}: "Attempted to unwrap empty Optional" package ExplorerTest api; diff --git a/explorer/testdata/random/fail_empty_range.carbon b/explorer/testdata/random/fail_empty_range.carbon index 03b4c42e8317..81b7d839cd57 100644 --- a/explorer/testdata/random/fail_empty_range.carbon +++ b/explorer/testdata/random/fail_empty_range.carbon @@ -3,7 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // // AUTOUPDATE -// CHECK:STDERR: RUNTIME ERROR: {{.*}}/explorer/data/prelude.carbon:{{.*}}: Rand inputs must be ordered for a non-empty range: 0 must be less than 0 +// CHECK:STDERR: RUNTIME ERROR: /explorer/data/prelude.carbon:{{\d+}}: Rand inputs must be ordered for a non-empty range: 0 must be less than 0 package ExplorerTest api; diff --git a/explorer/testdata/random/fail_reverse_range.carbon b/explorer/testdata/random/fail_reverse_range.carbon index 23b782ea3b4c..f8f6ece01961 100644 --- a/explorer/testdata/random/fail_reverse_range.carbon +++ b/explorer/testdata/random/fail_reverse_range.carbon @@ -3,7 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // // AUTOUPDATE -// CHECK:STDERR: RUNTIME ERROR: {{.*}}/explorer/data/prelude.carbon:{{.*}}: Rand inputs must be ordered for a non-empty range: 1 must be less than -1 +// CHECK:STDERR: RUNTIME ERROR: /explorer/data/prelude.carbon:{{\d+}}: Rand inputs must be ordered for a non-empty range: 1 must be less than -1 package ExplorerTest api; diff --git a/explorer/testdata/trace/context_all.carbon b/explorer/testdata/trace/context_all.carbon new file mode 100644 index 000000000000..77aa4d1bb895 --- /dev/null +++ b/explorer/testdata/trace/context_all.carbon @@ -0,0 +1,22 @@ +// 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 + +package ExplorerTest api; + +interface TestInterface {} + +fn Main() -> i32 { + return 0; +} + +// Place checks after code so that line numbers are stable, reducing merge +// conflicts. +// ARGS: --trace_file=- --trace_phase=all --trace_file_context=all %s +// NOAUTOUPDATE +// SET-CHECK-SUBSET +// CHECK:STDOUT: ** declaring interface As +// CHECK:STDOUT: ** declaring function Main +// CHECK:STDOUT: interface As { +// CHECK:STDOUT: fn Main ()-> i32 { +// CHECK:STDOUT: --- step exp Main() .0. (:0) ---> diff --git a/explorer/testdata/trace/context_main.carbon b/explorer/testdata/trace/context_main.carbon new file mode 100644 index 000000000000..a74d35275475 --- /dev/null +++ b/explorer/testdata/trace/context_main.carbon @@ -0,0 +1,160 @@ +// 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 + +package ExplorerTest api; + +interface TestInterface {} + +fn Main() -> i32 { + return 0; +} + +// Place checks after code so that line numbers are stable, reducing merge +// conflicts. +// ARGS: --trace_file=- --trace_phase=all --trace_file_context=main %s +// AUTOUPDATE +// CHECK:STDOUT: ********** source program ********** +// CHECK:STDOUT: interface TestInterface { +// CHECK:STDOUT: } +// CHECK:STDOUT: fn Main ()-> i32 { +// CHECK:STDOUT: { +// CHECK:STDOUT: return 0; +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: ********** resolving names ********** +// CHECK:STDOUT: --- declared `TestInterface` as `interface TestInterface` in `package` (context_main.carbon:7) +// CHECK:STDOUT: --- declared `Main` as `fn Main` in `package` (context_main.carbon:11) +// CHECK:STDOUT: ** resolving decl `interface TestInterface` (context_main.carbon:7) +// CHECK:STDOUT: --- marked `TestInterface` declared but not usable in `package` +// CHECK:STDOUT: --- marked `TestInterface` usable in `package` +// CHECK:STDOUT: --- declared `Self` as `Self` in `interface TestInterface` (context_main.carbon:7) +// CHECK:STDOUT: ** finished resolving decl `interface TestInterface` (context_main.carbon:7) +// CHECK:STDOUT: ** resolving decl `fn Main` (context_main.carbon:11) +// CHECK:STDOUT: --- marked `Main` declared but not usable in `package` +// CHECK:STDOUT: --- marked `Main` usable in `package` +// CHECK:STDOUT: ** resolving stmt `{return 0;}` (context_main.carbon:11) +// CHECK:STDOUT: ** resolving stmt `return 0;` (context_main.carbon:10) +// CHECK:STDOUT: ** finished resolving stmt `return 0;` (context_main.carbon:10) +// CHECK:STDOUT: ** finished resolving stmt `{return 0;}` (context_main.carbon:11) +// CHECK:STDOUT: ** finished resolving decl `fn Main` (context_main.carbon:11) +// CHECK:STDOUT: --- resolved `Main` as `fn Main` in `package` (:0) +// CHECK:STDOUT: ********** resolving control flow ********** +// CHECK:STDOUT: --- flow-resolved return statement `return 0;` in `fn Main` (context_main.carbon:10) +// CHECK:STDOUT: ********** type checking ********** +// CHECK:STDOUT: ** declaring interface TestInterface +// CHECK:STDOUT: ** finished declaring interface TestInterface +// CHECK:STDOUT: checking InterfaceDeclaration +// CHECK:STDOUT: ** checking interface TestInterface +// CHECK:STDOUT: impl declarations:{{ }} +// CHECK:STDOUT: impl declarations: bool as interface EqWith(U = bool), i32 as interface EqWith(U = i32), String as interface EqWith(U = String), i32 as interface CompareWith(U = i32), String as interface CompareWith(U = String), i32 as interface LessWith(U = i32), String as interface LessWith(U = String), i32 as interface LessEqWith(U = i32), String as interface LessEqWith(U = String), i32 as interface GreaterWith(U = i32), String as interface GreaterWith(U = String), i32 as interface GreaterEqWith(U = i32), String as interface GreaterEqWith(U = String), i32 as interface Negate, i32 as interface AddWith(U = i32), i32 as interface SubWith(U = i32), i32 as interface MulWith(U = i32), i32 as interface DivWith(U = i32), i32 as interface ModWith(U = i32), i32 as interface BitComplement, i32 as interface BitAndWith(U = i32), i32 as interface BitOrWith(U = i32), i32 as interface BitXorWith(U = i32), i32 as interface LeftShiftWith(U = i32), i32 as interface RightShiftWith(U = i32), i32 as interface Inc, i32 as interface Dec, U as interface __EqualConverter [0], (T1,) as interface As(T = (U1,)) [0, 0, 0; 1, 1, 0, 0, 0], (T1, T2) as interface As(T = (U1, U2)) [0, 0, 0; 0, 0, 1; 1, 1, 0, 0, 0; 1, 1, 0, 0, 1], (T1, U1) as interface EqWith(U = (T2, U2)) [0, 0, 0; 0, 0, 1; 1, 1, 0, 0, 0; 1, 1, 0, 0, 1], (T1, T2, T3) as interface As(T = (U1, U2, U3)) [0, 0, 0; 0, 0, 1; 0, 0, 2; 1, 1, 0, 0, 0; 1, 1, 0, 0, 1; 1, 1, 0, 0, 2], T as interface ImplicitAs(T = U) [0; 1, 1, 0], T as interface As(T = U) [0; 1, 1, 0], T as interface ImplicitAs(T = U) [0; 1, 1, 0], T as interface As(T = U) [0; 1, 1, 0], T as interface AssignWith(U = U) [0; 1, 1, 0], T as interface AddAssignWith(U = U) [0; 1, 1, 0], T as interface SubAssignWith(U = U) [0; 1, 1, 0], T as interface MulAssignWith(U = U) [0; 1, 1, 0], T as interface DivAssignWith(U = U) [0; 1, 1, 0], T as interface ModAssignWith(U = U) [0; 1, 1, 0], T as interface BitAndAssignWith(U = U) [0; 1, 1, 0], T as interface BitOrAssignWith(U = U) [0; 1, 1, 0], T as interface BitXorAssignWith(U = U) [0; 1, 1, 0], T as interface LeftShiftAssignWith(U = U) [0; 1, 1, 0], T as interface RightShiftAssignWith(U = U) [0; 1, 1, 0] +// CHECK:STDOUT: ** finished checking interface TestInterface +// CHECK:STDOUT: ** declaring function Main +// CHECK:STDOUT: checking TuplePattern () +// CHECK:STDOUT: checking IntTypeLiteral i32 +// CHECK:STDOUT: (+) stack-push: i32 .0. +// CHECK:STDOUT: (+) stack-push: i32 .0. +// CHECK:STDOUT: --- step exp i32 .0. (context_main.carbon:9) ---> +// CHECK:STDOUT: (-) stack-pop: i32 .0. +// CHECK:STDOUT: (-) stack-pop: i32 .1. {{\[\[}}i32]] +// CHECK:STDOUT: ** finished declaring function Main of type fn () -> i32 +// CHECK:STDOUT: checking FunctionDeclaration +// CHECK:STDOUT: ** checking function Main +// CHECK:STDOUT: impl declarations:{{ }} +// CHECK:STDOUT: impl declarations: bool as interface EqWith(U = bool), i32 as interface EqWith(U = i32), String as interface EqWith(U = String), i32 as interface CompareWith(U = i32), String as interface CompareWith(U = String), i32 as interface LessWith(U = i32), String as interface LessWith(U = String), i32 as interface LessEqWith(U = i32), String as interface LessEqWith(U = String), i32 as interface GreaterWith(U = i32), String as interface GreaterWith(U = String), i32 as interface GreaterEqWith(U = i32), String as interface GreaterEqWith(U = String), i32 as interface Negate, i32 as interface AddWith(U = i32), i32 as interface SubWith(U = i32), i32 as interface MulWith(U = i32), i32 as interface DivWith(U = i32), i32 as interface ModWith(U = i32), i32 as interface BitComplement, i32 as interface BitAndWith(U = i32), i32 as interface BitOrWith(U = i32), i32 as interface BitXorWith(U = i32), i32 as interface LeftShiftWith(U = i32), i32 as interface RightShiftWith(U = i32), i32 as interface Inc, i32 as interface Dec, U as interface __EqualConverter [0], (T1,) as interface As(T = (U1,)) [0, 0, 0; 1, 1, 0, 0, 0], (T1, T2) as interface As(T = (U1, U2)) [0, 0, 0; 0, 0, 1; 1, 1, 0, 0, 0; 1, 1, 0, 0, 1], (T1, U1) as interface EqWith(U = (T2, U2)) [0, 0, 0; 0, 0, 1; 1, 1, 0, 0, 0; 1, 1, 0, 0, 1], (T1, T2, T3) as interface As(T = (U1, U2, U3)) [0, 0, 0; 0, 0, 1; 0, 0, 2; 1, 1, 0, 0, 0; 1, 1, 0, 0, 1; 1, 1, 0, 0, 2], T as interface ImplicitAs(T = U) [0; 1, 1, 0], T as interface As(T = U) [0; 1, 1, 0], T as interface ImplicitAs(T = U) [0; 1, 1, 0], T as interface As(T = U) [0; 1, 1, 0], T as interface AssignWith(U = U) [0; 1, 1, 0], T as interface AddAssignWith(U = U) [0; 1, 1, 0], T as interface SubAssignWith(U = U) [0; 1, 1, 0], T as interface MulAssignWith(U = U) [0; 1, 1, 0], T as interface DivAssignWith(U = U) [0; 1, 1, 0], T as interface ModAssignWith(U = U) [0; 1, 1, 0], T as interface BitAndAssignWith(U = U) [0; 1, 1, 0], T as interface BitOrAssignWith(U = U) [0; 1, 1, 0], T as interface BitXorAssignWith(U = U) [0; 1, 1, 0], T as interface LeftShiftAssignWith(U = U) [0; 1, 1, 0], T as interface RightShiftAssignWith(U = U) [0; 1, 1, 0] +// CHECK:STDOUT: checking Block { +// CHECK:STDOUT: return 0; +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: checking ReturnExpression return 0; +// CHECK:STDOUT: checking IntLiteral 0 +// CHECK:STDOUT: ** finished checking function Main +// CHECK:STDOUT: checking CallExpression Main() +// CHECK:STDOUT: checking IdentifierExpression Main +// CHECK:STDOUT: checking TupleLiteral () +// CHECK:STDOUT: checking call to function of type fn () -> i32 +// CHECK:STDOUT: with arguments of type: () +// CHECK:STDOUT: performing argument deduction for bindings:{{ }} +// CHECK:STDOUT: deduction succeeded with results: {} +// CHECK:STDOUT: ********** resolving unformed variables ********** +// CHECK:STDOUT: *** resolving-unformed in decl `interface TestInterface` (context_main.carbon:7) +// CHECK:STDOUT: *** resolving-unformed in decl `fn Main` (context_main.carbon:11) +// CHECK:STDOUT: *** resolving-unformed in stmt `{return 0;}` (context_main.carbon:11) +// CHECK:STDOUT: *** resolving-unformed in stmt `return 0;` (context_main.carbon:10) +// CHECK:STDOUT: ********** printing declarations ********** +// CHECK:STDOUT: interface TestInterface { +// CHECK:STDOUT: } +// CHECK:STDOUT: fn Main ()-> i32 { +// CHECK:STDOUT: { +// CHECK:STDOUT: return 0; +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: ********** starting execution ********** +// CHECK:STDOUT: ********** initializing globals ********** +// CHECK:STDOUT: (+) stack-push: interface TestInterface { +// CHECK:STDOUT: } +// CHECK:STDOUT: .0. +// CHECK:STDOUT: --- step decl interface TestInterface .0. (context_main.carbon:7) ---> +// CHECK:STDOUT: (-) stack-pop: interface TestInterface { +// CHECK:STDOUT: } +// CHECK:STDOUT: .0. +// CHECK:STDOUT: (+) stack-push: fn Main ()-> i32 { +// CHECK:STDOUT: { +// CHECK:STDOUT: return 0; +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: .0. +// CHECK:STDOUT: --- step decl fn Main .0. (context_main.carbon:11) ---> +// CHECK:STDOUT: (-) stack-pop: fn Main ()-> i32 { +// CHECK:STDOUT: { +// CHECK:STDOUT: return 0; +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: .0. +// CHECK:STDOUT: ********** calling main function ********** +// CHECK:STDOUT: (+) stack-push: Main() .0. +// CHECK:STDOUT: (+) stack-push: Main() .0. +// CHECK:STDOUT: --- step exp Main() .0. (:0) ---> +// CHECK:STDOUT: (+) stack-push: Main .0. +// CHECK:STDOUT: (+) stack-push: Main .0. +// CHECK:STDOUT: --- step exp Main .0. (:0) ---> +// CHECK:STDOUT: (-) stack-pop: Main .0. +// CHECK:STDOUT: (-) stack-pop: Main .1. {{\[\[}}fun
]] +// CHECK:STDOUT: --- step exp Main() .1. (:0) ---> +// CHECK:STDOUT: calling function: fun
+// CHECK:STDOUT: match pattern () +// CHECK:STDOUT: from value expression with value () +// CHECK:STDOUT: (+) stack-push: .0. {} +// CHECK:STDOUT: (+) stack-push: {return 0;} .0. +// CHECK:STDOUT: --- step stmt {return 0;} .0. (context_main.carbon:11) ---> +// CHECK:STDOUT: (+) stack-push: return 0; .0. +// CHECK:STDOUT: --- step stmt return 0; .0. (context_main.carbon:10) ---> +// CHECK:STDOUT: (+) stack-push: 0 .0. +// CHECK:STDOUT: (+) stack-push: 0 .0. +// CHECK:STDOUT: --- step exp 0 .0. (context_main.carbon:10) ---> +// CHECK:STDOUT: (-) stack-pop: 0 .0. +// CHECK:STDOUT: (-) stack-pop: 0 .1. {{\[\[}}0]] +// CHECK:STDOUT: --- step stmt return 0; .1. (context_main.carbon:10) ---> +// CHECK:STDOUT: (-) stack-pop: return 0; .1. {{\[\[}}0]] +// CHECK:STDOUT: (-) stack-pop: {return 0;} .1. {} +// CHECK:STDOUT: (-) stack-pop: .0. {} +// CHECK:STDOUT: (+) stack-push: clean up.0. {} +// CHECK:STDOUT: (+) stack-push: clean up.0. {} +// CHECK:STDOUT: (-) stack-pop: clean up.0. {} +// CHECK:STDOUT: (-) stack-pop: clean up.0. {} +// CHECK:STDOUT: --- step exp Main() .2. (:0) ---> +// CHECK:STDOUT: (-) stack-pop: Main() .2. {{\[\[}}fun
, 0]] {} +// CHECK:STDOUT: (+) stack-push: clean up.0. {} +// CHECK:STDOUT: (-) stack-pop: clean up.0. {} +// CHECK:STDOUT: (-) stack-pop: Main() .1. {{\[\[}}0]] +// CHECK:STDOUT: interpreter result: 0 +// CHECK:STDOUT: ********** printing timing ********** +// CHECK:STDOUT: Time elapsed in ExecProgram: {{\d+}}ms +// CHECK:STDOUT: Time elapsed in AnalyzeProgram: {{\d+}}ms +// CHECK:STDOUT: Time elapsed in AddPrelude: {{\d+}}ms +// CHECK:STDOUT: Time elapsed in Parse: {{\d+}}ms +// CHECK:STDOUT: result: 0 diff --git a/explorer/testdata/trace/context_prelude.carbon b/explorer/testdata/trace/context_prelude.carbon new file mode 100644 index 000000000000..c152b4207511 --- /dev/null +++ b/explorer/testdata/trace/context_prelude.carbon @@ -0,0 +1,19 @@ +// 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 + +package ExplorerTest api; + +interface TestInterface {} + +fn Main() -> i32 { + return 0; +} + +// Place checks after code so that line numbers are stable, reducing merge +// conflicts. +// ARGS: --trace_file=- --trace_phase=all --trace_file_context=prelude %s +// NOAUTOUPDATE +// SET-CHECK-SUBSET +// CHECK:STDOUT: ** declaring interface As +// CHECK:STDOUT: interface As { diff --git a/explorer/trace_testdata/full_trace.carbon b/explorer/testdata/trace/phase_all.carbon similarity index 76% rename from explorer/trace_testdata/full_trace.carbon rename to explorer/testdata/trace/phase_all.carbon index 619184430ee1..ea198f8a708c 100644 --- a/explorer/trace_testdata/full_trace.carbon +++ b/explorer/testdata/trace/phase_all.carbon @@ -17,7 +17,8 @@ fn Main() -> i32 { return x; } -// Place checks after code so that line numbers are stable, reducing merge conflicts. +// Place checks after code so that line numbers are stable, reducing merge +// conflicts. // ARGS: --trace_file=- --trace_phase=all %s // AUTOUPDATE // CHECK:STDOUT: ********** source program ********** @@ -37,48 +38,48 @@ fn Main() -> i32 { // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: ********** resolving names ********** -// CHECK:STDOUT: --- declared `TestInterface` as `interface TestInterface` in `package` (full_trace.carbon:7) -// CHECK:STDOUT: --- declared `N` as `namespace N` in `package` (full_trace.carbon:9) -// CHECK:STDOUT: --- resolved `N` as `namespace N` in `package` (full_trace.carbon:11) -// CHECK:STDOUT: --- declared `Foo` as `fn N.Foo` in `namespace N` (full_trace.carbon:13) -// CHECK:STDOUT: --- declared `Main` as `fn Main` in `package` (full_trace.carbon:18) -// CHECK:STDOUT: ** resolving decl `interface TestInterface` (full_trace.carbon:7) +// CHECK:STDOUT: --- declared `TestInterface` as `interface TestInterface` in `package` (phase_all.carbon:7) +// CHECK:STDOUT: --- declared `N` as `namespace N` in `package` (phase_all.carbon:9) +// CHECK:STDOUT: --- resolved `N` as `namespace N` in `package` (phase_all.carbon:11) +// CHECK:STDOUT: --- declared `Foo` as `fn N.Foo` in `namespace N` (phase_all.carbon:13) +// CHECK:STDOUT: --- declared `Main` as `fn Main` in `package` (phase_all.carbon:18) +// CHECK:STDOUT: ** resolving decl `interface TestInterface` (phase_all.carbon:7) // CHECK:STDOUT: --- marked `TestInterface` declared but not usable in `package` // CHECK:STDOUT: --- marked `TestInterface` usable in `package` -// CHECK:STDOUT: --- declared `Self` as `Self` in `interface TestInterface` (full_trace.carbon:7) -// CHECK:STDOUT: ** finished resolving decl `interface TestInterface` (full_trace.carbon:7) -// CHECK:STDOUT: ** resolving decl `namespace N` (full_trace.carbon:9) +// CHECK:STDOUT: --- declared `Self` as `Self` in `interface TestInterface` (phase_all.carbon:7) +// CHECK:STDOUT: ** finished resolving decl `interface TestInterface` (phase_all.carbon:7) +// CHECK:STDOUT: ** resolving decl `namespace N` (phase_all.carbon:9) // CHECK:STDOUT: --- marked `N` usable in `package` -// CHECK:STDOUT: ** finished resolving decl `namespace N` (full_trace.carbon:9) -// CHECK:STDOUT: ** resolving decl `fn N.Foo` (full_trace.carbon:13) -// CHECK:STDOUT: --- resolved `N` as `namespace N` in `package` (full_trace.carbon:11) +// CHECK:STDOUT: ** finished resolving decl `namespace N` (phase_all.carbon:9) +// CHECK:STDOUT: ** resolving decl `fn N.Foo` (phase_all.carbon:13) +// CHECK:STDOUT: --- resolved `N` as `namespace N` in `package` (phase_all.carbon:11) // CHECK:STDOUT: --- marked `Foo` declared but not usable in `namespace N` -// CHECK:STDOUT: --- declared `n` as `n` in `fn N.Foo` (full_trace.carbon:11) +// CHECK:STDOUT: --- declared `n` as `n` in `fn N.Foo` (phase_all.carbon:11) // CHECK:STDOUT: --- marked `Foo` usable in `namespace N` -// CHECK:STDOUT: ** resolving stmt `{return (n + 1);}` (full_trace.carbon:13) -// CHECK:STDOUT: ** resolving stmt `return (n + 1);` (full_trace.carbon:12) -// CHECK:STDOUT: --- resolved `n` as `n` in `fn N.Foo` (full_trace.carbon:12) -// CHECK:STDOUT: ** finished resolving stmt `return (n + 1);` (full_trace.carbon:12) -// CHECK:STDOUT: ** finished resolving stmt `{return (n + 1);}` (full_trace.carbon:13) -// CHECK:STDOUT: ** finished resolving decl `fn N.Foo` (full_trace.carbon:13) -// CHECK:STDOUT: ** resolving decl `fn Main` (full_trace.carbon:18) +// CHECK:STDOUT: ** resolving stmt `{return (n + 1);}` (phase_all.carbon:13) +// CHECK:STDOUT: ** resolving stmt `return (n + 1);` (phase_all.carbon:12) +// CHECK:STDOUT: --- resolved `n` as `n` in `fn N.Foo` (phase_all.carbon:12) +// CHECK:STDOUT: ** finished resolving stmt `return (n + 1);` (phase_all.carbon:12) +// CHECK:STDOUT: ** finished resolving stmt `{return (n + 1);}` (phase_all.carbon:13) +// CHECK:STDOUT: ** finished resolving decl `fn N.Foo` (phase_all.carbon:13) +// CHECK:STDOUT: ** resolving decl `fn Main` (phase_all.carbon:18) // CHECK:STDOUT: --- marked `Main` declared but not usable in `package` // CHECK:STDOUT: --- marked `Main` usable in `package` -// CHECK:STDOUT: ** resolving stmt `{var x: i32 = N.Foo(0);return x;}` (full_trace.carbon:18) -// CHECK:STDOUT: ** resolving stmt `var x: i32 = N.Foo(0);` (full_trace.carbon:16) -// CHECK:STDOUT: --- resolved `N` as `namespace N` in `package` (full_trace.carbon:16) -// CHECK:STDOUT: --- resolved `Foo` as `fn N.Foo` in `namespace N` (full_trace.carbon:16) -// CHECK:STDOUT: --- declared `x` as `x` in `{var x: i32 = N.Foo(0);return x;}` (full_trace.carbon:16) -// CHECK:STDOUT: ** finished resolving stmt `var x: i32 = N.Foo(0);` (full_trace.carbon:16) -// CHECK:STDOUT: ** resolving stmt `return x;` (full_trace.carbon:17) -// CHECK:STDOUT: --- resolved `x` as `x` in `{var x: i32 = N.Foo(0);return x;}` (full_trace.carbon:17) -// CHECK:STDOUT: ** finished resolving stmt `return x;` (full_trace.carbon:17) -// CHECK:STDOUT: ** finished resolving stmt `{var x: i32 = N.Foo(0);return x;}` (full_trace.carbon:18) -// CHECK:STDOUT: ** finished resolving decl `fn Main` (full_trace.carbon:18) +// CHECK:STDOUT: ** resolving stmt `{var x: i32 = N.Foo(0);return x;}` (phase_all.carbon:18) +// CHECK:STDOUT: ** resolving stmt `var x: i32 = N.Foo(0);` (phase_all.carbon:16) +// CHECK:STDOUT: --- resolved `N` as `namespace N` in `package` (phase_all.carbon:16) +// CHECK:STDOUT: --- resolved `Foo` as `fn N.Foo` in `namespace N` (phase_all.carbon:16) +// CHECK:STDOUT: --- declared `x` as `x` in `{var x: i32 = N.Foo(0);return x;}` (phase_all.carbon:16) +// CHECK:STDOUT: ** finished resolving stmt `var x: i32 = N.Foo(0);` (phase_all.carbon:16) +// CHECK:STDOUT: ** resolving stmt `return x;` (phase_all.carbon:17) +// CHECK:STDOUT: --- resolved `x` as `x` in `{var x: i32 = N.Foo(0);return x;}` (phase_all.carbon:17) +// CHECK:STDOUT: ** finished resolving stmt `return x;` (phase_all.carbon:17) +// CHECK:STDOUT: ** finished resolving stmt `{var x: i32 = N.Foo(0);return x;}` (phase_all.carbon:18) +// CHECK:STDOUT: ** finished resolving decl `fn Main` (phase_all.carbon:18) // CHECK:STDOUT: --- resolved `Main` as `fn Main` in `package` (:0) // CHECK:STDOUT: ********** resolving control flow ********** -// CHECK:STDOUT: --- flow-resolved return statement `return (n + 1);` in `fn N.Foo` (full_trace.carbon:12) -// CHECK:STDOUT: --- flow-resolved return statement `return x;` in `fn Main` (full_trace.carbon:17) +// CHECK:STDOUT: --- flow-resolved return statement `return (n + 1);` in `fn N.Foo` (phase_all.carbon:12) +// CHECK:STDOUT: --- flow-resolved return statement `return x;` in `fn Main` (phase_all.carbon:17) // CHECK:STDOUT: ********** type checking ********** // CHECK:STDOUT: ** declaring interface TestInterface // CHECK:STDOUT: ** finished declaring interface TestInterface @@ -95,16 +96,16 @@ fn Main() -> i32 { // CHECK:STDOUT: checking IntTypeLiteral i32 // CHECK:STDOUT: (+) stack-push: i32 .0. // CHECK:STDOUT: (+) stack-push: i32 .0. -// CHECK:STDOUT: --- step exp i32 .0. (full_trace.carbon:11) ---> +// CHECK:STDOUT: --- step exp i32 .0. (phase_all.carbon:11) ---> // CHECK:STDOUT: (-) stack-pop: i32 .0. -// CHECK:STDOUT: (-) stack-pop: i32 .1. {{[[][[]}}i32]] +// CHECK:STDOUT: (-) stack-pop: i32 .1. {{\[\[}}i32]] // CHECK:STDOUT: finished checking tuple pattern field n: i32 // CHECK:STDOUT: checking IntTypeLiteral i32 // CHECK:STDOUT: (+) stack-push: i32 .0. // CHECK:STDOUT: (+) stack-push: i32 .0. -// CHECK:STDOUT: --- step exp i32 .0. (full_trace.carbon:11) ---> +// CHECK:STDOUT: --- step exp i32 .0. (phase_all.carbon:11) ---> // CHECK:STDOUT: (-) stack-pop: i32 .0. -// CHECK:STDOUT: (-) stack-pop: i32 .1. {{[[][[]}}i32]] +// CHECK:STDOUT: (-) stack-pop: i32 .1. {{\[\[}}i32]] // CHECK:STDOUT: ** finished declaring function Foo of type fn (i32,) -> i32 // CHECK:STDOUT: checking FunctionDeclaration // CHECK:STDOUT: ** checking function Foo @@ -124,9 +125,9 @@ fn Main() -> i32 { // CHECK:STDOUT: checking IntTypeLiteral i32 // CHECK:STDOUT: (+) stack-push: i32 .0. // CHECK:STDOUT: (+) stack-push: i32 .0. -// CHECK:STDOUT: --- step exp i32 .0. (full_trace.carbon:15) ---> +// CHECK:STDOUT: --- step exp i32 .0. (phase_all.carbon:15) ---> // CHECK:STDOUT: (-) stack-pop: i32 .0. -// CHECK:STDOUT: (-) stack-pop: i32 .1. {{[[][[]}}i32]] +// CHECK:STDOUT: (-) stack-pop: i32 .1. {{\[\[}}i32]] // CHECK:STDOUT: ** finished declaring function Main of type fn () -> i32 // CHECK:STDOUT: checking FunctionDeclaration // CHECK:STDOUT: ** checking function Main @@ -153,9 +154,9 @@ fn Main() -> i32 { // CHECK:STDOUT: checking IntTypeLiteral i32 // CHECK:STDOUT: (+) stack-push: i32 .0. // CHECK:STDOUT: (+) stack-push: i32 .0. -// CHECK:STDOUT: --- step exp i32 .0. (full_trace.carbon:16) ---> +// CHECK:STDOUT: --- step exp i32 .0. (phase_all.carbon:16) ---> // CHECK:STDOUT: (-) stack-pop: i32 .0. -// CHECK:STDOUT: (-) stack-pop: i32 .1. {{[[][[]}}i32]] +// CHECK:STDOUT: (-) stack-pop: i32 .1. {{\[\[}}i32]] // CHECK:STDOUT: checking ReturnExpression return x; // CHECK:STDOUT: checking IdentifierExpression x // CHECK:STDOUT: ** finished checking function Main @@ -167,18 +168,18 @@ fn Main() -> i32 { // CHECK:STDOUT: performing argument deduction for bindings:{{ }} // CHECK:STDOUT: deduction succeeded with results: {} // CHECK:STDOUT: ********** resolving unformed variables ********** -// CHECK:STDOUT: *** resolving-unformed in decl `interface TestInterface` (full_trace.carbon:7) -// CHECK:STDOUT: *** resolving-unformed in decl `namespace N` (full_trace.carbon:9) -// CHECK:STDOUT: *** resolving-unformed in decl `fn N.Foo` (full_trace.carbon:13) -// CHECK:STDOUT: *** resolving-unformed in stmt `{return (n + 1);}` (full_trace.carbon:13) -// CHECK:STDOUT: *** resolving-unformed in stmt `return (n + 1);` (full_trace.carbon:12) -// CHECK:STDOUT: --- check `n` (full_trace.carbon:12) -// CHECK:STDOUT: *** resolving-unformed in decl `fn Main` (full_trace.carbon:18) -// CHECK:STDOUT: *** resolving-unformed in stmt `{var x: i32 = N.Foo(0);return x;}` (full_trace.carbon:18) -// CHECK:STDOUT: *** resolving-unformed in stmt `var x: i32 = N.Foo(0);` (full_trace.carbon:16) -// CHECK:STDOUT: --- add init `x` (full_trace.carbon:16) -// CHECK:STDOUT: *** resolving-unformed in stmt `return x;` (full_trace.carbon:17) -// CHECK:STDOUT: --- check `x` (full_trace.carbon:17) +// CHECK:STDOUT: *** resolving-unformed in decl `interface TestInterface` (phase_all.carbon:7) +// CHECK:STDOUT: *** resolving-unformed in decl `namespace N` (phase_all.carbon:9) +// CHECK:STDOUT: *** resolving-unformed in decl `fn N.Foo` (phase_all.carbon:13) +// CHECK:STDOUT: *** resolving-unformed in stmt `{return (n + 1);}` (phase_all.carbon:13) +// CHECK:STDOUT: *** resolving-unformed in stmt `return (n + 1);` (phase_all.carbon:12) +// CHECK:STDOUT: --- check `n` (phase_all.carbon:12) +// CHECK:STDOUT: *** resolving-unformed in decl `fn Main` (phase_all.carbon:18) +// CHECK:STDOUT: *** resolving-unformed in stmt `{var x: i32 = N.Foo(0);return x;}` (phase_all.carbon:18) +// CHECK:STDOUT: *** resolving-unformed in stmt `var x: i32 = N.Foo(0);` (phase_all.carbon:16) +// CHECK:STDOUT: --- add init `x` (phase_all.carbon:16) +// CHECK:STDOUT: *** resolving-unformed in stmt `return x;` (phase_all.carbon:17) +// CHECK:STDOUT: --- check `x` (phase_all.carbon:17) // CHECK:STDOUT: ********** printing declarations ********** // CHECK:STDOUT: interface TestInterface { // CHECK:STDOUT: } @@ -200,12 +201,12 @@ fn Main() -> i32 { // CHECK:STDOUT: (+) stack-push: interface TestInterface { // CHECK:STDOUT: } // CHECK:STDOUT: .0. -// CHECK:STDOUT: --- step decl interface TestInterface .0. (full_trace.carbon:7) ---> +// CHECK:STDOUT: --- step decl interface TestInterface .0. (phase_all.carbon:7) ---> // CHECK:STDOUT: (-) stack-pop: interface TestInterface { // CHECK:STDOUT: } // CHECK:STDOUT: .0. // CHECK:STDOUT: (+) stack-push: namespace N; .0. -// CHECK:STDOUT: --- step decl namespace N .0. (full_trace.carbon:9) ---> +// CHECK:STDOUT: --- step decl namespace N .0. (phase_all.carbon:9) ---> // CHECK:STDOUT: (-) stack-pop: namespace N; .0. // CHECK:STDOUT: (+) stack-push: fn Foo (n: i32)-> i32 { // CHECK:STDOUT: { @@ -214,7 +215,7 @@ fn Main() -> i32 { // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: .0. -// CHECK:STDOUT: --- step decl fn N.Foo .0. (full_trace.carbon:13) ---> +// CHECK:STDOUT: --- step decl fn N.Foo .0. (phase_all.carbon:13) ---> // CHECK:STDOUT: (-) stack-pop: fn Foo (n: i32)-> i32 { // CHECK:STDOUT: { // CHECK:STDOUT: return (n + 1); @@ -230,7 +231,7 @@ fn Main() -> i32 { // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: .0. -// CHECK:STDOUT: --- step decl fn Main .0. (full_trace.carbon:18) ---> +// CHECK:STDOUT: --- step decl fn Main .0. (phase_all.carbon:18) ---> // CHECK:STDOUT: (-) stack-pop: fn Main ()-> i32 { // CHECK:STDOUT: { // CHECK:STDOUT: var x: i32 = N.Foo(0); @@ -247,32 +248,32 @@ fn Main() -> i32 { // CHECK:STDOUT: (+) stack-push: Main .0. // CHECK:STDOUT: --- step exp Main .0. (:0) ---> // CHECK:STDOUT: (-) stack-pop: Main .0. -// CHECK:STDOUT: (-) stack-pop: Main .1. {{[[][[]}}fun
]] +// CHECK:STDOUT: (-) stack-pop: Main .1. {{\[\[}}fun
]] // CHECK:STDOUT: --- step exp Main() .1. (:0) ---> // CHECK:STDOUT: calling function: fun
// CHECK:STDOUT: match pattern () // CHECK:STDOUT: from value expression with value () // CHECK:STDOUT: (+) stack-push: .0. {} // CHECK:STDOUT: (+) stack-push: {var x: i32 = N.Foo(0);return x;} .0. -// CHECK:STDOUT: --- step stmt {var x: i32 = N.Foo(0);return x;} .0. (full_trace.carbon:18) ---> +// CHECK:STDOUT: --- step stmt {var x: i32 = N.Foo(0);return x;} .0. (phase_all.carbon:18) ---> // CHECK:STDOUT: (+) stack-push: var x: i32 = N.Foo(0); .0. -// CHECK:STDOUT: --- step stmt var x: i32 = N.Foo(0); .0. (full_trace.carbon:16) ---> +// CHECK:STDOUT: --- step stmt var x: i32 = N.Foo(0); .0. (phase_all.carbon:16) ---> // CHECK:STDOUT: (+) memory-alloc: #1 `Uninit` uninitialized // CHECK:STDOUT: (+) stack-push: N.Foo(0) .0. -// CHECK:STDOUT: --- step exp N.Foo(0) .0. (full_trace.carbon:16) ---> +// CHECK:STDOUT: --- step exp N.Foo(0) .0. (phase_all.carbon:16) ---> // CHECK:STDOUT: (+) stack-push: N.Foo .0. // CHECK:STDOUT: (+) stack-push: N.Foo .0. -// CHECK:STDOUT: --- step exp N.Foo .0. (full_trace.carbon:16) ---> +// CHECK:STDOUT: --- step exp N.Foo .0. (phase_all.carbon:16) ---> // CHECK:STDOUT: (-) stack-pop: N.Foo .0. // CHECK:STDOUT: (+) stack-push: Foo .0. -// CHECK:STDOUT: --- step exp Foo .0. (full_trace.carbon:16) ---> +// CHECK:STDOUT: --- step exp Foo .0. (phase_all.carbon:16) ---> // CHECK:STDOUT: (-) stack-pop: Foo .0. -// CHECK:STDOUT: (-) stack-pop: N.Foo .1. {{[[][[]}}fun]] -// CHECK:STDOUT: --- step exp N.Foo(0) .1. (full_trace.carbon:16) ---> +// CHECK:STDOUT: (-) stack-pop: N.Foo .1. {{\[\[}}fun]] +// CHECK:STDOUT: --- step exp N.Foo(0) .1. (phase_all.carbon:16) ---> // CHECK:STDOUT: (+) stack-push: 0 .0. -// CHECK:STDOUT: --- step exp 0 .0. (full_trace.carbon:16) ---> +// CHECK:STDOUT: --- step exp 0 .0. (phase_all.carbon:16) ---> // CHECK:STDOUT: (-) stack-pop: 0 .0. -// CHECK:STDOUT: --- step exp N.Foo(0) .2. (full_trace.carbon:16) ---> +// CHECK:STDOUT: --- step exp N.Foo(0) .2. (phase_all.carbon:16) ---> // CHECK:STDOUT: calling function: fun // CHECK:STDOUT: match pattern (Placeholder,) // CHECK:STDOUT: from value expression with value (0,) @@ -280,55 +281,55 @@ fn Main() -> i32 { // CHECK:STDOUT: from value expression with value 0 // CHECK:STDOUT: (+) stack-push: .0. {n: i32: 0} // CHECK:STDOUT: (+) stack-push: {return (n + 1);} .0. -// CHECK:STDOUT: --- step stmt {return (n + 1);} .0. (full_trace.carbon:13) ---> +// CHECK:STDOUT: --- step stmt {return (n + 1);} .0. (phase_all.carbon:13) ---> // CHECK:STDOUT: (+) stack-push: return (n + 1); .0. -// CHECK:STDOUT: --- step stmt return (n + 1); .0. (full_trace.carbon:12) ---> +// CHECK:STDOUT: --- step stmt return (n + 1); .0. (phase_all.carbon:12) ---> // CHECK:STDOUT: (+) stack-push: (n + 1) .0. // CHECK:STDOUT: (+) stack-push: (n + 1) .0. -// CHECK:STDOUT: --- step exp (n + 1) .0. (full_trace.carbon:12) ---> +// CHECK:STDOUT: --- step exp (n + 1) .0. (phase_all.carbon:12) ---> // CHECK:STDOUT: (+) stack-push: n .0. // CHECK:STDOUT: (+) stack-push: n .0. -// CHECK:STDOUT: --- step exp n .0. (full_trace.carbon:12) ---> +// CHECK:STDOUT: --- step exp n .0. (phase_all.carbon:12) ---> // CHECK:STDOUT: (-) stack-pop: n .0. -// CHECK:STDOUT: (-) stack-pop: n .1. {{[[][[]}}0]] -// CHECK:STDOUT: --- step exp (n + 1) .1. (full_trace.carbon:12) ---> +// CHECK:STDOUT: (-) stack-pop: n .1. {{\[\[}}0]] +// CHECK:STDOUT: --- step exp (n + 1) .1. (phase_all.carbon:12) ---> // CHECK:STDOUT: (+) stack-push: 1 .0. // CHECK:STDOUT: (+) stack-push: 1 .0. -// CHECK:STDOUT: --- step exp 1 .0. (full_trace.carbon:12) ---> +// CHECK:STDOUT: --- step exp 1 .0. (phase_all.carbon:12) ---> // CHECK:STDOUT: (-) stack-pop: 1 .0. -// CHECK:STDOUT: (-) stack-pop: 1 .1. {{[[][[]}}1]] -// CHECK:STDOUT: --- step exp (n + 1) .2. (full_trace.carbon:12) ---> -// CHECK:STDOUT: (-) stack-pop: (n + 1) .2. {{[[][[]}}0, 1]] -// CHECK:STDOUT: (-) stack-pop: (n + 1) .1. {{[[][[]}}1]] -// CHECK:STDOUT: --- step stmt return (n + 1); .1. (full_trace.carbon:12) ---> +// CHECK:STDOUT: (-) stack-pop: 1 .1. {{\[\[}}1]] +// CHECK:STDOUT: --- step exp (n + 1) .2. (phase_all.carbon:12) ---> +// CHECK:STDOUT: (-) stack-pop: (n + 1) .2. {{\[\[}}0, 1]] +// CHECK:STDOUT: (-) stack-pop: (n + 1) .1. {{\[\[}}1]] +// CHECK:STDOUT: --- step stmt return (n + 1); .1. (phase_all.carbon:12) ---> // CHECK:STDOUT: +++ memory-write: #1 `1` -// CHECK:STDOUT: (-) stack-pop: return (n + 1); .1. {{[[][[]}}1]] +// CHECK:STDOUT: (-) stack-pop: return (n + 1); .1. {{\[\[}}1]] // CHECK:STDOUT: (-) stack-pop: {return (n + 1);} .1. {} // CHECK:STDOUT: (-) stack-pop: .0. {n: i32: 0} // CHECK:STDOUT: (+) stack-push: clean up.0. {n: i32: 0} // CHECK:STDOUT: (+) stack-push: clean up.0. {} // CHECK:STDOUT: (-) stack-pop: clean up.0. {} // CHECK:STDOUT: (-) stack-pop: clean up.0. {n: i32: 0} -// CHECK:STDOUT: --- step exp N.Foo(0) .3. (full_trace.carbon:16) ---> -// CHECK:STDOUT: (-) stack-pop: N.Foo(0) .3. {{[[][[]}}fun, 0, 1]] {} +// CHECK:STDOUT: --- step exp N.Foo(0) .3. (phase_all.carbon:16) ---> +// CHECK:STDOUT: (-) stack-pop: N.Foo(0) .3. {{\[\[}}fun, 0, 1]] {} // CHECK:STDOUT: (+) stack-push: clean up.0. {} // CHECK:STDOUT: (-) stack-pop: clean up.0. {} -// CHECK:STDOUT: --- step stmt var x: i32 = N.Foo(0); .1. (full_trace.carbon:16) ---> +// CHECK:STDOUT: --- step stmt var x: i32 = N.Foo(0); .1. (phase_all.carbon:16) ---> // CHECK:STDOUT: +++ memory-read: #1 `1` // CHECK:STDOUT: match pattern Placeholder // CHECK:STDOUT: from initializing expression with value 1 -// CHECK:STDOUT: (-) stack-pop: var x: i32 = N.Foo(0); .1. {{[[][[]}}1]] -// CHECK:STDOUT: --- step stmt {var x: i32 = N.Foo(0);return x;} .1. (full_trace.carbon:18) ---> +// CHECK:STDOUT: (-) stack-pop: var x: i32 = N.Foo(0); .1. {{\[\[}}1]] +// CHECK:STDOUT: --- step stmt {var x: i32 = N.Foo(0);return x;} .1. (phase_all.carbon:18) ---> // CHECK:STDOUT: (+) stack-push: return x; .0. -// CHECK:STDOUT: --- step stmt return x; .0. (full_trace.carbon:17) ---> +// CHECK:STDOUT: --- step stmt return x; .0. (phase_all.carbon:17) ---> // CHECK:STDOUT: (+) stack-push: x .0. // CHECK:STDOUT: (+) stack-push: x .0. -// CHECK:STDOUT: --- step exp x .0. (full_trace.carbon:17) ---> +// CHECK:STDOUT: --- step exp x .0. (phase_all.carbon:17) ---> // CHECK:STDOUT: +++ memory-read: #1 `1` // CHECK:STDOUT: (-) stack-pop: x .0. -// CHECK:STDOUT: (-) stack-pop: x .1. {{[[][[]}}ref_expr]] -// CHECK:STDOUT: --- step stmt return x; .1. (full_trace.carbon:17) ---> -// CHECK:STDOUT: (-) stack-pop: return x; .1. {{[[][[]}}1]] +// CHECK:STDOUT: (-) stack-pop: x .1. {{\[\[}}ref_expr]] +// CHECK:STDOUT: --- step stmt return x; .1. (phase_all.carbon:17) ---> +// CHECK:STDOUT: (-) stack-pop: return x; .1. {{\[\[}}1]] // CHECK:STDOUT: (-) stack-pop: {var x: i32 = N.Foo(0);return x;} .2. {x: i32: lval} // CHECK:STDOUT: (-) stack-pop: .0. {} // CHECK:STDOUT: (+) stack-push: clean up.0. {} @@ -340,14 +341,14 @@ fn Main() -> i32 { // CHECK:STDOUT: (-) stack-pop: clean up.2. {x: i32: lval} // CHECK:STDOUT: (-) stack-pop: clean up.0. {} // CHECK:STDOUT: --- step exp Main() .2. (:0) ---> -// CHECK:STDOUT: (-) stack-pop: Main() .2. {{[[][[]}}fun
, 1]] {} +// CHECK:STDOUT: (-) stack-pop: Main() .2. {{\[\[}}fun
, 1]] {} // CHECK:STDOUT: (+) stack-push: clean up.0. {} // CHECK:STDOUT: (-) stack-pop: clean up.0. {} -// CHECK:STDOUT: (-) stack-pop: Main() .1. {{[[][[]}}1]] +// CHECK:STDOUT: (-) stack-pop: Main() .1. {{\[\[}}1]] // CHECK:STDOUT: interpreter result: 1 // CHECK:STDOUT: ********** printing timing ********** -// CHECK:STDOUT: Time elapsed in ExecProgram: {{[0-9]+}}ms -// CHECK:STDOUT: Time elapsed in AnalyzeProgram: {{[0-9]+}}ms -// CHECK:STDOUT: Time elapsed in AddPrelude: {{[0-9]+}}ms -// CHECK:STDOUT: Time elapsed in Parse: {{[0-9]+}}ms +// CHECK:STDOUT: Time elapsed in ExecProgram: {{\d+}}ms +// CHECK:STDOUT: Time elapsed in AnalyzeProgram: {{\d+}}ms +// CHECK:STDOUT: Time elapsed in AddPrelude: {{\d+}}ms +// CHECK:STDOUT: Time elapsed in Parse: {{\d+}}ms // CHECK:STDOUT: result: 1 diff --git a/explorer/testdata/trace/phase_control_flow_resolution.carbon b/explorer/testdata/trace/phase_control_flow_resolution.carbon new file mode 100644 index 000000000000..e954c5e99d60 --- /dev/null +++ b/explorer/testdata/trace/phase_control_flow_resolution.carbon @@ -0,0 +1,19 @@ +// 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 + +package ExplorerTest api; + +interface TestInterface {} + +fn Main() -> i32 { + return 0; +} + +// Place checks after code so that line numbers are stable, reducing merge +// conflicts. +// ARGS: --trace_file=- --trace_phase=control_flow_resolution %s +// AUTOUPDATE +// CHECK:STDOUT: ********** resolving control flow ********** +// CHECK:STDOUT: --- flow-resolved return statement `return 0;` in `fn Main` (phase_control_flow_resolution.carbon:10) +// CHECK:STDOUT: result: 0 diff --git a/explorer/testdata/trace/phase_declarations.carbon b/explorer/testdata/trace/phase_declarations.carbon new file mode 100644 index 000000000000..4bde91f5ae57 --- /dev/null +++ b/explorer/testdata/trace/phase_declarations.carbon @@ -0,0 +1,26 @@ +// 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 + +package ExplorerTest api; + +interface TestInterface {} + +fn Main() -> i32 { + return 0; +} + +// Place checks after code so that line numbers are stable, reducing merge +// conflicts. +// ARGS: --trace_file=- --trace_phase=declarations %s +// AUTOUPDATE +// CHECK:STDOUT: ********** printing declarations ********** +// CHECK:STDOUT: interface TestInterface { +// CHECK:STDOUT: } +// CHECK:STDOUT: fn Main ()-> i32 { +// CHECK:STDOUT: { +// CHECK:STDOUT: return 0; +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: result: 0 diff --git a/explorer/testdata/trace/phase_execution.carbon b/explorer/testdata/trace/phase_execution.carbon new file mode 100644 index 000000000000..d941627f5ea9 --- /dev/null +++ b/explorer/testdata/trace/phase_execution.carbon @@ -0,0 +1,78 @@ +// 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 + +package ExplorerTest api; + +interface TestInterface {} + +fn Main() -> i32 { + return 0; +} + +// Place checks after code so that line numbers are stable, reducing merge +// conflicts. +// ARGS: --trace_file=- --trace_phase=execution %s +// AUTOUPDATE +// CHECK:STDOUT: ********** starting execution ********** +// CHECK:STDOUT: ********** initializing globals ********** +// CHECK:STDOUT: (+) stack-push: interface TestInterface { +// CHECK:STDOUT: } +// CHECK:STDOUT: .0. +// CHECK:STDOUT: --- step decl interface TestInterface .0. (phase_execution.carbon:7) ---> +// CHECK:STDOUT: (-) stack-pop: interface TestInterface { +// CHECK:STDOUT: } +// CHECK:STDOUT: .0. +// CHECK:STDOUT: (+) stack-push: fn Main ()-> i32 { +// CHECK:STDOUT: { +// CHECK:STDOUT: return 0; +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: .0. +// CHECK:STDOUT: --- step decl fn Main .0. (phase_execution.carbon:11) ---> +// CHECK:STDOUT: (-) stack-pop: fn Main ()-> i32 { +// CHECK:STDOUT: { +// CHECK:STDOUT: return 0; +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: .0. +// CHECK:STDOUT: ********** calling main function ********** +// CHECK:STDOUT: (+) stack-push: Main() .0. +// CHECK:STDOUT: (+) stack-push: Main() .0. +// CHECK:STDOUT: --- step exp Main() .0. (:0) ---> +// CHECK:STDOUT: (+) stack-push: Main .0. +// CHECK:STDOUT: (+) stack-push: Main .0. +// CHECK:STDOUT: --- step exp Main .0. (:0) ---> +// CHECK:STDOUT: (-) stack-pop: Main .0. +// CHECK:STDOUT: (-) stack-pop: Main .1. {{\[\[}}fun
]] +// CHECK:STDOUT: --- step exp Main() .1. (:0) ---> +// CHECK:STDOUT: calling function: fun
+// CHECK:STDOUT: match pattern () +// CHECK:STDOUT: from value expression with value () +// CHECK:STDOUT: (+) stack-push: .0. {} +// CHECK:STDOUT: (+) stack-push: {return 0;} .0. +// CHECK:STDOUT: --- step stmt {return 0;} .0. (phase_execution.carbon:11) ---> +// CHECK:STDOUT: (+) stack-push: return 0; .0. +// CHECK:STDOUT: --- step stmt return 0; .0. (phase_execution.carbon:10) ---> +// CHECK:STDOUT: (+) stack-push: 0 .0. +// CHECK:STDOUT: (+) stack-push: 0 .0. +// CHECK:STDOUT: --- step exp 0 .0. (phase_execution.carbon:10) ---> +// CHECK:STDOUT: (-) stack-pop: 0 .0. +// CHECK:STDOUT: (-) stack-pop: 0 .1. {{\[\[}}0]] +// CHECK:STDOUT: --- step stmt return 0; .1. (phase_execution.carbon:10) ---> +// CHECK:STDOUT: (-) stack-pop: return 0; .1. {{\[\[}}0]] +// CHECK:STDOUT: (-) stack-pop: {return 0;} .1. {} +// CHECK:STDOUT: (-) stack-pop: .0. {} +// CHECK:STDOUT: (+) stack-push: clean up.0. {} +// CHECK:STDOUT: (+) stack-push: clean up.0. {} +// CHECK:STDOUT: (-) stack-pop: clean up.0. {} +// CHECK:STDOUT: (-) stack-pop: clean up.0. {} +// CHECK:STDOUT: --- step exp Main() .2. (:0) ---> +// CHECK:STDOUT: (-) stack-pop: Main() .2. {{\[\[}}fun
, 0]] {} +// CHECK:STDOUT: (+) stack-push: clean up.0. {} +// CHECK:STDOUT: (-) stack-pop: clean up.0. {} +// CHECK:STDOUT: (-) stack-pop: Main() .1. {{\[\[}}0]] +// CHECK:STDOUT: interpreter result: 0 +// CHECK:STDOUT: result: 0 diff --git a/explorer/testdata/trace/phase_name_resolution.carbon b/explorer/testdata/trace/phase_name_resolution.carbon new file mode 100644 index 000000000000..237d2fcce1ff --- /dev/null +++ b/explorer/testdata/trace/phase_name_resolution.carbon @@ -0,0 +1,34 @@ +// 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 + +package ExplorerTest api; + +interface TestInterface {} + +fn Main() -> i32 { + return 0; +} + +// Place checks after code so that line numbers are stable, reducing merge +// conflicts. +// ARGS: --trace_file=- --trace_phase=name_resolution %s +// AUTOUPDATE +// CHECK:STDOUT: ********** resolving names ********** +// CHECK:STDOUT: --- declared `TestInterface` as `interface TestInterface` in `package` (phase_name_resolution.carbon:7) +// CHECK:STDOUT: --- declared `Main` as `fn Main` in `package` (phase_name_resolution.carbon:11) +// CHECK:STDOUT: ** resolving decl `interface TestInterface` (phase_name_resolution.carbon:7) +// CHECK:STDOUT: --- marked `TestInterface` declared but not usable in `package` +// CHECK:STDOUT: --- marked `TestInterface` usable in `package` +// CHECK:STDOUT: --- declared `Self` as `Self` in `interface TestInterface` (phase_name_resolution.carbon:7) +// CHECK:STDOUT: ** finished resolving decl `interface TestInterface` (phase_name_resolution.carbon:7) +// CHECK:STDOUT: ** resolving decl `fn Main` (phase_name_resolution.carbon:11) +// CHECK:STDOUT: --- marked `Main` declared but not usable in `package` +// CHECK:STDOUT: --- marked `Main` usable in `package` +// CHECK:STDOUT: ** resolving stmt `{return 0;}` (phase_name_resolution.carbon:11) +// CHECK:STDOUT: ** resolving stmt `return 0;` (phase_name_resolution.carbon:10) +// CHECK:STDOUT: ** finished resolving stmt `return 0;` (phase_name_resolution.carbon:10) +// CHECK:STDOUT: ** finished resolving stmt `{return 0;}` (phase_name_resolution.carbon:11) +// CHECK:STDOUT: ** finished resolving decl `fn Main` (phase_name_resolution.carbon:11) +// CHECK:STDOUT: --- resolved `Main` as `fn Main` in `package` (:0) +// CHECK:STDOUT: result: 0 diff --git a/explorer/testdata/trace/phase_source_program.carbon b/explorer/testdata/trace/phase_source_program.carbon new file mode 100644 index 000000000000..d56b30b0e0ac --- /dev/null +++ b/explorer/testdata/trace/phase_source_program.carbon @@ -0,0 +1,26 @@ +// 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 + +package ExplorerTest api; + +interface TestInterface {} + +fn Main() -> i32 { + return 0; +} + +// Place checks after code so that line numbers are stable, reducing merge +// conflicts. +// ARGS: --trace_file=- --trace_phase=source_program %s +// AUTOUPDATE +// CHECK:STDOUT: ********** source program ********** +// CHECK:STDOUT: interface TestInterface { +// CHECK:STDOUT: } +// CHECK:STDOUT: fn Main ()-> i32 { +// CHECK:STDOUT: { +// CHECK:STDOUT: return 0; +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: result: 0 diff --git a/explorer/testdata/trace/phase_timing.carbon b/explorer/testdata/trace/phase_timing.carbon new file mode 100644 index 000000000000..6d8a9f61c3de --- /dev/null +++ b/explorer/testdata/trace/phase_timing.carbon @@ -0,0 +1,22 @@ +// 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 + +package ExplorerTest api; + +interface TestInterface {} + +fn Main() -> i32 { + return 0; +} + +// Place checks after code so that line numbers are stable, reducing merge +// conflicts. +// ARGS: --trace_file=- --trace_phase=timing %s +// AUTOUPDATE +// CHECK:STDOUT: ********** printing timing ********** +// CHECK:STDOUT: Time elapsed in ExecProgram: {{\d+}}ms +// CHECK:STDOUT: Time elapsed in AnalyzeProgram: {{\d+}}ms +// CHECK:STDOUT: Time elapsed in AddPrelude: {{\d+}}ms +// CHECK:STDOUT: Time elapsed in Parse: {{\d+}}ms +// CHECK:STDOUT: result: 0 diff --git a/explorer/testdata/trace/phase_type_checking.carbon b/explorer/testdata/trace/phase_type_checking.carbon new file mode 100644 index 000000000000..7c535ae0a9f0 --- /dev/null +++ b/explorer/testdata/trace/phase_type_checking.carbon @@ -0,0 +1,52 @@ +// 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 + +package ExplorerTest api; + +interface TestInterface {} + +fn Main() -> i32 { + return 0; +} + +// Place checks after code so that line numbers are stable, reducing merge +// conflicts. +// ARGS: --trace_file=- --trace_phase=type_checking %s +// AUTOUPDATE +// CHECK:STDOUT: ********** type checking ********** +// CHECK:STDOUT: ** declaring interface TestInterface +// CHECK:STDOUT: ** finished declaring interface TestInterface +// CHECK:STDOUT: checking InterfaceDeclaration +// CHECK:STDOUT: ** checking interface TestInterface +// CHECK:STDOUT: impl declarations:{{ }} +// CHECK:STDOUT: impl declarations: bool as interface EqWith(U = bool), i32 as interface EqWith(U = i32), String as interface EqWith(U = String), i32 as interface CompareWith(U = i32), String as interface CompareWith(U = String), i32 as interface LessWith(U = i32), String as interface LessWith(U = String), i32 as interface LessEqWith(U = i32), String as interface LessEqWith(U = String), i32 as interface GreaterWith(U = i32), String as interface GreaterWith(U = String), i32 as interface GreaterEqWith(U = i32), String as interface GreaterEqWith(U = String), i32 as interface Negate, i32 as interface AddWith(U = i32), i32 as interface SubWith(U = i32), i32 as interface MulWith(U = i32), i32 as interface DivWith(U = i32), i32 as interface ModWith(U = i32), i32 as interface BitComplement, i32 as interface BitAndWith(U = i32), i32 as interface BitOrWith(U = i32), i32 as interface BitXorWith(U = i32), i32 as interface LeftShiftWith(U = i32), i32 as interface RightShiftWith(U = i32), i32 as interface Inc, i32 as interface Dec, U as interface __EqualConverter [0], (T1,) as interface As(T = (U1,)) [0, 0, 0; 1, 1, 0, 0, 0], (T1, T2) as interface As(T = (U1, U2)) [0, 0, 0; 0, 0, 1; 1, 1, 0, 0, 0; 1, 1, 0, 0, 1], (T1, U1) as interface EqWith(U = (T2, U2)) [0, 0, 0; 0, 0, 1; 1, 1, 0, 0, 0; 1, 1, 0, 0, 1], (T1, T2, T3) as interface As(T = (U1, U2, U3)) [0, 0, 0; 0, 0, 1; 0, 0, 2; 1, 1, 0, 0, 0; 1, 1, 0, 0, 1; 1, 1, 0, 0, 2], T as interface ImplicitAs(T = U) [0; 1, 1, 0], T as interface As(T = U) [0; 1, 1, 0], T as interface ImplicitAs(T = U) [0; 1, 1, 0], T as interface As(T = U) [0; 1, 1, 0], T as interface AssignWith(U = U) [0; 1, 1, 0], T as interface AddAssignWith(U = U) [0; 1, 1, 0], T as interface SubAssignWith(U = U) [0; 1, 1, 0], T as interface MulAssignWith(U = U) [0; 1, 1, 0], T as interface DivAssignWith(U = U) [0; 1, 1, 0], T as interface ModAssignWith(U = U) [0; 1, 1, 0], T as interface BitAndAssignWith(U = U) [0; 1, 1, 0], T as interface BitOrAssignWith(U = U) [0; 1, 1, 0], T as interface BitXorAssignWith(U = U) [0; 1, 1, 0], T as interface LeftShiftAssignWith(U = U) [0; 1, 1, 0], T as interface RightShiftAssignWith(U = U) [0; 1, 1, 0] +// CHECK:STDOUT: ** finished checking interface TestInterface +// CHECK:STDOUT: ** declaring function Main +// CHECK:STDOUT: checking TuplePattern () +// CHECK:STDOUT: checking IntTypeLiteral i32 +// CHECK:STDOUT: (+) stack-push: i32 .0. +// CHECK:STDOUT: (+) stack-push: i32 .0. +// CHECK:STDOUT: --- step exp i32 .0. (phase_type_checking.carbon:9) ---> +// CHECK:STDOUT: (-) stack-pop: i32 .0. +// CHECK:STDOUT: (-) stack-pop: i32 .1. {{\[\[}}i32]] +// CHECK:STDOUT: ** finished declaring function Main of type fn () -> i32 +// CHECK:STDOUT: checking FunctionDeclaration +// CHECK:STDOUT: ** checking function Main +// CHECK:STDOUT: impl declarations:{{ }} +// CHECK:STDOUT: impl declarations: bool as interface EqWith(U = bool), i32 as interface EqWith(U = i32), String as interface EqWith(U = String), i32 as interface CompareWith(U = i32), String as interface CompareWith(U = String), i32 as interface LessWith(U = i32), String as interface LessWith(U = String), i32 as interface LessEqWith(U = i32), String as interface LessEqWith(U = String), i32 as interface GreaterWith(U = i32), String as interface GreaterWith(U = String), i32 as interface GreaterEqWith(U = i32), String as interface GreaterEqWith(U = String), i32 as interface Negate, i32 as interface AddWith(U = i32), i32 as interface SubWith(U = i32), i32 as interface MulWith(U = i32), i32 as interface DivWith(U = i32), i32 as interface ModWith(U = i32), i32 as interface BitComplement, i32 as interface BitAndWith(U = i32), i32 as interface BitOrWith(U = i32), i32 as interface BitXorWith(U = i32), i32 as interface LeftShiftWith(U = i32), i32 as interface RightShiftWith(U = i32), i32 as interface Inc, i32 as interface Dec, U as interface __EqualConverter [0], (T1,) as interface As(T = (U1,)) [0, 0, 0; 1, 1, 0, 0, 0], (T1, T2) as interface As(T = (U1, U2)) [0, 0, 0; 0, 0, 1; 1, 1, 0, 0, 0; 1, 1, 0, 0, 1], (T1, U1) as interface EqWith(U = (T2, U2)) [0, 0, 0; 0, 0, 1; 1, 1, 0, 0, 0; 1, 1, 0, 0, 1], (T1, T2, T3) as interface As(T = (U1, U2, U3)) [0, 0, 0; 0, 0, 1; 0, 0, 2; 1, 1, 0, 0, 0; 1, 1, 0, 0, 1; 1, 1, 0, 0, 2], T as interface ImplicitAs(T = U) [0; 1, 1, 0], T as interface As(T = U) [0; 1, 1, 0], T as interface ImplicitAs(T = U) [0; 1, 1, 0], T as interface As(T = U) [0; 1, 1, 0], T as interface AssignWith(U = U) [0; 1, 1, 0], T as interface AddAssignWith(U = U) [0; 1, 1, 0], T as interface SubAssignWith(U = U) [0; 1, 1, 0], T as interface MulAssignWith(U = U) [0; 1, 1, 0], T as interface DivAssignWith(U = U) [0; 1, 1, 0], T as interface ModAssignWith(U = U) [0; 1, 1, 0], T as interface BitAndAssignWith(U = U) [0; 1, 1, 0], T as interface BitOrAssignWith(U = U) [0; 1, 1, 0], T as interface BitXorAssignWith(U = U) [0; 1, 1, 0], T as interface LeftShiftAssignWith(U = U) [0; 1, 1, 0], T as interface RightShiftAssignWith(U = U) [0; 1, 1, 0] +// CHECK:STDOUT: checking Block { +// CHECK:STDOUT: return 0; +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: checking ReturnExpression return 0; +// CHECK:STDOUT: checking IntLiteral 0 +// CHECK:STDOUT: ** finished checking function Main +// CHECK:STDOUT: checking CallExpression Main() +// CHECK:STDOUT: checking IdentifierExpression Main +// CHECK:STDOUT: checking TupleLiteral () +// CHECK:STDOUT: checking call to function of type fn () -> i32 +// CHECK:STDOUT: with arguments of type: () +// CHECK:STDOUT: performing argument deduction for bindings:{{ }} +// CHECK:STDOUT: deduction succeeded with results: {} +// CHECK:STDOUT: result: 0 diff --git a/explorer/testdata/trace/phase_unformed_variables_resolution.carbon b/explorer/testdata/trace/phase_unformed_variables_resolution.carbon new file mode 100644 index 000000000000..c3bda2856da5 --- /dev/null +++ b/explorer/testdata/trace/phase_unformed_variables_resolution.carbon @@ -0,0 +1,22 @@ +// 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 + +package ExplorerTest api; + +interface TestInterface {} + +fn Main() -> i32 { + return 0; +} + +// Place checks after code so that line numbers are stable, reducing merge +// conflicts. +// ARGS: --trace_file=- --trace_phase=unformed_variables_resolution %s +// AUTOUPDATE +// CHECK:STDOUT: ********** resolving unformed variables ********** +// CHECK:STDOUT: *** resolving-unformed in decl `interface TestInterface` (phase_unformed_variables_resolution.carbon:7) +// CHECK:STDOUT: *** resolving-unformed in decl `fn Main` (phase_unformed_variables_resolution.carbon:11) +// CHECK:STDOUT: *** resolving-unformed in stmt `{return 0;}` (phase_unformed_variables_resolution.carbon:11) +// CHECK:STDOUT: *** resolving-unformed in stmt `return 0;` (phase_unformed_variables_resolution.carbon:10) +// CHECK:STDOUT: result: 0 diff --git a/testing/file_test/autoupdate.cpp b/testing/file_test/autoupdate.cpp index 6122c27ad4e3..f2c305f68f47 100644 --- a/testing/file_test/autoupdate.cpp +++ b/testing/file_test/autoupdate.cpp @@ -19,12 +19,23 @@ namespace Carbon::Testing { // Put helper classes in an anonymous namespace. namespace { +// Converts a matched line number to an int, trimming whitespace. +static auto ParseLineNumber(absl::string_view matched_line_number) -> int { + llvm::StringRef trimmed = matched_line_number; + trimmed = trimmed.trim(); + // NOLINTNEXTLINE(google-runtime-int): API requirement. + long long val; + CARBON_CHECK(!llvm::getAsSignedInteger(trimmed, 10, val)); + return val; +} + class CheckLine : public FileTestLineBase { public: // RE2 is passed by a pointer because it doesn't support std::optional. - explicit CheckLine(int line_number, const RE2* line_number_re, - std::string line) + explicit CheckLine(int line_number, bool line_number_re_has_file, + const RE2* line_number_re, std::string line) : FileTestLineBase(line_number), + line_number_re_has_file_(line_number_re_has_file), line_number_re_(line_number_re), line_(std::move(line)) {} @@ -41,20 +52,50 @@ class CheckLine : public FileTestLineBase { // When the location of all lines in a file are known, we can set the line // offset based on the target line. - auto SetRemappedLine(const std::string& sub_for_formatv, - int target_line_number) -> void { - // Should only be called when we have a regex. - CARBON_CHECK(line_number_re_); + auto RemapLineNumbers(const llvm::DenseMap& output_line_remap, + const std::string& line_formatv) -> void { + // Only need to do remappings when there's a regex. + if (!line_number_re_) { + return; + } - int offset = target_line_number - output_line_number_; - const char* offset_prefix = offset < 0 ? "" : "+"; - std::string replacement = - llvm::formatv(sub_for_formatv.data(), - llvm::formatv("[[@LINE{0}{1}]]", offset_prefix, offset)); - RE2::Replace(&line_, *line_number_re_, replacement); + bool found_one = false; + while (true) { + // Look for a line number to replace. There may be multiple, so we + // repeatedly check. + absl::string_view matched_line_number; + if (line_number_re_has_file_) { + RE2::PartialMatch(line_, *line_number_re_, nullptr, + &matched_line_number); + } else { + RE2::PartialMatch(line_, *line_number_re_, &matched_line_number); + } + if (matched_line_number.empty()) { + CARBON_CHECK(found_one) << line_; + return; + } + found_one = true; + + // Calculate the offset from the CHECK line to the new line number + // (possibly with new CHECK lines added, or some removed). + // NOLINTNEXTLINE(google-runtime-int): API requirement. + auto remapped = + output_line_remap.find(ParseLineNumber(matched_line_number)); + CARBON_CHECK(remapped != output_line_remap.end()); + int offset = remapped->second - output_line_number_; + + // Update the line offset in the CHECK line. + const char* offset_prefix = offset < 0 ? "" : "+"; + std::string replacement = llvm::formatv( + line_formatv.c_str(), + llvm::formatv("[[@LINE{0}{1}]]", offset_prefix, offset)); + line_.replace(matched_line_number.data() - line_.data(), + matched_line_number.size(), replacement); + } } private: + bool line_number_re_has_file_; const RE2* line_number_re_; std::string line_; llvm::StringRef indent_; @@ -90,10 +131,19 @@ static auto AddCheckLines( lines.pop_back(); } + // `{{` and `[[` are escaped as a regex matcher. + RE2 double_brace_re(R"(\{\{)"); + RE2 double_square_bracket_re(R"(\[\[)"); + // End-of-line whitespace is replaced with a regex matcher to make it visible. + RE2 end_of_line_whitespace_re(R"((\s+)$)"); + int append_to = 0; for (const auto& line : lines) { std::string check_line = llvm::formatv("// CHECK:{0}:{1}{2}", label, line.empty() ? "" : " ", line); + RE2::Replace(&check_line, double_brace_re, R"({{\\{\\{}})"); + RE2::Replace(&check_line, double_square_bracket_re, R"({{\\[\\[}})"); + RE2::Replace(&check_line, end_of_line_whitespace_re, R"({{\1}})"); // Ignore TEST_TMPDIR in output. if (auto pos = check_line.find(tmpdir); pos != std::string::npos) { @@ -102,10 +152,10 @@ static auto AddCheckLines( do_extra_check_replacements(check_line); - // Look for line information in the output. line_number is only set if the - // match is correct. - int line_number = -1; - int match_line_number; + // Look for line information in the output. use_line_number is only set if + // the match is correct. + std::optional use_line_number; + absl::string_view match_line_number; if (line_number_re_has_file) { absl::string_view match_filename; if (RE2::PartialMatch(check_line, line_number_re, &match_filename, @@ -119,22 +169,25 @@ static auto AddCheckLines( if (pos != filenames.end()) { remaining_filenames = pos + 1; append_to = pos - filenames.begin(); - line_number = match_line_number; + use_line_number = match_line_number; } } else { // The line applies to the current file. - line_number = match_line_number; + use_line_number = match_line_number; } } } else { // There's no file association, so we only look at the line. if (RE2::PartialMatch(check_line, line_number_re, &match_line_number)) { - line_number = match_line_number; + use_line_number = match_line_number; } } + // NOLINTNEXTLINE(google-runtime-int): API requirement. + long long line_number = + use_line_number ? ParseLineNumber(*use_line_number) : -1; check_lines[append_to].push_back( - CheckLine(line_number, line_number == -1 ? nullptr : &line_number_re, - check_line)); + CheckLine(line_number, line_number_re_has_file, + use_line_number ? &line_number_re : nullptr, check_line)); } } @@ -212,12 +265,8 @@ auto AutoupdateFileTest( // Update all remapped lines in CHECK output. for (auto& offset_check_line : check_file) { - if (offset_check_line.line_number() >= 1) { - auto new_line = output_line_remap.find(offset_check_line.line_number()); - CARBON_CHECK(new_line != output_line_remap.end()); - offset_check_line.SetRemappedLine( - line_number_replacement.sub_for_formatv, new_line->second); - } + offset_check_line.RemapLineNumbers(output_line_remap, + line_number_replacement.line_formatv); } } diff --git a/testing/file_test/autoupdate.h b/testing/file_test/autoupdate.h index 0683610f2272..c0c81165795a 100644 --- a/testing/file_test/autoupdate.h +++ b/testing/file_test/autoupdate.h @@ -20,8 +20,8 @@ struct FileTestLineNumberReplacement { // should have a file and line group; otherwise, only a line group. std::string pattern; - // sub_for_formatv should provide {0} to substitute with [[@LINE...]] deltas. - std::string sub_for_formatv; + // line_formatv should provide {0} to substitute with [[@LINE...]] deltas. + std::string line_formatv; }; // Automatically updates CHECKs in the provided file. Returns true if updated. diff --git a/testing/file_test/file_test_base.cpp b/testing/file_test/file_test_base.cpp index 7dd6becb674f..1a55f3453bb6 100644 --- a/testing/file_test/file_test_base.cpp +++ b/testing/file_test/file_test_base.cpp @@ -52,15 +52,11 @@ static auto SplitOutput(llvm::StringRef output) // Runs a test and compares output. This keeps output split by line so that // issues are a little easier to identify by the different line. auto FileTestBase::TestBody() -> void { - const char* src_dir = getenv("TEST_SRCDIR"); - CARBON_CHECK(src_dir); - std::string test_file = path().lexically_relative( - std::filesystem::path(src_dir).append("carbon")); const char* target = getenv("TEST_TARGET"); CARBON_CHECK(target); // This advice overrides the --file_tests flag provided by the file_test rule. llvm::errs() << "\nTo test this file alone, run:\n bazel test " << target - << " --test_arg=--file_tests=" << test_file << "\n\n"; + << " --test_arg=--file_tests=" << GetTestFilename() << "\n\n"; TestContext context; auto run_result = ProcessTestFileAndRun(context); @@ -86,10 +82,13 @@ auto FileTestBase::TestBody() -> void { } } -auto FileTestBase::Autoupdate() -> bool { +auto FileTestBase::Autoupdate() -> ErrorOr { TestContext context; auto run_result = ProcessTestFileAndRun(context); - CARBON_CHECK(run_result.ok()) << run_result.error(); + if (!run_result.ok()) { + return ErrorBuilder() << "Error updating " << GetTestFilename() << ": " + << run_result.error(); + } if (!context.autoupdate_line_number) { return false; } @@ -120,8 +119,8 @@ auto FileTestBase::GetLineNumberReplacement( llvm::ArrayRef filenames) -> LineNumberReplacement { return { .has_file = true, - .pattern = llvm::formatv(R"(({0}):(\d+):)", llvm::join(filenames, "|")), - .sub_for_formatv = R"(\1:{0}:)"}; + .pattern = llvm::formatv(R"(({0}):(\d+))", llvm::join(filenames, "|")), + .line_formatv = R"({0})"}; } auto FileTestBase::ProcessTestFileAndRun(TestContext& context) @@ -258,15 +257,21 @@ auto FileTestBase::ProcessTestFile(TestContext& context) -> ErrorOr { // Process expectations when found. if (line_trimmed.consume_front("// CHECK")) { - llvm::SmallVector>* expected = nullptr; - if (line_trimmed.consume_front(":STDOUT:")) { - expected = &context.expected_stdout; - } else if (line_trimmed.consume_front(":STDERR:")) { - expected = &context.expected_stderr; - } else { - return ErrorBuilder() << "Unexpected CHECK in input: " << line.str(); + // Don't build expectations when doing an autoupdate. We don't want to + // break the autoupdate on an invalid CHECK line. + if (!absl::GetFlag(FLAGS_autoupdate)) { + llvm::SmallVector>* expected = nullptr; + if (line_trimmed.consume_front(":STDOUT:")) { + expected = &context.expected_stdout; + } else if (line_trimmed.consume_front(":STDERR:")) { + expected = &context.expected_stderr; + } else { + return ErrorBuilder() << "Unexpected CHECK in input: " << line.str(); + } + CARBON_ASSIGN_OR_RETURN(Matcher check_matcher, + TransformExpectation(line_index, line_trimmed)); + expected->push_back(check_matcher); } - expected->push_back(TransformExpectation(line_index, line_trimmed)); } else { context.non_check_lines.back().push_back(FileTestLine(line_index, line)); if (line_trimmed.consume_front("// ARGS: ")) { @@ -330,11 +335,13 @@ auto FileTestBase::ProcessTestFile(TestContext& context) -> ErrorOr { } auto FileTestBase::TransformExpectation(int line_index, llvm::StringRef in) - -> Matcher { + -> ErrorOr> { if (in.empty()) { - return StrEq(""); + return Matcher{StrEq("")}; + } + if (in[0] != ' ') { + return ErrorBuilder() << "Malformated CHECK line: " << in; } - CARBON_CHECK(in[0] == ' ') << "Malformated input: " << in; std::string str = in.substr(1).str(); for (int pos = 0; pos < static_cast(str.size());) { switch (str[pos]) { @@ -364,18 +371,20 @@ auto FileTestBase::TransformExpectation(int line_index, llvm::StringRef in) line_keyword_cursor.consume_front("+"); int offset; // consumeInteger returns true for errors, not false. - CARBON_CHECK(!line_keyword_cursor.consumeInteger(10, offset) && - line_keyword_cursor.consume_front("]]")) - << "Unexpected @LINE offset at `" - << line_keyword_cursor.substr(0, 5) << "` in: " << in; + if (line_keyword_cursor.consumeInteger(10, offset) || + !line_keyword_cursor.consume_front("]]")) { + return ErrorBuilder() + << "Unexpected @LINE offset at `" + << line_keyword_cursor.substr(0, 5) << "` in: " << in; + } std::string int_str = llvm::Twine(line_index + offset).str(); int remove_len = (line_keyword_cursor.data() - str.data()) - pos; str.replace(pos, remove_len, int_str); pos += int_str.size(); } else { - CARBON_FATAL() << "Unexpected [[, should be {{\\[\\[}} at `" - << line_keyword_cursor.substr(0, 5) - << "` in: " << in; + return ErrorBuilder() + << "Unexpected [[, should be {{\\[\\[}} at `" + << line_keyword_cursor.substr(0, 5) << "` in: " << in; } } else { // Escape the `[`. @@ -408,7 +417,14 @@ auto FileTestBase::TransformExpectation(int line_index, llvm::StringRef in) } } - return MatchesRegex(str); + return Matcher{MatchesRegex(str)}; +} + +auto FileTestBase::GetTestFilename() -> std::string { + const char* src_dir = getenv("TEST_SRCDIR"); + CARBON_CHECK(src_dir); + return path().lexically_relative( + std::filesystem::path(src_dir).append("carbon")); } } // namespace Carbon::Testing @@ -429,7 +445,7 @@ auto main(int argc, char** argv) -> int { // Configure the base directory for test names. const char* target = getenv("TEST_TARGET"); - CARBON_CHECK(target != nullptr); + CARBON_CHECK(target); llvm::StringRef target_dir = target; std::error_code ec; std::filesystem::path working_dir = std::filesystem::current_path(ec); @@ -450,7 +466,9 @@ auto main(int argc, char** argv) -> int { if (absl::GetFlag(FLAGS_autoupdate)) { std::unique_ptr test( test_factory.factory_fn(path)); - llvm::errs() << (test->Autoupdate() ? "!" : "."); + auto result = test->Autoupdate(); + llvm::errs() << (result.ok() ? (*result ? "!" : ".") + : result.error().message()); } else { std::string test_name = path.string().substr(base_dir.size()); testing::RegisterTest(test_factory.name, test_name.c_str(), nullptr, diff --git a/testing/file_test/file_test_base.h b/testing/file_test/file_test_base.h index 93667e8cc017..e5f8865e39ca 100644 --- a/testing/file_test/file_test_base.h +++ b/testing/file_test/file_test_base.h @@ -79,7 +79,7 @@ class FileTestBase : public testing::Test { auto TestBody() -> void final; // Runs the test and autoupdates checks. Returns true if updated. - auto Autoupdate() -> bool; + auto Autoupdate() -> ErrorOr; // Returns the full path of the file being tested. auto path() -> const std::filesystem::path& { return path_; }; @@ -134,10 +134,13 @@ class FileTestBase : public testing::Test { // Processes the test input, producing test files and expected output. auto ProcessTestFile(TestContext& context) -> ErrorOr; + // Gets the test filename, relative to the target directory. + auto GetTestFilename() -> std::string; + // Transforms an expectation on a given line from `FileCheck` syntax into a // standard regex matcher. static auto TransformExpectation(int line_index, llvm::StringRef in) - -> testing::Matcher; + -> ErrorOr>; const std::filesystem::path path_; }; diff --git a/testing/lit_test/__init__.py b/testing/lit_test/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/testing/lit_test/lit.cfg.py b/testing/lit_test/lit.cfg.py deleted file mode 100644 index 8f5483251e65..000000000000 --- a/testing/lit_test/lit.cfg.py +++ /dev/null @@ -1,58 +0,0 @@ -__copyright__ = """ -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 -""" - -import lit.formats -import os -from pathlib import Path - - -# This is a provided variable, ignore the undefined name warning. -config = config # noqa: F821 - - -def fullpath(relative_path): - return Path(os.environ["TEST_SRCDIR"]).joinpath(relative_path) - - -def add_substitution(before, after): - """Adds a substitution to the config. Wraps before as `%{before}`.""" - config.substitutions.append((f"%{{{before}}}", after)) - - -def add_substitutions(): - """Adds required substitutions to the config.""" - tools = { - "carbon": fullpath("carbon/toolchain/driver/carbon"), - "explorer": fullpath("carbon/explorer/explorer"), - "explorer_prelude": fullpath("carbon/explorer/data/prelude.carbon"), - "filecheck": fullpath("llvm-project/llvm/FileCheck"), - "not": fullpath("llvm-project/llvm/not"), - "merge_output": fullpath("carbon/testing/lit_test/merge_output"), - } - - run_carbon = f"{tools['merge_output']} {tools['carbon']}" - run_explorer = ( - f"{tools['merge_output']} {tools['explorer']} %s " - f"--prelude={tools['explorer_prelude']}" - ) - filecheck_allow_unmatched = ( - f"{tools['filecheck']} %s --match-full-lines --strict-whitespace" - ) - filecheck_strict = ( - f"{filecheck_allow_unmatched} --implicit-check-not={{{{.}}}}" - ) - - add_substitution("carbon", f"{run_carbon}") - add_substitution("explorer", f"{run_explorer}") - add_substitution("FileCheck-allow-unmatched", filecheck_allow_unmatched) - add_substitution("FileCheck-strict", filecheck_strict) - add_substitution("not", tools["not"]) - - -config.name = "lit" -config.suffixes = [".carbon"] -config.test_format = lit.formats.ShTest() -add_substitutions() diff --git a/testing/lit_test/lit_test.py b/testing/lit_test/lit_test.py deleted file mode 100644 index 7d7313de7233..000000000000 --- a/testing/lit_test/lit_test.py +++ /dev/null @@ -1,57 +0,0 @@ -"""Runs `lit` for testing.""" - -__copyright__ = """ -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 -""" - -import argparse -import os -from pathlib import Path -import shutil -import subprocess - - -def _parse_args(): - """Parses command line arguments, returning the result.""" - arg_parser = argparse.ArgumentParser(description=__doc__) - arg_parser.add_argument( - "--package_name", help="The directory containing tests to run." - ) - arg_parser.add_argument( - "lit_args", nargs="*", help="Arguments to pass through to lit." - ) - return arg_parser.parse_args() - - -def main(): - parsed_args = _parse_args() - - args = [ - str(Path(os.environ["TEST_SRCDIR"]).joinpath("llvm-project/llvm/lit")), - str(Path.cwd().joinpath(parsed_args.package_name)), - "-v", - ] - - # Force tests to be explicit about command paths. Some tools are required by - # bazel's py_binary output in order to find python3, so we add these. The - # list of tools may prove to be fragile: if so, we may need to change or - # remove the PATH hiding. - system_tools = Path(os.environ["TEST_TMPDIR"]).joinpath("system_tools") - system_tools.mkdir() - for tool in ("env", "grep", "python3", "sh", "which"): - system_tools.joinpath(tool).symlink_to(shutil.which(tool)) - env = os.environ.copy() - env["PATH"] = str(system_tools) - - # Run lit. - try: - subprocess.check_call(args=args + parsed_args.lit_args, env=env) - except subprocess.CalledProcessError as e: - # Print without the stack trace. - exit(e) - - -if __name__ == "__main__": - exit(main()) diff --git a/testing/lit_test/merge_output.py b/testing/lit_test/merge_output.py deleted file mode 100644 index f57aaf91cd12..000000000000 --- a/testing/lit_test/merge_output.py +++ /dev/null @@ -1,38 +0,0 @@ -"""Merges stdout and stderr into a single stream with labels.""" - -__copyright__ = """ -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 -""" - -import subprocess -import sys - - -def label_output(label: str, output: str) -> None: - """Prints output with labels. - - This mirrors label_output in scripts/autoupdate_testdata_base.py and should - be kept in sync. They're separate in order to avoid a subprocess or import - complexity. - """ - if output: - for line in output.splitlines(): - print(" ".join(filter(None, (label, line)))) - - -def main() -> None: - p = subprocess.run( - sys.argv[1:], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - encoding="utf-8", - ) - label_output("STDOUT:", p.stdout) - label_output("STDERR:", p.stderr) - exit(p.returncode) - - -if __name__ == "__main__": - main() diff --git a/testing/lit_test/rules.bzl b/testing/lit_test/rules.bzl deleted file mode 100644 index c0ac72d18895..000000000000 --- a/testing/lit_test/rules.bzl +++ /dev/null @@ -1,66 +0,0 @@ -# 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 - -"""Rule for a lit test.""" - -def glob_lit_tests(name, driver, data, test_file_exts, exclude = None, **kwargs): - """Runs `lit` on test_dir. - - `lit` reference: - https://llvm.org/docs/CommandGuide/lit.html - - This will generate three types of rules: - 1. For each test file, a rule with ".test" at the end. For example, - "foo/bar/baz.carbon" will generate ":foo/bar/baz.carbon.test" - 2. If any test exists in subdirectory, a test_suite is generated for each - directory. For example, ":foo" will run all tests under directory "foo", - and ":foo/bar" will run all tests under "foo/bar". - 3. A test_suite containing all tests. The name of this will be the "name" - arg passed to the glob_lit_tests rule. - - Args: - name: The name of the test_suite rule to generate for running all tests. - driver: The path to the lit config. - data: A list of tools to provide to the tests. These will be aliased for - execution. - test_file_exts: A list of extensions to use for tests. - exclude: A list of paths to exclude from the glob. - **kwargs: Any additional parameters for the generated py_test. - """ - if not exclude: - exclude = [] - test_files = native.glob( - ["**"], - exclude = exclude, - exclude_directories = 1, - ) - data.append("@llvm-project//llvm:lit") - suites = dict() - all_tests = list() - for f in test_files: - if f.split(".")[-1] not in test_file_exts: - continue - test = "%s.test" % f - all_tests.append(test) - native.py_test( - name = test, - srcs = ["//testing/lit_test:lit_test.py"], - main = "//testing/lit_test:lit_test.py", - data = data + [driver, f], - args = ["--package_name=%s" % native.package_name(), "--"], - size = "small", - **kwargs - ) - - # Cluster tests by directory in order to produce suites. For example, - # foo/bar/baz.carbon.test is added to suites :foo and :foo/bar. - dirs = f.split("/")[:-1] - for num_parts in range(1, 1 + len(dirs)): - dir = "/".join(dirs[:num_parts]) - if dir not in suites: - suites[dir] = [] - suites[dir].append(test) - native.test_suite(name = name, tests = all_tests) - for suite, tests in suites.items(): - native.test_suite(name = suite, tests = tests) diff --git a/testing/scripts/__init__.py b/testing/scripts/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/testing/scripts/autoupdate_testdata_base.py b/testing/scripts/autoupdate_testdata_base.py deleted file mode 100755 index 7de5d66a5de9..000000000000 --- a/testing/scripts/autoupdate_testdata_base.py +++ /dev/null @@ -1,542 +0,0 @@ -#!/usr/bin/env python3 - -"""Updates the CHECK: lines in tests with an AUTOUPDATE line.""" - -__copyright__ = """ -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 -""" - -from abc import ABC, abstractmethod -import argparse -from concurrent import futures -import os -from pathlib import Path -import re -import subprocess -from typing import ( - Any, - Dict, - List, - Match, - NamedTuple, - Optional, - Pattern, - Set, - Tuple, -) - -# A prefix followed by a command to run for autoupdating checked output. -AUTOUPDATE_MARKER = "// AUTOUPDATE" - -# Indicates no autoupdate is requested. -NOAUTOUPDATE_MARKER = "// NOAUTOUPDATE" - -# Supported tools. -TOOLS = { - "carbon": "//toolchain/driver:carbon", - "explorer": "//explorer:explorer", -} - - -class ParsedArgs(NamedTuple): - autoupdate_args: List[str] - build_mode: str - extra_check_replacements: List[Tuple[Pattern, Pattern, str]] - line_number_delta_prefix: str - line_number_pattern: Pattern - lit_run: List[str] - testdata: str - tests: List[Path] - tool: str - - -def parse_args() -> ParsedArgs: - """Parses command-line arguments and flags.""" - parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument("tests", nargs="*") - parser.add_argument( - "--autoupdate_arg", - metavar="COMMAND", - default=[], - action="append", - help="Optional arguments to pass to the autoupdate command.", - ) - parser.add_argument( - "--build_mode", - metavar="MODE", - default="opt", - help="The build mode to use. Defaults to opt for faster execution.", - ) - parser.add_argument( - "--extra_check_replacement", - nargs=3, - metavar=("MATCHING", "BEFORE", "AFTER"), - default=[], - action="append", - help="On a CHECK line with MATCHING, does a regex replacement of " - "BEFORE with AFTER.", - ) - parser.add_argument( - "--line_number_delta_prefix", - metavar="PREFIX", - default="", - help="An optional prefix to add before the [[@LINE+delta]] marker.", - ) - parser.add_argument( - "--line_number_pattern", - metavar="PATTERN", - default=r"(?P(?P\w+\.carbon):)" - r"(?P\d+)(?P(?:\D|$))", - help="A regular expression which matches line numbers to update as its " - "only group. Capture groups 'prefix', 'line', and 'suffix' are " - "required for structure. The 'filename' capture group is optional and " - "should be provided when lines may belong to different files.", - ) - parser.add_argument( - "--lit_run", - metavar="COMMAND", - default=[], - required=False, - action="append", - help="RUN lines to set.", - ) - parser.add_argument( - "--testdata", - metavar="PATH", - required=True, - help="The path to the testdata to update, relative to the workspace " - "root.", - ) - parser.add_argument( - "--tool", - metavar="TOOL", - required=True, - choices=TOOLS.keys(), - help="The tool being tested.", - ) - parsed_args = parser.parse_args() - extra_check_replacements = [ - (re.compile(line_matcher), re.compile(before), after) - for line_matcher, before, after in parsed_args.extra_check_replacement - ] - return ParsedArgs( - autoupdate_args=parsed_args.autoupdate_arg, - build_mode=parsed_args.build_mode, - extra_check_replacements=extra_check_replacements, - line_number_delta_prefix=parsed_args.line_number_delta_prefix, - line_number_pattern=re.compile(parsed_args.line_number_pattern), - lit_run=parsed_args.lit_run, - testdata=parsed_args.testdata, - tests=[Path(test).resolve() for test in parsed_args.tests], - tool=parsed_args.tool, - ) - - -def get_tests(testdata: str) -> Set[Path]: - """Get the list of tests from the filesystem.""" - tests = set() - for root, _, files in os.walk(testdata): - for f in files: - if f in {"lit.cfg.py", "BUILD", "README.md"}: - # Ignore the lit config. - continue - if os.path.splitext(f)[1] == ".carbon": - tests.add(Path(root).joinpath(f)) - else: - exit(f"Unrecognized file type in testdata: {f}") - return tests - - -class Line(ABC): - """A line that may appear in the resulting test file.""" - - @abstractmethod - def format( - self, *, output_line_number: int, line_number_remap: Dict[int, int] - ) -> str: - raise NotImplementedError - - -class OriginalLine(Line): - """A line that was copied from the original test file.""" - - def __init__(self, line_number: int, text: str) -> None: - self.line_number = line_number - self.text = text - - def format(self, **kwargs: Any) -> str: - return self.text - - -class RunLine(Line): - """A RUN line.""" - - def __init__(self, text: str) -> None: - self.text = text - - def format(self, **kwargs: Any) -> str: - return self.text - - -class CheckLine(Line): - """A `// CHECK:` line generated from the test output. - - If there's a line number, it'll be fixed up after we've figured out which - lines to include in the resulting test file and in what order, because - their contents depend on where an original input line appears in the output. - """ - - def __init__( - self, - test: str, - out_line: str, - line_number_delta_prefix: str, - line_number_pattern: Pattern, - ) -> None: - super().__init__() - self.filename = Path(test).name - self.indent = "" - self.out_line = out_line - self.line_number_delta_prefix = line_number_delta_prefix - self.line_number_pattern = line_number_pattern - self.trailing_whitespace_pattern = re.compile(r"(\s+$)") - - # If any match is specific to this file, use the first matched line for - # the location of the CHECK comment. - self.line_in_file = None - for match in line_number_pattern.finditer(self.out_line): - if self._matches_filename(match): - self.line_in_file = int(match.group("line")) - 1 - break - - def format( - self, *, output_line_number: int, line_number_remap: Dict[int, int] - ) -> str: - assert self.out_line - result = self.out_line - while True: - line_match = self.line_number_pattern.search(result) - trailing_match = self.trailing_whitespace_pattern.search(result) - if line_match: - if self._matches_filename(line_match): - line_number = int(line_match.group("line")) - 1 - delta = line_number_remap[line_number] - output_line_number - # We use `:+d` here to produce `LINE-n` or `LINE+n` as - # appropriate. - result = self.line_number_pattern.sub( - rf"\g{self.line_number_delta_prefix}" - rf"[[@LINE{delta:+d}]]\g", - result, - count=1, - ) - else: - result = self.line_number_pattern.sub( - r"\g{{.*}}\g", - result, - count=1, - ) - elif trailing_match: - result = self.trailing_whitespace_pattern.sub(r"{{\1}}", result) - else: - break - - return f"{self.indent}// CHECK:{result}\n" - - def _matches_filename(self, match: Match) -> bool: - return ( - "filename" not in match.groupdict() - or match.group("filename") == self.filename - ) - - -def find_autoupdate(test: str, orig_lines: List[str]) -> Optional[int]: - """Figures out whether autoupdate should occur. - - For AUTOUPDATE, returns the line. For NOAUTOUPDATE, returns None. - """ - found = 0 - result = None - for line_number, line in enumerate(orig_lines): - if line.startswith(AUTOUPDATE_MARKER): - found += 1 - result = line_number - elif line.startswith(NOAUTOUPDATE_MARKER): - found += 1 - if found == 0: - raise ValueError( - f"{test} must have either '{AUTOUPDATE_MARKER}' or " - f"'{NOAUTOUPDATE_MARKER}'" - ) - elif found > 1: - raise ValueError( - f"{test} must have only one of '{AUTOUPDATE_MARKER}' or " - f"'{NOAUTOUPDATE_MARKER}'" - ) - return result - - -def replace_all(s: str, replacements: List[Tuple[str, str]]) -> str: - """Runs multiple replacements on a string.""" - for before, after in replacements: - s = s.replace(before, after) - return s - - -def label_output(label: str, output: str) -> List[str]: - """Merges output with labels. - - This mirrors label_output in lit_test/merge_output.py and should - be kept in sync. They're separate in order to avoid a subprocess or import - complexity. - """ - result = [] - if output: - for line in output.splitlines(): - result.append(" ".join(filter(None, (label, line)))) - return result - - -def get_matchable_test_output( - autoupdate_args: List[str], - extra_check_replacements: List[Tuple[Pattern, Pattern, str]], - tool: str, - bazel_runfiles: Pattern, - llvm_symbolizer: str, - test: str, -) -> List[str]: - """Runs the autoupdate command and returns the output lines.""" - # Run the autoupdate command to generate output. - # (`bazel run` would serialize) - autoupdate_cmd = Path.cwd().joinpath( - TOOLS[tool].replace("//", "./bazel-bin/").replace(":", "/") - ) - p = subprocess.run( - [str(autoupdate_cmd)] + autoupdate_args + [Path(test).name], - env={"LLVM_SYMBOLIZER_PATH": llvm_symbolizer}, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - encoding="utf-8", - cwd=str(Path(test).parent), - ) - - out_lines = label_output("STDOUT:", p.stdout) - out_lines.extend(label_output("STDERR:", p.stderr)) - - for i, line in enumerate(out_lines): - # Escape things that mirror FileCheck special characters. - line = line.replace("{{", "{{[{][{]}}") - line = line.replace("[[", "{{[[][[]}}") - line = bazel_runfiles.sub("{{.*}}/", line) - - for line_matcher, before, after in extra_check_replacements: - if line_matcher.match(line): - line = before.sub(after, line) - - out_lines[i] = line - - return out_lines - - -def is_replaced(line: str) -> bool: - """Returns true if autoupdate should replace the line.""" - line = line.lstrip() - return line.startswith("// CHECK") or line.startswith("// RUN:") - - -def merge_lines( - line_number_delta_prefix: str, - line_number_pattern: Pattern, - lit_run: List[str], - test: str, - autoupdate_line_number: int, - raw_orig_lines: List[str], - out_lines: List[str], -) -> List[Line]: - """Merges the original output and new lines.""" - orig_lines = [ - OriginalLine(i, line) - for i, line in enumerate(raw_orig_lines) - if not is_replaced(line) - ] - check_lines = [ - CheckLine(test, out_line, line_number_delta_prefix, line_number_pattern) - for out_line in out_lines - ] - - result_lines: List[Line] = [] - # CHECK lines must go after AUTOUPDATE. - while orig_lines and orig_lines[0].line_number <= autoupdate_line_number: - result_lines.append(orig_lines.pop(0)) - for line in lit_run: - run_not = "" - if Path(test).name.startswith("fail_"): - run_not = "%{not} " - result_lines.append(RunLine(f"// RUN: {run_not}{line}\n")) - # Interleave the original lines and the CHECK: lines. - while orig_lines and check_lines: - # Original lines go first when the CHECK line is known and later. - if ( - check_lines[0].line_in_file is not None - and check_lines[0].line_in_file > orig_lines[0].line_number - ): - result_lines.append(orig_lines.pop(0)) - else: - check_line = check_lines.pop(0) - # Indent to match the next original line. - check_line.indent = re.findall("^ *", orig_lines[0].text)[0] - result_lines.append(check_line) - # One list is non-empty; append remaining lines from both to catch it. - result_lines.extend(orig_lines) - result_lines.extend(check_lines) - - return result_lines - - -def update_check( - parsed_args: ParsedArgs, - bazel_runfiles: Pattern, - llvm_symbolizer: str, - test: Path, -) -> bool: - """Updates the CHECK: lines for `test` by running the tool. - - Returns true if a change was made. - """ - with test.open() as f: - orig_lines = f.readlines() - - # Make sure we're supposed to autoupdate. - autoupdate_line = find_autoupdate(str(test), orig_lines) - if autoupdate_line is None: - return False - - # Determine the merged output lines. - out_lines = get_matchable_test_output( - parsed_args.autoupdate_args, - parsed_args.extra_check_replacements, - parsed_args.tool, - bazel_runfiles, - llvm_symbolizer, - str(test), - ) - result_lines = merge_lines( - parsed_args.line_number_delta_prefix, - parsed_args.line_number_pattern, - parsed_args.lit_run, - str(test), - autoupdate_line, - orig_lines, - out_lines, - ) - - # Calculate the remap for original lines. - line_number_remap = dict( - [ - (line.line_number, i) - for i, line in enumerate(result_lines) - if isinstance(line, OriginalLine) - ] - ) - # If the last line of the original output was a CHECK, replace it with an - # empty line. - if orig_lines[-1].lstrip().startswith("// CHECK"): - line_number_remap[len(orig_lines) - 1] = len(result_lines) - 1 - - # Generate contents for any lines that depend on line numbers. - formatted_result_lines = [ - line.format(output_line_number=i, line_number_remap=line_number_remap) - for i, line in enumerate(result_lines) - ] - - # If nothing's changed, we're done. - if formatted_result_lines == orig_lines: - return False - - # Interleave the new CHECK: lines with the tested content. - with test.open("w") as f: - f.writelines(formatted_result_lines) - return True - - -def update_checks( - parsed_args: ParsedArgs, - bazel_runfiles: Pattern, - llvm_symbolizer: str, - tests: Set[Path], -) -> None: - """Updates CHECK: lines in lit tests.""" - - def map_helper(test: Path) -> bool: - try: - updated = update_check( - parsed_args, bazel_runfiles, llvm_symbolizer, test - ) - except Exception as e: - raise ValueError(f"Failed to update {test}") from e - print(".", end="", flush=True) - return updated - - print(f"Updating {len(tests)} lit test(s)...") - with futures.ThreadPoolExecutor() as exec: - # list() iterates in order to immediately propagate exceptions. - results = list(exec.map(map_helper, tests)) - - # Each update call indicates progress with a dot without a newline, so put a - # newline to wrap. - print(f"\nUpdated {results.count(True)} lit test(s).") - - -def main() -> None: - # Parse arguments relative to the working directory. - parsed_args = parse_args() - - # Remaining script logic should be relative to the repository root. - root = Path(__file__).parent.parent.parent - os.chdir(root) - - if parsed_args.tests: - tests = {test.relative_to(root) for test in parsed_args.tests} - else: - print( - "HINT: run `autoupdate_testdata.py f1 f2 ...` " - "to update specific tests" - ) - tests = get_tests(parsed_args.testdata) - - # Build inputs. - print(f"Building {parsed_args.tool}...") - subprocess.check_call( - [ - "bazel", - "build", - "-c", - parsed_args.build_mode, - TOOLS[parsed_args.tool], - ] - ) - bazel_bin_dir = subprocess.check_output( - ["bazel", "info", "-c", parsed_args.build_mode, "bazel-bin"], - encoding="utf-8", - ).strip() - bazel_runfiles = re.compile( - r"{0}/.*\.runfiles/carbon/".format(re.escape(bazel_bin_dir)) - ) - - # Grab the symbolizer. - clang_var_content = Path( - "bazel-execroot/external/bazel_cc_toolchain/" - "clang_detected_variables.bzl" - ).read_text() - llvm_symbolizer = re.search( - '(?m)^llvm_symbolizer = "(.*)"$', clang_var_content - ) - assert llvm_symbolizer is not None - - # Run updates. - update_checks(parsed_args, bazel_runfiles, llvm_symbolizer[1], tests) - - -if __name__ == "__main__": - main() diff --git a/toolchain/lexer/lexer_file_test.cpp b/toolchain/lexer/lexer_file_test.cpp index 0ef0720c4671..54196743357b 100644 --- a/toolchain/lexer/lexer_file_test.cpp +++ b/toolchain/lexer/lexer_file_test.cpp @@ -24,9 +24,9 @@ class LexerFileTest : public DriverFileTestBase { auto GetLineNumberReplacement(llvm::ArrayRef /*filenames*/) -> LineNumberReplacement override { return {.has_file = false, - .pattern = R"(line: +(\d+))", + .pattern = R"(line: (\s*\d+))", // The `{{{{` becomes `{{`. - .sub_for_formatv = "line: {{{{ *}}{0}"}; + .line_formatv = "{{{{ *}}{0}"}; } auto DoExtraCheckReplacements(std::string& check_line) -> void override {