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 {