Revert "Add writer to emit the AST."

This reverts commit a753ad47a48fc0fba6e617b7ffcddc0e1fdc4b2e.

Reason for revert: This seems to be breaking `gn check` when the option is not enabled. Not sure why the preprocessor guard isn't working. Will fix and reland later.

Original change's description:
> Add writer to emit the AST.
>
> This CL adds a new `SyntaxTree` writer and a `dump-syntax-tree` option
> to the `tint` program which emits a copy of the AST to the terminal.
>
> Change-Id: I83f6cd7aad3413b0a823728e8aac0d551421b33a
> Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/122540
> Reviewed-by: Ben Clayton <bclayton@google.com>
> Commit-Queue: Dan Sinclair <dsinclair@chromium.org>
> Kokoro: Kokoro <noreply+kokoro@google.com>

TBR=dsinclair@chromium.org,bclayton@google.com,noreply+kokoro@google.com,dawn-scoped@luci-project-accounts.iam.gserviceaccount.com

Change-Id: Icaac76f8daba6034658cf05e15f15676ce2bf155
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/122760
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Dan Sinclair <dsinclair@chromium.org>
Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
Reviewed-by: Ben Clayton <bclayton@google.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 59776f9..66e2dcd 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -157,7 +157,6 @@
 option_if_not_defined(TINT_BUILD_SPV_WRITER "Build the SPIR-V output writer" ${DAWN_ENABLE_VULKAN})
 option_if_not_defined(TINT_BUILD_WGSL_WRITER "Build the WGSL output writer" ON)
 
-option_if_not_defined(TINT_BUILD_SYNTAX_TREE_WRITER "Build the syntax tree writer" OFF)
 option_if_not_defined(TINT_BUILD_IR "Build the IR" ON)
 
 option_if_not_defined(TINT_BUILD_FUZZERS "Build fuzzers" OFF)
@@ -293,7 +292,6 @@
 message(STATUS "Tint build MSL writer: ${TINT_BUILD_MSL_WRITER}")
 message(STATUS "Tint build SPIR-V writer: ${TINT_BUILD_SPV_WRITER}")
 message(STATUS "Tint build WGSL writer: ${TINT_BUILD_WGSL_WRITER}")
-message(STATUS "Tint build Syntax Tree writer: ${TINT_BUILD_SYNTAX_TREE_WRITER}")
 message(STATUS "Tint build IR: ${TINT_BUILD_IR}")
 message(STATUS "Tint build fuzzers: ${TINT_BUILD_FUZZERS}")
 message(STATUS "Tint build SPIRV-Tools fuzzer: ${TINT_BUILD_SPIRV_TOOLS_FUZZER}")
@@ -523,8 +521,6 @@
   target_compile_definitions(${TARGET} PUBLIC -DTINT_BUILD_MSL_WRITER=$<BOOL:${TINT_BUILD_MSL_WRITER}>)
   target_compile_definitions(${TARGET} PUBLIC -DTINT_BUILD_SPV_WRITER=$<BOOL:${TINT_BUILD_SPV_WRITER}>)
   target_compile_definitions(${TARGET} PUBLIC -DTINT_BUILD_WGSL_WRITER=$<BOOL:${TINT_BUILD_WGSL_WRITER}>)
-  target_compile_definitions(${TARGET} PUBLIC
-      -DTINT_BUILD_SYNTAX_TREE_WRITER=$<BOOL:${TINT_BUILD_SYNTAX_TREE_WRITER}>)
   target_compile_definitions(${TARGET} PUBLIC -DTINT_BUILD_IR=$<BOOL:${TINT_BUILD_IR}>)
 
   common_compile_options(${TARGET})
diff --git a/src/tint/BUILD.gn b/src/tint/BUILD.gn
index 44b7406..89eb6eef 100644
--- a/src/tint/BUILD.gn
+++ b/src/tint/BUILD.gn
@@ -78,12 +78,6 @@
     defines += [ "TINT_BUILD_GLSL_WRITER=0" ]
   }
 
-  if (tint_build_syntax_tree_writer) {
-    defines += [ "TINT_BUILD_SYNTAX_TREE_WRITER=1" ]
-  } else {
-    defines += [ "TINT_BUILD_SYNTAX_TREE_WRITER=0" ]
-  }
-
   include_dirs = [
     "${tint_root_dir}/",
     "${tint_root_dir}/include/",
@@ -1051,25 +1045,6 @@
   ]
 }
 
-libtint_source_set("libtint_syntax_tree_writer_src") {
-  sources = [
-    "writer/syntax_tree/generator.cc",
-    "writer/syntax_tree/generator.h",
-    "writer/syntax_tree/generator_impl.cc",
-    "writer/syntax_tree/generator_impl.h",
-  ]
-
-  deps = [
-    ":libtint_ast_src",
-    ":libtint_base_src",
-    ":libtint_builtins_src",
-    ":libtint_program_src",
-    ":libtint_sem_src",
-    ":libtint_type_src",
-    ":libtint_writer_src",
-  ]
-}
-
 source_set("libtint") {
   public_deps = [
     ":libtint_ast_src",
@@ -1114,10 +1089,6 @@
     public_deps += [ ":libtint_glsl_writer_src" ]
   }
 
-  if (tint_build_syntax_tree_writer) {
-    public_deps += [ ":libtint_syntax_tree_writer_src" ]
-  }
-
   configs += [ ":tint_common_config" ]
   public_configs = [ ":tint_public_config" ]
 
diff --git a/src/tint/CMakeLists.txt b/src/tint/CMakeLists.txt
index b46c8b1..1d31896 100644
--- a/src/tint/CMakeLists.txt
+++ b/src/tint/CMakeLists.txt
@@ -677,15 +677,6 @@
   )
 endif()
 
-if(${TINT_BUILD_SYNTAX_TREE_WRITER})
-    list(APPEND TINT_LIB_SRCS
-      writer/syntax_tree/generator.cc
-      writer/syntax_tree/generator.h
-      writer/syntax_tree/generator_impl.cc
-      writer/syntax_tree/generator_impl.h
-    )
-endif()
-
 if(${TINT_BUILD_IR})
   list(APPEND TINT_LIB_SRCS
     ir/binary.cc
diff --git a/src/tint/cmd/main.cc b/src/tint/cmd/main.cc
index 22cbf0b..0b2aad2 100644
--- a/src/tint/cmd/main.cc
+++ b/src/tint/cmd/main.cc
@@ -29,10 +29,6 @@
 #include "glslang/Public/ShaderLang.h"
 #endif  // TINT_BUILD_GLSL_WRITER
 
-#if TINT_BUILD_SYNTAX_TREE_WRITER
-#include "src/tint/writer/syntax_tree/generator.h"
-#endif  // TINT_BUILD_SYNTAX_TREE_WRITER
-
 #if TINT_BUILD_SPV_READER
 #include "spirv-tools/libspirv.hpp"
 #endif  // TINT_BUILD_SPV_READER
@@ -110,10 +106,6 @@
     bool dump_ir = false;
     bool dump_ir_graph = false;
 #endif  // TINT_BUILD_IR
-
-#if TINT_BUILD_SYNTAX_TREE_WRITER
-    bool dump_syntax_tree = false;
-#endif  // TINB_BUILD_SYNTAX_TREE_WRITER
 };
 
 const char kUsage[] = R"(Usage: tint [options] <input-file>
@@ -391,10 +383,6 @@
         } else if (arg == "--dump-ir-graph") {
             opts->dump_ir_graph = true;
 #endif  // TINT_BUILD_IR
-#if TINT_BUILD_SYNTAX_TREE_WRITER
-        } else if (arg == "--dump-ast") {
-            opts->dump_syntax_tree = true;
-#endif  // TINT_BUILD_SYNTAX_TREE_WRITER
         } else if (arg == "--xcrun") {
             ++i;
             if (i >= args.size()) {
@@ -1067,9 +1055,6 @@
             "  --dump-ir                 -- Writes the IR to stdout\n"
             "  --dump-ir-graph           -- Writes the IR graph to 'tint.dot' as a dot graph\n";
 #endif  // TINT_BUILD_IR
-#if TINT_BUILD_SYNTAX_TREE_WRITER
-        usage += "  --dump-ast                -- Writes the AST to stdout\n";
-#endif  // TINT_BUILD_SYNTAX_TREE_WRITER
 
         std::cout << usage << std::endl;
         return 0;
@@ -1107,18 +1092,6 @@
         return 1;
     }
 
-#if TINT_BUILD_SYNTAX_TREE_WRITER
-    if (options.dump_syntax_tree) {
-        tint::writer::syntax_tree::Options gen_options;
-        auto result = tint::writer::syntax_tree::Generate(program.get(), gen_options);
-        if (!result.success) {
-            std::cerr << "Failed to dump AST: " << result.error << std::endl;
-        } else {
-            std::cout << result.ast << std::endl;
-        }
-    }
-#endif  // TINT_BUILD_SYNTAX_TREE_WRITER
-
 #if TINT_BUILD_IR
     if (options.dump_ir || options.dump_ir_graph) {
         auto result = tint::ir::Module::FromProgram(program.get());
diff --git a/src/tint/writer/syntax_tree/generator.cc b/src/tint/writer/syntax_tree/generator.cc
deleted file mode 100644
index 6919d24..0000000
--- a/src/tint/writer/syntax_tree/generator.cc
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2023 The Tint Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "src/tint/writer/syntax_tree/generator.h"
-#include "src/tint/writer/syntax_tree/generator_impl.h"
-
-namespace tint::writer::syntax_tree {
-
-Result::Result() = default;
-Result::~Result() = default;
-Result::Result(const Result&) = default;
-
-Result Generate(const Program* program, const Options&) {
-    Result result;
-
-    // Generate the AST dump.
-    auto impl = std::make_unique<GeneratorImpl>(program);
-    result.success = impl->Generate();
-    result.error = impl->error();
-    result.ast = impl->result();
-
-    return result;
-}
-
-}  // namespace tint::writer::syntax_tree
diff --git a/src/tint/writer/syntax_tree/generator.h b/src/tint/writer/syntax_tree/generator.h
deleted file mode 100644
index ce81c3f..0000000
--- a/src/tint/writer/syntax_tree/generator.h
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright 2023 The Tint Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef SRC_TINT_WRITER_SYNTAX_TREE_GENERATOR_H_
-#define SRC_TINT_WRITER_SYNTAX_TREE_GENERATOR_H_
-
-#include <memory>
-#include <string>
-
-#include "src/tint/writer/text.h"
-
-// Forward declarations
-namespace tint {
-class Program;
-}  // namespace tint
-
-namespace tint::writer::syntax_tree {
-
-class GeneratorImpl;
-
-/// Configuration options used for generating AST.
-struct Options {};
-
-/// The result produced when generating AST.
-struct Result {
-    /// Constructor
-    Result();
-
-    /// Destructor
-    ~Result();
-
-    /// Copy constructor
-    Result(const Result&);
-
-    /// True if generation was successful.
-    bool success = false;
-
-    /// The errors generated during code generation, if any.
-    std::string error;
-
-    /// The generated AST.
-    std::string ast = "";
-};
-
-/// Generate an AST dump for a program, according to a set of configuration options.
-/// The result will contain the AST, as well as success status and diagnostic information.
-/// @param program the program to dump
-/// @param options the configuration options to use when dumping
-/// @returns the resulting AST dump and supplementary information
-Result Generate(const Program* program, const Options& options);
-
-}  // namespace tint::writer::syntax_tree
-
-#endif  // SRC_TINT_WRITER_SYNTAX_TREE_GENERATOR_H_
diff --git a/src/tint/writer/syntax_tree/generator_impl.cc b/src/tint/writer/syntax_tree/generator_impl.cc
deleted file mode 100644
index e5e2f2f..0000000
--- a/src/tint/writer/syntax_tree/generator_impl.cc
+++ /dev/null
@@ -1,1349 +0,0 @@
-// Copyright 2023 The Tint Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "src/tint/writer/syntax_tree/generator_impl.h"
-
-#include <algorithm>
-
-#include "src/tint/ast/alias.h"
-#include "src/tint/ast/bool_literal_expression.h"
-#include "src/tint/ast/call_statement.h"
-#include "src/tint/ast/float_literal_expression.h"
-#include "src/tint/ast/id_attribute.h"
-#include "src/tint/ast/internal_attribute.h"
-#include "src/tint/ast/interpolate_attribute.h"
-#include "src/tint/ast/invariant_attribute.h"
-#include "src/tint/ast/module.h"
-#include "src/tint/ast/stage_attribute.h"
-#include "src/tint/ast/stride_attribute.h"
-#include "src/tint/ast/struct_member_align_attribute.h"
-#include "src/tint/ast/struct_member_offset_attribute.h"
-#include "src/tint/ast/struct_member_size_attribute.h"
-#include "src/tint/ast/variable_decl_statement.h"
-#include "src/tint/ast/workgroup_attribute.h"
-#include "src/tint/sem/struct.h"
-#include "src/tint/sem/switch_statement.h"
-#include "src/tint/utils/math.h"
-#include "src/tint/utils/scoped_assignment.h"
-#include "src/tint/writer/float_to_string.h"
-
-namespace tint::writer::syntax_tree {
-
-GeneratorImpl::GeneratorImpl(const Program* program) : TextGenerator(program) {}
-
-GeneratorImpl::~GeneratorImpl() = default;
-
-bool GeneratorImpl::Generate() {
-    // Generate global declarations in the order they appear in the module.
-    for (auto* decl : program_->AST().GlobalDeclarations()) {
-        if (!Switch(
-                decl,  //
-                [&](const ast::DiagnosticDirective* dd) {
-                    return EmitDiagnosticControl(dd->control);
-                },
-                [&](const ast::Enable* e) { return EmitEnable(e); },
-                [&](const ast::TypeDecl* td) { return EmitTypeDecl(td); },
-                [&](const ast::Function* func) { return EmitFunction(func); },
-                [&](const ast::Variable* var) { return EmitVariable(var); },
-                [&](const ast::ConstAssert* ca) { return EmitConstAssert(ca); },
-                [&](Default) {
-                    TINT_UNREACHABLE(Writer, diagnostics_);
-                    return false;
-                })) {
-            return false;
-        }
-        if (decl != program_->AST().GlobalDeclarations().Back()) {
-            line();
-        }
-    }
-
-    return true;
-}
-
-bool GeneratorImpl::EmitDiagnosticControl(const ast::DiagnosticControl& diagnostic) {
-    line() << "DiagnosticControl [severity: " << diagnostic.severity
-           << ", rule: " << program_->Symbols().NameFor(diagnostic.rule_name->symbol) << "]";
-    return true;
-}
-
-bool GeneratorImpl::EmitEnable(const ast::Enable* enable) {
-    line() << "Enable [" << enable->extension << "]";
-    return true;
-}
-
-bool GeneratorImpl::EmitTypeDecl(const ast::TypeDecl* ty) {
-    return Switch(
-        ty,
-        [&](const ast::Alias* alias) {  //
-            line() << "Alias [";
-            {
-                ScopedIndent ai(this);
-
-                line() << "name: " << program_->Symbols().NameFor(alias->name->symbol);
-                line() << "expr: ";
-                {
-                    ScopedIndent ex(this);
-                    if (!EmitExpression(alias->type)) {
-                        return false;
-                    }
-                }
-            }
-            line() << "]";
-            return true;
-        },
-        [&](const ast::Struct* str) {  //
-            return EmitStructType(str);
-        },
-        [&](Default) {  //
-            diagnostics_.add_error(diag::System::Writer,
-                                   "unknown declared type: " + std::string(ty->TypeInfo().name));
-            return false;
-        });
-}
-
-bool GeneratorImpl::EmitExpression(const ast::Expression* expr) {
-    return Switch(
-        expr,
-        [&](const ast::IndexAccessorExpression* a) {  //
-            return EmitIndexAccessor(a);
-        },
-        [&](const ast::BinaryExpression* b) {  //
-            return EmitBinary(b);
-        },
-        [&](const ast::BitcastExpression* b) {  //
-            return EmitBitcast(b);
-        },
-        [&](const ast::CallExpression* c) {  //
-            return EmitCall(c);
-        },
-        [&](const ast::IdentifierExpression* i) {  //
-            return EmitIdentifier(i);
-        },
-        [&](const ast::LiteralExpression* l) {  //
-            return EmitLiteral(l);
-        },
-        [&](const ast::MemberAccessorExpression* m) {  //
-            return EmitMemberAccessor(m);
-        },
-        [&](const ast::PhonyExpression*) {  //
-            line() << "[PhonyExpression]";
-            return true;
-        },
-        [&](const ast::UnaryOpExpression* u) {  //
-            return EmitUnaryOp(u);
-        },
-        [&](Default) {
-            diagnostics_.add_error(diag::System::Writer, "unknown expression type");
-            return false;
-        });
-}
-
-bool GeneratorImpl::EmitIndexAccessor(const ast::IndexAccessorExpression* expr) {
-    line() << "IndexAccessorExpression [";
-    {
-        ScopedIndent iae(this);
-        line() << "object: ";
-        {
-            ScopedIndent obj(this);
-            if (!EmitExpression(expr->object)) {
-                return false;
-            }
-        }
-
-        line() << "index: ";
-        {
-            ScopedIndent idx(this);
-            if (!EmitExpression(expr->index)) {
-                return false;
-            }
-        }
-    }
-    line() << "]";
-
-    return true;
-}
-
-bool GeneratorImpl::EmitMemberAccessor(const ast::MemberAccessorExpression* expr) {
-    line() << "MemberAccessorExpression [";
-    {
-        ScopedIndent mae(this);
-
-        line() << "object: ";
-        {
-            ScopedIndent obj(this);
-            if (!EmitExpression(expr->object)) {
-                return false;
-            }
-        }
-        line() << "member: " << program_->Symbols().NameFor(expr->member->symbol);
-    }
-    line() << "]";
-    return true;
-}
-
-bool GeneratorImpl::EmitBitcast(const ast::BitcastExpression* expr) {
-    line() << "BitcastExpression [";
-    {
-        ScopedIndent bc(this);
-        {
-            line() << "type: ";
-            ScopedIndent ty(this);
-            if (!EmitExpression(expr->type)) {
-                return false;
-            }
-        }
-        {
-            line() << "expr: ";
-            ScopedIndent exp(this);
-            if (!EmitExpression(expr->expr)) {
-                return false;
-            }
-        }
-    }
-    line() << "]";
-    return true;
-}
-
-bool GeneratorImpl::EmitCall(const ast::CallExpression* expr) {
-    line() << "Call [";
-    {
-        ScopedIndent cl(this);
-
-        line() << "target: [";
-        {
-            ScopedIndent tgt(this);
-            if (!EmitExpression(expr->target)) {
-                return false;
-            }
-        }
-        line() << "]";
-
-        if (!expr->args.IsEmpty()) {
-            line() << "args: [";
-            {
-                ScopedIndent args(this);
-                for (auto* arg : expr->args) {
-                    line() << "arg: [";
-                    {
-                        ScopedIndent arg_val(this);
-                        if (!EmitExpression(arg)) {
-                            return false;
-                        }
-                    }
-                    line() << "]";
-                }
-            }
-            line() << "]";
-        }
-    }
-    line() << "]";
-    return true;
-}
-
-bool GeneratorImpl::EmitLiteral(const ast::LiteralExpression* lit) {
-    bool ret = false;
-    line() << "LiteralExpression [";
-    {
-        ScopedIndent le(this);
-        ret = Switch(
-            lit,
-            [&](const ast::BoolLiteralExpression* l) {  //
-                line() << (l->value ? "true" : "false");
-                return true;
-            },
-            [&](const ast::FloatLiteralExpression* l) {  //
-                // f16 literals are also emitted as float value with suffix "h".
-                // Note that all normal and subnormal f16 values are normal f32 values, and since
-                // NaN and Inf are not allowed to be spelled in literal, it should be fine to emit
-                // f16 literals in this way.
-                if (l->suffix == ast::FloatLiteralExpression::Suffix::kNone) {
-                    line() << DoubleToBitPreservingString(l->value);
-                } else {
-                    line() << FloatToBitPreservingString(static_cast<float>(l->value)) << l->suffix;
-                }
-                return true;
-            },
-            [&](const ast::IntLiteralExpression* l) {  //
-                line() << l->value << l->suffix;
-                return true;
-            },
-            [&](Default) {  //
-                diagnostics_.add_error(diag::System::Writer, "unknown literal type");
-                return false;
-            });
-    }
-    line() << "]";
-    return ret;
-}
-
-bool GeneratorImpl::EmitIdentifier(const ast::IdentifierExpression* expr) {
-    bool ret = false;
-    line() << "IdentifierExpression [";
-    {
-        ScopedIndent ie(this);
-        ret = EmitIdentifier(expr->identifier);
-    }
-    line() << "]";
-    return ret;
-}
-
-bool GeneratorImpl::EmitIdentifier(const ast::Identifier* ident) {
-    line() << "Identifier [";
-    {
-        ScopedIndent id(this);
-        if (auto* tmpl_ident = ident->As<ast::TemplatedIdentifier>()) {
-            line() << "Templated [";
-            {
-                ScopedIndent tmpl(this);
-                if (!tmpl_ident->attributes.IsEmpty()) {
-                    line() << "attrs: [";
-                    {
-                        ScopedIndent attrs(this);
-                        EmitAttributes(tmpl_ident->attributes);
-                    }
-                    line() << "]";
-                }
-                line() << "name: " << program_->Symbols().NameFor(ident->symbol);
-                if (!tmpl_ident->arguments.IsEmpty()) {
-                    line() << "args: [";
-                    {
-                        ScopedIndent args(this);
-                        for (auto* expr : tmpl_ident->arguments) {
-                            if (!EmitExpression(expr)) {
-                                return false;
-                            }
-                        }
-                    }
-                    line() << "]";
-                }
-            }
-            line() << "]";
-        } else {
-            line() << program_->Symbols().NameFor(ident->symbol);
-        }
-    }
-    line() << "]";
-    return true;
-}
-
-bool GeneratorImpl::EmitFunction(const ast::Function* func) {
-    line() << "Function [";
-    {
-        ScopedIndent funct(this);
-
-        if (func->attributes.Length()) {
-            line() << "attrs: [";
-            {
-                ScopedIndent attrs(this);
-                if (!EmitAttributes(func->attributes)) {
-                    return false;
-                }
-            }
-            line() << "]";
-        }
-        line() << "name: " << program_->Symbols().NameFor(func->name->symbol);
-
-        if (!func->params.IsEmpty()) {
-            line() << "params: [";
-            {
-                ScopedIndent args(this);
-                for (auto* v : func->params) {
-                    line() << "param: [";
-                    {
-                        ScopedIndent param(this);
-                        line() << "name: " << program_->Symbols().NameFor(v->name->symbol);
-                        if (!v->attributes.IsEmpty()) {
-                            line() << "attrs: [";
-                            {
-                                ScopedIndent attrs(this);
-                                if (!EmitAttributes(v->attributes)) {
-                                    return false;
-                                }
-                            }
-                            line() << "]";
-                        }
-                        line() << "type: [";
-                        {
-                            ScopedIndent ty(this);
-                            if (!EmitExpression(v->type)) {
-                                return false;
-                            }
-                        }
-                        line() << "]";
-                    }
-                    line() << "]";
-                }
-            }
-            line() << "]";
-        }
-
-        line() << "return: [";
-        {
-            ScopedIndent ret(this);
-
-            if (func->return_type || !func->return_type_attributes.IsEmpty()) {
-                if (!func->return_type_attributes.IsEmpty()) {
-                    line() << "attrs: [";
-                    {
-                        ScopedIndent attrs(this);
-                        if (!EmitAttributes(func->return_type_attributes)) {
-                            return false;
-                        }
-                    }
-                    line() << "]";
-                }
-
-                line() << "type: [";
-                {
-                    ScopedIndent ty(this);
-                    if (!EmitExpression(func->return_type)) {
-                        return false;
-                    }
-                }
-                line() << "]";
-            } else {
-                line() << "void";
-            }
-        }
-        line() << "]";
-        line() << "body: [";
-        {
-            ScopedIndent bdy(this);
-            if (func->body) {
-                if (!EmitBlockHeader(func->body)) {
-                    return false;
-                }
-                if (!EmitStatementsWithIndent(func->body->statements)) {
-                    return false;
-                }
-            }
-        }
-        line() << "]";
-    }
-    line() << "]";
-    return true;
-}
-
-bool GeneratorImpl::EmitImageFormat(const builtin::TexelFormat fmt) {
-    line() << "builtin::TexelFormat [" << fmt << "]";
-    return true;
-}
-
-bool GeneratorImpl::EmitStructType(const ast::Struct* str) {
-    line() << "Struct [";
-    {
-        ScopedIndent strct(this);
-
-        if (str->attributes.Length()) {
-            line() << "attrs: [";
-            {
-                ScopedIndent attrs(this);
-                if (!EmitAttributes(str->attributes)) {
-                    return false;
-                }
-            }
-            line() << "]";
-        }
-        line() << "name: " << program_->Symbols().NameFor(str->name->symbol);
-        line() << "members: [";
-        {
-            ScopedIndent membs(this);
-
-            for (auto* mem : str->members) {
-                line() << "StructMember[";
-                {
-                    ScopedIndent m(this);
-                    if (!mem->attributes.IsEmpty()) {
-                        line() << "attrs: [";
-                        {
-                            ScopedIndent attrs(this);
-                            if (!EmitAttributes(mem->attributes)) {
-                                return false;
-                            }
-                        }
-                        line() << "]";
-                    }
-
-                    line() << "name: " << program_->Symbols().NameFor(mem->name->symbol);
-                    line() << "type: [";
-                    {
-                        ScopedIndent ty(this);
-                        if (!EmitExpression(mem->type)) {
-                            return false;
-                        }
-                    }
-                    line() << "]";
-                }
-            }
-            line() << "]";
-        }
-        line() << "]";
-    }
-    line() << "]";
-    return true;
-}
-
-bool GeneratorImpl::EmitVariable(const ast::Variable* v) {
-    line() << "Variable [";
-    {
-        ScopedIndent variable(this);
-        if (!v->attributes.IsEmpty()) {
-            line() << "attrs: [";
-            {
-                ScopedIndent attr(this);
-                if (!EmitAttributes(v->attributes)) {
-                    return false;
-                }
-            }
-            line() << "]";
-        }
-
-        bool ok = Switch(
-            v,  //
-            [&](const ast::Var* var) {
-                if (var->declared_address_space || var->declared_access) {
-                    line() << "Var [";
-                    {
-                        ScopedIndent vr(this);
-                        line() << "address_space: [";
-                        {
-                            ScopedIndent addr(this);
-                            if (!EmitExpression(var->declared_address_space)) {
-                                return false;
-                            }
-                        }
-                        line() << "]";
-                        if (var->declared_access) {
-                            line() << "access: [";
-                            {
-                                ScopedIndent acs(this);
-                                if (!EmitExpression(var->declared_access)) {
-                                    return false;
-                                }
-                            }
-                            line() << "]";
-                        }
-                    }
-                    line() << "]";
-                } else {
-                    line() << "Var []";
-                }
-                return true;
-            },
-            [&](const ast::Let*) {
-                line() << "Let []";
-                return true;
-            },
-            [&](const ast::Override*) {
-                line() << "Override []";
-                return true;
-            },
-            [&](const ast::Const*) {
-                line() << "Const []";
-                return true;
-            },
-            [&](Default) {
-                TINT_ICE(Writer, diagnostics_) << "unhandled variable type " << v->TypeInfo().name;
-                return false;
-            });
-        if (!ok) {
-            return false;
-        }
-
-        line() << "name: " << program_->Symbols().NameFor(v->name->symbol);
-
-        if (auto ty = v->type) {
-            line() << "type: [";
-            {
-                ScopedIndent vty(this);
-                if (!EmitExpression(ty)) {
-                    return false;
-                }
-            }
-            line() << "]";
-        }
-
-        if (v->initializer != nullptr) {
-            line() << "initializer: [";
-            {
-                ScopedIndent init(this);
-                if (!EmitExpression(v->initializer)) {
-                    return false;
-                }
-            }
-            line() << "]";
-        }
-    }
-    line() << "]";
-    return true;
-}
-
-bool GeneratorImpl::EmitAttributes(utils::VectorRef<const ast::Attribute*> attrs) {
-    for (auto* attr : attrs) {
-        bool ok = Switch(
-            attr,
-            [&](const ast::WorkgroupAttribute* workgroup) {
-                auto values = workgroup->Values();
-                line() << "WorkgroupAttribute [";
-                {
-                    ScopedIndent wg(this);
-                    for (size_t i = 0; i < 3; i++) {
-                        if (values[i]) {
-                            if (!EmitExpression(values[i])) {
-                                return false;
-                            }
-                        }
-                    }
-                }
-                line() << "]";
-                return true;
-            },
-            [&](const ast::StageAttribute* stage) {
-                line() << "StageAttribute [" << stage->stage << "]";
-                return true;
-            },
-            [&](const ast::BindingAttribute* binding) {
-                line() << "BindingAttribute [";
-                {
-                    ScopedIndent ba(this);
-                    if (!EmitExpression(binding->expr)) {
-                        return false;
-                    }
-                }
-                line() << "]";
-                return true;
-            },
-            [&](const ast::GroupAttribute* group) {
-                line() << "GroupAttribute [";
-                {
-                    ScopedIndent ga(this);
-                    if (!EmitExpression(group->expr)) {
-                        return false;
-                    }
-                }
-                line() << "]";
-                return true;
-            },
-            [&](const ast::LocationAttribute* location) {
-                line() << "LocationAttribute [";
-                {
-                    ScopedIndent la(this);
-                    if (!EmitExpression(location->expr)) {
-                        return false;
-                    }
-                }
-                line() << "]";
-                return true;
-            },
-            [&](const ast::BuiltinAttribute* builtin) {
-                line() << "BuiltinAttribute [";
-                {
-                    ScopedIndent ba(this);
-                    if (!EmitExpression(builtin->builtin)) {
-                        return false;
-                    }
-                }
-                line() << "]";
-                return true;
-            },
-            [&](const ast::DiagnosticAttribute* diagnostic) {
-                return EmitDiagnosticControl(diagnostic->control);
-            },
-            [&](const ast::InterpolateAttribute* interpolate) {
-                line() << "InterpolateAttribute [";
-                {
-                    ScopedIndent ia(this);
-                    line() << "type: [";
-                    {
-                        ScopedIndent ty(this);
-                        if (!EmitExpression(interpolate->type)) {
-                            return false;
-                        }
-                    }
-                    line() << "]";
-                    if (interpolate->sampling) {
-                        line() << "sampling: [";
-                        {
-                            ScopedIndent sa(this);
-                            if (!EmitExpression(interpolate->sampling)) {
-                                return false;
-                            }
-                        }
-                        line() << "]";
-                    }
-                }
-                line() << "]";
-                return true;
-            },
-            [&](const ast::InvariantAttribute*) {
-                line() << "InvariantAttribute []";
-                return true;
-            },
-            [&](const ast::IdAttribute* override_deco) {
-                line() << "IdAttribute [";
-                {
-                    ScopedIndent id(this);
-                    if (!EmitExpression(override_deco->expr)) {
-                        return false;
-                    }
-                }
-                line() << "]";
-                return true;
-            },
-            [&](const ast::MustUseAttribute*) {
-                line() << "MustUseAttribute []";
-                return true;
-            },
-            [&](const ast::StructMemberOffsetAttribute* offset) {
-                line() << "StructMemberOffsetAttribute [";
-                {
-                    ScopedIndent smoa(this);
-                    if (!EmitExpression(offset->expr)) {
-                        return false;
-                    }
-                }
-                line() << "]";
-                return true;
-            },
-            [&](const ast::StructMemberSizeAttribute* size) {
-                line() << "StructMemberSizeAttribute [";
-                {
-                    ScopedIndent smsa(this);
-                    if (!EmitExpression(size->expr)) {
-                        return false;
-                    }
-                }
-                line() << "]";
-                return true;
-            },
-            [&](const ast::StructMemberAlignAttribute* align) {
-                line() << "StructMemberAlignAttribute [";
-                {
-                    ScopedIndent smaa(this);
-                    if (!EmitExpression(align->expr)) {
-                        return false;
-                    }
-                }
-                line() << "]";
-                return true;
-            },
-            [&](const ast::StrideAttribute* stride) {
-                line() << "StrideAttribute [" << stride->stride << "]";
-                return true;
-            },
-            [&](const ast::InternalAttribute* internal) {
-                line() << "InternalAttribute [" << internal->InternalName() << "]";
-                return true;
-            },
-            [&](Default) {
-                TINT_ICE(Writer, diagnostics_)
-                    << "Unsupported attribute '" << attr->TypeInfo().name << "'";
-                return false;
-            });
-
-        if (!ok) {
-            return false;
-        }
-    }
-    return true;
-}
-
-bool GeneratorImpl::EmitBinary(const ast::BinaryExpression* expr) {
-    line() << "BinaryExpression [";
-    {
-        ScopedIndent be(this);
-        line() << "lhs: [";
-        {
-            ScopedIndent lhs(this);
-
-            if (!EmitExpression(expr->lhs)) {
-                return false;
-            }
-        }
-        line() << "]";
-        line() << "op: [";
-        {
-            ScopedIndent op(this);
-            if (!EmitBinaryOp(expr->op)) {
-                return false;
-            }
-        }
-        line() << "]";
-        line() << "rhs: [";
-        {
-            ScopedIndent rhs(this);
-            if (!EmitExpression(expr->rhs)) {
-                return false;
-            }
-        }
-        line() << "]";
-    }
-    line() << "]";
-    return true;
-}
-
-bool GeneratorImpl::EmitBinaryOp(const ast::BinaryOp op) {
-    switch (op) {
-        case ast::BinaryOp::kAnd:
-            line() << "&";
-            break;
-        case ast::BinaryOp::kOr:
-            line() << "|";
-            break;
-        case ast::BinaryOp::kXor:
-            line() << "^";
-            break;
-        case ast::BinaryOp::kLogicalAnd:
-            line() << "&&";
-            break;
-        case ast::BinaryOp::kLogicalOr:
-            line() << "||";
-            break;
-        case ast::BinaryOp::kEqual:
-            line() << "==";
-            break;
-        case ast::BinaryOp::kNotEqual:
-            line() << "!=";
-            break;
-        case ast::BinaryOp::kLessThan:
-            line() << "<";
-            break;
-        case ast::BinaryOp::kGreaterThan:
-            line() << ">";
-            break;
-        case ast::BinaryOp::kLessThanEqual:
-            line() << "<=";
-            break;
-        case ast::BinaryOp::kGreaterThanEqual:
-            line() << ">=";
-            break;
-        case ast::BinaryOp::kShiftLeft:
-            line() << "<<";
-            break;
-        case ast::BinaryOp::kShiftRight:
-            line() << ">>";
-            break;
-        case ast::BinaryOp::kAdd:
-            line() << "+";
-            break;
-        case ast::BinaryOp::kSubtract:
-            line() << "-";
-            break;
-        case ast::BinaryOp::kMultiply:
-            line() << "*";
-            break;
-        case ast::BinaryOp::kDivide:
-            line() << "/";
-            break;
-        case ast::BinaryOp::kModulo:
-            line() << "%";
-            break;
-        case ast::BinaryOp::kNone:
-            diagnostics_.add_error(diag::System::Writer, "missing binary operation type");
-            return false;
-    }
-    return true;
-}
-
-bool GeneratorImpl::EmitUnaryOp(const ast::UnaryOpExpression* expr) {
-    line() << "UnaryOpExpression [";
-    {
-        ScopedIndent uoe(this);
-        line() << "op: [";
-        {
-            ScopedIndent op(this);
-            switch (expr->op) {
-                case ast::UnaryOp::kAddressOf:
-                    line() << "&";
-                    break;
-                case ast::UnaryOp::kComplement:
-                    line() << "~";
-                    break;
-                case ast::UnaryOp::kIndirection:
-                    line() << "*";
-                    break;
-                case ast::UnaryOp::kNot:
-                    line() << "!";
-                    break;
-                case ast::UnaryOp::kNegation:
-                    line() << "-";
-                    break;
-            }
-        }
-        line() << "]";
-        line() << "expr: [";
-        {
-            ScopedIndent ex(this);
-            if (!EmitExpression(expr->expr)) {
-                return false;
-            }
-        }
-        line() << "]";
-    }
-    line() << "]";
-
-    return true;
-}
-
-bool GeneratorImpl::EmitBlock(const ast::BlockStatement* stmt) {
-    {
-        if (!EmitBlockHeader(stmt)) {
-            return false;
-        }
-    }
-    if (!EmitStatementsWithIndent(stmt->statements)) {
-        return false;
-    }
-
-    return true;
-}
-
-bool GeneratorImpl::EmitBlockHeader(const ast::BlockStatement* stmt) {
-    if (!stmt->attributes.IsEmpty()) {
-        line() << "attrs: [";
-        {
-            ScopedIndent attrs(this);
-            if (!EmitAttributes(stmt->attributes)) {
-                return false;
-            }
-        }
-        line() << "]";
-    }
-    return true;
-}
-
-bool GeneratorImpl::EmitStatement(const ast::Statement* stmt) {
-    return Switch(
-        stmt,  //
-        [&](const ast::AssignmentStatement* a) { return EmitAssign(a); },
-        [&](const ast::BlockStatement* b) { return EmitBlock(b); },
-        [&](const ast::BreakStatement* b) { return EmitBreak(b); },
-        [&](const ast::BreakIfStatement* b) { return EmitBreakIf(b); },
-        [&](const ast::CallStatement* c) { return EmitCall(c->expr); },
-        [&](const ast::CompoundAssignmentStatement* c) { return EmitCompoundAssign(c); },
-        [&](const ast::ContinueStatement* c) { return EmitContinue(c); },
-        [&](const ast::DiscardStatement* d) { return EmitDiscard(d); },
-        [&](const ast::IfStatement* i) { return EmitIf(i); },
-        [&](const ast::IncrementDecrementStatement* l) { return EmitIncrementDecrement(l); },
-        [&](const ast::LoopStatement* l) { return EmitLoop(l); },
-        [&](const ast::ForLoopStatement* l) { return EmitForLoop(l); },
-        [&](const ast::WhileStatement* l) { return EmitWhile(l); },
-        [&](const ast::ReturnStatement* r) { return EmitReturn(r); },
-        [&](const ast::ConstAssert* c) { return EmitConstAssert(c); },
-        [&](const ast::SwitchStatement* s) { return EmitSwitch(s); },
-        [&](const ast::VariableDeclStatement* v) { return EmitVariable(v->variable); },
-        [&](Default) {
-            diagnostics_.add_error(diag::System::Writer,
-                                   "unknown statement type: " + std::string(stmt->TypeInfo().name));
-            return false;
-        });
-}
-
-bool GeneratorImpl::EmitStatements(utils::VectorRef<const ast::Statement*> stmts) {
-    for (auto* s : stmts) {
-        if (!EmitStatement(s)) {
-            return false;
-        }
-    }
-    return true;
-}
-
-bool GeneratorImpl::EmitStatementsWithIndent(utils::VectorRef<const ast::Statement*> stmts) {
-    ScopedIndent si(this);
-    return EmitStatements(stmts);
-}
-
-bool GeneratorImpl::EmitAssign(const ast::AssignmentStatement* stmt) {
-    line() << "AssignmentStatement [";
-    {
-        ScopedIndent as(this);
-        line() << "lhs: [";
-        {
-            ScopedIndent lhs(this);
-            if (!EmitExpression(stmt->lhs)) {
-                return false;
-            }
-        }
-        line() << "]";
-        line() << "rhs: [";
-        {
-            ScopedIndent rhs(this);
-            if (!EmitExpression(stmt->rhs)) {
-                return false;
-            }
-            line() << "]";
-        }
-    }
-    line() << "]";
-
-    return true;
-}
-
-bool GeneratorImpl::EmitBreak(const ast::BreakStatement*) {
-    line() << "BreakStatement []";
-    return true;
-}
-
-bool GeneratorImpl::EmitBreakIf(const ast::BreakIfStatement* b) {
-    line() << "BreakIfStatement [";
-    {
-        ScopedIndent bis(this);
-        if (!EmitExpression(b->condition)) {
-            return false;
-        }
-    }
-    line() << "]";
-    return true;
-}
-
-bool GeneratorImpl::EmitCase(const ast::CaseStatement* stmt) {
-    line() << "CaseStatement [";
-    {
-        ScopedIndent cs(this);
-        if (stmt->selectors.Length() == 1 && stmt->ContainsDefault()) {
-            line() << "selector: default";
-            if (!EmitBlockHeader(stmt->body)) {
-                return false;
-            }
-        } else {
-            line() << "selectors: [";
-            {
-                ScopedIndent sels(this);
-                for (auto* sel : stmt->selectors) {
-                    if (sel->IsDefault()) {
-                        line() << "default []";
-                    } else if (!EmitExpression(sel->expr)) {
-                        return false;
-                    }
-                }
-            }
-            line() << "]";
-            if (!EmitBlockHeader(stmt->body)) {
-                return false;
-            }
-        }
-        if (!EmitStatementsWithIndent(stmt->body->statements)) {
-            return false;
-        }
-    }
-    line() << "]";
-    return true;
-}
-
-bool GeneratorImpl::EmitCompoundAssign(const ast::CompoundAssignmentStatement* stmt) {
-    line() << "CompoundAssignmentStatement [";
-    {
-        ScopedIndent cas(this);
-        line() << "lhs: [";
-        {
-            ScopedIndent lhs(this);
-            if (!EmitExpression(stmt->lhs)) {
-                return false;
-            }
-        }
-        line() << "]";
-
-        line() << "op: [";
-        {
-            ScopedIndent op(this);
-            if (!EmitBinaryOp(stmt->op)) {
-                return false;
-            }
-        }
-        line() << "]";
-        line() << "rhs: [";
-        {
-            ScopedIndent rhs(this);
-
-            if (!EmitExpression(stmt->rhs)) {
-                return false;
-            }
-        }
-        line() << "]";
-    }
-    line() << "]";
-    return true;
-}
-
-bool GeneratorImpl::EmitContinue(const ast::ContinueStatement*) {
-    line() << "ContinueStatement []";
-    return true;
-}
-
-bool GeneratorImpl::EmitIf(const ast::IfStatement* stmt) {
-    {
-        line() << "IfStatement [";
-        {
-            ScopedIndent ifs(this);
-            line() << "condition: [";
-            {
-                ScopedIndent cond(this);
-                if (!EmitExpression(stmt->condition)) {
-                    return false;
-                }
-            }
-            line() << "]";
-            if (!EmitBlockHeader(stmt->body)) {
-                return false;
-            }
-        }
-        line() << "] ";
-    }
-    if (!EmitStatementsWithIndent(stmt->body->statements)) {
-        return false;
-    }
-
-    const ast::Statement* e = stmt->else_statement;
-    while (e) {
-        if (auto* elseif = e->As<ast::IfStatement>()) {
-            {
-                line() << "Else IfStatement [";
-                {
-                    ScopedIndent ifs(this);
-                    line() << "condition: [";
-                    if (!EmitExpression(elseif->condition)) {
-                        return false;
-                    }
-                }
-                line() << "]";
-                if (!EmitBlockHeader(elseif->body)) {
-                    return false;
-                }
-            }
-            line() << "]";
-            if (!EmitStatementsWithIndent(elseif->body->statements)) {
-                return false;
-            }
-            e = elseif->else_statement;
-        } else {
-            auto* body = e->As<ast::BlockStatement>();
-            {
-                line() << "Else [";
-                {
-                    ScopedIndent els(this);
-                    if (!EmitBlockHeader(body)) {
-                        return false;
-                    }
-                }
-                line() << "]";
-            }
-            if (!EmitStatementsWithIndent(body->statements)) {
-                return false;
-            }
-            break;
-        }
-    }
-    return true;
-}
-
-bool GeneratorImpl::EmitIncrementDecrement(const ast::IncrementDecrementStatement* stmt) {
-    line() << "IncrementDecrementStatement [";
-    {
-        ScopedIndent ids(this);
-        line() << "expr: [";
-        if (!EmitExpression(stmt->lhs)) {
-            return false;
-        }
-        line() << "]";
-        line() << "dir: " << (stmt->increment ? "++" : "--");
-    }
-    line() << "]";
-    return true;
-}
-
-bool GeneratorImpl::EmitDiscard(const ast::DiscardStatement*) {
-    line() << "DiscardStatement []";
-    return true;
-}
-
-bool GeneratorImpl::EmitLoop(const ast::LoopStatement* stmt) {
-    line() << "LoopStatement [";
-    {
-        ScopedIndent ls(this);
-        if (!EmitStatements(stmt->body->statements)) {
-            return false;
-        }
-
-        if (stmt->continuing && !stmt->continuing->Empty()) {
-            line() << "Continuing [";
-            {
-                ScopedIndent cont(this);
-                if (!EmitStatementsWithIndent(stmt->continuing->statements)) {
-                    return false;
-                }
-            }
-            line() << "]";
-        }
-    }
-    line() << "]";
-
-    return true;
-}
-
-bool GeneratorImpl::EmitForLoop(const ast::ForLoopStatement* stmt) {
-    TextBuffer init_buf;
-    if (auto* init = stmt->initializer) {
-        TINT_SCOPED_ASSIGNMENT(current_buffer_, &init_buf);
-        if (!EmitStatement(init)) {
-            return false;
-        }
-    }
-
-    TextBuffer cont_buf;
-    if (auto* cont = stmt->continuing) {
-        TINT_SCOPED_ASSIGNMENT(current_buffer_, &cont_buf);
-        if (!EmitStatement(cont)) {
-            return false;
-        }
-    }
-
-    line() << "ForLoopStatement [";
-    {
-        ScopedIndent fs(this);
-
-        line() << "initializer: [";
-        {
-            ScopedIndent init(this);
-            switch (init_buf.lines.size()) {
-                case 0:  // No initializer
-                    break;
-                case 1:  // Single line initializer statement
-                    line() << TrimSuffix(init_buf.lines[0].content, ";");
-                    break;
-                default:  // Block initializer statement
-                    for (size_t i = 1; i < init_buf.lines.size(); i++) {
-                        // Indent all by the first line
-                        init_buf.lines[i].indent += current_buffer_->current_indent;
-                    }
-                    line() << TrimSuffix(init_buf.String(), "\n");
-                    break;
-            }
-        }
-        line() << "]";
-        line() << "condition: [";
-        {
-            ScopedIndent con(this);
-            if (auto* cond = stmt->condition) {
-                if (!EmitExpression(cond)) {
-                    return false;
-                }
-            }
-        }
-
-        line() << "]";
-        line() << "continuing: [";
-        {
-            ScopedIndent cont(this);
-            switch (cont_buf.lines.size()) {
-                case 0:  // No continuing
-                    break;
-                case 1:  // Single line continuing statement
-                    line() << TrimSuffix(cont_buf.lines[0].content, ";");
-                    break;
-                default:  // Block continuing statement
-                    for (size_t i = 1; i < cont_buf.lines.size(); i++) {
-                        // Indent all by the first line
-                        cont_buf.lines[i].indent += current_buffer_->current_indent;
-                    }
-                    line() << TrimSuffix(cont_buf.String(), "\n");
-                    break;
-            }
-        }
-        if (!EmitBlockHeader(stmt->body)) {
-            return false;
-        }
-
-        if (!EmitStatementsWithIndent(stmt->body->statements)) {
-            return false;
-        }
-    }
-    line() << "]";
-
-    return true;
-}
-
-bool GeneratorImpl::EmitWhile(const ast::WhileStatement* stmt) {
-    line() << "WhileStatement [";
-    {
-        ScopedIndent ws(this);
-        {
-            auto* cond = stmt->condition;
-            if (!EmitExpression(cond)) {
-                return false;
-            }
-        }
-        if (!EmitBlockHeader(stmt->body)) {
-            return false;
-        }
-        if (!EmitStatementsWithIndent(stmt->body->statements)) {
-            return false;
-        }
-    }
-    line() << "]";
-    return true;
-}
-
-bool GeneratorImpl::EmitReturn(const ast::ReturnStatement* stmt) {
-    line() << "ReturnStatement [";
-    {
-        ScopedIndent ret(this);
-        if (stmt->value) {
-            if (!EmitExpression(stmt->value)) {
-                return false;
-            }
-        }
-    }
-    line() << "]";
-    return true;
-}
-
-bool GeneratorImpl::EmitConstAssert(const ast::ConstAssert* stmt) {
-    line() << "ConstAssert [";
-    {
-        ScopedIndent ca(this);
-        if (!EmitExpression(stmt->condition)) {
-            return false;
-        }
-    }
-    line() << "]";
-    return true;
-}
-
-bool GeneratorImpl::EmitSwitch(const ast::SwitchStatement* stmt) {
-    line() << "SwitchStatement [";
-    {
-        ScopedIndent ss(this);
-        line() << "condition: [";
-        {
-            ScopedIndent cond(this);
-            if (!EmitExpression(stmt->condition)) {
-                return false;
-            }
-        }
-        line() << "]";
-
-        {
-            ScopedIndent si(this);
-            for (auto* s : stmt->body) {
-                if (!EmitCase(s)) {
-                    return false;
-                }
-            }
-        }
-    }
-    line() << "]";
-    return true;
-}
-
-}  // namespace tint::writer::syntax_tree
diff --git a/src/tint/writer/syntax_tree/generator_impl.h b/src/tint/writer/syntax_tree/generator_impl.h
deleted file mode 100644
index 8b9a187..0000000
--- a/src/tint/writer/syntax_tree/generator_impl.h
+++ /dev/null
@@ -1,215 +0,0 @@
-// Copyright 2023 The Tint Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef SRC_TINT_WRITER_SYNTAX_TREE_GENERATOR_IMPL_H_
-#define SRC_TINT_WRITER_SYNTAX_TREE_GENERATOR_IMPL_H_
-
-#include <string>
-
-#include "src/tint/ast/assignment_statement.h"
-#include "src/tint/ast/binary_expression.h"
-#include "src/tint/ast/bitcast_expression.h"
-#include "src/tint/ast/break_if_statement.h"
-#include "src/tint/ast/break_statement.h"
-#include "src/tint/ast/compound_assignment_statement.h"
-#include "src/tint/ast/continue_statement.h"
-#include "src/tint/ast/discard_statement.h"
-#include "src/tint/ast/for_loop_statement.h"
-#include "src/tint/ast/if_statement.h"
-#include "src/tint/ast/index_accessor_expression.h"
-#include "src/tint/ast/loop_statement.h"
-#include "src/tint/ast/member_accessor_expression.h"
-#include "src/tint/ast/return_statement.h"
-#include "src/tint/ast/switch_statement.h"
-#include "src/tint/ast/unary_op_expression.h"
-#include "src/tint/program.h"
-#include "src/tint/sem/struct.h"
-#include "src/tint/utils/string_stream.h"
-#include "src/tint/writer/text_generator.h"
-
-namespace tint::writer::syntax_tree {
-
-/// Implementation class for AST generator
-class GeneratorImpl : public TextGenerator {
-  public:
-    /// Constructor
-    /// @param program the program
-    explicit GeneratorImpl(const Program* program);
-    ~GeneratorImpl();
-
-    /// Generates the result data
-    /// @returns true on successful generation; false otherwise
-    bool Generate();
-
-    /// Handles generating a diagnostic control
-    /// @param diagnostic the diagnostic control node
-    /// @returns true if the diagnostic control was emitted
-    bool EmitDiagnosticControl(const ast::DiagnosticControl& diagnostic);
-    /// Handles generating an enable directive
-    /// @param enable the enable node
-    /// @returns true if the enable directive was emitted
-    bool EmitEnable(const ast::Enable* enable);
-    /// Handles generating a declared type
-    /// @param ty the declared type to generate
-    /// @returns true if the declared type was emitted
-    bool EmitTypeDecl(const ast::TypeDecl* ty);
-    /// Handles an index accessor expression
-    /// @param expr the expression to emit
-    /// @returns true if the index accessor was emitted
-    bool EmitIndexAccessor(const ast::IndexAccessorExpression* expr);
-    /// Handles an assignment statement
-    /// @param stmt the statement to emit
-    /// @returns true if the statement was emitted successfully
-    bool EmitAssign(const ast::AssignmentStatement* stmt);
-    /// Handles generating a binary expression
-    /// @param expr the binary expression
-    /// @returns true if the expression was emitted, false otherwise
-    bool EmitBinary(const ast::BinaryExpression* expr);
-    /// Handles generating a binary operator
-    /// @param op the binary operator
-    /// @returns true if the operator was emitted, false otherwise
-    bool EmitBinaryOp(const ast::BinaryOp op);
-    /// Handles generating a bitcast expression
-    /// @param expr the bitcast expression
-    /// @returns true if the bitcast was emitted
-    bool EmitBitcast(const ast::BitcastExpression* expr);
-    /// Handles a block statement
-    /// @param stmt the statement to emit
-    /// @returns true if the statement was emitted successfully
-    bool EmitBlock(const ast::BlockStatement* stmt);
-    /// Handles emitting the start of a block statement (including attributes)
-    /// @param stmt the block statement to emit the header for
-    /// @returns true if the statement was emitted successfully
-    bool EmitBlockHeader(const ast::BlockStatement* stmt);
-    /// Handles a break statement
-    /// @param stmt the statement to emit
-    /// @returns true if the statement was emitted successfully
-    bool EmitBreak(const ast::BreakStatement* stmt);
-    /// Handles a break-if statement
-    /// @param stmt the statement to emit
-    /// @returns true if the statement was emitted successfully
-    bool EmitBreakIf(const ast::BreakIfStatement* stmt);
-    /// Handles generating a call expression
-    /// @param expr the call expression
-    /// @returns true if the call expression is emitted
-    bool EmitCall(const ast::CallExpression* expr);
-    /// Handles a case statement
-    /// @param stmt the statement
-    /// @returns true if the statment was emitted successfully
-    bool EmitCase(const ast::CaseStatement* stmt);
-    /// Handles a compound assignment statement
-    /// @param stmt the statement to emit
-    /// @returns true if the statement was emitted successfully
-    bool EmitCompoundAssign(const ast::CompoundAssignmentStatement* stmt);
-    /// Handles generating a literal expression
-    /// @param expr the literal expression expression
-    /// @returns true if the literal expression is emitted
-    bool EmitLiteral(const ast::LiteralExpression* expr);
-    /// Handles a continue statement
-    /// @param stmt the statement to emit
-    /// @returns true if the statement was emitted successfully
-    bool EmitContinue(const ast::ContinueStatement* stmt);
-    /// Handles generate an Expression
-    /// @param expr the expression
-    /// @returns true if the expression was emitted
-    bool EmitExpression(const ast::Expression* expr);
-    /// Handles generating a function
-    /// @param func the function to generate
-    /// @returns true if the function was emitted
-    bool EmitFunction(const ast::Function* func);
-    /// Handles generating an identifier expression
-    /// @param expr the identifier expression
-    /// @returns true if the identifier was emitted
-    bool EmitIdentifier(const ast::IdentifierExpression* expr);
-    /// Handles generating an identifier
-    /// @param ident the identifier
-    /// @returns true if the identifier was emitted
-    bool EmitIdentifier(const ast::Identifier* ident);
-    /// Handles an if statement
-    /// @param stmt the statement to emit
-    /// @returns true if the statement was successfully emitted
-    bool EmitIf(const ast::IfStatement* stmt);
-    /// Handles an increment/decrement statement
-    /// @param stmt the statement to emit
-    /// @returns true if the statement was successfully emitted
-    bool EmitIncrementDecrement(const ast::IncrementDecrementStatement* stmt);
-    /// Handles generating a discard statement
-    /// @param stmt the discard statement
-    /// @returns true if the statement was successfully emitted
-    bool EmitDiscard(const ast::DiscardStatement* stmt);
-    /// Handles a loop statement
-    /// @param stmt the statement to emit
-    /// @returns true if the statement was emtited
-    bool EmitLoop(const ast::LoopStatement* stmt);
-    /// Handles a for-loop statement
-    /// @param stmt the statement to emit
-    /// @returns true if the statement was emtited
-    bool EmitForLoop(const ast::ForLoopStatement* stmt);
-    /// Handles a while statement
-    /// @param stmt the statement to emit
-    /// @returns true if the statement was emtited
-    bool EmitWhile(const ast::WhileStatement* stmt);
-    /// Handles a member accessor expression
-    /// @param expr the member accessor expression
-    /// @returns true if the member accessor was emitted
-    bool EmitMemberAccessor(const ast::MemberAccessorExpression* expr);
-    /// Handles return statements
-    /// @param stmt the statement to emit
-    /// @returns true if the statement was successfully emitted
-    bool EmitReturn(const ast::ReturnStatement* stmt);
-    /// Handles const assertion statements
-    /// @param stmt the statement to emit
-    /// @returns true if the statement was successfully emitted
-    bool EmitConstAssert(const ast::ConstAssert* stmt);
-    /// Handles statement
-    /// @param stmt the statement to emit
-    /// @returns true if the statement was emitted
-    bool EmitStatement(const ast::Statement* stmt);
-    /// Handles a statement list
-    /// @param stmts the statements to emit
-    /// @returns true if the statements were emitted
-    bool EmitStatements(utils::VectorRef<const ast::Statement*> stmts);
-    /// Handles a statement list with an increased indentation
-    /// @param stmts the statements to emit
-    /// @returns true if the statements were emitted
-    bool EmitStatementsWithIndent(utils::VectorRef<const ast::Statement*> stmts);
-    /// Handles generating a switch statement
-    /// @param stmt the statement to emit
-    /// @returns true if the statement was emitted
-    bool EmitSwitch(const ast::SwitchStatement* stmt);
-    /// Handles generating a struct declaration
-    /// @param str the struct
-    /// @returns true if the struct is emitted
-    bool EmitStructType(const ast::Struct* str);
-    /// Handles emitting an image format
-    /// @param fmt the format to generate
-    /// @returns true if the format is emitted
-    bool EmitImageFormat(const builtin::TexelFormat fmt);
-    /// Handles a unary op expression
-    /// @param expr the expression to emit
-    /// @returns true if the expression was emitted
-    bool EmitUnaryOp(const ast::UnaryOpExpression* expr);
-    /// Handles generating a variable
-    /// @param var the variable to generate
-    /// @returns true if the variable was emitted
-    bool EmitVariable(const ast::Variable* var);
-    /// Handles generating a attribute list
-    /// @param attrs the attribute list
-    /// @returns true if the attributes were emitted
-    bool EmitAttributes(utils::VectorRef<const ast::Attribute*> attrs);
-};
-
-}  // namespace tint::writer::syntax_tree
-
-#endif  // SRC_TINT_WRITER_SYNTAX_TREE_GENERATOR_IMPL_H_
diff --git a/tint_overrides_with_defaults.gni b/tint_overrides_with_defaults.gni
index c54915d..9e39248 100644
--- a/tint_overrides_with_defaults.gni
+++ b/tint_overrides_with_defaults.gni
@@ -72,11 +72,6 @@
     tint_build_glsl_writer = true
   }
 
-  # Build the Syntax Tree writer
-  if (!defined(tint_build_syntax_tree_writer)) {
-    tint_build_syntax_tree_writer = false
-  }
-
   # Build unittests
   if (!defined(tint_build_unittests)) {
     tint_build_unittests = true